feat: add workspace-isolated toolhost runtime and capability-gap skill loop

This commit is contained in:
2026-02-28 17:48:33 +08:00
parent ce9346e350
commit 7d6cf6b435
28 changed files with 2223 additions and 143 deletions

196
doc/技术说明文档.md Normal file
View File

@@ -0,0 +1,196 @@
# LaodingBot 技术说明文档2026-02-28 最新实现)
> 本文档基于当前代码状态,描述真实可运行架构与能力边界。
---
## 1. 项目定位
LaodingBot 当前已从“单进程工具调用 MVP”演进为
- **父进程 Agent 编排**(技能路由 + ReAct + 记忆)
- **子进程 ToolHost 执行**JSON-RPC
- **workspace 隔离运行空间**(配置与工具权限收敛)
- **能力缺口闭环**(落库、聚类、自动生成技能并热加载)
核心目标:让 Agent 在安全边界内持续补全能力,而不是仅做静态问答。
---
## 2. 目录与模块
- `cmd/bot/main.go`应用入口、workspace 引导、toolhost 启动、通道分发
- `internal/config/config.go`配置加载、workspace 路径解析、安全策略归一化
- `internal/runtimews/bootstrap.go`:运行时 workspace 准备与种子目录复制
- `internal/agent/orchestrator.go`主编排器技能匹配、ReAct、能力缺口闭环
- `internal/toolhost/*`:工具子进程协议、服务端、客户端、远程工具适配
- `internal/tools/filetool/filetool.go`:文件工具(`read/list/write`
- `internal/tools/shelltool/shelltool.go`:命令工具(白名单 + 超时 + 输出限制)
- `internal/memory/store_sqlite.go`:消息与能力缺口存储、聚类查询
- `internal/knowledge/loader.go`skill/soul 加载
- `internal/knowledge/drafts.go`:能力缺口驱动的 skill 自动生成
---
## 3. 启动链路(当前)
`main()` 执行顺序:
1. 建立可取消上下文SIGINT/SIGTERM
2. 调用 `runtimews.PrepareFromEnv()`
- 解析 `AGENT_WORKSPACE_DIR`(默认 `./workspace/agent_runtime`
-`configs/data/skills/bot_context` 种子复制到 runtime workspace缺失才复制
- 设定 `CONFIG_ENV_FILE=<workspace>/configs/env`
3. 调用 `config.Load()`,优先读取 workspace env。
4.`--toolhost` 模式,进入子进程服务。
5. 正常父进程初始化日志、SQLite、ToolHost Client、知识、Orchestrator。
6. 根据 `MESSAGE_CHANNEL` 启动 Telegram 或 Feishu transport。
---
## 4. 配置加载与优先级(关键变更)
`config.Load()` 的 env 读取优先级:
1. `CONFIG_ENV_FILE`(强覆盖)
2. `<workspace>/configs/env``<workspace>/.env`(强覆盖)
3. 根目录 `configs/env``.env`(仅兜底,不覆盖已有值)
这保证 VS Code Debug 场景下,**workspace 配置优先于根目录配置**。
### 关键配置
- `REACT_MAX_STEPS`:必须来自 env无代码默认值
- `AGENT_WORKSPACE_DIR`agent 运行空间根目录
- `ALLOWED_DIRS` / `ALLOWED_COMMANDS` / `WORK_DIR`:工具安全边界
- `AUTO_SKILL_DIR`:自动生成 skill 的目标目录(默认 workspace/skills
- `GAP_DRAFT_TRIGGER_COUNT` / `GAP_CLUSTER_LOOKBACK_HOURS`:缺口聚类触发参数
---
## 5. workspace 隔离策略
当前实现中Agent 与工具默认都在 workspace 内高权限运行:
- 相对路径统一按 `AGENT_WORKSPACE_DIR` 解析
- `ALLOWED_DIRS` 强制补齐:
- workspace 根
- `workspace/skills`
- `workspace/data`
- `workspace/workspace`
- `ALLOWED_COMMANDS` 自动补齐:`go``curl``curl.exe`
`filetool` 对相对路径优先按 workspace 根解析,避免写到代码仓库根目录。
---
## 6. ToolHost 子进程架构
当前工具调用已迁移到 JSON-RPC 子进程:
- 协议方法:`ping``tool.list``tool.call`
- 父进程 `Client` 能力:
- 调用超时
- 心跳检测
- 失败重启与重试
- 并发限制(信号量)
- 子进程 stdout 仅承载协议数据(避免日志污染 RPC
效果:工具崩溃不会直接拖垮 Agent 主编排逻辑。
---
## 7. ReAct 与技能路由
`Orchestrator` 流程:
1. 保存用户消息到 SQLite
2. 读取最近对话并压缩
3. LLM 进行技能路由(最多命中 2 个)
4. 若无技能命中:尝试回退到 `创建skill` 技能
5. 进入 ReAct 多轮决策(`action/final`
6. 工具调用观察写入 scratchpad
7. 保存 assistant 回复
工具错误会结构化为:
- `ERROR_CODE=...; TOOL=...; REASON=...`
---
## 8. 能力缺口闭环(已落地)
当出现“不会做”信号(如无 skill、解析失败、工具失败
1. 写入 `capability_gaps`
2. 进行意图归一化聚类(按 `intent_key + reason`
3. 高频达到阈值后自动生成 skill 文件
4. 自动调用 `ReloadSkills()` 热加载
可通过消息命令查看与控制:
- `/capability_gaps`:输出当前高频缺口清单
- `/reload_skills`:手动热加载 skills
---
## 9. 自动生成 skill 的当前行为
自动生成由 `internal/knowledge/drafts.go` 执行:
- 目标目录:`AUTO_SKILL_DIR`(默认 workspace/skills
- 命名:`auto_<intent_key>/skill.md`
- 仅在文件不存在时创建,避免重复覆盖
- 模板内包含:触发背景、执行流程、工具建议、测试建议
并额外提供基础引导技能:
- `skills/skill_builder/skill.md`
---
## 10. file/shell 工具现状
### file tool
支持:
- `read <path>`
- `list <path>`
- `write <path>\n<content>`
特性:
- 白名单路径检查
- 目录误读防护:`read` 目录返回 `PATH_IS_DIRECTORY`
- 输出长度限制
### shell tool
特性:
- 命令白名单(首 token
- 超时中断
- 固定工作目录
- 输出截断
- Windows 不可执行命令友好报错
---
## 11. 数据存储
SQLite 表:
1. `messages`:对话消息
2. `capability_gaps`:能力缺口事件
提供查询:
- 最近消息
- 最近缺口事件
- 高频缺口聚类(含计数与最近出现时间)
---
## 12. 与最初文档相比的变化
当前代码已经完成并替代旧文档中的以下“待实现项”:
- ToolHost 子进程隔离(已实现)
- 能力缺口闭环(已实现)
- 自动 skill 生成与热加载(已实现)
- workspace 配置优先与运行空间隔离(已实现)
仍属于持续演进项:
- 新工具代码自动注册与生效的全自动化流水线
- 更细粒度权限域(按 skill/tool 分级)
- 更强的自动化验收e2e + 故障注入)
---
## 13. 下一步建议
1.`toolhost client/server` 增加专项故障单测(心跳失败、子进程崩溃、并发压力)。
2. 增加“自动生成 tool 后自动接线注册”的流水线模块。
3. 为 skill 自动生成增加结构门禁frontmatter/章节完整性校验)。
4. 引入操作审计视图,串联 trace_id 与 capability_gap。