Files
ai-terminal-assistant/packages/core/src/utils/config.ts
T
kurihada c307cd3a7c refactor(agent): 将 Summary Model 改造为内置 Sub Agent
- 扩展 AgentMode 类型添加 'internal' 模式
- 新增 summary agent preset (claude-3-5-haiku)
- AgentRegistry 添加 getInternal/listInternalAgents 方法
- CompressionManager 添加 setSummaryModelFromAgentConfig
- Agent 构造函数改用 Registry 配置初始化 Summary 模型
- 清理旧的 SummaryConfig 配置系统
- UI AgentsPanel 分离显示 System/Preset/Custom agents
- UI AgentEditor 为 internal agent 显示简化编辑界面
2025-12-14 22:12:36 +08:00

172 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import type { AgentConfig, ProviderType } from '../types/index.js';
import { providerRegistry, resolveApiKey } from '../provider/index.js';
const CONFIG_DIR = path.join(os.homedir(), '.ai-terminal-assistant');
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
interface StoredConfig {
provider?: ProviderType;
model?: string;
maxTokens?: number;
tavilyApiKey?: string;
/** 自定义 API 基础 URL(用于 OpenAI 兼容服务,如阿里云百炼) */
baseUrl?: string;
// Vision 配置
visionProvider?: ProviderType;
visionModel?: string;
/** Vision 专用的 Base URL(用于 OpenAI 兼容的 Vision 服务) */
visionBaseUrl?: string;
}
// Vision 配置接口
export interface VisionConfig {
provider: ProviderType;
apiKey: string;
model: string;
/** 自定义 Base URL(用于 OpenAI 兼容的 Vision 服务) */
baseUrl?: string;
}
// 默认模型配置
const DEFAULT_MODELS: Record<ProviderType, string> = {
anthropic: 'claude-sonnet-4-20250514',
deepseek: 'deepseek-chat',
openai: 'gpt-4o',
};
// 默认 Vision 模型(需要支持图片理解)
const DEFAULT_VISION_MODELS: Record<ProviderType, string> = {
anthropic: 'claude-sonnet-4-20250514',
deepseek: 'deepseek-chat', // DeepSeek 暂不支持 vision,占位用
openai: 'gpt-4o',
};
// 默认系统提示词
const DEFAULT_SYSTEM_PROMPT = `你是一个运行在终端中的 AI 编程助手。你可以帮助用户:
- 读取和写入文件
- 执行 bash 命令
- 搜索代码和文件
- 回答编程问题
使用工具时请注意:
1. 在修改文件前,先读取文件内容
2. 执行可能有风险的命令前,先向用户确认
3. 给出清晰、简洁的回答
重要的工具使用规则:
- 创建或修改文件时,必须使用 write_file 或 edit_file 工具,不要使用 bash 命令(如 cat、echo 等)
- write_file 和 edit_file 工具集成了代码诊断功能,可以在写入后自动检查代码错误
- bash 工具仅用于运行命令、安装依赖、执行脚本等操作,不要用于文件内容的创建和修改
当前工作目录: ${process.cwd()}
操作系统: ${process.platform}`;
// 获取原始配置(包含所有字段)
export function getConfig(): StoredConfig {
if (fs.existsSync(CONFIG_FILE)) {
try {
const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
return JSON.parse(content);
} catch {
return {};
}
}
return {};
}
// 加载配置
export function loadConfig(): AgentConfig {
// 从配置文件读取
const storedConfig = getConfig();
// 确定最终的 provider
const finalProvider = storedConfig.provider || 'anthropic';
// 通过 ProviderRegistry 获取 API Key
const providerConfig = providerRegistry.getConfig(finalProvider);
const finalApiKey = resolveApiKey(providerConfig);
if (!finalApiKey) {
console.error(`❌ 错误: 未配置 API Key`);
console.error(`请在设置中配置 ${finalProvider} 的 API Key`);
process.exit(1);
}
// 确定模型
const finalModel = storedConfig.model || DEFAULT_MODELS[finalProvider];
// 确定 baseUrl
const finalBaseUrl = storedConfig.baseUrl || providerConfig?.baseUrl;
return {
provider: finalProvider,
apiKey: finalApiKey,
model: finalModel,
maxTokens: storedConfig.maxTokens || 4096,
systemPrompt: DEFAULT_SYSTEM_PROMPT,
baseUrl: finalBaseUrl,
};
}
/**
* 加载 Vision 配置
* Vision 用于图片理解,当主模型不支持 vision 时使用
* 通过 ProviderRegistry 获取 API Key
*/
export function loadVisionConfig(): VisionConfig | null {
// 从配置文件读取
const storedConfig = getConfig();
// 确定 vision provider(默认使用 anthropic,因为 Claude 支持 vision
const finalProvider = storedConfig.visionProvider || 'anthropic';
// 通过 ProviderRegistry 获取 API Key
const providerConfig = providerRegistry.getConfig(finalProvider);
const finalApiKey = resolveApiKey(providerConfig);
// 如果没有 API Key,返回 null
if (!finalApiKey) {
return null;
}
// 确定模型
const finalModel = storedConfig.visionModel || DEFAULT_VISION_MODELS[finalProvider];
// 确定 baseUrl
const finalBaseUrl = storedConfig.visionBaseUrl || providerConfig?.baseUrl;
return {
provider: finalProvider,
apiKey: finalApiKey,
model: finalModel,
baseUrl: finalBaseUrl,
};
}
// 保存配置
export function saveConfig(config: Partial<StoredConfig>): void {
// 确保目录存在
if (!fs.existsSync(CONFIG_DIR)) {
fs.mkdirSync(CONFIG_DIR, { recursive: true });
}
// 读取现有配置
let existingConfig: StoredConfig = {};
if (fs.existsSync(CONFIG_FILE)) {
try {
const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
existingConfig = JSON.parse(content);
} catch {
// 忽略
}
}
// 合并并保存
const newConfig = { ...existingConfig, ...config };
fs.writeFileSync(CONFIG_FILE, JSON.stringify(newConfig, null, 2));
}