@wu529778790/open-im 1.3.1 → 1.3.2-beta.1

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.
Files changed (37) hide show
  1. package/README.md +142 -92
  2. package/dist/adapters/codex-adapter.d.ts +10 -0
  3. package/dist/adapters/codex-adapter.js +59 -0
  4. package/dist/adapters/cursor-adapter.d.ts +11 -0
  5. package/dist/adapters/cursor-adapter.js +50 -0
  6. package/dist/adapters/registry.js +10 -0
  7. package/dist/adapters/tool-adapter.interface.d.ts +2 -0
  8. package/dist/cli.js +1 -1
  9. package/dist/codex/cli-runner.d.ts +37 -0
  10. package/dist/codex/cli-runner.js +394 -0
  11. package/dist/commands/handler.d.ts +1 -1
  12. package/dist/commands/handler.js +8 -3
  13. package/dist/config.d.ts +4 -0
  14. package/dist/config.js +238 -14
  15. package/dist/constants.d.ts +0 -5
  16. package/dist/constants.js +0 -13
  17. package/dist/cursor/cli-runner.d.ts +33 -0
  18. package/dist/cursor/cli-runner.js +290 -0
  19. package/dist/feishu/card-builder.d.ts +2 -0
  20. package/dist/feishu/card-builder.js +13 -10
  21. package/dist/feishu/event-handler.js +3 -3
  22. package/dist/feishu/message-sender.d.ts +1 -1
  23. package/dist/feishu/message-sender.js +8 -11
  24. package/dist/index.js +37 -9
  25. package/dist/session/session-manager.d.ts +7 -0
  26. package/dist/session/session-manager.js +30 -1
  27. package/dist/setup.js +101 -38
  28. package/dist/shared/ai-task.d.ts +2 -0
  29. package/dist/shared/ai-task.js +25 -13
  30. package/dist/shared/utils.d.ts +6 -1
  31. package/dist/shared/utils.js +24 -12
  32. package/dist/telegram/message-sender.js +5 -16
  33. package/dist/wechat/message-sender.js +2 -7
  34. package/dist/wework/message-sender.js +2 -7
  35. package/package.json +1 -4
  36. package/dist/shared/message-dedup.d.ts +0 -4
  37. package/dist/shared/message-dedup.js +0 -25
package/README.md CHANGED
@@ -1,19 +1,21 @@
1
1
  # open-im
2
2
 
3
- 多平台 IM 桥接,将 Telegram、飞书 (Feishu/Lark)、企业微信和微信连接到 AI CLI 工具(Claude Code、Codex、Cursor),实现移动端/远程访问 AI 编程助手。
3
+ 多平台 IM 桥接工具,把 Telegram、飞书、企业微信、微信接到 AI CLI 工具(Claude Code、Codex、Cursor),方便在手机或聊天窗口里远程使用 AI 编程助手。
4
4
 
5
5
  ## 功能特性
6
6
 
7
- - **多平台**:支持 Telegram、飞书、企业微信、微信(测试中),可同时启用
8
- - **多 AI 工具**:通过配置切换 Claude Code / Codex / Cursor
9
- - **流式输出**:节流更新,实时展示 AI 回复
10
- - **会话管理**:每用户独立 session,`/new` 重置会话
11
- - **命令支持**:`/help` `/new` `/cd` `/pwd` `/status` `/allow` `/deny`
7
+ - 多平台:支持 Telegram、飞书、企业微信、微信(测试中),可同时启用
8
+ - AI 工具:支持 ClaudeCodexCursor
9
+ - 流式输出:实时回传 AI 回复与工具执行进度
10
+ - 会话隔离:每个用户独立维护本地会话,`/new` 可重置
11
+ - 权限模式:支持 `ask`、`accept-edits`、`plan`、`yolo`
12
+ - 常用命令:支持 `/help`、`/mode`、`/new`、`/cd`、`/pwd`、`/status`
12
13
 
13
14
  ## 环境要求
14
15
 
15
- - **Node.js** >= 20
16
- - **Claude API**:需要 API Key 或 Auth Token([获取方式](https://console.anthropic.com/))
16
+ - Node.js >= 20
17
+ - 至少配置一个 IM 平台
18
+ - 根据所选 AI 工具完成认证
17
19
 
18
20
  ## 快速开始
19
21
 
@@ -21,142 +23,190 @@
21
23
  npx @wu529778790/open-im start
22
24
  ```
23
25
 
24
- 或全局安装后直接使用:
26
+ 或全局安装:
25
27
 
26
28
  ```bash
27
- npm install @wu529778790/open-im -g
29
+ npm install -g @wu529778790/open-im
28
30
  open-im start
29
31
  ```
30
32
 
31
- 配置保存到 `~/.open-im/config.json`。
33
+ 配置文件默认保存在 `~/.open-im/config.json`。
32
34
 
33
- ## 命令说明
35
+ ## 仓库开发
36
+
37
+ ```bash
38
+ npm run build
39
+ npm run dev
40
+ npm start
41
+ npm stop
42
+ ```
43
+
44
+ ## CLI 命令
34
45
 
35
46
  | 命令 | 说明 |
36
- |------|------|
37
- | `open-im init` | 初始化配置(不启动服务) |
38
- | `open-im start` | 后台运行,适合长期使用 |
47
+ | ---- | ---- |
48
+ | `open-im init` | 初始化或追加配置,不启动服务 |
49
+ | `open-im start` | 后台运行服务 |
39
50
  | `open-im stop` | 停止后台服务 |
40
- | `open-im dev` | 前台运行(调试模式),Ctrl+C 停止 |
51
+ | `open-im dev` | 前台运行(调试模式) |
41
52
 
42
53
  ## 会话说明
43
54
 
44
- **会话上下文存储在本地**(`~/.open-im/data/sessions.json`),与 IM 聊天记录无关。每用户在本地维护独立的 session Claude 会话 ID,`/new` 可重置当前会话。
55
+ 会话上下文保存在本地 `~/.open-im/data/sessions.json`,与 IM 聊天记录本身无关。每个用户有独立会话目录和 session 信息,发送 `/new` 会重置当前 AI 会话。
45
56
 
46
- ### 环境变量
57
+ ## 配置说明
47
58
 
48
- | 变量 | 说明 |
49
- |------|------|
50
- | `TELEGRAM_BOT_TOKEN` | Telegram Bot Token |
51
- | `FEISHU_APP_ID` | 飞书 App ID |
52
- | `FEISHU_APP_SECRET` | 飞书 App Secret |
53
- | `WEWORK_CORP_ID` | 企业微信 Bot ID |
54
- | `WEWORK_SECRET` | 企业微信 Secret |
55
- | `ALLOWED_USER_IDS` | 白名单(逗号分隔,空=所有人) |
56
- | `CLAUDE_WORK_DIR` | 工作目录,默认当前目录 |
57
- | `ALLOWED_BASE_DIRS` | 允许访问的目录(逗号分隔) |
59
+ ### Claude
58
60
 
59
- ### Claude API 配置
61
+ Claude 默认使用 Agent SDK,不依赖本地 `claude` 可执行文件;通常只需要配置 API 凭证。
60
62
 
61
- **自动加载**:优先使用环境变量,其次从 `~/.open-im/config.json` 的 `env` 字段读取,最后从 `~/.claude/settings.json`(与 Claude Code 共用)自动加载。
63
+ 自动加载顺序:
62
64
 
63
- **快速配置**:
65
+ 1. 环境变量
66
+ 2. `~/.open-im/config.json` 的 `env`
67
+ 3. `~/.claude/settings.json` 或 `~/.claude.json`
64
68
 
65
- ```bash
66
- # 方式 1:运行配置向导
67
- open-im init
69
+ 支持官方 API,也支持第三方兼容接口:
68
70
 
69
- # 方式 2:编辑配置文件
70
- cat > ~/.open-im/config.json << 'EOF'
71
+ ```json
72
+ {
73
+ "env": {
74
+ "ANTHROPIC_AUTH_TOKEN": "your-token",
75
+ "ANTHROPIC_BASE_URL": "https://your-api-endpoint",
76
+ "ANTHROPIC_MODEL": "glm-4.7"
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### 配置文件示例
82
+
83
+ 下面示例是合法 JSON,可直接保存为 `~/.open-im/config.json`:
84
+
85
+ ```json
71
86
  {
72
- # 工作目录 默认当前目录
73
- "claudeWorkDir": "YOUR_WORK_DIR",
74
- # 是否跳过权限确认 默认 true
75
- "claudeSkipPermissions": true,
76
- # 使用的 AI 命令 默认 claude
77
87
  "aiCommand": "claude",
78
- # 平台配置
79
- "platforms": {
80
- # 企业微信配置
81
- "wework": {
82
- "enabled": true,
83
- "allowedUserIds": [],
84
- "corpId": "YOUR_WEWORK_CORP_ID",
85
- "secret": "YOUR_WEWORK_SECRET" # 从企业微信管理后台获取 Corp ID 和 Secret
88
+ "tools": {
89
+ "claude": {
90
+ "cliPath": "claude",
91
+ "workDir": "D:/coding/open-im",
92
+ "skipPermissions": true,
93
+ "timeoutMs": 600000
94
+ },
95
+ "cursor": {
96
+ "cliPath": "agent",
97
+ "skipPermissions": true
86
98
  },
87
- # Telegram 配置
99
+ "codex": {
100
+ "cliPath": "codex",
101
+ "workDir": "D:/coding/open-im",
102
+ "skipPermissions": true,
103
+ "proxy": "http://127.0.0.1:7890"
104
+ }
105
+ },
106
+ "platforms": {
88
107
  "telegram": {
89
108
  "enabled": true,
90
109
  "proxy": "http://127.0.0.1:7890",
91
110
  "allowedUserIds": [],
92
- "botToken": "YOUR_TELEGRAM_BOT_TOKEN" # 从 @BotFather 获取 Bot Token
111
+ "botToken": "YOUR_TELEGRAM_BOT_TOKEN"
93
112
  },
94
- # 飞书配置
95
113
  "feishu": {
96
- "enabled": true,
114
+ "enabled": false,
97
115
  "allowedUserIds": [],
98
116
  "appId": "YOUR_FEISHU_APP_ID",
99
- "appSecret": "YOUR_FEISHU_APP_SECRET" # 从飞书开放平台获取 App ID 和 App Secret
117
+ "appSecret": "YOUR_FEISHU_APP_SECRET"
118
+ },
119
+ "wework": {
120
+ "enabled": false,
121
+ "allowedUserIds": [],
122
+ "corpId": "YOUR_WEWORK_CORP_ID",
123
+ "secret": "YOUR_WEWORK_SECRET"
124
+ },
125
+ "wechat": {
126
+ "enabled": false,
127
+ "allowedUserIds": [],
128
+ "appId": "YOUR_WECHAT_APP_ID",
129
+ "appSecret": "YOUR_WECHAT_APP_SECRET"
100
130
  }
101
131
  }
102
132
  }
103
- EOF
104
- ```
105
-
106
- **支持第三方模型**(可选):
107
-
108
- ```json
109
- {
110
- "env": {
111
- "ANTHROPIC_AUTH_TOKEN": "your-token",
112
- "ANTHROPIC_BASE_URL": "https://your-api-endpoint",
113
- "ANTHROPIC_MODEL": "glm-4.7"
114
- }
115
- }
116
133
  ```
117
134
 
118
- ### 平台配置
135
+ ### 常用环境变量
119
136
 
120
- 运行 `open-im init` 自动配置,或手动设置:
121
-
122
- - **Telegram**:从 [@BotFather](https://t.me/BotFather) 获取 Bot Token
123
- - **飞书**:[开放平台](https://open.feishu.cn/) 创建应用,启用机器人,配置 WebSocket 事件订阅
124
- - **企业微信**:[管理后台](https://work.weixin.qq.com/) 创建应用,获取 Bot ID 和 Secret
125
- - **微信**:测试中,基于 Qclaw 协议
137
+ | 变量 | 说明 |
138
+ | ---- | ---- |
139
+ | `AI_COMMAND` | 选择 `claude` / `codex` / `cursor` |
140
+ | `CLAUDE_WORK_DIR` | 默认会话目录 |
141
+ | `ALLOWED_BASE_DIRS` | 允许访问的目录列表,逗号分隔 |
142
+ | `LOG_DIR` | 日志目录 |
143
+ | `LOG_LEVEL` | 日志级别 |
144
+ | `HOOK_PORT` | 权限服务端口 |
145
+ | `CODEX_PROXY` | Codex 访问 `chatgpt.com` 的代理 |
146
+ | `OPENAI_API_KEY` | Codex API Key,可替代 `codex login` |
147
+ | `CURSOR_API_KEY` | Cursor API Key,可替代 `agent login` |
148
+ | `TELEGRAM_BOT_TOKEN` | Telegram Bot Token |
149
+ | `TELEGRAM_PROXY` | Telegram 代理地址 |
150
+ | `TELEGRAM_ALLOWED_USER_IDS` | Telegram 白名单 |
151
+ | `FEISHU_APP_ID` | 飞书 App ID |
152
+ | `FEISHU_APP_SECRET` | 飞书 App Secret |
153
+ | `FEISHU_ALLOWED_USER_IDS` | 飞书白名单 |
154
+ | `WEWORK_CORP_ID` | 企业微信 Bot ID |
155
+ | `WEWORK_SECRET` | 企业微信 Secret |
156
+ | `WEWORK_WS_URL` | 企业微信 WebSocket 地址 |
157
+ | `WEWORK_ALLOWED_USER_IDS` | 企业微信白名单 |
158
+ | `WECHAT_APP_ID` | 微信标准模式 App ID |
159
+ | `WECHAT_APP_SECRET` | 微信标准模式 App Secret |
160
+ | `WECHAT_TOKEN` | 微信 AGP 模式 Token |
161
+ | `WECHAT_GUID` | 微信 AGP 模式 GUID |
162
+ | `WECHAT_USER_ID` | 微信 AGP 模式 User ID |
163
+ | `WECHAT_WS_URL` | 微信 WebSocket 地址 |
164
+ | `WECHAT_ALLOWED_USER_IDS` | 微信白名单 |
165
+
166
+ ### 平台配置来源
167
+
168
+ - Telegram:从 [@BotFather](https://t.me/BotFather) 获取 Bot Token
169
+ - 飞书:从 [飞书开放平台](https://open.feishu.cn/) 创建应用并启用机器人
170
+ - 企业微信:从 [企业微信管理后台](https://work.weixin.qq.com/) 获取 Bot ID 和 Secret
171
+ - 微信:测试中,支持标准模式和 AGP/Qclaw 相关配置
126
172
 
127
173
  ## IM 内命令
128
174
 
129
175
  | 命令 | 说明 |
130
- |------|------|
176
+ | ---- | ---- |
131
177
  | `/help` | 显示帮助 |
132
- | `/mode` | 切换权限模式(卡片/按钮选择) |
133
- | `/mode <模式>` | 直接切换:ask / accept-edits / plan / yolo |
178
+ | `/mode` | 飞书显示卡片,Telegram 显示按钮,其它平台显示文本模式列表 |
179
+ | `/mode <模式>` | 直接切换:`ask` / `accept-edits` / `plan` / `yolo` |
134
180
  | `/new` | 开始新会话 |
135
- | `/status` | 显示状态(AI 工具、工作目录、费用等) |
136
- | `/cd <路径>` | 切换工作目录 |
137
- | `/pwd` | 显示当前工作目录 |
181
+ | `/status` | 显示 AI 工具、版本、会话目录、会话 ID |
182
+ | `/cd <路径>` | 切换会话目录 |
183
+ | `/pwd` | 显示当前会话目录 |
138
184
  | `/allow` `/y` | 允许权限请求 |
139
185
  | `/deny` `/n` | 拒绝权限请求 |
140
186
 
141
187
  ### 权限模式
142
188
 
143
- 与 Claude Code 官方命名一致,见 [permissions](https://code.claude.com/docs/en/permissions):
189
+ 与 Claude Code 官方命名保持一致,参考 [permissions](https://code.claude.com/docs/en/permissions):
144
190
 
145
191
  | 模式 | Claude 名 | 说明 |
146
- |------|-----------|------|
147
- | ask | default | 首次使用每个工具时提示确认 |
148
- | accept-edits | acceptEdits | 编辑权限自动通过 |
149
- | plan | plan | 仅分析,不修改文件不执行命令 |
150
- | yolo | bypassPermissions | 跳过所有权限确认 |
192
+ | ---- | --------- | ---- |
193
+ | `ask` | `default` | 首次使用工具时询问 |
194
+ | `accept-edits` | `acceptEdits` | 自动允许编辑 |
195
+ | `plan` | `plan` | 只读分析,不执行命令、不改文件 |
196
+ | `yolo` | `bypassPermissions` | 跳过所有权限确认 |
151
197
 
152
- ## 📝 License
198
+ ## 故障排除
153
199
 
154
- [MIT](LICENSE)
200
+ **Telegram 无响应**:检查网络,必要时在 Telegram 平台配置中添加 `"proxy": "http://127.0.0.1:7890"` 或设置 `TELEGRAM_PROXY`。
155
201
 
156
- ## 🔧 故障排除
202
+ **飞书卡片报错**:未配置卡片回调时,可直接用 `/mode ask`、`/mode yolo`。
157
203
 
158
- **Telegram 无响应**:检查网络,可能需要代理,在配置文件中添加 `"proxy": "http://127.0.0.1:7890"`
204
+ **企业微信收不到通知**:需要先给机器人发过一条消息,后续才能收到主动通知。
159
205
 
160
- **飞书卡片报错**:未配置卡片回调,使用命令替代:`/mode ask`、`/mode yolo`
206
+ **Cursor `Authentication required`**:先执行 `agent login`,或在 `env` 中设置 `CURSOR_API_KEY`。
161
207
 
162
- **企业微信收不到通知**:需先发一条消息给机器人,才能接收启动通知
208
+ **Codex 报 `stream disconnected` / `error sending request`**:无法访问 `chatgpt.com`,请配置 `tools.codex.proxy` 或环境变量 `CODEX_PROXY`。
209
+
210
+ ## License
211
+
212
+ [MIT](LICENSE)
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Codex Adapter - run tasks through OpenAI Codex CLI (`codex exec`)
3
+ */
4
+ import type { RunCallbacks, RunHandle, RunOptions, ToolAdapter } from "./tool-adapter.interface.js";
5
+ export declare class CodexAdapter implements ToolAdapter {
6
+ private cliPath;
7
+ readonly toolId = "codex";
8
+ constructor(cliPath: string);
9
+ run(prompt: string, sessionId: string | undefined, workDir: string, callbacks: RunCallbacks, options?: RunOptions): RunHandle;
10
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Codex Adapter - run tasks through OpenAI Codex CLI (`codex exec`)
3
+ */
4
+ import { runCodex } from "../codex/cli-runner.js";
5
+ export class CodexAdapter {
6
+ cliPath;
7
+ toolId = "codex";
8
+ constructor(cliPath) {
9
+ this.cliPath = cliPath;
10
+ }
11
+ run(prompt, sessionId, workDir, callbacks, options) {
12
+ const opts = {
13
+ skipPermissions: options?.skipPermissions,
14
+ permissionMode: options?.permissionMode,
15
+ timeoutMs: options?.timeoutMs,
16
+ model: options?.model,
17
+ chatId: options?.chatId,
18
+ hookPort: options?.hookPort,
19
+ proxy: options?.proxy,
20
+ };
21
+ return runCodex(this.cliPath, prompt, sessionId, workDir, {
22
+ onText: callbacks.onText,
23
+ onThinking: callbacks.onThinking,
24
+ onToolUse: callbacks.onToolUse,
25
+ onComplete: (raw) => {
26
+ const result = {
27
+ success: raw.success,
28
+ result: raw.result,
29
+ accumulated: raw.accumulated,
30
+ cost: raw.cost,
31
+ durationMs: raw.durationMs,
32
+ model: raw.model,
33
+ numTurns: raw.numTurns,
34
+ toolStats: raw.toolStats,
35
+ };
36
+ callbacks.onComplete(result);
37
+ },
38
+ onError: (err) => {
39
+ const msg = typeof err === "string" ? err : String(err);
40
+ const friendly = msg.includes("Authentication") || msg.includes("login")
41
+ ? "Codex 需要先登录。请在终端运行 codex login,或在 ~/.open-im/config.json 的 env 中添加 OPENAI_API_KEY。"
42
+ : msg.includes("stream disconnected") ||
43
+ msg.includes("error sending request") ||
44
+ msg.includes("Connection refused") ||
45
+ msg.includes("ENOTFOUND") ||
46
+ msg.includes("ETIMEDOUT")
47
+ ? "Codex 网络请求失败。如无法访问 chatgpt.com,请在 tools.codex.proxy 或 CODEX_PROXY 中配置代理。"
48
+ : msg.includes("No session found") ||
49
+ msg.includes("No conversation found") ||
50
+ msg.includes("Unable to find session")
51
+ ? "Codex 会话已失效,旧 session 已清理。请直接重试当前请求。"
52
+ : msg;
53
+ callbacks.onError(friendly);
54
+ },
55
+ onSessionId: callbacks.onSessionId,
56
+ onSessionInvalid: callbacks.onSessionInvalid,
57
+ }, opts);
58
+ }
59
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Cursor Adapter - 通过 Cursor Agent CLI 执行任务
3
+ * 需要预先安装: curl https://cursor.com/install -fsSL | bash
4
+ */
5
+ import type { ToolAdapter, RunCallbacks, RunOptions, RunHandle } from './tool-adapter.interface.js';
6
+ export declare class CursorAdapter implements ToolAdapter {
7
+ private cliPath;
8
+ readonly toolId = "cursor";
9
+ constructor(cliPath: string);
10
+ run(prompt: string, sessionId: string | undefined, workDir: string, callbacks: RunCallbacks, options?: RunOptions): RunHandle;
11
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Cursor Adapter - 通过 Cursor Agent CLI 执行任务
3
+ * 需要预先安装: curl https://cursor.com/install -fsSL | bash
4
+ */
5
+ import { runCursor } from '../cursor/cli-runner.js';
6
+ import { createLogger } from '../logger.js';
7
+ const log = createLogger('CursorAdapter');
8
+ export class CursorAdapter {
9
+ cliPath;
10
+ toolId = 'cursor';
11
+ constructor(cliPath) {
12
+ this.cliPath = cliPath;
13
+ }
14
+ run(prompt, sessionId, workDir, callbacks, options) {
15
+ const opts = {
16
+ skipPermissions: options?.skipPermissions,
17
+ permissionMode: options?.permissionMode,
18
+ timeoutMs: options?.timeoutMs,
19
+ model: options?.model,
20
+ chatId: options?.chatId,
21
+ hookPort: options?.hookPort,
22
+ };
23
+ return runCursor(this.cliPath, prompt, sessionId, workDir, {
24
+ onText: callbacks.onText,
25
+ onThinking: callbacks.onThinking,
26
+ onToolUse: callbacks.onToolUse,
27
+ onComplete: (raw) => {
28
+ const result = {
29
+ success: raw.success,
30
+ result: raw.result,
31
+ accumulated: raw.accumulated,
32
+ cost: raw.cost,
33
+ durationMs: raw.durationMs,
34
+ model: raw.model,
35
+ numTurns: raw.numTurns,
36
+ toolStats: raw.toolStats,
37
+ };
38
+ callbacks.onComplete(result);
39
+ },
40
+ onError: (err) => {
41
+ const msg = typeof err === 'string' ? err : String(err);
42
+ const friendly = msg.includes('Authentication required') || msg.includes('agent login')
43
+ ? 'Cursor 需要先登录。请在终端运行 agent login,或在 ~/.open-im/config.json 的 env 中添加 "CURSOR_API_KEY"。'
44
+ : msg;
45
+ callbacks.onError(friendly);
46
+ },
47
+ onSessionId: callbacks.onSessionId,
48
+ }, opts);
49
+ }
50
+ }
@@ -1,5 +1,7 @@
1
1
  import { ClaudeAdapter } from './claude-adapter.js';
2
2
  import { ClaudeSDKAdapter } from './claude-sdk-adapter.js';
3
+ import { CursorAdapter } from './cursor-adapter.js';
4
+ import { CodexAdapter } from './codex-adapter.js';
3
5
  const adapters = new Map();
4
6
  export function initAdapters(config) {
5
7
  adapters.clear();
@@ -16,6 +18,14 @@ export function initAdapters(config) {
16
18
  }));
17
19
  }
18
20
  }
21
+ else if (config.aiCommand === 'cursor') {
22
+ console.log('🖱️ 使用 Cursor Agent CLI 适配器');
23
+ adapters.set('cursor', new CursorAdapter(config.cursorCliPath));
24
+ }
25
+ else if (config.aiCommand === 'codex') {
26
+ console.log('📦 使用 Codex CLI 适配器');
27
+ adapters.set('codex', new CodexAdapter(config.codexCliPath));
28
+ }
19
29
  }
20
30
  export function getAdapter(aiCommand) {
21
31
  return adapters.get(aiCommand);
@@ -29,6 +29,8 @@ export interface RunOptions {
29
29
  model?: string;
30
30
  chatId?: string;
31
31
  hookPort?: number;
32
+ /** Codex 专用:HTTP/HTTPS 代理地址,如 http://127.0.0.1:7890 */
33
+ proxy?: string;
32
34
  }
33
35
  export interface RunHandle {
34
36
  abort: () => void;
package/dist/cli.js CHANGED
@@ -185,7 +185,7 @@ function showHelp(exitCode = 0) {
185
185
  命令:
186
186
  start 后台运行服务
187
187
  stop 停止后台服务
188
- init 配置向导(首次或追加配置,会覆盖已有 config.json)
188
+ init 配置向导(首次或追加配置,保留已有平台配置并更新 config.json)
189
189
  dev 前台运行(调试模式),Ctrl+C 停止
190
190
 
191
191
  选项:
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Codex CLI Runner - 解析 codex exec --json 的 JSONL 输出
3
+ * 参考: https://developers.openai.com/codex/cli/reference/
4
+ * https://takopi.dev/reference/runners/codex/exec-json-cheatsheet/
5
+ */
6
+ export interface CodexRunCallbacks {
7
+ onText: (accumulated: string) => void;
8
+ onThinking?: (accumulated: string) => void;
9
+ onToolUse?: (toolName: string, toolInput?: Record<string, unknown>) => void;
10
+ onComplete: (result: {
11
+ success: boolean;
12
+ result: string;
13
+ accumulated: string;
14
+ cost: number;
15
+ durationMs: number;
16
+ model?: string;
17
+ numTurns: number;
18
+ toolStats: Record<string, number>;
19
+ }) => void;
20
+ onError: (error: string) => void;
21
+ onSessionId?: (sessionId: string) => void;
22
+ onSessionInvalid?: () => void;
23
+ }
24
+ export interface CodexRunOptions {
25
+ skipPermissions?: boolean;
26
+ permissionMode?: 'default' | 'acceptEdits' | 'plan';
27
+ timeoutMs?: number;
28
+ model?: string;
29
+ chatId?: string;
30
+ hookPort?: number;
31
+ /** HTTP/HTTPS 代理,用于访问 chatgpt.com */
32
+ proxy?: string;
33
+ }
34
+ export interface CodexRunHandle {
35
+ abort: () => void;
36
+ }
37
+ export declare function runCodex(cliPath: string, prompt: string, sessionId: string | undefined, workDir: string, callbacks: CodexRunCallbacks, options?: CodexRunOptions): CodexRunHandle;