Skip to content

Commit 1f8f90e

Browse files
authored
Merge branch 'claude-code-best:main' into main
2 parents ecac0ab + 2782529 commit 1f8f90e

42 files changed

Lines changed: 12587 additions & 420 deletions

Some content is hidden

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

.gitignore

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,21 @@ coverage
88
.vscode
99
*.suo
1010
*.lock
11-
src/utils/vendor/
11+
src/utils/vendor/
12+
13+
# AI tool runtime directories
14+
.agents/
15+
.codex/
16+
.omx/
17+
18+
# Binary / screenshot files (root only)
19+
/*.png
20+
*.bmp
21+
22+
# Agent / tool state dirs
23+
.swarm/
24+
.agents/__pycache__/
25+
26+
# Python bytecode
27+
__pycache__/
28+
*.pyc

DEV-LOG.md

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,56 @@
11
# DEV-LOG
22

3+
## Enable SHOT_STATS, TOKEN_BUDGET, PROMPT_CACHE_BREAK_DETECTION (2026-04-05)
4+
5+
**PR**: [claude-code-best/claude-code#140](https://github.com/claude-code-best/claude-code/pull/140)
6+
**分支**: `feat/enable-safe-feature-flags`
7+
8+
对 22 个被标记为 "COMPLETE" 的编译时 feature flag 进行实际源码验证(6 个并行子代理 + Codex CLI 独立复核),发现审计报告存在大量误判。最终确认仅 3 个 flag 为真正 compile-only,安全启用。
9+
10+
**验证流程:**
11+
12+
1. 6 个并行子代理分别检查每个 flag 的 `feature('FLAG_NAME')` 引用点、依赖模块完整性、外部服务依赖
13+
2. Codex CLI (v0.118.0, 240K tokens) 独立复核,将原 7 个 "compile-only" 进一步缩减为 3 个
14+
3. 3 个专项代理逐一验证代码路径完整性和运行时安全性
15+
16+
**新启用的 3 个 flag:**
17+
18+
| Flag | 功能 | 用户可感知效果 |
19+
|------|------|---------------|
20+
| `SHOT_STATS` | shot 分布统计 | `/stats` 面板显示 shot 分布和 one-shot rate |
21+
| `TOKEN_BUDGET` | token 预算目标 | 支持 `+500k` / `spend 2M tokens` 语法,自动续写直到达标,带进度条 |
22+
| `PROMPT_CACHE_BREAK_DETECTION` | cache key 变化检测 | 内部诊断,`--debug` 模式可见,写 diff 到临时目录 |
23+
24+
**修改文件:**
25+
26+
| 文件 | 变更 |
27+
|------|------|
28+
| `build.ts` | `DEFAULT_BUILD_FEATURES` 新增 3 个 flag |
29+
| `scripts/dev.ts` | `DEFAULT_FEATURES` 新增 3 个 flag |
30+
| `package.json` / `bun.lock` | 新增 `openai` 依赖(OpenAI 兼容层需要) |
31+
32+
**新增文档:**
33+
34+
| 文件 | 说明 |
35+
|------|------|
36+
| `docs/features/feature-flags-codex-review.md` | Codex 独立复核报告:修正后的 5 类分类、恢复优先级、三轴分类标准建议 |
37+
| `docs/features/feature-flags-audit-complete.md` | 标记所有已启用 flag 的状态(`[build: ON]` / `[dev: ON]`|
38+
39+
**Codex 复核关键发现:**
40+
41+
- 原 22 个 "COMPLETE" flag 中,8 个核心模块是 stub,3 个依赖远程服务
42+
- `TEAMMEM``AGENT_TRIGGERS``EXTRACT_MEMORIES``KAIROS_BRIEF` 被降级为"有条件可用"(受 GrowthBook 门控)
43+
- 建议审计分类标准改为三轴:实现完整度 × 激活条件 × 运行风险
44+
- 恢复优先级:REACTIVE_COMPACT > BG_SESSIONS > PROACTIVE > CONTEXT_COLLAPSE
45+
46+
**验证结果:**
47+
48+
- `bun run build` → 475 files ✅
49+
- `bun test` → 零新增失败 ✅
50+
- 3 个 flag 代码路径全部完整,无缺失依赖,无 crash 风险 ✅
51+
52+
---
53+
354
## /dream 手动触发 + DreamTask 类型补全 (2026-04-04)
455

556
`/dream` 命令从 KAIROS feature gate 中解耦,作为 bundled skill 无条件注册;补全 DreamTask 类型存根。
@@ -39,6 +90,7 @@
3990

4091
## Computer Use Windows 增强:窗口绑定截图 + UI Automation + OCR (2026-04-03)
4192

93+
4294
在三平台基础实现之上,利用 Windows 原生 API 增强 Computer Use 的 Windows 专属能力。
4395

4496
**新增文件:**
@@ -118,23 +170,6 @@ packages/@ant/computer-use-{input,swift}/src/
118170
| `vendor/audio-capture/{platform}/audio-capture.node` | 6 个平台的原生音频二进制(cpal,来自参考项目) |
119171
| `vendor/audio-capture-src/index.ts` | 原生模块加载器(按 `${arch}-${platform}` 动态 require `.node`|
120172

121-
**修改文件:**
122-
123-
| 文件 | 变更 |
124-
|------|------|
125-
| `packages/audio-capture-napi/src/index.ts` | SoX 子进程 stub → 原生 `.node` 加载器(含 `process.cwd()` workspace 路径 fallback) |
126-
| `scripts/dev.ts` | `DEFAULT_FEATURES``"VOICE_MODE"` |
127-
| `build.ts` | `DEFAULT_BUILD_FEATURES``"VOICE_MODE"` |
128-
| `docs/features/voice-mode.md` | 追加恢复计划章节(第八节) |
129-
130-
**验证结果:**
131-
132-
- `isNativeAudioAvailable()``true`(Windows x64 原生 `.node` 加载成功)
133-
- `feature('VOICE_MODE')``ENABLED`
134-
- `bun run build` → voice 代码编入产物
135-
136-
**运行时前置条件:** claude.ai OAuth 登录 + 麦克风权限
137-
138173
---
139174

140175
## Enable Claude in Chrome MCP (2026-04-03)

build.ts

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,88 @@
1-
import { readdir, readFile, writeFile, cp } from "fs/promises";
2-
import { join } from "path";
3-
import { getMacroDefines } from "./scripts/defines.ts";
1+
import { readdir, readFile, writeFile, cp } from 'fs/promises'
2+
import { join } from 'path'
3+
import { getMacroDefines } from './scripts/defines.ts'
44

5-
const outdir = "dist";
5+
const outdir = 'dist'
66

77
// Step 1: Clean output directory
8-
const { rmSync } = await import("fs");
9-
rmSync(outdir, { recursive: true, force: true });
8+
const { rmSync } = await import('fs')
9+
rmSync(outdir, { recursive: true, force: true })
1010

1111
// Default features that match the official CLI build.
1212
// Additional features can be enabled via FEATURE_<NAME>=1 env vars.
13-
const DEFAULT_BUILD_FEATURES = ["AGENT_TRIGGERS_REMOTE", "CHICAGO_MCP", "VOICE_MODE"];
13+
const DEFAULT_BUILD_FEATURES = [
14+
'AGENT_TRIGGERS_REMOTE',
15+
'CHICAGO_MCP',
16+
'VOICE_MODE',
17+
'SHOT_STATS',
18+
'PROMPT_CACHE_BREAK_DETECTION',
19+
'TOKEN_BUDGET',
20+
]
1421

1522
// Collect FEATURE_* env vars → Bun.build features
1623
const envFeatures = Object.keys(process.env)
17-
.filter(k => k.startsWith("FEATURE_"))
18-
.map(k => k.replace("FEATURE_", ""));
19-
const features = [...new Set([...DEFAULT_BUILD_FEATURES, ...envFeatures])];
24+
.filter(k => k.startsWith('FEATURE_'))
25+
.map(k => k.replace('FEATURE_', ''))
26+
const features = [...new Set([...DEFAULT_BUILD_FEATURES, ...envFeatures])]
2027

2128
// Step 2: Bundle with splitting
2229
const result = await Bun.build({
23-
entrypoints: ["src/entrypoints/cli.tsx"],
24-
outdir,
25-
target: "bun",
26-
splitting: true,
27-
define: getMacroDefines(),
28-
features,
29-
});
30+
entrypoints: ['src/entrypoints/cli.tsx'],
31+
outdir,
32+
target: 'bun',
33+
splitting: true,
34+
define: getMacroDefines(),
35+
features,
36+
})
3037

3138
if (!result.success) {
32-
console.error("Build failed:");
33-
for (const log of result.logs) {
34-
console.error(log);
35-
}
36-
process.exit(1);
39+
console.error('Build failed:')
40+
for (const log of result.logs) {
41+
console.error(log)
42+
}
43+
process.exit(1)
3744
}
3845

3946
// Step 3: Post-process — replace Bun-only `import.meta.require` with Node.js compatible version
40-
const files = await readdir(outdir);
41-
const IMPORT_META_REQUIRE = "var __require = import.meta.require;";
42-
const COMPAT_REQUIRE = `var __require = typeof import.meta.require === "function" ? import.meta.require : (await import("module")).createRequire(import.meta.url);`;
47+
const files = await readdir(outdir)
48+
const IMPORT_META_REQUIRE = 'var __require = import.meta.require;'
49+
const COMPAT_REQUIRE = `var __require = typeof import.meta.require === "function" ? import.meta.require : (await import("module")).createRequire(import.meta.url);`
4350

44-
let patched = 0;
51+
let patched = 0
4552
for (const file of files) {
46-
if (!file.endsWith(".js")) continue;
47-
const filePath = join(outdir, file);
48-
const content = await readFile(filePath, "utf-8");
49-
if (content.includes(IMPORT_META_REQUIRE)) {
50-
await writeFile(
51-
filePath,
52-
content.replace(IMPORT_META_REQUIRE, COMPAT_REQUIRE),
53-
);
54-
patched++;
55-
}
53+
if (!file.endsWith('.js')) continue
54+
const filePath = join(outdir, file)
55+
const content = await readFile(filePath, 'utf-8')
56+
if (content.includes(IMPORT_META_REQUIRE)) {
57+
await writeFile(
58+
filePath,
59+
content.replace(IMPORT_META_REQUIRE, COMPAT_REQUIRE),
60+
)
61+
patched++
62+
}
5663
}
5764

5865
console.log(
59-
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for Node.js compat)`,
60-
);
66+
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for Node.js compat)`,
67+
)
6168

6269
// Step 4: Copy native .node addon files (audio-capture)
63-
const vendorDir = join(outdir, "vendor", "audio-capture");
64-
await cp("vendor/audio-capture", vendorDir, { recursive: true });
65-
console.log(`Copied vendor/audio-capture/ → ${vendorDir}/`);
70+
const vendorDir = join(outdir, 'vendor', 'audio-capture')
71+
await cp('vendor/audio-capture', vendorDir, { recursive: true })
72+
console.log(`Copied vendor/audio-capture/ → ${vendorDir}/`)
6673

6774
// Step 5: Bundle download-ripgrep script as standalone JS for postinstall
6875
const rgScript = await Bun.build({
69-
entrypoints: ["scripts/download-ripgrep.ts"],
70-
outdir,
71-
target: "node",
72-
});
76+
entrypoints: ['scripts/download-ripgrep.ts'],
77+
outdir,
78+
target: 'node',
79+
})
7380
if (!rgScript.success) {
74-
console.error("Failed to bundle download-ripgrep script:");
75-
for (const log of rgScript.logs) {
76-
console.error(log);
77-
}
78-
// Non-fatal — postinstall fallback to bun run scripts/download-ripgrep.ts
81+
console.error('Failed to bundle download-ripgrep script:')
82+
for (const log of rgScript.logs) {
83+
console.error(log)
84+
}
85+
// Non-fatal — postinstall fallback to bun run scripts/download-ripgrep.ts
7986
} else {
80-
console.log(`Bundled download-ripgrep script to ${outdir}/`);
87+
console.log(`Bundled download-ripgrep script to ${outdir}/`)
8188
}

0 commit comments

Comments
 (0)