@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.
- package/dist/index.js +42 -0
- package/dist/src/bot.js +3 -16
- package/dist/src/client.js +0 -3
- package/dist/src/cspl/call-api.d.ts +3 -0
- package/dist/src/cspl/call-api.js +79 -0
- package/dist/src/cspl/config.d.ts +19 -0
- package/dist/src/cspl/config.js +50 -0
- package/dist/src/cspl/constants.d.ts +43 -0
- package/dist/src/cspl/constants.js +22 -0
- package/dist/src/cspl/utils.d.ts +10 -0
- package/dist/src/cspl/utils.js +57 -0
- package/dist/src/formatter.js +3 -23
- package/dist/src/heartbeat.js +0 -4
- package/dist/src/reply-dispatcher.js +32 -0
- package/dist/src/steer-injector.d.ts +16 -0
- package/dist/src/steer-injector.js +74 -0
- package/dist/src/tools/calendar-tool.js +2 -37
- package/dist/src/tools/call-phone-tool.js +1 -42
- package/dist/src/tools/create-alarm-tool.js +3 -74
- package/dist/src/tools/delete-alarm-tool.js +3 -45
- package/dist/src/tools/image-reading-tool.js +0 -47
- package/dist/src/tools/location-tool.js +1 -32
- package/dist/src/tools/modify-alarm-tool.js +3 -77
- package/dist/src/tools/modify-note-tool.js +1 -34
- package/dist/src/tools/note-tool.js +2 -4
- package/dist/src/tools/search-alarm-tool.js +3 -61
- package/dist/src/tools/search-calendar-tool.js +2 -39
- package/dist/src/tools/search-contact-tool.js +0 -30
- package/dist/src/tools/search-file-tool.js +0 -33
- package/dist/src/tools/search-message-tool.js +0 -33
- package/dist/src/tools/search-note-tool.js +1 -26
- package/dist/src/tools/search-photo-gallery-tool.js +2 -31
- package/dist/src/tools/send-file-to-user-tool.js +0 -39
- package/dist/src/tools/send-message-tool.js +1 -39
- package/dist/src/tools/session-manager.js +0 -45
- package/dist/src/tools/upload-file-tool.js +0 -49
- package/dist/src/tools/upload-photo-tool.js +0 -42
- package/dist/src/tools/view-push-result-tool.js +0 -11
- package/dist/src/tools/xiaoyi-collection-tool.js +4 -82
- package/dist/src/tools/xiaoyi-gui-tool.js +0 -34
- package/dist/src/websocket.js +24 -10
- 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);
|
package/dist/src/websocket.js
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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") {
|