feat(workbench): redesign investigation reports and diagrams

This commit is contained in:
2026-10-10 16:02:47 +08:00
parent 85a9a3ab45
commit ba78a24384
27 changed files with 2380 additions and 187 deletions
@@ -0,0 +1,93 @@
import { z } from "zod";
import type { AgentTaskDiscussionContext } from "@/features/agent";
export type InvestigationDiscussion = { prompt?: string; context?: AgentTaskDiscussionContext };
const text = z.string().trim().min(1);
export const investigationDiagramSchema = z
.object({
title: text,
mermaid: text
.max(20000)
.refine(
(source) =>
/^\s*(?:flowchart|graph)\s+(?:TD|TB|BT|LR|RL)\b/.test(source) &&
!source.includes("```") &&
!source.includes("%%{") &&
!/(?:^|[;\n])\s*click\b/.test(source),
"调查图只接受不含指令或回调的 Mermaid 流程描述"
),
node_refs: z
.array(
z
.object({
node_id: z.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,79}$/),
label: text,
evidence_refs: z.array(text).default([]),
action_refs: z.array(z.string().uuid()).default([])
})
.strict()
)
.max(100)
.default([])
})
.strict()
.superRefine((diagram, ctx) => {
if (new Set(diagram.node_refs.map((node) => node.node_id)).size !== diagram.node_refs.length) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "调查图节点引用重复" });
}
});
const dataGapSchema = z
.object({
gap_id: text,
node_id: text.nullish(),
missing_data: text,
scope: text,
impact: text,
required_data: text,
evidence_refs: z.array(text).min(1),
blocking: z.boolean()
})
.strict();
/** Historical omissions remain unknown. Never infer outcomes from report prose. */
export const investigationReportSchema = z
.object({
title: text,
current_conclusion: text,
conclusion_boundary: text,
evidence_refs: z.array(text),
recommendations: z.array(text),
pending_items: z.array(text),
stage: z.enum(["interim", "final"]).nullish(),
outcome: z.enum(["concluded", "insufficient_data"]).nullish(),
stop_reason: text.nullish(),
data_gaps: z.array(dataGapSchema).nullish(),
diagram: investigationDiagramSchema.nullish()
})
.strict()
.superRefine((report, ctx) => {
const invalid = (message: string) => ctx.addIssue({ code: z.ZodIssueCode.custom, message });
if (report.outcome == null) {
if (report.stage != null || report.stop_reason != null || report.data_gaps != null)
invalid("报告结构化字段必须一起提供");
return;
}
if (report.stage == null || report.data_gaps == null) {
invalid("报告缺少阶段或数据缺口清单");
return;
}
if (new Set(report.data_gaps.map((gap) => gap.gap_id)).size !== report.data_gaps.length)
invalid("数据缺口编号重复");
const blocking = report.data_gaps.some((gap) => gap.blocking);
if (report.outcome === "insufficient_data") {
if (report.stage !== "final" || !report.stop_reason || !blocking)
invalid("证据不足必须提供最终报告、结束原因和关键缺口");
if (report.recommendations.length || report.pending_items.length)
invalid("证据不足退出后不再生成后续处置建议或待办");
} else if (report.stop_reason != null || blocking)
invalid("已形成结论不能包含结束原因或阻塞缺口");
});
export type InvestigationReport = z.infer<typeof investigationReportSchema>;
export type InvestigationDiagram = z.infer<typeof investigationDiagramSchema>;