@wu529778790/open-im 1.9.2 → 1.9.3-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.
@@ -36,7 +36,7 @@ setInterval(() => {
36
36
  break; // Clean one at a time to avoid blocking
37
37
  }
38
38
  }
39
- }, STREAM_MAX_AGE_MS);
39
+ }, STREAM_MAX_AGE_MS).unref();
40
40
  function generateMessageId() {
41
41
  return `${Date.now()}-${randomBytes(6).toString('hex')}`;
42
42
  }
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createServer } from "node:http";
2
2
  import { writeFileSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
3
+ import { randomUUID } from "node:crypto";
3
4
  import { dirname, join } from "node:path";
4
5
  import { getConfiguredAiCommands, loadConfig, needsSetup, resolvePlatformAiCommand } from "./config.js";
5
6
  import { runInteractiveSetup, runClaudeApiSetup } from "./setup.js";
@@ -22,6 +23,7 @@ import { initDingTalk, stopDingTalk, formatDingTalkInitError } from "./dingtalk/
22
23
  import { setupDingTalkHandlers } from "./dingtalk/event-handler.js";
23
24
  import { initWorkBuddy, stopWorkBuddy } from "./workbuddy/client.js";
24
25
  import { setupWorkBuddyHandlers } from "./workbuddy/event-handler.js";
26
+ import { sendTextReply as sendWorkBuddyTextReply } from "./workbuddy/message-sender.js";
25
27
  import { initAdapters, cleanupAdapters } from "./adapters/registry.js";
26
28
  import { SessionManager } from "./session/session-manager.js";
27
29
  import { loadActiveChats, getActiveChatId, flushActiveChats, } from "./shared/active-chats.js";
@@ -33,13 +35,14 @@ const require = createRequire(import.meta.url);
33
35
  const { version: APP_VERSION } = require("../package.json");
34
36
  const log = createLogger("Main");
35
37
  async function sendLifecycleNotification(platform, message) {
36
- // DingTalk 和 WorkBuddy 不支持主动发消息(OpenAPI 需 robotCode 等,易报 robot 不存在),跳过启动/关闭通知
37
- if (platform === "dingtalk" || platform === "workbuddy")
38
+ // DingTalk 不支持主动发消息(OpenAPI 需 robotCode 等,易报 robot 不存在),跳过启动/关闭通知
39
+ if (platform === "dingtalk")
38
40
  return;
39
41
  const telegramChatId = getActiveChatId("telegram");
40
42
  const feishuChatId = getActiveChatId("feishu");
41
43
  const qqChatId = getActiveChatId("qq");
42
44
  const weworkChatId = getActiveChatId("wework");
45
+ const workbuddyChatId = getActiveChatId("workbuddy");
43
46
  const sendPromises = [];
44
47
  if (platform === "telegram" && telegramChatId) {
45
48
  sendPromises.push(sendTelegramTextReply(telegramChatId, message).catch((err) => {
@@ -61,6 +64,11 @@ async function sendLifecycleNotification(platform, message) {
61
64
  log.debug("Failed to send WeWork notification:", err);
62
65
  }));
63
66
  }
67
+ if (platform === "workbuddy" && workbuddyChatId) {
68
+ sendPromises.push(sendWorkBuddyTextReply(null, workbuddyChatId, message, randomUUID()).catch((err) => {
69
+ log.debug("Failed to send WorkBuddy notification:", err);
70
+ }));
71
+ }
64
72
  await Promise.all(sendPromises);
65
73
  }
66
74
  function buildStartupMessage(platform, appVersion, aiCommand, defaultWorkDir, sessionManager) {
@@ -17,7 +17,7 @@ setInterval(() => {
17
17
  pendingReplies.delete(id);
18
18
  }
19
19
  }
20
- }, PENDING_MAX_AGE_MS);
20
+ }, PENDING_MAX_AGE_MS).unref();
21
21
  function parseChatTarget(chatId) {
22
22
  if (chatId.startsWith("group:")) {
23
23
  return { kind: "group", id: chatId.slice("group:".length) };
@@ -14,7 +14,7 @@ setInterval(() => {
14
14
  chatToPlatform.delete(key);
15
15
  }
16
16
  }
17
- }, 60 * 60 * 1000); // Check every hour
17
+ }, 60 * 60 * 1000).unref(); // Check every hour
18
18
  export function setChatUser(chatId, userId, platform) {
19
19
  chatToUser.set(chatId, userId);
20
20
  if (platform)
@@ -17,7 +17,7 @@ setInterval(() => {
17
17
  if (lastSentByMsg.size > 0) {
18
18
  lastSentByMsg.clear();
19
19
  }
20
- }, LAST_SENT_MAX_AGE_MS);
20
+ }, LAST_SENT_MAX_AGE_MS).unref();
21
21
  const STATUS_ICONS = {
22
22
  thinking: "🔵",
23
23
  streaming: "🔵",
@@ -112,7 +112,7 @@ setInterval(() => {
112
112
  log.info(`Cleaned up expired stream state: ${id}`);
113
113
  }
114
114
  }
115
- }, STREAM_CLEANUP_INTERVAL_MS);
115
+ }, STREAM_CLEANUP_INTERVAL_MS).unref();
116
116
  function sleep(ms) {
117
117
  return new Promise((resolve) => setTimeout(resolve, ms));
118
118
  }
@@ -91,10 +91,12 @@ export class WorkBuddyOAuth {
91
91
  }
92
92
  catch (e) {
93
93
  // code 11217 = still waiting, continue polling
94
- if (e?.message?.includes('11217'))
94
+ const msg = e instanceof Error ? e.message : '';
95
+ const code = e?.code;
96
+ if (msg.includes('11217'))
95
97
  continue;
96
98
  // network errors: retry
97
- if (e?.code === 'UND_ERR_CONNECT_TIMEOUT' || e?.code === 'ECONNREFUSED')
99
+ if (code === 'UND_ERR_CONNECT_TIMEOUT' || code === 'ECONNREFUSED')
98
100
  continue;
99
101
  throw e;
100
102
  }
@@ -133,7 +135,8 @@ export class WorkBuddyOAuth {
133
135
  return data.data;
134
136
  }
135
137
  catch (e) {
136
- if (e?.message?.includes('12151'))
138
+ const msg = e instanceof Error ? e.message : '';
139
+ if (msg.includes('12151'))
137
140
  continue;
138
141
  throw e;
139
142
  }
@@ -194,7 +197,8 @@ export class WorkBuddyOAuth {
194
197
  const body = await res.text().catch(() => '');
195
198
  return { success: false, message: `获取链接失败: ${res.status} ${body}` };
196
199
  }
197
- return (await res.json());
200
+ const body = (await res.json());
201
+ return body.data ?? { success: false, message: 'Empty response' };
198
202
  }
199
203
  /**
200
204
  * Check WeChat KF binding status
@@ -209,7 +213,8 @@ export class WorkBuddyOAuth {
209
213
  if (!res.ok) {
210
214
  return { success: false, bound: false, message: `查询状态失败: ${res.status}` };
211
215
  }
212
- return (await res.json());
216
+ const body = (await res.json());
217
+ return body.data ?? { success: false, bound: false, message: 'Empty response' };
213
218
  }
214
219
  /**
215
220
  * Poll binding status until bound
@@ -266,7 +271,8 @@ export class WorkBuddyOAuth {
266
271
  const body = await res.text().catch(() => '');
267
272
  throw new Error(`registerChannel failed: ${res.status} ${body}`);
268
273
  }
269
- return (await res.json());
274
+ const body = (await res.json());
275
+ return body.data ?? {};
270
276
  }
271
277
  /**
272
278
  * Send response to WeChat KF
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.9.2",
3
+ "version": "1.9.3-beta.1",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,8 +29,7 @@
29
29
  "dingtalk",
30
30
  "telegram",
31
31
  "feishu",
32
- "wechat",
33
- "weixin",
32
+ "workbuddy",
34
33
  "claude",
35
34
  "claude-code",
36
35
  "bot",
@@ -48,7 +47,6 @@
48
47
  "dependencies": {
49
48
  "@anthropic-ai/claude-agent-sdk": "^0.2.86",
50
49
  "@larksuiteoapi/node-sdk": "^1.59.0",
51
- "@wu529778790/open-im": "^1.8.1-beta.8",
52
50
  "centrifuge": "^5.3.0",
53
51
  "dingtalk-stream": "^2.1.4",
54
52
  "prompts": "^2.4.2",