@wu529778790/open-im 1.11.1-beta.8 → 1.11.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.
package/README.md CHANGED
@@ -2,66 +2,45 @@
2
2
 
3
3
  **English** · [中文](./README.zh-CN.md)
4
4
 
5
- Multi-platform IM bridge for AI CLI tools. Connect Telegram, Feishu, WeCom, DingTalk, QQ, WeChat (WorkBuddy), and WeChat (ClawBot) to Claude Code, Codex, and CodeBuddy — use your AI coding assistant from any phone or chat window.
5
+ > Your AI coding assistant, in every chat app.
6
+
7
+ open-im bridges Claude Code, Codex, and CodeBuddy to Telegram, Feishu, WeCom, DingTalk, QQ, WeChat (WorkBuddy), and WeChat (ClawBot). Send a message from your phone, get code written on your server.
6
8
 
7
9
  ## Architecture
8
10
 
9
11
  ![Open-IM Architecture](./diagram/architecture/open-im-architecture.svg)
10
12
 
11
- ## Features
12
-
13
- - **Seven IM platforms** — Telegram, Feishu, WeCom, DingTalk, QQ, WorkBuddy, ClawBot
14
- - **Three AI backends** — Claude (Agent SDK), Codex, CodeBuddy (per-platform override supported)
15
- - **Streaming, media, sessions** — live output where supported; `/new` for a fresh AI session
16
- - **Web UI** — dashboard bundled in the package; default **`http://127.0.0.1:39282`**
17
-
18
- ## Requirements
19
-
20
- - Node.js ≥ 20
21
- - At least one IM platform configured + credentials for your AI tool
22
-
23
- ## Quick start
24
-
25
- ```bash
26
- npx @wu529778790/open-im start
27
- ```
28
-
29
- Or: `npm install -g @wu529778790/open-im` then `open-im start`.
13
+ ## Why
30
14
 
31
- Config: **`~/.open-im/config.json`**
15
+ - **Work from anywhere** — trigger Claude Code from your phone while commuting, waiting in line, or on the couch
16
+ - **Seamless handoff** — open-im shares sessions with the Claude Code CLI; pick up on your computer exactly where you left off on your phone
17
+ - **Full power, simple interface** — stream responses, manage sessions, switch models — all through chat commands
18
+ - **One bridge, many platforms** — same bot works on Telegram, Feishu, DingTalk, WeChat, and more
32
19
 
33
- ## CLI
34
-
35
- | Command | Description |
36
- | --- | --- |
37
- | `open-im init` | Interactive setup (does not start the bridge) |
38
- | `open-im start` | Run the bridge in the background |
39
- | `open-im stop` | Stop the background bridge |
40
- | `open-im restart` | Stop then start |
41
- | `open-im dashboard` | Web config server only (no bridge) |
42
-
43
- After `start`, the CLI prints the dashboard URL (default **`http://127.0.0.1:39282`**).
20
+ ## Features
44
21
 
45
- ## Chat commands
22
+ ### Chat commands
46
23
 
47
24
  | Command | Description |
48
25
  | --- | --- |
49
- | `/help` | Help |
50
- | `/new` | New AI session |
51
- | `/sessions` | Session history with preview |
52
- | `/resume [N]` | Resume session (no arg = most recent) |
53
- | `/status` | AI + session info |
54
- | `/cd` / `/pwd` | Switch work dir (auto-resumes that dir's session) |
55
- | `/allow` / `/y`, `/deny` / `/n` | Permission prompts |
56
-
57
- ## Session continuity
26
+ | `/help` | Show all commands |
27
+ | `/new` | Start a fresh AI session |
28
+ | `/sessions` | Browse session history with previews |
29
+ | `/resume [N]` | Resume a session (no arg = most recent) |
30
+ | `/history [N]` | View conversation messages in a session |
31
+ | `/delete <N>` | Delete a session |
32
+ | `/rename <title>` | Rename the current session |
33
+ | `/fork [N]` | Fork a session (create a branch) |
34
+ | `/models` | List available AI models |
35
+ | `/context` | Show context window usage |
36
+ | `/status` | Show AI tool, account, and session info |
37
+ | `/cd <path>` / `/pwd` | Switch work directory (auto-resumes that dir's session) |
38
+ | `/allow` / `/y`, `/deny` / `/n` | Respond to permission prompts |
39
+
40
+ ### Session continuity
58
41
 
59
42
  open-im and Claude Code CLI share the same session storage. In the same directory, you can seamlessly switch between phone and computer.
60
43
 
61
- **Phone → Computer:** open-im auto-resumes the latest CLI session — no configuration needed.
62
-
63
- **Computer → Phone:** use `claude --continue` (or `claude -c`) to pick up the phone conversation.
64
-
65
44
  ```
66
45
  # On computer
67
46
  cd /my-project && claude # work as usual, then Ctrl+C
@@ -75,16 +54,43 @@ claude -c # continues the phone conversation
75
54
 
76
55
  > Only one side can be active at a time. Exit the CLI before sending messages from the phone, and vice versa.
77
56
 
78
- ## Git co-authors
57
+ ### Platform support
79
58
 
80
- `Co-authored-by` is appended by default on AI-driven commits. **Disable:** set **`OPEN_IM_GIT_COAUTHOR=0`** in the environment and restart the bridge.
59
+ Seven IM platforms, three AI backends, per-platform override:
81
60
 
82
- ## Minimal config
61
+ | Platform | Streaming | Media | Notes |
62
+ | --- | --- | --- | --- |
63
+ | Telegram | Yes | Images | Full bot support |
64
+ | Feishu | Yes | Images | Streaming card |
65
+ | WeCom | Yes | Images | Streaming card |
66
+ | DingTalk | Partial | Images | Fallback to text |
67
+ | QQ | Yes | Images | |
68
+ | WorkBuddy | Yes | Images | WeChat-based |
69
+ | ClawBot | Yes | Images | WeChat-based |
70
+
71
+ Set `platforms.<name>.aiCommand` (`claude` / `codex` / `codebuddy`) per channel. Default: `claude`.
72
+
73
+ ### Web dashboard
74
+
75
+ `open-im start` serves a built-in SPA and API at **`http://127.0.0.1:39282`** (configurable via `OPEN_IM_WEB_PORT`). For LAN access: `export OPEN_IM_WEB_HOST=0.0.0.0`.
76
+
77
+ ## Quick start
78
+
79
+ ```bash
80
+ npx @wu529778790/open-im init # interactive setup
81
+ npx @wu529778790/open-im start # run the bridge
82
+ ```
83
+
84
+ Or install globally: `npm install -g @wu529778790/open-im` then `open-im start`.
85
+
86
+ Config file: **`~/.open-im/config.json`**
87
+
88
+ ### Minimal config
83
89
 
84
90
  ```json
85
91
  {
86
92
  "tools": {
87
- "claude": { "workDir": "/path/to/project", "skipPermissions": true, "timeoutMs": 600000 }
93
+ "claude": { "workDir": "/path/to/project", "skipPermissions": true }
88
94
  },
89
95
  "platforms": {
90
96
  "telegram": { "enabled": true, "botToken": "YOUR_TELEGRAM_BOT_TOKEN" }
@@ -92,11 +98,11 @@ claude -c # continues the phone conversation
92
98
  }
93
99
  ```
94
100
 
95
- Add other platforms under **`platforms`** as needed. Run **`open-im init`** for a full template.
101
+ Run `open-im init` for a full template with all platforms.
96
102
 
97
103
  ### Claude (Agent SDK)
98
104
 
99
- No local `claude` binary required. Third-party / compatible API:
105
+ No local `claude` binary required. Supports third-party / compatible APIs:
100
106
 
101
107
  ```json
102
108
  {
@@ -112,26 +118,37 @@ No local `claude` binary required. Third-party / compatible API:
112
118
  }
113
119
  ```
114
120
 
115
- ### Per-platform AI
121
+ ### CLI reference
116
122
 
117
- Set **`platforms.<name>.aiCommand`** (`claude` / `codex` / `codebuddy`) per channel. Default: `claude`.
123
+ | Command | Description |
124
+ | --- | --- |
125
+ | `open-im init` | Interactive setup (does not start the bridge) |
126
+ | `open-im start` | Run the bridge in the background |
127
+ | `open-im stop` | Stop the background bridge |
128
+ | `open-im restart` | Stop then start |
129
+ | `open-im dashboard` | Web config server only (no bridge) |
118
130
 
119
- ### Web dashboard
131
+ ### Environment variables
120
132
 
121
- `open-im start` serves the built-in SPA and **`/api/*`** on **`OPEN_IM_WEB_PORT`** (default **39282**). For LAN access: `export OPEN_IM_WEB_HOST=0.0.0.0`.
133
+ **`ANTHROPIC_*`** (shell or `tools.claude.env`), **`TELEGRAM_BOT_TOKEN`**, **`OPEN_IM_WEB_PORT`**, **`OPEN_IM_WEB_HOST`**, plus platform-specific `*_APP_ID`, `*_SECRET`, `WORKBUDDY_*`, etc.
122
134
 
123
- ### Environment variables
135
+ ### Git co-authors
124
136
 
125
- Typical keys: **`ANTHROPIC_*`** (shell or **`tools.claude.env`**), **`TELEGRAM_BOT_TOKEN`**, **`OPEN_IM_WEB_PORT`**, **`OPEN_IM_WEB_HOST`**, plus platform-specific `*_APP_ID`, `*_SECRET`, `WORKBUDDY_*`, etc.
137
+ `Co-authored-by` is appended by default on AI-driven commits. Disable: set **`OPEN_IM_GIT_COAUTHOR=0`** in the environment and restart the bridge.
126
138
 
127
139
  ### Privacy
128
140
 
129
- **Anonymous** usage information may be collected to improve reliability (no chat or prompt content). To disable: **`OPEN_IM_TELEMETRY=false`** or **`"telemetry": { "enabled": false }`** in **`config.json`**.
141
+ **Anonymous** usage information may be collected to improve reliability (no chat or prompt content). To disable: **`OPEN_IM_TELEMETRY=false`** or `"telemetry": { "enabled": false }` in `config.json`.
130
142
 
131
143
  ## Platform setup & troubleshooting
132
144
 
133
145
  See **[docs/platforms.md](./docs/platforms.md)** for detailed per-platform configuration, credential setup, and troubleshooting.
134
146
 
147
+ ## Requirements
148
+
149
+ - Node.js >= 20
150
+ - At least one IM platform configured + credentials for your AI tool
151
+
135
152
  ## License
136
153
 
137
154
  [MIT](LICENSE)
package/README.zh-CN.md CHANGED
@@ -2,65 +2,44 @@
2
2
 
3
3
  [English](./README.md) · **中文**
4
4
 
5
- 多平台 IM 桥接:把 Telegram、飞书、企业微信、钉钉、QQ、微信(WorkBuddy)、微信(ClawBot)接到 Claude Code、Codex、CodeBuddy,在手机或聊天里使用 AI 编程助手。
5
+ > 你的 AI 编程助手,在每个聊天 App 里。
6
+
7
+ open-im 把 Claude Code、Codex、CodeBuddy 接入 Telegram、飞书、企业微信、钉钉、QQ、微信(WorkBuddy)、微信(ClawBot)。手机发条消息,服务器上就写好代码。
6
8
 
7
9
  ## 架构
8
10
 
9
11
  ![Open-IM 架构图](./diagram/architecture/open-im-architecture.svg)
10
12
 
11
- ## 功能特性
13
+ ## 为什么用 open-im
12
14
 
13
- - **七个 IM 平台** Telegram、飞书、企业微信、钉钉、QQ、WorkBuddy、ClawBot
14
- - **三种 AI 后端** Claude(Agent SDK)、Codex、CodeBuddy(可按平台覆盖)
15
- - **流式、多媒体、会话**视平台能力;`/new` 开启新 AI 会话
16
- - **Web 控制台** 随包内置,默认 **`http://127.0.0.1:39282`**
15
+ - **随时随地** 通勤、排队、躺沙发上,手机发消息就能让 Claude Code 干活
16
+ - **无缝接力** open-im Claude Code CLI 共享 session,在手机上聊到一半,电脑上接着来
17
+ - **完整能力,简单界面**流式输出、会话管理、模型切换,全靠聊天命令搞定
18
+ - **一个桥接,多个平台**同一个 bot 支持 Telegram、飞书、钉钉、微信等
17
19
 
18
- ## 环境要求
20
+ ## 功能
19
21
 
20
- - Node.js ≥ 20
21
- - 至少配置一个 IM 平台 + 所选 AI 的凭证
22
-
23
- ## 快速开始
24
-
25
- ```bash
26
- npx @wu529778790/open-im start
27
- ```
28
-
29
- 或:`npm install -g @wu529778790/open-im` 后执行 `open-im start`。
30
-
31
- 配置:**`~/.open-im/config.json`**
32
-
33
- ## CLI 命令
22
+ ### 聊天命令
34
23
 
35
24
  | 命令 | 说明 |
36
25
  | --- | --- |
37
- | `open-im init` | 交互配置(不启动桥接) |
38
- | `open-im start` | 后台运行桥接 |
39
- | `open-im stop` | 停止后台服务 |
40
- | `open-im restart` | 重启 |
41
- | `open-im dashboard` | 仅 Web 配置服务(不启动桥接) |
42
-
43
- `start` 后会提示控制台地址(默认 **`http://127.0.0.1:39282`**)。
44
-
45
- ## IM 内命令
46
-
47
- | 命令 | 说明 |
48
- | --- | --- |
49
- | `/help` | 帮助 |
50
- | `/new` | 新 AI 会话 |
51
- | `/sessions` | 历史会话(含摘要预览) |
26
+ | `/help` | 显示所有命令 |
27
+ | `/new` | 开启新 AI 会话 |
28
+ | `/sessions` | 浏览历史会话(含摘要预览) |
52
29
  | `/resume [序号]` | 恢复会话(无参数恢复最近一条) |
53
- | `/status` | AI 与会话信息 |
54
- | `/cd` / `/pwd` | 切换工作目录(自动恢复该目录的历史会话) |
30
+ | `/history [序号]` | 查看会话对话记录 |
31
+ | `/delete <序号>` | 删除历史会话 |
32
+ | `/rename <标题>` | 重命名当前会话 |
33
+ | `/fork [序号]` | 分支会话(创建副本) |
34
+ | `/models` | 查看可用 AI 模型 |
35
+ | `/context` | 查看上下文窗口占用 |
36
+ | `/status` | 显示 AI 工具、账号、会话信息 |
37
+ | `/cd <路径>` / `/pwd` | 切换工作目录(自动恢复该目录的历史会话) |
55
38
  | `/allow` / `/y`、`/deny` / `/n` | 权限确认 |
56
39
 
57
- ## 会话接力
58
-
59
- open-im 和 Claude Code CLI 共享同一份 session 存储。在同一个目录下,手机和电脑可以无缝切换。
40
+ ### 会话接力
60
41
 
61
- **手机接电脑:** open-im 自动恢复同目录下最新的 CLI session,无需配置。
62
-
63
- **电脑接手机:** 使用 `claude --continue`(或 `claude -c`)接上 open-im 端的对话。
42
+ open-im Claude Code CLI 共享同一份 session 存储。同一个目录下,手机和电脑可以无缝切换。
64
43
 
65
44
  ```bash
66
45
  # 电脑端
@@ -75,16 +54,43 @@ claude -c # 接上手机端的对话
75
54
 
76
55
  > 同一时刻只能有一端活跃。从手机发消息前先退出 CLI,反之亦然。
77
56
 
78
- ## Git 共同作者
57
+ ### 平台支持
58
+
59
+ 七个 IM 平台,三种 AI 后端,可按平台覆盖:
79
60
 
80
- 默认在 AI 发起的提交里追加 `Co-authored-by`。**关闭**:设置环境变量 **`OPEN_IM_GIT_COAUTHOR=0`** 并重启桥接。
61
+ | 平台 | 流式输出 | 备注 |
62
+ | --- | --- | --- |
63
+ | Telegram | 支持 | 完整 bot 支持 |
64
+ | 飞书 | 支持 | 流式卡片 |
65
+ | 企业微信 | 支持 | 流式卡片 |
66
+ | 钉钉 | 部分 | 回退到纯文本 |
67
+ | QQ | 支持 | |
68
+ | WorkBuddy | 支持 | 微信生态 |
69
+ | ClawBot | 支持 | 微信生态 |
81
70
 
82
- ## 最小配置
71
+ 在每个平台上设置 `platforms.<name>.aiCommand`(`claude` / `codex` / `codebuddy`),默认 `claude`。
72
+
73
+ ### Web 控制台
74
+
75
+ `open-im start` 在 **`http://127.0.0.1:39282`** 提供内置页面与 API(通过 `OPEN_IM_WEB_PORT` 配置端口)。局域网访问:`export OPEN_IM_WEB_HOST=0.0.0.0`。
76
+
77
+ ## 快速开始
78
+
79
+ ```bash
80
+ npx @wu529778790/open-im init # 交互式配置
81
+ npx @wu529778790/open-im start # 启动桥接
82
+ ```
83
+
84
+ 或全局安装:`npm install -g @wu529778790/open-im` 后执行 `open-im start`。
85
+
86
+ 配置文件:**`~/.open-im/config.json`**
87
+
88
+ ### 最小配置
83
89
 
84
90
  ```json
85
91
  {
86
92
  "tools": {
87
- "claude": { "workDir": "/path/to/project", "skipPermissions": true, "timeoutMs": 600000 }
93
+ "claude": { "workDir": "/path/to/project", "skipPermissions": true }
88
94
  },
89
95
  "platforms": {
90
96
  "telegram": { "enabled": true, "botToken": "YOUR_TELEGRAM_BOT_TOKEN" }
@@ -92,11 +98,11 @@ claude -c # 接上手机端的对话
92
98
  }
93
99
  ```
94
100
 
95
- **`platforms`** 下按需补充其他平台。完整模板请用 **`open-im init`**。
101
+ 完整模板请用 `open-im init`。
96
102
 
97
103
  ### Claude(Agent SDK)
98
104
 
99
- 无需本地 `claude` 可执行文件。第三方兼容接口示例:
105
+ 无需本地 `claude` 可执行文件。支持第三方兼容接口:
100
106
 
101
107
  ```json
102
108
  {
@@ -112,26 +118,37 @@ claude -c # 接上手机端的对话
112
118
  }
113
119
  ```
114
120
 
115
- ### 按平台指定 AI
121
+ ### CLI 命令
116
122
 
117
- 在每个平台上设置 **`platforms.<name>.aiCommand`**(`claude` / `codex` / `codebuddy`)。默认 `claude`。
123
+ | 命令 | 说明 |
124
+ | --- | --- |
125
+ | `open-im init` | 交互配置(不启动桥接) |
126
+ | `open-im start` | 后台运行桥接 |
127
+ | `open-im stop` | 停止后台服务 |
128
+ | `open-im restart` | 重启 |
129
+ | `open-im dashboard` | 仅 Web 配置服务(不启动桥接) |
118
130
 
119
- ### Web 控制台
131
+ ### 环境变量
120
132
 
121
- `open-im start` 在 **`OPEN_IM_WEB_PORT`**(默认 **39282**)提供内置页面与 **`/api/*`**。局域网访问:`export OPEN_IM_WEB_HOST=0.0.0.0`。
133
+ **`ANTHROPIC_*`**(shell `tools.claude.env`)、**`TELEGRAM_BOT_TOKEN`**、**`OPEN_IM_WEB_PORT`**、**`OPEN_IM_WEB_HOST`**,以及各平台的 `*_APP_ID`、`*_SECRET`、`WORKBUDDY_*` 等。
122
134
 
123
- ### 环境变量
135
+ ### Git 共同作者
124
136
 
125
- 常见:**`ANTHROPIC_*`**(shell **`tools.claude.env`**)、**`TELEGRAM_BOT_TOKEN`**、**`OPEN_IM_WEB_PORT`**、**`OPEN_IM_WEB_HOST`**,以及各平台的 `*_APP_ID`、`*_SECRET`、`WORKBUDDY_*` 等。
137
+ 默认在 AI 发起的提交里追加 `Co-authored-by`。关闭:设置环境变量 **`OPEN_IM_GIT_COAUTHOR=0`** 并重启桥接。
126
138
 
127
139
  ### 隐私
128
140
 
129
- 为改进稳定性,可能记录**匿名**运行信息(不含聊天或 prompt 内容)。若需关闭:环境变量 **`OPEN_IM_TELEMETRY=false`**,或 **`config.json`****`"telemetry": { "enabled": false }`**。
141
+ 为改进稳定性,可能记录**匿名**运行信息(不含聊天或 prompt 内容)。若需关闭:环境变量 **`OPEN_IM_TELEMETRY=false`**,或 `config.json``"telemetry": { "enabled": false }`。
130
142
 
131
143
  ## 平台配置与故障排除
132
144
 
133
145
  详见 **[docs/platforms.zh-CN.md](./docs/platforms.zh-CN.md)**。
134
146
 
147
+ ## 环境要求
148
+
149
+ - Node.js >= 20
150
+ - 至少配置一个 IM 平台 + 所选 AI 的凭证
151
+
135
152
  ## License
136
153
 
137
154
  [MIT](LICENSE)
@@ -6,7 +6,8 @@
6
6
  * - 支持 resume/cwd/model 等 options,无需 process.chdir hack
7
7
  * - SDK 内部管理 session 生命周期,无需手动维护 session pool
8
8
  */
9
- import type { SDKSessionInfo } from '@anthropic-ai/claude-agent-sdk';
9
+ import { query } from '@anthropic-ai/claude-agent-sdk';
10
+ import type { SDKSessionInfo, SessionMessage, ModelInfo, SDKControlGetContextUsageResponse, AccountInfo } from '@anthropic-ai/claude-agent-sdk';
10
11
  import type { ToolAdapter, RunCallbacks, RunOptions, RunHandle } from './tool-adapter.interface.js';
11
12
  interface ClaudeSessionMeta {
12
13
  sessionId: string;
@@ -28,6 +29,39 @@ export declare class ClaudeSDKAdapter implements ToolAdapter {
28
29
  * List sessions for a directory using the SDK's listSessions API.
29
30
  */
30
31
  static listSessionsForDir(workDir: string, limit?: number): Promise<SDKSessionInfo[]>;
32
+ /**
33
+ * Get session messages for a given session ID.
34
+ */
35
+ static getSessionMessagesForId(sessionId: string, workDir: string, limit?: number): Promise<SessionMessage[]>;
36
+ /**
37
+ * Delete a session by ID.
38
+ */
39
+ static deleteSessionById(sessionId: string, workDir?: string): Promise<boolean>;
40
+ /**
41
+ * Rename a session.
42
+ */
43
+ static renameSessionById(sessionId: string, title: string, workDir?: string): Promise<boolean>;
44
+ /**
45
+ * Fork a session.
46
+ */
47
+ static forkSessionById(sessionId: string, workDir?: string): Promise<string | undefined>;
48
+ /**
49
+ * Create a short-lived query for fetching session info (models, context, etc).
50
+ * The caller must close the returned query when done.
51
+ */
52
+ static createInfoQuery(workDir: string, model?: string): Promise<ReturnType<typeof query>>;
53
+ /**
54
+ * Get available models for a work directory.
55
+ */
56
+ static getSupportedModels(workDir: string, model?: string): Promise<ModelInfo[]>;
57
+ /**
58
+ * Get context usage for a work directory.
59
+ */
60
+ static getContextUsage(workDir: string, model?: string): Promise<SDKControlGetContextUsageResponse | undefined>;
61
+ /**
62
+ * Get account info for a work directory.
63
+ */
64
+ static getAccountInfo(workDir: string, model?: string): Promise<AccountInfo | undefined>;
31
65
  run(prompt: string, sessionId: string | undefined, workDir: string, callbacks: RunCallbacks, options?: RunOptions): RunHandle;
32
66
  }
33
67
  export {};
@@ -6,7 +6,7 @@
6
6
  * - 支持 resume/cwd/model 等 options,无需 process.chdir hack
7
7
  * - SDK 内部管理 session 生命周期,无需手动维护 session pool
8
8
  */
9
- import { query, listSessions } from '@anthropic-ai/claude-agent-sdk';
9
+ import { query, listSessions, getSessionMessages, deleteSession, renameSession, forkSession } from '@anthropic-ai/claude-agent-sdk';
10
10
  import { existsSync, readFileSync, statSync, openSync, readSync, closeSync } from 'fs';
11
11
  import { execSync } from 'child_process';
12
12
  import { homedir } from 'os';
@@ -15,6 +15,17 @@ import { createLogger } from '../logger.js';
15
15
  import { refreshClaudeEnvToProcess } from '../config/file-io.js';
16
16
  import { toReplyPlainText } from '../shared/utils.js';
17
17
  const log = createLogger('ClaudeSDK');
18
+ /**
19
+ * 注入交互式上下文指令,让 Claude 认为这是交互式终端会话。
20
+ * 解决 query() 非交互环境下 Claude 跳过用户选择、直接自主决策的问题。
21
+ */
22
+ const INTERACTIVE_CONTEXT = `[SYSTEM: You are in an interactive chat session via instant messenger. The user CAN and WILL respond to your messages — treat this like an interactive terminal session. Rules:
23
+ 1. When you need to make a decision involving user preference (choosing an approach, selecting between options, deciding what to do next), ALWAYS present clearly numbered options and WAIT for the user's response.
24
+ 2. Do NOT proceed autonomously when user input would be valuable.
25
+ 3. Only proceed autonomously for obvious single-path tasks (e.g. reading a file, running a simple command).
26
+ 4. When presenting options, format them as a numbered list and end with a question.
27
+ ]
28
+ `;
18
29
  function loadUserPluginSettings() {
19
30
  try {
20
31
  const settingsPath = join(homedir(), '.claude', 'settings.json');
@@ -199,7 +210,6 @@ export class ClaudeSDKAdapter {
199
210
  */
200
211
  static destroy() {
201
212
  // query() API 的 Query 对象通过 abortController.abort() 清理
202
- // 不再需要手动管理 session pool
203
213
  }
204
214
  /**
205
215
  * List sessions for a directory using the SDK's listSessions API.
@@ -213,6 +223,138 @@ export class ClaudeSDKAdapter {
213
223
  return [];
214
224
  }
215
225
  }
226
+ /**
227
+ * Get session messages for a given session ID.
228
+ */
229
+ static async getSessionMessagesForId(sessionId, workDir, limit = 50) {
230
+ try {
231
+ return await getSessionMessages(sessionId, { dir: workDir, limit });
232
+ }
233
+ catch (err) {
234
+ log.warn(`Failed to get session messages for ${sessionId}: ${err}`);
235
+ return [];
236
+ }
237
+ }
238
+ /**
239
+ * Delete a session by ID.
240
+ */
241
+ static async deleteSessionById(sessionId, workDir) {
242
+ try {
243
+ await deleteSession(sessionId, { dir: workDir });
244
+ return true;
245
+ }
246
+ catch (err) {
247
+ log.warn(`Failed to delete session ${sessionId}: ${err}`);
248
+ return false;
249
+ }
250
+ }
251
+ /**
252
+ * Rename a session.
253
+ */
254
+ static async renameSessionById(sessionId, title, workDir) {
255
+ try {
256
+ await renameSession(sessionId, title, { dir: workDir });
257
+ return true;
258
+ }
259
+ catch (err) {
260
+ log.warn(`Failed to rename session ${sessionId}: ${err}`);
261
+ return false;
262
+ }
263
+ }
264
+ /**
265
+ * Fork a session.
266
+ */
267
+ static async forkSessionById(sessionId, workDir) {
268
+ try {
269
+ const result = await forkSession(sessionId, { dir: workDir });
270
+ return result.sessionId;
271
+ }
272
+ catch (err) {
273
+ log.warn(`Failed to fork session ${sessionId}: ${err}`);
274
+ return undefined;
275
+ }
276
+ }
277
+ /**
278
+ * Create a short-lived query for fetching session info (models, context, etc).
279
+ * The caller must close the returned query when done.
280
+ */
281
+ static async createInfoQuery(workDir, model) {
282
+ const resolvedModel = model?.trim() || process.env.ANTHROPIC_MODEL?.trim() || 'claude-opus-4-5';
283
+ return query({
284
+ prompt: '',
285
+ options: {
286
+ cwd: workDir,
287
+ model: resolvedModel,
288
+ permissionMode: 'default',
289
+ },
290
+ });
291
+ }
292
+ /**
293
+ * Get available models for a work directory.
294
+ */
295
+ static async getSupportedModels(workDir, model) {
296
+ let q;
297
+ try {
298
+ q = await this.createInfoQuery(workDir, model);
299
+ return await q.supportedModels();
300
+ }
301
+ catch (err) {
302
+ log.warn(`Failed to get supported models: ${err}`);
303
+ return [];
304
+ }
305
+ finally {
306
+ if (q) {
307
+ try {
308
+ await q.return(undefined);
309
+ }
310
+ catch { /* ignore */ }
311
+ }
312
+ }
313
+ }
314
+ /**
315
+ * Get context usage for a work directory.
316
+ */
317
+ static async getContextUsage(workDir, model) {
318
+ let q;
319
+ try {
320
+ q = await this.createInfoQuery(workDir, model);
321
+ return await q.getContextUsage();
322
+ }
323
+ catch (err) {
324
+ log.warn(`Failed to get context usage: ${err}`);
325
+ return undefined;
326
+ }
327
+ finally {
328
+ if (q) {
329
+ try {
330
+ await q.return(undefined);
331
+ }
332
+ catch { /* ignore */ }
333
+ }
334
+ }
335
+ }
336
+ /**
337
+ * Get account info for a work directory.
338
+ */
339
+ static async getAccountInfo(workDir, model) {
340
+ let q;
341
+ try {
342
+ q = await this.createInfoQuery(workDir, model);
343
+ return await q.accountInfo();
344
+ }
345
+ catch (err) {
346
+ log.warn(`Failed to get account info: ${err}`);
347
+ return undefined;
348
+ }
349
+ finally {
350
+ if (q) {
351
+ try {
352
+ await q.return(undefined);
353
+ }
354
+ catch { /* ignore */ }
355
+ }
356
+ }
357
+ }
216
358
  run(prompt, sessionId, workDir, callbacks, options) {
217
359
  // 刷新 Claude 环境变量(支持 cc switch 后无需重启即可生效)
218
360
  refreshClaudeEnvToProcess();
@@ -255,12 +397,18 @@ export class ClaudeSDKAdapter {
255
397
  }
256
398
  }
257
399
  const q = query({
258
- prompt,
400
+ prompt: INTERACTIVE_CONTEXT + prompt,
259
401
  options: {
260
402
  cwd: workDir,
261
403
  model: resolvedModel,
262
404
  permissionMode,
405
+ // 启用完整工具集,与 cc 终端一致
406
+ tools: { type: 'preset', preset: 'claude_code' },
407
+ // 启用所有技能(superpowers, playwright 等),与 cc 终端一致
408
+ skills: 'all',
263
409
  ...(resumeId ? { resume: resumeId } : {}),
410
+ ...(options?.fallbackModel ? { fallbackModel: options.fallbackModel } : {}),
411
+ ...(options?.disallowedTools?.length ? { disallowedTools: options.disallowedTools } : {}),
264
412
  abortController,
265
413
  stderr: (data) => {
266
414
  recentStderr = appendStderrSnippet(recentStderr, data);
@@ -30,6 +30,10 @@ export interface RunOptions {
30
30
  hookPort?: number;
31
31
  /** Codex 专用:HTTP/HTTPS 代理地址,如 http://127.0.0.1:7890 */
32
32
  proxy?: string;
33
+ /** 备用模型,主模型过载时自动切换 */
34
+ fallbackModel?: string;
35
+ /** 禁用的工具列表 */
36
+ disallowedTools?: string[];
33
37
  }
34
38
  export interface RunHandle {
35
39
  abort: () => void;
@@ -10,5 +10,5 @@
10
10
  import type { Config } from '../config.js';
11
11
  import type { ClawBotState } from './types.js';
12
12
  export declare function getChannelState(): ClawBotState;
13
- export declare function initClawbot(config: Config, eventHandler: (chatId: string, msgId: string, content: string) => Promise<void>, onStateChange?: (state: ClawBotState) => void): Promise<void>;
13
+ export declare function initClawbot(config: Config, eventHandler: (chatId: string, msgId: string, content: string, imagePaths?: string[]) => Promise<void>, onStateChange?: (state: ClawBotState) => void): Promise<void>;
14
14
  export declare function stopClawbot(): void;