后端: 1. 工具结果结构化切流继续推进:schedule 读工具改为“父包 adapter + 子包 view builder”,`queue_pop_head` / `queue_skip_head` 脱离 legacy wrapper,`analyze_health` / `analyze_rhythm` 补齐 `schedule.analysis_result` 诊断卡片。 2. 非 schedule 工具补齐专属结果协议:`web_search` / `web_fetch`、`upsert_task_class`、`context_tools_add` / `context_tools_remove` 全部接入结构化 `ResultView`,注册表继续去 legacy wrapper,同时保持原始 `ObservationText` 供模型链路复用。 3. 工具展示细节继续收口:参数本地化补齐 `domain` / `packs` / `mode` / `all`,deliver 阶段补发段落分隔,避免 execute 与总结正文黏连。 前端: 4. `ToolCardRenderer` 升级为多协议通用渲染器,补齐 read / analysis / web / taskclass / context 卡片渲染、参数折叠区、未知协议兜底与操作明细展示。 5. `AssistantPanel` 修正 `tool_result` 结果回填与卡片布局宽度问题,并新增结构化卡片 fixture / mock 调试入口,便于整体验收。 仓库: 6. 更新工具结果结构化交接文档,补记第四批切流范围、当前切流点与后续收尾建议。
367 lines
13 KiB
Markdown
367 lines
13 KiB
Markdown
# 工具结果结构化交接文档
|
||
|
||
## 最新负责人验收结论
|
||
|
||
本轮已经按“直接切流”完成 read 结果构造迁移:6 个 `schedule.read_result` 工具仍由父包注册入口暴露,但父包只保留薄 adapter,真实展示数据构造已经切到 `backend/newAgent/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/newAgent/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/newAgent/tools/taskclass_result/**` + `taskclass_result_handlers.go`
|
||
- `upsert_task_class` 输出 `result_view.view_type = "taskclass.write_result"`。
|
||
- 写库、confirm、校验、错误处理语义不变,只替换展示层。
|
||
4. `backend/newAgent/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/newAgent/tools/schedule_queue_handlers.go`
|
||
- `queue_pop_head` 复用 `schedule.read_result`。
|
||
- `queue_skip_head` 复用 `schedule.operation_result`。
|
||
|
||
第四批验收结果:
|
||
|
||
1. `go test ./newAgent/tools/...` 通过。
|
||
2. `go test ./...` 通过。
|
||
3. 根目录 `.gocache` 已清理。
|
||
4. 没有遗留临时 `*_test.go`。
|
||
5. `ObservationText` 均保持原始工具 observation,不被展示层改写。
|
||
|
||
analysis 当前切流点:
|
||
|
||
1. `registry.go`
|
||
- `analyze_health` 已切到 `NewAnalyzeHealthToolHandler()`。
|
||
- `analyze_rhythm` 已切到 `NewAnalyzeRhythmToolHandler()`。
|
||
2. `backend/newAgent/tools/schedule_analysis_handlers.go`
|
||
- 父包唯一 analysis adapter 文件。
|
||
- 负责执行 `schedule.AnalyzeHealth` / `schedule.AnalyzeRhythm`,保留原始 `ObservationText`,生成中文 `ArgumentView`,再调用 `schedule_analysis.BuildAnalyzeHealthView()` / `BuildAnalyzeRhythmView()`。
|
||
3. `backend/newAgent/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 ./newAgent/tools/...` 通过。
|
||
6. `go test ./...` 通过。
|
||
7. 根目录 `.gocache` 已清理。
|
||
8. 没有遗留临时 `*_test.go`。
|
||
|
||
当前切流点:
|
||
|
||
1. `registry.go`
|
||
- 继续注册 `NewQueryAvailableSlotsToolHandler()`、`NewQueryRangeToolHandler()`、`NewQueryTargetTasksToolHandler()`、`NewGetTaskInfoToolHandler()`、`NewGetOverviewToolHandler()`、`NewQueueStatusToolHandler()`。
|
||
2. `backend/newAgent/tools/schedule_read_handlers.go`
|
||
- 父包唯一 read adapter 文件。
|
||
- 负责执行底层 `schedule.*` 工具,保留原始 `ObservationText`,生成中文 `ArgumentView`,再调用 `schedule_read.BuildXxxView()`。
|
||
3. `backend/newAgent/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 ./newAgent/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/newAgent/tools/schedule_read_result_types.go`
|
||
- read 结果常量、payload 结构、轻量内部结构。
|
||
2. `backend/newAgent/tools/schedule_read_result_common.go`
|
||
- 统一 `schedule.read_result` builder、失败卡片、中文格式化、跨工具统计 helper。
|
||
- 当前文件偏重,约 600 行,是下一轮整理的重点。
|
||
3. `backend/newAgent/tools/schedule_read_slots_handlers.go`
|
||
- `query_available_slots`、`query_range`。
|
||
4. `backend/newAgent/tools/schedule_read_tasks_handlers.go`
|
||
- `query_target_tasks`、`get_task_info`。
|
||
5. `backend/newAgent/tools/schedule_read_overview_queue_handlers.go`
|
||
- `get_overview`、`queue_status`。
|
||
6. `backend/newAgent/tools/execution_result.go`
|
||
- 补齐 read/analyze 相关参数的中文 `argument_view` 标签和展示值。
|
||
7. `backend/newAgent/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/newAgent/tools` 根包里。后续整理目标是把 read 结果构造逻辑收到子目录,避免根目录继续膨胀。
|
||
|
||
不要直接把现有 `.go` 文件机械移动到子目录。Go 里子目录就是新 package;当前文件依赖父包里的 `ToolHandler`、`ToolExecutionResult`、`ToolDisplayView`、`LegacyResultWithState` 等类型,直接移动会造成 import cycle。
|
||
|
||
推荐整理结构:
|
||
|
||
```text
|
||
backend/newAgent/tools/
|
||
registry.go
|
||
schedule_read_handlers.go
|
||
schedule_read/
|
||
types.go
|
||
common.go
|
||
slots.go
|
||
tasks.go
|
||
overview_queue.go
|
||
```
|
||
|
||
职责边界:
|
||
|
||
1. `backend/newAgent/tools/schedule_read/**`
|
||
- 子包只做纯 read 展示数据构造。
|
||
- 不 import 父包 `newagenttools`。
|
||
- 不返回 `ToolExecutionResult`。
|
||
- 返回类似 `ReadResultView` 的纯数据结构:`ViewType`、`Collapsed`、`Expanded`、`MachinePayload`。
|
||
2. `backend/newAgent/tools/schedule_read_handlers.go`
|
||
- 留在父包 `newagenttools`。
|
||
- 只做薄 adapter:调用 `schedule_read` 子包构造展示数据,再包成 `ToolExecutionResult`。
|
||
- 继续保证 `ObservationText` 原样给 LLM。
|
||
3. `registry.go`
|
||
- 只保留注册入口,不放业务逻辑。
|
||
|
||
如果整理时发现 `schedule_read_result_common.go` 里的 helper 同时被第三批 analysis 使用,再考虑抽更中性的公共包:
|
||
|
||
```text
|
||
backend/newAgent/tools/toolview/
|
||
```
|
||
|
||
但不要提前大抽象;只有 read 和 analysis 都真实复用同一批结构后再抽。
|
||
|
||
## 第三批计划
|
||
|
||
第三批建议处理 schedule 诊断分析域:
|
||
|
||
1. `analyze_health`
|
||
2. `analyze_rhythm`
|
||
|
||
建议新增:
|
||
|
||
```text
|
||
backend/newAgent/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/newAgent/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. 结构迁移最终答复要说明:迁了什么、旧实现保留什么、切流点在哪里、下一轮建议迁什么。
|
||
|