Skip to content

Commit 2b84333

Browse files
Merge pull request #137 from amDosion/feat/computer-use-windows
feat: Computer Use v2 — 跨平台 Executor + Python Bridge + GUI 无障碍
2 parents ba97889 + c17edcb commit 2b84333

36 files changed

Lines changed: 8336 additions & 385 deletions

.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: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

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

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

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

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-
138122
---
139123

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

build.ts

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,62 @@ import { readdir, readFile, writeFile, cp } from "fs/promises";
22
import { join } from "path";
33
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.
1313
const DEFAULT_BUILD_FEATURES = ["AGENT_TRIGGERS_REMOTE", "CHICAGO_MCP", "VOICE_MODE"];
1414

1515
// Collect FEATURE_* env vars → Bun.build features
1616
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])];
17+
.filter(k => k.startsWith('FEATURE_'))
18+
.map(k => k.replace('FEATURE_', ''))
19+
const features = [...new Set([...DEFAULT_BUILD_FEATURES, ...envFeatures])]
2020

2121
// Step 2: Bundle with splitting
2222
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-
});
23+
entrypoints: ['src/entrypoints/cli.tsx'],
24+
outdir,
25+
target: 'bun',
26+
splitting: true,
27+
define: getMacroDefines(),
28+
features,
29+
})
3030

3131
if (!result.success) {
32-
console.error("Build failed:");
33-
for (const log of result.logs) {
34-
console.error(log);
35-
}
36-
process.exit(1);
32+
console.error('Build failed:')
33+
for (const log of result.logs) {
34+
console.error(log)
35+
}
36+
process.exit(1)
3737
}
3838

3939
// 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);`;
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);`
4343

44-
let patched = 0;
44+
let patched = 0
4545
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-
}
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+
}
5656
}
5757

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

6262
// Step 4: Copy native .node addon files (audio-capture)
6363
const vendorDir = join(outdir, "vendor", "audio-capture");
@@ -66,16 +66,16 @@ console.log(`Copied vendor/audio-capture/ → ${vendorDir}/`);
6666

6767
// Step 5: Bundle download-ripgrep script as standalone JS for postinstall
6868
const rgScript = await Bun.build({
69-
entrypoints: ["scripts/download-ripgrep.ts"],
70-
outdir,
71-
target: "node",
72-
});
69+
entrypoints: ['scripts/download-ripgrep.ts'],
70+
outdir,
71+
target: 'node',
72+
})
7373
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
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
7979
} else {
80-
console.log(`Bundled download-ripgrep script to ${outdir}/`);
80+
console.log(`Bundled download-ripgrep script to ${outdir}/`)
8181
}

0 commit comments

Comments
 (0)