@wu529778790/open-im 1.0.3 → 1.1.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 +59 -3
- package/dist/commands/handler.d.ts +1 -1
- package/dist/config.d.ts +19 -1
- package/dist/config.js +69 -4
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/index.js +59 -12
- package/dist/setup.js +140 -29
- package/dist/shared/active-chats.d.ts +2 -2
- package/dist/wechat/auth/device-bind.d.ts +13 -0
- package/dist/wechat/auth/device-bind.js +76 -0
- package/dist/wechat/auth/device-guid.d.ts +5 -0
- package/dist/wechat/auth/device-guid.js +28 -0
- package/dist/wechat/auth/environments.d.ts +5 -0
- package/dist/wechat/auth/environments.js +21 -0
- package/dist/wechat/auth/index.d.ts +7 -0
- package/dist/wechat/auth/index.js +5 -0
- package/dist/wechat/auth/qclaw-api.d.ts +26 -0
- package/dist/wechat/auth/qclaw-api.js +100 -0
- package/dist/wechat/auth/types.d.ts +18 -0
- package/dist/wechat/auth/types.js +4 -0
- package/dist/wechat/auth/wechat-login.d.ts +17 -0
- package/dist/wechat/auth/wechat-login.js +172 -0
- package/dist/wechat/client.js +11 -2
- package/dist/wework/client.d.ts +46 -0
- package/dist/wework/client.js +356 -0
- package/dist/wework/event-handler.d.ts +12 -0
- package/dist/wework/event-handler.js +245 -0
- package/dist/wework/message-sender.d.ts +57 -0
- package/dist/wework/message-sender.js +258 -0
- package/dist/wework/types.d.ts +156 -0
- package/dist/wework/types.js +6 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# open-im
|
|
2
2
|
|
|
3
|
-
多平台 IM 桥接,将 Telegram、飞书 (Feishu/Lark)
|
|
3
|
+
多平台 IM 桥接,将 Telegram、飞书 (Feishu/Lark)、企业微信和微信连接到 AI CLI 工具(Claude Code、Codex、Cursor),实现移动端/远程访问 AI 编程助手。
|
|
4
4
|
|
|
5
5
|
## 功能特性
|
|
6
6
|
|
|
7
|
-
- **多平台**:支持 Telegram
|
|
7
|
+
- **多平台**:支持 Telegram、飞书、企业微信和微信,可同时启用
|
|
8
8
|
- **多 AI 工具**:通过配置切换 Claude Code / Codex / Cursor
|
|
9
9
|
- **流式输出**:节流更新,实时展示 AI 回复
|
|
10
10
|
- **会话管理**:每用户独立 session,`/new` 重置会话
|
|
@@ -71,6 +71,9 @@ npm run dev # 直接运行源码(tsx,无需 build)
|
|
|
71
71
|
| `WECHAT_APP_ID` | 微信应用 App ID(AGP 协议) |
|
|
72
72
|
| `WECHAT_APP_SECRET` | 微信应用 App Secret |
|
|
73
73
|
| `WECHAT_WS_URL` | AGP WebSocket URL(可选,默认使用官方服务) |
|
|
74
|
+
| `WEWORK_CORP_ID` | 企业微信机器人 ID(Bot ID) |
|
|
75
|
+
| `WEWORK_SECRET` | 企业微信机器人 Secret |
|
|
76
|
+
| `WEWORK_WS_URL` | 企业微信 WebSocket URL(可选,默认官方) |
|
|
74
77
|
| `ALLOWED_USER_IDS` | 白名单用户 ID(逗号分隔,空=所有人) |
|
|
75
78
|
| `AI_COMMAND` | `claude` \| `codex` \| `cursor`,默认 `claude` |
|
|
76
79
|
| `CLAUDE_CLI_PATH` | Claude CLI 路径,默认 `claude` |
|
|
@@ -86,10 +89,11 @@ npm run dev # 直接运行源码(tsx,无需 build)
|
|
|
86
89
|
|
|
87
90
|
配置优先级:环境变量 > `~/.open-im/config.json` > 默认值。
|
|
88
91
|
|
|
89
|
-
至少需配置 **Telegram
|
|
92
|
+
至少需配置 **Telegram**、**飞书**、**企业微信** 或 **微信** 其中一个:
|
|
90
93
|
|
|
91
94
|
- **Telegram**:`TELEGRAM_BOT_TOKEN` 或 `telegramBotToken`
|
|
92
95
|
- **飞书**:`FEISHU_APP_ID` + `FEISHU_APP_SECRET` 或 `feishuAppId` + `feishuAppSecret`
|
|
96
|
+
- **企业微信**:`WEWORK_CORP_ID` + `WEWORK_SECRET` 或 `platforms.wework.corpId` + `platforms.wework.secret`
|
|
93
97
|
- **微信**:`WECHAT_APP_ID` + `WECHAT_APP_SECRET` 或 `wechatAppId` + `wechatAppSecret`
|
|
94
98
|
|
|
95
99
|
### 飞书配置说明
|
|
@@ -107,6 +111,28 @@ npm run dev # 直接运行源码(tsx,无需 build)
|
|
|
107
111
|
|
|
108
112
|
**若点击 /mode 卡片按钮报错**:说明未配置卡片回调。配置较复杂时,可直接用 `/mode ask`、`/mode yolo` 等命令切换模式,无需卡片。
|
|
109
113
|
|
|
114
|
+
### 企业微信配置说明
|
|
115
|
+
|
|
116
|
+
1. 在 [企业微信管理后台](https://work.weixin.qq.com/) 创建企业自建应用
|
|
117
|
+
2. 进入「应用管理」→ 选择你的应用 → 获取 **AgentId** 和 **Secret**
|
|
118
|
+
3. 开启「智能机器人」能力,获取 **机器人 ID(Bot ID)** 和 **机器人 Secret**
|
|
119
|
+
4. 配置到 `~/.open-im/config.json`:
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"platforms": {
|
|
123
|
+
"wework": {
|
|
124
|
+
"enabled": true,
|
|
125
|
+
"corpId": "你的机器人ID",
|
|
126
|
+
"secret": "你的机器人Secret",
|
|
127
|
+
"allowedUserIds": []
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
5. 将机器人添加到目标群聊或发起私聊
|
|
133
|
+
|
|
134
|
+
**说明**:企业微信使用 WebSocket 长连接(`wss://openws.work.weixin.qq.com`),连接建立后会自动订阅,支持接收消息、回复消息和主动推送(如启动/关闭通知)。首次启动时,需用户先发一条消息,机器人才能向其推送启动通知。
|
|
135
|
+
|
|
110
136
|
## IM 内命令
|
|
111
137
|
|
|
112
138
|
| 命令 | 说明 |
|
|
@@ -165,6 +191,12 @@ npm run dev # 直接运行源码(tsx,无需 build)
|
|
|
165
191
|
"enabled": true,
|
|
166
192
|
"botToken": "你的Bot Token",
|
|
167
193
|
"allowedUserIds": ["你的Telegram用户ID"]
|
|
194
|
+
},
|
|
195
|
+
"wework": {
|
|
196
|
+
"enabled": true,
|
|
197
|
+
"corpId": "你的企业微信机器人ID",
|
|
198
|
+
"secret": "你的企业微信机器人Secret",
|
|
199
|
+
"allowedUserIds": []
|
|
168
200
|
}
|
|
169
201
|
},
|
|
170
202
|
"claudeWorkDir": "$(pwd)",
|
|
@@ -247,3 +279,27 @@ open-im init
|
|
|
247
279
|
4. 添加 **「卡片回传交互」**(`card.action.trigger`)— 若搜不到,可尝试搜「action」「trigger」或浏览分类
|
|
248
280
|
|
|
249
281
|
**更简单**:直接用 `/mode ask`、`/mode yolo` 等命令切换模式,无需配置卡片。
|
|
282
|
+
|
|
283
|
+
### Q: 企业微信 846609(aibot websocket not subscribed)?
|
|
284
|
+
|
|
285
|
+
说明在订阅确认完成前就发送了主动消息。当前版本已修复:连接建立后会等待服务端订阅确认(`errcode: 0`)后再发送启动通知。若仍出现,请检查网络或重启服务。
|
|
286
|
+
|
|
287
|
+
### Q: 企业微信收不到启动通知?
|
|
288
|
+
|
|
289
|
+
启动通知需要用户先发过消息,系统才能获取到 chatId。请先向机器人发送任意消息(如「你好」),之后重启服务即可收到启动/关闭通知。
|
|
290
|
+
|
|
291
|
+
### Q: 微信连接失败(错误 1006 或 500)?
|
|
292
|
+
|
|
293
|
+
微信使用 AGP 协议连接,该协议服务器由第三方提供。如果出现连接失败,可能原因:
|
|
294
|
+
|
|
295
|
+
1. **AGP 服务器限制**
|
|
296
|
+
- AGP 服务器使用了 Qclaw 通道,可能有白名单限制
|
|
297
|
+
- 独立客户端可能不在允许列表中
|
|
298
|
+
- token 或 guid 无效或已过期
|
|
299
|
+
|
|
300
|
+
2. **建议**
|
|
301
|
+
- 确认 token 和 guid 是否正确
|
|
302
|
+
- 尝试更新 token/guid(如果提供商支持)
|
|
303
|
+
- 或暂时使用其他平台(Telegram/飞书/企业微信)
|
|
304
|
+
|
|
305
|
+
**注意**:这是 AGP 协议服务器的限制,非本项目的 bug。如果 AGP 服务器调整策略,微信功能可能恢复正常。
|
|
@@ -21,7 +21,7 @@ export type ClaudeRequestHandler = (userId: string, chatId: string, prompt: stri
|
|
|
21
21
|
export declare class CommandHandler {
|
|
22
22
|
private deps;
|
|
23
23
|
constructor(deps: CommandHandlerDeps);
|
|
24
|
-
dispatch(text: string, chatId: string, userId: string, platform: 'feishu' | 'telegram' | 'wechat', handleClaudeRequest: ClaudeRequestHandler): Promise<boolean>;
|
|
24
|
+
dispatch(text: string, chatId: string, userId: string, platform: 'feishu' | 'telegram' | 'wechat' | 'wework', handleClaudeRequest: ClaudeRequestHandler): Promise<boolean>;
|
|
25
25
|
private handleMode;
|
|
26
26
|
private getClearHistoryHint;
|
|
27
27
|
private handleHelp;
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LogLevel } from './logger.js';
|
|
2
|
-
export type Platform = 'feishu' | 'telegram' | 'wechat';
|
|
2
|
+
export type Platform = 'feishu' | 'telegram' | 'wechat' | 'wework';
|
|
3
3
|
export type AiCommand = 'claude' | 'codex' | 'cursor';
|
|
4
4
|
export interface Config {
|
|
5
5
|
enabledPlatforms: Platform[];
|
|
@@ -8,11 +8,20 @@ export interface Config {
|
|
|
8
8
|
feishuAppSecret?: string;
|
|
9
9
|
wechatAppId?: string;
|
|
10
10
|
wechatAppSecret?: string;
|
|
11
|
+
wechatToken?: string;
|
|
12
|
+
wechatJwtToken?: string;
|
|
13
|
+
wechatLoginKey?: string;
|
|
14
|
+
wechatGuid?: string;
|
|
15
|
+
wechatUserId?: string;
|
|
11
16
|
wechatWsUrl?: string;
|
|
17
|
+
weworkCorpId?: string;
|
|
18
|
+
weworkSecret?: string;
|
|
19
|
+
weworkWsUrl?: string;
|
|
12
20
|
allowedUserIds: string[];
|
|
13
21
|
telegramAllowedUserIds: string[];
|
|
14
22
|
feishuAllowedUserIds: string[];
|
|
15
23
|
wechatAllowedUserIds: string[];
|
|
24
|
+
weworkAllowedUserIds: string[];
|
|
16
25
|
aiCommand: AiCommand;
|
|
17
26
|
claudeCliPath: string;
|
|
18
27
|
claudeWorkDir: string;
|
|
@@ -37,6 +46,15 @@ export interface Config {
|
|
|
37
46
|
wechat?: {
|
|
38
47
|
enabled: boolean;
|
|
39
48
|
wsUrl?: string;
|
|
49
|
+
token?: string;
|
|
50
|
+
jwtToken?: string;
|
|
51
|
+
loginKey?: string;
|
|
52
|
+
guid?: string;
|
|
53
|
+
userId?: string;
|
|
54
|
+
allowedUserIds: string[];
|
|
55
|
+
};
|
|
56
|
+
wework?: {
|
|
57
|
+
enabled: boolean;
|
|
40
58
|
allowedUserIds: string[];
|
|
41
59
|
};
|
|
42
60
|
};
|
package/dist/config.js
CHANGED
|
@@ -26,14 +26,22 @@ export function needsSetup() {
|
|
|
26
26
|
return false;
|
|
27
27
|
if (process.env.WECHAT_APP_ID && process.env.WECHAT_APP_SECRET)
|
|
28
28
|
return false;
|
|
29
|
+
if (process.env.WECHAT_TOKEN && process.env.WECHAT_GUID && process.env.WECHAT_USER_ID)
|
|
30
|
+
return false;
|
|
31
|
+
if (process.env.WEWORK_CORP_ID && process.env.WEWORK_SECRET)
|
|
32
|
+
return false;
|
|
29
33
|
const file = loadFileConfig();
|
|
30
34
|
const tg = file.platforms?.telegram;
|
|
31
35
|
const fs = file.platforms?.feishu;
|
|
32
36
|
const wc = file.platforms?.wechat;
|
|
37
|
+
const ww = file.platforms?.wework;
|
|
33
38
|
const hasTelegram = !!tg?.botToken;
|
|
34
39
|
const hasFeishu = !!(fs?.appId && fs?.appSecret);
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
// 微信支持 AGP 协议(token + guid + userId)或标准协议(appId + appSecret)
|
|
41
|
+
const hasWechat = !!(wc?.token && wc?.guid && wc?.userId) || !!(wc?.appId && wc?.appSecret);
|
|
42
|
+
// 企业微信只需要 corpId 和 secret
|
|
43
|
+
const hasWework = !!(ww?.corpId && ww?.secret);
|
|
44
|
+
return !hasTelegram && !hasFeishu && !hasWechat && !hasWework;
|
|
37
45
|
}
|
|
38
46
|
function parseCommaSeparated(value) {
|
|
39
47
|
return value.split(',').map((s) => s.trim()).filter(Boolean);
|
|
@@ -43,6 +51,7 @@ export function loadConfig() {
|
|
|
43
51
|
const fileTelegram = file.platforms?.telegram;
|
|
44
52
|
const fileFeishu = file.platforms?.feishu;
|
|
45
53
|
const fileWechat = file.platforms?.wechat;
|
|
54
|
+
const fileWework = file.platforms?.wework;
|
|
46
55
|
// 1. 加载各平台凭证(env 优先,其次新结构,最后旧字段)
|
|
47
56
|
const telegramBotToken = process.env.TELEGRAM_BOT_TOKEN ??
|
|
48
57
|
fileTelegram?.botToken ??
|
|
@@ -53,28 +62,53 @@ export function loadConfig() {
|
|
|
53
62
|
const feishuAppSecret = process.env.FEISHU_APP_SECRET ??
|
|
54
63
|
fileFeishu?.appSecret ??
|
|
55
64
|
file.feishuAppSecret;
|
|
65
|
+
// 微信支持两种协议:
|
|
66
|
+
// 1. AGP 协议:token + guid + userId(推荐)
|
|
67
|
+
// 2. 标准协议:appId + appSecret
|
|
68
|
+
const wechatToken = process.env.WECHAT_TOKEN ??
|
|
69
|
+
fileWechat?.token;
|
|
70
|
+
const wechatJwtToken = fileWechat?.jwtToken;
|
|
71
|
+
const wechatLoginKey = fileWechat?.loginKey;
|
|
72
|
+
const wechatGuid = process.env.WECHAT_GUID ??
|
|
73
|
+
fileWechat?.guid;
|
|
74
|
+
const wechatUserId = process.env.WECHAT_USER_ID ??
|
|
75
|
+
fileWechat?.userId;
|
|
56
76
|
const wechatAppId = process.env.WECHAT_APP_ID ??
|
|
57
77
|
fileWechat?.appId;
|
|
58
78
|
const wechatAppSecret = process.env.WECHAT_APP_SECRET ??
|
|
59
79
|
fileWechat?.appSecret;
|
|
60
80
|
const wechatWsUrl = process.env.WECHAT_WS_URL ??
|
|
61
81
|
fileWechat?.wsUrl;
|
|
82
|
+
const weworkCorpId = process.env.WEWORK_CORP_ID ??
|
|
83
|
+
fileWework?.corpId;
|
|
84
|
+
const weworkSecret = process.env.WEWORK_SECRET ??
|
|
85
|
+
fileWework?.secret;
|
|
86
|
+
const weworkWsUrl = process.env.WEWORK_WS_URL ??
|
|
87
|
+
fileWework?.wsUrl;
|
|
62
88
|
// 2. 计算启用平台
|
|
63
89
|
const enabledPlatforms = [];
|
|
64
90
|
const telegramEnabledFlag = fileTelegram?.enabled;
|
|
65
91
|
const feishuEnabledFlag = fileFeishu?.enabled;
|
|
66
92
|
const wechatEnabledFlag = fileWechat?.enabled;
|
|
93
|
+
const weworkEnabledFlag = fileWework?.enabled;
|
|
67
94
|
const telegramEnabled = !!telegramBotToken && (telegramEnabledFlag !== false);
|
|
68
95
|
const feishuEnabled = !!(feishuAppId && feishuAppSecret) && (feishuEnabledFlag !== false);
|
|
69
|
-
|
|
96
|
+
// 微信启用条件:AGP 协议凭证 或 标准协议凭证
|
|
97
|
+
const hasWechatAGPCreds = !!(wechatToken && wechatGuid && wechatUserId);
|
|
98
|
+
const hasWechatStandardCreds = !!(wechatAppId && wechatAppSecret);
|
|
99
|
+
const wechatEnabled = (hasWechatAGPCreds || hasWechatStandardCreds) && (wechatEnabledFlag !== false);
|
|
100
|
+
// 企业微信只需要 corpId (botId) 和 secret
|
|
101
|
+
const weworkEnabled = !!(weworkCorpId && weworkSecret) && (weworkEnabledFlag !== false);
|
|
70
102
|
if (telegramEnabled)
|
|
71
103
|
enabledPlatforms.push('telegram');
|
|
72
104
|
if (feishuEnabled)
|
|
73
105
|
enabledPlatforms.push('feishu');
|
|
74
106
|
if (wechatEnabled)
|
|
75
107
|
enabledPlatforms.push('wechat');
|
|
108
|
+
if (weworkEnabled)
|
|
109
|
+
enabledPlatforms.push('wework');
|
|
76
110
|
if (enabledPlatforms.length === 0) {
|
|
77
|
-
throw new Error('至少需要配置 Telegram、Feishu 或
|
|
111
|
+
throw new Error('至少需要配置 Telegram、Feishu、WeChat 或 WeWork 其中一个平台(可以通过环境变量或 config.json)');
|
|
78
112
|
}
|
|
79
113
|
// 3. 全局白名单(旧字段,向后兼容,主要用于作为 per-platform 的兜底)
|
|
80
114
|
const allowedUserIds = process.env.ALLOWED_USER_IDS !== undefined
|
|
@@ -90,6 +124,9 @@ export function loadConfig() {
|
|
|
90
124
|
const wechatAllowedUserIds = process.env.WECHAT_ALLOWED_USER_IDS !== undefined
|
|
91
125
|
? parseCommaSeparated(process.env.WECHAT_ALLOWED_USER_IDS)
|
|
92
126
|
: fileWechat?.allowedUserIds ?? allowedUserIds;
|
|
127
|
+
const weworkAllowedUserIds = process.env.WEWORK_ALLOWED_USER_IDS !== undefined
|
|
128
|
+
? parseCommaSeparated(process.env.WEWORK_ALLOWED_USER_IDS)
|
|
129
|
+
: fileWework?.allowedUserIds ?? allowedUserIds;
|
|
93
130
|
// 5. AI / 工作目录 / 安全配置
|
|
94
131
|
const aiCommand = (process.env.AI_COMMAND ?? file.aiCommand ?? 'claude');
|
|
95
132
|
const claudeCliPath = process.env.CLAUDE_CLI_PATH ?? file.claudeCliPath ?? 'claude';
|
|
@@ -176,13 +213,32 @@ export function loadConfig() {
|
|
|
176
213
|
? {
|
|
177
214
|
enabled: true,
|
|
178
215
|
wsUrl: wechatWsUrl,
|
|
216
|
+
token: wechatToken,
|
|
217
|
+
jwtToken: wechatJwtToken,
|
|
218
|
+
loginKey: wechatLoginKey,
|
|
219
|
+
guid: wechatGuid,
|
|
220
|
+
userId: wechatUserId,
|
|
179
221
|
allowedUserIds: wechatAllowedUserIds,
|
|
180
222
|
}
|
|
181
223
|
: {
|
|
182
224
|
enabled: false,
|
|
183
225
|
wsUrl: wechatWsUrl,
|
|
226
|
+
token: wechatToken,
|
|
227
|
+
jwtToken: wechatJwtToken,
|
|
228
|
+
loginKey: wechatLoginKey,
|
|
229
|
+
guid: wechatGuid,
|
|
230
|
+
userId: wechatUserId,
|
|
184
231
|
allowedUserIds: wechatAllowedUserIds,
|
|
185
232
|
},
|
|
233
|
+
wework: weworkEnabled
|
|
234
|
+
? {
|
|
235
|
+
enabled: true,
|
|
236
|
+
allowedUserIds: weworkAllowedUserIds,
|
|
237
|
+
}
|
|
238
|
+
: {
|
|
239
|
+
enabled: false,
|
|
240
|
+
allowedUserIds: weworkAllowedUserIds,
|
|
241
|
+
},
|
|
186
242
|
};
|
|
187
243
|
return {
|
|
188
244
|
enabledPlatforms,
|
|
@@ -191,11 +247,20 @@ export function loadConfig() {
|
|
|
191
247
|
feishuAppSecret: feishuAppSecret ?? '',
|
|
192
248
|
wechatAppId: wechatAppId ?? '',
|
|
193
249
|
wechatAppSecret: wechatAppSecret ?? '',
|
|
250
|
+
wechatToken: wechatToken,
|
|
251
|
+
wechatJwtToken: wechatJwtToken,
|
|
252
|
+
wechatLoginKey: wechatLoginKey,
|
|
253
|
+
wechatGuid: wechatGuid,
|
|
254
|
+
wechatUserId: wechatUserId,
|
|
194
255
|
wechatWsUrl: wechatWsUrl,
|
|
256
|
+
weworkCorpId: weworkCorpId ?? '',
|
|
257
|
+
weworkSecret: weworkSecret ?? '',
|
|
258
|
+
weworkWsUrl: weworkWsUrl,
|
|
195
259
|
allowedUserIds,
|
|
196
260
|
telegramAllowedUserIds,
|
|
197
261
|
feishuAllowedUserIds,
|
|
198
262
|
wechatAllowedUserIds,
|
|
263
|
+
weworkAllowedUserIds,
|
|
199
264
|
aiCommand,
|
|
200
265
|
claudeCliPath,
|
|
201
266
|
claudeWorkDir,
|
package/dist/constants.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare const FEISHU_THROTTLE_MS = 200;
|
|
|
11
11
|
export declare const TELEGRAM_THROTTLE_MS = 200;
|
|
12
12
|
/** WeChat 流式更新节流:1000ms(AGP 协议建议值) */
|
|
13
13
|
export declare const WECHAT_THROTTLE_MS = 1000;
|
|
14
|
+
export declare const WEWORK_THROTTLE_MS = 500;
|
|
14
15
|
export declare const MAX_TELEGRAM_MESSAGE_LENGTH = 4000;
|
|
15
16
|
export declare const MAX_FEISHU_MESSAGE_LENGTH = 4000;
|
|
16
17
|
export declare const MAX_WECHAT_MESSAGE_LENGTH = 2048;
|
|
18
|
+
export declare const MAX_WEWORK_MESSAGE_LENGTH = 2048;
|
package/dist/constants.js
CHANGED
|
@@ -40,6 +40,8 @@ export const FEISHU_THROTTLE_MS = 200;
|
|
|
40
40
|
export const TELEGRAM_THROTTLE_MS = 200;
|
|
41
41
|
/** WeChat 流式更新节流:1000ms(AGP 协议建议值) */
|
|
42
42
|
export const WECHAT_THROTTLE_MS = 1000;
|
|
43
|
+
export const WEWORK_THROTTLE_MS = 500;
|
|
43
44
|
export const MAX_TELEGRAM_MESSAGE_LENGTH = 4000;
|
|
44
45
|
export const MAX_FEISHU_MESSAGE_LENGTH = 4000;
|
|
45
46
|
export const MAX_WECHAT_MESSAGE_LENGTH = 2048;
|
|
47
|
+
export const MAX_WEWORK_MESSAGE_LENGTH = 2048;
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,9 @@ import { sendTextReply as sendFeishuTextReply } from "./feishu/message-sender.js
|
|
|
14
14
|
import { initWeChat, stopWeChat } from "./wechat/client.js";
|
|
15
15
|
import { setupWeChatHandlers } from "./wechat/event-handler.js";
|
|
16
16
|
import { sendTextReply as sendWeChatTextReply } from "./wechat/message-sender.js";
|
|
17
|
+
import { initWeWork, stopWeWork } from "./wework/client.js";
|
|
18
|
+
import { setupWeWorkHandlers } from "./wework/event-handler.js";
|
|
19
|
+
import { sendProactiveTextReply as sendWeWorkTextReply } from "./wework/message-sender.js";
|
|
17
20
|
import { initAdapters, cleanupAdapters } from "./adapters/registry.js";
|
|
18
21
|
import { SessionManager } from "./session/session-manager.js";
|
|
19
22
|
import { loadActiveChats, getActiveChatId, flushActiveChats, } from "./shared/active-chats.js";
|
|
@@ -29,6 +32,7 @@ async function sendLifecycleNotification(platform, message) {
|
|
|
29
32
|
const telegramChatId = getActiveChatId("telegram");
|
|
30
33
|
const feishuChatId = getActiveChatId("feishu");
|
|
31
34
|
const wechatChatId = getActiveChatId("wechat");
|
|
35
|
+
const weworkChatId = getActiveChatId("wework");
|
|
32
36
|
const sendPromises = [];
|
|
33
37
|
if (platform === "telegram" && telegramChatId) {
|
|
34
38
|
sendPromises.push(sendTelegramTextReply(telegramChatId, message).catch((err) => {
|
|
@@ -45,6 +49,11 @@ async function sendLifecycleNotification(platform, message) {
|
|
|
45
49
|
log.debug("Failed to send WeChat notification:", err);
|
|
46
50
|
}));
|
|
47
51
|
}
|
|
52
|
+
if (platform === "wework" && weworkChatId) {
|
|
53
|
+
sendPromises.push(sendWeWorkTextReply(weworkChatId, message).catch((err) => {
|
|
54
|
+
log.debug("Failed to send WeWork notification:", err);
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
48
57
|
await Promise.all(sendPromises);
|
|
49
58
|
}
|
|
50
59
|
export async function main() {
|
|
@@ -72,30 +81,66 @@ export async function main() {
|
|
|
72
81
|
let telegramHandle = null;
|
|
73
82
|
let feishuHandle = null;
|
|
74
83
|
let wechatHandle = null;
|
|
84
|
+
let weworkHandle = null;
|
|
85
|
+
// Track successfully initialized platforms
|
|
86
|
+
const successfulPlatforms = [];
|
|
75
87
|
if (config.enabledPlatforms.includes("telegram")) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
try {
|
|
89
|
+
await initTelegram(config, (bot) => {
|
|
90
|
+
telegramHandle = setupTelegramHandlers(bot, config, sessionManager);
|
|
91
|
+
});
|
|
92
|
+
successfulPlatforms.push("telegram");
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
log.error("Failed to initialize Telegram:", err);
|
|
96
|
+
}
|
|
79
97
|
}
|
|
80
98
|
if (config.enabledPlatforms.includes("feishu")) {
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
try {
|
|
100
|
+
feishuHandle = setupFeishuHandlers(config, sessionManager);
|
|
101
|
+
await initFeishu(config, feishuHandle.handleEvent);
|
|
102
|
+
successfulPlatforms.push("feishu");
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
log.error("Failed to initialize Feishu:", err);
|
|
106
|
+
}
|
|
83
107
|
}
|
|
84
108
|
if (config.enabledPlatforms.includes("wechat")) {
|
|
85
|
-
|
|
86
|
-
|
|
109
|
+
try {
|
|
110
|
+
wechatHandle = setupWeChatHandlers(config, sessionManager);
|
|
111
|
+
await initWeChat(config, wechatHandle.handleEvent);
|
|
112
|
+
successfulPlatforms.push("wechat");
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
log.error("Failed to initialize WeChat:", err);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (config.enabledPlatforms.includes("wework")) {
|
|
119
|
+
try {
|
|
120
|
+
weworkHandle = setupWeWorkHandlers(config, sessionManager);
|
|
121
|
+
await initWeWork(config, weworkHandle.handleEvent);
|
|
122
|
+
successfulPlatforms.push("wework");
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
log.error("Failed to initialize WeWork:", err);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Require at least one platform to start successfully
|
|
129
|
+
if (successfulPlatforms.length === 0) {
|
|
130
|
+
throw new Error("No platforms initialized successfully. Service cannot start.");
|
|
87
131
|
}
|
|
88
132
|
log.info("Service is running. Press Ctrl+C to stop.");
|
|
133
|
+
log.info(`Successfully initialized platforms: ${successfulPlatforms.join(", ")}`);
|
|
89
134
|
const startupMsg = [
|
|
90
135
|
`🟢 open-im v${APP_VERSION} 服务已启动`,
|
|
91
136
|
"",
|
|
92
137
|
`AI 工具: ${config.aiCommand}`,
|
|
93
138
|
`工作目录: ${config.claudeWorkDir}`,
|
|
94
139
|
`默认权限模式: ${defaultModeLabel} (${config.defaultPermissionMode})`,
|
|
95
|
-
|
|
140
|
+
`成功启动平台: ${successfulPlatforms.join(", ")}`,
|
|
96
141
|
].join("\n");
|
|
97
|
-
// Send notification to
|
|
98
|
-
for (const platform of
|
|
142
|
+
// Send notification only to successfully initialized platforms
|
|
143
|
+
for (const platform of successfulPlatforms) {
|
|
99
144
|
await sendLifecycleNotification(platform, startupMsg).catch(() => { });
|
|
100
145
|
}
|
|
101
146
|
const startedAt = Date.now();
|
|
@@ -106,8 +151,8 @@ export async function main() {
|
|
|
106
151
|
const uptimeSec = Math.floor((Date.now() - startedAt) / 1000);
|
|
107
152
|
const m = Math.floor(uptimeSec / 60);
|
|
108
153
|
const shutdownMsg = `🔴 open-im 服务正在关闭...\n运行时长: ${m}分钟`;
|
|
109
|
-
// Send notification to
|
|
110
|
-
for (const platform of
|
|
154
|
+
// Send notification only to successfully initialized platforms
|
|
155
|
+
for (const platform of successfulPlatforms) {
|
|
111
156
|
await sendLifecycleNotification(platform, shutdownMsg).catch(() => { });
|
|
112
157
|
}
|
|
113
158
|
shutdownServer?.close();
|
|
@@ -125,6 +170,8 @@ export async function main() {
|
|
|
125
170
|
stopFeishu();
|
|
126
171
|
wechatHandle?.stop();
|
|
127
172
|
stopWeChat();
|
|
173
|
+
weworkHandle?.stop();
|
|
174
|
+
stopWeWork();
|
|
128
175
|
stopPermissionServer();
|
|
129
176
|
sessionManager.destroy();
|
|
130
177
|
cleanupAdapters();
|