feat(app-instance): 集成Beaver后端并更新配置管理
集成新的Beaver后端服务到应用实例中,替换原有的nanobot实现。 主要变更包括: - 在Dockerfile和环境配置中添加Beaver相关路径和配置变量 - 更新工作目录结构从.nanobot到.beaver - 实现Beaver引擎加载器,支持配置文件加载和工具组装 - 添加内置工具如ListDirectoryTool、ReadFileTool、SearchFilesTool - 更新消息处理流程,支持通道适配器和网关模式 - 重构技能系统,支持显式工具提示和嵌入式检索 - 改进错误处理和生命周期管理 此变更使应用实例能够使用统一的Beaver后端进行AI代理运行时管理。
This commit is contained in:
@ -704,6 +704,7 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
|
||||
1. `beaver/tools/base.py`
|
||||
2. `beaver/tools/registry/tool_registry.py`
|
||||
3. `beaver/tools/assembler/task_assembler.py`
|
||||
|
||||
参考旧文件:
|
||||
|
||||
@ -732,6 +733,48 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
1. registry 可以注册工具
|
||||
2. provider 返回 tool call 时可以找到并执行工具
|
||||
3. memory / session_search 已纳入统一工具集合
|
||||
4. 本地工具描述采用 MCP-style `name/description/inputSchema`
|
||||
5. `ToolAssembler` 能按 task description 用 embedding 召回本轮 top10 工具
|
||||
6. activated skill frontmatter 里的 `tools` 能参与本轮工具选择
|
||||
7. 只读 filesystem tools 已接入:
|
||||
- `list_directory`
|
||||
- `read_file`
|
||||
- `search_files`
|
||||
8. filesystem tools 强制限制在 `ToolContext.workspace`
|
||||
9. 相对路径逃逸、绝对路径逃逸、符号链接逃逸都会拒绝
|
||||
10. 二进制文件读取会拒绝,搜索会跳过二进制 / 大文件
|
||||
|
||||
当前工具选择规则已经定为:
|
||||
|
||||
1. always tools 每轮默认可用
|
||||
- `memory`
|
||||
- `session_search`
|
||||
- `skill_view`
|
||||
- `list_directory`
|
||||
- `read_file`
|
||||
- `search_files`
|
||||
2. activated skill 可以显式声明工具:
|
||||
|
||||
```yaml
|
||||
---
|
||||
tools:
|
||||
- terminal
|
||||
- read_file
|
||||
---
|
||||
```
|
||||
|
||||
3. `ToolAssembler` 合并:
|
||||
- always tools
|
||||
- skill hints
|
||||
- task embedding top10 tools
|
||||
4. 第一版只信任 frontmatter / metadata 的显式 `tools`,不从正文里猜工具名
|
||||
5. 如果 skill 声明了尚未注册的工具,先忽略,不阻断 run
|
||||
|
||||
filesystem 这一版只做只读,不做写文件 / shell:
|
||||
|
||||
1. 先让 agent 能看见 workspace 结构、读源码、搜文本
|
||||
2. 写文件和 shell 属于高风险工具,必须等 permission gates 明确后再接
|
||||
3. 当前 workspace 边界只保证路径隔离,不等价于完整权限系统
|
||||
|
||||
### 4.5 最后实现第一版 `AgentLoop`
|
||||
|
||||
@ -855,6 +898,23 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
- 先用 embedding 做语义召回
|
||||
- 输出应该激活的 skills
|
||||
6. embedding 配置通过 provider bundle 的独立 `embedding runtime` 传入;若没有显式 embedding 配置,则只有主链本身是 OpenAI-compatible 时才允许继承 `api_base/api_key`
|
||||
7. skill frontmatter 可声明本 skill 推荐工具;这些 tool hints 会交给 `ToolAssembler`
|
||||
|
||||
当前和长期目标的关系:
|
||||
|
||||
1. 已完成基础入口:
|
||||
- curated memory CRUD
|
||||
- `session_search`
|
||||
- `skill_view`
|
||||
- `SkillAssembler`
|
||||
- `ToolAssembler`
|
||||
2. 还没完成长期智能体治理:
|
||||
- 智能体定期整理 / 提示记忆
|
||||
- 复杂任务完成后自主创建技能
|
||||
- 技能在使用过程中自我提升
|
||||
- FTS5 + LLM 摘要的跨会话回忆增强
|
||||
- Honcho 风格辩证用户建模
|
||||
- agentskills.io 开放标准兼容
|
||||
|
||||
---
|
||||
|
||||
@ -884,6 +944,10 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
3. `ContextBuilder`
|
||||
- 不再直接依赖进程内状态
|
||||
- 只从 Session / curated memory / skills 中提取当前需要的上下文
|
||||
4. `ToolAssembler`
|
||||
- 不把所有工具无脑暴露给模型
|
||||
- 按 task description / activated skill hints 选择本轮工具
|
||||
- 输出 provider 可消费的 tool schema
|
||||
|
||||
这一步不是要一口气做完 fork / rewind / checkpoint 全套系统,而是先把“Session-first, Stateless Harness”这条主线立住。
|
||||
|
||||
@ -926,12 +990,13 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
|
||||
1. `session_started/ensured`
|
||||
2. `run_started`
|
||||
3. `system_prompt_snapshotted`
|
||||
4. `user_message_added`
|
||||
5. `assistant_message_added`
|
||||
6. `tool_call_requested`
|
||||
7. `tool_result_recorded`
|
||||
8. `run_failed` 或 `run_completed`
|
||||
3. `skill_activation_snapshotted`
|
||||
4. `tool_selection_snapshotted`
|
||||
5. `system_prompt_snapshotted`
|
||||
6. `user_message_added`
|
||||
7. `assistant_message_added`
|
||||
8. `tool_result_recorded`
|
||||
9. `run_failed` 或 `run_completed`
|
||||
|
||||
并且每次 run 都要带独立 `run_id`,这样同一个 session 内的多次运行才能被切开。
|
||||
|
||||
@ -1016,6 +1081,31 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
7. `stop()` / `shutdown()` 应支持 graceful timeout,必要时允许 force cancel
|
||||
8. `close()`:只有在实例已停止后才能释放 runtime 资源
|
||||
|
||||
这一阶段也明确了模型配置的归属:
|
||||
|
||||
1. 大模型 provider / api_key / api_base 属于 backend runtime config
|
||||
2. Web / Gateway / Channel 不单独保存模型密钥
|
||||
3. 前端请求不传 API Key,只传 `message/session_id/user_id` 等业务输入
|
||||
4. Docker 单实例部署时,每个用户 sandbox 读取自己的实例配置
|
||||
5. 默认使用新 Beaver 实例目录:
|
||||
- `/root/.beaver/config.json`
|
||||
- `/root/.beaver/workspace`
|
||||
6. 新 Beaver 命名优先使用:
|
||||
- `BEAVER_CONFIG_PATH`
|
||||
- `BEAVER_HOME/config.json`
|
||||
7. 兼容迁移期旧命名:
|
||||
- `NANOBOT_CONFIG_PATH`
|
||||
- `NANOBOT_HOME/config.json`
|
||||
|
||||
app-instance 镜像也已经切到新 Beaver 后端:
|
||||
|
||||
1. Dockerfile 只安装 `backend/beaver`
|
||||
2. 不再复制旧 `backend/nanobot`、`backend/bridge`、vendored `swarms`
|
||||
3. entrypoint 通过 `python -m uvicorn beaver.interfaces.web.app:create_app --factory` 启动 Web
|
||||
4. 容器内默认配置与 workspace 使用:
|
||||
- `/root/.beaver/config.json`
|
||||
- `/root/.beaver/workspace`
|
||||
|
||||
### 6.2.1 Web / Gateway 现在如何接这套 lifecycle
|
||||
|
||||
这一层现在已经开始落成真正的宿主层,而不是只停留在文档占位:
|
||||
@ -1045,13 +1135,25 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
- `run_gateway()` 启动时:
|
||||
- 如果 gateway 自己创建 service,则 `await service.start()`
|
||||
- 持有最小 `MessageBus`
|
||||
- 常驻消费 `bus.inbound`
|
||||
- 调 `await service.submit_direct(...)`
|
||||
- 将结果写回 `bus.outbound`
|
||||
- 可选接收 `ChannelManager` / channel adapters
|
||||
- `ChannelManager` 和 `channels` 参数二选一:
|
||||
- 传 `ChannelManager`:外部提前配置好 channel
|
||||
- 传 `channels`:gateway 内部创建 `ChannelManager` 并注册这些 channel
|
||||
- inbound 流向:
|
||||
- channel adapter 发布 `InboundMessage`
|
||||
- `MessageBus.inbound`
|
||||
- gateway bridge 常驻消费
|
||||
- 调 `await service.handle_inbound_message(...)`
|
||||
- outbound 流向:
|
||||
- `AgentService` 内部完成 `InboundMessage -> OutboundMessage` 映射
|
||||
- gateway bridge 将结果写回 `MessageBus.outbound`
|
||||
- 如果启用了 `ChannelManager`,则分发给对应 channel adapter
|
||||
- 未启用 `ChannelManager` 时,保留直接消费 `bus.outbound` 的最小测试能力
|
||||
- 同时等待 `stop_event`
|
||||
- 停机时:
|
||||
- 先尝试 `await service.shutdown(timeout_seconds=5.0, force=True)`
|
||||
- 再等待 bridge 协程收尾;必要时取消 bridge
|
||||
- 再等待 outbound dispatch 协程收尾;必要时取消 dispatch
|
||||
- 如果 gateway 自己接管 lifecycle 且 `start()` 失败:
|
||||
- 立即 `close()` 做 startup cleanup
|
||||
- 未处理完的 inbound:
|
||||
@ -1068,6 +1170,16 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
- `outbound`
|
||||
- 还没有 broker / topic routing / retry / persistence
|
||||
|
||||
4. `beaver/interfaces/channels/*`
|
||||
- 已经补了最小 channel adapter 层:
|
||||
- `ChannelAdapter`
|
||||
- `ChannelManager`
|
||||
- `MemoryChannelAdapter`
|
||||
- 当前 channel 职责很窄:
|
||||
- 把外部输入发布成 `InboundMessage`
|
||||
- 接收并投递 `OutboundMessage`
|
||||
- `MemoryChannelAdapter` 只用于本地测试和内嵌接入,不是正式消息 broker
|
||||
|
||||
所以现在已经明确:
|
||||
|
||||
1. Web / Gateway 属于宿主层
|
||||
@ -1082,16 +1194,18 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
- 外部注入的 `AgentService`:默认不自动 start/shutdown,除非显式要求接管
|
||||
5. gateway 已经从“只会常驻等待”推进到“最小消息桥接层”
|
||||
- external inbound message
|
||||
- channel adapter
|
||||
- `MessageBus.inbound`
|
||||
- `service.submit_direct(...)`
|
||||
- `service.handle_inbound_message(...)`
|
||||
- `MessageBus.outbound`
|
||||
- channel adapter outbound delivery
|
||||
|
||||
但这一阶段还没做:
|
||||
|
||||
1. channels adapter
|
||||
2. realtime streaming
|
||||
3. platform-level supervisor
|
||||
4. 更复杂的 bus 语义(retry / routing / persistence)
|
||||
1. realtime streaming
|
||||
2. platform-level supervisor
|
||||
3. 更复杂的 bus 语义(retry / routing / persistence)
|
||||
4. 外部真实 channel adapter
|
||||
|
||||
### 6.3 第三步:回填 bus 模式
|
||||
|
||||
@ -1107,9 +1221,16 @@ provider 层不要再做成“一个厂商一个世界”,而是要拆成 4
|
||||
需要补的函数:
|
||||
|
||||
1. 从 inbound 读取消息
|
||||
2. 调用 `_process_message`
|
||||
2. 通过 `AgentService.handle_inbound_message(...)` 映射到 runtime 调用
|
||||
3. 发布 outbound
|
||||
|
||||
当前这一步的最小收口方式已经确定为:
|
||||
|
||||
1. `MessageBus` 只负责协议和队列
|
||||
2. `gateway` 只负责宿主、常驻消费和 channel 分发
|
||||
3. `InboundMessage -> AgentRunResult -> OutboundMessage` 的映射收口在 `AgentService`
|
||||
4. `AgentLoop` 继续只关心 agent 执行内核,不直接感知 bus 协议
|
||||
|
||||
注意:
|
||||
|
||||
只有在 `process_direct()` 稳定,并且 6.1 / 6.2 已经把 Session-first + lifecycle 骨架立住后,才做 `run()` 的长循环版本。
|
||||
|
||||
Reference in New Issue
Block a user