@ynhcj/xiaoyi-channel 0.0.26-beta → 0.0.26-next

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 (86) hide show
  1. package/dist/index.d.ts +0 -2
  2. package/dist/index.js +48 -2
  3. package/dist/src/bot.js +81 -28
  4. package/dist/src/channel.js +33 -7
  5. package/dist/src/client.js +11 -27
  6. package/dist/src/config.js +2 -2
  7. package/dist/src/cspl/call-api.d.ts +3 -0
  8. package/dist/src/cspl/call-api.js +107 -0
  9. package/dist/src/cspl/config.d.ts +19 -0
  10. package/dist/src/cspl/config.js +50 -0
  11. package/dist/src/cspl/constants.d.ts +43 -0
  12. package/dist/src/cspl/constants.js +22 -0
  13. package/dist/src/cspl/utils.d.ts +10 -0
  14. package/dist/src/cspl/utils.js +57 -0
  15. package/dist/src/file-upload.d.ts +5 -0
  16. package/dist/src/file-upload.js +92 -0
  17. package/dist/src/formatter.d.ts +14 -0
  18. package/dist/src/formatter.js +49 -25
  19. package/dist/src/heartbeat.js +0 -4
  20. package/dist/src/monitor.js +12 -0
  21. package/dist/src/onboarding.d.ts +3 -4
  22. package/dist/src/onboarding.js +2 -2
  23. package/dist/src/outbound.d.ts +2 -1
  24. package/dist/src/outbound.js +52 -6
  25. package/dist/src/parser.d.ts +7 -0
  26. package/dist/src/parser.js +22 -0
  27. package/dist/src/push.d.ts +8 -1
  28. package/dist/src/push.js +30 -22
  29. package/dist/src/reply-dispatcher.js +39 -5
  30. package/dist/src/steer-injector.d.ts +16 -0
  31. package/dist/src/steer-injector.js +74 -0
  32. package/dist/src/thread-bindings.d.ts +54 -0
  33. package/dist/src/thread-bindings.js +214 -0
  34. package/dist/src/tools/calendar-tool.js +7 -40
  35. package/dist/src/tools/call-phone-tool.d.ts +5 -0
  36. package/dist/src/tools/call-phone-tool.js +142 -0
  37. package/dist/src/tools/create-alarm-tool.d.ts +7 -0
  38. package/dist/src/tools/create-alarm-tool.js +349 -0
  39. package/dist/src/tools/delete-alarm-tool.d.ts +11 -0
  40. package/dist/src/tools/delete-alarm-tool.js +174 -0
  41. package/dist/src/tools/image-reading-tool.d.ts +5 -0
  42. package/dist/src/tools/image-reading-tool.js +328 -0
  43. package/dist/src/tools/location-tool.js +8 -42
  44. package/dist/src/tools/modify-alarm-tool.d.ts +9 -0
  45. package/dist/src/tools/modify-alarm-tool.js +365 -0
  46. package/dist/src/tools/modify-note-tool.js +5 -43
  47. package/dist/src/tools/note-tool.js +33 -24
  48. package/dist/src/tools/search-alarm-tool.d.ts +8 -0
  49. package/dist/src/tools/search-alarm-tool.js +285 -0
  50. package/dist/src/tools/search-calendar-tool.js +10 -84
  51. package/dist/src/tools/search-contact-tool.js +4 -57
  52. package/dist/src/tools/search-file-tool.d.ts +5 -0
  53. package/dist/src/tools/search-file-tool.js +128 -0
  54. package/dist/src/tools/search-message-tool.d.ts +5 -0
  55. package/dist/src/tools/search-message-tool.js +116 -0
  56. package/dist/src/tools/search-note-tool.js +6 -24
  57. package/dist/src/tools/search-photo-gallery-tool.js +40 -61
  58. package/dist/src/tools/send-file-to-user-tool.d.ts +5 -0
  59. package/dist/src/tools/send-file-to-user-tool.js +279 -0
  60. package/dist/src/tools/send-message-tool.d.ts +5 -0
  61. package/dist/src/tools/send-message-tool.js +138 -0
  62. package/dist/src/tools/session-manager.d.ts +15 -0
  63. package/dist/src/tools/session-manager.js +43 -31
  64. package/dist/src/tools/upload-file-tool.d.ts +13 -0
  65. package/dist/src/tools/upload-file-tool.js +216 -0
  66. package/dist/src/tools/upload-photo-tool.js +2 -44
  67. package/dist/src/tools/view-push-result-tool.d.ts +5 -0
  68. package/dist/src/tools/view-push-result-tool.js +107 -0
  69. package/dist/src/tools/xiaoyi-collection-tool.d.ts +5 -0
  70. package/dist/src/tools/xiaoyi-collection-tool.js +112 -0
  71. package/dist/src/tools/xiaoyi-gui-tool.js +2 -36
  72. package/dist/src/trigger-handler.d.ts +22 -0
  73. package/dist/src/trigger-handler.js +59 -0
  74. package/dist/src/types.d.ts +1 -8
  75. package/dist/src/types.js +4 -0
  76. package/dist/src/utils/pushdata-manager.d.ts +28 -0
  77. package/dist/src/utils/pushdata-manager.js +171 -0
  78. package/dist/src/utils/pushid-manager.d.ts +12 -0
  79. package/dist/src/utils/pushid-manager.js +105 -0
  80. package/dist/src/websocket.d.ts +25 -31
  81. package/dist/src/websocket.js +233 -271
  82. package/package.json +2 -2
  83. package/dist/src/tools/search-photo-tool.d.ts +0 -9
  84. package/dist/src/tools/search-photo-tool.js +0 -270
  85. package/dist/src/utils/session.d.ts +0 -34
  86. package/dist/src/utils/session.js +0 -50
@@ -0,0 +1,5 @@
1
+ /**
2
+ * XY Image Reading tool - performs image understanding using local or remote image URLs.
3
+ * Supports both local file paths and remote URLs.
4
+ */
5
+ export declare const imageReadingTool: any;
@@ -0,0 +1,328 @@
1
+ // Image Reading tool implementation
2
+ import { XYFileUploadService } from "../file-upload.js";
3
+ import { getCurrentSessionContext } from "./session-manager.js";
4
+ import fetch from "node-fetch";
5
+ import fs from "fs/promises";
6
+ import path from "path";
7
+ import { v4 as uuidv4 } from "uuid";
8
+ /**
9
+ * Check if value is a remote URL
10
+ */
11
+ function isRemoteUrl(value) {
12
+ try {
13
+ const url = new URL(value);
14
+ return url.protocol === "http:" || url.protocol === "https:";
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ /**
21
+ * Check if value is a local file path
22
+ */
23
+ async function isLocalFile(value) {
24
+ try {
25
+ const stats = await fs.stat(value);
26
+ return stats.isFile();
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ /**
33
+ * Download remote file to local temp directory
34
+ */
35
+ async function downloadRemoteFile(url) {
36
+ try {
37
+ const response = await fetch(url);
38
+ if (!response.ok) {
39
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
40
+ }
41
+ // Get filename from URL or use default
42
+ let filename = url.split("/").pop() || "downloaded_image";
43
+ filename = filename.split("?")[0];
44
+ // Ensure temp directory exists
45
+ const tempDir = "/tmp/xy_channel";
46
+ await fs.mkdir(tempDir, { recursive: true });
47
+ // Generate unique filename to avoid conflicts
48
+ const timestamp = Date.now();
49
+ const ext = path.extname(filename) || ".jpg";
50
+ const baseName = path.basename(filename, ext);
51
+ const uniqueFilename = `${baseName}_${timestamp}${ext}`;
52
+ const localPath = path.join(tempDir, uniqueFilename);
53
+ // Save file to local temp directory
54
+ const arrayBuffer = await response.arrayBuffer();
55
+ const buffer = Buffer.from(arrayBuffer);
56
+ await fs.writeFile(localPath, buffer);
57
+ return localPath;
58
+ }
59
+ catch (error) {
60
+ throw new Error(`Failed to download remote file: ${error instanceof Error ? error.message : String(error)}`);
61
+ }
62
+ }
63
+ /**
64
+ * Process image input: validate and convert local file to OBS URL, keep remote URL unchanged
65
+ */
66
+ async function processImageInput(imageInput, uploadService) {
67
+ // Check if it's a remote URL
68
+ if (isRemoteUrl(imageInput)) {
69
+ const localPath = await downloadRemoteFile(imageInput);
70
+ const imageUrl = await uploadService.uploadFileAndGetUrl(localPath, "TEMPORARY_MATERIAL_DOC");
71
+ if (!imageUrl) {
72
+ throw new Error("图片上传失败:无法获取图片访问地址");
73
+ }
74
+ return { imageUrl, localPath };
75
+ }
76
+ // Check if it's a local file
77
+ const isLocal = await isLocalFile(imageInput);
78
+ if (isLocal) {
79
+ const imageUrl = await uploadService.uploadFileAndGetUrl(imageInput, "TEMPORARY_MATERIAL_DOC");
80
+ if (!imageUrl) {
81
+ throw new Error("图片上传失败:无法获取图片访问地址");
82
+ }
83
+ return { imageUrl };
84
+ }
85
+ throw new Error(`Invalid image input: must be a remote URL or local file path, got: ${imageInput}`);
86
+ }
87
+ /**
88
+ * Call image understanding API with streaming response
89
+ */
90
+ async function callImageUnderstandingAPI(imageUrl, text, apiKey, uid) {
91
+ const apiUrl = "https://hag-drcn.op.dbankcloud.com/celia-claw/v1/sse-api/skill/execute";
92
+ const traceId = uuidv4();
93
+ const headers = {
94
+ "Content-Type": "application/json",
95
+ "Accept": "text/event-stream",
96
+ "x-hag-trace-id": traceId,
97
+ "x-api-key": apiKey,
98
+ "x-request-from": "openclaw",
99
+ "x-uid": uid,
100
+ "x-skill-id": "image_comprehension",
101
+ "x-prd-pkg-name": "com.huawei.hag",
102
+ };
103
+ const payload = {
104
+ version: "1.0",
105
+ session: {
106
+ isNew: false,
107
+ sessionId: "wangyu202410241921",
108
+ interactionId: 0,
109
+ },
110
+ endpoint: {
111
+ device: {
112
+ sid: "3df83a4a8124d7600f66206f96ea1e7e4e21c593adc4246bd20d450d8404cbf3",
113
+ deviceId: "3f35019f-ba4c-4ed5-80c0-6ddcef741200",
114
+ prdVer: "99.0.64.303",
115
+ phoneType: "WLZ-AL10",
116
+ sysVer: "HarmonyOS_2.0.0",
117
+ deviceType: 0,
118
+ timezone: "GMT+08:00",
119
+ },
120
+ locale: "zh-CN",
121
+ sysLocale: "zh",
122
+ countryCode: "CN",
123
+ },
124
+ utterance: { type: "text", original: text },
125
+ actions: [
126
+ {
127
+ actionSn: uuidv4(),
128
+ actionExecutorTask: {
129
+ pluginId: "aeac4e92c32949c1b7fc02de262615e6",
130
+ agentState: "OnShelf",
131
+ actionName: "imageUnderStandStream",
132
+ content: { imageUrl, text },
133
+ },
134
+ },
135
+ ],
136
+ };
137
+ try {
138
+ const response = await fetch(apiUrl, {
139
+ method: "POST",
140
+ headers,
141
+ body: JSON.stringify(payload),
142
+ // @ts-ignore - node-fetch supports this
143
+ timeout: 120000, // 2 minutes timeout
144
+ });
145
+ if (!response.ok) {
146
+ const errorText = await response.text();
147
+ throw new Error(`API request failed: ${response.status} ${response.statusText}`);
148
+ }
149
+ // Process SSE stream
150
+ let lastCaption = "";
151
+ let lineCount = 0;
152
+ let buffer = "";
153
+ // Read the response body as a stream
154
+ if (!response.body) {
155
+ throw new Error("Response body is null");
156
+ }
157
+ for await (const chunk of response.body) {
158
+ if (!chunk)
159
+ continue;
160
+ buffer += chunk.toString();
161
+ const lines = buffer.split("\n");
162
+ buffer = lines.pop() || "";
163
+ for (const line of lines) {
164
+ lineCount++;
165
+ const trimmedLine = line.replace(/\r$/, "");
166
+ if (!trimmedLine)
167
+ continue;
168
+ if (trimmedLine.startsWith("data:")) {
169
+ const dataContent = trimmedLine.substring(5).trim();
170
+ if (dataContent && dataContent !== "[DONE]") {
171
+ try {
172
+ const dataJson = JSON.parse(dataContent);
173
+ // Extract streamContent from abilityInfos
174
+ if (dataJson.abilityInfos && Array.isArray(dataJson.abilityInfos)) {
175
+ for (const info of dataJson.abilityInfos) {
176
+ if (info.actionExecutorResult?.reply?.streamInfo) {
177
+ const streamContent = info.actionExecutorResult.reply.streamInfo.streamContent;
178
+ if (streamContent) {
179
+ lastCaption = streamContent;
180
+ }
181
+ }
182
+ }
183
+ }
184
+ }
185
+ catch (parseError) {
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+ if (!lastCaption) {
192
+ throw new Error("No caption received from image understanding API");
193
+ }
194
+ return lastCaption;
195
+ }
196
+ catch (error) {
197
+ throw error;
198
+ }
199
+ }
200
+ /**
201
+ * XY Image Reading tool - performs image understanding using local or remote image URLs.
202
+ * Supports both local file paths and remote URLs.
203
+ */
204
+ export const imageReadingTool = {
205
+ name: "image_reading",
206
+ label: "Image Reading",
207
+ description: `
208
+ 工具使用场景:
209
+ 【必须调用此工具的情况】
210
+ 1. 用户消息中包含 mediaPath 字段且不为空(表示用户发送了图片)
211
+ 2. 用户希望理解图片内容,询问图片是什么,例如:
212
+ - "这是什么?"
213
+ - "图片里有什么?"
214
+ - "帮我看看这张图"
215
+ - "描述一下这张图片"
216
+ - "分析一下这张照片"
217
+ - "这个图片是什么意思"
218
+ - "识别一下图片内容"
219
+ - 或任何关于图片内容的理解、识别、分析类询问
220
+
221
+ 当同时满足以上两个条件时,必须优先调用此工具进行图像理解。
222
+
223
+ 工具能力描述:对图片进行理解和分析,返回图片的描述内容。
224
+
225
+ 工具参数说明:
226
+ a. localUrl:本地图片文件路径(可选,通常从用户消息的 mediaPath 字段获取)
227
+ b. remoteUrl:公网图片地址(可选)
228
+ c. prompt:对图片的提示问题,默认为"描述这张图片内容",可根据用户的具体问题自定义
229
+ d. localUrl 与 remoteUrl 任意一个不为空即可,优先使用 localUrl
230
+
231
+ 注意事项:
232
+ a. 支持常见图片格式(jpg, png, gif等)
233
+ b. 远程图片会先下载到本地再处理
234
+ c. 操作超时时间为2分钟(120秒)
235
+ d. 返回图像理解的文本描述内容`,
236
+ parameters: {
237
+ type: "object",
238
+ properties: {
239
+ localUrl: {
240
+ type: "string",
241
+ description: "本地图片文件路径",
242
+ },
243
+ remoteUrl: {
244
+ type: "string",
245
+ description: "公网图片地址(HTTP/HTTPS URL)",
246
+ },
247
+ prompt: {
248
+ type: "string",
249
+ description: "对图片的提示问题,默认为'描述这张图片内容'",
250
+ },
251
+ },
252
+ },
253
+ async execute(toolCallId, params) {
254
+ // Validate that at least one parameter is provided
255
+ if (!params.localUrl && !params.remoteUrl) {
256
+ throw new Error("At least one of localUrl or remoteUrl must be provided");
257
+ }
258
+ // Get prompt (default to "描述这张图片内容")
259
+ const prompt = params.prompt || "描述这张图片内容";
260
+ // Get session context
261
+ const sessionContext = getCurrentSessionContext();
262
+ if (!sessionContext) {
263
+ throw new Error("No active XY session found. Image reading tool can only be used during an active conversation.");
264
+ }
265
+ const { config } = sessionContext;
266
+ // Create upload service
267
+ const uploadService = new XYFileUploadService(config.fileUploadUrl, config.apiKey, config.uid);
268
+ let processedImage = null;
269
+ let downloadedFile = null;
270
+ try {
271
+ // Process image input (prefer localUrl over remoteUrl)
272
+ const imageInput = params.localUrl || params.remoteUrl;
273
+ processedImage = await processImageInput(imageInput, uploadService);
274
+ // Track downloaded file for cleanup
275
+ if (processedImage.localPath) {
276
+ downloadedFile = processedImage.localPath;
277
+ }
278
+ // Call image understanding API
279
+ const caption = await callImageUnderstandingAPI(processedImage.imageUrl, prompt, config.apiKey, config.uid);
280
+ // Clean up downloaded file if any
281
+ if (downloadedFile) {
282
+ try {
283
+ await fs.unlink(downloadedFile);
284
+ }
285
+ catch (error) {
286
+ }
287
+ }
288
+ return {
289
+ content: [
290
+ {
291
+ type: "text",
292
+ text: JSON.stringify({
293
+ caption,
294
+ prompt,
295
+ imageSource: params.localUrl ? "local" : "remote",
296
+ success: true,
297
+ }),
298
+ },
299
+ ],
300
+ };
301
+ }
302
+ catch (error) {
303
+ // Clean up downloaded file on error
304
+ if (downloadedFile) {
305
+ try {
306
+ await fs.unlink(downloadedFile);
307
+ }
308
+ catch (cleanupError) {
309
+ }
310
+ }
311
+ const errorMessage = error instanceof Error ? error.message : "图片分析失败";
312
+ // Return error result instead of throwing
313
+ return {
314
+ content: [
315
+ {
316
+ type: "text",
317
+ text: JSON.stringify({
318
+ error: errorMessage,
319
+ prompt,
320
+ imageSource: params.localUrl ? "local" : "remote",
321
+ success: false,
322
+ }),
323
+ },
324
+ ],
325
+ };
326
+ }
327
+ },
328
+ };
@@ -1,7 +1,6 @@
1
1
  import { getXYWebSocketManager } from "../client.js";
2
2
  import { sendCommand } from "../formatter.js";
3
- import { getLatestSessionContext } from "./session-manager.js";
4
- import { logger } from "../utils/logger.js";
3
+ import { getCurrentSessionContext } from "./session-manager.js";
5
4
  /**
6
5
  * XY location tool - gets user's current location.
7
6
  * Returns WGS84 coordinates (latitude, longitude).
@@ -9,38 +8,22 @@ import { logger } from "../utils/logger.js";
9
8
  export const locationTool = {
10
9
  name: "get_user_location",
11
10
  label: "Get User Location",
12
- description: "获取用户当前位置(经纬度坐标,WGS84坐标系)。需要用户设备授权位置访问权限。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。",
11
+ description: "获取用户当前位置(经纬度坐标,WGS84坐标系)。需要用户设备授权位置访问权限。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。",
13
12
  parameters: {
14
13
  type: "object",
15
14
  properties: {},
16
15
  required: [],
17
16
  },
18
17
  async execute(toolCallId, params) {
19
- logger.log(`[LOCATION_TOOL] 🚀 Starting execution`);
20
- logger.log(`[LOCATION_TOOL] - toolCallId: ${toolCallId}`);
21
- logger.log(`[LOCATION_TOOL] - params:`, JSON.stringify(params));
22
- logger.log(`[LOCATION_TOOL] - timestamp: ${new Date().toISOString()}`);
23
18
  // Get session context
24
- logger.log(`[LOCATION_TOOL] 🔍 Attempting to get session context...`);
25
- const sessionContext = getLatestSessionContext();
19
+ const sessionContext = getCurrentSessionContext();
26
20
  if (!sessionContext) {
27
- logger.error(`[LOCATION_TOOL] ❌ FAILED: No active session found!`);
28
- logger.error(`[LOCATION_TOOL] - toolCallId: ${toolCallId}`);
29
- logger.error(`[LOCATION_TOOL] - This suggests the session was not registered or already cleaned up`);
30
21
  throw new Error("No active XY session found. Location tool can only be used during an active conversation.");
31
22
  }
32
- logger.log(`[LOCATION_TOOL] ✅ Session context found`);
33
- logger.log(`[LOCATION_TOOL] - sessionId: ${sessionContext.sessionId}`);
34
- logger.log(`[LOCATION_TOOL] - taskId: ${sessionContext.taskId}`);
35
- logger.log(`[LOCATION_TOOL] - messageId: ${sessionContext.messageId}`);
36
- logger.log(`[LOCATION_TOOL] - agentId: ${sessionContext.agentId}`);
37
23
  const { config, sessionId, taskId, messageId } = sessionContext;
38
24
  // Get WebSocket manager
39
- logger.log(`[LOCATION_TOOL] 🔌 Getting WebSocket manager...`);
40
25
  const wsManager = getXYWebSocketManager(config);
41
- logger.log(`[LOCATION_TOOL] ✅ WebSocket manager obtained`);
42
26
  // Build GetCurrentLocation command
43
- logger.log(`[LOCATION_TOOL] 📦 Building GetCurrentLocation command...`);
44
27
  const command = {
45
28
  header: {
46
29
  namespace: "Common",
@@ -55,7 +38,9 @@ export const locationTool = {
55
38
  dimension: "",
56
39
  executeMode: "background",
57
40
  intentName: "GetCurrentLocation",
58
- intentParam: {},
41
+ intentParam: {
42
+ isNeedGeoAddress: true,
43
+ },
59
44
  needUnlock: true,
60
45
  permissionId: [],
61
46
  timeOut: 5,
@@ -70,53 +55,36 @@ export const locationTool = {
70
55
  },
71
56
  };
72
57
  // Send command and wait for response (60 second timeout)
73
- logger.log(`[LOCATION_TOOL] ⏳ Setting up promise to wait for location response...`);
74
- logger.log(`[LOCATION_TOOL] - Timeout: 60 seconds`);
75
58
  return new Promise((resolve, reject) => {
76
59
  const timeout = setTimeout(() => {
77
- logger.error(`[LOCATION_TOOL] ⏰ Timeout: No response received within 60 seconds`);
78
60
  wsManager.off("data-event", handler);
79
61
  reject(new Error("获取位置超时(60秒)"));
80
62
  }, 60000);
81
63
  // Listen for data events from WebSocket
82
64
  const handler = (event) => {
83
- logger.log(`[LOCATION_TOOL] 📨 Received data event:`, JSON.stringify(event));
84
65
  if (event.intentName === "GetCurrentLocation") {
85
- logger.log(`[LOCATION_TOOL] 🎯 GetCurrentLocation event received`);
86
- logger.log(`[LOCATION_TOOL] - status: ${event.status}`);
87
66
  clearTimeout(timeout);
88
67
  wsManager.off("data-event", handler);
89
68
  if (event.status === "success" && event.outputs) {
90
- const { latitude, longitude } = event.outputs;
91
- logger.log(`[LOCATION_TOOL] ✅ Location retrieved successfully`);
92
- logger.log(`[LOCATION_TOOL] - latitude: ${latitude}`);
93
- logger.log(`[LOCATION_TOOL] - longitude: ${longitude}`);
69
+ // 成功,直接返回完整的 event.outputs JSON 字符串
94
70
  resolve({
95
71
  content: [
96
72
  {
97
73
  type: "text",
98
- text: JSON.stringify({
99
- latitude,
100
- longitude,
101
- coordinateSystem: "WGS84",
102
- })
74
+ text: JSON.stringify(event.outputs),
103
75
  }
104
76
  ]
105
77
  });
106
78
  }
107
79
  else {
108
- logger.error(`[LOCATION_TOOL] ❌ Location retrieval failed`);
109
- logger.error(`[LOCATION_TOOL] - status: ${event.status}`);
110
80
  reject(new Error(`获取位置失败: ${event.status}`));
111
81
  }
112
82
  }
113
83
  };
114
84
  // Register event handler
115
85
  // Note: The WebSocket manager needs to emit 'data-event' when receiving data events
116
- logger.log(`[LOCATION_TOOL] 📡 Registering data-event handler on WebSocket manager`);
117
86
  wsManager.on("data-event", handler);
118
87
  // Send the command
119
- logger.log(`[LOCATION_TOOL] 📤 Sending GetCurrentLocation command...`);
120
88
  sendCommand({
121
89
  config,
122
90
  sessionId,
@@ -124,9 +92,7 @@ export const locationTool = {
124
92
  messageId,
125
93
  command,
126
94
  }).then(() => {
127
- logger.log(`[LOCATION_TOOL] ✅ Command sent successfully, waiting for response...`);
128
95
  }).catch((error) => {
129
- logger.error(`[LOCATION_TOOL] ❌ Failed to send command:`, error);
130
96
  clearTimeout(timeout);
131
97
  wsManager.off("data-event", handler);
132
98
  reject(error);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * XY modify alarm tool - modifies an existing alarm on user's device.
3
+ * Requires entityId from search_alarm or create_alarm tool.
4
+ *
5
+ * Prerequisites:
6
+ * 1. Call search_alarm or create_alarm tool first to get entityId
7
+ * 2. Use the entityId to identify which alarm to modify
8
+ */
9
+ export declare const modifyAlarmTool: any;