feat(beaver): 完成Task Team功能v1实现,重构后端架构支持统一内核

新增内部Task系统,包括验证、反馈门控机制,实现自动质量验证
(通过率>=0.75)和用户反馈闭环(satisfied/revise/abandon)。

实现Agent Team v1协调器,支持sequence/parallel/dag执行策略,
sub-agent复用主AgentLoop,每个run使用独立memory snapshot。

建立Skill学习pipeline,包含draft/审核/发布/回滚完整生命周期,
通过Task验证通过且用户满意才生成学习候选。

重构目录结构,移除third_party依赖,建立统一engine内核,
所有agent共享运行时基础组件。

更新ContextBuilder清理provider消息字段,增强SkillContext版本管理,
集成TaskExecutionPlanner和TaskSkillResolver实现技能解析机制。
This commit is contained in:
2026-05-08 17:14:14 +08:00
parent 5ba5c7e4c1
commit 8a12c30141
93 changed files with 16724 additions and 1247 deletions

View File

@ -161,6 +161,36 @@ function runSummary(run: ProcessRun, feed: AgentFeedItem[], locale: 'zh-CN' | 'e
return latestAssistant?.text || pickAppText(locale, '已完成子任务处理', 'Subtask processing completed');
}
function SkillChips({ metadata }: { metadata?: Record<string, unknown> }) {
const rawSelected = metadata?.selected_skill_names;
const rawEphemeral = metadata?.ephemeral_skill_names;
const selected = Array.isArray(rawSelected) ? rawSelected.map(String).filter(Boolean) : [];
const ephemeral = Array.isArray(rawEphemeral) ? rawEphemeral.map(String).filter(Boolean) : [];
const draftId = typeof metadata?.generated_skill_draft_id === 'string' ? metadata.generated_skill_draft_id : '';
if (selected.length === 0 && ephemeral.length === 0 && !draftId) {
return null;
}
return (
<div className="mt-1.5 flex flex-wrap gap-1.5">
{selected.map((name) => (
<Badge key={`skill:${name}`} variant="secondary" className="max-w-[128px] truncate text-[10px]">
skill:{name}
</Badge>
))}
{ephemeral.map((name) => (
<Badge key={`ephemeral:${name}`} variant="outline" className="max-w-[128px] truncate text-[10px]">
ephemeral:{name}
</Badge>
))}
{draftId && (
<Badge variant="outline" className="text-[10px]">
draft:{draftId.slice(0, 8)}
</Badge>
)}
</div>
);
}
function useRunCardPhases(runs: ProcessRun[]) {
const [phases, setPhases] = React.useState<Record<string, RunCardPhase>>(() =>
Object.fromEntries(
@ -288,10 +318,11 @@ function LiveAgentCard({
<div className="min-w-0">
<div className="flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.18em] text-muted-foreground">
<span className={cn('h-2 w-2 rounded-full', accent.dot)} />
<span>{pickAppText(locale, '子 Agent', 'Sub-agent')}</span>
<span>{pickAppText(locale, '子任务', 'Subtask')}</span>
</div>
<div className={cn('mt-1 truncate text-sm font-semibold', accent.title)}>{run.actor_name}</div>
<div className="mt-1 line-clamp-2 text-xs text-muted-foreground">{run.title}</div>
<SkillChips metadata={run.metadata} />
</div>
<Badge variant="outline" className={cn('border', statusTone(run.status))}>
{appStatusLabel(run.status, locale)}
@ -302,7 +333,7 @@ function LiveAgentCard({
<div className="max-h-[280px] space-y-2.5 overflow-y-auto pr-1">
{feed.length === 0 && (
<div className="rounded-2xl border border-dashed border-border/60 bg-background/60 px-4 py-5 text-center text-sm text-muted-foreground">
{pickAppText(locale, '等待子 agent 输出...', 'Waiting for sub-agent output...')}
{pickAppText(locale, '等待子任务输出...', 'Waiting for subtask output...')}
</div>
)}
{feed.map((item) => (
@ -445,13 +476,13 @@ export function AgentTeamBlock({
<div>
<div className="inline-flex items-center gap-2 text-xs font-medium uppercase tracking-[0.2em] text-muted-foreground">
<Sparkles className="h-3.5 w-3.5" />
{pickAppText(locale, '智能体团队', 'Agent team')}
{pickAppText(locale, '任务子流程', 'Task subprocess')}
</div>
<div className="mt-1.5 text-base font-semibold text-foreground">{rootRun.title}</div>
<p className="mt-1 text-sm text-muted-foreground">
{liveCount > 0
? pickAppText(locale, `agent 正在协调 ${liveCount} 个运行中的 sub-agent`, `Lead agent is coordinating ${liveCount} running sub-agents`)
: pickAppText(locale, '子 agent 已完成,结果已折叠为摘要卡片', 'Sub-agents are done. Results are folded into summary cards')}
? pickAppText(locale, `Agent 正在协调 ${liveCount} 个运行中的子任务`, `Main Agent is coordinating ${liveCount} running subtasks`)
: pickAppText(locale, '子任务已完成,结果已折叠为摘要卡片', 'Subtasks are done. Results are folded into summary cards')}
</p>
</div>
<div className="flex items-center gap-2">
@ -462,7 +493,7 @@ export function AgentTeamBlock({
</Button>
)}
<Badge variant="outline" className="border-border/70 bg-background/55 text-foreground/85">
{pickAppText(locale, `${memberRuns.length} sub-agent`, `${memberRuns.length} sub-agents`)}
{pickAppText(locale, `${memberRuns.length}子任务`, `${memberRuns.length} subtasks`)}
</Badge>
<Badge variant="outline" className={cn('border', statusTone(rootRun.status))}>
{appStatusLabel(rootRun.status, locale)}