@ynhcj/xiaoyi-channel 0.0.50-beta → 0.0.52-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 (42) hide show
  1. package/dist/index.js +42 -0
  2. package/dist/src/bot.js +3 -16
  3. package/dist/src/client.js +0 -3
  4. package/dist/src/cspl/call-api.d.ts +3 -0
  5. package/dist/src/cspl/call-api.js +79 -0
  6. package/dist/src/cspl/config.d.ts +19 -0
  7. package/dist/src/cspl/config.js +50 -0
  8. package/dist/src/cspl/constants.d.ts +43 -0
  9. package/dist/src/cspl/constants.js +22 -0
  10. package/dist/src/cspl/utils.d.ts +10 -0
  11. package/dist/src/cspl/utils.js +57 -0
  12. package/dist/src/formatter.js +3 -23
  13. package/dist/src/heartbeat.js +0 -4
  14. package/dist/src/reply-dispatcher.js +32 -0
  15. package/dist/src/steer-injector.d.ts +16 -0
  16. package/dist/src/steer-injector.js +74 -0
  17. package/dist/src/tools/calendar-tool.js +2 -37
  18. package/dist/src/tools/call-phone-tool.js +1 -42
  19. package/dist/src/tools/create-alarm-tool.js +3 -74
  20. package/dist/src/tools/delete-alarm-tool.js +3 -45
  21. package/dist/src/tools/image-reading-tool.js +0 -47
  22. package/dist/src/tools/location-tool.js +1 -32
  23. package/dist/src/tools/modify-alarm-tool.js +3 -77
  24. package/dist/src/tools/modify-note-tool.js +1 -34
  25. package/dist/src/tools/note-tool.js +2 -4
  26. package/dist/src/tools/search-alarm-tool.js +3 -61
  27. package/dist/src/tools/search-calendar-tool.js +2 -39
  28. package/dist/src/tools/search-contact-tool.js +0 -30
  29. package/dist/src/tools/search-file-tool.js +0 -33
  30. package/dist/src/tools/search-message-tool.js +0 -33
  31. package/dist/src/tools/search-note-tool.js +1 -26
  32. package/dist/src/tools/search-photo-gallery-tool.js +2 -31
  33. package/dist/src/tools/send-file-to-user-tool.js +0 -39
  34. package/dist/src/tools/send-message-tool.js +1 -39
  35. package/dist/src/tools/session-manager.js +0 -45
  36. package/dist/src/tools/upload-file-tool.js +0 -49
  37. package/dist/src/tools/upload-photo-tool.js +0 -42
  38. package/dist/src/tools/view-push-result-tool.js +0 -11
  39. package/dist/src/tools/xiaoyi-collection-tool.js +4 -82
  40. package/dist/src/tools/xiaoyi-gui-tool.js +0 -34
  41. package/dist/src/websocket.js +24 -10
  42. package/package.json +1 -1
@@ -2,7 +2,6 @@
2
2
  import { getXYWebSocketManager } from "../client.js";
3
3
  import { sendCommand } from "../formatter.js";
4
4
  import { getCurrentSessionContext } from "./session-manager.js";
5
- import { logger } from "../utils/logger.js";
6
5
  /**
7
6
  * XiaoYi GUI tool - executes phone app interactions through GUI agent.
8
7
  * Simulates user interactions on phone screen (click, swipe, input, navigation, etc.)
@@ -38,35 +37,19 @@ export const xiaoyiGuiTool = {
38
37
  required: ["query"],
39
38
  },
40
39
  async execute(toolCallId, params) {
41
- logger.log(`[XIAOYI_GUI_TOOL] 🚀 Starting execution`);
42
- logger.log(`[XIAOYI_GUI_TOOL] - toolCallId: ${toolCallId}`);
43
- logger.log(`[XIAOYI_GUI_TOOL] - query: ${params.query}`);
44
- logger.log(`[XIAOYI_GUI_TOOL] - timestamp: ${new Date().toISOString()}`);
45
40
  // Validate parameters
46
41
  if (!params.query || typeof params.query !== "string") {
47
- logger.error(`[XIAOYI_GUI_TOOL] ❌ FAILED: Invalid query parameter`);
48
42
  throw new Error("Missing or invalid required parameter: query must be a non-empty string");
49
43
  }
50
44
  // Get session context
51
- logger.log(`[XIAOYI_GUI_TOOL] 🔍 Attempting to get session context...`);
52
45
  const sessionContext = getCurrentSessionContext();
53
46
  if (!sessionContext) {
54
- logger.error(`[XIAOYI_GUI_TOOL] ❌ FAILED: No active session found!`);
55
- logger.error(`[XIAOYI_GUI_TOOL] - toolCallId: ${toolCallId}`);
56
47
  throw new Error("No active XY session found. XiaoYi GUI tool can only be used during an active conversation.");
57
48
  }
58
- logger.log(`[XIAOYI_GUI_TOOL] ✅ Session context found`);
59
- logger.log(`[XIAOYI_GUI_TOOL] - sessionId: ${sessionContext.sessionId}`);
60
- logger.log(`[XIAOYI_GUI_TOOL] - taskId (interactionId): ${sessionContext.taskId}`);
61
- logger.log(`[XIAOYI_GUI_TOOL] - messageId: ${sessionContext.messageId}`);
62
- logger.log(`[XIAOYI_GUI_TOOL] - agentId: ${sessionContext.agentId}`);
63
49
  const { config, sessionId, taskId, messageId } = sessionContext;
64
50
  // Get WebSocket manager
65
- logger.log(`[XIAOYI_GUI_TOOL] 🔌 Getting WebSocket manager...`);
66
51
  const wsManager = getXYWebSocketManager(config);
67
- logger.log(`[XIAOYI_GUI_TOOL] ✅ WebSocket manager obtained`);
68
52
  // Build InvokeJarvisGUIAgentRequest command
69
- logger.log(`[XIAOYI_GUI_TOOL] 📦 Building InvokeJarvisGUIAgentRequest command...`);
70
53
  const command = {
71
54
  header: {
72
55
  namespace: "ClawAgent",
@@ -78,32 +61,23 @@ export const xiaoyiGuiTool = {
78
61
  interactionId: taskId, // taskId corresponds to interactionId
79
62
  },
80
63
  };
81
- logger.log(`[XIAOYI_GUI_TOOL] 📋 Command details:`, JSON.stringify(command, null, 2));
82
64
  // Send command and wait for response (5 minute timeout)
83
- logger.log(`[XIAOYI_GUI_TOOL] ⏳ Setting up promise to wait for GUI agent response...`);
84
- logger.log(`[XIAOYI_GUI_TOOL] - Timeout: 300 seconds (5 minutes)`);
85
65
  return new Promise((resolve, reject) => {
86
66
  const timeout = setTimeout(() => {
87
- logger.error(`[XIAOYI_GUI_TOOL] ⏰ Timeout: No response received within 300 seconds (5 minutes)`);
88
67
  wsManager.off("gui-agent-response", handler);
89
68
  reject(new Error("XiaoYi GUI Agent 操作超时(5分钟)"));
90
69
  }, 180000); // 5 minutes timeout
91
70
  // Listen for GUI agent response events
92
71
  const handler = (event) => {
93
- logger.log(`[XIAOYI_GUI_TOOL] 📨 Received event:`, JSON.stringify(event));
94
72
  // Check if this is the InvokeJarvisGUIAgentResponse we're waiting for
95
73
  if (event.header?.namespace === "ClawAgent" &&
96
74
  event.header?.name === "InvokeJarvisGUIAgentResponse") {
97
- logger.log(`[XIAOYI_GUI_TOOL] 🎯 InvokeJarvisGUIAgentResponse event received`);
98
- logger.log(`[XIAOYI_GUI_TOOL] - isFinal: ${event.payload?.isFinal}`);
99
75
  // According to the spec, we only get one response (isFinal: true)
100
76
  if (event.payload?.isFinal === true) {
101
77
  clearTimeout(timeout);
102
78
  wsManager.off("gui-agent-response", handler);
103
79
  const streamContent = event.payload?.streamInfo?.streamContent;
104
80
  if (streamContent) {
105
- logger.log(`[XIAOYI_GUI_TOOL] ✅ GUI Agent operation completed successfully`);
106
- logger.log(`[XIAOYI_GUI_TOOL] - streamContent: ${streamContent}`);
107
81
  resolve({
108
82
  content: [
109
83
  {
@@ -114,23 +88,18 @@ export const xiaoyiGuiTool = {
114
88
  });
115
89
  }
116
90
  else {
117
- logger.error(`[XIAOYI_GUI_TOOL] ❌ Response missing streamContent`);
118
- logger.error(`[XIAOYI_GUI_TOOL] - payload:`, JSON.stringify(event.payload));
119
91
  reject(new Error("XiaoYi GUI Agent 响应格式错误:缺少 streamContent"));
120
92
  }
121
93
  }
122
94
  else if (event.payload?.isFinal === false) {
123
95
  // According to spec, we shouldn't get intermediate responses, but log if we do
124
- logger.log(`[XIAOYI_GUI_TOOL] 📝 Intermediate response received (isFinal: false), waiting for final...`);
125
96
  }
126
97
  }
127
98
  };
128
99
  // Register event handler
129
100
  // Note: The WebSocket manager needs to emit 'gui-agent-response' when receiving this type of response
130
- logger.log(`[XIAOYI_GUI_TOOL] 📡 Registering gui-agent-response handler on WebSocket manager`);
131
101
  wsManager.on("gui-agent-response", handler);
132
102
  // Send the command
133
- logger.log(`[XIAOYI_GUI_TOOL] 📤 Sending InvokeJarvisGUIAgentRequest command...`);
134
103
  sendCommand({
135
104
  config,
136
105
  sessionId,
@@ -138,10 +107,7 @@ export const xiaoyiGuiTool = {
138
107
  messageId,
139
108
  command,
140
109
  }).then(() => {
141
- logger.log(`[XIAOYI_GUI_TOOL] ✅ Command sent successfully, waiting for response...`);
142
- logger.log(`[XIAOYI_GUI_TOOL] - This may take up to 5 minutes depending on the task complexity`);
143
110
  }).catch((error) => {
144
- logger.error(`[XIAOYI_GUI_TOOL] ❌ Failed to send command:`, error);
145
111
  clearTimeout(timeout);
146
112
  wsManager.off("gui-agent-response", handler);
147
113
  reject(error);
@@ -92,13 +92,11 @@ export class XYWebSocketManager extends EventEmitter {
92
92
  * Send a message to the server.
93
93
  */
94
94
  async sendMessage(sessionId, message) {
95
- console.log(`[WEBSOCKET-SEND] <<<<<<< Preparing to send message for session: ${sessionId} <<<<<<<`);
96
95
  if (!this.ws || !this.state.ready || this.ws.readyState !== WebSocket.OPEN) {
97
96
  throw new Error("WebSocket not ready");
98
97
  }
99
98
  const messageStr = JSON.stringify(message);
100
99
  this.ws.send(messageStr);
101
- console.log(`[WS-SEND] Message sent successfully, size: ${messageStr.length} bytes`);
102
100
  }
103
101
  /**
104
102
  * Check if server is ready.
@@ -325,24 +323,40 @@ export class XYWebSocketManager extends EventEmitter {
325
323
  const messageStr = data.toString();
326
324
  console.log(`[WS-RECV] Raw message frame, size: ${messageStr.length} bytes`);
327
325
  const parsed = JSON.parse(messageStr);
328
- console.log("[WS-RECV] Parsed message:", JSON.stringify(parsed, null, 2));
326
+ // 提取并打印消息内容(只显示 text,data 只打印提示)
327
+ const parts = parsed.params?.message?.parts;
328
+ if (parts && Array.isArray(parts) && parts.length > 0) {
329
+ const textParts = parts.filter((p) => p?.kind === "text");
330
+ const dataParts = parts.filter((p) => p?.kind === "data");
331
+ // 打印 text 内容
332
+ if (textParts.length > 0) {
333
+ const textContents = textParts
334
+ .map((p) => p?.text || "")
335
+ .filter((text) => text.length > 0)
336
+ .join(" ");
337
+ if (textContents.length > 0) {
338
+ console.log("[WS-RECV] Text:", textContents);
339
+ }
340
+ }
341
+ // 打印 data 提示
342
+ if (dataParts.length > 0) {
343
+ console.log("[WS-RECV] Data: received data message(s)");
344
+ }
345
+ }
329
346
  // Check if message is in direct A2A JSON-RPC format (server push)
330
347
  if (parsed.jsonrpc === "2.0") {
331
348
  const a2aRequest = parsed;
332
- console.log(`[XY] Message type: Direct A2A JSON-RPC, method: ${a2aRequest.method}`);
333
349
  // Extract sessionId from params
334
350
  const sessionId = a2aRequest.params?.sessionId;
335
351
  if (!sessionId) {
336
352
  console.error("[XY] Message missing sessionId");
337
353
  return;
338
354
  }
339
- console.log(`[XY] Session ID: ${sessionId}`);
340
355
  // Check if message contains only data parts (tool results)
341
356
  const dataParts = a2aRequest.params?.message?.parts?.filter((p) => p.kind === "data");
342
357
  const hasOnlyDataParts = dataParts && dataParts.length > 0 &&
343
358
  dataParts.length === a2aRequest.params?.message?.parts?.length;
344
359
  if (hasOnlyDataParts) {
345
- console.log("[XY] Message contains only data parts, processing as tool result");
346
360
  for (const dataPart of dataParts) {
347
361
  const events = dataPart.data?.events;
348
362
  if (!Array.isArray(events)) {
@@ -357,11 +371,11 @@ export class XYWebSocketManager extends EventEmitter {
357
371
  outputs: item.payload.outputs || {},
358
372
  status: "success",
359
373
  };
360
- console.log("[XY] Emitting data-event:", dataEvent);
374
+ console.log(`[XY] Emitting data-event, intentName: ${item.payload.intentName}, size: ${JSON.stringify(dataEvent).length} bytes`);
361
375
  this.emit("data-event", dataEvent);
362
376
  }
363
377
  else if (item.header?.namespace === "ClawAgent" && item.header?.name === "InvokeJarvisGUIAgentResponse") {
364
- console.log("[XY] Emitting gui-agent-response:", item);
378
+ console.log(`[XY] Emitting gui-agent-response, size: ${JSON.stringify(item).length} bytes`);
365
379
  this.emit("gui-agent-response", item);
366
380
  }
367
381
  else if (item.header?.namespace === "Common" && item.header?.name === "Trigger") {
@@ -412,11 +426,11 @@ export class XYWebSocketManager extends EventEmitter {
412
426
  outputs: item.payload.outputs || {},
413
427
  status: "success",
414
428
  };
415
- console.log("[XY] Emitting data-event:", dataEvent);
429
+ console.log(`[XY] Emitting data-event, intentName: ${item.payload.intentName}, size: ${JSON.stringify(dataEvent).length} bytes`);
416
430
  this.emit("data-event", dataEvent);
417
431
  }
418
432
  else if (item.header?.namespace === "ClawAgent" && item.header?.name === "InvokeJarvisGUIAgentResponse") {
419
- console.log("[XY] Emitting gui-agent-response:", item);
433
+ console.log(`[XY] Emitting gui-agent-response, size: ${JSON.stringify(item).length} bytes`);
420
434
  this.emit("gui-agent-response", item);
421
435
  }
422
436
  else if (item.header?.namespace === "Common" && item.header?.name === "Trigger") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.50-beta",
3
+ "version": "0.0.52-beta",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",