@ynhcj/xiaoyi 2.2.4 → 2.2.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.
Files changed (2) hide show
  1. package/dist/channel.js +13 -199
  2. package/package.json +1 -1
package/dist/channel.js CHANGED
@@ -3,57 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.xiaoyiPlugin = void 0;
4
4
  const runtime_1 = require("./runtime");
5
5
  const file_handler_1 = require("./file-handler");
6
- // Import agent event functions - will be resolved at runtime
7
- // Use dynamic require for compatibility
8
- let onAgentEvent = null;
9
- let registerAgentRunContext = null;
10
- try {
11
- // Try multiple import paths
12
- let agentEvents = null;
13
- // Try path 1: openclaw/dist/infra/agent-events
14
- try {
15
- agentEvents = require("openclaw/dist/infra/agent-events");
16
- console.log("XiaoYi: [AGENT EVENT] Imported from openclaw/dist/infra/agent-events");
17
- }
18
- catch (e1) {
19
- console.log("XiaoYi: [AGENT EVENT] Path 1 failed:", e1?.message || e1);
20
- // Try path 2: ../openclaw/dist/infra/agent-events
21
- try {
22
- agentEvents = require("../openclaw/dist/infra/agent-events");
23
- console.log("XiaoYi: [AGENT EVENT] Imported from ../openclaw/dist/infra/agent-events");
24
- }
25
- catch (e2) {
26
- console.log("XiaoYi: [AGENT EVENT] Path 2 failed:", e2?.message || e2);
27
- // Try path 3: ../../openclaw/dist/infra/agent-events
28
- try {
29
- agentEvents = require("../../openclaw/dist/infra/agent-events");
30
- console.log("XiaoYi: [AGENT EVENT] Imported from ../../openclaw/dist/infra/agent-events");
31
- }
32
- catch (e3) {
33
- console.error("XiaoYi: [AGENT EVENT] All import paths failed:");
34
- console.error(" Path 1 (openclaw/dist/infra/agent-events):", e1?.message || e1);
35
- console.error(" Path 2 (../openclaw/dist/infra/agent-events):", e2?.message || e2);
36
- console.error(" Path 3 (../../openclaw/dist/infra/agent-events):", e3?.message || e3);
37
- }
38
- }
39
- }
40
- if (agentEvents) {
41
- onAgentEvent = agentEvents.onAgentEvent;
42
- registerAgentRunContext = agentEvents.registerAgentRunContext;
43
- if (typeof onAgentEvent === "function") {
44
- console.log("XiaoYi: [AGENT EVENT] ✓ onAgentEvent function imported successfully");
45
- }
46
- else {
47
- console.error("XiaoYi: [AGENT EVENT] ✗ onAgentEvent is not a function, type:", typeof onAgentEvent);
48
- }
49
- }
50
- else {
51
- console.warn("XiaoYi: [AGENT EVENT] Could not import agent event module");
52
- }
53
- }
54
- catch (error) {
55
- console.error("XiaoYi: [AGENT EVENT] Fatal import error:", error?.message || error);
56
- }
57
6
  /**
58
7
  * XiaoYi Channel Plugin
59
8
  * Implements OpenClaw ChannelPlugin interface for XiaoYi A2A protocol
@@ -358,164 +307,33 @@ exports.xiaoyiPlugin = {
358
307
  SenderId: senderId,
359
308
  OriginatingChannel: "xiaoyi",
360
309
  };
361
- // Use the correct API to dispatch the message (streaming via onAgentEvent)
310
+ // Dispatch message using OpenClaw's reply dispatcher
362
311
  try {
363
- const streamingEnabled = resolvedAccount.config.enableStreaming === true;
364
- const hasAgentEventSupport = typeof onAgentEvent === "function";
365
312
  console.log("\n" + "=".repeat(60));
366
- console.log(`XiaoYi: [STREAMING] Starting message processing`);
313
+ console.log(`XiaoYi: [MESSAGE] Processing user message`);
367
314
  console.log(` Session: ${message.sessionId}`);
368
315
  console.log(` Task ID: ${message.params.id}`);
369
316
  console.log(` User input: ${bodyText.substring(0, 50)}${bodyText.length > 50 ? "..." : ""}`);
370
- console.log(` Config Streaming: ${streamingEnabled ? "ENABLED" : "DISABLED"}`);
371
- console.log(` Agent Event Support: ${hasAgentEventSupport ? "AVAILABLE" : "NOT AVAILABLE"}`);
372
- console.log(` Effective Streaming: ${streamingEnabled && hasAgentEventSupport ? "ENABLED (via onAgentEvent)" : "DISABLED"}`);
317
+ console.log(` Images: ${images.length}`);
373
318
  console.log("=".repeat(60) + "\n");
374
- // Track response state for streaming
375
- let accumulatedText = "";
376
- let taskId = runtime.getTaskIdForSession(message.sessionId) || `task_${Date.now()}`;
377
- let frameCount = 0;
378
- let partialCount = 0;
319
+ const taskId = runtime.getTaskIdForSession(message.sessionId) || `task_${Date.now()}`;
379
320
  const startTime = Date.now();
380
- // Register agent event listener for streaming (NEW METHOD)
381
- let unsubscribeAgentEvents;
382
- let runId;
383
- let isCompleted = false;
384
- if (streamingEnabled && hasAgentEventSupport) {
385
- // Subscribe to agent events BEFORE dispatching the message
386
- unsubscribeAgentEvents = onAgentEvent((evt) => {
387
- if (isCompleted)
388
- return;
389
- // Get runId from first event
390
- if (!runId && evt.runId) {
391
- runId = evt.runId;
392
- console.log(`XiaoYi: [AGENT EVENT] Registered runId: ${runId}`);
393
- }
394
- // Only process events for this run
395
- if (runId && evt.runId !== runId)
396
- return;
397
- const elapsed = Date.now() - startTime;
398
- // Handle streaming text events
399
- if (evt.stream === "assistant" && typeof evt.data?.text === "string") {
400
- const newText = evt.data.text;
401
- if (!newText)
402
- return;
403
- // Calculate delta text
404
- const previousLength = accumulatedText.length;
405
- accumulatedText = newText;
406
- const deltaText = newText.slice(previousLength);
407
- console.log(`\n>>> XiaoYi: [AGENT EVENT] Stream frame #${++partialCount} at ${elapsed}ms`);
408
- console.log(` Run ID: ${evt.runId}`);
409
- console.log(` Delta length: ${deltaText.length} chars`);
410
- console.log(` Total length: ${newText.length} chars`);
411
- console.log(` Delta content: "${deltaText}"`);
412
- // Send PARTIAL frame with delta content
413
- const partialResponse = {
414
- sessionId: message.sessionId,
415
- messageId: `partial_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
416
- timestamp: Date.now(),
417
- agentId: resolvedAccount.config.agentId,
418
- sender: {
419
- id: resolvedAccount.config.agentId,
420
- name: "OpenClaw Agent",
421
- type: "agent",
422
- },
423
- content: {
424
- type: "text",
425
- text: deltaText || newText,
426
- },
427
- status: "processing",
428
- };
429
- const conn = runtime.getConnection();
430
- if (conn) {
431
- conn.sendResponse(partialResponse, taskId, message.sessionId, false, true)
432
- .then(() => {
433
- console.log(` ✓ SENT (isFinal=false, append=true)\n`);
434
- })
435
- .catch((err) => {
436
- console.error(` ✗ Send failed: ${err}\n`);
437
- });
438
- }
439
- }
440
- // Handle lifecycle events (completion/error)
441
- if (evt.stream === "lifecycle") {
442
- const phase = evt.data?.phase;
443
- if (phase === "end") {
444
- isCompleted = true;
445
- console.log("\n" + "-".repeat(60));
446
- console.log(`XiaoYi: [AGENT EVENT] Lifecycle phase: end`);
447
- console.log(` Run ID: ${evt.runId}`);
448
- console.log(` Elapsed: ${elapsed}ms`);
449
- console.log(` Total frames: ${partialCount}`);
450
- console.log(` Final length: ${accumulatedText.length} chars`);
451
- console.log("-".repeat(60) + "\n");
452
- // Send FINAL frame
453
- const response = {
454
- sessionId: message.sessionId,
455
- messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
456
- timestamp: Date.now(),
457
- agentId: resolvedAccount.config.agentId,
458
- sender: {
459
- id: resolvedAccount.config.agentId,
460
- name: "OpenClaw Agent",
461
- type: "agent",
462
- },
463
- content: {
464
- type: "text",
465
- text: accumulatedText,
466
- },
467
- status: "success",
468
- };
469
- const conn = runtime.getConnection();
470
- if (conn) {
471
- conn.sendResponse(response, taskId, message.sessionId, true, false)
472
- .then(() => {
473
- console.log(`✓ XiaoYi: FINAL frame sent (isFinal=true, append=false)\n`);
474
- })
475
- .catch((err) => {
476
- console.error(`✗ Final send failed: ${err}\n`);
477
- });
478
- }
479
- // Unsubscribe from events
480
- if (unsubscribeAgentEvents) {
481
- unsubscribeAgentEvents();
482
- unsubscribeAgentEvents = undefined;
483
- }
484
- }
485
- else if (phase === "error") {
486
- isCompleted = true;
487
- console.error(`XiaoYi: [AGENT EVENT] Error phase:`, evt.data?.error);
488
- // Unsubscribe from events
489
- if (unsubscribeAgentEvents) {
490
- unsubscribeAgentEvents();
491
- unsubscribeAgentEvents = undefined;
492
- }
493
- }
494
- }
495
- });
496
- console.log(`XiaoYi: [AGENT EVENT] Listener registered for streaming`);
497
- }
498
- else if (streamingEnabled && !hasAgentEventSupport) {
499
- console.warn(`XiaoYi: [WARN] Streaming enabled but onAgentEvent not available, falling back to non-streaming mode`);
500
- }
321
+ let accumulatedText = "";
501
322
  await pluginRuntime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
502
323
  ctx: msgContext,
503
324
  cfg: config,
504
325
  dispatcherOptions: {
505
326
  deliver: async (payload) => {
506
- // NOTE: onAgentEvent does NOT emit "assistant" stream events in production
507
- // Only lifecycle and tool events are emitted
508
- // So we must handle the final result here
509
327
  const elapsed = Date.now() - startTime;
510
328
  const completeText = payload.text || "";
511
329
  accumulatedText = completeText;
512
330
  console.log("\n" + "-".repeat(60));
513
- console.log(`XiaoYi: [DELIVER] Final result received`);
331
+ console.log(`XiaoYi: [DELIVER] AI response received`);
514
332
  console.log(` Elapsed: ${elapsed}ms`);
515
333
  console.log(` Length: ${completeText.length} chars`);
516
- console.log(` Streaming frames sent: ${partialCount}`);
334
+ console.log(` Preview: ${completeText.substring(0, 100)}...`);
517
335
  console.log("-".repeat(60) + "\n");
518
- // Send FINAL frame
336
+ // Send final response to XiaoYi
519
337
  const response = {
520
338
  sessionId: message.sessionId,
521
339
  messageId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
@@ -535,7 +353,10 @@ exports.xiaoyiPlugin = {
535
353
  const conn = runtime.getConnection();
536
354
  if (conn) {
537
355
  await conn.sendResponse(response, taskId, message.sessionId, true, false);
538
- console.log(`✓ XiaoYi: FINAL frame sent (isFinal=true, append=false)\n`);
356
+ console.log(`✓ XiaoYi: Response sent successfully\n`);
357
+ }
358
+ else {
359
+ console.error(`✗ XiaoYi: Connection not available\n`);
539
360
  }
540
361
  },
541
362
  onIdle: async () => {
@@ -543,18 +364,11 @@ exports.xiaoyiPlugin = {
543
364
  console.log("\n" + "=".repeat(60));
544
365
  console.log(`XiaoYi: [IDLE] Processing complete`);
545
366
  console.log(` Total time: ${elapsed}ms`);
546
- console.log(` Streaming frames: ${partialCount}`);
547
367
  console.log(` Final length: ${accumulatedText.length} chars`);
548
368
  console.log("=".repeat(60) + "\n");
549
- // Cleanup event listener if still active
550
- if (unsubscribeAgentEvents && !isCompleted) {
551
- console.log(`XiaoYi: [IDLE] Cleaning up event listener`);
552
- unsubscribeAgentEvents();
553
- unsubscribeAgentEvents = undefined;
554
- }
555
369
  },
556
370
  },
557
- replyOptions: undefined, // onPartialReply is not used
371
+ replyOptions: undefined,
558
372
  images: images.length > 0 ? images : undefined,
559
373
  });
560
374
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "description": "XiaoYi channel plugin for OpenClaw",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",