@ynhcj/xiaoyi-channel 0.0.150-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 (75) 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/location-tool.js +1 -1
  41. package/dist/src/tools/modify-alarm-tool.js +1 -1
  42. package/dist/src/tools/modify-note-tool.js +1 -1
  43. package/dist/src/tools/note-tool.js +1 -1
  44. package/dist/src/tools/query-app-message-tool.js +1 -1
  45. package/dist/src/tools/query-memory-data-tool.js +1 -1
  46. package/dist/src/tools/query-todo-task-tool.js +1 -1
  47. package/dist/src/tools/save-file-to-phone-tool.js +1 -1
  48. package/dist/src/tools/save-media-to-gallery-tool.js +1 -1
  49. package/dist/src/tools/search-alarm-tool.js +1 -1
  50. package/dist/src/tools/search-calendar-tool.js +1 -1
  51. package/dist/src/tools/search-contact-tool.js +1 -1
  52. package/dist/src/tools/search-email-tool.js +1 -1
  53. package/dist/src/tools/search-file-tool.js +11 -8
  54. package/dist/src/tools/search-message-tool.js +1 -1
  55. package/dist/src/tools/search-note-tool.js +1 -1
  56. package/dist/src/tools/search-photo-gallery-tool.js +1 -1
  57. package/dist/src/tools/send-email-tool.js +1 -1
  58. package/dist/src/tools/send-file-to-user-tool.js +2 -2
  59. package/dist/src/tools/send-message-tool.js +1 -1
  60. package/dist/src/tools/session-manager.js +5 -0
  61. package/dist/src/tools/upload-file-tool.js +15 -5
  62. package/dist/src/tools/upload-photo-tool.js +1 -1
  63. package/dist/src/tools/xiaoyi-add-collection-tool.js +1 -1
  64. package/dist/src/tools/xiaoyi-collection-tool.js +1 -1
  65. package/dist/src/tools/xiaoyi-delete-collection-tool.js +1 -1
  66. package/dist/src/tools/xiaoyi-gui-tool.js +1 -1
  67. package/dist/src/trigger-handler.js +4 -7
  68. package/dist/src/utils/config-manager.js +3 -6
  69. package/dist/src/utils/logger.d.ts +8 -0
  70. package/dist/src/utils/logger.js +69 -34
  71. package/dist/src/utils/pushdata-manager.js +1 -5
  72. package/dist/src/utils/pushid-manager.js +1 -2
  73. package/dist/src/utils/runtime-manager.js +1 -4
  74. package/dist/src/websocket.js +37 -25
  75. package/package.json +1 -1
@@ -1,98 +1,94 @@
1
1
  import { getXYWebSocketManager } from "../client.js";
2
2
  import { sendCommand } from "../formatter.js";
3
- import { getCurrentSessionContext } from "./session-manager.js";
4
3
  /**
5
4
  * XY find PC devices tool - finds all PC devices associated with the user.
6
5
  * Returns device IDs for use in subsequent file search operations.
7
6
  */
8
- export const findPcDevicesTool = {
9
- name: "find_pc_devices",
10
- label: "Find PC Devices",
11
- description: `查找用户所有PC/电脑设备,获取设备ID列表。当用户说"帮我找一下PC/电脑上的xxx文件"、"帮我搜索电脑上的xxx"等涉及PC设备的请求时,先调用此工具获取设备ID,再进行后续操作。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,请严格遵守。`,
12
- parameters: {
13
- type: "object",
14
- properties: {},
15
- required: [],
16
- },
17
- async execute(toolCallId, params) {
18
- // Get session context
19
- const sessionContext = getCurrentSessionContext();
20
- if (!sessionContext) {
21
- throw new Error("No active XY session found. Find PC devices tool can only be used during an active conversation.");
22
- }
23
- const { config, sessionId, taskId, messageId } = sessionContext;
24
- // Get WebSocket manager
25
- const wsManager = getXYWebSocketManager(config);
26
- // Build GetAllDevice command
27
- const command = {
28
- header: {
29
- namespace: "Common",
30
- name: "Action",
31
- },
32
- payload: {
33
- cardParam: {},
34
- executeParam: {
35
- achieveType: "INTENT",
36
- actionResponse: true,
37
- bundleName: "com.huawei.hmos.aidispatchservice",
38
- dimension: "",
39
- executeMode: "background",
40
- intentName: "GetAllDevice",
41
- intentParam: {},
42
- needUnlock: true,
43
- permissionId: [],
44
- timeOut: 5,
7
+ export function createFindPcDevicesTool(ctx) {
8
+ const { config, sessionId, taskId, messageId } = ctx;
9
+ return {
10
+ name: "find_pc_devices",
11
+ label: "Find PC Devices",
12
+ description: `查找用户所有PC/电脑设备,获取设备ID列表。当用户说"帮我找一下PC/电脑上的xxx文件"、"帮我搜索电脑上的xxx"等涉及PC设备的请求时,先调用此工具获取设备ID,再进行后续操作。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,请严格遵守。`,
13
+ parameters: {
14
+ type: "object",
15
+ properties: {},
16
+ required: [],
17
+ },
18
+ async execute(toolCallId, params) {
19
+ // Get WebSocket manager
20
+ const wsManager = getXYWebSocketManager(config);
21
+ // Build GetAllDevice command
22
+ const command = {
23
+ header: {
24
+ namespace: "Common",
25
+ name: "Action",
45
26
  },
46
- needUploadResult: true,
47
- pageControlRelated: false,
48
- responses: [{
49
- displayText: "",
50
- resultCode: "",
51
- ttsText: "",
52
- }],
53
- },
54
- };
55
- // Send command and wait for response (60 second timeout)
56
- return new Promise((resolve, reject) => {
57
- const timeout = setTimeout(() => {
58
- wsManager.off("data-event", handler);
59
- reject(new Error("查找PC设备超时(60秒)"));
60
- }, 60000);
61
- // Listen for data events from WebSocket
62
- const handler = (event) => {
63
- if (event.intentName === "GetAllDevice") {
64
- clearTimeout(timeout);
27
+ payload: {
28
+ cardParam: {},
29
+ executeParam: {
30
+ achieveType: "INTENT",
31
+ actionResponse: true,
32
+ bundleName: "com.huawei.hmos.aidispatchservice",
33
+ dimension: "",
34
+ executeMode: "background",
35
+ intentName: "GetAllDevice",
36
+ intentParam: {},
37
+ needUnlock: true,
38
+ permissionId: [],
39
+ timeOut: 5,
40
+ },
41
+ needUploadResult: true,
42
+ pageControlRelated: false,
43
+ responses: [{
44
+ displayText: "",
45
+ resultCode: "",
46
+ ttsText: "",
47
+ }],
48
+ },
49
+ };
50
+ // Send command and wait for response (60 second timeout)
51
+ return new Promise((resolve, reject) => {
52
+ const timeout = setTimeout(() => {
65
53
  wsManager.off("data-event", handler);
66
- if (event.status === "success" && event.outputs) {
67
- resolve({
68
- content: [
69
- {
70
- type: "text",
71
- text: JSON.stringify(event.outputs),
72
- }
73
- ]
74
- });
75
- }
76
- else {
77
- reject(new Error(`查找PC设备失败: ${event.status}`));
54
+ reject(new Error("查找PC设备超时(60秒)"));
55
+ }, 60000);
56
+ // Listen for data events from WebSocket
57
+ const handler = (event) => {
58
+ if (event.intentName === "GetAllDevice") {
59
+ clearTimeout(timeout);
60
+ wsManager.off("data-event", handler);
61
+ if (event.status === "success" && event.outputs) {
62
+ resolve({
63
+ content: [
64
+ {
65
+ type: "text",
66
+ text: JSON.stringify(event.outputs),
67
+ }
68
+ ]
69
+ });
70
+ }
71
+ else {
72
+ reject(new Error(`查找PC设备失败: ${event.status}`));
73
+ }
78
74
  }
79
- }
80
- };
81
- // Register event handler
82
- wsManager.on("data-event", handler);
83
- // Send the command
84
- sendCommand({
85
- config,
86
- sessionId,
87
- taskId,
88
- messageId,
89
- command,
90
- }).then(() => {
91
- }).catch((error) => {
92
- clearTimeout(timeout);
93
- wsManager.off("data-event", handler);
94
- reject(error);
75
+ };
76
+ // Register event handler
77
+ wsManager.on("data-event", handler);
78
+ // Send the command
79
+ sendCommand({
80
+ config,
81
+ sessionId,
82
+ taskId,
83
+ messageId,
84
+ command,
85
+ }).then(() => {
86
+ }).catch((error) => {
87
+ clearTimeout(timeout);
88
+ wsManager.off("data-event", handler);
89
+ reject(error);
90
+ });
95
91
  });
96
- });
97
- },
98
- };
92
+ },
93
+ };
94
+ }
@@ -2,13 +2,14 @@ import { createSchemaTool } from "./schema-tool-factory.js";
2
2
  import { createSearchFileTool } from "./search-file-tool.js";
3
3
  import { createUploadFileTool } from "./upload-file-tool.js";
4
4
  import { createSaveFileToPhoneTool } from "./save-file-to-phone-tool.js";
5
+ import { createFindPcDevicesTool } from "./find-pc-devices-tool.js";
5
6
  export function createGetDeviceFileToolSchemaTool(ctx) {
6
7
  const searchFileTool = createSearchFileTool(ctx);
7
8
  const saveFileToPhoneTool = createSaveFileToPhoneTool(ctx);
8
9
  return createSchemaTool({
9
10
  name: "get_device_file_tool_schema",
10
11
  label: "Get Device File Tool Schema",
11
- description: "获取可在用户设备上搜索文件系统的文件、将用户设备本地文件上传到公网并获取链接、保存文件到文件管理器的相关端工具列表。",
12
- tools: [searchFileTool, createUploadFileTool(ctx), saveFileToPhoneTool],
12
+ description: "获取可在用户设备上搜索文件系统的文件、将用户设备本地文件上传到公网并获取链接、保存文件到文件管理器、查找PC设备的相关端工具列表。",
13
+ tools: [searchFileTool, createUploadFileTool(ctx), saveFileToPhoneTool, createFindPcDevicesTool(ctx)],
13
14
  });
14
15
  }
@@ -55,7 +55,7 @@ export function createLocationTool(ctx) {
55
55
  return new Promise((resolve, reject) => {
56
56
  const timeout = setTimeout(() => {
57
57
  wsManager.off("data-event", handler);
58
- logger.error("超时: 获取位置超时(60秒)", { sessionId, toolCallId });
58
+ logger.error("超时: 获取位置超时(60秒)", { toolCallId });
59
59
  reject(new Error("获取位置超时(60秒)"));
60
60
  }, 60000);
61
61
  // Listen for data events from WebSocket
@@ -236,7 +236,7 @@ export function createModifyAlarmTool(ctx) {
236
236
  return new Promise((resolve, reject) => {
237
237
  const timeout = setTimeout(() => {
238
238
  wsManager.off("data-event", handler);
239
- logger.error("超时: 修改闹钟超时(60秒)", { sessionId, toolCallId });
239
+ logger.error("超时: 修改闹钟超时(60秒)", { toolCallId });
240
240
  reject(new Error("修改闹钟超时(60秒)"));
241
241
  }, 60000);
242
242
  // Listen for data events from WebSocket
@@ -77,7 +77,7 @@ export function createModifyNoteTool(ctx) {
77
77
  return new Promise((resolve, reject) => {
78
78
  const timeout = setTimeout(() => {
79
79
  wsManager.off("data-event", handler);
80
- logger.error("超时: 修改备忘录超时(60秒)", { sessionId, toolCallId });
80
+ logger.error("超时: 修改备忘录超时(60秒)", { toolCallId });
81
81
  reject(new Error("修改备忘录超时(60秒)"));
82
82
  }, 60000);
83
83
  // Listen for data events from WebSocket
@@ -94,7 +94,7 @@ export function createNoteTool(ctx) {
94
94
  return new Promise((resolve, reject) => {
95
95
  const timeout = setTimeout(() => {
96
96
  wsManager.off("data-event", handler);
97
- logger.error("超时: 创建备忘录超时(60秒)", { sessionId, toolCallId });
97
+ logger.error("超时: 创建备忘录超时(60秒)", { toolCallId });
98
98
  reject(new Error("创建备忘录超时(60秒)"));
99
99
  }, 60000);
100
100
  // Listen for data events from WebSocket
@@ -96,7 +96,7 @@ c. 调用工具前需认真检查调用参数是否满足工具要求
96
96
  return new Promise((resolve, reject) => {
97
97
  const timeout = setTimeout(() => {
98
98
  wsManager.off("data-event", handler);
99
- logger.error("超时: 查询通知消息超时(60秒)", { sessionId, toolCallId: _toolCallId });
99
+ logger.error("超时: 查询通知消息超时(60秒)", { toolCallId: _toolCallId });
100
100
  reject(new Error("查询通知消息超时(60秒)"));
101
101
  }, 60000);
102
102
  const handler = (event) => {
@@ -112,7 +112,7 @@ c. 调用工具前需认真检查调用参数是否满足工具要求
112
112
  return new Promise((resolve, reject) => {
113
113
  const timeout = setTimeout(() => {
114
114
  wsManager.off("data-event", handler);
115
- logger.error("超时: 查询记忆数据超时(60秒)", { sessionId, toolCallId: _toolCallId });
115
+ logger.error("超时: 查询记忆数据超时(60秒)", { toolCallId: _toolCallId });
116
116
  reject(new Error("查询记忆数据超时(60秒)"));
117
117
  }, 60000);
118
118
  const handler = (event) => {
@@ -91,7 +91,7 @@ d. 当只传入 startTime 时,返回该时间点之后的所有任务;当只
91
91
  return new Promise((resolve, reject) => {
92
92
  const timeout = setTimeout(() => {
93
93
  wsManager.off("data-event", handler);
94
- logger.error("超时: 查询待办任务超时(60秒)", { sessionId, toolCallId: _toolCallId });
94
+ logger.error("超时: 查询待办任务超时(60秒)", { toolCallId: _toolCallId });
95
95
  reject(new Error("查询待办任务超时(60秒)"));
96
96
  }, 60000);
97
97
  const handler = (event) => {
@@ -119,7 +119,7 @@ export function createSaveFileToPhoneTool(ctx) {
119
119
  return new Promise((resolve, reject) => {
120
120
  const timeout = setTimeout(() => {
121
121
  wsManager.off("data-event", handler);
122
- logger.error("超时: 保存文件到手机超时(60秒)", { sessionId, toolCallId });
122
+ logger.error("超时: 保存文件到手机超时(60秒)", { toolCallId });
123
123
  reject(new Error("保存文件到手机超时(60秒)"));
124
124
  }, 60000);
125
125
  // Listen for data events from WebSocket
@@ -127,7 +127,7 @@ export function createSaveMediaToGalleryTool(ctx) {
127
127
  return new Promise((resolve, reject) => {
128
128
  const timeout = setTimeout(() => {
129
129
  wsManager.off("data-event", handler);
130
- logger.error("超时: 保存媒体到图库超时(60秒)", { sessionId, toolCallId });
130
+ logger.error("超时: 保存媒体到图库超时(60秒)", { toolCallId });
131
131
  reject(new Error("保存媒体到图库超时(60秒)"));
132
132
  }, 60000);
133
133
  // Listen for data events from WebSocket
@@ -168,7 +168,7 @@ b. 使用该工具之前需获取当前真实时间
168
168
  return new Promise((resolve, reject) => {
169
169
  const timeout = setTimeout(() => {
170
170
  wsManager.off("data-event", handler);
171
- logger.error("超时: 检索闹钟超时(60秒)", { sessionId, toolCallId });
171
+ logger.error("超时: 检索闹钟超时(60秒)", { toolCallId });
172
172
  reject(new Error("检索闹钟超时(60秒)"));
173
173
  }, 60000);
174
174
  // Listen for data events from WebSocket
@@ -139,7 +139,7 @@ d. 如果查询结果返回-303,代表查询结果为空
139
139
  return new Promise((resolve, reject) => {
140
140
  const timeout = setTimeout(() => {
141
141
  wsManager.off("data-event", handler);
142
- logger.error("超时: 检索日程超时(60秒)", { sessionId, toolCallId });
142
+ logger.error("超时: 检索日程超时(60秒)", { toolCallId });
143
143
  reject(new Error("检索日程超时(60秒)"));
144
144
  }, 60000);
145
145
  // Listen for data events from WebSocket
@@ -67,7 +67,7 @@ export function createSearchContactTool(ctx) {
67
67
  return new Promise((resolve, reject) => {
68
68
  const timeout = setTimeout(() => {
69
69
  wsManager.off("data-event", handler);
70
- logger.error("超时: 搜索联系人超时(60秒)", { sessionId, toolCallId });
70
+ logger.error("超时: 搜索联系人超时(60秒)", { toolCallId });
71
71
  reject(new Error("搜索联系人超时(60秒)"));
72
72
  }, 60000);
73
73
  // Listen for data events from WebSocket
@@ -91,7 +91,7 @@ b. 使用该工具之前需获取当前真实时间
91
91
  return new Promise((resolve, reject) => {
92
92
  const timeout = setTimeout(() => {
93
93
  wsManager.off("data-event", handler);
94
- logger.error("超时: 检索邮件超时(60秒)", { sessionId, toolCallId: _toolCallId });
94
+ logger.error("超时: 检索邮件超时(60秒)", { toolCallId: _toolCallId });
95
95
  reject(new Error("检索邮件超时(60秒)"));
96
96
  }, 60000);
97
97
  // Listen for data events from WebSocket
@@ -11,15 +11,13 @@ export function createSearchFileTool(ctx) {
11
11
  return {
12
12
  name: "search_file",
13
13
  label: "Search File",
14
- description: `搜索用户设备文件系统的文件。
14
+ description: `搜索手机或PC/电脑文件系统的文件。
15
15
 
16
- 【重要】使用约束:此工具仅在用户显著说明要从手机/PC等用户设备搜索时才执行,例如:
17
- - "从我手机/鸿蒙PC里面搜索xxxx"
18
- - "从手机文件系统找一下xxxx"
19
- - "在手机上查找文件xxxx"
20
- - "搜索手机里的文件"
16
+ 【重要】使用场景与调用流程:
17
+ 1. 搜索手机文件:当用户明确说明要从手机搜索时(如"从手机里面搜索xxxx"、"在手机上查找文件xxxx"),直接调用此工具,无需传入 udid。
18
+ 2. 搜索PC/电脑文件:当用户要求搜索PC/电脑上的文件时(如"帮我找一下PC上的xxx文件"、"搜索电脑上的xxx"),必须先调用 find_pc_devices 工具获取设备ID(udid),然后将 udid 传入此工具进行搜索。
21
19
 
22
- 如果用户没有明确说明从手机或者PC搜索(如仅说"搜索文件"、"找一下xxxx"),应默认从当前runtime运行环境的本地的文件系统查询,不要调用此工具。
20
+ 如果用户没有明确说明从手机或PC搜索(如仅说"搜索文件"、"找一下xxxx"),应默认从当前runtime运行环境的本地文件系统查询,不要调用此工具。
23
21
 
24
22
  功能说明:根据关键词搜索文件名称或内容,返回匹配的文件列表(包括文件名、路径、大小、修改时间等信息)。
25
23
 
@@ -31,6 +29,10 @@ export function createSearchFileTool(ctx) {
31
29
  type: "string",
32
30
  description: "搜索关键词,用于匹配文件名称、后缀名或文件内容",
33
31
  },
32
+ udid: {
33
+ type: "string",
34
+ description: "PC/电脑设备ID。当搜索PC/电脑上的文件时,需要先通过 find_pc_devices 工具获取设备ID后传入。搜索手机文件时不需要传入此参数。",
35
+ },
34
36
  },
35
37
  required: ["query"],
36
38
  },
@@ -59,6 +61,7 @@ export function createSearchFileTool(ctx) {
59
61
  timeOut: 5,
60
62
  intentParam: {
61
63
  query: params.query.trim(),
64
+ ...(params.udid ? { udid: params.udid } : {}),
62
65
  },
63
66
  permissionId: [],
64
67
  achieveType: "INTENT",
@@ -79,7 +82,7 @@ export function createSearchFileTool(ctx) {
79
82
  return new Promise((resolve, reject) => {
80
83
  const timeout = setTimeout(() => {
81
84
  wsManager.off("data-event", handler);
82
- logger.error("超时: 搜索文件超时(60秒)", { sessionId, toolCallId });
85
+ logger.error("超时: 搜索文件超时(60秒)", { toolCallId });
83
86
  reject(new Error("搜索文件超时(60秒)"));
84
87
  }, 60000);
85
88
  // Listen for data events from WebSocket
@@ -68,7 +68,7 @@ export function createSearchMessageTool(ctx) {
68
68
  return new Promise((resolve, reject) => {
69
69
  const timeout = setTimeout(() => {
70
70
  wsManager.off("data-event", handler);
71
- logger.error("超时: 搜索短信超时(60秒)", { sessionId, toolCallId });
71
+ logger.error("超时: 搜索短信超时(60秒)", { toolCallId });
72
72
  reject(new Error("搜索短信超时(60秒)"));
73
73
  }, 60000);
74
74
  // Listen for data events from WebSocket
@@ -66,7 +66,7 @@ export function createSearchNoteTool(ctx) {
66
66
  return new Promise((resolve, reject) => {
67
67
  const timeout = setTimeout(() => {
68
68
  wsManager.off("data-event", handler);
69
- logger.error("超时: 搜索备忘录超时(60秒)", { sessionId, toolCallId });
69
+ logger.error("超时: 搜索备忘录超时(60秒)", { toolCallId });
70
70
  reject(new Error("搜索备忘录超时(60秒)"));
71
71
  }, 60000);
72
72
  // Listen for data events from WebSocket
@@ -128,7 +128,7 @@ async function searchPhotos(wsManager, config, sessionId, taskId, messageId, que
128
128
  return new Promise((resolve, reject) => {
129
129
  const timeout = setTimeout(() => {
130
130
  wsManager.off("data-event", handler);
131
- logger.error("超时: 搜索照片超时(60秒)", { sessionId });
131
+ logger.error("超时: 搜索照片超时(60秒)");
132
132
  reject(new Error("搜索照片超时(60秒)"));
133
133
  }, 60000);
134
134
  const handler = (event) => {
@@ -92,7 +92,7 @@ c. 调用工具前需认真检查调用参数是否满足工具要求
92
92
  return new Promise((resolve, reject) => {
93
93
  const timeout = setTimeout(() => {
94
94
  wsManager.off("data-event", handler);
95
- logger.error("超时: 发送邮件超时(60秒)", { sessionId, toolCallId: _toolCallId });
95
+ logger.error("超时: 发送邮件超时(60秒)", { toolCallId: _toolCallId });
96
96
  reject(new Error("发送邮件超时(60秒)"));
97
97
  }, 60000);
98
98
  const handler = (event) => {
@@ -240,10 +240,10 @@ b. 操作超时时间为2分钟(120秒),请勿重复调用此工具,如
240
240
  error: { code: 0 },
241
241
  }),
242
242
  };
243
- logger.log(`[SEND-FILE-TO-USER] 🚀 EXEC sending: sessionId=${sessionId} taskId=${currentTaskId} fileName=${fileName}`);
243
+ logger.log(`[SEND-FILE-TO-USER] EXEC sending, fileName=${fileName}`);
244
244
  // Send WebSocket message
245
245
  await wsManager.sendMessage(sessionId, agentResponse);
246
- logger.log(`send ${fileName} file to user success`);
246
+ logger.log(`[SEND-FILE-TO-USER] send ${fileName} file to user success`);
247
247
  sentFiles.push({ fileName, fileId });
248
248
  }
249
249
  return {
@@ -89,7 +89,7 @@ export function createSendMessageTool(ctx) {
89
89
  return new Promise((resolve, reject) => {
90
90
  const timeout = setTimeout(() => {
91
91
  wsManager.off("data-event", handler);
92
- logger.error("超时: 发送短信超时(60秒)", { sessionId, toolCallId });
92
+ logger.error("超时: 发送短信超时(60秒)", { toolCallId });
93
93
  reject(new Error("发送短信超时(60秒)"));
94
94
  }, 60000);
95
95
  // Listen for data events from WebSocket
@@ -27,6 +27,11 @@ const getLastRegisteredKey = () => _g.__xyLastRegisteredSessionKey;
27
27
  const setLastRegisteredKey = (key) => { _g.__xyLastRegisteredSessionKey = key; };
28
28
  // AsyncLocalStorage for thread-safe session context isolation
29
29
  export const asyncLocalStorage = new AsyncLocalStorage();
30
+ // Export AsyncLocalStorage to globalThis so logger.ts can access it
31
+ // without creating a circular dependency (session-manager imports logger)
32
+ if (!_g.__xyAsyncLocalStorage) {
33
+ _g.__xyAsyncLocalStorage = asyncLocalStorage;
34
+ }
30
35
  /**
31
36
  * Register a session context for tool access.
32
37
  * Should be called when starting to process a message.
@@ -19,14 +19,19 @@ export function createUploadFileTool(ctx) {
19
19
  return {
20
20
  name: "upload_file",
21
21
  label: "Upload File",
22
- description: `工具能力描述:将用户本地设备文件上传并获取可公网访问的 URL。
22
+ description: `工具能力描述:将手机或PC/电脑本地文件上传并获取可公网访问的 URL。
23
23
 
24
24
  前置工具调用:此工具使用前必须先通过call_device_tool调用 search_file 或者 query_collection 工具获取文件的 uri
25
25
 
26
+ 使用场景与调用流程:
27
+ 1. 上传手机文件:直接调用此工具,无需传入 udid。
28
+ 2. 上传PC/电脑文件:当用户要求上传PC/电脑上的文件时,需要先通过 find_pc_devices 工具获取设备ID(udid),然后将 udid 传入此工具。
29
+
26
30
  工具参数说明:
27
31
  a. 入参中的fileInfos数组,每个元素必须包含mediaUri字段(对应于search_file工具或者query_collection返回结果中的uri),必须与search_file或者query_collection结果中对应的uri完全保持一致,不要自行修改。
28
32
  b. fileInfos中的timeout字段是可选的,表示上传文件超时时间,单位是毫秒,默认是20000(20秒)。
29
- c. fileInfos 是文件在用户设备本地的信息数组(从 search_file 工具或者query_collection 工具响应中获取)。限制:每次最多支持传入 5 条文件信息。
33
+ c. fileInfos 是文件在本地的信息数组(从 search_file 工具或者query_collection 工具响应中获取)。限制:每次最多支持传入 5 条文件信息。
34
+ d. udid 是PC/电脑设备ID,仅在上传PC/电脑文件时需要传入(通过 find_pc_devices 工具获取)。
30
35
 
31
36
  注意事项:
32
37
  a. 操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。
@@ -39,6 +44,10 @@ export function createUploadFileTool(ctx) {
39
44
  // 具体的类型验证和转换在 execute 函数内部进行
40
45
  description: "文件信息数组,每个元素包含mediaUri(必需)和timeout(可选,默认20000)。必须先通过 search_file 工具获取。每次最多支持 5 条文件信息。",
41
46
  },
47
+ udid: {
48
+ type: "string",
49
+ description: "PC/电脑设备ID。当上传PC/电脑上的文件时,需要先通过 find_pc_devices 工具获取设备ID后传入。上传手机文件时不需要传入此参数。",
50
+ },
42
51
  },
43
52
  required: ["fileInfos"],
44
53
  },
@@ -97,7 +106,7 @@ export function createUploadFileTool(ctx) {
97
106
  const wsManager = getXYWebSocketManager(config);
98
107
  // Get public URLs for the files
99
108
  const currentTaskId = getCurrentTaskId(sessionId) ?? taskId;
100
- const fileUrls = await getFileUrls(wsManager, config, sessionId, currentTaskId, messageId, fileInfos);
109
+ const fileUrls = await getFileUrls(wsManager, config, sessionId, currentTaskId, messageId, fileInfos, params.udid);
101
110
  return {
102
111
  content: [
103
112
  {
@@ -117,7 +126,7 @@ export function createUploadFileTool(ctx) {
117
126
  * Get public URLs for files using fileInfos
118
127
  * Returns array of publicly accessible file URLs
119
128
  */
120
- async function getFileUrls(wsManager, config, sessionId, taskId, messageId, fileInfos) {
129
+ async function getFileUrls(wsManager, config, sessionId, taskId, messageId, fileInfos, udid) {
121
130
  const command = {
122
131
  header: {
123
132
  namespace: "Common",
@@ -135,6 +144,7 @@ async function getFileUrls(wsManager, config, sessionId, taskId, messageId, file
135
144
  timeOut: 5,
136
145
  intentParam: {
137
146
  fileInfos: fileInfos,
147
+ ...(udid ? { udid } : {}),
138
148
  },
139
149
  permissionId: [],
140
150
  achieveType: "INTENT",
@@ -154,7 +164,7 @@ async function getFileUrls(wsManager, config, sessionId, taskId, messageId, file
154
164
  return new Promise((resolve, reject) => {
155
165
  const timeout = setTimeout(() => {
156
166
  wsManager.off("data-event", handler);
157
- logger.error("超时: 获取文件URL超时(60秒)", { sessionId });
167
+ logger.error("超时: 获取文件URL超时(60秒)");
158
168
  reject(new Error("获取文件URL超时(60秒)"));
159
169
  }, 60000);
160
170
  const handler = (event) => {
@@ -137,7 +137,7 @@ async function getPhotoUrls(wsManager, config, sessionId, taskId, messageId, med
137
137
  return new Promise((resolve, reject) => {
138
138
  const timeout = setTimeout(() => {
139
139
  wsManager.off("data-event", handler);
140
- logger.error("超时: 获取照片URL超时(60秒)", { sessionId });
140
+ logger.error("超时: 获取照片URL超时(60秒)");
141
141
  reject(new Error("获取照片URL超时(60秒)"));
142
142
  }, 60000);
143
143
  const handler = (event) => {
@@ -145,7 +145,7 @@ export function createXiaoyiAddCollectionTool(ctx) {
145
145
  return new Promise((resolve, reject) => {
146
146
  const timeout = setTimeout(() => {
147
147
  wsManager.off("data-event", handler);
148
- logger.error("超时: 添加小艺收藏超时(60秒)", { sessionId, toolCallId });
148
+ logger.error("超时: 添加小艺收藏超时(60秒)", { toolCallId });
149
149
  reject(new Error("添加小艺收藏超时(60秒)"));
150
150
  }, 60000);
151
151
  // Listen for data events from WebSocket
@@ -100,7 +100,7 @@ export function createXiaoyiCollectionTool(ctx) {
100
100
  return new Promise((resolve, reject) => {
101
101
  const timeout = setTimeout(() => {
102
102
  wsManager.off("data-event", handler);
103
- logger.error("超时: 查询小艺收藏超时(60秒)", { sessionId, toolCallId });
103
+ logger.error("超时: 查询小艺收藏超时(60秒)", { toolCallId });
104
104
  reject(new Error("查询小艺收藏超时(60秒)"));
105
105
  }, 60000);
106
106
  // Listen for data events from WebSocket
@@ -116,7 +116,7 @@ export function createXiaoyiDeleteCollectionTool(ctx) {
116
116
  return new Promise((resolve, reject) => {
117
117
  const timeout = setTimeout(() => {
118
118
  wsManager.off("data-event", handler);
119
- logger.error("超时: 删除小艺收藏超时(60秒)", { sessionId, toolCallId });
119
+ logger.error("超时: 删除小艺收藏超时(60秒)", { toolCallId });
120
120
  reject(new Error("删除小艺收藏超时(60秒)"));
121
121
  }, 60000);
122
122
  // Listen for data events from WebSocket
@@ -64,7 +64,7 @@ export function createXiaoyiGuiTool(ctx) {
64
64
  return new Promise((resolve, reject) => {
65
65
  const timeout = setTimeout(() => {
66
66
  wsManager.off("gui-agent-response", handler);
67
- logger.error("超时: XiaoYi GUI Agent 操作超时(5分钟)", { sessionId, toolCallId });
67
+ logger.error("超时: XiaoYi GUI Agent 操作超时(5分钟)", { toolCallId });
68
68
  reject(new Error("XiaoYi GUI Agent 操作超时(5分钟)"));
69
69
  }, 180000); // 5 minutes timeout
70
70
  // Listen for GUI agent response events
@@ -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
  }