"use client"; import { useEffect, useMemo, useRef, useState } from "react"; import { ArrowLeft, BookOpen, ChevronRight, FileText, GitCompareArrows, X } from "lucide-react"; import type { CanvasItem, DetailItem, DetailSection, InspectorDetailProjection, InspectorSemanticMeta, InspectorTab, RetrievalActivity } from "@/lib/types"; import { SourceNoticeBadge, StatusBadge } from "@/components/ui/Badges"; import { RichText } from "@/components/ui/RichText"; import { ValueView } from "@/components/ui/ValueView"; import { TabList } from "@/components/ui/TabList"; import { DecisionDetailRenderer } from "@/components/decision/DecisionDetailRenderer"; import { authorityLabel, decisionFor, decisionTypeLabel } from "@/components/decision/AgentDecisionCard"; import { RetrievalDetailRenderer } from "@/components/inspector/RetrievalDetailRenderer"; interface Props { item: CanvasItem; tab: InspectorTab; onTab: (tab: InspectorTab) => void; onClose: () => void; onBack?: () => void; backLabel?: string; onNavigate?: (activity: RetrievalActivity) => void; onPrompt?: (promptRef: string) => void; onArtifact?: () => void; onLineage?: () => void; detail?: unknown; detailLoading?: boolean; detailError?: string; } export function LegacyInspector({ item, tab, onTab, onClose, onBack, backLabel, onNavigate, onPrompt, onArtifact, onLineage, detail, detailLoading, detailError }: Props) { const dialog = useRef(null); const [modal, setModal] = useState(false); const projection = useMemo(() => normalizeProjection(item, detail), [item, detail]); const tabs = useMemo>(() => [ { id: "business", label: "业务详情" }, ...(projection.changes ? [{ id: "changes" as const, label: "产出与改动" }] : []), { id: "technical", label: "技术详情" }, ], [projection.changes]); useEffect(() => { const query = window.matchMedia("(max-width: 1199px)"); const update = () => setModal(query.matches); update(); query.addEventListener("change", update); return () => query.removeEventListener("change", update); }, []); useEffect(() => { if (!tabs.some((entry) => entry.id === tab)) onTab("business"); }, [onTab, tab, tabs]); const trapFocus = (event: React.KeyboardEvent) => { if (event.key !== "Tab" || !modal) return; const focusable = [...(dialog.current?.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])') || [])]; if (!focusable.length) return; const first = focusable[0]; const last = focusable[focusable.length - 1]; if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); } else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); } }; return ; } function BusinessDetails({ item, projection, onPrompt, onNavigate, onArtifact }: { item: CanvasItem; projection: InspectorDetailProjection; onPrompt?: Props["onPrompt"]; onNavigate?: Props["onNavigate"]; onArtifact?: Props["onArtifact"] }) { const decision = decisionFor(item); const promptRef = projection.promptRef || decision?.promptRef; const actorRole = projection.actor?.role || decision?.actor.role; return <> {promptRef && onPrompt || item.itemType === "final-result" && onArtifact ?
{promptRef && onPrompt ? : null} {item.itemType === "final-result" && onArtifact ? : null}
: null} {projection.detailKind?.startsWith("retrieval-") ? : projection.detailKind === "agent-decision" ? <>
{projection.actor ? {projection.actor.label} : null}{projection.decisionType ? {decisionTypeLabel(projection.decisionType)} : null}{projection.authority ? {authorityLabel(projection.authority)} : null}
{projection.question ? : null} : projection.businessSections?.length ? projection.businessSections.map((section) => ) : } ; } function promptActionLabel(item: CanvasItem, actorRole?: string) { if (item.itemType === "story" && item.role === "data-decision") return "查看取数任务与提示词"; if (actorRole === "main") return "查看主 Agent 提示词"; if (actorRole === "multipath-evaluator") return "查看评审任务与提示词"; if (actorRole === "overall-evaluator") return "查看整体评审提示词"; return "查看实现任务与提示词"; } function ChangesDetails({ changes }: { changes: NonNullable }) { return <>{changes.summary ? : null}{changes.sections.map((section) => )}

{exactnessLabel(changes.exactness)}

; } function SectionPanel({ section }: { section: DetailSection }) { const content = section.id === "plan" && section.content ? insertExecutionPlanBreaks(section.content) : section.content; return {section.items?.length ? : content ? : }; } function insertExecutionPlanBreaks(value: string) { const pattern = /(^|[ \t\u3000]+)(\d+)([.)、])(?=[ \t\u3000]*\S)/gm; const markers = [...value.matchAll(pattern)]; if (markers.length < 2) return value; const numbers = markers.map((match) => Number(match[2])); if (numbers[0] !== 1 || numbers.some((number, index) => index > 0 && number !== numbers[index - 1] + 1)) return value; let markerIndex = 0; return value.replace(pattern, (match, prefix: string, number: string, punctuation: string, offset: number) => { const first = markerIndex++ === 0; if (first && offset === 0) return `${number}${punctuation}`; return `${first ? "\n\n" : " \n"}${number}${punctuation}`; }); } function DetailItems({ items }: { items: DetailItem[] }) { return
{items.map((item, index) =>
{item.label}
{item.sourceNotice && item.sourceNotice !== "runtime-associated" ? : null}
)}
; } function StoryBadges({ item }: { item: CanvasItem }) { const status = item.itemType === "story" ? item.status : item.itemType === "branch-summary" ? item.branch.status : item.itemType === "round-summary" ? item.round.state : item.itemType === "final-result" ? item.result.status : item.itemType === "retrieval-stage" ? item.stage.status : item.itemType === "retrieval-agent" ? item.run.status : item.itemType === "retrieval-direct" ? item.group.failureCount || item.group.interruptedCount ? "partial" : item.group.runningCount ? "running" : "completed" : item.itemType === "query-attempt" ? item.attempt.status : item.itemType === "retrieval-activity" ? item.activity.status : item.itemType === "multipath-review" ? item.review.status : undefined; return status ?
: null; } function normalizeProjection(item: CanvasItem, detail: unknown): InspectorDetailProjection { const record = asRecord(detail); if (record && Object.prototype.hasOwnProperty.call(record, "technical") && (Array.isArray(record.businessSections) || typeof record.detailKind === "string")) return record as unknown as InspectorDetailProjection; return { detailKind: "activity", businessSections: [], technical: detail ?? item }; } function TechnicalDetails({ value }: { value: unknown }) { const record = asRecord(value); if (!record) return ; const groups = [["source", "数据来源与定位"], ["association", "关联方式与完整性"], ["input", "原始输入"], ["output", "原始输出"], ["cost", "耗时与成本"]] as const; const shown = new Set(); return <>{groups.map(([key, title]) => { if (!Object.prototype.hasOwnProperty.call(record, key)) return null; shown.add(key); return ; })} !shown.has(key)))} />; } function exactnessLabel(value: NonNullable["exactness"]) { return ({ exact: "这是可确认的精确记录。", "current-only": "这里只能确认当前主脚本,无法还原每轮结束时的完整版本。", "historical-snapshot": "这里展示的是处置前保存的候选快照。", unknown: "当前记录不足以还原精确的前后差异。" } as const)[value]; } function Panel({ title, children, missing = false, variant = "default", visualRole, presentation, collapsible = false, defaultOpen = false }: { title: string; children: React.ReactNode; missing?: boolean; variant?: DetailSection["variant"] } & InspectorSemanticMeta) { const role = visualRole || (variant === "summary" ? "key-result" : "section"); const panelProps = { className: `inspectorPanel ${missing ? "isMissing" : ""} is-${variant} is-role-${role} ${collapsible ? "decisionDisclosurePanel" : ""}`, "data-visual-role": role, "data-presentation": presentation || "prose" }; if (collapsible) return
{children}
; return

{title}

{children}
; } function BusinessText({ value, className = "" }: { value: string; className?: string }) { return ; } function asRecord(value: unknown): Record | undefined { return value && typeof value === "object" && !Array.isArray(value) ? value as Record : undefined; } function itemLabel(item: CanvasItem) { return item.itemType === "story" ? item.role === "planning-analysis" ? "构建开始前的规划" : item.kind === "decision" ? "这一步的决定" : item.kind === "result" ? "这一步的结果" : "这一步做了什么" : item.itemType === "branch-summary" ? "候选方案" : item.itemType === "round-summary" ? "轮次摘要" : item.itemType === "retrieval-stage" ? "取数阶段" : item.itemType === "retrieval-direct" ? "工具取数" : item.itemType === "retrieval-agent" ? "Agent 取数" : item.itemType === "query-attempt" ? "单次查询" : item.itemType === "retrieval-activity" ? item.activity.kind === "tool" ? "单次工具调用" : "单次查询" : item.itemType === "multipath-review" ? "候选方案评审" : item.itemType === "multipath-decision" ? "主 Agent 决策" : "最终结果"; }