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 显示简化编辑界面
This commit is contained in:
2025-12-14 22:12:36 +08:00
parent e97daaa0eb
commit c307cd3a7c
20 changed files with 339 additions and 594 deletions
+55 -19
View File
@@ -20,6 +20,7 @@ import {
Sparkles,
Cpu,
Layers,
Lock,
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { toast } from 'sonner';
@@ -52,6 +53,8 @@ function getModeColor(mode: AgentListItem['mode']) {
return 'bg-purple-500/20 text-purple-400';
case 'all':
return 'bg-green-500/20 text-green-400';
case 'internal':
return 'bg-slate-500/20 text-slate-400';
default:
return 'bg-gray-500/20 text-gray-400';
}
@@ -66,6 +69,8 @@ function getModeText(mode: AgentListItem['mode']) {
return 'Subagent';
case 'all':
return 'Both';
case 'internal':
return 'Internal';
default:
return mode;
}
@@ -189,9 +194,10 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
setAgentDetails({});
};
// 统计
const presetAgents = agents.filter((a) => a.isPreset);
const customAgents = agents.filter((a) => !a.isPreset);
// 统计 - 按分类过滤
const internalAgents = agents.filter((a) => a.mode === 'internal');
const presetAgents = agents.filter((a) => a.isPreset && a.mode !== 'internal');
const customAgents = agents.filter((a) => !a.isPreset && a.mode !== 'internal');
// Loading 骨架屏
const LoadingSkeleton = () => (
@@ -214,6 +220,7 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
const isExpanded = expandedAgents.has(agent.name);
const isLoading = actionLoading === agent.name;
const detail = agentDetails[agent.name];
const isInternal = agent.mode === 'internal';
return (
<motion.div
@@ -236,7 +243,9 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
</button>
{/* Icon */}
{agent.isPreset ? (
{isInternal ? (
<Lock size={16} className="text-slate-400" />
) : agent.isPreset ? (
<Sparkles size={16} className="text-yellow-400" />
) : (
<Bot size={16} className="text-primary-400" />
@@ -264,8 +273,18 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
<div className="animate-spin rounded-full h-5 w-5 border-t-2 border-b-2 border-primary-500" />
) : (
<>
{/* View/Edit */}
{agent.isPreset && !agent.isCustomized ? (
{/* View/Edit - Internal agents can be edited (model config) */}
{isInternal ? (
<Button
variant="ghost"
size="sm"
onClick={() => setEditingAgent({ name: agent.name, isNew: false })}
className="text-blue-400 hover:text-blue-300"
title="Edit Model Config"
>
<Edit3 size={14} />
</Button>
) : agent.isPreset && !agent.isCustomized ? (
<Button
variant="ghost"
size="sm"
@@ -287,19 +306,21 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
</Button>
)}
{/* Copy */}
<Button
variant="ghost"
size="sm"
onClick={() => handleCopy(agent.name)}
className="text-gray-400 hover:text-gray-300"
title="Copy"
>
<Copy size={14} />
</Button>
{/* Copy - not for internal agents */}
{!isInternal && (
<Button
variant="ghost"
size="sm"
onClick={() => handleCopy(agent.name)}
className="text-gray-400 hover:text-gray-300"
title="Copy"
>
<Copy size={14} />
</Button>
)}
{/* Delete (only for custom agents) */}
{!agent.isPreset && (
{/* Delete (only for custom agents, not internal) */}
{!agent.isPreset && !isInternal && (
<Button
variant="ghost"
size="sm"
@@ -475,7 +496,7 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
Agent Presets
</h2>
<p className="text-xs text-gray-500">
{agents.length} agents ({presetAgents.length} preset, {customAgents.length} custom)
{agents.length} agents ({internalAgents.length} system, {presetAgents.length} preset, {customAgents.length} custom)
</p>
</div>
<div className="flex items-center gap-2">
@@ -541,6 +562,21 @@ export function AgentsPanel({ onClose, responsive = false }: AgentsPanelProps) {
animate={{ opacity: 1 }}
className={cn('space-y-4', responsive ? 'p-4' : 'p-4')}
>
{/* System Agents (Internal) */}
{internalAgents.length > 0 && (
<div>
<h3 className="text-xs font-medium text-slate-400 uppercase tracking-wide mb-2 flex items-center gap-2">
<Lock size={12} />
System Agents
</h3>
<div className="space-y-2">
{internalAgents.map((agent) => (
<AgentItem key={agent.name} agent={agent} />
))}
</div>
</div>
)}
{/* Preset Agents */}
{presetAgents.length > 0 && (
<div>