Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
7c50aab
feat: add mcp and skills
wangcham May 2, 2026
58ec377
feat: add filter
wangcham May 2, 2026
3b3deec
feat: modify frontend
wangcham May 4, 2026
ba7a457
feat(box): add sandbox_exec tool loop for local-agent calculations
huanghuoguoguo Mar 19, 2026
70c56af
feat(box): add host workspace mounting and sandbox_exec guidance
huanghuoguoguo Mar 19, 2026
86b2d51
feat(box): add BoxProfile with resource limits and improved output tr…
huanghuoguoguo Mar 20, 2026
15c03fe
feat(box): add obs
huanghuoguoguo Mar 20, 2026
eaae31e
refactor(box): unify box service lifecycle and local runtime
huanghuoguoguo Mar 20, 2026
6391678
refactor(box): remove legacy in-process runtime code and clean up smells
huanghuoguoguo Mar 20, 2026
55fc0ca
feat: add test
huanghuoguoguo Mar 20, 2026
c802dc8
fix: fix box intergration test
huanghuoguoguo Mar 20, 2026
e8aa7b2
feat(box/mcp): integrate MCP stdio with Box sandbox — auto-isolation,…
huanghuoguoguo Mar 21, 2026
791d052
feat(box/mcp): instance-based orphan cleanup, error classification, s…
huanghuoguoguo Mar 21, 2026
14057d1
refactor: use rpc
huanghuoguoguo Mar 21, 2026
fbe6e14
fix: import
huanghuoguoguo Mar 21, 2026
76fbd08
refactor(box): clean up sandbox subsystem code quality and efficiency
huanghuoguoguo Mar 22, 2026
a7664d1
fix: ruff
huanghuoguoguo Mar 22, 2026
42fa753
refactor(sandbox): keep box logic out of pipeline and localagent
huanghuoguoguo Mar 22, 2026
c095e83
fix: ruff
huanghuoguoguo Mar 22, 2026
b64a23f
refactor(box): move box runtime to langbot-plugin-sdk
huanghuoguoguo Mar 22, 2026
9e0fa37
fix: ruff
huanghuoguoguo Mar 22, 2026
bfeb831
feat: enhance sandbox api
huanghuoguoguo Mar 24, 2026
63d22b1
refactor(box): derive paths from shared host root
huanghuoguoguo Mar 24, 2026
2911220
fix(box): tighten sandbox exposure and restore box integration coverage
huanghuoguoguo Mar 24, 2026
3f368c5
refactor(types): remove quoted annotations under postponed evaluation
huanghuoguoguo Mar 24, 2026
93104a9
feat(box): unify native agent tools around exec/read/write/edit
huanghuoguoguo Mar 24, 2026
0f00269
chore(sandbox): move MCP loader changes to follow-up branch
huanghuoguoguo Mar 26, 2026
fcf74c3
feat(box): add session workspace quota enforcement and SDK quota meta…
huanghuoguoguo Mar 26, 2026
4b8a8c5
feat(skills): add Agent Skills management system (#1917)
fdc310 Apr 8, 2026
fd68c16
feat(sandbox): add MCP box integration on top of sandbox base (#2083)
huanghuoguoguo Apr 8, 2026
51fcf26
refactor(mcp): extract box stdio runtime helper
huanghuoguoguo Apr 8, 2026
a8eb6e6
refactor(box): introduce reusable workspace session helper
huanghuoguoguo Apr 8, 2026
2697d82
refactor(box): run Box Runtime as subprocess inside LangBot container
huanghuoguoguo Apr 9, 2026
fad69c7
fix(web): prevent first-emission snapshot from swallowing unsaved cha…
RockChinQ Apr 14, 2026
bae6535
style(web): align plugin list header button heights
RockChinQ Apr 14, 2026
b2ae4a6
docs(review): update Box architecture review documents
RockChinQ Apr 17, 2026
3340e98
feat(web): improve login error layout and add Terms of Service link
RockChinQ Apr 17, 2026
f6e7983
refactor(web): replace all hardcoded SVG icons with lucide-react
RockChinQ Apr 17, 2026
94da5bf
fix(web): stop polling plugin tasks when no active installs
RockChinQ Apr 17, 2026
c7e8f19
fix(deps): update langbot-plugin version and add new dependencies
RockChinQ Apr 17, 2026
1b4107a
refactor: use Space API for release checks and stop idle polling
RockChinQ Apr 17, 2026
f4406cd
feat(box): add --standalone-box flag and 3-way transport decision for…
RockChinQ Apr 17, 2026
aa40151
refactor(box): use single port with path-based routing for Box WS
RockChinQ Apr 17, 2026
e2d555a
feat(web): show Box runtime status in plugin debug info popover
RockChinQ Apr 17, 2026
ec00e49
fix(web): remove ephemeral sandbox count from Box status display
RockChinQ Apr 17, 2026
7e50063
feat(box): configurable sandbox scope and unified skill containers
RockChinQ Apr 18, 2026
cee5e9e
feat(web): show active sandbox details in Box status popover
RockChinQ Apr 18, 2026
cbb3613
feat(box): add startup and availability logging for sandbox tools
RockChinQ Apr 18, 2026
5a4ec62
feat(box): support custom sandbox container image via config.yaml
RockChinQ Apr 18, 2026
29eadcb
feat(box): add heartbeat and reconnection for Box runtime connector
RockChinQ Apr 18, 2026
b71f690
feat(web): move runtime status to dashboard, clean up plugin debug po…
RockChinQ Apr 19, 2026
eaffde0
refactor(web): compact system status into a single card alongside met…
RockChinQ Apr 19, 2026
7858d17
feat: show connector error details for Plugin and Box runtime status
RockChinQ Apr 19, 2026
d47803d
fix(web): auto-refresh system status and show disconnect errors in re…
RockChinQ Apr 19, 2026
7e0a197
fix(box): handle RPC failure in get_status/get_sessions gracefully
RockChinQ Apr 19, 2026
3e2190a
fix(box): add persistent reconnection loop with exponential backoff
RockChinQ Apr 19, 2026
2dfd9d5
fix(box): detect disconnect when handler.run() returns normally
RockChinQ Apr 19, 2026
e0510bc
fix(web): refresh system status card when clicking Refresh Data button
RockChinQ Apr 19, 2026
dfd4ab7
fix(web): fix system status card stuck in loading state
RockChinQ Apr 19, 2026
f196cbc
feat(web): show active sandbox details in dashboard Box status popover
RockChinQ Apr 19, 2026
e955b3d
feat(box): add global sandbox scope option
RockChinQ Apr 19, 2026
f19cd40
refactor(web): replace popover with dialog for system status details
RockChinQ Apr 19, 2026
fe9aed4
fix(web): widen system status dialog and fix scroll border issue
RockChinQ Apr 19, 2026
db135f2
feat(web): add tooltips for truncated fields in system status dialog
RockChinQ Apr 19, 2026
f934781
feat: add download button
wangcham May 4, 2026
80911a3
Merge remote-tracking branch 'origin/master' into feat/sandbox
RockChinQ May 5, 2026
58f9ff9
feat: successfully install
wangcham May 7, 2026
188511a
feat: delete old filter
wangcham May 7, 2026
e412ed5
feat: youhua frontend
wangcham May 7, 2026
ad9aa39
fix: align box runtime launch args
RockChinQ May 8, 2026
f306c76
feat: translate
wangcham May 8, 2026
fffc862
feat: refactor market
wangcham May 9, 2026
f3d45ee
feat: youhua qianduan
wangcham May 9, 2026
46a9ed3
chore: rename extension zh translation
RockChinQ May 9, 2026
8ff60c5
feat(extensions): unify extensions endpoint and refresh extensions pa…
RockChinQ May 9, 2026
14c2da4
feat(extensions): fallback lucide icon when extension icon is missing
RockChinQ May 9, 2026
6f97877
feat(sidebar): unify installed-extensions list with plugins, MCP and …
RockChinQ May 9, 2026
dd809d3
feat(extensions): mobile-friendly layout for extensions and add-exten…
RockChinQ May 9, 2026
3db2ddd
feat: change ui
wangcham May 11, 2026
3f7031b
feat: delete version for mcp and skills
wangcham May 12, 2026
b739007
fix: constrain home page content width
RockChinQ May 12, 2026
afc3795
fix: preserve monitoring card borders under sticky filters
RockChinQ May 12, 2026
e4c674a
fix(box): restore sandbox config and shared mcp runtime
RockChinQ May 12, 2026
a565f3e
fix(box): harden sandbox session isolation
RockChinQ May 12, 2026
4db0f20
fix(skill): remove auto activation setting
RockChinQ May 12, 2026
7145447
feat(skill): align skill system with Claude Code's Tool Call design
huanghuoguoguo May 13, 2026
892556d
feat(tools): add glob and grep native sandbox tools
huanghuoguoguo May 13, 2026
77a85c5
feat(skill): add skill file browsing capability
huanghuoguoguo May 13, 2026
b9e8827
fix(skill): copy builtin skills to data/skills on startup
huanghuoguoguo May 13, 2026
17ae695
fix(skill): improve file browsing and fix path handling
huanghuoguoguo May 13, 2026
d786b34
fix(toolmgr): correct skill_tool_loader attribute name
huanghuoguoguo May 13, 2026
fd03b20
fix(native): update tool descriptions to use register_skill
huanghuoguoguo May 13, 2026
656dafb
feat(toolmgr): enhance tool initialization with backend availability …
huanghuoguoguo May 14, 2026
d5ce3b3
refactor: remove unused imports and clean up code in various files
huanghuoguoguo May 14, 2026
ae11bce
feat: polish extension detail pages
RockChinQ May 15, 2026
98a106d
feat: persist sidebar list expansion
RockChinQ May 15, 2026
e8c7147
fix: refine extension ui and backend errors
RockChinQ May 15, 2026
c1f5ba1
fix: align add extension marketplace ui
RockChinQ May 15, 2026
e814f35
feat: manage skills through box runtime
RockChinQ May 16, 2026
bf8b515
feat: support github skill installation
RockChinQ May 17, 2026
651904a
fix: import github skill directories
RockChinQ May 18, 2026
971cc3f
feat: install market extensions from card click
RockChinQ May 18, 2026
9e62227
feat(web): improve skill import flow
RockChinQ May 18, 2026
747ea06
feat: polish extension import flow
RockChinQ May 18, 2026
257d9d3
fix(mcp): stabilize shared box managed processes
RockChinQ May 18, 2026
d809724
fix(web): improve backend retry and sidebar scrolling
RockChinQ May 19, 2026
6351730
docs(review): refresh box architecture review for feat/sandbox
RockChinQ May 19, 2026
5773e8a
refactor(box): use unified env-override mechanism for box.local config
RockChinQ May 19, 2026
18ad51e
test: repair stale skill/sandbox tests for feat/sandbox
RockChinQ May 19, 2026
28c00cb
ci(tests): run unit tests on every push to feat/** branches
RockChinQ May 19, 2026
99328cf
fix(skill): harden mount/reload paths and HTTP errors against stale s…
RockChinQ May 20, 2026
ec2d21f
feat(box): add box.enabled toggle and gate consumers on availability
RockChinQ May 20, 2026
446099e
feat(web): surface Box disabled/unavailable state across consumers
RockChinQ May 20, 2026
f7ee2c0
docs(box): document the box.enabled toggle and gate behavior matrix
RockChinQ May 20, 2026
9f9b112
refactor(pipeline-form): swap Box banner for field-level disable_if +…
RockChinQ May 20, 2026
216b1b9
feat(mcp): friendly UI message when stdio MCP refused by Box state
RockChinQ May 20, 2026
aa8d53d
feat(mcp-web): block stdio MCP creation at the form when Box is unava…
RockChinQ May 20, 2026
49064ff
fix(web): prevent plugin config form overflow
RockChinQ May 20, 2026
cc072be
refactor(skill): remove all local-filesystem fallbacks; Box is the so…
RockChinQ May 20, 2026
42855cf
chore(skill): prune dead local-filesystem helpers left over from Box …
RockChinQ May 20, 2026
68bd786
fix(skill): re-inject skill index into local-agent system prompt
RockChinQ May 20, 2026
a2a9f42
fix(box): downgrade get_status.available when backend probed unavailable
RockChinQ May 20, 2026
2cddc7e
feat(web): surface the specific Box failure reason in unavailable banner
RockChinQ May 20, 2026
e65f851
Merge remote-tracking branch 'langbot-app/master' into feat/sandbox
RockChinQ May 20, 2026
d1ddff9
test: reconcile master's unit tests with feat/sandbox refactors
RockChinQ May 20, 2026
3430221
refactor(box): launch box runtime via the lbp CLI subcommand
RockChinQ May 21, 2026
a39c4d5
chore: bump langbot-plugin beta 1
RockChinQ May 21, 2026
7cf4e58
fix(ci): resolve langbot-plugin from PyPI and clear lint failures
RockChinQ May 21, 2026
cb79a6d
chore: bump beta version
RockChinQ May 21, 2026
708fb1a
docs: remove BOX_BACKEND override reference
RockChinQ May 22, 2026
901a925
fix(pipelines): stop attributing dashboard debug WS to bound web_page…
RockChinQ May 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@ on:
branches:
- master
- develop
paths:
- 'src/langbot/**'
- 'tests/**'
- '.github/workflows/run-tests.yml'
- 'pyproject.toml'
- 'uv.lock'
- 'run_tests.sh'
- 'scripts/test-*.sh'
- 'feat/**'
# No path filter on push: every push to the branches above runs the
# full unit-test suite. feat/** branches in particular must be tested
# on every push (they accumulate large changes before a PR exists).

jobs:
test:
Expand Down
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<a href="https://link.langbot.app/zh/docs/guide">文档</a> |
<a href="https://link.langbot.app/zh/docs/api">API</a> |
<a href="https://space.langbot.app/cloud">Cloud</a> |
<a href="https://space.langbot.app">插件市场</a> |
<a href="https://space.langbot.app">扩展市场</a> |
<a href="https://langbot.featurebase.app/roadmap">路线图</a>

</div>
Expand Down
43 changes: 42 additions & 1 deletion docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,40 @@ services:
networks:
- langbot_network

# The Box sandbox runtime is optional. It is only started when you run
# ``docker compose --profile box up`` (or ``docker compose --profile all
# up``). With Box off, LangBot keeps the dashboard / skills list visible
# (read-only) but disables sandbox tools, skill add/edit and stdio MCP —
# set ``box.enabled: false`` in ``data/config.yaml`` (or
# ``BOX__ENABLED=false`` in the langbot service env below) to match.
langbot_box:
image: rockchin/langbot:latest
container_name: langbot_box
profiles: ["box", "all"]
volumes:
# Keep the source and target path identical because langbot_box uses the
# host Docker socket to create sandbox containers. Override
# LANGBOT_BOX_ROOT with an absolute path if you do not want the default.
- ${LANGBOT_BOX_ROOT:-${PWD}/data/box}:${LANGBOT_BOX_ROOT:-${PWD}/data/box}
# Mount container runtime socket for Box sandbox backend.
# Uncomment the one that matches your container runtime:
# - /var/run/podman/podman.sock:/var/run/podman/podman.sock # Podman
- /var/run/docker.sock:/var/run/docker.sock # Docker
restart: on-failure
environment:
- TZ=Asia/Shanghai
# The Box runtime does NOT read box.local.* from config.yaml or env; it
# receives its configuration from LangBot via the INIT RPC action.
# Do not add LANGBOT_BOX_* / BOX__* here — they would be silently ignored.
# Launched through the same CLI entry point as the plugin runtime
# (`langbot_plugin.cli.__init__ <subcommand>`). WebSocket is the default
# control transport — mirrors `rt`, which also runs with no flag. Pass
# `-s` / `--stdio-control` only for the stdio mode LangBot uses outside
# containers.
command: ["uv", "run", "--no-sync", "-m", "langbot_plugin.cli.__init__", "box"]
networks:
- langbot_network

langbot:
image: rockchin/langbot:latest
container_name: langbot
Expand All @@ -26,6 +60,13 @@ services:
restart: on-failure
environment:
- TZ=Asia/Shanghai
# Unified env-override convention: SECTION__SUBSECTION__KEY overrides the
# matching config.yaml field (see LoadConfigStage). These map onto
# box.local.* and are forwarded to the Box runtime via INIT RPC.
- BOX__LOCAL__HOST_ROOT=${LANGBOT_BOX_ROOT:-${PWD}/data/box}
- BOX__LOCAL__DEFAULT_WORKSPACE=default
- BOX__LOCAL__SKILLS_ROOT=skills
- BOX__LOCAL__ALLOWED_MOUNT_ROOTS=${LANGBOT_BOX_ROOT:-${PWD}/data/box}
ports:
- 5300:5300 # For web ui and webhook callback
- 2280-2285:2280-2285 # For platform reverse connection
Expand All @@ -34,4 +75,4 @@ services:

networks:
langbot_network:
driver: bridge
driver: bridge
594 changes: 594 additions & 0 deletions docs/review/box-architecture.md

Large diffs are not rendered by default.

157 changes: 157 additions & 0 deletions docs/review/box-issues.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Box 系统架构问题清单

> 更新日期: 2026-05-19
> 分支: `feat/sandbox` (LangBot + langbot-plugin-sdk)

---

## 已解决(自上一轮 review)

下列原 P0/P1 项在最新分支已被修复,仅作记录:

| 原编号 | 问题 | 处理 commit / 说明 |
|--------|------|---------------------|
| #3 | Box 无重连机制 | `_make_connection_callback` 已接入 `runtime_disconnect_callback`;`BoxService._reconnect_loop()` 实现指数退避重连 (`2dfd9d5d`、`c6882cf`) |
| #4 | Box 无心跳 | `BoxRuntimeConnector._heartbeat_loop()`,间隔 20s(沿用 Plugin 模式) |
| #10 | Windows 兼容 | connector 增加 Windows 分支 (subprocess + WS),backend 适配 Windows Docker (`120817a`、`fafb7a4`) |
| #12 | nsjail image 字段冲突 | `_assert_session_compatible()` 在不支持自定义镜像的 backend 跳过 image 字段 |
| #22 | 前端无 Box UI | 监控页 `SystemStatusCards.tsx` 已接入 `/api/v1/box/status`;Skill 管理页接入了全部 skill API(sessions/errors API 仍未接入) |

---

## P0 — 合并前建议修复

### 1. policy.py 是死代码

- **位置**: `pkg/box/policy.py` (98 行)
- **现状**: `SandboxPolicy`、`ToolPolicy`、`ElevatedPolicy` 三个类已定义,但全项目无任何导入或调用
- **影响**: 三层安全策略(沙箱模式 / 工具白名单 / 权限提升)完全未生效。当前实际策略仍是"Box 可用就暴露全部 6 个 native tool,不可用就全部隐藏"
- **建议**: 要么删除死代码,要么接入 NativeToolLoader 的工具暴露 / exec 调用链。如果短期不会接入,至少在 `pkg/box/__init__.py` 显式标注其状态

### 2. WebSocket relay 无认证

- **位置**: SDK `box/server.py` — Action RPC 路径 `/rpc/ws` 与 managed-process relay `/v1/sessions/{id}/managed-process/{pid}/ws`
- **现状**: 任何能访问 5410 端口的客户端都可以连接,attach 任意 session 的 managed process stdin/stdout,或直接发起 EXEC
- **影响**: 容器化 / Docker compose 部署中,若 Box runtime 端口外暴露,网络内的攻击者可直接控制沙箱
- **建议**: 至少加 token 认证(INIT 时下发,WS 连接 query string 或 header 校验);多 process 后 attach 面更大,更不能裸奔

### 3. security.py 根路径未拦截

- **位置**: SDK `box/security.py` `BLOCKED_HOST_PATHS_POSIX`
- **现状**: 黑名单中没有 `/`,`host_path="/"` 可通过校验并挂载整个主机文件系统;用户 home 目录、`/var` 等也未拦截
- **建议**: 将 `/` 加入黑名单,或改用白名单策略与 LangBot 侧 `allowed_mount_roots` 二次拦截

### 4. INIT 与 backend 初始化的竞态

- **位置**: SDK `box/runtime.py` `init()` 在握手后才下发实际配置;`backend` 在 INIT 之前可能已经按默认值实例化
- **现状**: commit `5029d9c` 修复了 "init config before backend reuse" 的部分场景,但 backend 重新实例化时若有正在执行的 session,可能命中旧 backend
- **建议**: 整理 init/handshake 顺序——要么 INIT 完成前不接受任何业务 action,要么允许 backend 配置变更时显式清理现有 session

---

## P1 — 合并后优先跟进

### 5. Session 数量无上限

- **位置**: SDK `box/runtime.py` `_get_or_create_session()`
- **现状**: `_sessions` dict 无容量限制,恶意或异常调用可创建无限 session
- **建议**: 加 `max_sessions` 配置项,达到上限时拒绝新建或按 LRU 清理

### 6. Quota 检查存在 TOCTOU

- **位置**: `pkg/box/service.py` `_enforce_workspace_quota()`
- **现状**: 应用层先读磁盘大小再执行命令,两步之间有竞态窗口
- **建议**: 短期用 Docker `--storage-opt size=` 做内核级限制;长期用 Redis 原子计数器做预留式配额

### 7. 全局锁持有期间执行慢操作

- **位置**: SDK `box/runtime.py` `_get_or_create_session()` — `self._lock` 下调用 `backend.start_session()` (即 `docker run` / `nsjail` 进程启动 / E2B `Sandbox.create`)
- **影响**: `docker run` 可能耗时数秒(含镜像拉取)、E2B 冷启动通常 > 1s,期间阻塞所有并发请求
- **建议**: 在 `_lock` 下仅做状态检查和 session 注册,容器创建在锁外执行

### 8. Session 清理是机会性的

- **位置**: SDK `box/runtime.py` `_reap_expired_sessions_locked()` — 仅在 `_get_or_create_session()` 时调用
- **影响**: 如果长时间无新 session 请求,过期 session(含容器)不会被清理
- **建议**: 加一个独立的 `asyncio.create_task` 定时清理(如每 60s 一次)

### 9. server.py 直接访问 runtime 私有字段

- **位置**: SDK `box/server.py` — managed-process WS handler 直接读 `runtime._sessions`
- **影响**: 绕过锁和封装,在并发场景下可能读到不一致状态
- **建议**: 在 BoxRuntime 上增加公共方法(如 `get_session_managed_process(session_id, process_id)`)

### 10. workspace quota 检查阻塞事件循环

- **位置**: `pkg/box/service.py` `_get_workspace_size_bytes()` — 使用同步 `os.scandir` 递归遍历
- **影响**: 大工作区可能阻塞 asyncio event loop
- **建议**: 用 `asyncio.to_thread()` 包装,或用 `aiofiles` 异步扫描

### 11. extra_mounts 一旦容器创建即固定

- **位置**: SDK `box/runtime.py` 的兼容性检查;`pkg/box/service.py:build_skill_extra_mounts()`
- **现状**: Skill 挂载在容器创建时一次性写入;同一 session 后续 pipeline 切换 skill 列表时,新挂载不会生效(除非销毁重建)
- **影响**: 用户长时间共享 session 的场景下,新激活的 skill 可能挂不上
- **建议**: 要么在创建时把 pipeline 绑定的所有 skill 都挂上(实际现状)+ 写入文档;要么变更挂载时强制销毁 session 重建(已被 commit `5029d9c` 部分覆盖,需校验)

---

## P2 — 后续迭代

### 12. 重复的 `_is_path_under` 函数

- **位置**: `pkg/box/service.py` 行 30 附近 — 同名函数定义两次
- **建议**: 删除重复定义

### 13. localagent.py 工具循环无迭代上限

- **位置**: `pkg/provider/runners/localagent.py` `while pending_tool_calls` 循环
- **影响**: 恶意或混乱的 LLM 可无限产生 tool call,消耗资源
- **建议**: 加 `max_tool_iterations` 配置项(如默认 50 次)

### 14. localagent.py 中的死代码

- **位置**: `pkg/provider/runners/localagent.py:29-35` 附近 — 旧命名 `SANDBOX_EXEC_TOOL_NAME` 和 `SANDBOX_EXEC_SYSTEM_GUIDANCE`
- **现状**: 旧命名方案的遗留常量,从未被引用(实际使用 `EXEC_TOOL_NAME` from native.py)
- **建议**: 删除

### 15. @loader_class 装饰器未使用

- **位置**: `pkg/provider/tools/loader.py` — `preregistered_loaders` 列表和 `@loader_class` 装饰器
- **现状**: 各 loader 的 `@loader_class` 多数被注释掉,ToolManager 手动实例化所有 loader
- **建议**: 要么启用装饰器自动注册,要么删除未用的机制

### 16. 工具名冲突风险

- **位置**: `pkg/provider/tools/toolmgr.py` `execute_func_call()` — 按优先级 native → plugin → mcp → skill → skill_authoring 分发
- **影响**: 如果 plugin 或 MCP 有名为 `exec`/`read`/`write`/`edit`/`glob`/`grep`/`activate` 的工具,会被前序 loader 静默遮蔽
- **建议**: 加命名空间前缀或冲突检测告警

### 17. client.py 反序列化不一致

- **位置**: SDK `box/client.py` — `execute()` 与其他方法对返回值的反序列化方式不统一(部分手动构造 model,部分用 `model_validate`)
- **建议**: 统一使用 `model_validate`

### 18. 错误类型还原基于字符串前缀匹配

- **位置**: SDK `box/client.py` `_translate_action_error()`
- **影响**: 如果 server 端错误消息格式变化,client 会回退到通用 `BoxError`,丢失类型信息
- **建议**: 在 ActionResponse 中增加结构化的错误类型字段(如 `error_code` 枚举)

### 19. 前端只用到了 status

- **位置**: `web/src/app/home/monitoring/...` 已接入 `/api/v1/box/status`
- **现状**: `/api/v1/box/sessions` 与 `/api/v1/box/errors` 后端可用、前端未消费
- **建议**: 在监控页或独立 Box 详情页展示活跃 session 列表与最近错误,提升运维体感

### 20. skill_store 测试覆盖偏薄

- **位置**: SDK `tests/box/test_skill_store.py` 仅 88 行
- **现状**: 相对 `skill_store.py` 的 647 行实现,单测覆盖度不够;GitHub 安装路径、`source_subdir` / `target_suffix` 组合、损坏 zip 的错误处理等场景未覆盖
- **建议**: 至少补到核心 path 覆盖(preview/install/list/file CRUD 各 2~3 个 case)

### 21. 集成测试未进 CI

- **位置**: LangBot `tests/integration_tests/box/test_box_integration.py`、`test_box_mcp_integration.py`,SDK 端的 E2B 真机测试
- **现状**: 容器实际执行、E2B 真实 sandbox、Managed process WS attach 均仅本地能跑
- **建议**: 加一个可选的 Docker-in-Docker CI stage,或在合并前手动跑 checklist
Loading
Loading