执行方案 DevDocs/audit/_plan.md 阶段 0 · G0-D: - lib/types.ts(871) → lib/types/ 11 个域文件 + 14 行 `export *` barrel(仿 lib/api.ts 先例) chat / ws / session / agent / flow / persona / api / admin(269) / adminWrite(176) / kook / notification - lib/ws.ts(494) → 203 行入口 + lib/ws/handlers/ 8 文件;dispatchFrame(266 行) 改为按组 分发链(7 个 handler 各持一组 case,命中 return true,未命中走原 default 兜底), 33 个 case 标签一一守恒 机械证明:type 导出集 86 个守恒(拆后并集 diff 为空);去掉空行与 import/export 语句后 **784=784 行、排序 diff 为空**;dispatchFrame 的 case 标签集 33=33 守恒;ws.ts 的 scheduleReconnect 至文件尾与 HEAD 字节级一致。 65 个 lib/types 消费方 + 3 个 lib/ws 消费方**零改动**通过 —— tsc 0 错误正是这一点的强判据。 验证:npx tsc --noEmit 0 错误;npm run build 成功;9 个前端逻辑测试全绿(含真实驱动 拆后 dispatchFrame 的 messageSync 54 checks 与 personaSession 23 checks); 最大文件 admin.ts 269 行、最大函数 openSocket 72 行(均达标)。
40 lines
1.4 KiB
TypeScript
40 lines
1.4 KiB
TypeScript
import { streamFrameApplies } from "../../streamScope";
|
|
import { parseTool, parseToolCall } from "../../wsParse";
|
|
import type { FrameEvent, FramePayload, StoreState } from "./shared";
|
|
|
|
/** 工具帧处理组:tool_call.start / tool_call.end / tool_call.delta /
|
|
* tool_execution.update + 遗留 tool_used。命中(含组内主动丢弃)返回 true,
|
|
* 未命中返回 false 交给下一组。 */
|
|
export function handleToolEvent(ev: FrameEvent, r: FramePayload, s: StoreState): boolean {
|
|
switch (ev.type) {
|
|
case "tool_call.start":
|
|
case "tool_call.end": {
|
|
if (!streamFrameApplies(ev, r, s.activeSessionId)) return true;
|
|
const tool = parseToolCall(ev.data);
|
|
if (tool) s.addTool(tool);
|
|
return true;
|
|
}
|
|
case "tool_call.delta": {
|
|
// Argument fragments stream between start/end; the card is added at the
|
|
// boundary so mid-stream reconnects do not drop it.
|
|
return true;
|
|
}
|
|
case "tool_execution.update": {
|
|
// Same card as tool_call.* — same guard.
|
|
if (!streamFrameApplies(ev, r, s.activeSessionId)) return true;
|
|
const tool = parseToolCall(ev.data);
|
|
if (tool) s.addTool(tool);
|
|
return true;
|
|
}
|
|
case "tool_used": {
|
|
// Legacy tool echo — same card as tool_call.*.
|
|
if (!streamFrameApplies(ev, r, s.activeSessionId)) return true;
|
|
const tool = parseTool(ev.data);
|
|
if (tool) s.addTool(tool);
|
|
return true;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|