mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 22:35:51 +00:00
Compare commits
13 Commits
feature/po
...
v1.10.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0ca1d054c | ||
|
|
6585d0f67c | ||
|
|
e4403ff010 | ||
|
|
9e61e7a90d | ||
|
|
d03af7bd4e | ||
|
|
e8ef955ff9 | ||
|
|
a8ed0cdce5 | ||
|
|
1c3b280c6a | ||
|
|
7a3cc24a00 | ||
|
|
2e7fc428cd | ||
|
|
ad09f38fd1 | ||
|
|
b0a3ef90dc | ||
|
|
c07ad4c738 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -44,3 +44,4 @@ data
|
|||||||
!.codex/prompts/
|
!.codex/prompts/
|
||||||
!.codex/prompts/**
|
!.codex/prompts/**
|
||||||
teach-me
|
teach-me
|
||||||
|
credentials.json
|
||||||
|
|||||||
10
AGENTS.md
10
AGENTS.md
@@ -171,8 +171,8 @@ bun run docs:dev
|
|||||||
| `packages/audio-capture-napi/` | 原生音频捕获(已恢复) |
|
| `packages/audio-capture-napi/` | 原生音频捕获(已恢复) |
|
||||||
| `packages/color-diff-napi/` | 颜色差异计算(完整实现,11 tests) |
|
| `packages/color-diff-napi/` | 颜色差异计算(完整实现,11 tests) |
|
||||||
| `packages/image-processor-napi/` | 图像处理(已恢复) |
|
| `packages/image-processor-napi/` | 图像处理(已恢复) |
|
||||||
| `packages/modifiers-napi/` | 键盘修饰键检测(stub) |
|
| `packages/modifiers-napi/` | 键盘修饰键检测(macOS FFI 实现) |
|
||||||
| `packages/url-handler-napi/` | URL scheme 处理(stub) |
|
| `packages/url-handler-napi/` | URL scheme 处理(环境变量 + CLI 参数读取) |
|
||||||
|
|
||||||
### Bridge / Remote Control
|
### Bridge / Remote Control
|
||||||
|
|
||||||
@@ -254,13 +254,13 @@ Feature flags control which functionality is enabled at runtime. 代码中统一
|
|||||||
| Module | Status |
|
| Module | Status |
|
||||||
|--------|--------|
|
|--------|--------|
|
||||||
| Computer Use (`@ant/*`) | Restored — macOS + Windows + Linux(后端完整度不一) |
|
| Computer Use (`@ant/*`) | Restored — macOS + Windows + Linux(后端完整度不一) |
|
||||||
| `*-napi` packages | `audio-capture-napi`、`image-processor-napi` 已恢复;`color-diff-napi` 完整;`modifiers-napi`、`url-handler-napi` 仍为 stub |
|
| `*-napi` packages | 全部已恢复/实现:`audio-capture-napi`、`image-processor-napi` 已恢复;`color-diff-napi` 完整;`modifiers-napi`(macOS FFI);`url-handler-napi`(环境变量+CLI) |
|
||||||
| Voice Mode | Restored — Push-to-Talk 语音输入(需 Anthropic OAuth) |
|
| Voice Mode | Restored — Push-to-Talk 语音输入(需 Anthropic OAuth) |
|
||||||
| OpenAI/Gemini/Grok 兼容层 | Restored |
|
| OpenAI/Gemini/Grok 兼容层 | Restored |
|
||||||
| Remote Control Server | Restored — 自托管 RCS + Web UI |
|
| Remote Control Server | Restored — 自托管 RCS + Web UI |
|
||||||
| Analytics / GrowthBook / Sentry | Empty implementations |
|
| Analytics / GrowthBook / Sentry | Empty implementations |
|
||||||
| Magic Docs / LSP Server | Removed |
|
| Magic Docs / LSP Server | Restored — Magic Docs 自动更新 + LSP 服务器管理器 |
|
||||||
| Plugins / Marketplace | Removed |
|
| Plugins / Marketplace | Restored — 插件安装/卸载/启用/禁用 + Marketplace 浏览 |
|
||||||
| MCP OAuth | Simplified |
|
| MCP OAuth | Simplified |
|
||||||
|
|
||||||
### Key Type Files
|
### Key Type Files
|
||||||
|
|||||||
14
CLAUDE.md
14
CLAUDE.md
@@ -76,7 +76,9 @@ bun run docs:dev
|
|||||||
### Runtime & Build
|
### Runtime & Build
|
||||||
|
|
||||||
- **Runtime**: Bun (not Node.js). All imports, builds, and execution use Bun APIs.
|
- **Runtime**: Bun (not Node.js). All imports, builds, and execution use Bun APIs.
|
||||||
- **Build**: `build.ts` 执行 `Bun.build()` with `splitting: true`,入口 `src/entrypoints/cli.tsx`,输出 `dist/cli.js` + chunk files。Build 默认启用 19 个 feature(见下方 Feature Flag 段)。构建后自动替换 `import.meta.require` 为 Node.js 兼容版本(产物 bun/node 都可运行)。
|
- **Build**: `build.ts` 执行 `Bun.build()` with `splitting: true`,入口 `src/entrypoints/cli.tsx`,输出 `dist/cli.js` + chunk files。Build 默认启用 19 个 feature(见下方 Feature Flag 段)。构建后自动替换 `import.meta.require` 为 Node.js 兼容版本(产物 bun/node 都可运行)。构建时会将 `vendor/audio-capture/` 和 `src/utils/vendor/ripgrep/` 复制到 `dist/vendor/` 下。
|
||||||
|
- **Build (Vite)**: `vite.config.ts` + `scripts/post-build.ts`,chunk 输出到 `dist/chunks/`。post-build 同样复制 vendor 文件到 `dist/vendor/`。
|
||||||
|
- **Vendor 路径解析**: 构建后 chunk 文件位于 `dist/` 或 `dist/chunks/` 下,vendor 二进制在 `dist/vendor/`。`src/utils/ripgrep.ts` 和 `packages/audio-capture-napi/src/index.ts` 均通过 `import.meta.url` 路径中 `lastIndexOf('dist')` 定位 dist 根目录,再拼接 `vendor/` 子路径,确保不同构建产物层级下路径一致。
|
||||||
- **Dev mode**: `scripts/dev.ts` 通过 Bun `-d` flag 注入 `MACRO.*` defines,运行 `src/entrypoints/cli.tsx`。默认启用全部 feature。
|
- **Dev mode**: `scripts/dev.ts` 通过 Bun `-d` flag 注入 `MACRO.*` defines,运行 `src/entrypoints/cli.tsx`。默认启用全部 feature。
|
||||||
- **Module system**: ESM (`"type": "module"`), TSX with `react-jsx` transform.
|
- **Module system**: ESM (`"type": "module"`), TSX with `react-jsx` transform.
|
||||||
- **Monorepo**: Bun workspaces — 15 个 workspace packages + 若干辅助目录 in `packages/` resolved via `workspace:*`。
|
- **Monorepo**: Bun workspaces — 15 个 workspace packages + 若干辅助目录 in `packages/` resolved via `workspace:*`。
|
||||||
@@ -171,8 +173,8 @@ bun run docs:dev
|
|||||||
| `packages/audio-capture-napi/` | 原生音频捕获(已恢复) |
|
| `packages/audio-capture-napi/` | 原生音频捕获(已恢复) |
|
||||||
| `packages/color-diff-napi/` | 颜色差异计算(完整实现,11 tests) |
|
| `packages/color-diff-napi/` | 颜色差异计算(完整实现,11 tests) |
|
||||||
| `packages/image-processor-napi/` | 图像处理(已恢复) |
|
| `packages/image-processor-napi/` | 图像处理(已恢复) |
|
||||||
| `packages/modifiers-napi/` | 键盘修饰键检测(stub) |
|
| `packages/modifiers-napi/` | 键盘修饰键检测(macOS FFI 实现) |
|
||||||
| `packages/url-handler-napi/` | URL scheme 处理(stub) |
|
| `packages/url-handler-napi/` | URL scheme 处理(环境变量 + CLI 参数读取) |
|
||||||
|
|
||||||
### Bridge / Remote Control
|
### Bridge / Remote Control
|
||||||
|
|
||||||
@@ -254,13 +256,13 @@ Feature flags control which functionality is enabled at runtime. 代码中统一
|
|||||||
| Module | Status |
|
| Module | Status |
|
||||||
|--------|--------|
|
|--------|--------|
|
||||||
| Computer Use (`@ant/*`) | Restored — macOS + Windows + Linux(后端完整度不一) |
|
| Computer Use (`@ant/*`) | Restored — macOS + Windows + Linux(后端完整度不一) |
|
||||||
| `*-napi` packages | `audio-capture-napi`、`image-processor-napi` 已恢复;`color-diff-napi` 完整;`modifiers-napi`、`url-handler-napi` 仍为 stub |
|
| `*-napi` packages | 全部已恢复/实现:`audio-capture-napi`、`image-processor-napi` 已恢复;`color-diff-napi` 完整;`modifiers-napi`(macOS FFI);`url-handler-napi`(环境变量+CLI) |
|
||||||
| Voice Mode | Restored — Push-to-Talk 语音输入(需 Anthropic OAuth) |
|
| Voice Mode | Restored — Push-to-Talk 语音输入(需 Anthropic OAuth) |
|
||||||
| OpenAI/Gemini/Grok 兼容层 | Restored |
|
| OpenAI/Gemini/Grok 兼容层 | Restored |
|
||||||
| Remote Control Server | Restored — 自托管 RCS + Web UI |
|
| Remote Control Server | Restored — 自托管 RCS + Web UI |
|
||||||
| Analytics / GrowthBook / Sentry | Empty implementations |
|
| Analytics / GrowthBook / Sentry | Empty implementations |
|
||||||
| Magic Docs / LSP Server | Removed |
|
| Magic Docs / LSP Server | Restored — Magic Docs 自动更新 + LSP 服务器管理器 |
|
||||||
| Plugins / Marketplace | Removed |
|
| Plugins / Marketplace | Restored — 插件安装/卸载/启用/禁用 + Marketplace 浏览 |
|
||||||
| MCP OAuth | Simplified |
|
| MCP OAuth | Simplified |
|
||||||
|
|
||||||
### Key Type Files
|
### Key Type Files
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -19,15 +19,15 @@
|
|||||||
|
|
||||||
| 特性 | 说明 | 文档 |
|
| 特性 | 说明 | 文档 |
|
||||||
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **Claude 群控技术** | Pipe IPC 多实例协作:同机 main/sub 自动编排 + LAN 跨机器零配置发现与通讯,`/pipes` 选择面板 + `Shift+↓` 交互 + 消息广播路由 | [Pipe IPC](https://ccb.agent-aura.top/docs/features/pipes-and-lan) / [LAN](https://ccb.agent-aura.top/docs/features/lan-pipes) |
|
| **Claude 群控技术** | Pipe IPC 多实例协作:同机 main/sub 自动编排 + LAN 跨机器零配置发现与通讯,`/pipes` 选择面板 + `Shift+↓` 交互 + 消息广播路由 | [Pipe IPC](https://ccb.agent-aura.top/docs/features/uds-inbox) / [LAN](https://ccb.agent-aura.top/docs/features/lan-pipes) |
|
||||||
| **ACP 协议一等一支持** | 支持接入 Zed、Cursor 等 IDE,支持会话恢复、Skills、权限桥接 | [文档](https://ccb.agent-aura.top/docs/features/acp-zed) |
|
| **ACP 协议一等一支持** | 支持接入 Zed、Cursor 等 IDE,支持会话恢复、Skills、权限桥接 | [文档](https://ccb.agent-aura.top/docs/features/acp-zed) |
|
||||||
| **Remote Control 私有部署** | Docker 自托管远程界面, 可以手机上看 CC | [文档](https://ccb.agent-aura.top/docs/features/remote-control-self-hosting) |
|
| **Remote Control 私有部署** | Docker 自托管远程界面, 可以手机上看 CC | [文档](https://ccb.agent-aura.top/docs/features/remote-control-self-hosting) |
|
||||||
| **Langfuse 监控** | 企业级 Agent 监控, 可以清晰看到每次 agent loop 细节, 可以一键转化为数据集 | [文档](https://ccb.agent-aura.top/docs/features/langfuse-monitoring) |
|
| **Langfuse 监控** | 企业级 Agent 监控, 可以清晰看到每次 agent loop 细节, 可以一键转化为数据集 | [文档](https://ccb.agent-aura.top/docs/features/langfuse-monitoring) |
|
||||||
| **Web Search** | 内置网页搜索工具, 支持 bing 和 brave 搜索 | [文档](https://ccb.agent-aura.top/docs/features/web-browser-tool) |
|
| **Web Search** | 内置网页搜索工具, 支持 bing 和 brave 搜索 | [文档](https://ccb.agent-aura.top/docs/features/web-browser-tool) |
|
||||||
| **Poor Mode** | 穷鬼模式,关闭记忆提取和键入建议,大幅度减少并发请求 | /poor 可以开关 |
|
| **Poor Mode** | 穷鬼模式,关闭记忆提取和键入建议,大幅度减少并发请求 | /poor 可以开关 |
|
||||||
| **Channels 频道通知** | MCP 服务器推送外部消息到会话(飞书/Slack/Discord/微信等),`--channels plugin:name@marketplace` 启用 | [文档](https://ccb.agent-aura.top/docs/features/channels) |
|
| **Channels 频道通知** | MCP 服务器推送外部消息到会话(飞书/Slack/Discord/微信等),`--channels plugin:name@marketplace` 启用 | [文档](https://ccb.agent-aura.top/docs/features/channels) |
|
||||||
| **自定义模型供应商** | OpenAI/Anthropic/Gemini/Grok 兼容 | [文档](https://ccb.agent-aura.top/docs/features/custom-platform-login) |
|
| **自定义模型供应商** | OpenAI/Anthropic/Gemini/Grok 兼容 (`/login`) | [文档](https://ccb.agent-aura.top/docs/features/all-features-guide) |
|
||||||
| Voice Mode | Push-to-Talk 语音输入 | [文档](https://ccb.agent-aura.top/docs/features/voice-mode) |
|
| Voice Mode | 语音输入,支持豆包语言输入(`/voice doubao`) | [文档](https://ccb.agent-aura.top/docs/features/voice-mode) |
|
||||||
| Computer Use | 屏幕截图、键鼠控制 | [文档](https://ccb.agent-aura.top/docs/features/computer-use) |
|
| Computer Use | 屏幕截图、键鼠控制 | [文档](https://ccb.agent-aura.top/docs/features/computer-use) |
|
||||||
| Chrome Use | 浏览器自动化、表单填写、数据抓取 | [自托管](https://ccb.agent-aura.top/docs/features/chrome-use-mcp) [原生版](https://ccb.agent-aura.top/docs/features/claude-in-chrome-mcp) |
|
| Chrome Use | 浏览器自动化、表单填写、数据抓取 | [自托管](https://ccb.agent-aura.top/docs/features/chrome-use-mcp) [原生版](https://ccb.agent-aura.top/docs/features/claude-in-chrome-mcp) |
|
||||||
| Sentry | 企业级错误追踪 | [文档](https://ccb.agent-aura.top/docs/internals/sentry-setup) |
|
| Sentry | 企业级错误追踪 | [文档](https://ccb.agent-aura.top/docs/internals/sentry-setup) |
|
||||||
@@ -233,6 +233,10 @@ TUI (REPL) 模式需要真实终端,无法直接通过 VS Code launch 启动
|
|||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
- [doubaoime-asr](https://github.com/starccy/doubaoime-asr) — 豆包 ASR 语音识别 SDK,为 Voice Mode 提供无需 Anthropic OAuth 的语音输入方案
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
本项目仅供学习研究用途。Claude Code 的所有权利归 [Anthropic](https://www.anthropic.com/) 所有。
|
本项目仅供学习研究用途。Claude Code 的所有权利归 [Anthropic](https://www.anthropic.com/) 所有。
|
||||||
|
|||||||
12
build.ts
12
build.ts
@@ -75,10 +75,14 @@ console.log(
|
|||||||
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for import.meta.require, ${bunPatched} for Bun destructure)`,
|
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for import.meta.require, ${bunPatched} for Bun destructure)`,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Step 4: Copy native .node addon files (audio-capture)
|
// Step 4: Copy native .node addon files (audio-capture) and vendored binaries (ripgrep)
|
||||||
const vendorDir = join(outdir, 'vendor', 'audio-capture')
|
const audioCaptureDir = join(outdir, 'vendor', 'audio-capture')
|
||||||
await cp('vendor/audio-capture', vendorDir, { recursive: true })
|
await cp('vendor/audio-capture', audioCaptureDir, { recursive: true })
|
||||||
console.log(`Copied vendor/audio-capture/ → ${vendorDir}/`)
|
console.log(`Copied vendor/audio-capture/ → ${audioCaptureDir}/`)
|
||||||
|
|
||||||
|
const ripgrepDir = join(outdir, 'vendor', 'ripgrep')
|
||||||
|
await cp('src/utils/vendor/ripgrep', ripgrepDir, { recursive: true })
|
||||||
|
console.log(`Copied src/utils/vendor/ripgrep/ → ${ripgrepDir}/`)
|
||||||
|
|
||||||
// Step 5: Generate cli-bun and cli-node executable entry points
|
// Step 5: Generate cli-bun and cli-node executable entry points
|
||||||
const cliBun = join(outdir, 'cli-bun.js')
|
const cliBun = join(outdir, 'cli-bun.js')
|
||||||
|
|||||||
13
bun.lock
13
bun.lock
@@ -145,6 +145,9 @@
|
|||||||
"yaml": "^2.8.3",
|
"yaml": "^2.8.3",
|
||||||
"zod": "^4.3.6",
|
"zod": "^4.3.6",
|
||||||
},
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"doubaoime-asr": "^0.1.0",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"packages/@ant/claude-for-chrome-mcp": {
|
"packages/@ant/claude-for-chrome-mcp": {
|
||||||
"name": "@ant/claude-for-chrome-mcp",
|
"name": "@ant/claude-for-chrome-mcp",
|
||||||
@@ -1791,6 +1794,8 @@
|
|||||||
|
|
||||||
"dompurify": ["dompurify@3.4.0", "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.0.tgz", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg=="],
|
"dompurify": ["dompurify@3.4.0", "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.0.tgz", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg=="],
|
||||||
|
|
||||||
|
"doubaoime-asr": ["doubaoime-asr@0.1.0", "", { "dependencies": { "opus-encdec": "^0.1.1", "protobufjs": "^8.0.0", "ws": "^8.18.0" }, "bin": { "doubaoime-asr": "bin/doubaoime-asr.mjs" } }, "sha512-HYUfHkTxNdOoztXwS18e6GBRLY9dSDWX43K4WvPvEmO6+RevO6WbawMMoUfHKPb4ySQn461un7XyN5l4UGejwg=="],
|
||||||
|
|
||||||
"dunder-proto": ["dunder-proto@1.0.1", "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
"dunder-proto": ["dunder-proto@1.0.1", "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
||||||
@@ -2343,6 +2348,8 @@
|
|||||||
|
|
||||||
"openai": ["openai@6.34.0", "https://registry.npmmirror.com/openai/-/openai-6.34.0.tgz", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-yEr2jdGf4tVFYG6ohmr3pF6VJuveP0EA/sS8TBx+4Eq5NT10alu5zg2dmxMXMgqpihRDQlFGpRt2XwsGj+Fyxw=="],
|
"openai": ["openai@6.34.0", "https://registry.npmmirror.com/openai/-/openai-6.34.0.tgz", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-yEr2jdGf4tVFYG6ohmr3pF6VJuveP0EA/sS8TBx+4Eq5NT10alu5zg2dmxMXMgqpihRDQlFGpRt2XwsGj+Fyxw=="],
|
||||||
|
|
||||||
|
"opus-encdec": ["opus-encdec@0.1.1", "", {}, "sha512-TDzyGqYqrwn5UEUNaLsfLGu8Ma+HRNrgLYj7Vx5wfTnafAA21G6Bnm/qTIa3orQi/yZPZYmkdpO/gez4nfA1Rw=="],
|
||||||
|
|
||||||
"os-tmpdir": ["os-tmpdir@1.0.2", "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="],
|
"os-tmpdir": ["os-tmpdir@1.0.2", "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="],
|
||||||
|
|
||||||
"oxc-parser": ["oxc-parser@0.121.0", "https://registry.npmmirror.com/oxc-parser/-/oxc-parser-0.121.0.tgz", { "dependencies": { "@oxc-project/types": "^0.121.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.121.0", "@oxc-parser/binding-android-arm64": "0.121.0", "@oxc-parser/binding-darwin-arm64": "0.121.0", "@oxc-parser/binding-darwin-x64": "0.121.0", "@oxc-parser/binding-freebsd-x64": "0.121.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.121.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.121.0", "@oxc-parser/binding-linux-arm64-gnu": "0.121.0", "@oxc-parser/binding-linux-arm64-musl": "0.121.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.121.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.121.0", "@oxc-parser/binding-linux-riscv64-musl": "0.121.0", "@oxc-parser/binding-linux-s390x-gnu": "0.121.0", "@oxc-parser/binding-linux-x64-gnu": "0.121.0", "@oxc-parser/binding-linux-x64-musl": "0.121.0", "@oxc-parser/binding-openharmony-arm64": "0.121.0", "@oxc-parser/binding-wasm32-wasi": "0.121.0", "@oxc-parser/binding-win32-arm64-msvc": "0.121.0", "@oxc-parser/binding-win32-ia32-msvc": "0.121.0", "@oxc-parser/binding-win32-x64-msvc": "0.121.0" } }, "sha512-ek9o58+SCv6AV7nchiAcUJy1DNE2CC5WRdBcO0mF+W4oRjNQfPO7b3pLjTHSFECpHkKGOZSQxx3hk8viIL5YCg=="],
|
"oxc-parser": ["oxc-parser@0.121.0", "https://registry.npmmirror.com/oxc-parser/-/oxc-parser-0.121.0.tgz", { "dependencies": { "@oxc-project/types": "^0.121.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.121.0", "@oxc-parser/binding-android-arm64": "0.121.0", "@oxc-parser/binding-darwin-arm64": "0.121.0", "@oxc-parser/binding-darwin-x64": "0.121.0", "@oxc-parser/binding-freebsd-x64": "0.121.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.121.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.121.0", "@oxc-parser/binding-linux-arm64-gnu": "0.121.0", "@oxc-parser/binding-linux-arm64-musl": "0.121.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.121.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.121.0", "@oxc-parser/binding-linux-riscv64-musl": "0.121.0", "@oxc-parser/binding-linux-s390x-gnu": "0.121.0", "@oxc-parser/binding-linux-x64-gnu": "0.121.0", "@oxc-parser/binding-linux-x64-musl": "0.121.0", "@oxc-parser/binding-openharmony-arm64": "0.121.0", "@oxc-parser/binding-wasm32-wasi": "0.121.0", "@oxc-parser/binding-win32-arm64-msvc": "0.121.0", "@oxc-parser/binding-win32-ia32-msvc": "0.121.0", "@oxc-parser/binding-win32-x64-msvc": "0.121.0" } }, "sha512-ek9o58+SCv6AV7nchiAcUJy1DNE2CC5WRdBcO0mF+W4oRjNQfPO7b3pLjTHSFECpHkKGOZSQxx3hk8viIL5YCg=="],
|
||||||
@@ -2435,7 +2442,7 @@
|
|||||||
|
|
||||||
"property-information": ["property-information@7.1.0", "https://registry.npmmirror.com/property-information/-/property-information-7.1.0.tgz", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
"property-information": ["property-information@7.1.0", "https://registry.npmmirror.com/property-information/-/property-information-7.1.0.tgz", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
||||||
|
|
||||||
"protobufjs": ["protobufjs@7.5.4", "https://registry.npmmirror.com/protobufjs/-/protobufjs-7.5.4.tgz", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
"protobufjs": ["protobufjs@8.0.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w=="],
|
||||||
|
|
||||||
"proxy-addr": ["proxy-addr@2.0.7", "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
"proxy-addr": ["proxy-addr@2.0.7", "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||||
|
|
||||||
@@ -3029,6 +3036,8 @@
|
|||||||
|
|
||||||
"@fastify/otel/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.212.0", "https://registry.npmmirror.com/@opentelemetry/instrumentation/-/instrumentation-0.212.0.tgz", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "import-in-the-middle": "^2.0.6", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg=="],
|
"@fastify/otel/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.212.0", "https://registry.npmmirror.com/@opentelemetry/instrumentation/-/instrumentation-0.212.0.tgz", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "import-in-the-middle": "^2.0.6", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg=="],
|
||||||
|
|
||||||
|
"@grpc/proto-loader/protobufjs": ["protobufjs@7.5.4", "https://registry.npmmirror.com/protobufjs/-/protobufjs-7.5.4.tgz", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
||||||
|
|
||||||
"@grpc/proto-loader/yargs": ["yargs@17.7.2", "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
"@grpc/proto-loader/yargs": ["yargs@17.7.2", "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||||
|
|
||||||
"@hono/node-ws/@hono/node-server": ["@hono/node-server@1.19.13", "https://registry.npmmirror.com/@hono/node-server/-/node-server-1.19.13.tgz", { "peerDependencies": { "hono": "^4" } }, "sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ=="],
|
"@hono/node-ws/@hono/node-server": ["@hono/node-server@1.19.13", "https://registry.npmmirror.com/@hono/node-server/-/node-server-1.19.13.tgz", { "peerDependencies": { "hono": "^4" } }, "sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ=="],
|
||||||
@@ -3123,6 +3132,8 @@
|
|||||||
|
|
||||||
"@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.1", "https://registry.npmmirror.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw=="],
|
"@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.1", "https://registry.npmmirror.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw=="],
|
||||||
|
|
||||||
|
"@opentelemetry/otlp-transformer/protobufjs": ["protobufjs@7.5.4", "https://registry.npmmirror.com/protobufjs/-/protobufjs-7.5.4.tgz", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
||||||
|
|
||||||
"@opentelemetry/sdk-logs/@opentelemetry/core": ["@opentelemetry/core@2.6.1", "https://registry.npmmirror.com/@opentelemetry/core/-/core-2.6.1.tgz", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g=="],
|
"@opentelemetry/sdk-logs/@opentelemetry/core": ["@opentelemetry/core@2.6.1", "https://registry.npmmirror.com/@opentelemetry/core/-/core-2.6.1.tgz", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g=="],
|
||||||
|
|
||||||
"@opentelemetry/sdk-logs/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "https://registry.npmmirror.com/@opentelemetry/resources/-/resources-2.6.1.tgz", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
"@opentelemetry/sdk-logs/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "https://registry.npmmirror.com/@opentelemetry/resources/-/resources-2.6.1.tgz", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||||
|
|||||||
@@ -1,27 +1,32 @@
|
|||||||
# VOICE_MODE — 语音输入
|
# VOICE_MODE — 语音输入
|
||||||
|
|
||||||
> Feature Flag: `FEATURE_VOICE_MODE=1`
|
> Feature Flag: `FEATURE_VOICE_MODE=1`
|
||||||
> 实现状态:完整可用(需要 Anthropic OAuth)
|
> 实现状态:完整可用(双后端:Anthropic OAuth / 豆包 ASR)
|
||||||
> 引用数:46
|
> 引用数:46
|
||||||
|
|
||||||
## 一、功能概述
|
## 一、功能概述
|
||||||
|
|
||||||
VOICE_MODE 实现"按键说话"(Push-to-Talk)语音输入。用户按住空格键录音,音频通过 WebSocket 流式传输到 Anthropic STT 端点(Nova 3),实时转录显示在终端中。
|
VOICE_MODE 实现"按键说话"(Push-to-Talk)语音输入。用户按住空格键录音,音频流式传输到 STT 后端,实时转录显示在终端中。支持两个后端:
|
||||||
|
|
||||||
|
- **Anthropic STT(默认)**:通过 WebSocket 流式传输到 Nova 3 端点,需要 Anthropic OAuth
|
||||||
|
- **豆包 ASR(Doubao)**:通过 `doubaoime-asr` 包的 AsyncGenerator 协议流式识别,使用独立凭证文件,无需 Anthropic OAuth
|
||||||
|
|
||||||
### 核心特性
|
### 核心特性
|
||||||
|
|
||||||
- **Push-to-Talk**:长按空格键录音,释放后自动发送
|
- **Push-to-Talk**:长按空格键录音,释放后自动发送
|
||||||
- **流式转录**:录音过程中实时显示中间转录结果
|
- **流式转录**:录音过程中实时显示中间转录结果
|
||||||
- **无缝集成**:转录文本直接作为用户消息提交到对话
|
- **无缝集成**:转录文本直接作为用户消息提交到对话
|
||||||
|
- **双后端切换**:通过 `/voice` 命令参数选择 STT 后端,持久化到 settings.json
|
||||||
|
|
||||||
## 二、用户交互
|
## 二、用户交互
|
||||||
|
|
||||||
| 操作 | 行为 |
|
| 操作 | 行为 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| 长按空格 | 开始录音,显示录音状态 |
|
| 长按空格 | 开始录音,显示录音状态 |
|
||||||
| 释放空格 | 停止录音,等待最终转录 |
|
| 释放空格 | 停止录音,转录结果自动提交 |
|
||||||
| 转录完成 | 自动插入到输入框并提交 |
|
| `/voice` | 切换语音模式开关(默认使用 Anthropic 后端) |
|
||||||
| `/voice` 命令 | 切换语音模式开关 |
|
| `/voice doubao` | 启用语音模式并使用豆包 ASR 后端 |
|
||||||
|
| `/voice anthropic` | 切换回 Anthropic STT 后端 |
|
||||||
|
|
||||||
### UI 反馈
|
### UI 反馈
|
||||||
|
|
||||||
@@ -35,26 +40,37 @@ VOICE_MODE 实现"按键说话"(Push-to-Talk)语音输入。用户按住空
|
|||||||
|
|
||||||
文件:`src/voice/voiceModeEnabled.ts`
|
文件:`src/voice/voiceModeEnabled.ts`
|
||||||
|
|
||||||
三层检查:
|
两层检查函数:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
// Anthropic 后端(需要 OAuth)
|
||||||
isVoiceModeEnabled() = hasVoiceAuth() && isVoiceGrowthBookEnabled()
|
isVoiceModeEnabled() = hasVoiceAuth() && isVoiceGrowthBookEnabled()
|
||||||
|
|
||||||
|
// 豆包后端 / 通用可用性检查(不需要 OAuth)
|
||||||
|
isVoiceAvailable() = isVoiceGrowthBookEnabled()
|
||||||
```
|
```
|
||||||
|
|
||||||
1. **Feature Flag**:`feature('VOICE_MODE')` — 编译时/运行时开关
|
1. **Feature Flag**:`feature('VOICE_MODE')` — 编译时/运行时开关
|
||||||
2. **GrowthBook Kill-Switch**:`!getFeatureValue_CACHED_MAY_BE_STALE('tengu_amber_quartz_disabled', false)` — 紧急关闭开关(默认 false = 未禁用)
|
2. **GrowthBook Kill-Switch**:`!getFeatureValue_CACHED_MAY_BE_STALE('tengu_amber_quartz_disabled', false)` — 紧急关闭开关(默认 false = 未禁用)
|
||||||
3. **Auth 检查**:`hasVoiceAuth()` — 需要 Anthropic OAuth token(非 API key)
|
3. **Auth 检查(仅 Anthropic)**:`hasVoiceAuth()` — 需要 Anthropic OAuth token(非 API key)
|
||||||
|
4. **Provider 检查**:`voiceProvider` 设置决定使用哪个后端,豆包后端跳过 OAuth 检查
|
||||||
|
|
||||||
### 3.2 核心模块
|
### 3.2 核心模块
|
||||||
|
|
||||||
| 模块 | 职责 |
|
| 模块 | 职责 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `src/voice/voiceModeEnabled.ts` | Feature flag + GrowthBook + Auth 三层门控 |
|
| `src/voice/voiceModeEnabled.ts` | Feature flag + GrowthBook + Auth 三层门控 |
|
||||||
| `src/hooks/useVoice.ts` | React hook 管理录音状态和 WebSocket 连接 |
|
| `src/hooks/useVoice.ts` | React hook 管理录音状态和后端连接 |
|
||||||
| `src/services/voiceStreamSTT.ts` | WebSocket 流式传输到 Anthropic STT |
|
| `src/services/voiceStreamSTT.ts` | Anthropic WebSocket 流式 STT |
|
||||||
|
| `src/services/doubaoSTT.ts` | 豆包 ASR 适配器(AsyncGenerator → VoiceStreamConnection) |
|
||||||
|
| `src/commands/voice/voice.ts` | `/voice` 命令实现,处理后端选择和持久化 |
|
||||||
|
| `src/hooks/useVoiceEnabled.ts` | 语音启用状态 hook,根据 provider 决定是否跳过 OAuth |
|
||||||
|
| `src/utils/settings/types.ts` | `voiceProvider: 'anthropic' | 'doubao'` 设置类型定义 |
|
||||||
|
|
||||||
### 3.3 数据流
|
### 3.3 数据流
|
||||||
|
|
||||||
|
#### Anthropic 后端
|
||||||
|
|
||||||
```
|
```
|
||||||
用户按下空格键
|
用户按下空格键
|
||||||
│
|
│
|
||||||
@@ -79,20 +95,108 @@ WebSocket 连接到 Anthropic STT 端点
|
|||||||
转录文本 → 插入输入框 → 自动提交
|
转录文本 → 插入输入框 → 自动提交
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 豆包 ASR 后端
|
||||||
|
|
||||||
|
```
|
||||||
|
用户按下空格键
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
useVoice hook 激活(检测到 voiceProvider === 'doubao')
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
macOS 原生音频 / SoX 开始录音
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
connectDoubaoStream() 创建 AudioChunkQueue + VoiceStreamConnection
|
||||||
|
│
|
||||||
|
├──→ onReady 立即触发(无需等待握手)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
音频数据通过 AudioChunkQueue 传入 transcribeRealtime()
|
||||||
|
│
|
||||||
|
├──→ INTERIM_RESULT → 实时显示中间转录
|
||||||
|
├──→ FINAL_RESULT → 显示最终转录
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
用户释放空格键
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
finalize() 立即返回(豆包在录音过程中已返回结果,无需等待)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
转录文本 → 插入输入框 → 自动提交
|
||||||
|
```
|
||||||
|
|
||||||
### 3.4 音频录制
|
### 3.4 音频录制
|
||||||
|
|
||||||
支持两种音频后端:
|
支持两种音频后端(两个 STT 后端共享):
|
||||||
- **macOS 原生音频**:优先使用,低延迟
|
- **macOS 原生音频**:优先使用,低延迟
|
||||||
- **SoX(Sound eXchange)**:回退方案,跨平台
|
- **SoX(Sound eXchange)**:回退方案,跨平台
|
||||||
|
|
||||||
音频流通过 WebSocket 发送到 Anthropic 的 Nova 3 STT 模型。
|
### 3.5 豆包 ASR 适配器设计
|
||||||
|
|
||||||
|
文件:`src/services/doubaoSTT.ts`
|
||||||
|
|
||||||
|
豆包后端使用适配器模式,将 `doubaoime-asr` 的 AsyncGenerator 协议桥接到 `VoiceStreamConnection` 接口:
|
||||||
|
|
||||||
|
**AudioChunkQueue** — push 式异步队列:
|
||||||
|
- 实现 `AsyncIterable<Uint8Array>` 接口
|
||||||
|
- `push(chunk)` 将音频数据入队,`push(null)` 发送结束信号
|
||||||
|
- 内部维护等待者(waiting)和缓冲队列(chunks)两个状态
|
||||||
|
|
||||||
|
**connectDoubaoStream()** — 连接入口:
|
||||||
|
- 动态导入 `doubaoime-asr`(optionalDependencies)
|
||||||
|
- 从 `~/.claude/tts/doubao/credentials.json` 加载凭证
|
||||||
|
- 创建 AudioChunkQueue 和 VoiceStreamConnection
|
||||||
|
- 立即触发 `onReady`(避免与 useVoice 的音频缓冲死锁)
|
||||||
|
- `finalize()` 立即返回(豆包在录音过程中已返回结果)
|
||||||
|
- 后台 async IIFE 消费 `transcribeRealtime` generator,映射响应类型到回调
|
||||||
|
|
||||||
|
**响应类型映射**:
|
||||||
|
|
||||||
|
| doubaoime-asr ResponseType | 回调映射 |
|
||||||
|
|----------------------------|----------|
|
||||||
|
| SESSION_STARTED | 日志记录 |
|
||||||
|
| VAD_START | 日志记录 |
|
||||||
|
| INTERIM_RESULT | `onTranscript(text, false)` |
|
||||||
|
| FINAL_RESULT | `onTranscript(text, true)` |
|
||||||
|
| ERROR | `onError(errorMsg)` |
|
||||||
|
| SESSION_FINISHED | 日志记录 |
|
||||||
|
|
||||||
|
### 3.6 后端选择逻辑
|
||||||
|
|
||||||
|
文件:`src/hooks/useVoice.ts`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// 判断当前 provider
|
||||||
|
isDoubaoProvider() → 读取 settings.voiceProvider
|
||||||
|
|
||||||
|
// handleKeyEvent 中的可用性检查
|
||||||
|
const sttAvailable = isDoubaoProvider()
|
||||||
|
? isDoubaoAvailableSync() // 乐观检查(首次返回 true)
|
||||||
|
: isVoiceStreamAvailable() // Anthropic WebSocket 检查
|
||||||
|
|
||||||
|
// attemptConnect 中的连接函数选择
|
||||||
|
const connectFn = isDoubaoProvider()
|
||||||
|
? connectDoubaoStream
|
||||||
|
: connectVoiceStream
|
||||||
|
```
|
||||||
|
|
||||||
|
豆包后端的特殊处理:
|
||||||
|
- 跳过 `getVoiceKeyterms()` 调用(豆包无需关键词提示)
|
||||||
|
- 跳过 Focus Mode(`if (!enabled || !focusMode || isDoubaoProvider())`)
|
||||||
|
|
||||||
## 四、关键设计决策
|
## 四、关键设计决策
|
||||||
|
|
||||||
1. **OAuth 独占**:语音模式使用 `voice_stream` 端点(claude.ai),仅 Anthropic OAuth 用户可用。API key、Bedrock、Vertex 用户无法使用
|
1. **双后端共存**:豆包后端作为独立适配器与 Anthropic 后端并存,不替换原有流程,通过 `voiceProvider` 设置切换
|
||||||
2. **GrowthBook 负向门控**:`tengu_amber_quartz_disabled` 默认 `false`,新安装自动可用(无需等 GrowthBook 初始化)
|
2. **设置持久化**:`voiceProvider` 存储在 `settings.json`,通过 `/voice` 命令修改,跨会话生效
|
||||||
3. **Keychain 缓存**:`getClaudeAIOAuthTokens()` 首次调用访问 macOS keychain(~20-50ms),后续缓存命中
|
3. **OAuth 独占(Anthropic)**:Anthropic 后端使用 `voice_stream` 端点(claude.ai),仅 OAuth 用户可用
|
||||||
4. **独立于主 feature flag**:`isVoiceGrowthBookEnabled()` 在 feature flag 关闭时短路返回 `false`,不触发任何模块加载
|
4. **豆包无需 OAuth**:豆包后端使用独立凭证文件,不依赖 Anthropic 认证,通过 `isVoiceAvailable()` 放宽门控
|
||||||
|
5. **GrowthBook 负向门控**:`tengu_amber_quartz_disabled` 默认 `false`,新安装自动可用
|
||||||
|
6. **onReady 立即触发**:豆包后端在连接建立后立即触发 `onReady`,避免与 useVoice 音频缓冲的时序死锁(Anthropic 需要等待 WebSocket 握手)
|
||||||
|
7. **finalize() 立即返回**:豆包在录音过程中已返回所有结果,用户抬手时无需等待处理
|
||||||
|
8. **乐观可用性检查**:`isDoubaoAvailableSync()` 在首次调用时返回 `true`,实际导入错误在 `connectDoubaoStream` 中处理
|
||||||
|
9. **optionalDependencies**:`doubaoime-asr` 作为可选依赖,安装失败不影响 Anthropic 后端
|
||||||
|
|
||||||
## 五、使用方式
|
## 五、使用方式
|
||||||
|
|
||||||
@@ -100,26 +204,60 @@ WebSocket 连接到 Anthropic STT 端点
|
|||||||
# 启用 feature
|
# 启用 feature
|
||||||
FEATURE_VOICE_MODE=1 bun run dev
|
FEATURE_VOICE_MODE=1 bun run dev
|
||||||
|
|
||||||
# 在 REPL 中使用
|
# 在 REPL 中使用 Anthropic 后端
|
||||||
# 1. 确保已通过 OAuth 登录(claude.ai 订阅)
|
# 1. 确保已通过 OAuth 登录(claude.ai 订阅)
|
||||||
# 2. 按住空格键说话
|
# 2. 输入 /voice 启用
|
||||||
# 3. 释放空格键等待转录
|
# 3. 按住空格键说话
|
||||||
# 4. 或使用 /voice 命令切换开关
|
# 4. 释放空格键等待转录
|
||||||
|
|
||||||
|
# 在 REPL 中使用豆包 ASR 后端
|
||||||
|
# 1. 确保 doubaoime-asr 已安装(bun add doubaoime-asr)
|
||||||
|
# 2. 配置凭证文件:~/.claude/tts/doubao/credentials.json
|
||||||
|
# 3. 输入 /voice doubao 启用
|
||||||
|
# 4. 按住空格键说话
|
||||||
|
# 5. 释放空格键,转录结果即刻显示
|
||||||
|
|
||||||
|
# 切换后端
|
||||||
|
/voice doubao # 切换到豆包 ASR
|
||||||
|
/voice anthropic # 切换回 Anthropic STT
|
||||||
|
/voice # 关闭语音模式
|
||||||
|
```
|
||||||
|
|
||||||
|
### 豆包凭证配置
|
||||||
|
|
||||||
|
凭证文件路径:`~/.claude/tts/doubao/credentials.json`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceId": "...",
|
||||||
|
"installId": "...",
|
||||||
|
"cdid": "...",
|
||||||
|
"openudid": "...",
|
||||||
|
"clientudid": "...",
|
||||||
|
"token": "..."
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 六、外部依赖
|
## 六、外部依赖
|
||||||
|
|
||||||
| 依赖 | 说明 |
|
| 依赖 | 说明 | 适用后端 |
|
||||||
|------|------|
|
|------|------|----------|
|
||||||
| Anthropic OAuth | claude.ai 订阅登录,非 API key |
|
| Anthropic OAuth | claude.ai 订阅登录,非 API key | Anthropic |
|
||||||
| GrowthBook | `tengu_amber_quartz_disabled` 紧急关闭 |
|
| GrowthBook | `tengu_amber_quartz_disabled` 紧急关闭 | 通用 |
|
||||||
| macOS 原生音频 或 SoX | 音频录制 |
|
| macOS 原生音频 或 SoX | 音频录制 | 通用 |
|
||||||
| Nova 3 STT | 语音转文本模型 |
|
| Nova 3 STT | Anthropic 语音转文本模型 | Anthropic |
|
||||||
|
| doubaoime-asr | 豆包 ASR SDK(optionalDependencies) | 豆包 |
|
||||||
|
| 凭证文件 | `~/.claude/tts/doubao/credentials.json` | 豆包 |
|
||||||
|
|
||||||
## 七、文件索引
|
## 七、文件索引
|
||||||
|
|
||||||
| 文件 | 行数 | 职责 |
|
| 文件 | 职责 |
|
||||||
|------|------|------|
|
|------|------|
|
||||||
| `src/voice/voiceModeEnabled.ts` | 54 | 三层门控逻辑 |
|
| `src/voice/voiceModeEnabled.ts` | 三层门控逻辑 + `isVoiceAvailable()` |
|
||||||
| `src/hooks/useVoice.ts` | — | React hook(录音状态 + WebSocket) |
|
| `src/hooks/useVoice.ts` | React hook(录音状态 + 后端选择 + 连接管理) |
|
||||||
| `src/services/voiceStreamSTT.ts` | — | STT WebSocket 流式传输 |
|
| `src/hooks/useVoiceEnabled.ts` | 语音启用状态 hook(按 provider 决定 OAuth 检查) |
|
||||||
|
| `src/services/voiceStreamSTT.ts` | Anthropic STT WebSocket 流式传输 |
|
||||||
|
| `src/services/doubaoSTT.ts` | 豆包 ASR 适配器(AudioChunkQueue + connectDoubaoStream) |
|
||||||
|
| `src/commands/voice/voice.ts` | `/voice` 命令(开关 + 后端选择) |
|
||||||
|
| `src/commands/voice/index.ts` | 命令注册(去除 availability 限制) |
|
||||||
|
| `src/utils/settings/types.ts` | `voiceProvider` 类型定义 |
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-code-best",
|
"name": "claude-code-best",
|
||||||
"version": "1.9.4",
|
"version": "1.10.2",
|
||||||
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
|
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "claude-code-best <claude-code-best@proton.me>",
|
"author": "claude-code-best <claude-code-best@proton.me>",
|
||||||
@@ -205,5 +205,8 @@
|
|||||||
"xss": "^1.0.15",
|
"xss": "^1.0.15",
|
||||||
"yaml": "^2.8.3",
|
"yaml": "^2.8.3",
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"doubaoime-asr": "^0.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,33 @@
|
|||||||
import { createRequire } from 'node:module'
|
import { createRequire } from 'node:module'
|
||||||
|
import { dirname, resolve, sep } from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
// createRequire works in both Bun and Node.js ESM contexts.
|
// createRequire works in both Bun and Node.js ESM contexts.
|
||||||
// Needed because this package is "type": "module" but uses require() for
|
// Needed because this package is "type": "module" but uses require() for
|
||||||
// loading native .node addons — bare require is not available in Node.js ESM.
|
// loading native .node addons — bare require is not available in Node.js ESM.
|
||||||
const nodeRequire = createRequire(import.meta.url)
|
const nodeRequire = createRequire(import.meta.url)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the "vendor root" directory where native .node binaries live.
|
||||||
|
*
|
||||||
|
* - Dev mode: import.meta.url → packages/audio-capture-napi/src/index.ts
|
||||||
|
* → vendor root = <project>/vendor/
|
||||||
|
* - Bun build: import.meta.url → dist/chunk-xxx.js
|
||||||
|
* → vendor root = <project>/dist/vendor/
|
||||||
|
* - Vite build: import.meta.url → dist/chunks/chunk-xxx.js
|
||||||
|
* → vendor root = <project>/dist/vendor/
|
||||||
|
*/
|
||||||
|
function getVendorRoot(): string {
|
||||||
|
const filePath = fileURLToPath(import.meta.url)
|
||||||
|
const dir = dirname(filePath)
|
||||||
|
const parts = dir.split(sep)
|
||||||
|
const distIdx = parts.lastIndexOf('dist')
|
||||||
|
if (distIdx !== -1) {
|
||||||
|
return parts.slice(0, distIdx + 1).join(sep) + sep + 'vendor'
|
||||||
|
}
|
||||||
|
// Dev mode — go up from packages/audio-capture-napi/src/ to project root
|
||||||
|
return resolve(dir, '..', '..', '..', 'vendor')
|
||||||
|
}
|
||||||
|
|
||||||
type AudioCaptureNapi = {
|
type AudioCaptureNapi = {
|
||||||
startRecording(
|
startRecording(
|
||||||
onData: (data: Buffer) => void,
|
onData: (data: Buffer) => void,
|
||||||
@@ -56,15 +79,18 @@ function loadModule(): AudioCaptureNapi | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Candidates 2-4: npm-install, dev/source, and workspace layouts.
|
// Candidates 2-5: resolved vendor path + relative fallbacks.
|
||||||
// In bundled output, require() resolves relative to cli.js at the package root.
|
// The primary candidate uses getVendorRoot() to find the correct dist root
|
||||||
// In dev, it resolves relative to this file. When loaded from a workspace
|
// regardless of chunk nesting depth. Relative fallbacks cover edge cases.
|
||||||
// package (packages/audio-capture-napi/src/), we need an absolute path fallback.
|
|
||||||
const platformDir = `${process.arch}-${platform}`
|
const platformDir = `${process.arch}-${platform}`
|
||||||
|
const binaryRel = `audio-capture/${platformDir}/audio-capture.node`
|
||||||
|
const vendorRoot = getVendorRoot()
|
||||||
const fallbacks = [
|
const fallbacks = [
|
||||||
`./vendor/audio-capture/${platformDir}/audio-capture.node`,
|
resolve(vendorRoot, binaryRel),
|
||||||
`../audio-capture/${platformDir}/audio-capture.node`,
|
`./vendor/${binaryRel}`,
|
||||||
`${process.cwd()}/vendor/audio-capture/${platformDir}/audio-capture.node`,
|
`../vendor/${binaryRel}`,
|
||||||
|
`../../vendor/${binaryRel}`,
|
||||||
|
`${process.cwd()}/vendor/${binaryRel}`,
|
||||||
]
|
]
|
||||||
for (const p of fallbacks) {
|
for (const p of fallbacks) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -98,22 +98,6 @@ export function storeDeleteToken(token: string): boolean {
|
|||||||
|
|
||||||
// ---------- Environment ----------
|
// ---------- Environment ----------
|
||||||
|
|
||||||
/** Find an active or offline environment by machineName (optionally filtered by workerType).
|
|
||||||
* Includes "offline" so ACP agents can be reused on reconnect. */
|
|
||||||
export function storeFindEnvironmentByMachineName(
|
|
||||||
machineName: string,
|
|
||||||
workerType?: string,
|
|
||||||
): EnvironmentRecord | undefined {
|
|
||||||
for (const rec of environments.values()) {
|
|
||||||
if (rec.machineName === machineName && (rec.status === "active" || rec.status === "offline")) {
|
|
||||||
if (!workerType || rec.workerType === workerType) {
|
|
||||||
return rec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function storeCreateEnvironment(req: {
|
export function storeCreateEnvironment(req: {
|
||||||
secret: string;
|
secret: string;
|
||||||
machineName?: string;
|
machineName?: string;
|
||||||
@@ -126,23 +110,6 @@ export function storeCreateEnvironment(req: {
|
|||||||
username?: string;
|
username?: string;
|
||||||
capabilities?: Record<string, unknown>;
|
capabilities?: Record<string, unknown>;
|
||||||
}): EnvironmentRecord {
|
}): EnvironmentRecord {
|
||||||
// ACP: reuse existing active record by machineName
|
|
||||||
if (req.workerType === "acp" && req.machineName) {
|
|
||||||
const existing = storeFindEnvironmentByMachineName(req.machineName, "acp");
|
|
||||||
if (existing) {
|
|
||||||
Object.assign(existing, {
|
|
||||||
status: "active",
|
|
||||||
lastPollAt: new Date(),
|
|
||||||
updatedAt: new Date(),
|
|
||||||
maxSessions: req.maxSessions ?? existing.maxSessions,
|
|
||||||
bridgeId: req.bridgeId ?? existing.bridgeId,
|
|
||||||
capabilities: req.capabilities ?? existing.capabilities,
|
|
||||||
username: req.username ?? existing.username,
|
|
||||||
});
|
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = `env_${uuid().replace(/-/g, "")}`;
|
const id = `env_${uuid().replace(/-/g, "")}`;
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const record: EnvironmentRecord = {
|
const record: EnvironmentRecord = {
|
||||||
|
|||||||
@@ -30,33 +30,33 @@ export const DEFAULT_BUILD_FEATURES = [
|
|||||||
'BUDDY', // 陪伴宠物角色(Squirtle Waddles)
|
'BUDDY', // 陪伴宠物角色(Squirtle Waddles)
|
||||||
'TRANSCRIPT_CLASSIFIER', // 对话分类器,用于标注会话类型
|
'TRANSCRIPT_CLASSIFIER', // 对话分类器,用于标注会话类型
|
||||||
'BRIDGE_MODE', // Remote Control / Bridge 模式,远程控制会话
|
'BRIDGE_MODE', // Remote Control / Bridge 模式,远程控制会话
|
||||||
'AGENT_TRIGGERS_REMOTE', // Agent 触发远程会话连接
|
'AGENT_TRIGGERS_REMOTE', // sessionIngress 模块级 Map 累积(非 GB 级主因)
|
||||||
'CHICAGO_MCP', // Chicago MCP 集成(内部代号)
|
'CHICAGO_MCP', // Chicago MCP 集成(内部代号)
|
||||||
'VOICE_MODE', // Push-to-Talk 语音输入模式
|
'VOICE_MODE', // Push-to-Talk 语音输入模式
|
||||||
'SHOT_STATS', // 单次请求统计信息收集
|
'SHOT_STATS', // 单次请求统计信息收集
|
||||||
'PROMPT_CACHE_BREAK_DETECTION', // 检测 prompt cache 是否被打破
|
'PROMPT_CACHE_BREAK_DETECTION', // 检测 prompt cache 是否被打破(有 10 条上限,可控)
|
||||||
'TOKEN_BUDGET', // Token 预算管理与控制
|
'TOKEN_BUDGET', // Token 预算管理与控制
|
||||||
// P0: local features
|
// P0: local features
|
||||||
'AGENT_TRIGGERS', // 本地 Agent 触发器(工具调用时启动子代理)
|
'AGENT_TRIGGERS', // 本地 Agent 触发器(工具调用时启动子代理)
|
||||||
'ULTRATHINK', // 超深度思考模式,增加推理链长度
|
'ULTRATHINK', // 超深度思考模式,增加推理链长度
|
||||||
'BUILTIN_EXPLORE_PLAN_AGENTS', // 内置 Explore/Plan 子代理类型
|
'BUILTIN_EXPLORE_PLAN_AGENTS', // 内置 Explore/Plan 子代理类型
|
||||||
'LODESTONE', // 上下文锚点,优化长对话的相关性检索
|
'LODESTONE', // 上下文锚点,优化长对话的相关性检索
|
||||||
'EXTRACT_MEMORIES', // 自动从对话中提取并持久化记忆
|
'EXTRACT_MEMORIES', // 每次 turn 结束 fork 完整消息历史(非 GB 级主因)
|
||||||
'VERIFICATION_AGENT', // 验证代理,任务完成后自动校验结果
|
'VERIFICATION_AGENT', // 任务完成后 fork 完整消息(非 GB 级主因)
|
||||||
'KAIROS_BRIEF', // Kairos 定时摘要(定时汇报当前状态)
|
'KAIROS_BRIEF', // Kairos 定时摘要(定时汇报当前状态)
|
||||||
'AWAY_SUMMARY', // 离线摘要(用户离开后生成总结)
|
'AWAY_SUMMARY', // 离线摘要(用户离开后生成总结)
|
||||||
'ULTRAPLAN', // 超级规划模式,深度分析后生成实施计划
|
'ULTRAPLAN', // 超级规划模式,深度分析后生成实施计划
|
||||||
// 'DAEMON', // 守护进程模式,长驻 supervisor 管理后台 worker(已禁用:内存占用过高)
|
'DAEMON', // 守护进程模式,长驻 supervisor 管理后台 worker(非 GB 级主因)
|
||||||
'ACP', // ACP 代理协议,支持外部 agent 接入
|
'ACP', // ACP 代理协议,支持外部 agent 接入
|
||||||
'WORKFLOW_SCRIPTS', // 工作流脚本(.claude/workflows/ 中的 YAML/MD)
|
'WORKFLOW_SCRIPTS', // 工作流脚本(.claude/workflows/ 中的 YAML/MD)
|
||||||
'HISTORY_SNIP', // 历史消息裁剪,压缩上下文窗口
|
'HISTORY_SNIP', // 历史消息裁剪,压缩上下文窗口
|
||||||
'CONTEXT_COLLAPSE', // 上下文折叠,自动压缩旧消息
|
'CONTEXT_COLLAPSE', // 上下文折叠,自动压缩旧消息
|
||||||
'MONITOR_TOOL', // Monitor 工具,流式监控后台进程输出
|
'MONITOR_TOOL', // Monitor 工具,流式监控后台进程输出
|
||||||
'FORK_SUBAGENT', // Fork 子代理,在隔离上下文中并行执行任务
|
'FORK_SUBAGENT', // Fork 子代理,在隔离上下文中并行执行任务
|
||||||
'UDS_INBOX', // Unix Domain Socket 收件箱,跨会话消息传递
|
'UDS_INBOX', // inbox 数组只增不减(非 GB 级主因)
|
||||||
'KAIROS', // Kairos 定时任务系统核心
|
'KAIROS', // Kairos 定时任务系统核心
|
||||||
'COORDINATOR_MODE', // 协调者模式,多代理团队任务调度
|
// 'COORDINATOR_MODE', // 已禁用:AgentSummary 30s fork 循环,GB 级泄露主因
|
||||||
'LAN_PIPES', // 局域网管道,LAN 设备间通信
|
'LAN_PIPES', // 依赖 UDS_INBOX(已随 UDS_INBOX 恢复)
|
||||||
'BG_SESSIONS', // 后台会话管理(ps/logs/attach/kill)
|
'BG_SESSIONS', // 后台会话管理(ps/logs/attach/kill)
|
||||||
'TEMPLATES', // 模板任务(new/list/reply 子命令)
|
'TEMPLATES', // 模板任务(new/list/reply 子命令)
|
||||||
// 'REVIEW_ARTIFACT', // 代码审查产物(API 请求无响应,待排查 schema 兼容性)
|
// 'REVIEW_ARTIFACT', // 代码审查产物(API 请求无响应,待排查 schema 兼容性)
|
||||||
@@ -68,11 +68,11 @@ export const DEFAULT_BUILD_FEATURES = [
|
|||||||
'DIRECT_CONNECT', // 直连模式(claude server / claude open)
|
'DIRECT_CONNECT', // 直连模式(claude server / claude open)
|
||||||
// Skill search & learning
|
// Skill search & learning
|
||||||
'EXPERIMENTAL_SKILL_SEARCH', // 实验性技能搜索(DiscoverSkills)
|
'EXPERIMENTAL_SKILL_SEARCH', // 实验性技能搜索(DiscoverSkills)
|
||||||
'SKILL_LEARNING', // 技能学习系统,从对话中自动生成/演化技能
|
'SKILL_LEARNING', // projectContext cache 无淘汰机制(非 GB 级主因)
|
||||||
// P3: poor mode
|
// P3: poor mode
|
||||||
'POOR', // 穷鬼模式,跳过 extract_memories/prompt_suggestion 减少消耗
|
'POOR', // 穷鬼模式,跳过 extract_memories/prompt_suggestion 减少消耗
|
||||||
// Team Memory
|
// Team Memory
|
||||||
'TEAMMEM', // 团队记忆,代理队友间共享记忆文件
|
// 'TEAMMEM', // 已禁用:依赖 COORDINATOR_MODE,邮箱文件无限增长
|
||||||
// SSH Remote
|
// SSH Remote
|
||||||
'SSH_REMOTE', // SSH 远程连接,本地 REPL + 远端工具执行
|
'SSH_REMOTE', // SSH 远程连接,本地 REPL + 远端工具执行
|
||||||
]as const;
|
]as const;
|
||||||
|
|||||||
@@ -36,9 +36,13 @@ async function postBuild() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Copy native addon files
|
// Step 2: Copy native addon files
|
||||||
const vendorDir = join(outdir, "vendor", "audio-capture");
|
const audioCaptureDir = join(outdir, "vendor", "audio-capture");
|
||||||
await cp("vendor/audio-capture", vendorDir, { recursive: true } as never);
|
await cp("vendor/audio-capture", audioCaptureDir, { recursive: true } as never);
|
||||||
console.log(`Copied vendor/audio-capture/ → ${vendorDir}/`);
|
console.log(`Copied vendor/audio-capture/ → ${audioCaptureDir}/`);
|
||||||
|
|
||||||
|
const ripgrepDir = join(outdir, "vendor", "ripgrep");
|
||||||
|
await cp("src/utils/vendor/ripgrep", ripgrepDir, { recursive: true } as never);
|
||||||
|
console.log(`Copied src/utils/vendor/ripgrep/ → ${ripgrepDir}/`);
|
||||||
|
|
||||||
// Step 3: Generate dual entry points
|
// Step 3: Generate dual entry points
|
||||||
const cliBun = join(outdir, "cli-bun.js");
|
const cliBun = join(outdir, "cli-bun.js");
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type HookEvent = any;
|
|
||||||
export type ModelUsage = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type AgentColorName = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type HookCallbackMatcher = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type SessionId = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type randomUUID = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type ModelSetting = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type ModelStrings = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type SettingSource = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type resetSettingsCache = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type PluginHookMatcher = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type createSignal = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type StdoutMessage = any;
|
|
||||||
@@ -190,12 +190,10 @@ export async function mcpListHandler(): Promise<void> {
|
|||||||
logEvent('tengu_mcp_list', {})
|
logEvent('tengu_mcp_list', {})
|
||||||
const { servers: configs } = await getAllMcpConfigs()
|
const { servers: configs } = await getAllMcpConfigs()
|
||||||
if (Object.keys(configs).length === 0) {
|
if (Object.keys(configs).length === 0) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(
|
console.log(
|
||||||
'No MCP servers configured. Use `claude mcp add` to add a server.',
|
'No MCP servers configured. Use `claude mcp add` to add a server.',
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log('Checking MCP server health...\n')
|
console.log('Checking MCP server health...\n')
|
||||||
|
|
||||||
// Check servers concurrently
|
// Check servers concurrently
|
||||||
@@ -213,18 +211,14 @@ export async function mcpListHandler(): Promise<void> {
|
|||||||
for (const { name, server, status } of results) {
|
for (const { name, server, status } of results) {
|
||||||
// Intentionally excluding sse-ide servers here since they're internal
|
// Intentionally excluding sse-ide servers here since they're internal
|
||||||
if (server.type === 'sse') {
|
if (server.type === 'sse') {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(`${name}: ${server.url} (SSE) - ${status}`)
|
console.log(`${name}: ${server.url} (SSE) - ${status}`)
|
||||||
} else if (server.type === 'http') {
|
} else if (server.type === 'http') {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(`${name}: ${server.url} (HTTP) - ${status}`)
|
console.log(`${name}: ${server.url} (HTTP) - ${status}`)
|
||||||
} else if (server.type === 'claudeai-proxy') {
|
} else if (server.type === 'claudeai-proxy') {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(`${name}: ${server.url} - ${status}`)
|
console.log(`${name}: ${server.url} - ${status}`)
|
||||||
} else if (!server.type || server.type === 'stdio') {
|
} else if (!server.type || server.type === 'stdio') {
|
||||||
const stdioServer = server as { command: string; args: string[]; type?: string }
|
const stdioServer = server as { command: string; args: string[]; type?: string }
|
||||||
const args = Array.isArray(stdioServer.args) ? stdioServer.args : []
|
const args = Array.isArray(stdioServer.args) ? stdioServer.args : []
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(`${name}: ${stdioServer.command} ${args.join(' ')} - ${status}`)
|
console.log(`${name}: ${stdioServer.command} ${args.join(' ')} - ${status}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,27 +238,20 @@ export async function mcpGetHandler(name: string): Promise<void> {
|
|||||||
cliError(`No MCP server found with name: ${name}`)
|
cliError(`No MCP server found with name: ${name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(`${name}:`)
|
console.log(`${name}:`)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Scope: ${getScopeLabel(server.scope)}`)
|
console.log(` Scope: ${getScopeLabel(server.scope)}`)
|
||||||
|
|
||||||
// Check server health
|
// Check server health
|
||||||
const status = await checkMcpServerHealth(name, server)
|
const status = await checkMcpServerHealth(name, server)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Status: ${status}`)
|
console.log(` Status: ${status}`)
|
||||||
|
|
||||||
// Intentionally excluding sse-ide servers here since they're internal
|
// Intentionally excluding sse-ide servers here since they're internal
|
||||||
if (server.type === 'sse') {
|
if (server.type === 'sse') {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Type: sse`)
|
console.log(` Type: sse`)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` URL: ${server.url}`)
|
console.log(` URL: ${server.url}`)
|
||||||
if (server.headers) {
|
if (server.headers) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(' Headers:')
|
console.log(' Headers:')
|
||||||
for (const [key, value] of Object.entries(server.headers)) {
|
for (const [key, value] of Object.entries(server.headers)) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` ${key}: ${value}`)
|
console.log(` ${key}: ${value}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,19 +264,14 @@ export async function mcpGetHandler(name: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
if (server.oauth.callbackPort)
|
if (server.oauth.callbackPort)
|
||||||
parts.push(`callback_port ${server.oauth.callbackPort}`)
|
parts.push(`callback_port ${server.oauth.callbackPort}`)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` OAuth: ${parts.join(', ')}`)
|
console.log(` OAuth: ${parts.join(', ')}`)
|
||||||
}
|
}
|
||||||
} else if (server.type === 'http') {
|
} else if (server.type === 'http') {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Type: http`)
|
console.log(` Type: http`)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` URL: ${server.url}`)
|
console.log(` URL: ${server.url}`)
|
||||||
if (server.headers) {
|
if (server.headers) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(' Headers:')
|
console.log(' Headers:')
|
||||||
for (const [key, value] of Object.entries(server.headers)) {
|
for (const [key, value] of Object.entries(server.headers)) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` ${key}: ${value}`)
|
console.log(` ${key}: ${value}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,27 +284,20 @@ export async function mcpGetHandler(name: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
if (server.oauth.callbackPort)
|
if (server.oauth.callbackPort)
|
||||||
parts.push(`callback_port ${server.oauth.callbackPort}`)
|
parts.push(`callback_port ${server.oauth.callbackPort}`)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` OAuth: ${parts.join(', ')}`)
|
console.log(` OAuth: ${parts.join(', ')}`)
|
||||||
}
|
}
|
||||||
} else if (server.type === 'stdio') {
|
} else if (server.type === 'stdio') {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Type: stdio`)
|
console.log(` Type: stdio`)
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Command: ${server.command}`)
|
console.log(` Command: ${server.command}`)
|
||||||
const args = Array.isArray(server.args) ? server.args : []
|
const args = Array.isArray(server.args) ? server.args : []
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` Args: ${args.join(' ')}`)
|
console.log(` Args: ${args.join(' ')}`)
|
||||||
if (server.env) {
|
if (server.env) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(' Environment:')
|
console.log(' Environment:')
|
||||||
for (const [key, value] of Object.entries(server.env)) {
|
for (const [key, value] of Object.entries(server.env)) {
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(` ${key}=${value}`)
|
console.log(` ${key}=${value}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
|
||||||
console.log(
|
console.log(
|
||||||
`\nTo remove this server, run: claude mcp remove "${name}" -s ${server.scope}`,
|
`\nTo remove this server, run: claude mcp remove "${name}" -s ${server.scope}`,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type ask = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type installOAuthTokens = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type RemoteIO = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type StructuredIO = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type collectContextData = any;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type SDKStatus = any;
|
|
||||||
export type ModelInfo = any;
|
|
||||||
export type SDKMessage = any;
|
|
||||||
export type SDKUserMessage = any;
|
|
||||||
export type SDKUserMessageReplay = any;
|
|
||||||
export type PermissionResult = any;
|
|
||||||
export type McpServerConfigForProcessTransport = any;
|
|
||||||
export type McpServerStatus = any;
|
|
||||||
export type RewindFilesResult = any;
|
|
||||||
export type HookEvent = any;
|
|
||||||
export type HookInput = any;
|
|
||||||
export type HookJSONOutput = any;
|
|
||||||
export type PermissionUpdate = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type SDKControlElicitationResponseSchema = any;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type StdoutMessage = any;
|
|
||||||
export type SDKControlInitializeRequest = any;
|
|
||||||
export type SDKControlInitializeResponse = any;
|
|
||||||
export type SDKControlRequest = any;
|
|
||||||
export type SDKControlResponse = any;
|
|
||||||
export type SDKControlMcpSetServersResponse = any;
|
|
||||||
export type SDKControlReloadPluginsResponse = any;
|
|
||||||
export type StdinMessage = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type CanUseToolFn = any;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type tryGenerateSuggestion = any;
|
|
||||||
export type logSuggestionOutcome = any;
|
|
||||||
export type logSuggestionSuppressed = any;
|
|
||||||
export type PromptVariant = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getFeatureValue_CACHED_MAY_BE_STALE = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type logEvent = any;
|
|
||||||
export type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type isQualifiedForGrove = any;
|
|
||||||
export type checkGroveForNonInteractive = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type EMPTY_USAGE = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type statusListeners = any;
|
|
||||||
export type ClaudeAILimits = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type performMCPOAuthFlow = any;
|
|
||||||
export type revokeServerTokens = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type isChannelAllowlisted = any;
|
|
||||||
export type isChannelsEnabled = any;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type ChannelMessageNotificationSchema = any;
|
|
||||||
export type gateChannelServer = any;
|
|
||||||
export type wrapChannelMessage = any;
|
|
||||||
export type findChannelEntry = any;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type setupSdkMcpClients = any;
|
|
||||||
export type connectToServer = any;
|
|
||||||
export type clearServerCache = any;
|
|
||||||
export type fetchToolsForClient = any;
|
|
||||||
export type areMcpConfigsEqual = any;
|
|
||||||
export type reconnectMcpServerImpl = any;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type filterMcpServersByPolicy = any;
|
|
||||||
export type getMcpConfigByName = any;
|
|
||||||
export type isMcpServerDisabled = any;
|
|
||||||
export type setMcpServerEnabled = any;
|
|
||||||
export type getAllMcpConfigs = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type runElicitationHooks = any;
|
|
||||||
export type runElicitationResultHooks = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getMcpPrefix = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type MCPServerConnection = any;
|
|
||||||
export type McpSdkServerConfig = any;
|
|
||||||
export type ScopedMcpServerConfig = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type commandBelongsToServer = any;
|
|
||||||
export type filterToolsByServer = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type setupVscodeSdkMcp = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type OAuthService = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type isPolicyAllowed = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type waitForRemoteManagedSettingsToLoad = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type downloadUserSettings = any;
|
|
||||||
export type redownloadUserSettings = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type AppState = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type externalMetadataToAppState = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type assembleToolPool = any;
|
|
||||||
export type filterToolsByDenyRules = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type createAbortController = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type uniq = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getAccountInformation = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getLatestVersion = any;
|
|
||||||
export type InstallStatus = any;
|
|
||||||
export type installGlobalPackage = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type AwsAuthStatusManager = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type modelSupportsAutoMode = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type registerCleanup = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type createCombinedAbortSignal = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type notifyCommandLifecycle = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type incrementPromptCount = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type regenerateCompletionCache = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getGlobalConfig = any;
|
|
||||||
export type InstallMethod = any;
|
|
||||||
export type saveGlobalConfig = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type loadConversationForResume = any;
|
|
||||||
export type TurnInterruptionState = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getCwd = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type logForDebugging = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type logForDiagnosticsNoPII = any;
|
|
||||||
export type withDiagnosticsTiming = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getDoctorDiagnostic = any;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type modelSupportsEffort = any;
|
|
||||||
export type modelSupportsMaxEffort = any;
|
|
||||||
export type EFFORT_LEVELS = any;
|
|
||||||
export type resolveAppliedEffort = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type AbortError = any;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type isFastModeAvailable = any;
|
|
||||||
export type isFastModeEnabled = any;
|
|
||||||
export type isFastModeSupportedByModel = any;
|
|
||||||
export type getFastModeState = any;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type fileHistoryRewind = any;
|
|
||||||
export type fileHistoryCanRestore = any;
|
|
||||||
export type fileHistoryEnabled = any;
|
|
||||||
export type fileHistoryGetDiffStats = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type executeFilePersistence = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type createFileStateCacheWithSizeLimit = any;
|
|
||||||
export type mergeFileStateCaches = any;
|
|
||||||
export type READ_FILE_STATE_CACHE_SIZE = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getLastCacheSafeParams = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type fromArray = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type gracefulShutdown = any;
|
|
||||||
export type gracefulShutdownSync = any;
|
|
||||||
export type isShuttingDown = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type headlessProfilerStartTurn = any;
|
|
||||||
export type headlessProfilerCheckpoint = any;
|
|
||||||
export type logHeadlessProfilerTurn = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type executeNotificationHooks = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type finalizePendingAsyncHooks = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type registerHookEventHandler = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type createIdleTimeoutManager = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type safeParseJSON = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type installOrUpdateClaudePackage = any;
|
|
||||||
export type localInstallationExists = any;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getInMemoryErrors = any;
|
|
||||||
export type logError = any;
|
|
||||||
export type logMCPDebug = any;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type dequeue = any;
|
|
||||||
export type dequeueAllMatching = any;
|
|
||||||
export type enqueue = any;
|
|
||||||
export type hasCommandsInQueue = any;
|
|
||||||
export type peek = any;
|
|
||||||
export type subscribeToCommandQueue = any;
|
|
||||||
export type getCommandsByMaxPriority = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type createModelSwitchBreadcrumbs = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type toInternalMessages = any;
|
|
||||||
export type toSDKRateLimitInfo = any;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getDefaultMainLoopModel = any;
|
|
||||||
export type getMainLoopModel = any;
|
|
||||||
export type modelDisplayString = any;
|
|
||||||
export type parseUserSpecifiedModel = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getModelOptions = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type ensureModelStringsInitialized = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getAPIProvider = any;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type installLatest = any;
|
|
||||||
export type removeInstalledSymlink = any;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// Auto-generated type stub — replace with real implementation
|
|
||||||
export type getPackageManager = any;
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user