@ynhcj/xiaoyi 2.4.5 → 2.4.7
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 +68 -11
- package/package.json +6 -6
package/dist/channel.js
CHANGED
|
@@ -323,6 +323,7 @@ exports.xiaoyiPlugin = {
|
|
|
323
323
|
const startTime = Date.now();
|
|
324
324
|
let accumulatedText = "";
|
|
325
325
|
let sentTextLength = 0; // Track sent text length for streaming
|
|
326
|
+
let hasSentFinal = false; // Track if final content has been sent (to prevent duplicate isFinal=true)
|
|
326
327
|
// ==================== CREATE ABORT CONTROLLER ====================
|
|
327
328
|
// Create AbortController for this session to allow cancelation
|
|
328
329
|
const { controller: abortController, signal: abortSignal } = runtime.createAbortControllerForSession(sessionId);
|
|
@@ -371,6 +372,22 @@ exports.xiaoyiPlugin = {
|
|
|
371
372
|
const completeText = payload.text || "";
|
|
372
373
|
accumulatedText = completeText;
|
|
373
374
|
const kind = info.kind; // "tool" | "block" | "final"
|
|
375
|
+
// ==================== DEBUG LOG - ENTRY POINT ====================
|
|
376
|
+
// Log EVERY call to deliver with full details
|
|
377
|
+
console.log("\n" + "█".repeat(70));
|
|
378
|
+
console.log(`📨 [DELIVER ENTRY] deliver() callback invoked`);
|
|
379
|
+
console.log(` Session: ${sessionId}`);
|
|
380
|
+
console.log(` Elapsed: ${elapsed}ms`);
|
|
381
|
+
console.log(` Kind: "${kind}"`);
|
|
382
|
+
console.log(` Text length: ${completeText.length} chars`);
|
|
383
|
+
console.log(` Sent so far: ${sentTextLength} chars`);
|
|
384
|
+
if (completeText.length > 0) {
|
|
385
|
+
console.log(` Text preview: "${completeText.substring(0, 80)}${completeText.length > 80 ? "..." : ""}"`);
|
|
386
|
+
}
|
|
387
|
+
console.log(` Full info object:`, JSON.stringify(info, null, 2));
|
|
388
|
+
console.log(` Full payload keys:`, Object.keys(payload));
|
|
389
|
+
console.log("█".repeat(70) + "\n");
|
|
390
|
+
// =================================================================
|
|
374
391
|
// Check if session was aborted
|
|
375
392
|
if (runtime.isSessionAborted(sessionId)) {
|
|
376
393
|
console.log("\n" + "=".repeat(60));
|
|
@@ -463,8 +480,16 @@ exports.xiaoyiPlugin = {
|
|
|
463
480
|
console.log(` Session: ${sessionId}`);
|
|
464
481
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
465
482
|
console.log(` Total length: ${completeText.length} chars`);
|
|
483
|
+
console.log(` Has already sent final: ${hasSentFinal}`);
|
|
466
484
|
console.log(` Preview: "${completeText.substring(0, 100)}..."`);
|
|
467
485
|
console.log("=".repeat(60) + "\n");
|
|
486
|
+
// Check if we've already sent final content - prevent duplicate isFinal=true
|
|
487
|
+
if (hasSentFinal) {
|
|
488
|
+
console.log(`XiaoYi: [STREAM] Skipping duplicate final response (already sent)\n`);
|
|
489
|
+
// Don't send anything, but clear timeout to prevent timeout warnings
|
|
490
|
+
runtime.clearSessionTimeout(sessionId);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
468
493
|
const response = {
|
|
469
494
|
sessionId: sessionId,
|
|
470
495
|
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
@@ -481,13 +506,16 @@ exports.xiaoyiPlugin = {
|
|
|
481
506
|
},
|
|
482
507
|
status: "success",
|
|
483
508
|
};
|
|
484
|
-
// Send complete text as
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
//
|
|
509
|
+
// Send complete text but NOT as final yet - use append mode to keep stream alive
|
|
510
|
+
// The true isFinal=true will be sent in onIdle callback
|
|
511
|
+
await conn.sendResponse(response, taskId, sessionId, false, true);
|
|
512
|
+
console.log(`✓ XiaoYi: Final response content sent (${completeText.length} chars, stream kept alive)\n`);
|
|
513
|
+
// Mark that we've sent the final content
|
|
514
|
+
hasSentFinal = true;
|
|
515
|
+
// Clear timeout to prevent timeout warnings, but don't mark session as completed yet
|
|
516
|
+
runtime.clearSessionTimeout(sessionId);
|
|
517
|
+
// Note: We DON'T call markSessionCompleted here
|
|
518
|
+
// The session will be marked completed in onIdle when we send isFinal=true
|
|
491
519
|
}
|
|
492
520
|
else if (kind === "tool") {
|
|
493
521
|
// Tool results - typically not sent as messages
|
|
@@ -504,15 +532,44 @@ exports.xiaoyiPlugin = {
|
|
|
504
532
|
console.log(`XiaoYi: [IDLE] Processing complete`);
|
|
505
533
|
console.log(` Total time: ${elapsed}ms`);
|
|
506
534
|
console.log(` Final length: ${accumulatedText.length} chars`);
|
|
507
|
-
|
|
508
|
-
//
|
|
535
|
+
console.log(` Has sent final: ${hasSentFinal}`);
|
|
536
|
+
// Only send final close message if we have valid content
|
|
509
537
|
if (accumulatedText.length > 0) {
|
|
538
|
+
const conn = runtime.getConnection();
|
|
539
|
+
if (conn) {
|
|
540
|
+
try {
|
|
541
|
+
// Send the true final response with isFinal=true to properly close the stream
|
|
542
|
+
const finalResponse = {
|
|
543
|
+
sessionId: sessionId,
|
|
544
|
+
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
545
|
+
timestamp: Date.now(),
|
|
546
|
+
agentId: resolvedAccount.config.agentId,
|
|
547
|
+
sender: {
|
|
548
|
+
id: resolvedAccount.config.agentId,
|
|
549
|
+
name: "OpenClaw Agent",
|
|
550
|
+
type: "agent",
|
|
551
|
+
},
|
|
552
|
+
content: {
|
|
553
|
+
type: "text",
|
|
554
|
+
text: accumulatedText,
|
|
555
|
+
},
|
|
556
|
+
status: "success",
|
|
557
|
+
};
|
|
558
|
+
// Send with isFinal=true to properly close the A2A communication stream
|
|
559
|
+
await conn.sendResponse(finalResponse, taskId, sessionId, true, false);
|
|
560
|
+
console.log(`✓ XiaoYi: True isFinal=true sent to close stream\n`);
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
console.error(`✗ XiaoYi: Failed to send final close message:`, error);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
// Now mark session as completed and clean up
|
|
510
567
|
runtime.markSessionCompleted(sessionId);
|
|
511
568
|
runtime.clearAbortControllerForSession(sessionId);
|
|
512
|
-
console.log(`[TIMEOUT]
|
|
569
|
+
console.log(`[TIMEOUT] Session completed and cleaned up\n`);
|
|
513
570
|
}
|
|
514
571
|
else {
|
|
515
|
-
console.log(`[TIMEOUT]
|
|
572
|
+
console.log(`[TIMEOUT] No valid response, keeping timeout active\n`);
|
|
516
573
|
}
|
|
517
574
|
console.log("=".repeat(60) + "\n");
|
|
518
575
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ynhcj/xiaoyi",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.7",
|
|
4
4
|
"description": "XiaoYi channel plugin for OpenClaw",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
"extensions": ["xiaoyi.js"],
|
|
21
21
|
"channels": ["xiaoyi"],
|
|
22
22
|
"installDependencies": true,
|
|
23
|
+
"install": {
|
|
24
|
+
"npmSpec": "@ynhcj/xiaoyi",
|
|
25
|
+
"localPath": ".",
|
|
26
|
+
"defaultChoice": "npm"
|
|
27
|
+
},
|
|
23
28
|
"channel": {
|
|
24
29
|
"id": "xiaoyi",
|
|
25
30
|
"label": "XiaoYi",
|
|
@@ -29,11 +34,6 @@
|
|
|
29
34
|
"blurb": "小艺 A2A 协议支持,通过 WebSocket 连接。",
|
|
30
35
|
"order": 80,
|
|
31
36
|
"aliases": ["xy"]
|
|
32
|
-
},
|
|
33
|
-
"install": {
|
|
34
|
-
"npmSpec": "@ynhcj/xiaoyi",
|
|
35
|
-
"localPath": ".",
|
|
36
|
-
"defaultChoice": "npm"
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|