@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 +76 -59
- package/README.zh-CN.md +74 -57
- package/dist/adapters/claude-sdk-adapter.d.ts +35 -1
- package/dist/adapters/claude-sdk-adapter.js +151 -3
- package/dist/adapters/tool-adapter.interface.d.ts +4 -0
- package/dist/clawbot/client.d.ts +1 -1
- package/dist/clawbot/client.js +71 -3
- package/dist/clawbot/event-handler.d.ts +1 -1
- package/dist/clawbot/event-handler.js +10 -3
- package/dist/commands/handler.d.ts +7 -0
- package/dist/commands/handler.js +214 -1
- package/dist/config-web-page-i18n.d.ts +96 -4
- package/dist/config-web-page-i18n.js +98 -4
- package/dist/config-web.js +15 -0
- package/dist/constants.js +0 -1
- package/dist/index.js +11 -2
- package/dist/logger.d.ts +5 -0
- package/dist/logger.js +21 -0
- package/dist/platform/handle-text-flow.d.ts +2 -0
- package/dist/platform/handle-text-flow.js +35 -2
- package/dist/shared/message-wal.d.ts +31 -0
- package/dist/shared/message-wal.js +91 -0
- package/package.json +2 -2
- package/web/dist/assets/index-B1c1xlbx.css +1 -0
- package/web/dist/assets/index-Dng7B2mE.js +57 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-7fl61tV1.css +0 -1
- package/web/dist/assets/index-BaLTMeeF.js +0 -57
package/README.md
CHANGED
|
@@ -2,66 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
**English** · [中文](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
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
|

|
|
10
12
|
|
|
11
|
-
##
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
22
|
+
### Chat commands
|
|
46
23
|
|
|
47
24
|
| Command | Description |
|
|
48
25
|
| --- | --- |
|
|
49
|
-
| `/help` |
|
|
50
|
-
| `/new` |
|
|
51
|
-
| `/sessions` |
|
|
52
|
-
| `/resume [N]` | Resume session (no arg = most recent) |
|
|
53
|
-
| `/
|
|
54
|
-
| `/
|
|
55
|
-
| `/
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
57
|
+
### Platform support
|
|
79
58
|
|
|
80
|
-
|
|
59
|
+
Seven IM platforms, three AI backends, per-platform override:
|
|
81
60
|
|
|
82
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
###
|
|
121
|
+
### CLI reference
|
|
116
122
|
|
|
117
|
-
|
|
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
|
-
###
|
|
131
|
+
### Environment variables
|
|
120
132
|
|
|
121
|
-
|
|
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
|
-
###
|
|
135
|
+
### Git co-authors
|
|
124
136
|
|
|
125
|
-
|
|
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
|
|
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
|
-
|
|
5
|
+
> 你的 AI 编程助手,在每个聊天 App 里。
|
|
6
|
+
|
|
7
|
+
open-im 把 Claude Code、Codex、CodeBuddy 接入 Telegram、飞书、企业微信、钉钉、QQ、微信(WorkBuddy)、微信(ClawBot)。手机发条消息,服务器上就写好代码。
|
|
6
8
|
|
|
7
9
|
## 架构
|
|
8
10
|
|
|
9
11
|

|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## 为什么用 open-im
|
|
12
14
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
15
|
+
- **随时随地** — 通勤、排队、躺沙发上,手机发消息就能让 Claude Code 干活
|
|
16
|
+
- **无缝接力** — open-im 和 Claude Code CLI 共享 session,在手机上聊到一半,电脑上接着来
|
|
17
|
+
- **完整能力,简单界面** — 流式输出、会话管理、模型切换,全靠聊天命令搞定
|
|
18
|
+
- **一个桥接,多个平台** — 同一个 bot 支持 Telegram、飞书、钉钉、微信等
|
|
17
19
|
|
|
18
|
-
##
|
|
20
|
+
## 功能
|
|
19
21
|
|
|
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
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
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
|
-
| `/
|
|
54
|
-
| `/
|
|
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
|
-
|
|
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
|
-
|
|
57
|
+
### 平台支持
|
|
58
|
+
|
|
59
|
+
七个 IM 平台,三种 AI 后端,可按平台覆盖:
|
|
79
60
|
|
|
80
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
###
|
|
121
|
+
### CLI 命令
|
|
116
122
|
|
|
117
|
-
|
|
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
|
-
###
|
|
131
|
+
### 环境变量
|
|
120
132
|
|
|
121
|
-
|
|
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
|
-
|
|
137
|
+
默认在 AI 发起的提交里追加 `Co-authored-by`。关闭:设置环境变量 **`OPEN_IM_GIT_COAUTHOR=0`** 并重启桥接。
|
|
126
138
|
|
|
127
139
|
### 隐私
|
|
128
140
|
|
|
129
|
-
为改进稳定性,可能记录**匿名**运行信息(不含聊天或 prompt 内容)。若需关闭:环境变量 **`OPEN_IM_TELEMETRY=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
|
|
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;
|
package/dist/clawbot/client.d.ts
CHANGED
|
@@ -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;
|