refactor(core): 统一配置系统,移除 config.json

- 移除 config.json,所有配置统一从 agents.json 和 providers.json 读取
- config-loader.ts 从全局目录 ~/.ai-terminal-assistant/ 加载配置
- loadConfig() 从 agentRegistry.getGlobalConfig() 获取 defaults.model
- 添加 loadVisionConfig() 支持 Vision 模型配置
- Tavily API Key 仅从环境变量读取
- UI AgentDefaultsEditor 添加 Vision 模型配置界面
- 更新相关测试
This commit is contained in:
2025-12-16 00:33:29 +08:00
parent 76b1ae1573
commit 9376887995
14 changed files with 414 additions and 643 deletions
+2
View File
@@ -496,6 +496,8 @@ export interface AgentDefaults {
maxSteps?: number;
/** 模型配置 */
model?: AgentModelConfig;
/** Vision 模型配置(用于图片理解) */
vision?: AgentModelConfig;
/** 权限配置 */
permission?: AgentPermission;
}
@@ -44,6 +44,10 @@ export function AgentDefaultsEditor({
const [temperature, setTemperature] = useState<number | undefined>(undefined);
const [maxTokens, setMaxTokens] = useState<number | undefined>(undefined);
// Vision 模型配置
const [visionProvider, setVisionProvider] = useState<string>('');
const [visionModel, setVisionModel] = useState('');
// UI 状态
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
@@ -66,6 +70,11 @@ export function AgentDefaultsEditor({
setTemperature(defaults.model.temperature);
setMaxTokens(defaults.model.maxTokens);
}
if (defaults.vision) {
setVisionProvider(defaults.vision.provider || '');
setVisionModel(defaults.vision.model || '');
}
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load defaults');
@@ -103,6 +112,18 @@ export function AgentDefaultsEditor({
defaults.model = model;
}
// Vision 配置
const vision: AgentModelConfig = {};
if (visionProvider) {
vision.provider = visionProvider as 'anthropic' | 'deepseek' | 'openai';
}
if (visionModel) {
vision.model = visionModel;
}
if (Object.keys(vision).length > 0) {
defaults.vision = vision;
}
return defaults;
};
@@ -225,6 +246,9 @@ export function AgentDefaultsEditor({
{/* Model Configuration */}
<div className="space-y-4">
<h3 className="text-sm font-medium text-fg-secondary">Default Model</h3>
<p className="text-xs text-fg-subtle -mt-2">
The main model used for all conversations
</p>
<div className="grid grid-cols-2 gap-4">
{/* Provider */}
<div>
@@ -287,6 +311,41 @@ export function AgentDefaultsEditor({
</div>
</div>
{/* Vision Model Configuration */}
<div className="space-y-4">
<h3 className="text-sm font-medium text-fg-secondary">Vision Model</h3>
<p className="text-xs text-fg-subtle -mt-2">
Used for image understanding when the default model doesn't support vision
</p>
<div className="grid grid-cols-2 gap-4">
{/* Vision Provider */}
<div>
<label className="block text-xs text-fg-muted mb-1">Provider</label>
<select
value={visionProvider}
onChange={(e) => setVisionProvider(e.target.value)}
className="w-full px-3 py-2 bg-surface-base border border-line rounded-lg text-sm focus:outline-none focus:border-primary-500"
>
<option value="">Not configured</option>
<option value="anthropic">Anthropic</option>
<option value="openai">OpenAI</option>
</select>
</div>
{/* Vision Model */}
<div>
<label className="block text-xs text-fg-muted mb-1">Model</label>
<input
type="text"
value={visionModel}
onChange={(e) => setVisionModel(e.target.value)}
placeholder="gpt-4o"
className="w-full px-3 py-2 bg-surface-base border border-line rounded-lg text-sm focus:outline-none focus:border-primary-500"
/>
</div>
</div>
</div>
{/* Info */}
<div className="p-3 bg-blue-500/10 border border-blue-500/30 rounded-lg text-blue-400 text-xs">
<p>