feat: add project name support for Volcengine integration

This commit is contained in:
suyao 2025-11-27 01:29:02 +08:00
parent c3c577dff4
commit 531101742e
No known key found for this signature in database
17 changed files with 69 additions and 13 deletions

View File

@ -34,6 +34,7 @@ const ListFoundationModelsRequestSchema = z.object({
})
const ListEndpointsRequestSchema = z.object({
ProjectName: z.optional(z.string()),
PageNumber: z.optional(z.number()),
PageSize: z.optional(z.number())
})
@ -544,8 +545,9 @@ class VolcengineService {
/**
* List user-created endpoints from Volcengine ARK
*/
private async listEndpoints(): Promise<ListEndpointsResponse> {
private async listEndpoints(projectName?: string): Promise<ListEndpointsResponse> {
const requestBody: ListEndpointsRequest = {
ProjectName: projectName || 'default',
PageNumber: 1,
PageSize: CONFIG.DEFAULT_PAGE_SIZE
}
@ -569,11 +571,11 @@ class VolcengineService {
* List all available models from Volcengine ARK
* Combines foundation models and user-created endpoints
*/
public listModels = async (): Promise<ListModelsResult> => {
public listModels = async (_?: Electron.IpcMainInvokeEvent, projectName?: string): Promise<ListModelsResult> => {
try {
const [foundationModelsResult, endpointsResult] = await Promise.allSettled([
this.listFoundationModels(),
this.listEndpoints()
this.listEndpoints(projectName)
])
const models: ModelInfo[] = []

View File

@ -578,10 +578,10 @@ const api = {
ipcRenderer.invoke(IpcChannel.Volcengine_SaveCredentials, accessKeyId, secretAccessKey),
hasCredentials: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.Volcengine_HasCredentials),
clearCredentials: (): Promise<void> => ipcRenderer.invoke(IpcChannel.Volcengine_ClearCredentials),
listModels: (): Promise<{
listModels: (projectName?: string): Promise<{
models: Array<{ id: string; name: string; description?: string; created?: number }>
total?: number
}> => ipcRenderer.invoke(IpcChannel.Volcengine_ListModels),
}> => ipcRenderer.invoke(IpcChannel.Volcengine_ListModels, projectName),
getAuthHeaders: (params: {
method: 'GET' | 'POST'
host: string

View File

@ -1,5 +1,6 @@
import type OpenAI from '@cherrystudio/openai'
import { loggerService } from '@logger'
import { getVolcengineProjectName } from '@renderer/hooks/useVolcengine'
import type { Provider } from '@renderer/types'
import { OpenAIAPIClient } from '../openai/OpenAIApiClient'
@ -33,7 +34,8 @@ export class VolcengineAPIClient extends OpenAIAPIClient {
logger.info('Fetching models from Volcengine API using signed request')
const response = await window.api.volcengine.listModels()
const projectName = getVolcengineProjectName()
const response = await window.api.volcengine.listModels(projectName)
if (!response || !response.models) {
logger.warn('Empty response from Volcengine listModels')

View File

@ -1,5 +1,10 @@
import store, { useAppSelector } from '@renderer/store'
import { setVolcengineAccessKeyId, setVolcengineRegion, setVolcengineSecretAccessKey } from '@renderer/store/llm'
import {
setVolcengineAccessKeyId,
setVolcengineProjectName,
setVolcengineRegion,
setVolcengineSecretAccessKey
} from '@renderer/store/llm'
import { useDispatch } from 'react-redux'
export function useVolcengineSettings() {
@ -10,7 +15,8 @@ export function useVolcengineSettings() {
...settings,
setAccessKeyId: (accessKeyId: string) => dispatch(setVolcengineAccessKeyId(accessKeyId)),
setSecretAccessKey: (secretAccessKey: string) => dispatch(setVolcengineSecretAccessKey(secretAccessKey)),
setRegion: (region: string) => dispatch(setVolcengineRegion(region))
setRegion: (region: string) => dispatch(setVolcengineRegion(region)),
setProjectName: (projectName: string) => dispatch(setVolcengineProjectName(projectName))
}
}
@ -29,3 +35,7 @@ export function getVolcengineSecretAccessKey() {
export function getVolcengineRegion() {
return store.getState().llm.settings.volcengine.region
}
export function getVolcengineProjectName() {
return store.getState().llm.settings.volcengine.projectName
}

View File

@ -4519,6 +4519,8 @@
"credentials_required": "Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "Credentials saved",
"description": "Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Please use IAM user's Access Key for authentication, do not use the root user credentials.",
"project_name": "Project Name",
"project_name_help": "Project name for endpoint filtering, default is 'default'",
"region": "Region",
"region_help": "Service region, e.g., cn-beijing",
"save_credentials": "Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "请填写 Access Key ID 和 Secret Access Key",
"credentials_saved": "凭证已保存",
"description": "火山引擎是字节跳动旗下的云服务平台,提供豆包等大语言模型服务。请使用 IAM 子用户的 Access Key 进行身份验证,不要使用主账号的根用户密钥。",
"project_name": "项目名称",
"project_name_help": "用于筛选推理接入点的项目名称,默认为 'default'",
"region": "地域",
"region_help": "服务地域,例如 cn-beijing",
"save_credentials": "保存凭证",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "請填寫 Access Key ID 和 Secret Access Key",
"credentials_saved": "憑證已儲存",
"description": "火山引擎是字節跳動旗下的雲端服務平台,提供豆包等大型語言模型服務。請使用 IAM 子用戶的 Access Key 進行身份驗證,不要使用主帳號的根用戶密鑰。",
"project_name": "專案名稱",
"project_name_help": "用於篩選推論接入點的專案名稱,預設為 'default'",
"region": "地區",
"region_help": "服務地區,例如 cn-beijing",
"save_credentials": "儲存憑證",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -4519,6 +4519,8 @@
"credentials_required": "[to be translated]:Please fill in Access Key ID and Secret Access Key",
"credentials_saved": "[to be translated]:Credentials saved",
"description": "[to be translated]:Volcengine is ByteDance's cloud service platform, providing Doubao and other large language model services. Use Access Key for authentication to fetch model list.",
"project_name": "[to be translated]:Project Name",
"project_name_help": "[to be translated]:Project name for endpoint filtering, default is 'default'",
"region": "[to be translated]:Region",
"region_help": "[to be translated]:Service region, e.g., cn-beijing",
"save_credentials": "[to be translated]:Save Credentials",

View File

@ -10,7 +10,7 @@ import { SettingHelpLink, SettingHelpText, SettingHelpTextRow, SettingSubtitle }
const VolcengineSettings: FC = () => {
const { t } = useTranslation()
const { accessKeyId, secretAccessKey, region, setAccessKeyId, setSecretAccessKey, setRegion } =
const { accessKeyId, secretAccessKey, region, projectName, setAccessKeyId, setSecretAccessKey, setRegion, setProjectName } =
useVolcengineSettings()
const providerConfig = PROVIDER_URLS['doubao']
@ -19,6 +19,7 @@ const VolcengineSettings: FC = () => {
const [localAccessKeyId, setLocalAccessKeyId] = useState(accessKeyId)
const [localSecretAccessKey, setLocalSecretAccessKey] = useState(secretAccessKey)
const [localRegion, setLocalRegion] = useState(region)
const [localProjectName, setLocalProjectName] = useState(projectName)
const [saving, setSaving] = useState(false)
const [hasCredentials, setHasCredentials] = useState(false)
@ -32,7 +33,8 @@ const VolcengineSettings: FC = () => {
setLocalAccessKeyId(accessKeyId)
setLocalSecretAccessKey(secretAccessKey)
setLocalRegion(region)
}, [accessKeyId, secretAccessKey, region])
setLocalProjectName(projectName)
}, [accessKeyId, secretAccessKey, region, projectName])
const handleSaveCredentials = useCallback(async () => {
if (!localAccessKeyId || !localSecretAccessKey) {
@ -46,6 +48,7 @@ const VolcengineSettings: FC = () => {
setAccessKeyId(localAccessKeyId)
setSecretAccessKey(localSecretAccessKey)
setRegion(localRegion)
setProjectName(localProjectName)
// Save to secure storage via IPC
await window.api.volcengine.saveCredentials(localAccessKeyId, localSecretAccessKey)
@ -56,7 +59,7 @@ const VolcengineSettings: FC = () => {
} finally {
setSaving(false)
}
}, [localAccessKeyId, localSecretAccessKey, localRegion, setAccessKeyId, setSecretAccessKey, setRegion, t])
}, [localAccessKeyId, localSecretAccessKey, localRegion, localProjectName, setAccessKeyId, setSecretAccessKey, setRegion, setProjectName, t])
const handleClearCredentials = useCallback(async () => {
try {
@ -122,6 +125,18 @@ const VolcengineSettings: FC = () => {
<SettingHelpText>{t('settings.provider.volcengine.region_help')}</SettingHelpText>
</SettingHelpTextRow>
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.volcengine.project_name')}</SettingSubtitle>
<Input
value={localProjectName}
placeholder="default"
onChange={(e) => setLocalProjectName(e.target.value)}
onBlur={() => setProjectName(localProjectName)}
style={{ marginTop: 5 }}
/>
<SettingHelpTextRow>
<SettingHelpText>{t('settings.provider.volcengine.project_name_help')}</SettingHelpText>
</SettingHelpTextRow>
<Space style={{ marginTop: 15 }}>
<Button type="primary" onClick={handleSaveCredentials} loading={saving}>
{t('settings.provider.volcengine.save_credentials')}

View File

@ -246,7 +246,8 @@ vi.mock('@renderer/store/llm.ts', () => {
volcengine: {
accessKeyId: '',
secretAccessKey: '',
region: 'cn-beijing'
region: 'cn-beijing',
projectName: 'default'
}
}
} satisfies LlmState

View File

@ -35,6 +35,7 @@ type LlmSettings = {
accessKeyId: string
secretAccessKey: string
region: string
projectName: string
}
}
@ -84,7 +85,8 @@ export const initialState: LlmState = {
volcengine: {
accessKeyId: '',
secretAccessKey: '',
region: 'cn-beijing'
region: 'cn-beijing',
projectName: 'default'
}
}
}
@ -235,6 +237,9 @@ const llmSlice = createSlice({
setVolcengineRegion: (state, action: PayloadAction<string>) => {
state.settings.volcengine.region = action.payload
},
setVolcengineProjectName: (state, action: PayloadAction<string>) => {
state.settings.volcengine.projectName = action.payload
},
updateModel: (
state,
action: PayloadAction<{
@ -279,6 +284,7 @@ export const {
setVolcengineAccessKeyId,
setVolcengineSecretAccessKey,
setVolcengineRegion,
setVolcengineProjectName,
updateModel
} = llmSlice.actions