@ynhcj/xiaoyi-channel 0.0.149-beta → 0.0.151-beta

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 (76) hide show
  1. package/dist/index.js +3 -69
  2. package/dist/src/approval-bridge.d.ts +48 -0
  3. package/dist/src/approval-bridge.js +382 -0
  4. package/dist/src/bot.js +64 -68
  5. package/dist/src/client.js +13 -23
  6. package/dist/src/cspl/call_api.d.ts +2 -0
  7. package/dist/src/cspl/call_api.js +107 -0
  8. package/dist/src/cspl/config.d.ts +4 -17
  9. package/dist/src/cspl/config.js +80 -70
  10. package/dist/src/cspl/configs.json +10 -0
  11. package/dist/src/cspl/constants.d.ts +46 -24
  12. package/dist/src/cspl/constants.js +41 -16
  13. package/dist/src/cspl/sentinel_hook.d.ts +2 -0
  14. package/dist/src/cspl/sentinel_hook.js +84 -0
  15. package/dist/src/cspl/steer-context.js +1 -1
  16. package/dist/src/cspl/upload_file.d.ts +1 -0
  17. package/dist/src/cspl/upload_file.js +211 -0
  18. package/dist/src/cspl/utils.d.ts +11 -2
  19. package/dist/src/cspl/utils.js +265 -15
  20. package/dist/src/formatter.js +92 -37
  21. package/dist/src/monitor.js +18 -21
  22. package/dist/src/outbound.js +8 -9
  23. package/dist/src/push.js +8 -15
  24. package/dist/src/reply-dispatcher.js +39 -48
  25. package/dist/src/self-evolution-handler.js +1 -1
  26. package/dist/src/sensitive-redactor.d.ts +4 -0
  27. package/dist/src/sensitive-redactor.js +364 -0
  28. package/dist/src/task-manager.js +6 -10
  29. package/dist/src/tools/agent-as-skill-tool.d.ts +7 -0
  30. package/dist/src/tools/agent-as-skill-tool.js +138 -0
  31. package/dist/src/tools/calendar-tool.js +1 -1
  32. package/dist/src/tools/call-device-tool.js +3 -0
  33. package/dist/src/tools/call-phone-tool.js +1 -1
  34. package/dist/src/tools/create-alarm-tool.js +1 -1
  35. package/dist/src/tools/create-all-tools.js +5 -1
  36. package/dist/src/tools/delete-alarm-tool.js +1 -1
  37. package/dist/src/tools/find-pc-devices-tool.d.ts +2 -1
  38. package/dist/src/tools/find-pc-devices-tool.js +84 -88
  39. package/dist/src/tools/get-device-file-tool-schema.js +3 -2
  40. package/dist/src/tools/image-reading-tool.js +4 -4
  41. package/dist/src/tools/location-tool.js +1 -1
  42. package/dist/src/tools/modify-alarm-tool.js +1 -1
  43. package/dist/src/tools/modify-note-tool.js +1 -1
  44. package/dist/src/tools/note-tool.js +1 -1
  45. package/dist/src/tools/query-app-message-tool.js +1 -1
  46. package/dist/src/tools/query-memory-data-tool.js +1 -1
  47. package/dist/src/tools/query-todo-task-tool.js +1 -1
  48. package/dist/src/tools/save-file-to-phone-tool.js +1 -1
  49. package/dist/src/tools/save-media-to-gallery-tool.js +1 -1
  50. package/dist/src/tools/search-alarm-tool.js +1 -1
  51. package/dist/src/tools/search-calendar-tool.js +1 -1
  52. package/dist/src/tools/search-contact-tool.js +1 -1
  53. package/dist/src/tools/search-email-tool.js +1 -1
  54. package/dist/src/tools/search-file-tool.js +11 -8
  55. package/dist/src/tools/search-message-tool.js +1 -1
  56. package/dist/src/tools/search-note-tool.js +1 -1
  57. package/dist/src/tools/search-photo-gallery-tool.js +1 -1
  58. package/dist/src/tools/send-email-tool.js +1 -1
  59. package/dist/src/tools/send-file-to-user-tool.js +2 -2
  60. package/dist/src/tools/send-message-tool.js +1 -1
  61. package/dist/src/tools/session-manager.js +5 -0
  62. package/dist/src/tools/upload-file-tool.js +15 -5
  63. package/dist/src/tools/upload-photo-tool.js +1 -1
  64. package/dist/src/tools/xiaoyi-add-collection-tool.js +1 -1
  65. package/dist/src/tools/xiaoyi-collection-tool.js +1 -1
  66. package/dist/src/tools/xiaoyi-delete-collection-tool.js +1 -1
  67. package/dist/src/tools/xiaoyi-gui-tool.js +1 -1
  68. package/dist/src/trigger-handler.js +4 -7
  69. package/dist/src/utils/config-manager.js +3 -6
  70. package/dist/src/utils/logger.d.ts +8 -0
  71. package/dist/src/utils/logger.js +69 -34
  72. package/dist/src/utils/pushdata-manager.js +1 -5
  73. package/dist/src/utils/pushid-manager.js +1 -2
  74. package/dist/src/utils/runtime-manager.js +1 -4
  75. package/dist/src/websocket.js +37 -25
  76. package/package.json +1 -1
@@ -15,10 +15,7 @@ import { logger } from "./utils/logger.js";
15
15
  export async function handleTriggerEvent(context, cfg, runtime, accountId) {
16
16
  try {
17
17
  const { event, sessionId, taskId } = context;
18
- logger.log(`[TRIGGER_HANDLER] 📌 Received Trigger event`);
19
- logger.log(`[TRIGGER_HANDLER] - sessionId: ${sessionId}`);
20
- logger.log(`[TRIGGER_HANDLER] - taskId: ${taskId}`);
21
- logger.log(`[TRIGGER_HANDLER] - pushDataId: ${event.payload?.dataMap?.pushDataId}`);
18
+ logger.log(`[TRIGGER_HANDLER] Received Trigger event, sessionId: ${sessionId}, taskId: ${taskId}, pushDataId: ${event.payload?.dataMap?.pushDataId}`);
22
19
  // 构造包含 Trigger 事件的 A2A 消息
23
20
  // 将原始 event 放入 message.parts 中,让 handleXYMessage 检测并处理
24
21
  const a2aMessage = {
@@ -42,7 +39,7 @@ export async function handleTriggerEvent(context, cfg, runtime, accountId) {
42
39
  },
43
40
  },
44
41
  };
45
- logger.log(`[TRIGGER_HANDLER] 🚀 Dispatching to handleXYMessage for processing`);
42
+ logger.log(`[TRIGGER_HANDLER] Dispatching to handleXYMessage for processing`);
46
43
  // 通过 handleXYMessage 处理(复用现有链路)
47
44
  await handleXYMessage({
48
45
  cfg,
@@ -50,9 +47,9 @@ export async function handleTriggerEvent(context, cfg, runtime, accountId) {
50
47
  message: a2aMessage,
51
48
  accountId,
52
49
  });
53
- logger.log(`[TRIGGER_HANDLER] Trigger event dispatched successfully`);
50
+ logger.log(`[TRIGGER_HANDLER] Trigger event dispatched successfully`);
54
51
  }
55
52
  catch (err) {
56
- logger.error(`[TRIGGER_HANDLER] Failed to handle Trigger event:`, err);
53
+ logger.error(`[TRIGGER_HANDLER] Failed to handle Trigger event:`, err);
57
54
  }
58
55
  }
@@ -12,15 +12,12 @@ class ConfigManager {
12
12
  */
13
13
  updatePushId(sessionId, pushId) {
14
14
  if (!pushId) {
15
- logger.warn(`[ConfigManager] Attempted to set empty pushId for session ${sessionId}`);
15
+ logger.warn(`[ConfigManager] Attempted to set empty pushId`);
16
16
  return;
17
17
  }
18
18
  const previous = this.sessionPushIds.get(sessionId);
19
19
  if (previous !== pushId) {
20
- logger.log(`[ConfigManager] Updated pushId for session ${sessionId}`);
21
- logger.log(`[ConfigManager] - Previous: ${previous ? previous.substring(0, 20) + '...' : 'none'}`);
22
- logger.log(`[ConfigManager] - New: ${pushId.substring(0, 20)}...`);
23
- logger.log(`[ConfigManager] - Full new pushId: ${pushId}`);
20
+ logger.log(`[ConfigManager] Updated pushId: previous=${previous ? previous.substring(0, 20) : 'none'}, new=${pushId.substring(0, 20)}`);
24
21
  this.sessionPushIds.set(sessionId, pushId);
25
22
  this.globalPushId = pushId; // Also update global for backward compatibility
26
23
  }
@@ -42,7 +39,7 @@ class ConfigManager {
42
39
  */
43
40
  clearSession(sessionId) {
44
41
  this.sessionPushIds.delete(sessionId);
45
- logger.debug(`[ConfigManager] Cleared pushId for session ${sessionId}`);
42
+ logger.debug(`[ConfigManager] Cleared pushId`);
46
43
  }
47
44
  /**
48
45
  * Clear all cached push IDs.
@@ -1,6 +1,14 @@
1
+ export interface ScopedLogger {
2
+ log(message: string, ...args: any[]): void;
3
+ warn(message: string, ...args: any[]): void;
4
+ error(message: string, ...args: any[]): void;
5
+ debug(message: string, ...args: any[]): void;
6
+ }
1
7
  export declare const logger: {
2
8
  log(message: string, ...args: any[]): void;
3
9
  warn(message: string, ...args: any[]): void;
4
10
  error(message: string, ...args: any[]): void;
5
11
  debug(message: string, ...args: any[]): void;
12
+ /** Create a scoped logger with explicit sessionId/taskId (bypasses AsyncLocalStorage/globalThis). */
13
+ withContext(sessionId: string, taskId: string): ScopedLogger;
6
14
  };
@@ -1,4 +1,5 @@
1
- // Pino-based logging utilities for XY channel
1
+ // Logging utilities for XY channel
2
+ // Format: | level | time | sessionId | taskId | msg
2
3
  import pino from "pino";
3
4
  import { mkdirSync, readdirSync, unlinkSync, statSync } from "fs";
4
5
  import { join } from "path";
@@ -6,14 +7,20 @@ import { join } from "path";
6
7
  const LOG_DIR = "/tmp/openclaw";
7
8
  const LOG_PREFIX = "xiaoyi-channel";
8
9
  const MAX_AGE_DAYS = 30;
9
- // ── Daily log file path ──
10
+ // ── UTC+8 helpers ──
10
11
  function getTodayDateStr() {
11
- const d = new Date();
12
- return [
13
- d.getFullYear(),
14
- String(d.getMonth() + 1).padStart(2, "0"),
15
- String(d.getDate()).padStart(2, "0"),
16
- ].join("");
12
+ const utc8 = new Date(Date.now() + 8 * 60 * 60 * 1000);
13
+ return `${utc8.getUTCFullYear()}${String(utc8.getUTCMonth() + 1).padStart(2, "0")}${String(utc8.getUTCDate()).padStart(2, "0")}`;
14
+ }
15
+ function formatTimestampUTC8() {
16
+ const utc8 = new Date(Date.now() + 8 * 60 * 60 * 1000);
17
+ const y = utc8.getUTCFullYear();
18
+ const M = String(utc8.getUTCMonth() + 1).padStart(2, "0");
19
+ const D = String(utc8.getUTCDate()).padStart(2, "0");
20
+ const h = String(utc8.getUTCHours()).padStart(2, "0");
21
+ const m = String(utc8.getUTCMinutes()).padStart(2, "0");
22
+ const s = String(utc8.getUTCSeconds()).padStart(2, "0");
23
+ return `${y}${M}${D}T${h}${m}${s}`;
17
24
  }
18
25
  function getLogFilePath(dateStr) {
19
26
  return join(LOG_DIR, `${LOG_PREFIX}-${dateStr ?? getTodayDateStr()}.log`);
@@ -46,19 +53,9 @@ cleanupOldLogs();
46
53
  // Schedule periodic cleanup every 6 hours
47
54
  const cleanupTimer = setInterval(cleanupOldLogs, 6 * 60 * 60 * 1000);
48
55
  cleanupTimer.unref?.();
49
- // ── Pino instance with daily rotation ──
56
+ // ── File destination with daily rotation ──
50
57
  let currentDate = getTodayDateStr();
51
58
  const dest = pino.destination({ dest: getLogFilePath(currentDate), sync: false, mkdir: true });
52
- const pinoLogger = pino({
53
- level: "debug",
54
- base: undefined,
55
- timestamp: pino.stdTimeFunctions.isoTime,
56
- formatters: {
57
- level(label) {
58
- return { level: label };
59
- },
60
- },
61
- }, dest);
62
59
  // ── Rotation check ──
63
60
  function checkRotation() {
64
61
  const today = getTodayDateStr();
@@ -68,34 +65,72 @@ function checkRotation() {
68
65
  cleanupOldLogs();
69
66
  }
70
67
  }
68
+ // ── Session context from globalThis (avoids circular dep with session-manager) ──
69
+ function getSessionInfo() {
70
+ try {
71
+ const g = globalThis;
72
+ // Try AsyncLocalStorage first (correct for concurrent sessions)
73
+ const als = g.__xyAsyncLocalStorage;
74
+ if (als) {
75
+ const store = als.getStore();
76
+ if (store?.sessionId)
77
+ return { sessionId: store.sessionId, taskId: store.taskId ?? "" };
78
+ }
79
+ // Fallback to activeSessions map
80
+ const sessions = g.__xyActiveSessions;
81
+ if (sessions && sessions.size > 0) {
82
+ const lastKey = g.__xyLastRegisteredSessionKey;
83
+ if (lastKey) {
84
+ const entry = sessions.get(lastKey);
85
+ if (entry?.sessionId)
86
+ return { sessionId: entry.sessionId, taskId: entry.taskId ?? "" };
87
+ }
88
+ const entry = sessions.values().next().value;
89
+ if (entry?.sessionId)
90
+ return { sessionId: entry.sessionId, taskId: entry.taskId ?? "" };
91
+ }
92
+ }
93
+ catch { }
94
+ return { sessionId: "", taskId: "" };
95
+ }
71
96
  // ── Global error handlers (catch-all) ──
72
97
  process.on("uncaughtException", (err) => {
73
- pinoLogger.fatal({ err }, "Uncaught exception");
98
+ writeLog("fatal", "Uncaught exception", [err]);
74
99
  });
75
100
  process.on("unhandledRejection", (reason) => {
76
- pinoLogger.error({ reason }, "Unhandled rejection");
101
+ writeLog("error", "Unhandled rejection", [reason]);
77
102
  });
78
- // ── Exported logger (same API as before) ──
103
+ // ── Core write function with optional explicit context ──
104
+ function writeLog(level, message, args, explicitSid, explicitTid) {
105
+ checkRotation();
106
+ const sessionId = explicitSid !== undefined ? explicitSid : getSessionInfo().sessionId;
107
+ const taskId = explicitTid !== undefined ? explicitTid : getSessionInfo().taskId;
108
+ const timestamp = formatTimestampUTC8();
109
+ const msg = args.length ? formatMessage(message, args) : message;
110
+ dest.write(`|${level}|${timestamp}|${sessionId}|${taskId}|${msg}\n`);
111
+ }
112
+ // ── Exported logger ──
79
113
  export const logger = {
80
114
  log(message, ...args) {
81
- checkRotation();
82
- const msg = formatMessage(message, args);
83
- pinoLogger.info(msg);
115
+ writeLog("info", message, args);
84
116
  },
85
117
  warn(message, ...args) {
86
- checkRotation();
87
- const msg = formatMessage(message, args);
88
- pinoLogger.warn(msg);
118
+ writeLog("warn", message, args);
89
119
  },
90
120
  error(message, ...args) {
91
- checkRotation();
92
- const msg = formatMessage(message, args);
93
- pinoLogger.error(msg);
121
+ writeLog("error", message, args);
94
122
  },
95
123
  debug(message, ...args) {
96
- checkRotation();
97
- const msg = formatMessage(`[DEBUG] ${message}`, args);
98
- pinoLogger.debug(msg);
124
+ writeLog("debug", message, args);
125
+ },
126
+ /** Create a scoped logger with explicit sessionId/taskId (bypasses AsyncLocalStorage/globalThis). */
127
+ withContext(sessionId, taskId) {
128
+ return {
129
+ log(message, ...args) { writeLog("info", message, args, sessionId, taskId); },
130
+ warn(message, ...args) { writeLog("warn", message, args, sessionId, taskId); },
131
+ error(message, ...args) { writeLog("error", message, args, sessionId, taskId); },
132
+ debug(message, ...args) { writeLog("debug", message, args, sessionId, taskId); },
133
+ };
99
134
  },
100
135
  };
101
136
  function formatMessage(message, args) {
@@ -88,11 +88,7 @@ export async function savePushData(dataDetail) {
88
88
  const list = await readPushDataList();
89
89
  list.push(item);
90
90
  await writePushDataList(list);
91
- logger.log(`[PushDataManager] Saved pushData`);
92
- logger.log(`[PushDataManager] - pushDataId: ${pushDataId}`);
93
- logger.log(`[PushDataManager] - time: ${time}`);
94
- logger.log(`[PushDataManager] - dataDetail length: ${dataDetail.length} chars`);
95
- logger.log(`[PushDataManager] - Total items: ${list.length}`);
91
+ logger.log(`[PushDataManager] Saved pushData: id=${pushDataId}, time=${time}, dataLength=${dataDetail.length}, totalItems=${list.length}`);
96
92
  return pushDataId;
97
93
  }
98
94
  catch (error) {
@@ -69,8 +69,7 @@ export async function addPushId(pushId) {
69
69
  // 添加新 pushId
70
70
  list.push(pushId);
71
71
  await writePushIdList(list);
72
- logger.log(`[PushIdManager] Added new pushId: ${pushId.substring(0, 20)}...`);
73
- logger.log(`[PushIdManager] - Total pushIds: ${list.length}`);
72
+ logger.log(`[PushIdManager] Added new pushId: ${pushId.substring(0, 20)}, total=${list.length}`);
74
73
  }
75
74
  catch (error) {
76
75
  logger.error(`[PushIdManager] Failed to add pushId:`, error);
@@ -52,10 +52,7 @@ export async function saveRuntimeInfo(webSocketSessionId, conversationId, taskId
52
52
  }
53
53
  const result = lines.filter((line) => line.trim() !== "").join("\n") + "\n";
54
54
  await fs.writeFile(RUNTIME_FILE, result, "utf-8");
55
- logger.log(`[RuntimeManager] Saved runtime info to .xiaoyiruntime`);
56
- logger.log(`[RuntimeManager] - SESSION_ID: ${webSocketSessionId}`);
57
- logger.log(`[RuntimeManager] - CONVERSATION_ID: ${conversationId}`);
58
- logger.log(`[RuntimeManager] - TASK_ID: ${taskId}`);
55
+ logger.log(`[RuntimeManager] Saved runtime info: SESSION_ID=${webSocketSessionId}, CONVERSATION_ID=${conversationId}, TASK_ID=${taskId}`);
59
56
  }
60
57
  catch (error) {
61
58
  logger.error(`[RuntimeManager] Failed to save runtime info:`, error);
@@ -137,7 +137,8 @@ export class XYWebSocketManager extends EventEmitter {
137
137
  this.listenerCount('error') +
138
138
  this.listenerCount('ready') +
139
139
  this.listenerCount('data-event') +
140
- this.listenerCount('gui-agent-response');
140
+ this.listenerCount('gui-agent-response') +
141
+ this.listenerCount('agent-as-skill-response');
141
142
  return {
142
143
  cacheKey,
143
144
  connection: connectionDiag,
@@ -364,8 +365,14 @@ export class XYWebSocketManager extends EventEmitter {
364
365
  handleMessage(data) {
365
366
  try {
366
367
  const messageStr = data.toString();
367
- this.log(`[WS-RECV] Raw message frame, size: ${messageStr.length} characters`);
368
368
  const parsed = JSON.parse(messageStr);
369
+ // Extract sessionId/taskId early for scoped logging
370
+ const sessionId = parsed.params?.sessionId || parsed.sessionId;
371
+ const taskId = parsed.params?.id || parsed.taskId || "";
372
+ const log = sessionId
373
+ ? logger.withContext(sessionId, taskId)
374
+ : { log: (msg, ...args) => logger.log(msg, ...args) };
375
+ log.log(`[WS-RECV] Raw message frame, size: ${messageStr.length} characters`);
369
376
  // 提取并打印消息内容(只显示 text,data 只打印提示)
370
377
  const parts = parsed.params?.message?.parts;
371
378
  if (parts && Array.isArray(parts) && parts.length > 0) {
@@ -390,7 +397,7 @@ export class XYWebSocketManager extends EventEmitter {
390
397
  // 如果长度 > 8,显示前5个 + *** + 后5个
391
398
  maskedText = `${textContents.slice(0, 5)}***${textContents.slice(-5)}`;
392
399
  }
393
- this.log("[WS-RECV] Text:", maskedText);
400
+ log.log(`[WS-RECV] Text: ${maskedText}`);
394
401
  }
395
402
  }
396
403
  }
@@ -398,7 +405,6 @@ export class XYWebSocketManager extends EventEmitter {
398
405
  if (parsed.jsonrpc === "2.0") {
399
406
  const a2aRequest = parsed;
400
407
  // Extract sessionId from params
401
- const sessionId = a2aRequest.params?.sessionId;
402
408
  if (!sessionId) {
403
409
  this.error("[XY] Message missing sessionId");
404
410
  return;
@@ -411,10 +417,10 @@ export class XYWebSocketManager extends EventEmitter {
411
417
  for (const dataPart of dataParts) {
412
418
  const events = dataPart.data?.events;
413
419
  if (!Array.isArray(events)) {
414
- this.log("[XY] dataPart.data.events is not an array, skipping");
420
+ log.log("[XY] dataPart.data.events is not an array, skipping");
415
421
  continue;
416
422
  }
417
- this.log(`[XY] Processing ${events.length} events from data.events`);
423
+ log.log(`[XY] Processing ${events.length} events from data.events`);
418
424
  for (const item of events) {
419
425
  if (item.header?.name === "UploadExeResult" && item.payload?.intentName) {
420
426
  const dataEvent = {
@@ -422,15 +428,15 @@ export class XYWebSocketManager extends EventEmitter {
422
428
  outputs: item.payload.outputs || {},
423
429
  status: "success",
424
430
  };
425
- this.log(`[XY] Emitting data-event, intentName: ${item.payload.intentName}, size: ${JSON.stringify(dataEvent).length} bytes`);
431
+ log.log(`[XY] Emitting data-event, intentName: ${item.payload.intentName}, size: ${JSON.stringify(dataEvent).length} bytes`);
426
432
  this.emit("data-event", dataEvent);
427
433
  }
428
434
  else if (item.header?.namespace === "ClawAgent" && item.header?.name === "InvokeJarvisGUIAgentResponse") {
429
- this.log(`[XY] Emitting gui-agent-response, size: ${JSON.stringify(item).length} bytes`);
435
+ log.log(`[XY] Emitting gui-agent-response, size: ${JSON.stringify(item).length} bytes`);
430
436
  this.emit("gui-agent-response", item);
431
437
  }
432
438
  else if (item.header?.namespace === "Common" && item.header?.name === "Trigger") {
433
- this.log("[XY] Trigger event detected, emitting trigger-event with context");
439
+ log.log("[XY] Trigger event detected, emitting trigger-event with context");
434
440
  // 传递完整上下文:event、sessionId、taskId
435
441
  this.emit("trigger-event", {
436
442
  event: item,
@@ -439,13 +445,13 @@ export class XYWebSocketManager extends EventEmitter {
439
445
  });
440
446
  }
441
447
  else if (item.header?.namespace === "AgentEvent" && item.header?.name === "ClawSelfEvolutionState") {
442
- this.log("[XY] ClawSelfEvolutionState event detected, emitting self-evolution-event");
448
+ log.log("[XY] ClawSelfEvolutionState event detected, emitting self-evolution-event");
443
449
  this.emit("self-evolution-event", {
444
450
  event: item,
445
451
  });
446
452
  }
447
453
  else if (item.header?.namespace === "AgentEvent" && item.header?.name === "ClawSelfEvolutionStateGet") {
448
- this.log("[XY] ClawSelfEvolutionStateGet event detected, emitting self-evolution-state-get-event");
454
+ log.log("[XY] ClawSelfEvolutionStateGet event detected, emitting self-evolution-state-get-event");
449
455
  this.emit("self-evolution-state-get-event", {
450
456
  event: item,
451
457
  sessionId: sessionId,
@@ -454,11 +460,15 @@ export class XYWebSocketManager extends EventEmitter {
454
460
  });
455
461
  }
456
462
  else if (item.header?.namespace === "LoginTokenEvent" && item.header?.name === "ClawAutoLogin") {
457
- this.log("[XY] LoginTokenEvent.ClawAutoLogin detected, emitting login-token-event");
463
+ log.log("[XY] LoginTokenEvent.ClawAutoLogin detected, emitting login-token-event");
458
464
  this.emit("login-token-event", {
459
465
  event: item,
460
466
  });
461
467
  }
468
+ else if (item.header?.namespace === "System" && item.header?.name === "ExecuteAgentAsSkillResponse") {
469
+ log.log("[XY] ExecuteAgentAsSkillResponse detected, emitting agent-as-skill-response");
470
+ this.emit("agent-as-skill-response", item);
471
+ }
462
472
  }
463
473
  }
464
474
  return;
@@ -469,16 +479,16 @@ export class XYWebSocketManager extends EventEmitter {
469
479
  }
470
480
  // Wrapped format (InboundWebSocketMessage)
471
481
  const inboundMsg = parsed;
472
- this.log(`[XY] Message type: Wrapped, msgType: ${inboundMsg.msgType}`);
482
+ log.log(`[XY] Message type: Wrapped, msgType: ${inboundMsg.msgType}`);
473
483
  // Handle heartbeat responses
474
484
  if (inboundMsg.msgType === "heartbeat") {
475
- this.log("[XY] Received heartbeat response");
485
+ log.log("[XY] Received heartbeat response");
476
486
  this.onHealthEvent?.();
477
487
  return;
478
488
  }
479
489
  // Handle data messages
480
490
  if (inboundMsg.msgType === "data") {
481
- this.log("[XY] Processing data message");
491
+ log.log("[XY] Processing data message");
482
492
  try {
483
493
  const a2aRequest = JSON.parse(inboundMsg.msgDetail);
484
494
  const dataParts = a2aRequest.params?.message?.parts?.filter((p) => p.kind === "data");
@@ -486,10 +496,10 @@ export class XYWebSocketManager extends EventEmitter {
486
496
  for (const dataPart of dataParts) {
487
497
  const events = dataPart.data?.events;
488
498
  if (!Array.isArray(events)) {
489
- this.log("[XY] dataPart.data.events is not an array, skipping");
499
+ log.log("[XY] dataPart.data.events is not an array, skipping");
490
500
  continue;
491
501
  }
492
- this.log(`[XY] Processing ${events.length} events from data.events`);
502
+ log.log(`[XY] Processing ${events.length} events from data.events`);
493
503
  for (const item of events) {
494
504
  if (item.header?.name === "UploadExeResult" && item.payload?.intentName) {
495
505
  const dataEvent = {
@@ -497,15 +507,15 @@ export class XYWebSocketManager extends EventEmitter {
497
507
  outputs: item.payload.outputs || {},
498
508
  status: "success",
499
509
  };
500
- this.log(`[XY] Emitting data-event, intentName: ${item.payload.intentName}, size: ${JSON.stringify(dataEvent).length} bytes`);
510
+ log.log(`[XY] Emitting data-event, intentName: ${item.payload.intentName}, size: ${JSON.stringify(dataEvent).length} bytes`);
501
511
  this.emit("data-event", dataEvent);
502
512
  }
503
513
  else if (item.header?.namespace === "ClawAgent" && item.header?.name === "InvokeJarvisGUIAgentResponse") {
504
- this.log(`[XY] Emitting gui-agent-response, size: ${JSON.stringify(item).length} bytes`);
514
+ log.log(`[XY] Emitting gui-agent-response, size: ${JSON.stringify(item).length} bytes`);
505
515
  this.emit("gui-agent-response", item);
506
516
  }
507
517
  else if (item.header?.namespace === "Common" && item.header?.name === "Trigger") {
508
- this.log("[XY] Trigger event detected (wrapped format), emitting trigger-event with context");
518
+ log.log("[XY] Trigger event detected (wrapped format), emitting trigger-event with context");
509
519
  // 传递完整上下文:event、sessionId、taskId
510
520
  this.emit("trigger-event", {
511
521
  event: item,
@@ -514,11 +524,15 @@ export class XYWebSocketManager extends EventEmitter {
514
524
  });
515
525
  }
516
526
  else if (item.header?.namespace === "LoginTokenEvent" && item.header?.name === "ClawAutoLogin") {
517
- this.log("[XY] LoginTokenEvent.ClawAutoLogin detected (wrapped format), emitting login-token-event");
527
+ log.log("[XY] LoginTokenEvent.ClawAutoLogin detected (wrapped format), emitting login-token-event");
518
528
  this.emit("login-token-event", {
519
529
  event: item,
520
530
  });
521
531
  }
532
+ else if (item.header?.namespace === "System" && item.header?.name === "ExecuteAgentAsSkillResponse") {
533
+ log.log("[XY] ExecuteAgentAsSkillResponse detected (wrapped format), emitting agent-as-skill-response");
534
+ this.emit("agent-as-skill-response", item);
535
+ }
522
536
  }
523
537
  }
524
538
  }
@@ -530,11 +544,9 @@ export class XYWebSocketManager extends EventEmitter {
530
544
  }
531
545
  // Parse msgDetail as A2AJsonRpcRequest
532
546
  const a2aRequest = JSON.parse(inboundMsg.msgDetail);
533
- this.log(`[XY] Parsed A2A request, method: ${a2aRequest.method}`);
534
- const sessionId = inboundMsg.sessionId;
535
- this.log(`[XY] Session ID: ${sessionId}`);
547
+ log.log(`[XY] Parsed A2A request, method: ${a2aRequest.method}`);
536
548
  // Emit message event
537
- this.log("[XY] *** EMITTING message event (Wrapped path) ***");
549
+ log.log("[XY] Emitting message event (Wrapped path)");
538
550
  this.emit("message", a2aRequest, sessionId);
539
551
  }
540
552
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.149-beta",
3
+ "version": "0.0.151-beta",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",