From 531101742e97d41b27d0059cee50012646256c49 Mon Sep 17 00:00:00 2001 From: suyao Date: Thu, 27 Nov 2025 01:29:02 +0800 Subject: [PATCH] feat: add project name support for Volcengine integration --- src/main/services/VolcengineService.ts | 8 ++++--- src/preload/index.ts | 4 ++-- .../clients/volcengine/VolcengineAPIClient.ts | 4 +++- src/renderer/src/hooks/useVolcengine.ts | 14 +++++++++++-- src/renderer/src/i18n/locales/en-us.json | 2 ++ src/renderer/src/i18n/locales/zh-cn.json | 2 ++ src/renderer/src/i18n/locales/zh-tw.json | 2 ++ src/renderer/src/i18n/translate/de-de.json | 2 ++ src/renderer/src/i18n/translate/el-gr.json | 2 ++ src/renderer/src/i18n/translate/es-es.json | 2 ++ src/renderer/src/i18n/translate/fr-fr.json | 2 ++ src/renderer/src/i18n/translate/ja-jp.json | 2 ++ src/renderer/src/i18n/translate/pt-pt.json | 2 ++ src/renderer/src/i18n/translate/ru-ru.json | 2 ++ .../ProviderSettings/VolcengineSettings.tsx | 21 ++++++++++++++++--- .../src/services/__tests__/ApiService.test.ts | 3 ++- src/renderer/src/store/llm.ts | 8 ++++++- 17 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/main/services/VolcengineService.ts b/src/main/services/VolcengineService.ts index f14cbc9ee8..8f67383f65 100644 --- a/src/main/services/VolcengineService.ts +++ b/src/main/services/VolcengineService.ts @@ -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 { + private async listEndpoints(projectName?: string): Promise { 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 => { + public listModels = async (_?: Electron.IpcMainInvokeEvent, projectName?: string): Promise => { try { const [foundationModelsResult, endpointsResult] = await Promise.allSettled([ this.listFoundationModels(), - this.listEndpoints() + this.listEndpoints(projectName) ]) const models: ModelInfo[] = [] diff --git a/src/preload/index.ts b/src/preload/index.ts index c34181e8ff..b713d5360e 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -578,10 +578,10 @@ const api = { ipcRenderer.invoke(IpcChannel.Volcengine_SaveCredentials, accessKeyId, secretAccessKey), hasCredentials: (): Promise => ipcRenderer.invoke(IpcChannel.Volcengine_HasCredentials), clearCredentials: (): Promise => 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 diff --git a/src/renderer/src/aiCore/legacy/clients/volcengine/VolcengineAPIClient.ts b/src/renderer/src/aiCore/legacy/clients/volcengine/VolcengineAPIClient.ts index ac7aa8865f..fc08f68060 100644 --- a/src/renderer/src/aiCore/legacy/clients/volcengine/VolcengineAPIClient.ts +++ b/src/renderer/src/aiCore/legacy/clients/volcengine/VolcengineAPIClient.ts @@ -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') diff --git a/src/renderer/src/hooks/useVolcengine.ts b/src/renderer/src/hooks/useVolcengine.ts index 148f984cf7..635fa6912f 100644 --- a/src/renderer/src/hooks/useVolcengine.ts +++ b/src/renderer/src/hooks/useVolcengine.ts @@ -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 +} diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 7fa4d5ded8..d21908d45c 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -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", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index d448198417..ab19d073d3 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -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": "保存凭证", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index c057e9d0b7..fba17f5aa2 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -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": "儲存憑證", diff --git a/src/renderer/src/i18n/translate/de-de.json b/src/renderer/src/i18n/translate/de-de.json index dde8b7fa61..15fc5c5ce0 100644 --- a/src/renderer/src/i18n/translate/de-de.json +++ b/src/renderer/src/i18n/translate/de-de.json @@ -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", diff --git a/src/renderer/src/i18n/translate/el-gr.json b/src/renderer/src/i18n/translate/el-gr.json index 3b6d231d50..07ebec6315 100644 --- a/src/renderer/src/i18n/translate/el-gr.json +++ b/src/renderer/src/i18n/translate/el-gr.json @@ -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", diff --git a/src/renderer/src/i18n/translate/es-es.json b/src/renderer/src/i18n/translate/es-es.json index cf2d94e99d..83909a02f3 100644 --- a/src/renderer/src/i18n/translate/es-es.json +++ b/src/renderer/src/i18n/translate/es-es.json @@ -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", diff --git a/src/renderer/src/i18n/translate/fr-fr.json b/src/renderer/src/i18n/translate/fr-fr.json index 44c6ede299..73f5a8f99d 100644 --- a/src/renderer/src/i18n/translate/fr-fr.json +++ b/src/renderer/src/i18n/translate/fr-fr.json @@ -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", diff --git a/src/renderer/src/i18n/translate/ja-jp.json b/src/renderer/src/i18n/translate/ja-jp.json index c8c758db6f..6df12fd67a 100644 --- a/src/renderer/src/i18n/translate/ja-jp.json +++ b/src/renderer/src/i18n/translate/ja-jp.json @@ -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", diff --git a/src/renderer/src/i18n/translate/pt-pt.json b/src/renderer/src/i18n/translate/pt-pt.json index 25d0f531b4..2e6a9c6307 100644 --- a/src/renderer/src/i18n/translate/pt-pt.json +++ b/src/renderer/src/i18n/translate/pt-pt.json @@ -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", diff --git a/src/renderer/src/i18n/translate/ru-ru.json b/src/renderer/src/i18n/translate/ru-ru.json index 7ceed795fc..4e13c5aeee 100644 --- a/src/renderer/src/i18n/translate/ru-ru.json +++ b/src/renderer/src/i18n/translate/ru-ru.json @@ -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", diff --git a/src/renderer/src/pages/settings/ProviderSettings/VolcengineSettings.tsx b/src/renderer/src/pages/settings/ProviderSettings/VolcengineSettings.tsx index 4d4692a946..76f6fbeea6 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/VolcengineSettings.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/VolcengineSettings.tsx @@ -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 = () => { {t('settings.provider.volcengine.region_help')} + {t('settings.provider.volcengine.project_name')} + setLocalProjectName(e.target.value)} + onBlur={() => setProjectName(localProjectName)} + style={{ marginTop: 5 }} + /> + + {t('settings.provider.volcengine.project_name_help')} + +