@ynhcj/xiaoyi 2.3.7 → 2.3.8
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 +26 -24
- package/dist/types.d.ts +3 -0
- package/dist/websocket.d.ts +2 -1
- package/dist/websocket.js +4 -2
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -214,8 +214,10 @@ exports.xiaoyiPlugin = {
|
|
|
214
214
|
const { getXiaoYiRuntime } = require("./runtime");
|
|
215
215
|
const runtime = getXiaoYiRuntime();
|
|
216
216
|
console.log(`XiaoYi: [Message Handler] Using runtime instance: ${runtime.getInstanceId()}`);
|
|
217
|
+
// For message/stream, sessionId is ONLY in params
|
|
218
|
+
const sessionId = message.params.sessionId;
|
|
217
219
|
// Store sessionId -> taskId mapping in runtime (use params.id as taskId)
|
|
218
|
-
runtime.setTaskIdForSession(
|
|
220
|
+
runtime.setTaskIdForSession(sessionId, message.params.id);
|
|
219
221
|
// Get PluginRuntime from our runtime wrapper
|
|
220
222
|
const pluginRuntime = runtime.getPluginRuntime();
|
|
221
223
|
if (!pluginRuntime) {
|
|
@@ -291,8 +293,8 @@ exports.xiaoyiPlugin = {
|
|
|
291
293
|
const msgContext = {
|
|
292
294
|
Body: bodyText,
|
|
293
295
|
From: senderId,
|
|
294
|
-
To:
|
|
295
|
-
SessionKey: `xiaoyi:${resolvedAccount.accountId}:${
|
|
296
|
+
To: sessionId,
|
|
297
|
+
SessionKey: `xiaoyi:${resolvedAccount.accountId}:${sessionId}`,
|
|
296
298
|
AccountId: resolvedAccount.accountId,
|
|
297
299
|
MessageSid: message.id, // Use top-level id as message sequence number
|
|
298
300
|
Timestamp: Date.now(), // Generate timestamp since new format doesn't include it
|
|
@@ -307,34 +309,34 @@ exports.xiaoyiPlugin = {
|
|
|
307
309
|
try {
|
|
308
310
|
console.log("\n" + "=".repeat(60));
|
|
309
311
|
console.log(`XiaoYi: [MESSAGE] Processing user message`);
|
|
310
|
-
console.log(` Session: ${
|
|
312
|
+
console.log(` Session: ${sessionId}`);
|
|
311
313
|
console.log(` Task ID: ${message.params.id}`);
|
|
312
314
|
console.log(` User input: ${bodyText.substring(0, 50)}${bodyText.length > 50 ? "..." : ""}`);
|
|
313
315
|
console.log(` Images: ${images.length}`);
|
|
314
316
|
console.log("=".repeat(60) + "\n");
|
|
315
|
-
const taskId = runtime.getTaskIdForSession(
|
|
317
|
+
const taskId = runtime.getTaskIdForSession(sessionId) || `task_${Date.now()}`;
|
|
316
318
|
const startTime = Date.now();
|
|
317
319
|
let accumulatedText = "";
|
|
318
320
|
// ==================== CREATE ABORT CONTROLLER ====================
|
|
319
321
|
// Create AbortController for this session to allow cancelation
|
|
320
|
-
const { controller: abortController, signal: abortSignal } = runtime.createAbortControllerForSession(
|
|
322
|
+
const { controller: abortController, signal: abortSignal } = runtime.createAbortControllerForSession(sessionId);
|
|
321
323
|
// ================================================================
|
|
322
324
|
// ==================== START TIMEOUT PROTECTION ====================
|
|
323
325
|
// Start 60-second timeout timer
|
|
324
326
|
const timeoutConfig = runtime.getTimeoutConfig();
|
|
325
|
-
console.log(`[TIMEOUT] Starting ${timeoutConfig.duration}ms timeout protection for session ${
|
|
326
|
-
runtime.setTimeoutForSession(
|
|
327
|
+
console.log(`[TIMEOUT] Starting ${timeoutConfig.duration}ms timeout protection for session ${sessionId}`);
|
|
328
|
+
runtime.setTimeoutForSession(sessionId, async () => {
|
|
327
329
|
// Timeout callback - send timeout message to user
|
|
328
330
|
const elapsed = Date.now() - startTime;
|
|
329
331
|
console.log("\n" + "=".repeat(60));
|
|
330
|
-
console.log(`[TIMEOUT] Timeout triggered for session ${
|
|
332
|
+
console.log(`[TIMEOUT] Timeout triggered for session ${sessionId}`);
|
|
331
333
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
332
334
|
console.log(` Task ID: ${taskId}`);
|
|
333
335
|
console.log("=".repeat(60) + "\n");
|
|
334
336
|
const conn = runtime.getConnection();
|
|
335
337
|
if (conn) {
|
|
336
338
|
const timeoutResponse = {
|
|
337
|
-
sessionId:
|
|
339
|
+
sessionId: sessionId,
|
|
338
340
|
messageId: `timeout_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
339
341
|
timestamp: Date.now(),
|
|
340
342
|
agentId: resolvedAccount.config.agentId,
|
|
@@ -350,8 +352,8 @@ exports.xiaoyiPlugin = {
|
|
|
350
352
|
status: "success",
|
|
351
353
|
};
|
|
352
354
|
try {
|
|
353
|
-
await conn.sendResponse(timeoutResponse, taskId,
|
|
354
|
-
console.log(`[TIMEOUT] Timeout message sent successfully to session ${
|
|
355
|
+
await conn.sendResponse(timeoutResponse, taskId, sessionId, true, false);
|
|
356
|
+
console.log(`[TIMEOUT] Timeout message sent successfully to session ${sessionId}\n`);
|
|
355
357
|
}
|
|
356
358
|
catch (error) {
|
|
357
359
|
console.error(`[TIMEOUT] Failed to send timeout message:`, error);
|
|
@@ -371,10 +373,10 @@ exports.xiaoyiPlugin = {
|
|
|
371
373
|
const completeText = payload.text || "";
|
|
372
374
|
accumulatedText = completeText;
|
|
373
375
|
// Check if session was aborted
|
|
374
|
-
if (runtime.isSessionAborted(
|
|
376
|
+
if (runtime.isSessionAborted(sessionId)) {
|
|
375
377
|
console.log("\n" + "=".repeat(60));
|
|
376
378
|
console.log(`[ABORT] Response received AFTER abort`);
|
|
377
|
-
console.log(` Session: ${
|
|
379
|
+
console.log(` Session: ${sessionId}`);
|
|
378
380
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
379
381
|
console.log(` Action: DISCARDING (session was canceled)`);
|
|
380
382
|
console.log("=".repeat(60) + "\n");
|
|
@@ -382,10 +384,10 @@ exports.xiaoyiPlugin = {
|
|
|
382
384
|
}
|
|
383
385
|
// ==================== CHECK TIMEOUT ====================
|
|
384
386
|
// If timeout already sent, discard this response
|
|
385
|
-
if (runtime.isSessionTimeout(
|
|
387
|
+
if (runtime.isSessionTimeout(sessionId)) {
|
|
386
388
|
console.log("\n" + "=".repeat(60));
|
|
387
389
|
console.log(`[TIMEOUT] Response received AFTER timeout`);
|
|
388
|
-
console.log(` Session: ${
|
|
390
|
+
console.log(` Session: ${sessionId}`);
|
|
389
391
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
390
392
|
console.log(` Action: DISCARDING (timeout message already sent)`);
|
|
391
393
|
console.log("=".repeat(60) + "\n");
|
|
@@ -396,7 +398,7 @@ exports.xiaoyiPlugin = {
|
|
|
396
398
|
if (!completeText || completeText.length === 0) {
|
|
397
399
|
console.log("\n" + "=".repeat(60));
|
|
398
400
|
console.log(`[TIMEOUT] Empty response detected`);
|
|
399
|
-
console.log(` Session: ${
|
|
401
|
+
console.log(` Session: ${sessionId}`);
|
|
400
402
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
401
403
|
console.log(` Action: KEEPING TIMEOUT (session conflict detected)`);
|
|
402
404
|
console.log("=".repeat(60) + "\n");
|
|
@@ -411,7 +413,7 @@ exports.xiaoyiPlugin = {
|
|
|
411
413
|
console.log("-".repeat(60) + "\n");
|
|
412
414
|
// Send final response to XiaoYi
|
|
413
415
|
const response = {
|
|
414
|
-
sessionId:
|
|
416
|
+
sessionId: sessionId,
|
|
415
417
|
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
416
418
|
timestamp: Date.now(),
|
|
417
419
|
agentId: resolvedAccount.config.agentId,
|
|
@@ -428,14 +430,14 @@ exports.xiaoyiPlugin = {
|
|
|
428
430
|
};
|
|
429
431
|
const conn = runtime.getConnection();
|
|
430
432
|
if (conn) {
|
|
431
|
-
await conn.sendResponse(response, taskId,
|
|
433
|
+
await conn.sendResponse(response, taskId, sessionId, true, false);
|
|
432
434
|
console.log(`✓ XiaoYi: Response sent successfully\n`);
|
|
433
435
|
}
|
|
434
436
|
else {
|
|
435
437
|
console.error(`✗ XiaoYi: Connection not available\n`);
|
|
436
438
|
}
|
|
437
439
|
// Clear timeout as response was sent successfully
|
|
438
|
-
runtime.markSessionCompleted(
|
|
440
|
+
runtime.markSessionCompleted(sessionId);
|
|
439
441
|
},
|
|
440
442
|
onIdle: async () => {
|
|
441
443
|
const elapsed = Date.now() - startTime;
|
|
@@ -446,8 +448,8 @@ exports.xiaoyiPlugin = {
|
|
|
446
448
|
// Only clear timeout if we have a valid response
|
|
447
449
|
// If empty, keep timeout running to handle session conflict
|
|
448
450
|
if (accumulatedText.length > 0) {
|
|
449
|
-
runtime.markSessionCompleted(
|
|
450
|
-
runtime.clearAbortControllerForSession(
|
|
451
|
+
runtime.markSessionCompleted(sessionId);
|
|
452
|
+
runtime.clearAbortControllerForSession(sessionId);
|
|
451
453
|
console.log(`[TIMEOUT] Timeout cleared (valid response)\n`);
|
|
452
454
|
}
|
|
453
455
|
else {
|
|
@@ -465,9 +467,9 @@ exports.xiaoyiPlugin = {
|
|
|
465
467
|
catch (error) {
|
|
466
468
|
console.error("XiaoYi: [ERROR] Error dispatching message:", error);
|
|
467
469
|
// Clear timeout on error
|
|
468
|
-
runtime.clearSessionTimeout(
|
|
470
|
+
runtime.clearSessionTimeout(sessionId);
|
|
469
471
|
// Clear abort controller on error
|
|
470
|
-
runtime.clearAbortControllerForSession(
|
|
472
|
+
runtime.clearAbortControllerForSession(sessionId);
|
|
471
473
|
}
|
|
472
474
|
});
|
|
473
475
|
// Setup cancel handler
|
package/dist/types.d.ts
CHANGED
|
@@ -3,11 +3,14 @@ export interface A2ARequestMessage {
|
|
|
3
3
|
jsonrpc: "2.0";
|
|
4
4
|
id: string;
|
|
5
5
|
method: "message/stream";
|
|
6
|
+
deviceId?: string;
|
|
6
7
|
params: {
|
|
7
8
|
id: string;
|
|
8
9
|
sessionId: string;
|
|
9
10
|
agentLoginSessionId?: string;
|
|
10
11
|
message: {
|
|
12
|
+
kind?: string;
|
|
13
|
+
messageId?: string;
|
|
11
14
|
role: "user" | "agent";
|
|
12
15
|
parts: Array<{
|
|
13
16
|
kind: "text" | "file" | "data";
|
package/dist/websocket.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export declare class XiaoYiWebSocketManager extends EventEmitter {
|
|
|
53
53
|
/**
|
|
54
54
|
* Extract sessionId from message based on method type
|
|
55
55
|
* Different methods have sessionId in different locations:
|
|
56
|
-
* - message/stream: sessionId in params
|
|
56
|
+
* - message/stream: sessionId ONLY in params
|
|
57
57
|
* - tasks/cancel: sessionId at top level
|
|
58
58
|
* - clearContext: sessionId at top level
|
|
59
59
|
*/
|
|
@@ -136,6 +136,7 @@ export declare class XiaoYiWebSocketManager extends EventEmitter {
|
|
|
136
136
|
private clearStableConnectionCheck;
|
|
137
137
|
/**
|
|
138
138
|
* Type guard for A2A request messages
|
|
139
|
+
* For message/stream, sessionId MUST be in params
|
|
139
140
|
*/
|
|
140
141
|
private isA2ARequestMessage;
|
|
141
142
|
/**
|
package/dist/websocket.js
CHANGED
|
@@ -306,12 +306,12 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
306
306
|
/**
|
|
307
307
|
* Extract sessionId from message based on method type
|
|
308
308
|
* Different methods have sessionId in different locations:
|
|
309
|
-
* - message/stream: sessionId in params
|
|
309
|
+
* - message/stream: sessionId ONLY in params
|
|
310
310
|
* - tasks/cancel: sessionId at top level
|
|
311
311
|
* - clearContext: sessionId at top level
|
|
312
312
|
*/
|
|
313
313
|
extractSessionId(message) {
|
|
314
|
-
// For message/stream, sessionId is in params
|
|
314
|
+
// For message/stream, sessionId is ONLY in params
|
|
315
315
|
if (message.method === "message/stream") {
|
|
316
316
|
return message.params?.sessionId;
|
|
317
317
|
}
|
|
@@ -798,6 +798,7 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
798
798
|
}
|
|
799
799
|
/**
|
|
800
800
|
* Type guard for A2A request messages
|
|
801
|
+
* For message/stream, sessionId MUST be in params
|
|
801
802
|
*/
|
|
802
803
|
isA2ARequestMessage(data) {
|
|
803
804
|
return data &&
|
|
@@ -807,6 +808,7 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
807
808
|
data.method === "message/stream" &&
|
|
808
809
|
data.params &&
|
|
809
810
|
typeof data.params.id === "string" &&
|
|
811
|
+
// For message/stream, sessionId MUST be in params
|
|
810
812
|
typeof data.params.sessionId === "string" &&
|
|
811
813
|
data.params.message &&
|
|
812
814
|
typeof data.params.message.role === "string" &&
|