NATIVE_CLAUDE_CODE_DESIGN.md 7.0 KB

原生 Claude-Code 模式设计(workspace.assistant 专用)

状态:设计 → 实现中 日期:2026-06-15 关联记忆:claude-code 大会话 resume 卡死、MCP 隔离、文件工具 CWD、目录守卫、401。

1. 动机(一句话)

workspace.assistant(选文件夹自由对话)现在被套进 react-over-text 封装: claude -p --tools "" 把 claude-code 阉割成纯文本生成器,平台再用正则从文本里抠 {"tool":...} 自己执行、自己管 session。实测这套不如直接调一次 claude-code

  • 工具调用是模型当散文手写的 JSON → 格式飘(input 裸串/path vs file_path)→ 平台解析失败 → 76 个调用 0 执行 0 落盘(run_541390a1ea49)。
  • 我们自己的 session 轮换/熔断在 API 高延迟下疯狂触发(40 分钟 14 个 session)→ 每次重注入只带原始任务、丢掉已读内容 → agent 永远从零开始、空转到步数耗尽。
  • claude-code 的强项(结构化 tool_use、上下文管理、文件编辑、持久会话)全被关掉

根因:用错模具。 react-over-text 是为多智能体编排(orchestrator 必须把活 派给子智能体,故必须禁 native 工具防它自己偷干——run_4e07736d7f60 伪造数据教训) 设计的。但 workspace.assistant单体 do-everything 助手,不是 orchestrator, 套进去只有成本没有收益。

2. 目标

为「工作区对话型」agent 开第二条执行车道:让 claude-code 当 agent 本身—— 在所选文件夹里用 native 工具干活,平台只负责选目录、起进程、流式透传、沙箱与落盘。 orchestrator / 科研评审 / pipeline 保持现有 react 车道不变。

3. 架构:两条执行车道

run_agent(_stream)
   ├─ agent_template ∈ {workspace.assistant}  且  inplace_dir 有效
   │     → 车道 B:原生 claude-code(本设计)
   └─ 否则
         → 车道 A:现有 react-over-text(不动)

判定点已就绪:_require_workspace_dir(强制绑文件夹)+ inplace_dir(=所选文件夹)。 新增布尔 native_workspace,在 _execute_agent 内分流。

4. 原生 runner 规格(新文件 providers/claude_code_native.py

run_native(prompt, *, cwd, model, system_append, session_id, on_event, config) -> NativeResult

4.1 命令

claude -p <prompt>
  --output-format stream-json --verbose      # 实时事件流
  --model <model>
  --append-system-prompt <平台 system 片段>   # 注入工作目录纪律/安全铁律
  --add-dir <cwd>                            # 文件操作限定在该文件夹
  --strict-mcp-config                        # 隔离用户 MCP(默认;可配开)
  --permission-mode bypassPermissions        # -p 非交互必须,否则工具会卡在审批
  [--resume <session_id>]                    # 多轮续接(同一 thread)
  (cwd = 工作文件夹)
  • native 工具开:不传 --tools ""。用 --allowedTools 白名单: Read Write Edit Bash Glob Grep NotebookEdit TodoWrite(按需加 WebSearch/WebFetch)。
  • 不再有 --tools ""、react JSON 协议、ConversationLam、session 轮换/熔断、 file_tools._resolve。claude-code 用它自己的 native 工具,cwd 已是工作文件夹。

4.2 流式事件解析(stream-json 每行一个 JSON)

claude stream-json 事件 平台 on_event(沿用现有 SSE 类型,前端零改动)
system/init 记录 session_id
assistant content text think_chunk(增量思考)
assistant content tool_use tool_call(name + input)
user content tool_result tool_result(output)
result/success answer + done(result 文本、usage、cost、session_id)
result is_error/401 _is_auth_error_AUTH_HINT;其余 → 失败

4.3 返回 / 落盘

NativeResult → 现有 trace_info 结构:input_tokens/output_tokens/cost_usd/ cache_*_tokens/steps/trace_json/workspace_path/session_id。直接喂回 run 记录, 前端 trace/cost 面板不变。

4.4 多轮(thread)会话续接

claude-code 自管上下文,无需我们轮换。需要把上一轮 session_id 持久化、下一轮 --resume。MVP:sidecar 文件 <agent_run_base>/.native_sessions.json {thread_id: session_id}(不污染用户文件夹、不动 DB schema)。resume 失败(session 丢失)→ 退化成新 first-turn(claude 自己重建上下文)。

4.5 超时/容错

  • 首字节超时(沿用 60s 思路)+ 硬超时(config.timeout)。
  • 401 → _AUTH_HINT(已实现,复用)。
  • 卡死直接失败(不再轮换;native 单进程长跑由 claude-code 自己管上下文,不会像 resume 那样越长越卡)。

5. 沙箱与安全

  • 文件cwd=工作文件夹 + 仅 --add-dir <cwd>(不加别的目录)→ claude-code 的 Read/Write/Edit 限定在该文件夹。
  • Bash:native Bash 不经平台 guard。MVP 接受此权衡(cwd 限定 + bypassPermissions), 与现状(react 车道 Bash 也只靠 CWD)一致。P1 硬化:claude-code settings permissions.deny 或 PreToolUse hook 拦危险命令/越界写(留迭代)。
  • MCP:默认 --strict-mcp-config 隔离(避免 Gmail/Calendar 干扰); config.extra["native_allow_mcp"]=true 可放开。

6. 保留 / 丢弃(仅车道 B)

丢弃 保留/复用
--tools ""、react JSON 协议 --strict-mcp-config(MCP 隔离)
ConversationLam / compiler react loop _is_auth_error / _AUTH_HINT(401)
session 轮换 / 连卡熔断 _require_workspace_dir(强制绑目录)
file_tools._resolve / 平台文件工具 on_step→SSE 事件管道(前端不变)
obs 截断、max_input_chars run 记录 / trace_info / cost 落盘

7. 向后兼容

  • agent_template ∈ {workspace.assistant} 走车道 B;其余 agent 零影响
  • 可加 config.extra["execution_mode"]="react" 强制退回车道 A(兜底开关)。
  • workspace.assistant.yml 标注 executionMode: native(声明意图,便于排查)。

8. 测试

  • TestNativeStreamParse:喂一段录制的 stream-json,断言事件映射正确、result/usage 抽取对。
  • TestNativeAuthError:result is_error 401 → 抛 _AUTH_HINT
  • TestNativeRouting:workspace.assistant + 有效 dir → native 分支;其他模板 → react。
  • live(skip 默认):真起一次 claude -p 在临时目录写一个文件,验证落盘。

9. 开放决策(已选默认,可改)

  1. 权限模式bypassPermissions(-p 必须非交互)— 选定。
  2. MCP:默认隔离 — 选定。
  3. 工具白名单Read Write Edit Bash Glob Grep NotebookEdit TodoWrite — 选定,可配。
  4. session 持久化:sidecar JSON(MVP)→ 后续可升 DB 列。

10. 实施顺序

P0(本次):native runner + stream 解析 + agents.py 分流 + 单测 + workspace.yml 标注。 P1(后续):Bash 硬沙箱(deny/hook)、session 持久化升 DB、native_allow_mcp 配置面。