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:
1 parent
34e8751b45
commit
1023642ef9
30 files changed
+703
-271
No files matched your search
@@ -7,6 +7,7 @@ import {
|
||||
useLiftSuppression,
|
||||
usePreferenceTags,
|
||||
useSuppressions,
|
||||
useTagRevisions,
|
||||
useUpdateTag,
|
||||
} from "~/api/preferences.ts";
|
||||
import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx";
|
||||
@@ -315,6 +316,9 @@ export default function PreferencesPage() {
|
||||
<DetailSection title="证据">
|
||||
<JsonView value={Object.keys(selected.evidence).length ? selected.evidence : null} />
|
||||
</DetailSection>
|
||||
<DetailSection title="修订历史">
|
||||
<TagRevisions id={selected.id} />
|
||||
</DetailSection>
|
||||
</>
|
||||
) : null}
|
||||
</DetailSheet>
|
||||
@@ -324,6 +328,44 @@ export default function PreferencesPage() {
|
||||
);
|
||||
}
|
||||
|
||||
const REV_ACTION = { created: "创建", updated: "修改", deleted: "删除" } as const;
|
||||
const FIELD_LABEL: Record<string, string> = {
|
||||
label: "名称",
|
||||
kind: "类型",
|
||||
scope: "作用范围",
|
||||
rule: "规则",
|
||||
description: "说明",
|
||||
evidence: "证据",
|
||||
status: "状态",
|
||||
};
|
||||
|
||||
function TagRevisions({ id }: { id: string }) {
|
||||
const q = useTagRevisions(id);
|
||||
if (q.isPending) return <LoadingState rows={2} />;
|
||||
if (q.isError) return <ErrorState plain error={q.error} onRetry={() => q.refetch()} />;
|
||||
if (q.data.length === 0)
|
||||
return <p className="text-caption text-muted-foreground">没有修订记录(W4 之前创建的标签不带历史)。</p>;
|
||||
return (
|
||||
<ul className="space-y-2">
|
||||
{q.data.map((r) => (
|
||||
<li key={r.id} className="rounded-lg border border-border/70 px-3 py-2 text-caption">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span className="font-medium text-foreground">{REV_ACTION[r.action]}</span>
|
||||
{r.revision ? <span className="text-muted-foreground tabular-nums">r{r.revision}</span> : null}
|
||||
<span className="text-muted-foreground">{r.actorType === "api_key" ? "API Key" : "用户"}</span>
|
||||
<span className="ml-auto text-meta text-muted-foreground tabular-nums">{formatDateTime(r.at)}</span>
|
||||
</div>
|
||||
<p className="mt-1 text-meta text-muted-foreground">
|
||||
{r.changedFields.length
|
||||
? `改动:${r.changedFields.map((f) => FIELD_LABEL[f] ?? f).join("、")}`
|
||||
: `名称:${r.snapshot.label} · 状态:${r.snapshot.status}`}
|
||||
</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function SuppressionRow({
|
||||
s,
|
||||
label,
|
||||
|
||||
Reference in new issue
Block a user