@ynhcj/xiaoyi 2.1.7 → 2.1.9

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 CHANGED
@@ -364,26 +364,44 @@ exports.xiaoyiPlugin = {
364
364
  }
365
365
  });
366
366
  // Setup cancel handler
367
+ // Note: The response is already sent in websocket.ts, this is just for additional handling
367
368
  connection.on("cancel", async (data) => {
368
- console.log(`Handling cancel request for task: ${data.taskId}`);
369
- // CRITICAL: Use dynamic require to get the latest runtime module after hot-reload
370
- const { getXiaoYiRuntime } = require("./runtime");
371
- const runtime = getXiaoYiRuntime();
372
- // Get PluginRuntime and emit cancel event
373
- const pluginRuntime = runtime.getPluginRuntime();
374
- if (pluginRuntime) {
375
- pluginRuntime.emit("task:cancel", {
376
- channel: "xiaoyi",
377
- accountId: resolvedAccount.accountId,
378
- taskId: data.taskId,
379
- sessionId: data.sessionId,
380
- });
369
+ console.log("\n" + "=".repeat(60));
370
+ console.log(`XiaoYi: [CANCEL] Cancel event received (response already sent)`);
371
+ console.log(` Session: ${data.sessionId}`);
372
+ console.log(` Task ID: ${data.taskId || "N/A"}`);
373
+ console.log("=".repeat(60) + "\n");
374
+ // Try to abort the running agent by clearing session queues
375
+ // This prevents new messages from being queued and may interrupt streaming
376
+ try {
377
+ const sessionKey = `xiaoyi:${resolvedAccount.accountId}:${data.sessionId}`;
378
+ // Try to load and use clearSessionQueues from OpenClaw at runtime
379
+ // Use require() instead of import to avoid TypeScript compilation errors
380
+ const clearSessionQueues = (() => {
381
+ try {
382
+ // Try direct require first (works when openclaw is installed as dependency)
383
+ const queueModule = require("openclaw/dist/auto-reply/reply/queue.js");
384
+ return queueModule.clearSessionQueues;
385
+ }
386
+ catch {
387
+ return null;
388
+ }
389
+ })();
390
+ if (clearSessionQueues) {
391
+ const cleared = clearSessionQueues([sessionKey]);
392
+ console.log(`XiaoYi: [CANCEL] Cleared session queues:`, cleared);
393
+ }
394
+ else {
395
+ console.log(`XiaoYi: [CANCEL] clearSessionQueues not available, skipping queue cleanup`);
396
+ }
381
397
  }
382
- // Send success response
383
- const connection = runtime.getConnection();
384
- if (connection) {
385
- await connection.sendCancelSuccessResponse(data.sessionId, data.taskId, data.id);
398
+ catch (error) {
399
+ console.log(`XiaoYi: [CANCEL] Could not clear session queues:`, error);
386
400
  }
401
+ // NOTE: True cancellation of the in-progress agent run requires OpenClaw's internal
402
+ // abortEmbeddedPiRun function, which needs the internal sessionId from session store.
403
+ // This channel plugin acknowledges the cancel request, but actual agent interruption
404
+ // depends on OpenClaw's internal mechanisms.
387
405
  });
388
406
  console.log("XiaoYi: Event handlers registered");
389
407
  console.log("XiaoYi: startAccount() completed - END");
package/dist/types.d.ts CHANGED
@@ -104,6 +104,7 @@ export interface A2AClearContextResult {
104
104
  };
105
105
  }
106
106
  export interface A2ATasksCancelResult {
107
+ id: string;
107
108
  status: {
108
109
  state: "canceled" | "failed" | "unknown";
109
110
  };
@@ -131,9 +132,12 @@ export interface A2ATasksCancelMessage {
131
132
  agentId: string;
132
133
  sessionId: string;
133
134
  id: string;
134
- action: "tasks/cancel";
135
- taskId: string;
136
- timestamp: number;
135
+ action?: "tasks/cancel";
136
+ method?: "tasks/cancel";
137
+ taskId?: string;
138
+ jsonrpc?: "2.0";
139
+ conversationId?: string;
140
+ timestamp?: number;
137
141
  }
138
142
  export interface XiaoYiChannelConfig {
139
143
  enabled: boolean;
@@ -78,6 +78,10 @@ export declare class XiaoYiWebSocketManager extends EventEmitter {
78
78
  /**
79
79
  * Handle A2A tasks/cancel message
80
80
  * Reference: https://developer.huawei.com/consumer/cn/doc/service/tasks-cancel-0000002537561193
81
+ *
82
+ * Simplified implementation similar to clearContext:
83
+ * 1. Send success response immediately
84
+ * 2. Emit cancel event for application to handle
81
85
  */
82
86
  private handleTasksCancelMessage;
83
87
  /**
package/dist/websocket.js CHANGED
@@ -165,10 +165,18 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
165
165
  jsonrpc: "2.0",
166
166
  id: requestId,
167
167
  result: {
168
+ id: requestId, // 使用请求中的该字段返回
168
169
  status: {
169
170
  state: success ? "canceled" : "failed"
170
171
  }
171
172
  },
173
+ error: success ? {
174
+ code: 0,
175
+ message: ""
176
+ } : {
177
+ code: -1,
178
+ message: "Failed to cancel task"
179
+ },
172
180
  };
173
181
  const message = {
174
182
  msgType: "agent_response",
@@ -334,8 +342,8 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
334
342
  this.handleClearMessage(message);
335
343
  return;
336
344
  }
337
- // Check if it's a tasks/cancel message
338
- if (message.action === "tasks/cancel") {
345
+ // Check if it's a tasks/cancel message (支持 method 和 action 两种格式)
346
+ if (message.method === "tasks/cancel" || message.action === "tasks/cancel") {
339
347
  this.handleTasksCancelMessage(message);
340
348
  return;
341
349
  }
@@ -371,17 +379,33 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
371
379
  /**
372
380
  * Handle A2A tasks/cancel message
373
381
  * Reference: https://developer.huawei.com/consumer/cn/doc/service/tasks-cancel-0000002537561193
382
+ *
383
+ * Simplified implementation similar to clearContext:
384
+ * 1. Send success response immediately
385
+ * 2. Emit cancel event for application to handle
374
386
  */
375
387
  handleTasksCancelMessage(message) {
376
- console.log(`Received tasks/cancel message for task: ${message.taskId}`);
388
+ // Use taskId if available, otherwise use id as the task identifier
389
+ const effectiveTaskId = message.taskId || message.id;
390
+ console.log(`\n============================================================`);
391
+ console.log(`XiaoYi: [CANCEL] Received cancel request`);
392
+ console.log(` Session: ${message.sessionId}`);
393
+ console.log(` Task ID: ${effectiveTaskId}`);
394
+ console.log(` Message ID: ${message.id}`);
395
+ console.log(`===========================================================\n`);
396
+ // Send success response immediately (similar to clearContext)
397
+ this.sendTasksCancelResponse(message.id, message.sessionId, true).catch(error => {
398
+ console.error("Failed to send tasks/cancel response:", error);
399
+ });
377
400
  // Emit cancel event for application to handle
401
+ // The application can decide how to handle the cancellation
378
402
  this.emit("cancel", {
379
403
  sessionId: message.sessionId,
380
- taskId: message.taskId,
404
+ taskId: effectiveTaskId,
381
405
  id: message.id,
382
406
  });
383
- // Note: We'll send the success response after OpenClaw confirms cancellation
384
- // This will be handled by the channel plugin
407
+ // Remove from active tasks
408
+ this.activeTasks.delete(effectiveTaskId);
385
409
  }
386
410
  /**
387
411
  * Send tasks/cancel success response
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi",
3
- "version": "2.1.7",
3
+ "version": "2.1.9",
4
4
  "description": "XiaoYi channel plugin for OpenClaw",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",