import type { Part } from "@opencode-ai/sdk/v2"; import { PRODUCT_MCP_TOOL_IDS, queryMcpToolId } from "../runtime/product-mcp-tools.js"; const labels = { reference: "查找所需资料", data: "获取业务数据", analysis: "分析与核查", visualization: "更新地图与图表", other: "执行操作" }; const classify = (tool: string): keyof typeof labels => { if (["skill", "read", "glob", "grep", queryMcpToolId("session_search"), "session_search", "memory_manager", "skill_manager"].includes(tool)) return "reference"; if ([...PRODUCT_MCP_TOOL_IDS, "websearch", queryMcpToolId("geocode"), queryMcpToolId("list_investigation_tasks"), queryMcpToolId("get_investigation_task"), queryMcpToolId("read_agent_messages"), "query_project_data", "query_operational_task_data", "get_operational_task_context"].includes(tool)) return "data"; if (["render_scada_analysis", "clear_scada_analysis", "locate_features", "zoom_to_map", "show_chart", "view_history", "publish_task_presentation"].includes(tool)) return "visualization"; if (["publish_execution_plan", "publish_task_report", "publish_task_progress", "propose_task_action", "add_task_human_evidence"].includes(tool)) return "analysis"; return "other"; }; export const createBusinessStageTracker = (write: (event: string, data: Record) => void) => { const stages = new Map }>(); return (part: Extract) => { if (["final_answer", "todowrite", "todoread", queryMcpToolId("todoread"), "question"].includes(part.tool)) return; const kind = classify(part.tool); const stage = stages.get(kind) ?? { startedAt: Date.now(), actions: new Map() }; stage.actions.set(part.id, part.state.status); stages.set(kind, stage); const statuses = [...stage.actions.values()]; const running = statuses.some((status) => status === "pending" || status === "running"); const status = running ? "running" : statuses.includes("error") ? "error" : "completed"; write("progress", { id: `business-${kind}`, phase: kind, status, title: labels[kind], detail: `${statuses.filter((s) => s === "completed").length}/${statuses.length} 项操作已完成`, started_at: stage.startedAt, ...(running ? { elapsed_ms: Date.now() - stage.startedAt } : { ended_at: Date.now(), duration_ms: Date.now() - stage.startedAt }), }); }; };