feat(web): W4-A wire console to real endpoints

- Agent page uses contracts (AgentRun/AgentRunDetail/AgentGoalReport) instead of a local
  mirror; ?mock=1 stays as an explicit demo switch; run snapshot refreshes on agent.run_status;
  stream auto-follow only while the user stays near the bottom (abort stays reachable)
- settings: Pi provider select incl. fake, new Agent runtime card (budgets, fakeScript)
- download trace uses /tasks?subjectId= and /organization-records?downloadTaskId= instead of
  time-window engine run matching and path matching; new business-task tab with cancel/retry
- workbench download dialog posts /acquisition-plans and shows per-slot rejection reasons
- preference tag revision history; subscription search by title/kind; identity/alias/subscription
  lists show entity titles; slot cards show current asset summary; policy preview sample titles
- DecisionSummary / IdentityRevisionList / ReleaseIdentityResult / TaskAccepted / PolicyPreviewSummary /
  OrganizePlanArtifactContent taken from contracts
- docs: SSE for console (cookie) vs GET /events?after=&limit= JSON replay for API keys

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-27 21:32:11 +08:00
1 parent 34e8751b45
commit 1023642ef9
30 files changed
+703 -271

No files matched your search

@@ -124,7 +124,17 @@ const PI_CARD: CardSpec = {
title: "Pi 上游与模型",
description: "Agent 使用的模型上游。密钥只写入、加密保存,不回显。",
fields: [
{ name: "pi.provider", label: "Provider", kind: "text", required: true, placeholder: "anthropic" },
{
name: "pi.provider",
label: "Provider",
kind: "select",
required: true,
options: [
{ value: "anthropic", label: "anthropic" },
{ value: "openai-compatible", label: "openai-compatible(baseUrl 带 /v1)" },
{ value: "fake", label: "fake(脚本化假模型,不联网,演示用)" },
],
},
{ name: "pi.model", label: "模型", kind: "text", placeholder: "留空用 provider 默认" },
{ name: "pi.baseUrl", label: "Base URL", kind: "url", placeholder: "留空用官方地址", wide: true },
{ name: "pi.apiKey", label: "API Key", kind: "password", hint: "留空表示不修改", wide: true },
@@ -216,11 +226,58 @@ const AGENT_BUDGET_CARD: CardSpec = {
}),
};
const AGENT_RUNTIME_CARD: CardSpec = {
title: "Agent 运行",
description: "单次运行预算、后台自动调查;provider 选 fake 时按下面的脚本回放工具调用(留空用内置演示脚本)。",
fields: [
{ name: "agent.maxToolCalls", label: "单次工具调用上限", kind: "number", hint: "1 – 500" },
{ name: "agent.maxDurationSec", label: "单次时长上限(秒)", kind: "number" },
{ name: "agent.autoInvestigate", label: "待处理事项自动调查", kind: "switch" },
{
name: "agent.investigateMaxToolCalls",
label: "自动调查工具调用上限",
kind: "number",
visible: (v) => v["agent.autoInvestigate"] === true,
},
{ name: "agent.goalPollSec", label: "目标落定轮询(秒)", kind: "number" },
{ name: "agent.goalWaitHours", label: "目标最长等待(小时)", kind: "number" },
{
name: "agent.fakeScript",
label: "fake 脚本(JSON)",
kind: "textarea",
hint: '{"match":"收进来","steps":[{"toolCalls":[{"capability":"inventory.query","input":{"query":"沙丘2"}}]}],"finalText":"…"},格式见 docs/runbook/agent.md',
},
],
fromSettings: (s) => ({
"agent.maxToolCalls": n(s.agent.maxToolCalls),
"agent.maxDurationSec": n(s.agent.maxDurationSec),
"agent.autoInvestigate": s.agent.autoInvestigate,
"agent.investigateMaxToolCalls": n(s.agent.investigateMaxToolCalls),
"agent.goalPollSec": n(s.agent.goalPollSec),
"agent.goalWaitHours": n(s.agent.goalWaitHours),
"agent.fakeScript": s.agent.fakeScript ?? "",
}),
toPatch: (v) => ({
agent: {
maxToolCalls: num(v["agent.maxToolCalls"]),
maxDurationSec: num(v["agent.maxDurationSec"]),
autoInvestigate: v["agent.autoInvestigate"] === true,
investigateMaxToolCalls: num(v["agent.investigateMaxToolCalls"]),
goalPollSec: num(v["agent.goalPollSec"]),
goalWaitHours: num(v["agent.goalWaitHours"]),
fakeScript: str(v["agent.fakeScript"]).trim() || null,
},
}),
};
export function PiTab() {
return useSettingsGate((s) => (
<div className="grid gap-4 xl:grid-cols-[minmax(0,3fr)_minmax(0,2fr)]">
<SettingsCard spec={PI_CARD} settings={s} />
<SettingsCard spec={AGENT_BUDGET_CARD} settings={s} />
<div className="grid content-start gap-4">
<SettingsCard spec={AGENT_BUDGET_CARD} settings={s} />
<SettingsCard spec={AGENT_RUNTIME_CARD} settings={s} />
</div>
</div>
));
}