Skip to content

Commit 70f32e2

Browse files
Merge branch 'main' into pr/smallflyingpig/36
# Conflicts: # src/entrypoints/cli.tsx
2 parents e815002 + 87fdd45 commit 70f32e2

184 files changed

Lines changed: 11173 additions & 1808 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ jobs:
2020
- name: Install dependencies
2121
run: bun install --frozen-lockfile
2222

23-
- name: Lint
24-
run: bun run lint
25-
2623
- name: Test
2724
run: bun test
2825

CLAUDE.md

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,38 @@ This is a **reverse-engineered / decompiled** version of Anthropic's official Cl
1212
# Install dependencies
1313
bun install
1414

15-
# Dev mode (direct execution via Bun)
15+
# Dev mode (runs cli.tsx with MACRO defines injected via -d flags)
1616
bun run dev
17-
# equivalent to: bun run src/entrypoints/cli.tsx
1817

1918
# Pipe mode
2019
echo "say hello" | bun run src/entrypoints/cli.tsx -p
2120

22-
# Build (outputs dist/cli.js, ~25MB)
21+
# Build (code splitting, outputs dist/cli.js + ~450 chunk files)
2322
bun run build
23+
24+
# Test
25+
bun test # run all tests
26+
bun test src/utils/__tests__/hash.test.ts # run single file
27+
bun test --coverage # with coverage report
28+
29+
# Lint & Format (Biome)
30+
bun run lint # check only
31+
bun run lint:fix # auto-fix
32+
bun run format # format all src/
2433
```
2534

26-
No test runner is configured. No linter is configured.
35+
详细的测试规范、覆盖状态和改进计划见 `docs/testing-spec.md`
2736

2837
## Architecture
2938

3039
### Runtime & Build
3140

3241
- **Runtime**: Bun (not Node.js). All imports, builds, and execution use Bun APIs.
33-
- **Build**: `bun build src/entrypoints/cli.tsx --outdir dist --target bun` — single-file bundle.
42+
- **Build**: `build.ts` 执行 `Bun.build()` with `splitting: true`,入口 `src/entrypoints/cli.tsx`,输出 `dist/cli.js` + ~450 chunk files。构建后自动替换 `import.meta.require` 为 Node.js 兼容版本(产物 bun/node 都可运行)。
43+
- **Dev mode**: `scripts/dev.ts` 通过 Bun `-d` flag 注入 `MACRO.*` defines,运行 `src/entrypoints/cli.tsx``scripts/defines.ts` 集中管理 define map。
3444
- **Module system**: ESM (`"type": "module"`), TSX with `react-jsx` transform.
3545
- **Monorepo**: Bun workspaces — internal packages live in `packages/` resolved via `workspace:*`.
46+
- **Lint/Format**: Biome (`biome.json`)。`bun run lint` / `bun run lint:fix` / `bun run format`
3647

3748
### Entry & Bootstrap
3849

@@ -106,10 +117,21 @@ All `feature('FLAG_NAME')` calls come from `bun:bundle` (a build-time API). In t
106117
- **`src/types/message.ts`** — Message type hierarchy (UserMessage, AssistantMessage, SystemMessage, etc.).
107118
- **`src/types/permissions.ts`** — Permission mode and result types.
108119

120+
## Testing
121+
122+
- **框架**: `bun:test`(内置断言 + mock)
123+
- **单元测试**: 就近放置于 `src/**/__tests__/`,文件名 `<module>.test.ts`
124+
- **集成测试**: `tests/integration/`,共享 mock/fixture 在 `tests/mocks/`
125+
- **命名**: `describe("functionName")` + `test("behavior description")`,英文
126+
- **Mock 模式**: 对重依赖模块使用 `mock.module()` + `await import()` 解锁(必须内联在测试文件中,不能从共享 helper 导入)
127+
- **当前状态**: 1286 tests / 67 files / 0 fail(详见 `docs/testing-spec.md` 的覆盖状态表和评分)
128+
109129
## Working with This Codebase
110130

111131
- **Don't try to fix all tsc errors** — they're from decompilation and don't affect runtime.
112132
- **`feature()` is always `false`** — any code behind a feature flag is dead code in this build.
113133
- **React Compiler output** — Components have decompiled memoization boilerplate (`const $ = _c(N)`). This is normal.
114134
- **`bun:bundle` import** — In `src/main.tsx` and other files, `import { feature } from 'bun:bundle'` works at build time. At dev-time, the polyfill in `cli.tsx` provides it.
115135
- **`src/` path alias** — tsconfig maps `src/*` to `./src/*`. Imports like `import { ... } from 'src/utils/...'` are valid.
136+
- **MACRO defines** — 集中管理在 `scripts/defines.ts`。Dev mode 通过 `bun -d` 注入,build 通过 `Bun.build({ define })` 注入。修改版本号等常量只改这个文件。
137+
- **构建产物兼容 Node.js**`build.ts` 会自动后处理 `import.meta.require`,产物可直接用 `node dist/cli.js` 运行。

DEV-LOG.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# DEV-LOG
2+
3+
## Auto Mode 补全 (2026-04-02)
4+
5+
反编译丢失了 auto mode 分类器的三个 prompt 模板文件,代码逻辑完整但无法运行。
6+
7+
**新增:**
8+
- `yolo-classifier-prompts/auto_mode_system_prompt.txt` — 主系统提示词
9+
- `yolo-classifier-prompts/permissions_external.txt` — 外部权限模板(用户规则替换默认值)
10+
- `yolo-classifier-prompts/permissions_anthropic.txt` — 内部权限模板(用户规则追加)
11+
12+
**改动:**
13+
- `scripts/dev.ts` + `build.ts` — 扫描 `FEATURE_*` 环境变量注入 Bun `--feature`
14+
- `cli.tsx` — 启动时打印已启用的 feature
15+
- `permissionSetup.ts``AUTO_MODE_ENABLED_DEFAULT``feature('TRANSCRIPT_CLASSIFIER')` 决定,开 feature 即开 auto mode
16+
- `docs/safety/auto-mode.mdx` — 补充 prompt 模板章节
17+
18+
**用法:** `FEATURE_TRANSCRIPT_CLASSIFIER=1 bun run dev`
19+
20+
**注意:** prompt 模板为重建产物。
21+
22+
---
23+
24+
## USER_TYPE=ant TUI 修复 (2026-04-02)
25+
26+
`global.d.ts` 声明的全局函数在反编译版本运行时未定义,导致 `USER_TYPE=ant` 时 TUI 崩溃。
27+
28+
修复方式:显式 import / 本地 stub / 全局 stub / 新建 stub 文件。涉及文件:
29+
`cli.tsx`, `model.ts`, `context.ts`, `effort.ts`, `thinking.ts`, `undercover.ts`, `Spinner.tsx`, `AntModelSwitchCallout.tsx`(新建), `UndercoverAutoCallout.tsx`(新建)
30+
31+
注意:
32+
- `USER_TYPE=ant` 启用 alt-screen 全屏模式,中心区域满屏是预期行为
33+
- `global.d.ts` 中剩余未 stub 的全局函数(`getAntModels` 等)遇到 `X is not defined` 时按同样模式处理

build.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@ const outdir = "dist";
88
const { rmSync } = await import("fs");
99
rmSync(outdir, { recursive: true, force: true });
1010

11+
// Collect FEATURE_* env vars → Bun.build features
12+
const features = Object.keys(process.env)
13+
.filter(k => k.startsWith("FEATURE_"))
14+
.map(k => k.replace("FEATURE_", ""));
15+
1116
// Step 2: Bundle with splitting
1217
const result = await Bun.build({
1318
entrypoints: ["src/entrypoints/cli.tsx"],
1419
outdir,
1520
target: "bun",
1621
splitting: true,
1722
define: getMacroDefines(),
23+
features,
1824
});
1925

2026
if (!result.success) {

docs/safety/auto-mode.mdx

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
---
2+
title: "Auto Mode - AI 分类器驱动的自主执行模式"
3+
description: "详解 Claude Code 的 auto mode:基于 transcript classifier 的自动权限决策、两阶段分类流水线、危险权限剥离机制、模式切换状态管理、以及与 plan mode 的协作方式。"
4+
keywords: ["auto mode", "yoloClassifier", "transcript classifier", "权限分类", "自动执行", "两阶段分类"]
5+
---
6+
7+
## 概述
8+
9+
Auto mode 是 Claude Code 的一种权限模式,让 AI 进入**连续自主执行**状态。与传统模式(每个敏感操作都弹出权限对话框等待用户审批)不同,auto mode 使用 AI 分类器(transcript classifier)自动判断每个工具调用是否安全,从而实现无中断的执行体验。
10+
11+
```
12+
权限模式层级:
13+
14+
default → auto → bypassPermissions
15+
(逐项确认) (AI 分类器审批) (全部放行)
16+
```
17+
18+
## 核心架构
19+
20+
### 1. AI 分类器(yoloClassifier)
21+
22+
分类器是 auto mode 的核心,位于 `src/utils/permissions/yoloClassifier.ts`
23+
24+
每个工具调用经过分类器评估,返回三种裁决之一:
25+
26+
| 裁决 | 含义 | 处理方式 |
27+
|------|------|---------|
28+
| **allow** | 操作安全 | 直接执行,用户无感知 |
29+
| **deny** | 操作危险 | 拒绝执行,向 AI 返回拒绝消息 |
30+
| **ask** | 无法确定 | 回退到传统权限对话框 |
31+
32+
分类器的判断基于完整的对话上下文(transcript),而不仅仅看单条命令——它能理解操作的意图和上下文。
33+
34+
### 2. 两阶段分类流水线
35+
36+
分类器支持两阶段 XML 分类(`classifyYoloActionXml`):
37+
38+
```
39+
Stage 1 — "fast"(快速判断)
40+
├── max_tokens=64,stop_sequences 触发即时 yes/no
41+
├── 如果 allow → 直接放行(最快路径)
42+
└── 如果 block → 进入 Stage 2
43+
44+
Stage 2 — "thinking"(深度思考)
45+
├── chain-of-thought 推理
46+
├── 减少误报(false positives)
47+
└── 最终决定 allow / deny / ask
48+
```
49+
50+
两个阶段共享相同的 system prompt 和 user content,利用 API 的 prompt caching(1 小时 TTL)优化性能。
51+
52+
可通过配置选择模式:
53+
- `'both'`(默认)— 两阶段都跑
54+
- `'fast'` — 只跑 Stage 1
55+
- `'thinking'` — 只跑 Stage 2
56+
57+
### 3. 分类器结果类型
58+
59+
```typescript
60+
// src/types/permissions.ts
61+
type YoloClassifierResult = {
62+
thinking?: string // 分类器的推理过程
63+
shouldBlock: boolean // 是否阻止
64+
reason: string // 决策原因
65+
unavailable?: boolean // 分类器是否不可用
66+
transcriptTooLong?: boolean // 对话是否超出上下文窗口
67+
model: string // 使用的分类器模型
68+
stage?: 'fast' | 'thinking' // 哪个阶段做出的决定
69+
// ... token 使用量、耗时等监控字段
70+
}
71+
```
72+
73+
## 安全机制
74+
75+
### 危险权限剥离
76+
77+
进入 auto mode 时,系统调用 `stripDangerousPermissionsForAutoMode()``permissionSetup.ts:510`),移除所有可能绕过分类器的 allow 规则。
78+
79+
被剥离的规则类型(`dangerousPatterns.ts`):
80+
81+
| 规则类型 | 示例 | 剥离原因 |
82+
|---------|------|---------|
83+
| **Bash 代码执行** | `Bash(python:*)`, `Bash(node:*)` | 解释器可执行任意代码,绕过分类器审查 |
84+
| **Shell 入口** | `Bash(bash:*)`, `Bash(sh:*)` | 直接 shell 访问等同无限制 |
85+
| **Agent 规则** | `Agent(*)` | 任何 Agent allow 规则会绕过分类器审批子代理 |
86+
| **PowerShell 代码执行** | `PowerShell(node:*)` | 同 Bash 逻辑 |
87+
| **权限提升** | `Bash(sudo:*)`, `Bash(eval:*)` | 可执行任意命令 |
88+
89+
剥离的规则被暂存在 `strippedDangerousRules` 中,退出 auto mode 时通过 `restoreDangerousPermissions()` 恢复。
90+
91+
### 模型支持检测
92+
93+
不是所有模型都支持 auto mode。`modelSupportsAutoMode()``src/utils/betas.ts`)检查当前模型是否具备安全分类能力。不支持的模型无法进入 auto mode。
94+
95+
### Circuit Breaker 机制
96+
97+
`autoModeState.ts` 维护一个 circuit breaker 标志:
98+
99+
```typescript
100+
let autoModeCircuitBroken = false // 由远程配置控制
101+
```
102+
103+
当远程配置(GrowthBook `tengu_auto_mode_config.enabled`)设为 `'disabled'` 时,circuit breaker 触发,阻止 auto mode 的进入和继续使用。这为 Anthropic 提供了远程紧急关停能力。
104+
105+
## 模式切换状态管理
106+
107+
### 进入 Auto Mode
108+
109+
`transitionPermissionMode()``permissionSetup.ts:597`)处理所有模式切换:
110+
111+
```
112+
1. 检查 auto mode gate 是否开启(isAutoModeGateEnabled)
113+
2. 设置 autoModeActive = true
114+
3. 调用 stripDangerousPermissionsForAutoMode() 剥离危险规则
115+
4. 向对话注入 Auto Mode 系统提示
116+
```
117+
118+
### 退出 Auto Mode
119+
120+
```
121+
1. 设置 autoModeActive = false
122+
2. 设置 needsAutoModeExitAttachment = true(触发退出通知)
123+
3. 调用 restoreDangerousPermissions() 恢复被剥离的规则
124+
4. 向对话注入 "Exited Auto Mode" 提示
125+
```
126+
127+
### 触发路径
128+
129+
Auto mode 可通过以下方式激活:
130+
- CLI 参数 `--enable-auto-mode`
131+
- settings.json 中的 `autoMode` 配置
132+
- Plan mode 默认使用 auto mode 语义(`useAutoModeDuringPlan`,默认 true)
133+
- SDK 控制消息
134+
- REPL 中 Shift+Tab 切换
135+
136+
## 系统提示词
137+
138+
### 进入时(Full Instructions)
139+
140+
注入到对话中的指令(`messages.ts:3464`):
141+
142+
> Auto mode is active. The user chose continuous, autonomous execution. You should:
143+
>
144+
> 1. **Execute immediately** — 直接实现,做合理假设
145+
> 2. **Minimize interruptions** — 常规决策自行判断,减少提问
146+
> 3. **Prefer action over planning** — 默认直接编码,不进 plan mode
147+
> 4. **Expect course corrections** — 用户可随时纠正
148+
> 5. **Do not take overly destructive actions** — 删除数据/修改生产系统仍需确认
149+
> 6. **Avoid data exfiltration** — 不主动分享密钥/内部文档
150+
151+
### 持续运行时(Sparse Instructions)
152+
153+
后续轮次注入简短提醒:
154+
155+
> Auto mode still active. Execute autonomously, minimize interruptions, prefer action over planning.
156+
157+
### 退出时(Exit Instructions)
158+
159+
> You have exited auto mode. Ask clarifying questions when the approach is ambiguous rather than making assumptions.
160+
161+
## 与 Plan Mode 的协作
162+
163+
Plan mode 默认使用 auto mode 语义(`getUseAutoModeDuringPlan()`,默认 true)。这意味着:
164+
165+
- Plan mode 进入时,如果 auto mode 可用,也会激活分类器
166+
- `isAutoModeActive()` 是权威信号(`prePlanMode`/`strippedDangerousRules` 不可靠)
167+
- 退出 plan mode 时会同时退出 auto mode
168+
169+
## 分类器不可用的降级策略
170+
171+
当分类器 API 不可用时(`unavailable: true``transcriptTooLong: true`):
172+
173+
- 不会直接 allow — 回退到传统的权限对话框(ask)
174+
- 向 AI 发送消息:"{model} is temporarily unavailable, so auto mode cannot determine the safety of {toolName} right now."
175+
- 确定性错误(如对话过长)不重试,直接降级
176+
177+
## 分类器 Prompt 模板
178+
179+
分类器的行为由三个 prompt 文件控制,位于 `src/utils/permissions/yolo-classifier-prompts/`。这些文件在构建时通过 `require()` 内联为字符串常量,运行时不可修改。
180+
181+
### auto_mode_system_prompt.txt
182+
183+
主系统提示词,定义分类器的角色、分类流程和决策类别。包含:
184+
185+
- **分类流程**:理解操作 → 检查用户意图 → 评估风险
186+
- **BLOCK 始终阻止**:外部代码执行、不可逆删除、未授权持久化、安全削弱、提权、网络服务
187+
- **BLOCK 除非明确意图**:CWD 外写入、系统包管理、git push、大规模变更
188+
- **ALLOW 安全操作**:读文件、搜索、git 只读命令、测试/lint/构建、CWD 内编辑
189+
- `<permissions_template>` 占位符 — 运行时替换为具体权限模板(external 或 anthropic)
190+
- 末尾 `Use the classify_result tool to report your classification.` — XML 模式下被替换为 `<block>` 标签格式说明
191+
192+
### permissions_external.txt
193+
194+
外部用户版本的权限模板。三个 `<user_*_to_replace>` 标签内包裹默认规则(bullet 格式),用户自定义规则**整体替换**默认值:
195+
196+
```
197+
<user_allow_rules_to_replace>
198+
- 默认 allow 规则 1
199+
- 默认 allow 规则 2
200+
</user_allow_rules_to_replace>
201+
```
202+
203+
- **allow**:9 条默认规则(只读命令、版本检查、git 只读、测试/lint/构建、包安装、CWD 内文件操作等)
204+
- **soft_deny**:10 条默认规则(外部代码执行、递归删除、shell 配置修改、提权、网络服务等)
205+
- **environment**:4 条环境描述(终端环境、auto mode 上下文、开发工具可用、语言/框架不限)
206+
207+
`getDefaultExternalAutoModeRules()` 从此文件提取 bullet 项,供 `claude auto-mode defaults` 命令输出。
208+
209+
### permissions_anthropic.txt
210+
211+
Anthropic 内部版本的权限模板。默认规则在标签**外部**,标签内为空,用户自定义规则以**追加**方式叠加:
212+
213+
```
214+
- 默认规则(在标签外,始终生效)
215+
<user_allow_rules_to_replace>
216+
</user_allow_rules_to_replace>
217+
```
218+
219+
相比 external 版本,额外包含:
220+
- 云 CLI 只读命令(aws describe, gcloud describe, kubectl get 等)
221+
- 基础设施即代码 plan 命令(terraform plan, pulumi preview 等)
222+
- 对应的 deny 规则(云资源创建/修改/删除、IaC apply、生产环境访问等)
223+
224+
### 模板替换流程
225+
226+
```
227+
buildYoloSystemPrompt()
228+
├── BASE_PROMPT.replace('<permissions_template>', EXTERNAL/ANTHROPIC_TEMPLATE)
229+
├── .replace(<user_allow_rules_to_replace>, userAllow ?? defaults)
230+
├── .replace(<user_deny_rules_to_replace>, userDeny ?? defaults)
231+
└── .replace(<user_environment_to_replace>, userEnvironment ?? defaults)
232+
```
233+
234+
- 外部模板:用户设置非空时**替换**对应标签内容,否则保留默认值
235+
- 内部模板:用户设置**追加**到默认值之后(标签在末尾为空)
236+
237+
## 当前状态说明
238+
239+
> **注意**:auto mode 的完整代码逻辑已存在于代码库中,但依赖 `feature('TRANSCRIPT_CLASSIFIER')` feature flag。
240+
> 在当前反编译版本中,`feature()` 始终返回 `false`,因此 auto mode 不可用。
241+
> 要启用需将 `feature('TRANSCRIPT_CLASSIFIER')` 改为 `true`,并确保 GrowthBook 配置源有合理的 fallback 默认值。
242+
243+
Prompt 模板文件为**重建产物**——原始文件在反编译过程中丢失,已根据代码逻辑和 `yoloClassifier.ts` 中的替换模式重新编写。
244+
245+
## 相关源码索引
246+
247+
| 文件 | 职责 |
248+
|------|------|
249+
| `src/utils/permissions/yoloClassifier.ts` | 分类器核心实现 |
250+
| `src/utils/permissions/autoModeState.ts` | Auto mode 状态管理 |
251+
| `src/utils/permissions/permissionSetup.ts` | 模式切换、危险权限剥离 |
252+
| `src/utils/permissions/dangerousPatterns.ts` | 危险命令模式列表 |
253+
| `src/utils/permissions/classifierDecision.ts` | 分类器决策处理 |
254+
| `src/utils/permissions/classifierShared.ts` | 分类器共享逻辑 |
255+
| `src/utils/permissions/bashClassifier.ts` | Bash 命令分类规则 |
256+
| `src/utils/permissions/bypassPermissionsKillswitch.ts` | bypass 权限熔断器 |
257+
| `src/utils/permissions/yolo-classifier-prompts/auto_mode_system_prompt.txt` | 分类器主系统提示词 |
258+
| `src/utils/permissions/yolo-classifier-prompts/permissions_external.txt` | 外部权限模板 |
259+
| `src/utils/permissions/yolo-classifier-prompts/permissions_anthropic.txt` | 内部权限模板 |
260+
| `src/cli/handlers/autoMode.ts` | CLI `auto-mode` 子命令处理 |
261+
| `src/utils/messages.ts` | Auto mode 系统提示词注入 |
262+
| `src/types/permissions.ts` | 权限类型定义 |
263+
| `src/utils/betas.ts` | 模型 auto mode 支持检测 |

0 commit comments

Comments
 (0)