@wu529778790/open-im 1.11.2-beta.2 → 1.11.2-beta.20
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 +106 -98
- package/dist/clawbot/event-handler.js +4 -2
- package/dist/config-web-page-i18n.d.ts +7 -7
- package/dist/config-web-page-i18n.js +7 -7
- package/dist/index.js +65 -23
- package/dist/logger.d.ts +0 -3
- package/dist/logger.js +5 -36
- package/dist/shared/ai-task.js +3 -49
- package/dist/shared/task-cleanup.js +1 -11
- package/dist/workbuddy/event-handler.js +5 -5
- package/package.json +1 -1
- package/web/dist/assets/index-CWE8jASz.js +57 -0
- package/web/dist/assets/index-UZ04hBdn.css +1 -0
- package/web/dist/index.html +2 -2
- package/README.zh-CN.md +0 -154
- package/dist/telemetry/hash-user.d.ts +0 -2
- package/dist/telemetry/hash-user.js +0 -5
- package/dist/telemetry/telemetry-sanitize.d.ts +0 -2
- package/dist/telemetry/telemetry-sanitize.js +0 -30
- package/web/dist/assets/index-B1c1xlbx.css +0 -1
- package/web/dist/assets/index-Dng7B2mE.js +0 -57
package/dist/shared/ai-task.js
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
import { resolvePlatformAiCommand } from '../config.js';
|
|
5
5
|
import { captureError } from './sentry.js';
|
|
6
6
|
import { formatToolStats, formatToolCallNotification, getContextWarning, getAIToolDisplayName, toReplyPlainText, } from './utils.js';
|
|
7
|
-
import { createLogger
|
|
8
|
-
import { hashUserId } from '../telemetry/hash-user.js';
|
|
9
|
-
import { sanitize } from '../sanitize.js';
|
|
7
|
+
import { createLogger } from '../logger.js';
|
|
10
8
|
const log = createLogger('AITask');
|
|
11
9
|
function isUsageLimitError(error) {
|
|
12
10
|
return /usage limit/i.test(error) || /try again at\s+\d{1,2}:\d{2}\s*(AM|PM)/i.test(error);
|
|
@@ -154,12 +152,6 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
154
152
|
const aiCommand = resolvePlatformAiCommand(config, ctx.platform);
|
|
155
153
|
const startRun = () => {
|
|
156
154
|
log.info(`[AITask] Starting: userId=${ctx.userId}, initialSessionId=${currentSessionId ?? 'new'}, prompt="${prompt.slice(0, 50)}..."`);
|
|
157
|
-
emitStructuredEvent('AITask', 'ai.task.start', {
|
|
158
|
-
platform: ctx.platform,
|
|
159
|
-
taskKey: hashUserId(ctx.taskKey),
|
|
160
|
-
userKey: hashUserId(ctx.userId),
|
|
161
|
-
toolId: aiCommand,
|
|
162
|
-
});
|
|
163
155
|
activeHandle = toolAdapter.run(prompt, currentSessionId, ctx.workDir, {
|
|
164
156
|
onSessionId: (id) => {
|
|
165
157
|
log.info(`[AITask] SessionId callback: old=${currentSessionId ?? 'none'}, new=${id}, aiCommand=${aiCommand}, userId=${ctx.userId}`);
|
|
@@ -218,17 +210,6 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
218
210
|
log.info(`[AITask] onComplete fired: settled=${settled}, success=${result.success}, platform=${ctx.platform}, taskKey=${ctx.taskKey}`);
|
|
219
211
|
if (settled)
|
|
220
212
|
return;
|
|
221
|
-
emitStructuredEvent('AITask', 'ai.task.complete', {
|
|
222
|
-
platform: ctx.platform,
|
|
223
|
-
taskKey: hashUserId(ctx.taskKey),
|
|
224
|
-
userKey: hashUserId(ctx.userId),
|
|
225
|
-
toolId: aiCommand,
|
|
226
|
-
durationMs: result.durationMs,
|
|
227
|
-
success: result.success,
|
|
228
|
-
numTurns: result.numTurns,
|
|
229
|
-
model: result.model,
|
|
230
|
-
toolStats: result.toolStats,
|
|
231
|
-
});
|
|
232
213
|
settled = true;
|
|
233
214
|
if (pendingUpdate) {
|
|
234
215
|
clearTimeout(pendingUpdate);
|
|
@@ -282,15 +263,6 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
282
263
|
}
|
|
283
264
|
settled = true;
|
|
284
265
|
log.error(`Task error for user ${ctx.userId}: ${error}`);
|
|
285
|
-
emitStructuredEvent('AITask', 'ai.task.error', {
|
|
286
|
-
platform: ctx.platform,
|
|
287
|
-
taskKey: hashUserId(ctx.taskKey),
|
|
288
|
-
userKey: hashUserId(ctx.userId),
|
|
289
|
-
toolId: aiCommand,
|
|
290
|
-
durationMs: Date.now() - taskState.startedAt,
|
|
291
|
-
errorSnippet: sanitize(String(error).slice(0, 400)),
|
|
292
|
-
errorType: classifyErrorType(String(error)),
|
|
293
|
-
});
|
|
294
266
|
if (isUsageLimitError(error)) {
|
|
295
267
|
// Usage limit errors: keep session for all tools (user can retry later)
|
|
296
268
|
log.warn(`Keeping ${aiCommand} session for user ${ctx.userId} after usage limit error`);
|
|
@@ -330,15 +302,6 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
330
302
|
handle: {
|
|
331
303
|
abort: () => {
|
|
332
304
|
if (!settled) {
|
|
333
|
-
emitStructuredEvent('AITask', 'ai.task.error', {
|
|
334
|
-
platform: ctx.platform,
|
|
335
|
-
taskKey: hashUserId(ctx.taskKey),
|
|
336
|
-
userKey: hashUserId(ctx.userId),
|
|
337
|
-
toolId: aiCommand,
|
|
338
|
-
durationMs: Date.now() - taskState.startedAt,
|
|
339
|
-
errorSnippet: 'aborted',
|
|
340
|
-
errorType: 'aborted',
|
|
341
|
-
});
|
|
342
305
|
// 用户取消(/new、/resume、队列超时、stale 清理):把「思考中…」占位卡片编辑为终态,
|
|
343
306
|
// 避免卡片卡在转圈。停按钮路径会先 settle() 再 abort,settled=true 时此处跳过,不会双发。
|
|
344
307
|
void platformAdapter.sendError('⏹️ 已取消').catch(() => {
|
|
@@ -354,9 +317,9 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
354
317
|
settle,
|
|
355
318
|
startedAt: Date.now(),
|
|
356
319
|
toolId: aiCommand,
|
|
357
|
-
taskKey:
|
|
320
|
+
taskKey: ctx.taskKey,
|
|
358
321
|
platform: ctx.platform,
|
|
359
|
-
userKey:
|
|
322
|
+
userKey: ctx.userId,
|
|
360
323
|
};
|
|
361
324
|
try {
|
|
362
325
|
startRun();
|
|
@@ -371,15 +334,6 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
|
|
|
371
334
|
userId: ctx.userId,
|
|
372
335
|
aiCommand,
|
|
373
336
|
});
|
|
374
|
-
emitStructuredEvent('AITask', 'ai.task.error', {
|
|
375
|
-
platform: ctx.platform,
|
|
376
|
-
taskKey: hashUserId(ctx.taskKey),
|
|
377
|
-
userKey: hashUserId(ctx.userId),
|
|
378
|
-
toolId: aiCommand,
|
|
379
|
-
durationMs: 0,
|
|
380
|
-
errorSnippet: sanitize(String(err).slice(0, 400)),
|
|
381
|
-
errorType: classifyErrorType(String(err)),
|
|
382
|
-
});
|
|
383
337
|
platformAdapter
|
|
384
338
|
.sendError(`内部错误:${err instanceof Error ? err.message : String(err)}`)
|
|
385
339
|
.catch(() => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Tasks older than 30 minutes are aborted and removed from the running-tasks
|
|
5
5
|
* map so they never accumulate indefinitely.
|
|
6
6
|
*/
|
|
7
|
-
import { createLogger
|
|
7
|
+
import { createLogger } from '../logger.js';
|
|
8
8
|
const log = createLogger('TaskCleanup');
|
|
9
9
|
const CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
|
|
10
10
|
const STALE_THRESHOLD_MS = 30 * 60 * 1000; // 30 minutes
|
|
@@ -46,17 +46,7 @@ export function startTaskCleanup(runningTasks) {
|
|
|
46
46
|
export function emitInterruptedTerminals(runningTasks) {
|
|
47
47
|
if (runningTasks.size === 0)
|
|
48
48
|
return;
|
|
49
|
-
const now = Date.now();
|
|
50
49
|
for (const state of runningTasks.values()) {
|
|
51
|
-
emitStructuredEvent('AITask', 'ai.task.error', {
|
|
52
|
-
platform: state.platform,
|
|
53
|
-
taskKey: state.taskKey,
|
|
54
|
-
userKey: state.userKey,
|
|
55
|
-
toolId: state.toolId,
|
|
56
|
-
durationMs: now - state.startedAt,
|
|
57
|
-
errorSnippet: 'interrupted',
|
|
58
|
-
errorType: 'interrupted',
|
|
59
|
-
});
|
|
60
50
|
// 标记已结算,使随后 shutdown 的 abort() 跳过重复的 aborted 事件
|
|
61
51
|
state.settle();
|
|
62
52
|
}
|
|
@@ -24,17 +24,17 @@ export function setupWorkBuddyHandlers(config, sessionManager) {
|
|
|
24
24
|
});
|
|
25
25
|
// Start task cleanup
|
|
26
26
|
const stopTaskCleanup = startTaskCleanup(ctx.runningTasks);
|
|
27
|
-
// WorkBuddy-specific sender callbacks
|
|
27
|
+
// WorkBuddy-specific sender callbacks
|
|
28
28
|
const platformSender = {
|
|
29
|
-
sendThinkingMessage: async (
|
|
30
|
-
// WorkBuddy
|
|
31
|
-
|
|
29
|
+
sendThinkingMessage: async (chatId, _replyToMessageId, _toolId) => {
|
|
30
|
+
// WorkBuddy 不支持 typing indicator,先发一条"思考中"消息给用户反馈
|
|
31
|
+
await sendTextReply(null, chatId, '🤔 正在处理...', '');
|
|
32
|
+
return 'workbuddy_thinking';
|
|
32
33
|
},
|
|
33
34
|
sendTextReply: async (chatId, text) => {
|
|
34
35
|
await sendTextReply(null, chatId, text, '');
|
|
35
36
|
},
|
|
36
37
|
startTyping: (_chatId) => {
|
|
37
|
-
// WorkBuddy doesn't support typing indicators
|
|
38
38
|
return () => { };
|
|
39
39
|
},
|
|
40
40
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wu529778790/open-im",
|
|
3
|
-
"version": "1.11.2-beta.
|
|
3
|
+
"version": "1.11.2-beta.20",
|
|
4
4
|
"description": "Your AI coding assistant, in every chat app. Multi-platform IM bridge for Claude Code, Codex, and CodeBuddy.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|