@ynhcj/xiaoyi 2.1.7 → 2.1.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 +86 -10
- package/dist/types.d.ts +7 -3
- package/dist/websocket.js +16 -4
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -365,19 +365,95 @@ exports.xiaoyiPlugin = {
|
|
|
365
365
|
});
|
|
366
366
|
// Setup cancel handler
|
|
367
367
|
connection.on("cancel", async (data) => {
|
|
368
|
-
console.log(
|
|
368
|
+
console.log("\n" + "=".repeat(60));
|
|
369
|
+
console.log(`XiaoYi: [CANCEL] Received cancel request`);
|
|
370
|
+
console.log(` Session: ${data.sessionId}`);
|
|
371
|
+
console.log(` Task ID: ${data.taskId || "N/A"}`);
|
|
372
|
+
console.log("=".repeat(60) + "\n");
|
|
369
373
|
// CRITICAL: Use dynamic require to get the latest runtime module after hot-reload
|
|
370
374
|
const { getXiaoYiRuntime } = require("./runtime");
|
|
371
375
|
const runtime = getXiaoYiRuntime();
|
|
372
|
-
//
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
376
|
+
// Build SessionKey to match the format used in message handler
|
|
377
|
+
const sessionKey = `xiaoyi:${resolvedAccount.accountId}:${data.sessionId}`;
|
|
378
|
+
// Try to abort the running agent using OpenClaw's internal API
|
|
379
|
+
try {
|
|
380
|
+
// Try to load OpenClaw's internal abort function
|
|
381
|
+
// Note: This requires the plugin to be run within OpenClaw's environment
|
|
382
|
+
const abortEmbeddedPiRun = globalThis["__openclaw_abortEmbeddedPiRun"] ||
|
|
383
|
+
(() => {
|
|
384
|
+
try {
|
|
385
|
+
const openclawPath = require.resolve("openclaw");
|
|
386
|
+
const runsModule = require(`${openclawPath}/dist/agents/pi-embedded-runner/runs.js`);
|
|
387
|
+
return runsModule.abortEmbeddedPiRun;
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
})();
|
|
393
|
+
if (!abortEmbeddedPiRun) {
|
|
394
|
+
console.warn(`XiaoYi: [CANCEL] abortEmbeddedPiRun not available, falling back to event emission`);
|
|
395
|
+
throw new Error("abortEmbeddedPiRun not available");
|
|
396
|
+
}
|
|
397
|
+
// Try to load session store functions
|
|
398
|
+
const loadSessionStore = globalThis["__openclaw_loadSessionStore"] ||
|
|
399
|
+
(() => {
|
|
400
|
+
try {
|
|
401
|
+
const openclawPath = require.resolve("openclaw");
|
|
402
|
+
const sessionModule = require(`${openclawPath}/dist/config/sessions.js`);
|
|
403
|
+
return sessionModule.loadSessionStore;
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
})();
|
|
409
|
+
const resolveStorePath = globalThis["__openclaw_resolveStorePath"] ||
|
|
410
|
+
(() => {
|
|
411
|
+
try {
|
|
412
|
+
const openclawPath = require.resolve("openclaw");
|
|
413
|
+
const sessionModule = require(`${openclawPath}/dist/config/sessions.js`);
|
|
414
|
+
return sessionModule.resolveStorePath;
|
|
415
|
+
}
|
|
416
|
+
catch {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
})();
|
|
420
|
+
if (!loadSessionStore || !resolveStorePath) {
|
|
421
|
+
console.warn(`XiaoYi: [CANCEL] Session store functions not available`);
|
|
422
|
+
throw new Error("Session store functions not available");
|
|
423
|
+
}
|
|
424
|
+
// Load session store and find the internal sessionId
|
|
425
|
+
const agentId = resolvedAccount.config.agentId || "default";
|
|
426
|
+
const storePath = resolveStorePath(config.session?.store, { agentId });
|
|
427
|
+
const store = loadSessionStore(storePath);
|
|
428
|
+
const sessionEntry = store[sessionKey];
|
|
429
|
+
if (sessionEntry && sessionEntry.sessionId) {
|
|
430
|
+
console.log(`XiaoYi: [CANCEL] Found session entry with internal sessionId: ${sessionEntry.sessionId}`);
|
|
431
|
+
// Abort the running agent
|
|
432
|
+
const aborted = abortEmbeddedPiRun(sessionEntry.sessionId);
|
|
433
|
+
if (aborted) {
|
|
434
|
+
console.log(`XiaoYi: [CANCEL] ✓ Successfully aborted agent run for session: ${data.sessionId}\n`);
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
console.warn(`XiaoYi: [CANCEL] ⚠ No active run found for session: ${data.sessionId}\n`);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
console.warn(`XiaoYi: [CANCEL] ⚠ No session entry found for key: ${sessionKey}\n`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
console.error(`XiaoYi: [CANCEL] Error aborting agent:`, error);
|
|
446
|
+
// Fallback: emit cancel event for any listeners
|
|
447
|
+
const pluginRuntime = runtime.getPluginRuntime();
|
|
448
|
+
if (pluginRuntime) {
|
|
449
|
+
pluginRuntime.emit("task:cancel", {
|
|
450
|
+
channel: "xiaoyi",
|
|
451
|
+
accountId: resolvedAccount.accountId,
|
|
452
|
+
taskId: data.taskId,
|
|
453
|
+
sessionId: data.sessionId,
|
|
454
|
+
});
|
|
455
|
+
console.log(`XiaoYi: [CANCEL] Emitted task:cancel event as fallback\n`);
|
|
456
|
+
}
|
|
381
457
|
}
|
|
382
458
|
// Send success response
|
|
383
459
|
const connection = runtime.getConnection();
|
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
|
|
135
|
-
|
|
136
|
-
|
|
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;
|
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
|
}
|
|
@@ -373,11 +381,15 @@ class XiaoYiWebSocketManager extends events_1.EventEmitter {
|
|
|
373
381
|
* Reference: https://developer.huawei.com/consumer/cn/doc/service/tasks-cancel-0000002537561193
|
|
374
382
|
*/
|
|
375
383
|
handleTasksCancelMessage(message) {
|
|
376
|
-
|
|
384
|
+
// Use taskId if available, otherwise use id as the task identifier
|
|
385
|
+
const effectiveTaskId = message.taskId || message.id;
|
|
386
|
+
console.log(`Received tasks/cancel message for task: ${effectiveTaskId}`);
|
|
387
|
+
console.log(` Session: ${message.sessionId}`);
|
|
388
|
+
console.log(` Message ID: ${message.id}`);
|
|
377
389
|
// Emit cancel event for application to handle
|
|
378
390
|
this.emit("cancel", {
|
|
379
391
|
sessionId: message.sessionId,
|
|
380
|
-
taskId:
|
|
392
|
+
taskId: effectiveTaskId,
|
|
381
393
|
id: message.id,
|
|
382
394
|
});
|
|
383
395
|
// Note: We'll send the success response after OpenClaw confirms cancellation
|