@wu529778790/open-im 1.8.1-beta.7 → 1.8.1-beta.9
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/dist/adapters/claude-sdk-adapter.js +10 -0
- package/dist/config-web-page-i18n.d.ts +12 -0
- package/dist/config-web-page-i18n.js +12 -0
- package/dist/config-web-page-script.js +1 -0
- package/dist/config-web-page-template.js +48 -1
- package/dist/dingtalk/event-handler.js +12 -1
- package/dist/feishu/event-handler.js +19 -1
- package/dist/qq/event-handler.js +12 -1
- package/dist/shared/ai-task.js +13 -1
- package/dist/telegram/client.js +2 -2
- package/dist/telegram/event-handler.js +4 -0
- package/dist/wechat/event-handler.js +4 -0
- package/dist/wework/client.js +4 -8
- package/dist/wework/event-handler.js +12 -1
- package/package.json +2 -1
|
@@ -263,6 +263,11 @@ export class ClaudeSDKAdapter {
|
|
|
263
263
|
if (abortController.signal.aborted) {
|
|
264
264
|
log.info('Session run aborted');
|
|
265
265
|
clearRunTimeout();
|
|
266
|
+
// 清理 pending tempId
|
|
267
|
+
if (actualSessionId?.startsWith('pending-')) {
|
|
268
|
+
activeSessions.delete(actualSessionId);
|
|
269
|
+
log.info(`Cleaned up pending session: ${actualSessionId}`);
|
|
270
|
+
}
|
|
266
271
|
return;
|
|
267
272
|
}
|
|
268
273
|
runSettled = true;
|
|
@@ -273,6 +278,11 @@ export class ClaudeSDKAdapter {
|
|
|
273
278
|
if (errorObj.stack) {
|
|
274
279
|
log.error(`Error stack: ${errorObj.stack}`);
|
|
275
280
|
}
|
|
281
|
+
// 清理 pending tempId(session 在获取真实 ID 前就失败了)
|
|
282
|
+
if (actualSessionId?.startsWith('pending-')) {
|
|
283
|
+
activeSessions.delete(actualSessionId);
|
|
284
|
+
log.info(`Cleaned up pending session after error: ${actualSessionId}`);
|
|
285
|
+
}
|
|
276
286
|
callbacks.onError(msg);
|
|
277
287
|
}
|
|
278
288
|
};
|
|
@@ -50,6 +50,7 @@ export declare const PAGE_TEXTS: {
|
|
|
50
50
|
readonly qqSummary: "App ID and secret for bot access.";
|
|
51
51
|
readonly weworkSummary: "Corp ID and secret for enterprise delivery.";
|
|
52
52
|
readonly dingtalkSummary: "Client credentials plus optional card template.";
|
|
53
|
+
readonly workbuddySummary: "CodeBuddy OAuth for WeChat customer service.";
|
|
53
54
|
readonly platformCredentialsTitle: "Credentials";
|
|
54
55
|
readonly platformAccessTitle: "Routing and access";
|
|
55
56
|
readonly platformTestNote: "Checks required credentials against the platform.";
|
|
@@ -70,8 +71,13 @@ export declare const PAGE_TEXTS: {
|
|
|
70
71
|
readonly clientId: "Client ID / AppKey";
|
|
71
72
|
readonly clientSecret: "Client Secret / AppSecret";
|
|
72
73
|
readonly dingtalkHelp: "Get credentials: Create an enterprise internal app on <a href=\"https://open-dev.dingtalk.com/\" target=\"_blank\">DingTalk Open Platform</a>, enable Stream Mode, and get Client ID / Client Secret";
|
|
74
|
+
readonly workbuddyHelp: "Get credentials: Login via CodeBuddy OAuth to get access/refresh tokens. WorkBuddy connects WeChat customer service through Centrifuge WebSocket.";
|
|
73
75
|
readonly secret: "Secret";
|
|
74
76
|
readonly cardTemplateId: "Card template ID";
|
|
77
|
+
readonly workbuddyAccessToken: "Access Token";
|
|
78
|
+
readonly workbuddyRefreshToken: "Refresh Token";
|
|
79
|
+
readonly workbuddyUserId: "User ID";
|
|
80
|
+
readonly workbuddyBaseUrl: "Base URL";
|
|
75
81
|
readonly optional: "Optional";
|
|
76
82
|
readonly commaSeparatedIds: "Comma-separated IDs";
|
|
77
83
|
readonly aiTitle: "AI Tooling";
|
|
@@ -178,6 +184,7 @@ export declare const PAGE_TEXTS: {
|
|
|
178
184
|
readonly qqSummary: "QQ 机器人 App ID 与 Secret。";
|
|
179
185
|
readonly weworkSummary: "企业微信 Corp ID 与 Secret。";
|
|
180
186
|
readonly dingtalkSummary: "钉钉 Client 凭证,可选配置卡片模板 ID。";
|
|
187
|
+
readonly workbuddySummary: "CodeBuddy OAuth 连接微信客服。";
|
|
181
188
|
readonly platformCredentialsTitle: "凭证";
|
|
182
189
|
readonly platformAccessTitle: "路由与访问";
|
|
183
190
|
readonly platformTestNote: "只会检查该平台的必填凭证是否可用。";
|
|
@@ -198,7 +205,12 @@ export declare const PAGE_TEXTS: {
|
|
|
198
205
|
readonly clientId: "Client ID / AppKey";
|
|
199
206
|
readonly clientSecret: "Client Secret / AppSecret";
|
|
200
207
|
readonly dingtalkHelp: "获取凭证:在 <a href=\"https://open-dev.dingtalk.com/\" target=\"_blank\">钉钉开放平台</a> 创建企业内部应用,启用 Stream Mode,并拿到 Client ID / Client Secret";
|
|
208
|
+
readonly workbuddyHelp: "获取凭证:通过 CodeBuddy OAuth 登录获取 access/refresh token。WorkBuddy 通过 Centrifuge WebSocket 连接微信客服。";
|
|
201
209
|
readonly cardTemplateId: "卡片模板 ID";
|
|
210
|
+
readonly workbuddyAccessToken: "Access Token";
|
|
211
|
+
readonly workbuddyRefreshToken: "Refresh Token";
|
|
212
|
+
readonly workbuddyUserId: "User ID";
|
|
213
|
+
readonly workbuddyBaseUrl: "基础 URL";
|
|
202
214
|
readonly optional: "可选";
|
|
203
215
|
readonly commaSeparatedIds: "多个 ID 用逗号分隔";
|
|
204
216
|
readonly aiTitle: "AI 工具配置";
|
|
@@ -50,6 +50,7 @@ export const PAGE_TEXTS = {
|
|
|
50
50
|
qqSummary: "App ID and secret for bot access.",
|
|
51
51
|
weworkSummary: "Corp ID and secret for enterprise delivery.",
|
|
52
52
|
dingtalkSummary: "Client credentials plus optional card template.",
|
|
53
|
+
workbuddySummary: "CodeBuddy OAuth for WeChat customer service.",
|
|
53
54
|
platformCredentialsTitle: "Credentials",
|
|
54
55
|
platformAccessTitle: "Routing and access",
|
|
55
56
|
platformTestNote: "Checks required credentials against the platform.",
|
|
@@ -70,8 +71,13 @@ export const PAGE_TEXTS = {
|
|
|
70
71
|
clientId: "Client ID / AppKey",
|
|
71
72
|
clientSecret: "Client Secret / AppSecret",
|
|
72
73
|
dingtalkHelp: 'Get credentials: Create an enterprise internal app on <a href="https://open-dev.dingtalk.com/" target="_blank">DingTalk Open Platform</a>, enable Stream Mode, and get Client ID / Client Secret',
|
|
74
|
+
workbuddyHelp: 'Get credentials: Login via CodeBuddy OAuth to get access/refresh tokens. WorkBuddy connects WeChat customer service through Centrifuge WebSocket.',
|
|
73
75
|
secret: "Secret",
|
|
74
76
|
cardTemplateId: "Card template ID",
|
|
77
|
+
workbuddyAccessToken: "Access Token",
|
|
78
|
+
workbuddyRefreshToken: "Refresh Token",
|
|
79
|
+
workbuddyUserId: "User ID",
|
|
80
|
+
workbuddyBaseUrl: "Base URL",
|
|
75
81
|
optional: "Optional",
|
|
76
82
|
commaSeparatedIds: "Comma-separated IDs",
|
|
77
83
|
aiTitle: "AI Tooling",
|
|
@@ -178,6 +184,7 @@ export const PAGE_TEXTS = {
|
|
|
178
184
|
qqSummary: "QQ \u673a\u5668\u4eba App ID \u4e0e Secret\u3002",
|
|
179
185
|
weworkSummary: "\u4f01\u4e1a\u5fae\u4fe1 Corp ID \u4e0e Secret\u3002",
|
|
180
186
|
dingtalkSummary: "\u9489\u9489 Client \u51ed\u8bc1\uff0c\u53ef\u9009\u914d\u7f6e\u5361\u7247\u6a21\u677f ID\u3002",
|
|
187
|
+
workbuddySummary: "CodeBuddy OAuth \u8fde\u63a5\u5fae\u4fe1\u5ba2\u670d\u3002",
|
|
181
188
|
platformCredentialsTitle: "\u51ed\u8bc1",
|
|
182
189
|
platformAccessTitle: "\u8def\u7531\u4e0e\u8bbf\u95ee",
|
|
183
190
|
platformTestNote: "\u53ea\u4f1a\u68c0\u67e5\u8be5\u5e73\u53f0\u7684\u5fc5\u586b\u51ed\u8bc1\u662f\u5426\u53ef\u7528\u3002",
|
|
@@ -198,7 +205,12 @@ export const PAGE_TEXTS = {
|
|
|
198
205
|
clientId: "Client ID / AppKey",
|
|
199
206
|
clientSecret: "Client Secret / AppSecret",
|
|
200
207
|
dingtalkHelp: '\u83b7\u53d6\u51ed\u8bc1\uff1a\u5728 <a href="https://open-dev.dingtalk.com/" target="_blank">\u9489\u9489\u5f00\u653e\u5e73\u53f0</a> \u521b\u5efa\u4f01\u4e1a\u5185\u90e8\u5e94\u7528\uff0c\u542f\u7528 Stream Mode\uff0c\u5e76\u62ff\u5230 Client ID / Client Secret',
|
|
208
|
+
workbuddyHelp: '\u83b7\u53d6\u51ed\u8bc1\uff1a\u901a\u8fc7 CodeBuddy OAuth \u767b\u5f55\u83b7\u53d6 access/refresh token\u3002WorkBuddy \u901a\u8fc7 Centrifuge WebSocket \u8fde\u63a5\u5fae\u4fe1\u5ba2\u670d\u3002',
|
|
201
209
|
cardTemplateId: "\u5361\u7247\u6a21\u677f ID",
|
|
210
|
+
workbuddyAccessToken: "Access Token",
|
|
211
|
+
workbuddyRefreshToken: "Refresh Token",
|
|
212
|
+
workbuddyUserId: "User ID",
|
|
213
|
+
workbuddyBaseUrl: "\u57fa\u7840 URL",
|
|
202
214
|
optional: "\u53ef\u9009",
|
|
203
215
|
commaSeparatedIds: "\u591a\u4e2a ID \u7528\u9017\u53f7\u5206\u9694",
|
|
204
216
|
aiTitle: "AI \u5de5\u5177\u914d\u7f6e",
|
|
@@ -4,6 +4,7 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
|
|
|
4
4
|
{ key: "qq", label: "QQ", fields: ["aiCommand", "appId", "secret", "allowedUserIds"], testFields: ["appId", "secret"], requiredFields: ["appId", "secret"] },
|
|
5
5
|
{ key: "wework", label: "WeWork", fields: ["aiCommand", "corpId", "secret", "allowedUserIds"], testFields: ["corpId", "secret"], requiredFields: ["corpId", "secret"] },
|
|
6
6
|
{ key: "dingtalk", label: "DingTalk", fields: ["aiCommand", "clientId", "clientSecret", "cardTemplateId", "allowedUserIds"], testFields: ["clientId", "clientSecret"], requiredFields: ["clientId", "clientSecret"] },
|
|
7
|
+
{ key: "workbuddy", label: "WorkBuddy", fields: ["aiCommand", "accessToken", "refreshToken", "userId", "baseUrl", "allowedUserIds"], testFields: ["accessToken", "refreshToken", "userId"], requiredFields: ["accessToken", "refreshToken", "userId"] },
|
|
7
8
|
];
|
|
8
9
|
const platformKeys = platformDefinitions.map((platform) => platform.key);
|
|
9
10
|
const aiTools = ["claude", "codex", "codebuddy"];
|
|
@@ -828,7 +828,7 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
|
|
|
828
828
|
<div class="stats-grid">
|
|
829
829
|
<div class="stat-card">
|
|
830
830
|
<div class="stat-label" id="statConfiguredLabel">Configured</div>
|
|
831
|
-
<div class="stat-value" id="statConfiguredValue">0/
|
|
831
|
+
<div class="stat-value" id="statConfiguredValue">0/6</div>
|
|
832
832
|
</div>
|
|
833
833
|
<div class="stat-card">
|
|
834
834
|
<div class="stat-label" id="statEnabledLabel">Enabled</div>
|
|
@@ -1058,6 +1058,53 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
|
|
|
1058
1058
|
<div id="test-dingtalk-result" class="mt-4"></div>
|
|
1059
1059
|
</div>
|
|
1060
1060
|
</div>
|
|
1061
|
+
|
|
1062
|
+
<!-- WorkBuddy -->
|
|
1063
|
+
<div class="platform-card">
|
|
1064
|
+
<div class="platform-header">
|
|
1065
|
+
<h3 class="platform-title">WorkBuddy</h3>
|
|
1066
|
+
<label class="toggle">
|
|
1067
|
+
<input type="checkbox" id="workbuddy-enabled" class="toggle-input">
|
|
1068
|
+
<span class="toggle-switch"></span>
|
|
1069
|
+
<span class="toggle-label" id="workbuddy-label">Enabled</span>
|
|
1070
|
+
</label>
|
|
1071
|
+
</div>
|
|
1072
|
+
<div class="platform-body">
|
|
1073
|
+
<div class="form-group">
|
|
1074
|
+
<label class="form-label" id="workbuddy-aiCommand-label">AI Tool</label>
|
|
1075
|
+
<select id="workbuddy-aiCommand" class="form-select">
|
|
1076
|
+
<option value="claude">claude</option>
|
|
1077
|
+
<option value="codex">codex</option>
|
|
1078
|
+
<option value="codebuddy">codebuddy</option>
|
|
1079
|
+
</select>
|
|
1080
|
+
</div>
|
|
1081
|
+
<div class="form-group">
|
|
1082
|
+
<label class="form-label" id="workbuddy-accessToken-label">Access Token</label>
|
|
1083
|
+
<input id="workbuddy-accessToken" class="form-input mono" type="password" autocomplete="off" />
|
|
1084
|
+
</div>
|
|
1085
|
+
<div class="form-group">
|
|
1086
|
+
<label class="form-label" id="workbuddy-refreshToken-label">Refresh Token</label>
|
|
1087
|
+
<input id="workbuddy-refreshToken" class="form-input mono" type="password" autocomplete="off" />
|
|
1088
|
+
</div>
|
|
1089
|
+
<div class="form-group">
|
|
1090
|
+
<label class="form-label" id="workbuddy-userId-label">User ID</label>
|
|
1091
|
+
<input id="workbuddy-userId" class="form-input mono" type="text" />
|
|
1092
|
+
</div>
|
|
1093
|
+
<div class="form-group">
|
|
1094
|
+
<label class="form-label" id="workbuddy-baseUrl-label">Base URL (optional)</label>
|
|
1095
|
+
<input id="workbuddy-baseUrl" class="form-input mono" type="text" placeholder="https://copilot.tencent.com" />
|
|
1096
|
+
</div>
|
|
1097
|
+
<div class="form-group">
|
|
1098
|
+
<label class="form-label" id="workbuddy-allowedUserIds-label">Allowed User IDs</label>
|
|
1099
|
+
<textarea id="workbuddy-allowedUserIds" class="form-textarea mono"></textarea>
|
|
1100
|
+
</div>
|
|
1101
|
+
<div class="form-help" id="workbuddy-help">WorkBuddy uses CodeBuddy OAuth to connect WeChat customer service. Get credentials from CodeBuddy login.</div>
|
|
1102
|
+
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
|
|
1103
|
+
<button id="test-workbuddy" class="btn btn-secondary btn-sm" type="button">Test Configuration</button>
|
|
1104
|
+
</div>
|
|
1105
|
+
<div id="test-workbuddy-result" class="mt-4"></div>
|
|
1106
|
+
</div>
|
|
1107
|
+
</div>
|
|
1061
1108
|
</div>
|
|
1062
1109
|
</section>
|
|
1063
1110
|
|
|
@@ -185,7 +185,18 @@ export function setupDingTalkHandlers(config, sessionManager) {
|
|
|
185
185
|
: undefined;
|
|
186
186
|
log.info(`[AI_REQUEST] Running ${aiCommand} for user ${userId}, sessionId=${sessionId ?? 'new'}`);
|
|
187
187
|
const toolId = aiCommand;
|
|
188
|
-
|
|
188
|
+
let msgId;
|
|
189
|
+
try {
|
|
190
|
+
msgId = await sendThinkingMessage(chatId, replyToMessageId, toolId, dingtalkTarget);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
log.error('Failed to send thinking message:', err);
|
|
194
|
+
try {
|
|
195
|
+
await sendTextReply(chatId, '启动 AI 处理失败,请重试。');
|
|
196
|
+
}
|
|
197
|
+
catch { /* ignore */ }
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
189
200
|
const stopTyping = startTypingLoop(chatId);
|
|
190
201
|
const taskKey = `${userId}:${msgId}`;
|
|
191
202
|
await runAITask({ config, sessionManager }, { userId, chatId, workDir, sessionId, convId, platform: 'dingtalk', taskKey }, prompt, toolAdapter, {
|
|
@@ -62,14 +62,32 @@ export function setupFeishuHandlers(config, sessionManager) {
|
|
|
62
62
|
}
|
|
63
63
|
catch (err) {
|
|
64
64
|
log.error('Failed to send thinking card:', err);
|
|
65
|
+
try {
|
|
66
|
+
await sendTextReply(chatId, '启动 AI 处理失败,请重试。');
|
|
67
|
+
}
|
|
68
|
+
catch { /* ignore */ }
|
|
65
69
|
return;
|
|
66
70
|
}
|
|
67
71
|
const { messageId: msgId, cardId } = cardHandle;
|
|
68
72
|
const stopTyping = startTypingLoop(chatId);
|
|
69
73
|
const taskKey = `${userId}:${cardId}`;
|
|
74
|
+
let consecutiveStreamErrors = 0;
|
|
75
|
+
const MAX_STREAM_ERRORS = 5;
|
|
70
76
|
const streamUpdate = (content, toolNote) => {
|
|
77
|
+
if (consecutiveStreamErrors >= MAX_STREAM_ERRORS)
|
|
78
|
+
return; // 停止尝试
|
|
71
79
|
const note = buildProgressNote(toolNote);
|
|
72
|
-
streamContentUpdate(cardId, content, note).
|
|
80
|
+
streamContentUpdate(cardId, content, note).then(() => {
|
|
81
|
+
consecutiveStreamErrors = 0;
|
|
82
|
+
}).catch((e) => {
|
|
83
|
+
consecutiveStreamErrors++;
|
|
84
|
+
if (consecutiveStreamErrors >= MAX_STREAM_ERRORS) {
|
|
85
|
+
log.warn(`Stream update failed ${consecutiveStreamErrors} times consecutively, giving up: ${e?.message ?? e}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
log.debug('Stream update failed (will retry on next update):', e?.message ?? e);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
73
91
|
};
|
|
74
92
|
await runAITask({ config, sessionManager }, { userId, chatId, workDir, sessionId, convId, platform: 'feishu', taskKey }, prompt, toolAdapter, {
|
|
75
93
|
throttleMs: CARDKIT_THROTTLE_MS,
|
package/dist/qq/event-handler.js
CHANGED
|
@@ -144,7 +144,18 @@ export function setupQQHandlers(config, sessionManager) {
|
|
|
144
144
|
? sessionManager.getSessionIdForConv(userId, convId, aiCommand)
|
|
145
145
|
: undefined;
|
|
146
146
|
const toolId = aiCommand;
|
|
147
|
-
|
|
147
|
+
let msgId;
|
|
148
|
+
try {
|
|
149
|
+
msgId = await sendThinkingMessage(chatId, replyToMessageId, toolId);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
log.error("Failed to send thinking message:", err);
|
|
153
|
+
try {
|
|
154
|
+
await sendTextReply(chatId, "启动 AI 处理失败,请重试。");
|
|
155
|
+
}
|
|
156
|
+
catch { /* ignore */ }
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
148
159
|
const stopTyping = startTypingLoop();
|
|
149
160
|
const taskKey = `${userId}:${msgId}`;
|
|
150
161
|
await runAITask({ config, sessionManager }, { userId, chatId, workDir, sessionId, convId, platform: "qq", taskKey }, prompt, toolAdapter, {
|
package/dist/shared/ai-task.js
CHANGED
|
@@ -247,7 +247,19 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
247
247
|
startedAt: Date.now(),
|
|
248
248
|
toolId: aiCommand,
|
|
249
249
|
};
|
|
250
|
-
|
|
250
|
+
try {
|
|
251
|
+
startRun();
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
if (!settled) {
|
|
255
|
+
settled = true;
|
|
256
|
+
cleanup();
|
|
257
|
+
log.error(`[AITask] Synchronous error in startRun: ${err}`);
|
|
258
|
+
platformAdapter.sendError(`内部错误:${err instanceof Error ? err.message : String(err)}`).catch(() => { });
|
|
259
|
+
resolve();
|
|
260
|
+
}
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
251
263
|
platformAdapter.onTaskReady(taskState);
|
|
252
264
|
});
|
|
253
265
|
}
|
package/dist/telegram/client.js
CHANGED
|
@@ -39,8 +39,8 @@ export async function initTelegram(config, setupHandlers) {
|
|
|
39
39
|
await new Promise((r) => setTimeout(r, delayMs));
|
|
40
40
|
return launchWithRetry(attempt + 1);
|
|
41
41
|
}
|
|
42
|
-
log.error("Telegram gave up reconnecting,
|
|
43
|
-
|
|
42
|
+
log.error("Telegram gave up reconnecting, skipping");
|
|
43
|
+
// 不再 exit(1),让其他通道继续运行
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
void launchWithRetry();
|
|
@@ -107,6 +107,10 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
|
|
|
107
107
|
}
|
|
108
108
|
catch (err) {
|
|
109
109
|
log.error("Failed to send thinking message:", err);
|
|
110
|
+
try {
|
|
111
|
+
await sendTextReply(chatId, "启动 AI 处理失败,请重试。");
|
|
112
|
+
}
|
|
113
|
+
catch { /* ignore */ }
|
|
110
114
|
return;
|
|
111
115
|
}
|
|
112
116
|
const stopTyping = startTypingLoop(chatId);
|
|
@@ -130,6 +130,10 @@ export function setupWeChatHandlers(config, sessionManager) {
|
|
|
130
130
|
}
|
|
131
131
|
catch (err) {
|
|
132
132
|
log.error('Failed to send thinking message:', err);
|
|
133
|
+
try {
|
|
134
|
+
await sendTextReply(chatId, '启动 AI 处理失败,请重试。');
|
|
135
|
+
}
|
|
136
|
+
catch { /* ignore */ }
|
|
133
137
|
return;
|
|
134
138
|
}
|
|
135
139
|
const stopTyping = startTypingLoop(chatId);
|
package/dist/wework/client.js
CHANGED
|
@@ -46,12 +46,10 @@ export function getConnectionState() {
|
|
|
46
46
|
*/
|
|
47
47
|
export function sendProactiveMessage(chatId, content) {
|
|
48
48
|
if (!ws || connectionState !== 'connected') {
|
|
49
|
-
|
|
50
|
-
return;
|
|
49
|
+
throw new Error('Cannot send proactive message: WebSocket not connected');
|
|
51
50
|
}
|
|
52
51
|
if (!chatId) {
|
|
53
|
-
|
|
54
|
-
return;
|
|
52
|
+
throw new Error('Cannot send proactive message: chatId is required');
|
|
55
53
|
}
|
|
56
54
|
const message = {
|
|
57
55
|
cmd: "aibot_send_msg" /* WeWorkCommand.AIBOT_SEND_MSG */,
|
|
@@ -77,12 +75,10 @@ export function sendProactiveMessage(chatId, content) {
|
|
|
77
75
|
*/
|
|
78
76
|
export function sendWebSocketReply(reqId, body) {
|
|
79
77
|
if (!ws || connectionState !== 'connected') {
|
|
80
|
-
|
|
81
|
-
return;
|
|
78
|
+
throw new Error('Cannot send reply: WebSocket not connected');
|
|
82
79
|
}
|
|
83
80
|
if (!reqId) {
|
|
84
|
-
|
|
85
|
-
return;
|
|
81
|
+
throw new Error('Cannot send reply: req_id is required');
|
|
86
82
|
}
|
|
87
83
|
const message = {
|
|
88
84
|
cmd: "aibot_respond_msg" /* WeWorkCommand.AIBOT_RESPOND_MSG */,
|
|
@@ -185,7 +185,18 @@ export function setupWeWorkHandlers(config, sessionManager) {
|
|
|
185
185
|
: undefined;
|
|
186
186
|
log.info(`[handleAIRequest] Running ${aiCommand} for user ${userId}, sessionId=${sessionId ?? 'new'}`);
|
|
187
187
|
const toolId = aiCommand;
|
|
188
|
-
|
|
188
|
+
let msgId;
|
|
189
|
+
try {
|
|
190
|
+
msgId = await sendThinkingMessage(chatId, replyToMessageId, toolId, reqId);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
log.error('Failed to send thinking message:', err);
|
|
194
|
+
try {
|
|
195
|
+
await sendTextReply(chatId, '启动 AI 处理失败,请重试。', reqId);
|
|
196
|
+
}
|
|
197
|
+
catch { /* ignore */ }
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
189
200
|
const stopTyping = startTypingLoop(chatId);
|
|
190
201
|
const taskKey = `${userId}:${msgId}`;
|
|
191
202
|
await runAITask({ config, sessionManager }, { userId, chatId, workDir, sessionId, convId, platform: 'wework', taskKey }, prompt, toolAdapter, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wu529778790/open-im",
|
|
3
|
-
"version": "1.8.1-beta.
|
|
3
|
+
"version": "1.8.1-beta.9",
|
|
4
4
|
"description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@anthropic-ai/claude-agent-sdk": "^0.2.76",
|
|
50
50
|
"@larksuiteoapi/node-sdk": "^1.59.0",
|
|
51
|
+
"@wu529778790/open-im": "^1.8.1-beta.8",
|
|
51
52
|
"centrifuge": "^5.3.0",
|
|
52
53
|
"dingtalk-stream": "^2.1.4",
|
|
53
54
|
"prompts": "^2.4.2",
|