Files
smartmate/backend/services/agent/tools/工具结果结构化交接文档.md
Losita d7184b776b Version: 0.9.75.dev.260505
后端:
1.收口阶段 6 agent 结构迁移,将 newAgent 内核与 agentsvc 编排层迁入 services/agent
- 切换 Agent 启动装配与 HTTP handler 直连 agent sv,移除旧 service agent bridge
- 补齐 Agent 对 memory、task、task-class、schedule 的 RPC 适配与契约字段
- 扩展 schedule、task、task-class RPC/contract 支撑 Agent 查询、写入与 provider 切流
- 更新迁移文档、README 与相关注释,明确 agent 当前切流点和剩余 memory 迁移面
2026-05-05 16:00:57 +08:00

367 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 工具结果结构化交接文档
## 最新负责人验收结论
本轮已经按“直接切流”完成 read 结果构造迁移6 个 `schedule.read_result` 工具仍由父包注册入口暴露,但父包只保留薄 adapter真实展示数据构造已经切到 `backend/services/agent/tools/schedule_read/` 子包。
第三批 `schedule.analysis_result` 也已经完成直接切流:`analyze_health` / `analyze_rhythm` 仍然保留原始 JSON `ObservationText`,前端展示新增走 `ResultView`
第四批非 schedule read/analysis 主链也已经完成直接切流:`web_search``web_fetch``upsert_task_class``context_tools_add``context_tools_remove` 已经分别切到专属结构化卡片;队列尾巴 `queue_pop_head` / `queue_skip_head` 也已经脱离 `legacy_text`
第四批当前切流点:
1. `registry.go`
- `web_search` 已切到 `NewWebSearchToolHandler()`
- `web_fetch` 已切到 `NewWebFetchToolHandler()`
- `upsert_task_class` 继续注册 `NewTaskClassUpsertToolHandler()`,但该入口已由 `taskclass_result_handlers.go` 承接结构化包装。
- `context_tools_add` / `context_tools_remove` 已在原 handler 内直接返回 `tool.context_result`
- `queue_pop_head` 已切到 `NewQueuePopHeadToolHandler()`
- `queue_skip_head` 已切到 `NewQueueSkipHeadToolHandler()`
- `wrapLegacyToolHandler` 已删除,当前默认注册表不再依赖该 legacy wrapper。
2. `backend/services/agent/tools/web_result/**` + `web_result_handlers.go`
- `web_search` 输出 `result_view.view_type = "web.search_result"`
- `web_fetch` 输出 `result_view.view_type = "web.fetch_result"`
- 原始 observation 继续写入 `ObservationText` / `expanded.raw_text`
3. `backend/services/agent/tools/taskclass_result/**` + `taskclass_result_handlers.go`
- `upsert_task_class` 输出 `result_view.view_type = "taskclass.write_result"`
- 写库、confirm、校验、错误处理语义不变只替换展示层。
4. `backend/services/agent/tools/tool_context_result/**` + `context_tools.go`
- `context_tools_add` / `context_tools_remove` 输出 `result_view.view_type = "tool.context_result"`
- 卡片展示 domain、packs、mode、all 和失败原因。
5. `backend/services/agent/tools/schedule_queue_handlers.go`
- `queue_pop_head` 复用 `schedule.read_result`
- `queue_skip_head` 复用 `schedule.operation_result`
第四批验收结果:
1. `go test ./services/agent/tools/...` 通过。
2. `go test ./...` 通过。
3. 根目录 `.gocache` 已清理。
4. 没有遗留临时 `*_test.go`
5. `ObservationText` 均保持原始工具 observation不被展示层改写。
analysis 当前切流点:
1. `registry.go`
- `analyze_health` 已切到 `NewAnalyzeHealthToolHandler()`
- `analyze_rhythm` 已切到 `NewAnalyzeRhythmToolHandler()`
2. `backend/services/agent/tools/schedule_analysis_handlers.go`
- 父包唯一 analysis adapter 文件。
- 负责执行 `schedule.AnalyzeHealth` / `schedule.AnalyzeRhythm`,保留原始 `ObservationText`,生成中文 `ArgumentView`,再调用 `schedule_analysis.BuildAnalyzeHealthView()` / `BuildAnalyzeRhythmView()`
3. `backend/services/agent/tools/schedule_analysis/**`
- 子包负责纯 analysis 展示数据构造。
- 不 import 父包 `newagenttools`,不返回 `ToolExecutionResult`
analysis 验收结果:
1. `result_view.view_type = "schedule.analysis_result"``version = 1`
2. `expanded.raw_text` 保留原始 observation JSON。
3. `expanded.machine_payload` 保留解析后的完整机器字段,供调试和后续交互使用。
4. `analyze_health` 的 observation JSON 契约未改动,仍可被 `state_snapshot` / prompt 摘要消费。
5. `go test ./services/agent/tools/...` 通过。
6. `go test ./...` 通过。
7. 根目录 `.gocache` 已清理。
8. 没有遗留临时 `*_test.go`
当前切流点:
1. `registry.go`
- 继续注册 `NewQueryAvailableSlotsToolHandler()``NewQueryRangeToolHandler()``NewQueryTargetTasksToolHandler()``NewGetTaskInfoToolHandler()``NewGetOverviewToolHandler()``NewQueueStatusToolHandler()`
2. `backend/services/agent/tools/schedule_read_handlers.go`
- 父包唯一 read adapter 文件。
- 负责执行底层 `schedule.*` 工具,保留原始 `ObservationText`,生成中文 `ArgumentView`,再调用 `schedule_read.BuildXxxView()`
3. `backend/services/agent/tools/schedule_read/**`
- 子包负责纯 read 展示数据构造。
- 不 import 父包 `newagenttools`,不返回 `ToolExecutionResult`
已删除旧实现:
1. `schedule_read_result_types.go`
2. `schedule_read_result_common.go`
3. `schedule_read_slots_handlers.go`
4. `schedule_read_tasks_handlers.go`
5. `schedule_read_overview_queue_handlers.go`
仍保留的父包能力:
1. `schedule_argument_format_helpers.go`
- 只服务 `execution_result.go` 的参数中文展示。
- 不再参与 `schedule.read_result` 卡片构造。
验收结果:
1. `go test ./services/agent/tools/...` 通过。
2. `go test ./...` 通过。
3. 根目录 `.gocache` 已清理。
4. 没有遗留临时 `*_test.go`
## 当前状态
本轮已经完成第二批 read 事实域工具的后端结构化结果改造。外层协议仍然是 `ToolExecutionResult`LLM 观察文本继续走 `ObservationText`,前端展示信息走 `ResultView` / `ArgumentView`
已经直接切到 `result_view.view_type = "schedule.read_result"` 的工具:
1. `query_available_slots`
2. `query_target_tasks`
3. `query_range`
4. `get_overview`
5. `get_task_info`
6. `queue_status`
尚未进入本轮的工具继续走 `LegacyResult`,不要为了“统一外观”在本轮顺手迁移其它工具。
当前新增/修改文件:
1. `backend/services/agent/tools/schedule_read_result_types.go`
- read 结果常量、payload 结构、轻量内部结构。
2. `backend/services/agent/tools/schedule_read_result_common.go`
- 统一 `schedule.read_result` builder、失败卡片、中文格式化、跨工具统计 helper。
- 当前文件偏重,约 600 行,是下一轮整理的重点。
3. `backend/services/agent/tools/schedule_read_slots_handlers.go`
- `query_available_slots``query_range`
4. `backend/services/agent/tools/schedule_read_tasks_handlers.go`
- `query_target_tasks``get_task_info`
5. `backend/services/agent/tools/schedule_read_overview_queue_handlers.go`
- `get_overview``queue_status`
6. `backend/services/agent/tools/execution_result.go`
- 补齐 read/analyze 相关参数的中文 `argument_view` 标签和展示值。
7. `backend/services/agent/tools/registry.go`
- 只把 6 个 read 工具的注册入口替换成新的 `NewXxxToolHandler()`
## 第二批协议
第二批新增的前端 view type 只有一个:
```json
{
"view_type": "schedule.read_result",
"version": 1,
"collapsed": {},
"expanded": {}
}
```
`collapsed` 面向卡片折叠态:
```json
{
"title": "找到 6 个目标任务",
"subtitle": "建议安排任务,已入队 6 个",
"status": "done",
"status_label": "已完成",
"metrics": [
{ "label": "任务数", "value": "6 个" }
]
}
```
`expanded` 面向卡片展开态:
```json
{
"items": [
{
"title": "[12]英语作文",
"subtitle": "待安排2 节",
"tags": ["待安排", "学习"],
"detail_lines": ["位置:未安排"],
"meta": {
"task_id": 12
}
}
],
"sections": [
{
"type": "items",
"title": "候选任务",
"items": []
}
],
"raw_text": "原始 observation 文本",
"machine_payload": {}
}
```
C 端默认展示字段:
1. `collapsed.title`
2. `collapsed.subtitle`
3. `collapsed.status_label`
4. `collapsed.metrics[].label/value`
5. `expanded.items[].title/subtitle/tags/detail_lines`
6. `expanded.sections[].title/summary/items`
默认不要展示的机器字段:
1. `expanded.machine_payload`
2. `expanded.raw_text`
3. `items[].meta`
4. `task_id``day``slot_start``week_filter` 等机器参数名
这些字段只给调试、回传、后续交互使用。
## 整理任务
当前第二批代码虽然已经拆成多个文件,但仍然平铺在 `backend/services/agent/tools` 根包里。后续整理目标是把 read 结果构造逻辑收到子目录,避免根目录继续膨胀。
不要直接把现有 `.go` 文件机械移动到子目录。Go 里子目录就是新 package当前文件依赖父包里的 `ToolHandler``ToolExecutionResult``ToolDisplayView``LegacyResultWithState` 等类型,直接移动会造成 import cycle。
推荐整理结构:
```text
backend/services/agent/tools/
registry.go
schedule_read_handlers.go
schedule_read/
types.go
common.go
slots.go
tasks.go
overview_queue.go
```
职责边界:
1. `backend/services/agent/tools/schedule_read/**`
- 子包只做纯 read 展示数据构造。
- 不 import 父包 `newagenttools`
- 不返回 `ToolExecutionResult`
- 返回类似 `ReadResultView` 的纯数据结构:`ViewType``Collapsed``Expanded``MachinePayload`
2. `backend/services/agent/tools/schedule_read_handlers.go`
- 留在父包 `newagenttools`
- 只做薄 adapter调用 `schedule_read` 子包构造展示数据,再包成 `ToolExecutionResult`
- 继续保证 `ObservationText` 原样给 LLM。
3. `registry.go`
- 只保留注册入口,不放业务逻辑。
如果整理时发现 `schedule_read_result_common.go` 里的 helper 同时被第三批 analysis 使用,再考虑抽更中性的公共包:
```text
backend/services/agent/tools/toolview/
```
但不要提前大抽象;只有 read 和 analysis 都真实复用同一批结构后再抽。
## 第三批计划
第三批建议处理 schedule 诊断分析域:
1. `analyze_health`
2. `analyze_rhythm`
建议新增:
```text
backend/services/agent/tools/schedule_analysis/
```
建议新增 view type
```text
schedule.analysis_result
```
外层协议继续不变:
```json
{
"result_view": {
"view_type": "schedule.analysis_result",
"version": 1,
"collapsed": {},
"expanded": {}
}
}
```
`schedule.analysis_result` 仍复用通用卡片结构,但语义上区别于 read
1. `collapsed.title`
- 例:`综合体检:建议继续微调``学习节律分析`
2. `collapsed.subtitle`
- 例:主问题、裁决摘要、风险摘要。
3. `collapsed.metrics`
- 例:高认知相邻天数、可局部移动任务数、推荐动作。
4. `expanded.sections`
- `裁决结论`
- `关键指标`
- `问题清单`
- `候选操作`
- `建议后续动作`
5. `expanded.items`
- 候选动作或风险日列表。
6. `expanded.machine_payload`
- 原始 JSON、候选动作参数、required_reads 等机器字段,只给调试/交互。
第三批不要和 read 整理同时改同一个公共 helper 文件。推荐顺序:
1. 先完成 read 整理,确定子包边界。
2. 再做 `schedule_analysis` 子包。
3. 最后只在父包 adapter 和 `registry.go` 接入 `analyze_health/analyze_rhythm`
## 后续批次
当前文档计划内的四批结构化结果已经完成。默认注册表里主链工具已经不再通过 `wrapLegacyToolHandler` 接入。
当前稳定 view type
1. `schedule.operation_result`
2. `schedule.read_result`
3. `schedule.analysis_result`
4. `web.search_result`
5. `web.fetch_result`
6. `taskclass.write_result`
7. `tool.context_result`
8. `legacy_text`
`legacy_text` 仍作为未知工具、兜底结果或未来新增工具的保底协议保留,不建议删除。
若后续继续整理,建议只做两类小收尾:
1. 前端补齐 `web.search_result``web.fetch_result``taskclass.write_result``tool.context_result` 的专项 mock 与视觉验收。
2. 评估是否把各子包重复的 `kv/items/callout` helper 下沉到中性公共包,例如 `backend/services/agent/tools/toolview/`;只有在确认 read、analysis、web、taskclass、context 都稳定后再抽,避免提前扩大回归面。
## 前端补丁提示
后端当前已经输出多种结构化 `result_view`。前端最低要求:
1. 头部继续优先读:
- `result_view.collapsed.title`
- `result_view.collapsed.subtitle`
- `result_view.collapsed.status_label`
- `result_view.collapsed.metrics`
2. 展开态新增通用 sections/items renderer
- 支持 `expanded.items`
- 支持 `expanded.sections`
- section 类型至少兼容 `items``kv``callout`
- `callout` 需要兼容 `subtitle``summary`
3. 默认不展示:
- `expanded.machine_payload`
- `items[].meta`
- 原始英文 key/value
4. `raw_text` 只放 debug 折叠区。
前端需要至少识别以下新协议:
1. `schedule.read_result`
2. `schedule.analysis_result`
3. `web.search_result`
4. `web.fetch_result`
5. `taskclass.write_result`
6. `tool.context_result`
前端如果暂时不识别某个专属 view type至少要显示折叠态但展开态退回 raw text 不符合 C 端目标。
## 验收清单
后续代理继续处理前必须先确认:
1. 不回滚、覆盖、删除用户或其它代理的工作区改动。
2. 不碰前端,除非用户明确要求。
3. `ObservationText` 不能被展示层改写。
4. 工具结果必须继续通过 `ToolExecutionResult -> SSE extra -> timeline payload` 传递。
5. 每次跑 `go test` 后必须删除根目录 `.gocache`
6. 如果新增临时 `*_test.go`,跑完测试后必须删除。
7. 结构迁移最终答复要说明:迁了什么、旧实现保留什么、切流点在哪里、下一轮建议迁什么。