@wu529778790/open-im 1.6.7 → 1.6.8-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  [中文](./README.zh-CN.md)
4
4
 
5
- Multi-platform IM bridge for AI CLI tools. Connect Telegram, Feishu, WeCom, DingTalk, QQ, and WeChat to Claude Code, Codex, Cursor, and CodeBuddy so you can use your coding assistant remotely from a phone or chat window.
5
+ Multi-platform IM bridge for AI CLI tools. Connect Telegram, Feishu, WeCom, DingTalk, QQ, and WeChat to Claude Code, Codex, and CodeBuddy so you can use your coding assistant remotely from a phone or chat window.
6
6
 
7
7
  ## Features
8
8
 
9
9
  - Multi-platform support: Telegram, Feishu, WeCom, DingTalk, QQ, and WeChat (experimental), with multiple platforms enabled at the same time
10
- - Multiple AI tools: Claude, Codex, Cursor, and CodeBuddy
10
+ - Multiple AI tools: Claude, Codex, and CodeBuddy
11
11
  - Per-platform AI routing: each IM platform can use a different AI tool, with `aiCommand` as the global default and `platforms.<name>.aiCommand` as the override
12
12
  - Streaming replies: relay AI output and tool execution progress in real time (DingTalk streaming is not fully supported yet)
13
13
  - Graphical configuration page and CLI setup flow
@@ -84,7 +84,7 @@ Example:
84
84
  },
85
85
  "feishu": {
86
86
  "enabled": true,
87
- "aiCommand": "cursor"
87
+ "aiCommand": "codex"
88
88
  },
89
89
  "qq": {
90
90
  "enabled": true,
@@ -94,7 +94,7 @@ Example:
94
94
  }
95
95
  ```
96
96
 
97
- In that setup, Telegram uses Codex, Feishu uses Cursor, QQ uses CodeBuddy, and any platform without its own `aiCommand` continues using Claude.
97
+ In that setup, Telegram uses Codex, Feishu uses Codex, QQ uses CodeBuddy, and any platform without its own `aiCommand` continues using Claude.
98
98
 
99
99
  ### Claude
100
100
 
@@ -151,10 +151,6 @@ The following is valid JSON and can be saved directly as `~/.open-im/config.json
151
151
  "skipPermissions": true,
152
152
  "timeoutMs": 600000
153
153
  },
154
- "cursor": {
155
- "cliPath": "agent",
156
- "skipPermissions": true
157
- },
158
154
  "codex": {
159
155
  "cliPath": "codex",
160
156
  "workDir": "D:/coding/open-im",
@@ -177,7 +173,7 @@ The following is valid JSON and can be saved directly as `~/.open-im/config.json
177
173
  },
178
174
  "feishu": {
179
175
  "enabled": false,
180
- "aiCommand": "cursor",
176
+ "aiCommand": "codex",
181
177
  "allowedUserIds": [],
182
178
  "appId": "YOUR_FEISHU_APP_ID",
183
179
  "appSecret": "YOUR_FEISHU_APP_SECRET"
@@ -219,14 +215,13 @@ The following is valid JSON and can be saved directly as `~/.open-im/config.json
219
215
 
220
216
  | Variable | Description |
221
217
  | ---- | ---- |
222
- | `AI_COMMAND` | Select `claude`, `codex`, `cursor`, or `codebuddy` |
218
+ | `AI_COMMAND` | Select `claude`, `codex`, or `codebuddy` |
223
219
  | `CLAUDE_WORK_DIR` | Default session working directory |
224
220
  | `LOG_DIR` | Log directory |
225
221
  | `LOG_LEVEL` | Log level |
226
222
  | `HOOK_PORT` | Permission service port |
227
223
  | `CODEX_PROXY` | Proxy used by Codex to access `chatgpt.com` |
228
224
  | `OPENAI_API_KEY` | Codex API key, can replace `codex login` |
229
- | `CURSOR_API_KEY` | Cursor API key, can replace `agent login` |
230
225
  | `CODEBUDDY_CLI_PATH` | Override CodeBuddy CLI path |
231
226
  | `CODEBUDDY_TIMEOUT_MS` | Override CodeBuddy timeout |
232
227
  | `CODEBUDDY_SKIP_PERMISSIONS` | Override CodeBuddy skip-permissions behavior |
@@ -304,8 +299,6 @@ DingTalk AI card templates are already compatible with the official "Search Resu
304
299
 
305
300
  **DingTalk has no streaming updates**: when `prepare` fails, the app falls back to plain text replies. In custom bot or regular group scenarios, neither the AI assistant API nor the interactive card API is available, so only single plain text replies are supported.
306
301
 
307
- **Cursor shows `Authentication required`**: run `agent login` first, or set `CURSOR_API_KEY` in `env`.
308
-
309
302
  **Codex shows `stream disconnected` or `error sending request`**: `chatgpt.com` is not reachable. Configure `tools.codex.proxy` or set `CODEX_PROXY`.
310
303
 
311
304
  **CodeBuddy prompts for login**: run `codebuddy login` first. `open-im` does not read CodeBuddy login state from `~/.open-im/config.json`.
package/README.zh-CN.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  [English](./README.md)
4
4
 
5
- 多平台 IM 桥接工具,把 Telegram、飞书、企业微信、钉钉、QQ、微信接到 AI CLI 工具(Claude Code、Codex、Cursor、CodeBuddy),方便在手机或聊天窗口里远程使用 AI 编程助手。
5
+ 多平台 IM 桥接工具,把 Telegram、飞书、企业微信、钉钉、QQ、微信接到 AI CLI 工具(Claude Code、Codex、CodeBuddy),方便在手机或聊天窗口里远程使用 AI 编程助手。
6
6
 
7
7
  ## 功能特性
8
8
 
9
9
  - 多平台:支持 Telegram、飞书、企业微信、钉钉、QQ、微信(测试中),可同时启用
10
- - 多 AI 工具:支持 Claude、Codex、Cursor、CodeBuddy
10
+ - 多 AI 工具:支持 Claude、Codex、CodeBuddy
11
11
  - 按平台分配 AI:根级 `aiCommand` 作为默认值,`platforms.<name>.aiCommand` 可为不同 IM 单独指定 AI 工具
12
12
  - 流式输出:实时回传 AI 回复与工具执行进度(目前钉钉暂未实现流式传输)
13
13
  - 图形化配置页面 / CLI 配置引导
@@ -84,7 +84,7 @@ open-im start
84
84
  },
85
85
  "feishu": {
86
86
  "enabled": true,
87
- "aiCommand": "cursor"
87
+ "aiCommand": "codex"
88
88
  },
89
89
  "qq": {
90
90
  "enabled": true,
@@ -94,7 +94,7 @@ open-im start
94
94
  }
95
95
  ```
96
96
 
97
- 这个配置下,Telegram 会走 Codex,飞书会走 Cursor,QQ 会走 CodeBuddy,其他未单独指定 `aiCommand` 的平台仍然使用 Claude。
97
+ 这个配置下,Telegram 会走 Codex,飞书会走 Codex,QQ 会走 CodeBuddy,其他未单独指定 `aiCommand` 的平台仍然使用 Claude。
98
98
 
99
99
  ### Claude
100
100
 
@@ -151,10 +151,6 @@ codebuddy login
151
151
  "skipPermissions": true,
152
152
  "timeoutMs": 600000
153
153
  },
154
- "cursor": {
155
- "cliPath": "agent",
156
- "skipPermissions": true
157
- },
158
154
  "codex": {
159
155
  "cliPath": "codex",
160
156
  "workDir": "D:/coding/open-im",
@@ -177,7 +173,7 @@ codebuddy login
177
173
  },
178
174
  "feishu": {
179
175
  "enabled": false,
180
- "aiCommand": "cursor",
176
+ "aiCommand": "codex",
181
177
  "allowedUserIds": [],
182
178
  "appId": "YOUR_FEISHU_APP_ID",
183
179
  "appSecret": "YOUR_FEISHU_APP_SECRET"
@@ -219,14 +215,13 @@ codebuddy login
219
215
 
220
216
  | 变量 | 说明 |
221
217
  | ---- | ---- |
222
- | `AI_COMMAND` | 选择 `claude` / `codex` / `cursor` / `codebuddy` |
218
+ | `AI_COMMAND` | 选择 `claude` / `codex` / `codebuddy` |
223
219
  | `CLAUDE_WORK_DIR` | 默认会话目录 |
224
220
  | `LOG_DIR` | 日志目录 |
225
221
  | `LOG_LEVEL` | 日志级别 |
226
222
  | `HOOK_PORT` | 权限服务端口 |
227
223
  | `CODEX_PROXY` | Codex 访问 `chatgpt.com` 的代理 |
228
224
  | `OPENAI_API_KEY` | Codex API Key,可替代 `codex login` |
229
- | `CURSOR_API_KEY` | Cursor API Key,可替代 `agent login` |
230
225
  | `CODEBUDDY_CLI_PATH` | 覆盖 CodeBuddy CLI 路径 |
231
226
  | `CODEBUDDY_TIMEOUT_MS` | 覆盖 CodeBuddy 超时 |
232
227
  | `CODEBUDDY_SKIP_PERMISSIONS` | 覆盖 CodeBuddy 的跳过权限确认行为 |
@@ -304,8 +299,6 @@ codebuddy login
304
299
 
305
300
  **钉钉没有流式更新**:`prepare` 失败时 fallback 为普通文本回复。自定义机器人/普通群场景下,AI 助理和互动卡片 API 均不可用,仅支持单条文本回复。
306
301
 
307
- **Cursor 报 `Authentication required`**:先执行 `agent login`,或在 `env` 中设置 `CURSOR_API_KEY`。
308
-
309
302
  **Codex 报 `stream disconnected` / `error sending request`**:无法访问 `chatgpt.com`,请配置 `tools.codex.proxy` 或环境变量 `CODEX_PROXY`。
310
303
 
311
304
  **CodeBuddy 提示需要登录**:先执行 `codebuddy login`。`open-im` 不会从 `~/.open-im/config.json` 读取 CodeBuddy 的登录态。
@@ -1,7 +1,6 @@
1
1
  import { getConfiguredAiCommands } from '../config.js';
2
2
  import { ClaudeAdapter } from './claude-adapter.js';
3
3
  import { ClaudeSDKAdapter } from './claude-sdk-adapter.js';
4
- import { CursorAdapter } from './cursor-adapter.js';
5
4
  import { CodexAdapter } from './codex-adapter.js';
6
5
  import { CodeBuddyAdapter } from './codebuddy-adapter.js';
7
6
  const adapters = new Map();
@@ -22,11 +21,6 @@ export function initAdapters(config) {
22
21
  }
23
22
  continue;
24
23
  }
25
- if (aiCommand === 'cursor') {
26
- console.log('Cursor CLI adapter enabled');
27
- adapters.set('cursor', new CursorAdapter(config.cursorCliPath));
28
- continue;
29
- }
30
24
  if (aiCommand === 'codex') {
31
25
  console.log('Codex CLI adapter enabled');
32
26
  adapters.set('codex', new CodexAdapter(config.codexCliPath));
@@ -172,13 +172,11 @@ export class CommandHandler {
172
172
  return true;
173
173
  }
174
174
  getAiVersion(aiCommand) {
175
- const cmd = aiCommand === 'cursor'
176
- ? this.deps.config.cursorCliPath
177
- : aiCommand === 'codex'
178
- ? this.deps.config.codexCliPath
179
- : aiCommand === 'codebuddy'
180
- ? this.deps.config.codebuddyCliPath
181
- : this.deps.config.claudeCliPath;
175
+ const cmd = aiCommand === 'codex'
176
+ ? this.deps.config.codexCliPath
177
+ : aiCommand === 'codebuddy'
178
+ ? this.deps.config.codebuddyCliPath
179
+ : this.deps.config.claudeCliPath;
182
180
  return new Promise((resolve) => {
183
181
  execFile(cmd, ['--version'], { timeout: 5000 }, (err, stdout) => {
184
182
  resolve(err ? '未知' : (stdout?.toString().trim() || '未知'));
@@ -85,7 +85,6 @@ export declare const PAGE_TEXTS: {
85
85
  readonly aiTool: "Default AI tool";
86
86
  readonly workDir: "Default work directory";
87
87
  readonly claudeCli: "Claude CLI path";
88
- readonly cursorCli: "Cursor CLI path";
89
88
  readonly codexCli: "Codex CLI path";
90
89
  readonly codebuddyCli: "CodeBuddy CLI path";
91
90
  readonly codexProxy: "Codex proxy";
@@ -96,10 +95,7 @@ export declare const PAGE_TEXTS: {
96
95
  readonly claudeModel: "ANTHROPIC_MODEL";
97
96
  readonly claudeProxy: "Proxy (optional)";
98
97
  readonly codexTimeout: "Codex timeout (ms)";
99
- readonly cursorTimeout: "Cursor timeout (ms)";
100
- readonly cursorModel: "Model (e.g. auto)";
101
98
  readonly codebuddyTimeout: "CodeBuddy timeout (ms)";
102
- readonly cursorProxy: "Proxy (optional)";
103
99
  readonly hookPort: "Hook port";
104
100
  readonly logLevel: "Log level";
105
101
  readonly logLevelDefault: "default (app default)";
@@ -206,7 +202,6 @@ export declare const PAGE_TEXTS: {
206
202
  readonly aiTool: "默认 AI 工具";
207
203
  readonly workDir: "默认工作目录";
208
204
  readonly claudeCli: "Claude CLI 路径";
209
- readonly cursorCli: "Cursor CLI 路径";
210
205
  readonly codexCli: "Codex CLI 路径";
211
206
  readonly codebuddyCli: "CodeBuddy CLI 路径";
212
207
  readonly codexProxy: "Codex 代理";
@@ -217,10 +212,7 @@ export declare const PAGE_TEXTS: {
217
212
  readonly claudeModel: "ANTHROPIC_MODEL";
218
213
  readonly claudeProxy: "代理(可选)";
219
214
  readonly codexTimeout: "Codex 超时(毫秒)";
220
- readonly cursorTimeout: "Cursor 超时(毫秒)";
221
- readonly cursorModel: "模型(如 auto)";
222
215
  readonly codebuddyTimeout: "CodeBuddy 超时(毫秒)";
223
- readonly cursorProxy: "代理(可选)";
224
216
  readonly hookPort: "Hook 端口";
225
217
  readonly logLevel: "日志级别";
226
218
  readonly logLevelDefault: "default(程序默认)";
@@ -85,7 +85,6 @@ export const PAGE_TEXTS = {
85
85
  aiTool: "Default AI tool",
86
86
  workDir: "Default work directory",
87
87
  claudeCli: "Claude CLI path",
88
- cursorCli: "Cursor CLI path",
89
88
  codexCli: "Codex CLI path",
90
89
  codebuddyCli: "CodeBuddy CLI path",
91
90
  codexProxy: "Codex proxy",
@@ -96,10 +95,7 @@ export const PAGE_TEXTS = {
96
95
  claudeModel: "ANTHROPIC_MODEL",
97
96
  claudeProxy: "Proxy (optional)",
98
97
  codexTimeout: "Codex timeout (ms)",
99
- cursorTimeout: "Cursor timeout (ms)",
100
- cursorModel: "Model (e.g. auto)",
101
98
  codebuddyTimeout: "CodeBuddy timeout (ms)",
102
- cursorProxy: "Proxy (optional)",
103
99
  hookPort: "Hook port",
104
100
  logLevel: "Log level",
105
101
  logLevelDefault: "default (app default)",
@@ -206,7 +202,6 @@ export const PAGE_TEXTS = {
206
202
  aiTool: "\u9ed8\u8ba4 AI \u5de5\u5177",
207
203
  workDir: "\u9ed8\u8ba4\u5de5\u4f5c\u76ee\u5f55",
208
204
  claudeCli: "Claude CLI \u8def\u5f84",
209
- cursorCli: "Cursor CLI \u8def\u5f84",
210
205
  codexCli: "Codex CLI \u8def\u5f84",
211
206
  codebuddyCli: "CodeBuddy CLI \u8def\u5f84",
212
207
  codexProxy: "Codex \u4ee3\u7406",
@@ -217,10 +212,7 @@ export const PAGE_TEXTS = {
217
212
  claudeModel: "ANTHROPIC_MODEL",
218
213
  claudeProxy: "\u4ee3\u7406\uff08\u53ef\u9009\uff09",
219
214
  codexTimeout: "Codex \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
220
- cursorTimeout: "Cursor \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
221
- cursorModel: "模型(如 auto)",
222
215
  codebuddyTimeout: "CodeBuddy \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
223
- cursorProxy: "\u4ee3\u7406\uff08\u53ef\u9009\uff09",
224
216
  hookPort: "Hook \u7aef\u53e3",
225
217
  logLevel: "\u65e5\u5fd7\u7ea7\u522b",
226
218
  logLevelDefault: "default\uff08\u7a0b\u5e8f\u9ed8\u8ba4\uff09",
@@ -6,11 +6,11 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
6
6
  { key: "dingtalk", label: "DingTalk", fields: ["aiCommand", "clientId", "clientSecret", "cardTemplateId", "allowedUserIds"], testFields: ["clientId", "clientSecret"], requiredFields: ["clientId", "clientSecret"] },
7
7
  ];
8
8
  const platformKeys = platformDefinitions.map((platform) => platform.key);
9
- const aiTools = ["claude", "codex", "cursor", "codebuddy"];
9
+ const aiTools = ["claude", "codex", "codebuddy"];
10
10
  const STORAGE_KEY_LANG = "open-im-web-lang";
11
11
  const STORAGE_KEY_DARK_MODE = "open-im-web-dark-mode";
12
12
  const POLLING_INTERVAL = 10000;
13
- const toolLabels = { claude: "Claude", codex: "Codex", cursor: "Cursor", codebuddy: "CodeBuddy" };
13
+ const toolLabels = { claude: "Claude", codex: "Codex", codebuddy: "CodeBuddy" };
14
14
 
15
15
  // Dark mode handling
16
16
  const getSystemDarkMode = () => window.matchMedia("(prefers-color-scheme: dark)").matches;
@@ -209,10 +209,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
209
209
  { id: "ai-codexCliPath-label", key: "codexCli" },
210
210
  { id: "ai-codexTimeoutMs-label", key: "codexTimeout" },
211
211
  { id: "ai-codexProxy-label", key: "codexProxy" },
212
- { id: "ai-cursorCliPath-label", key: "cursorCli" },
213
- { id: "ai-cursorModel-label", key: "cursorModel" },
214
- { id: "ai-cursorTimeoutMs-label", key: "cursorTimeout" },
215
- { id: "ai-cursorProxy-label", key: "cursorProxy" },
216
212
  { id: "ai-codebuddyCliPath-label", key: "codebuddyCli" },
217
213
  { id: "ai-codebuddyTimeoutMs-label", key: "codebuddyTimeout" },
218
214
  { id: "ai-hookPort-label", key: "hookPort" },
@@ -424,10 +420,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
424
420
  { id: "ai-codexCliPath", key: "codexCliPath" },
425
421
  { id: "ai-codexTimeoutMs", key: "codexTimeoutMs" },
426
422
  { id: "ai-codexProxy", key: "codexProxy" },
427
- { id: "ai-cursorCliPath", key: "cursorCliPath" },
428
- { id: "ai-cursorModel", key: "cursorModel" },
429
- { id: "ai-cursorTimeoutMs", key: "cursorTimeoutMs" },
430
- { id: "ai-cursorProxy", key: "cursorProxy" },
431
423
  { id: "ai-codebuddyCliPath", key: "codebuddyCliPath" },
432
424
  { id: "ai-codebuddyTimeoutMs", key: "codebuddyTimeoutMs" },
433
425
  { id: "ai-hookPort", key: "hookPort" },
@@ -672,10 +664,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
672
664
  codebuddyTimeoutMs: getNumber("ai-codebuddyTimeoutMs"),
673
665
  codexCliPath: getValue("ai-codexCliPath"),
674
666
  codexProxy: getValue("ai-codexProxy"),
675
- cursorCliPath: getValue("ai-cursorCliPath"),
676
- cursorModel: getValue("ai-cursorModel"),
677
- cursorTimeoutMs: getNumber("ai-cursorTimeoutMs"),
678
- cursorProxy: getValue("ai-cursorProxy"),
679
667
  codebuddyCliPath: getValue("ai-codebuddyCliPath"),
680
668
  hookPort: getNumber("ai-hookPort"),
681
669
  logLevel: getValue("ai-logLevel"),
@@ -875,7 +875,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
875
875
  <option value="">(default)</option>
876
876
  <option value="claude">claude</option>
877
877
  <option value="codex">codex</option>
878
- <option value="cursor">cursor</option>
879
878
  <option value="codebuddy">codebuddy</option>
880
879
  </select>
881
880
  </div>
@@ -918,7 +917,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
918
917
  <option value="">(default)</option>
919
918
  <option value="claude">claude</option>
920
919
  <option value="codex">codex</option>
921
- <option value="cursor">cursor</option>
922
920
  <option value="codebuddy">codebuddy</option>
923
921
  </select>
924
922
  </div>
@@ -960,7 +958,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
960
958
  <option value="">(default)</option>
961
959
  <option value="claude">claude</option>
962
960
  <option value="codex">codex</option>
963
- <option value="cursor">cursor</option>
964
961
  <option value="codebuddy">codebuddy</option>
965
962
  </select>
966
963
  </div>
@@ -1002,7 +999,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1002
999
  <option value="">(default)</option>
1003
1000
  <option value="claude">claude</option>
1004
1001
  <option value="codex">codex</option>
1005
- <option value="cursor">cursor</option>
1006
1002
  <option value="codebuddy">codebuddy</option>
1007
1003
  </select>
1008
1004
  </div>
@@ -1048,7 +1044,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1048
1044
  <option value="">(default)</option>
1049
1045
  <option value="claude">claude</option>
1050
1046
  <option value="codex">codex</option>
1051
- <option value="cursor">cursor</option>
1052
1047
  <option value="codebuddy">codebuddy</option>
1053
1048
  </select>
1054
1049
  </div>
@@ -1084,7 +1079,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1084
1079
  <select id="ai-aiCommand" class="form-select">
1085
1080
  <option value="claude">claude</option>
1086
1081
  <option value="codex">codex</option>
1087
- <option value="cursor">cursor</option>
1088
1082
  <option value="codebuddy">codebuddy</option>
1089
1083
  </select>
1090
1084
  </div>
@@ -1114,7 +1108,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1114
1108
  <div class="tabs" id="aiToolSwitcher">
1115
1109
  <button class="tab active" data-tool="claude" type="button">Claude</button>
1116
1110
  <button class="tab" data-tool="codex" type="button">Codex</button>
1117
- <button class="tab" data-tool="cursor" type="button">Cursor</button>
1118
1111
  <button class="tab" data-tool="codebuddy" type="button">CodeBuddy</button>
1119
1112
  </div>
1120
1113
  </div>
@@ -1170,27 +1163,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1170
1163
  </div>
1171
1164
  </div>
1172
1165
 
1173
- <div id="ai-tool-cursor" class="ai-tool-panel" data-tool-panel="cursor">
1174
- <div class="form-group">
1175
- <label class="form-label" id="ai-cursorCliPath-label">CLI Path</label>
1176
- <input id="ai-cursorCliPath" class="form-input mono" type="text" />
1177
- </div>
1178
- <div class="form-group">
1179
- <label class="form-label" id="ai-cursorModel-label">Model</label>
1180
- <input id="ai-cursorModel" class="form-input mono" type="text" placeholder="auto" />
1181
- <div class="form-hint" id="ai-cursorModel-hint">如 auto、Claude 4 Sonnet 等,agent --list-models 查看</div>
1182
- </div>
1183
- <div class="form-group">
1184
- <label class="form-label" id="ai-cursorTimeoutMs-label">Timeout (ms)</label>
1185
- <input id="ai-cursorTimeoutMs" class="form-input" type="number" min="1" />
1186
- </div>
1187
- <div class="form-group">
1188
- <label class="form-label" id="ai-cursorProxy-label">Proxy (optional)</label>
1189
- <input id="ai-cursorProxy" class="form-input mono" type="text" />
1190
- <div class="form-hint" id="ai-cursorProxy-hint">HTTP proxy for API requests (e.g., http://127.0.0.1:7890)</div>
1191
- </div>
1192
- </div>
1193
-
1194
1166
  <div id="ai-tool-codebuddy" class="ai-tool-panel" data-tool-panel="codebuddy">
1195
1167
  <div class="form-group">
1196
1168
  <label class="form-label" id="ai-codebuddyCliPath-label">CLI Path</label>
@@ -38,7 +38,7 @@ describe("config web page assembly", () => {
38
38
  const toolListMatch = PAGE_SCRIPT.match(/const aiTools = \[([^\]]+)\]/);
39
39
  expect(toolListMatch).toBeTruthy();
40
40
  const tools = Array.from((toolListMatch?.[1] ?? "").matchAll(/"([^"]+)"/g), (match) => match[1]);
41
- expect(tools).toEqual(["claude", "codex", "cursor", "codebuddy"]);
41
+ expect(tools).toEqual(["claude", "codex", "codebuddy"]);
42
42
  for (const tool of tools) {
43
43
  expect(PAGE_HTML).toContain(`data-tool="${tool}"`);
44
44
  expect(PAGE_HTML).toContain(`data-tool-panel="${tool}"`);
@@ -143,14 +143,10 @@ function buildInitialPayload(file) {
143
143
  claudeModel: file.tools?.claude?.model ?? claudeEnv.ANTHROPIC_MODEL ?? "",
144
144
  claudeProxy: file.tools?.claude?.proxy ?? "",
145
145
  codexTimeoutMs: file.tools?.codex?.timeoutMs ?? 600000,
146
- cursorTimeoutMs: file.tools?.cursor?.timeoutMs ?? 600000,
147
146
  codebuddyTimeoutMs: file.tools?.codebuddy?.timeoutMs ?? 600000,
148
- cursorCliPath: file.tools?.cursor?.cliPath ?? "cursor",
149
- cursorModel: file.tools?.cursor?.model ?? "auto",
150
147
  codexCliPath: file.tools?.codex?.cliPath ?? "codex",
151
148
  codebuddyCliPath: file.tools?.codebuddy?.cliPath ?? "codebuddy",
152
149
  codexProxy: file.tools?.codex?.proxy ?? "",
153
- cursorProxy: file.tools?.cursor?.proxy ?? "",
154
150
  defaultPermissionMode: file.defaultPermissionMode ?? "ask",
155
151
  hookPort: file.hookPort ?? 35801,
156
152
  logDir: file.logDir ?? "",
@@ -188,8 +184,6 @@ function validatePayload(payload) {
188
184
  errors.push("Claude timeout must be positive.");
189
185
  if (!Number.isFinite(payload.ai.codexTimeoutMs) || payload.ai.codexTimeoutMs <= 0)
190
186
  errors.push("Codex timeout must be positive.");
191
- if (!Number.isFinite(payload.ai.cursorTimeoutMs) || payload.ai.cursorTimeoutMs <= 0)
192
- errors.push("Cursor timeout must be positive.");
193
187
  if (!Number.isFinite(payload.ai.codebuddyTimeoutMs) || payload.ai.codebuddyTimeoutMs <= 0)
194
188
  errors.push("CodeBuddy timeout must be positive.");
195
189
  if (!Number.isFinite(payload.ai.hookPort) || payload.ai.hookPort <= 0)
@@ -271,14 +265,12 @@ function createProbeConfig(values) {
271
265
  dingtalkAllowedUserIds: [],
272
266
  aiCommand: "claude",
273
267
  claudeCliPath: "claude",
274
- cursorCliPath: "cursor",
275
268
  codexCliPath: "codex",
276
269
  claudeWorkDir: process.cwd(),
277
270
  claudeSkipPermissions: true,
278
271
  defaultPermissionMode: "ask",
279
272
  claudeTimeoutMs: 600000,
280
273
  codexTimeoutMs: 600000,
281
- cursorTimeoutMs: 600000,
282
274
  codebuddyTimeoutMs: 600000,
283
275
  hookPort: 35801,
284
276
  logDir: "",
@@ -422,14 +414,6 @@ function toFileConfig(payload, existing) {
422
414
  proxy: clean(payload.ai.claudeProxy),
423
415
  // model is now saved to ~/.claude/settings.json as ANTHROPIC_MODEL
424
416
  },
425
- cursor: {
426
- ...existing.tools?.cursor,
427
- cliPath: clean(payload.ai.cursorCliPath) ?? "cursor",
428
- skipPermissions: existing.tools?.cursor?.skipPermissions ?? payload.ai.claudeSkipPermissions,
429
- proxy: clean(payload.ai.cursorProxy),
430
- timeoutMs: payload.ai.cursorTimeoutMs,
431
- model: clean(payload.ai.cursorModel),
432
- },
433
417
  codex: {
434
418
  ...existing.tools?.codex,
435
419
  cliPath: clean(payload.ai.codexCliPath) ?? "codex",
@@ -55,33 +55,3 @@ describe("getHealthPlatformSnapshot", () => {
55
55
  expect(snapshot.qq.message).toContain("configured");
56
56
  });
57
57
  });
58
- describe("Cursor web config defaults", () => {
59
- it("surfaces cursor as the default CLI path in initial config", async () => {
60
- vi.resetModules();
61
- const { startWebConfigServer } = await import("./config-web.js");
62
- const server = await startWebConfigServer({ mode: "init", cwd: process.cwd(), persistent: true });
63
- if (!server.url) {
64
- await server.close();
65
- throw new Error("Web config server failed to bind (url empty)");
66
- }
67
- // 使用原生 fetch(可能被 testPlatformConfig 的 vi.fn 覆盖),改用 http.get
68
- const { get } = await import("node:http");
69
- const body = await new Promise((resolve, reject) => {
70
- get(`${server.url}/api/config`, (res) => {
71
- let data = "";
72
- res.on("data", (chunk) => { data += chunk; });
73
- res.on("end", () => {
74
- try {
75
- resolve(JSON.parse(data));
76
- }
77
- catch (e) {
78
- reject(e);
79
- }
80
- });
81
- }).on("error", reject);
82
- });
83
- await server.close();
84
- // 无显式配置时为 cursor;Windows 下可能解析为安装路径
85
- expect(body?.payload?.ai?.cursorCliPath === "cursor" || body?.payload?.ai?.cursorCliPath?.endsWith("cursor.cmd")).toBe(true);
86
- });
87
- });
package/dist/config.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { LogLevel } from './logger.js';
2
2
  export type Platform = 'dingtalk' | 'feishu' | 'qq' | 'telegram' | 'wechat' | 'wework';
3
- export type AiCommand = 'claude' | 'codex' | 'cursor' | 'codebuddy';
3
+ export type AiCommand = 'claude' | 'codex' | 'codebuddy';
4
4
  export interface Config {
5
5
  enabledPlatforms: Platform[];
6
6
  telegramBotToken?: string;
@@ -31,23 +31,17 @@ export interface Config {
31
31
  dingtalkAllowedUserIds: string[];
32
32
  aiCommand: AiCommand;
33
33
  claudeCliPath: string;
34
- cursorCliPath: string;
35
34
  codexCliPath: string;
36
35
  codebuddyCliPath: string;
37
36
  /** Codex 访问 chatgpt.com 的代理(如 http://127.0.0.1:7890) */
38
37
  codexProxy?: string;
39
- /** Cursor 访问 API 的代理(如 http://127.0.0.1:7890,CLI 非官方支持) */
40
- cursorProxy?: string;
41
38
  claudeTimeoutMs: number;
42
39
  codexTimeoutMs: number;
43
- cursorTimeoutMs: number;
44
40
  codebuddyTimeoutMs: number;
45
41
  claudeWorkDir: string;
46
42
  claudeSkipPermissions: boolean;
47
43
  defaultPermissionMode: 'ask' | 'accept-edits' | 'plan' | 'yolo';
48
44
  claudeModel?: string;
49
- /** Cursor 专用模型,如 auto(自动选择)、Claude 4 Sonnet 等 */
50
- cursorModel?: string;
51
45
  hookPort: number;
52
46
  logDir: string;
53
47
  logLevel: LogLevel;
@@ -152,16 +146,6 @@ export interface FileToolClaude {
152
146
  model?: string;
153
147
  proxy?: string;
154
148
  }
155
- export interface FileToolCursor {
156
- cliPath?: string;
157
- /** 是否跳过权限确认(默认 true,与 tools.claude 共用权限服务器) */
158
- skipPermissions?: boolean;
159
- /** HTTP/HTTPS 代理(CLI 非官方支持,部分环境可能生效) */
160
- proxy?: string;
161
- timeoutMs?: number;
162
- /** 模型名,如 auto、Claude 4 Sonnet、gpt-5.2 等,见 agent --list-models */
163
- model?: string;
164
- }
165
149
  export interface FileToolCodex {
166
150
  cliPath?: string;
167
151
  workDir?: string;
@@ -194,7 +178,6 @@ export interface FileConfig {
194
178
  aiCommand?: string;
195
179
  tools?: {
196
180
  claude?: FileToolClaude;
197
- cursor?: FileToolCursor;
198
181
  codex?: FileToolCodex;
199
182
  codebuddy?: FileToolCodeBuddy;
200
183
  };