# 原生 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 配置面。
