@ynhcj/xiaoyi 2.3.5 → 2.3.6
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/channel.js +34 -6
- package/dist/runtime.d.ts +31 -0
- package/dist/runtime.js +60 -0
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -315,6 +315,10 @@ exports.xiaoyiPlugin = {
|
|
|
315
315
|
const taskId = runtime.getTaskIdForSession(message.params.sessionId) || `task_${Date.now()}`;
|
|
316
316
|
const startTime = Date.now();
|
|
317
317
|
let accumulatedText = "";
|
|
318
|
+
// ==================== CREATE ABORT CONTROLLER ====================
|
|
319
|
+
// Create AbortController for this session to allow cancelation
|
|
320
|
+
const { controller: abortController, signal: abortSignal } = runtime.createAbortControllerForSession(message.params.sessionId);
|
|
321
|
+
// ================================================================
|
|
318
322
|
// ==================== START TIMEOUT PROTECTION ====================
|
|
319
323
|
// Start 60-second timeout timer
|
|
320
324
|
const timeoutConfig = runtime.getTimeoutConfig();
|
|
@@ -366,6 +370,16 @@ exports.xiaoyiPlugin = {
|
|
|
366
370
|
const elapsed = Date.now() - startTime;
|
|
367
371
|
const completeText = payload.text || "";
|
|
368
372
|
accumulatedText = completeText;
|
|
373
|
+
// Check if session was aborted
|
|
374
|
+
if (runtime.isSessionAborted(message.params.sessionId)) {
|
|
375
|
+
console.log("\n" + "=".repeat(60));
|
|
376
|
+
console.log(`[ABORT] Response received AFTER abort`);
|
|
377
|
+
console.log(` Session: ${message.params.sessionId}`);
|
|
378
|
+
console.log(` Elapsed: ${elapsed}ms`);
|
|
379
|
+
console.log(` Action: DISCARDING (session was canceled)`);
|
|
380
|
+
console.log("=".repeat(60) + "\n");
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
369
383
|
// ==================== CHECK TIMEOUT ====================
|
|
370
384
|
// If timeout already sent, discard this response
|
|
371
385
|
if (runtime.isSessionTimeout(message.params.sessionId)) {
|
|
@@ -433,6 +447,7 @@ exports.xiaoyiPlugin = {
|
|
|
433
447
|
// If empty, keep timeout running to handle session conflict
|
|
434
448
|
if (accumulatedText.length > 0) {
|
|
435
449
|
runtime.markSessionCompleted(message.params.sessionId);
|
|
450
|
+
runtime.clearAbortControllerForSession(message.params.sessionId);
|
|
436
451
|
console.log(`[TIMEOUT] Timeout cleared (valid response)\n`);
|
|
437
452
|
}
|
|
438
453
|
else {
|
|
@@ -441,7 +456,9 @@ exports.xiaoyiPlugin = {
|
|
|
441
456
|
console.log("=".repeat(60) + "\n");
|
|
442
457
|
},
|
|
443
458
|
},
|
|
444
|
-
replyOptions:
|
|
459
|
+
replyOptions: {
|
|
460
|
+
abortSignal: abortSignal, // Pass abort signal to allow cancellation
|
|
461
|
+
},
|
|
445
462
|
images: images.length > 0 ? images : undefined,
|
|
446
463
|
});
|
|
447
464
|
}
|
|
@@ -449,18 +466,29 @@ exports.xiaoyiPlugin = {
|
|
|
449
466
|
console.error("XiaoYi: [ERROR] Error dispatching message:", error);
|
|
450
467
|
// Clear timeout on error
|
|
451
468
|
runtime.clearSessionTimeout(message.params.sessionId);
|
|
469
|
+
// Clear abort controller on error
|
|
470
|
+
runtime.clearAbortControllerForSession(message.params.sessionId);
|
|
452
471
|
}
|
|
453
472
|
});
|
|
454
473
|
// Setup cancel handler
|
|
455
|
-
//
|
|
474
|
+
// When tasks/cancel is received, abort the current session's agent run
|
|
456
475
|
connection.on("cancel", async (data) => {
|
|
476
|
+
const { sessionId } = data;
|
|
457
477
|
console.log("\n" + "=".repeat(60));
|
|
458
|
-
console.log(`XiaoYi: [CANCEL] Cancel event received
|
|
459
|
-
console.log(` Session: ${
|
|
478
|
+
console.log(`XiaoYi: [CANCEL] Cancel event received`);
|
|
479
|
+
console.log(` Session: ${sessionId}`);
|
|
460
480
|
console.log(` Task ID: ${data.taskId || "N/A"}`);
|
|
461
481
|
console.log("=".repeat(60) + "\n");
|
|
462
|
-
//
|
|
463
|
-
|
|
482
|
+
// Abort the session's agent run
|
|
483
|
+
const aborted = runtime.abortSession(sessionId);
|
|
484
|
+
if (aborted) {
|
|
485
|
+
console.log(`[CANCEL] Successfully triggered abort for session ${sessionId}`);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
console.log(`[CANCEL] No active agent run found for session ${sessionId}`);
|
|
489
|
+
}
|
|
490
|
+
// Clear timeout as the session is being canceled
|
|
491
|
+
runtime.markSessionCompleted(sessionId);
|
|
464
492
|
});
|
|
465
493
|
console.log("XiaoYi: Event handlers registered");
|
|
466
494
|
console.log("XiaoYi: startAccount() completed - END");
|
package/dist/runtime.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare class XiaoYiRuntime {
|
|
|
21
21
|
private sessionTimeoutMap;
|
|
22
22
|
private sessionTimeoutSent;
|
|
23
23
|
private timeoutConfig;
|
|
24
|
+
private sessionAbortControllerMap;
|
|
24
25
|
constructor();
|
|
25
26
|
getInstanceId(): string;
|
|
26
27
|
/**
|
|
@@ -97,6 +98,36 @@ export declare class XiaoYiRuntime {
|
|
|
97
98
|
* Clear taskId for a session
|
|
98
99
|
*/
|
|
99
100
|
clearTaskIdForSession(sessionId: string): void;
|
|
101
|
+
/**
|
|
102
|
+
* Create and register an AbortController for a session
|
|
103
|
+
* @param sessionId - Session ID
|
|
104
|
+
* @returns The AbortController and its signal
|
|
105
|
+
*/
|
|
106
|
+
createAbortControllerForSession(sessionId: string): {
|
|
107
|
+
controller: AbortController;
|
|
108
|
+
signal: AbortSignal;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Abort a session's agent run
|
|
112
|
+
* @param sessionId - Session ID
|
|
113
|
+
* @returns true if a controller was found and aborted, false otherwise
|
|
114
|
+
*/
|
|
115
|
+
abortSession(sessionId: string): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a session has been aborted
|
|
118
|
+
* @param sessionId - Session ID
|
|
119
|
+
* @returns true if the session's abort signal was triggered
|
|
120
|
+
*/
|
|
121
|
+
isSessionAborted(sessionId: string): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Clear the AbortController for a session (call when agent completes successfully)
|
|
124
|
+
* @param sessionId - Session ID
|
|
125
|
+
*/
|
|
126
|
+
clearAbortControllerForSession(sessionId: string): void;
|
|
127
|
+
/**
|
|
128
|
+
* Clear all AbortControllers
|
|
129
|
+
*/
|
|
130
|
+
clearAllAbortControllers(): void;
|
|
100
131
|
}
|
|
101
132
|
export declare function getXiaoYiRuntime(): XiaoYiRuntime;
|
|
102
133
|
export declare function setXiaoYiRuntime(runtime: any): void;
|
package/dist/runtime.js
CHANGED
|
@@ -26,6 +26,8 @@ class XiaoYiRuntime {
|
|
|
26
26
|
this.sessionTimeoutMap = new Map();
|
|
27
27
|
this.sessionTimeoutSent = new Set();
|
|
28
28
|
this.timeoutConfig = DEFAULT_TIMEOUT_CONFIG;
|
|
29
|
+
// AbortController management for canceling agent runs
|
|
30
|
+
this.sessionAbortControllerMap = new Map();
|
|
29
31
|
this.instanceId = `runtime_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
30
32
|
console.log(`XiaoYi: Created new runtime instance: ${this.instanceId}`);
|
|
31
33
|
}
|
|
@@ -100,6 +102,8 @@ class XiaoYiRuntime {
|
|
|
100
102
|
this.sessionToTaskIdMap.clear();
|
|
101
103
|
// Clear all timeouts
|
|
102
104
|
this.clearAllTimeouts();
|
|
105
|
+
// Clear all abort controllers
|
|
106
|
+
this.clearAllAbortControllers();
|
|
103
107
|
}
|
|
104
108
|
/**
|
|
105
109
|
* Set timeout configuration
|
|
@@ -220,6 +224,62 @@ class XiaoYiRuntime {
|
|
|
220
224
|
clearTaskIdForSession(sessionId) {
|
|
221
225
|
this.sessionToTaskIdMap.delete(sessionId);
|
|
222
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Create and register an AbortController for a session
|
|
229
|
+
* @param sessionId - Session ID
|
|
230
|
+
* @returns The AbortController and its signal
|
|
231
|
+
*/
|
|
232
|
+
createAbortControllerForSession(sessionId) {
|
|
233
|
+
// Abort any existing controller for this session
|
|
234
|
+
this.abortSession(sessionId);
|
|
235
|
+
const controller = new AbortController();
|
|
236
|
+
this.sessionAbortControllerMap.set(sessionId, controller);
|
|
237
|
+
console.log(`[ABORT] Created AbortController for session ${sessionId}`);
|
|
238
|
+
return { controller, signal: controller.signal };
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Abort a session's agent run
|
|
242
|
+
* @param sessionId - Session ID
|
|
243
|
+
* @returns true if a controller was found and aborted, false otherwise
|
|
244
|
+
*/
|
|
245
|
+
abortSession(sessionId) {
|
|
246
|
+
const controller = this.sessionAbortControllerMap.get(sessionId);
|
|
247
|
+
if (controller) {
|
|
248
|
+
console.log(`[ABORT] Aborting session ${sessionId}`);
|
|
249
|
+
controller.abort();
|
|
250
|
+
this.sessionAbortControllerMap.delete(sessionId);
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
console.log(`[ABORT] No AbortController found for session ${sessionId}`);
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Check if a session has been aborted
|
|
258
|
+
* @param sessionId - Session ID
|
|
259
|
+
* @returns true if the session's abort signal was triggered
|
|
260
|
+
*/
|
|
261
|
+
isSessionAborted(sessionId) {
|
|
262
|
+
const controller = this.sessionAbortControllerMap.get(sessionId);
|
|
263
|
+
return controller ? controller.signal.aborted : false;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Clear the AbortController for a session (call when agent completes successfully)
|
|
267
|
+
* @param sessionId - Session ID
|
|
268
|
+
*/
|
|
269
|
+
clearAbortControllerForSession(sessionId) {
|
|
270
|
+
const controller = this.sessionAbortControllerMap.get(sessionId);
|
|
271
|
+
if (controller) {
|
|
272
|
+
this.sessionAbortControllerMap.delete(sessionId);
|
|
273
|
+
console.log(`[ABORT] Cleared AbortController for session ${sessionId}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Clear all AbortControllers
|
|
278
|
+
*/
|
|
279
|
+
clearAllAbortControllers() {
|
|
280
|
+
this.sessionAbortControllerMap.clear();
|
|
281
|
+
console.log("[ABORT] All AbortControllers cleared");
|
|
282
|
+
}
|
|
223
283
|
}
|
|
224
284
|
exports.XiaoYiRuntime = XiaoYiRuntime;
|
|
225
285
|
// Global runtime instance - use global object to survive module reloads
|