@ynhcj/xiaoyi 2.4.4 → 2.4.5
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 +94 -32
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -322,6 +322,7 @@ exports.xiaoyiPlugin = {
|
|
|
322
322
|
const taskId = runtime.getTaskIdForSession(sessionId) || `task_${Date.now()}`;
|
|
323
323
|
const startTime = Date.now();
|
|
324
324
|
let accumulatedText = "";
|
|
325
|
+
let sentTextLength = 0; // Track sent text length for streaming
|
|
325
326
|
// ==================== CREATE ABORT CONTROLLER ====================
|
|
326
327
|
// Create AbortController for this session to allow cancelation
|
|
327
328
|
const { controller: abortController, signal: abortSignal } = runtime.createAbortControllerForSession(sessionId);
|
|
@@ -365,15 +366,17 @@ exports.xiaoyiPlugin = {
|
|
|
365
366
|
ctx: msgContext,
|
|
366
367
|
cfg: config,
|
|
367
368
|
dispatcherOptions: {
|
|
368
|
-
deliver: async (payload) => {
|
|
369
|
+
deliver: async (payload, info) => {
|
|
369
370
|
const elapsed = Date.now() - startTime;
|
|
370
371
|
const completeText = payload.text || "";
|
|
371
372
|
accumulatedText = completeText;
|
|
373
|
+
const kind = info.kind; // "tool" | "block" | "final"
|
|
372
374
|
// Check if session was aborted
|
|
373
375
|
if (runtime.isSessionAborted(sessionId)) {
|
|
374
376
|
console.log("\n" + "=".repeat(60));
|
|
375
377
|
console.log(`[ABORT] Response received AFTER abort`);
|
|
376
378
|
console.log(` Session: ${sessionId}`);
|
|
379
|
+
console.log(` Kind: ${kind}`);
|
|
377
380
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
378
381
|
console.log(` Action: DISCARDING (session was canceled)`);
|
|
379
382
|
console.log("=".repeat(60) + "\n");
|
|
@@ -385,6 +388,7 @@ exports.xiaoyiPlugin = {
|
|
|
385
388
|
console.log("\n" + "=".repeat(60));
|
|
386
389
|
console.log(`[TIMEOUT] Response received AFTER timeout`);
|
|
387
390
|
console.log(` Session: ${sessionId}`);
|
|
391
|
+
console.log(` Kind: ${kind}`);
|
|
388
392
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
389
393
|
console.log(` Action: DISCARDING (timeout message already sent)`);
|
|
390
394
|
console.log("=".repeat(60) + "\n");
|
|
@@ -394,47 +398,105 @@ exports.xiaoyiPlugin = {
|
|
|
394
398
|
// If response is empty, don't clear timeout (let it trigger)
|
|
395
399
|
if (!completeText || completeText.length === 0) {
|
|
396
400
|
console.log("\n" + "=".repeat(60));
|
|
397
|
-
console.log(`[
|
|
401
|
+
console.log(`[STREAM] Empty ${kind} response detected`);
|
|
398
402
|
console.log(` Session: ${sessionId}`);
|
|
399
403
|
console.log(` Elapsed: ${elapsed}ms`);
|
|
400
|
-
console.log(` Action:
|
|
404
|
+
console.log(` Action: SKIPPING (empty response)`);
|
|
401
405
|
console.log("=".repeat(60) + "\n");
|
|
402
406
|
// Don't send anything, and don't clear timeout
|
|
403
407
|
return;
|
|
404
408
|
}
|
|
405
|
-
console.log("\n" + "-".repeat(60));
|
|
406
|
-
console.log(`XiaoYi: [DELIVER] AI response received`);
|
|
407
|
-
console.log(` Elapsed: ${elapsed}ms`);
|
|
408
|
-
console.log(` Length: ${completeText.length} chars`);
|
|
409
|
-
console.log(` Preview: ${completeText.substring(0, 100)}...`);
|
|
410
|
-
console.log("-".repeat(60) + "\n");
|
|
411
|
-
// Send final response to XiaoYi
|
|
412
|
-
const response = {
|
|
413
|
-
sessionId: sessionId,
|
|
414
|
-
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
415
|
-
timestamp: Date.now(),
|
|
416
|
-
agentId: resolvedAccount.config.agentId,
|
|
417
|
-
sender: {
|
|
418
|
-
id: resolvedAccount.config.agentId,
|
|
419
|
-
name: "OpenClaw Agent",
|
|
420
|
-
type: "agent",
|
|
421
|
-
},
|
|
422
|
-
content: {
|
|
423
|
-
type: "text",
|
|
424
|
-
text: accumulatedText,
|
|
425
|
-
},
|
|
426
|
-
status: "success",
|
|
427
|
-
};
|
|
428
409
|
const conn = runtime.getConnection();
|
|
429
|
-
if (conn) {
|
|
410
|
+
if (!conn) {
|
|
411
|
+
console.error(`✗ XiaoYi: Connection not available\n`);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
// ==================== STREAMING LOGIC ====================
|
|
415
|
+
// For "block" kind: send incremental text (streaming)
|
|
416
|
+
// For "final" kind: send complete text (final message)
|
|
417
|
+
if (kind === "block") {
|
|
418
|
+
// Calculate incremental text
|
|
419
|
+
const incrementalText = completeText.slice(sentTextLength);
|
|
420
|
+
if (incrementalText.length > 0) {
|
|
421
|
+
console.log("\n" + "-".repeat(60));
|
|
422
|
+
console.log(`XiaoYi: [STREAM] Incremental block received`);
|
|
423
|
+
console.log(` Session: ${sessionId}`);
|
|
424
|
+
console.log(` Elapsed: ${elapsed}ms`);
|
|
425
|
+
console.log(` Total length: ${completeText.length} chars`);
|
|
426
|
+
console.log(` Incremental: +${incrementalText.length} chars (sent: ${sentTextLength})`);
|
|
427
|
+
console.log(` Preview: "${incrementalText.substring(0, 50)}${incrementalText.length > 50 ? "..." : ""}"`);
|
|
428
|
+
console.log("-".repeat(60) + "\n");
|
|
429
|
+
const response = {
|
|
430
|
+
sessionId: sessionId,
|
|
431
|
+
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
432
|
+
timestamp: Date.now(),
|
|
433
|
+
agentId: resolvedAccount.config.agentId,
|
|
434
|
+
sender: {
|
|
435
|
+
id: resolvedAccount.config.agentId,
|
|
436
|
+
name: "OpenClaw Agent",
|
|
437
|
+
type: "agent",
|
|
438
|
+
},
|
|
439
|
+
content: {
|
|
440
|
+
type: "text",
|
|
441
|
+
text: incrementalText,
|
|
442
|
+
},
|
|
443
|
+
status: "success",
|
|
444
|
+
};
|
|
445
|
+
// Send incremental text, NOT final, append mode
|
|
446
|
+
await conn.sendResponse(response, taskId, sessionId, false, true);
|
|
447
|
+
console.log(`✓ XiaoYi: Stream chunk sent (+${incrementalText.length} chars)\n`);
|
|
448
|
+
// Update sent length
|
|
449
|
+
sentTextLength = completeText.length;
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
console.log("\n" + "-".repeat(60));
|
|
453
|
+
console.log(`XiaoYi: [STREAM] No new text to send`);
|
|
454
|
+
console.log(` Session: ${sessionId}`);
|
|
455
|
+
console.log(` Total length: ${completeText.length} chars`);
|
|
456
|
+
console.log(` Already sent: ${sentTextLength} chars`);
|
|
457
|
+
console.log("-".repeat(60) + "\n");
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else if (kind === "final") {
|
|
461
|
+
console.log("\n" + "=".repeat(60));
|
|
462
|
+
console.log(`XiaoYi: [STREAM] Final response received`);
|
|
463
|
+
console.log(` Session: ${sessionId}`);
|
|
464
|
+
console.log(` Elapsed: ${elapsed}ms`);
|
|
465
|
+
console.log(` Total length: ${completeText.length} chars`);
|
|
466
|
+
console.log(` Preview: "${completeText.substring(0, 100)}..."`);
|
|
467
|
+
console.log("=".repeat(60) + "\n");
|
|
468
|
+
const response = {
|
|
469
|
+
sessionId: sessionId,
|
|
470
|
+
messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
471
|
+
timestamp: Date.now(),
|
|
472
|
+
agentId: resolvedAccount.config.agentId,
|
|
473
|
+
sender: {
|
|
474
|
+
id: resolvedAccount.config.agentId,
|
|
475
|
+
name: "OpenClaw Agent",
|
|
476
|
+
type: "agent",
|
|
477
|
+
},
|
|
478
|
+
content: {
|
|
479
|
+
type: "text",
|
|
480
|
+
text: completeText,
|
|
481
|
+
},
|
|
482
|
+
status: "success",
|
|
483
|
+
};
|
|
484
|
+
// Send complete text as FINAL, NOT append
|
|
430
485
|
await conn.sendResponse(response, taskId, sessionId, true, false);
|
|
431
|
-
console.log(`✓ XiaoYi:
|
|
486
|
+
console.log(`✓ XiaoYi: Final response sent (${completeText.length} chars)\n`);
|
|
487
|
+
// Clear timeout and abort controller on final
|
|
488
|
+
runtime.markSessionCompleted(sessionId);
|
|
489
|
+
// Note: Don't clear abort controller here, let onIdle handle it
|
|
490
|
+
// This ensures we can still abort if there's any pending cleanup
|
|
432
491
|
}
|
|
433
|
-
else {
|
|
434
|
-
|
|
492
|
+
else if (kind === "tool") {
|
|
493
|
+
// Tool results - typically not sent as messages
|
|
494
|
+
console.log("\n" + "-".repeat(60));
|
|
495
|
+
console.log(`XiaoYi: [STREAM] Tool result received (not forwarded)`);
|
|
496
|
+
console.log(` Session: ${sessionId}`);
|
|
497
|
+
console.log(` Elapsed: ${elapsed}ms`);
|
|
498
|
+
console.log("-".repeat(60) + "\n");
|
|
435
499
|
}
|
|
436
|
-
// Clear timeout as response was sent successfully
|
|
437
|
-
runtime.markSessionCompleted(sessionId);
|
|
438
500
|
},
|
|
439
501
|
onIdle: async () => {
|
|
440
502
|
const elapsed = Date.now() - startTime;
|