Files
HomeAgent/internal/agent
JianFeeeee 28b42bcf0f refactor(toolcall): 批内消息改为「一个 assistant 带全部 tool_calls」(阶段 2a)
问题:现状每个工具各自 append 一对(assistant[tool_calls=[tc]] + tool),
既不表达「这是一批」,也无法支撑并行:
· 产生 N 条 assistant 消息,同一段 assistant 文本语义上只该出现一次
· 并行下完成顺序不确定,若等结果回来再落消息,assistant 就必须等所有
  结果齐了才能写——而 OpenAI 协议要求 assistant(tool_calls) 在结果**之前**

改动(task.go):
· TaskFrame 增 assistantMsgIdx
· 新增 ensureBatchAssistant:惰性写入,全批只写**一条** assistant,
  携带 f.PendingTools 全部 tool_calls;后续工具只补 tool 消息
· stepToolBegin 的 denied / unhealthy 分支与 stepToolAfter 统一改用它
· stepLLM 设 PendingTools 时清零 assistantMsgIdx
· msgContent 的 ContentOnce 归位移入 ensureBatchAssistant(仍是只挂第一条)

⚠️ 依赖:before_toolcall 阶段**不得**改写工具参数——已核实全仓无此用法
(grep ToolCalls[0].Arguments 赋值无结果)。若将来某插件要改写 args,
需改为「回填后重写该条 assistant」。该前提已写入代码注释。

判据(toolbatch_test.go 追加 TestBatchLayoutSingleAssistantCarriesAllToolCalls):
· 带 tool_calls 的 assistant **恰好一条**且携带 2 个 tool_calls
· 其后紧跟 2 条 tool 消息且按声明顺序(c1、c2)

变异验证:让 ensureBatchAssistant 退化为「每工具一条」⇒ 判据 FAIL
「批内 assistant 应带 2 个 tool_calls,实际 1」。

stage 0.5 补的三条判据(配对完整性 / ContentOnce / denied 后继续)
在本改动后**仍然全绿**——它们正是为这种改动准备的保护网。

回归:internal/agent/... internal/sdk/... internal/plugins/... 全绿(18 包)。
2026-09-27 11:09:02 +08:00
..