@wu529778790/open-im 1.8.1-beta.8 → 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/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
|
};
|
|
@@ -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",
|