feat(core): 将 Tavily API Key 从环境变量迁移到系统配置

- 新增 ServiceConfig 类型和 services 配置字段
- 添加 getServiceApiKey/saveServiceConfig/deleteServiceConfig API
- 更新 web_search 和 web_extract 工具使用配置系统
- 新增 /api/services REST 端点管理第三方服务配置
This commit is contained in:
2025-12-17 13:01:29 +08:00
parent bb3d42e6bf
commit 2afa7bb103
9 changed files with 238 additions and 10 deletions
+44 -3
View File
@@ -7,7 +7,7 @@
import { existsSync } from 'node:fs';
import { readFile, writeFile, mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import type { ProvidersConfigFile, CustomProviderDefinition, ProviderConfig } from './types.js';
import type { ProvidersConfigFile, CustomProviderDefinition, ProviderConfig, ServiceConfig, ServiceType } from './types.js';
import { getConfigDir as getGlobalConfigDir } from '../constants/paths.js';
/** 配置文件名 */
@@ -28,7 +28,7 @@ export async function loadProvidersConfig(): Promise<ProvidersConfigFile> {
const configPath = getConfigPath();
if (!existsSync(configPath)) {
return { providers: {}, configs: {} };
return { providers: {}, configs: {}, services: {} };
}
try {
@@ -37,10 +37,11 @@ export async function loadProvidersConfig(): Promise<ProvidersConfigFile> {
return {
providers: config.providers ?? {},
configs: config.configs ?? {},
services: config.services ?? {},
};
} catch {
// 解析失败返回空配置
return { providers: {}, configs: {} };
return { providers: {}, configs: {}, services: {} };
}
}
@@ -83,3 +84,43 @@ export function mergeProviderConfig(
enabled: config?.enabled ?? true,
};
}
/**
* 获取服务配置
*/
export async function getServiceConfig(serviceId: ServiceType): Promise<ServiceConfig | undefined> {
const config = await loadProvidersConfig();
return config.services?.[serviceId];
}
/**
* 获取服务 API Key
*/
export async function getServiceApiKey(serviceId: ServiceType): Promise<string | undefined> {
const serviceConfig = await getServiceConfig(serviceId);
if (serviceConfig?.enabled === false) {
return undefined;
}
return serviceConfig?.apiKey;
}
/**
* 保存服务配置
*/
export async function saveServiceConfig(serviceId: ServiceType, serviceConfig: Omit<ServiceConfig, 'id'>): Promise<void> {
const config = await loadProvidersConfig();
config.services = config.services ?? {};
config.services[serviceId] = { ...serviceConfig, id: serviceId };
await saveProvidersConfig(config);
}
/**
* 删除服务配置
*/
export async function deleteServiceConfig(serviceId: ServiceType): Promise<void> {
const config = await loadProvidersConfig();
if (config.services) {
delete config.services[serviceId];
await saveProvidersConfig(config);
}
}
+6
View File
@@ -19,6 +19,8 @@ export type {
ProvidersConfigFile,
ProviderListItem,
ProviderDetail,
ServiceConfig,
ServiceType,
} from './types.js';
// Registry
@@ -42,6 +44,10 @@ export {
saveProvidersConfig,
resolveApiKey,
getConfigPath,
getServiceConfig,
getServiceApiKey,
saveServiceConfig,
deleteServiceConfig,
} from './config.js';
// Utils
+15
View File
@@ -122,8 +122,23 @@ export interface ProvidersConfigFile {
providers?: Record<string, CustomProviderDefinition>;
/** 提供商配置(API Key、选项等) */
configs?: Record<string, ProviderConfig>;
/** 第三方服务配置(如 Tavily */
services?: Record<string, ServiceConfig>;
}
/** 第三方服务配置 */
export interface ServiceConfig {
/** 服务 ID */
id: string;
/** API Key */
apiKey?: string;
/** 是否启用 */
enabled?: boolean;
}
/** 已知的服务类型 */
export type ServiceType = 'tavily';
/** 提供商列表项(API 响应用) */
export interface ProviderListItem {
id: string;