@ynhcj/xiaoyi-channel 0.0.26-beta → 0.0.28-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 (36) hide show
  1. package/dist/src/bot.js +13 -3
  2. package/dist/src/channel.js +11 -1
  3. package/dist/src/outbound.js +88 -76
  4. package/dist/src/tools/calendar-tool.js +2 -2
  5. package/dist/src/tools/call-phone-tool.d.ts +5 -0
  6. package/dist/src/tools/call-phone-tool.js +183 -0
  7. package/dist/src/tools/create-alarm-tool.d.ts +7 -0
  8. package/dist/src/tools/create-alarm-tool.js +444 -0
  9. package/dist/src/tools/delete-alarm-tool.d.ts +11 -0
  10. package/dist/src/tools/delete-alarm-tool.js +238 -0
  11. package/dist/src/tools/location-tool.js +2 -2
  12. package/dist/src/tools/modify-alarm-tool.d.ts +9 -0
  13. package/dist/src/tools/modify-alarm-tool.js +474 -0
  14. package/dist/src/tools/modify-note-tool.js +2 -2
  15. package/dist/src/tools/note-tool.js +2 -2
  16. package/dist/src/tools/search-alarm-tool.d.ts +8 -0
  17. package/dist/src/tools/search-alarm-tool.js +389 -0
  18. package/dist/src/tools/search-calendar-tool.js +2 -2
  19. package/dist/src/tools/search-contact-tool.js +2 -2
  20. package/dist/src/tools/search-file-tool.d.ts +5 -0
  21. package/dist/src/tools/search-file-tool.js +173 -0
  22. package/dist/src/tools/search-message-tool.d.ts +5 -0
  23. package/dist/src/tools/search-message-tool.js +173 -0
  24. package/dist/src/tools/search-note-tool.js +2 -2
  25. package/dist/src/tools/search-photo-gallery-tool.js +2 -2
  26. package/dist/src/tools/send-file-to-user-tool.d.ts +5 -0
  27. package/dist/src/tools/send-file-to-user-tool.js +290 -0
  28. package/dist/src/tools/send-message-tool.d.ts +5 -0
  29. package/dist/src/tools/send-message-tool.js +189 -0
  30. package/dist/src/tools/session-manager.d.ts +12 -0
  31. package/dist/src/tools/session-manager.js +33 -0
  32. package/dist/src/tools/upload-file-tool.d.ts +13 -0
  33. package/dist/src/tools/upload-file-tool.js +265 -0
  34. package/dist/src/tools/upload-photo-tool.js +2 -2
  35. package/dist/src/tools/xiaoyi-gui-tool.js +2 -2
  36. package/package.json +1 -1
@@ -0,0 +1,444 @@
1
+ import { getXYWebSocketManager } from "../client.js";
2
+ import { sendCommand } from "../formatter.js";
3
+ import { getCurrentSessionContext } from "./session-manager.js";
4
+ import { logger } from "../utils/logger.js";
5
+ // Enum definitions for alarm parameters
6
+ const ALARM_SNOOZE_DURATION_VALUES = [5, 10, 15, 20, 25, 30];
7
+ const ALARM_SNOOZE_TOTAL_VALUES = [0, 1, 3, 5, 10];
8
+ const ALARM_RING_DURATION_VALUES = [1, 5, 10, 15, 20, 30];
9
+ const DAYS_OF_WAKE_TYPE_VALUES = [0, 1, 2, 3, 4];
10
+ const DAYS_OF_WEEK_VALUES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
11
+ /**
12
+ * XY create alarm tool - creates an alarm on user's device.
13
+ * Requires alarmTime parameter. Other parameters are optional with sensible defaults.
14
+ *
15
+ * Time format: YYYYMMDD hhmmss (e.g., 20240315 143000)
16
+ */
17
+ export const createAlarmTool = {
18
+ name: "create_alarm",
19
+ label: "Create Alarm",
20
+ description: `在用户设备上创建闹钟。
21
+
22
+ 必需参数:
23
+ - alarmTime: 闹钟时间,格式必须为:YYYYMMDD hhmmss(例如:20240315 143000,表示2024年3月15日14:30:00)
24
+
25
+ 可选参数:
26
+ - alarmTitle: 闹钟名称/标题,默认为"闹钟"
27
+ - alarmSnoozeDuration: 小睡间隔(分钟),枚举值:5,10,15,20,25,30,默认10
28
+ - alarmSnoozeTotal: 再响次数,枚举值:0,1,3,5,10,默认0(表示不再响)
29
+ - alarmRingDuration: 响铃时长(分钟),枚举值:1,5,10,15,20,30,默认20
30
+ - daysOfWakeType: 闹钟响铃类型,枚举值:0=单次响铃,1=法定节假日,2=每天,3=自定义时间,4=法定工作日,默认0
31
+ - daysOfWeek: 自定义响铃星期,仅当daysOfWakeType=3(自定义时间)时必需且有效,其他情况不要传递此参数。数组或JSON字符串,枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun。注意:仅支持长度为1的数组,如果需要一周中不同的几天,需要多次调用此工具
32
+
33
+ 注意事项:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。`,
34
+ parameters: {
35
+ type: "object",
36
+ properties: {
37
+ alarmTime: {
38
+ type: "string",
39
+ description: "闹钟时间,格式必须为:YYYYMMDD hhmmss(例如:20240315 143000)",
40
+ },
41
+ alarmTitle: {
42
+ type: "string",
43
+ description: "闹钟名称/标题,默认为'闹钟'",
44
+ },
45
+ alarmSnoozeDuration: {
46
+ type: "number",
47
+ description: "小睡间隔(分钟),枚举值:5,10,15,20,25,30,默认10",
48
+ },
49
+ alarmSnoozeTotal: {
50
+ type: "number",
51
+ description: "再响次数,枚举值:0,1,3,5,10,默认0",
52
+ },
53
+ alarmRingDuration: {
54
+ type: "number",
55
+ description: "响铃时长(分钟),枚举值:1,5,10,15,20,30,默认5",
56
+ },
57
+ daysOfWakeType: {
58
+ type: "number",
59
+ description: "闹钟响铃类型:0=单次,1=法定节假日,2=每天,3=自定义,4=法定工作日,默认0",
60
+ },
61
+ daysOfWeek: {
62
+ // 不指定 type,允许传入数组或 JSON 字符串
63
+ // 具体的类型验证和转换在 execute 函数内部进行
64
+ description: "自定义响铃星期(仅当daysOfWakeType=3时需要,其他情况不要传递),数组或JSON字符串,枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun。注意:仅支持长度为1的数组,如果需要一周中不同的几天,需要多次调用此工具",
65
+ },
66
+ },
67
+ required: ["alarmTime"],
68
+ },
69
+ async execute(toolCallId, params) {
70
+ logger.log(`[CREATE_ALARM_TOOL] 🚀 Starting execution`);
71
+ logger.log(`[CREATE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
72
+ logger.log(`[CREATE_ALARM_TOOL] - params:`, JSON.stringify(params));
73
+ logger.log(`[CREATE_ALARM_TOOL] - timestamp: ${new Date().toISOString()}`);
74
+ // ===== Validate required parameter: alarmTime =====
75
+ if (!params.alarmTime || typeof params.alarmTime !== "string") {
76
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Missing or invalid alarmTime`);
77
+ throw new Error("Missing required parameter: alarmTime must be a string in format YYYYMMDD hhmmss");
78
+ }
79
+ // Parse and convert alarmTime to timestamp
80
+ logger.log(`[CREATE_ALARM_TOOL] 🕒 Parsing alarmTime: ${params.alarmTime}`);
81
+ const alarmTimeMs = parseAlarmTimeToTimestamp(params.alarmTime);
82
+ if (alarmTimeMs === null) {
83
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmTime format`);
84
+ throw new Error("Invalid alarmTime format. Required format: YYYYMMDD hhmmss (e.g., 20240315 143000)");
85
+ }
86
+ logger.log(`[CREATE_ALARM_TOOL] ✅ alarmTime converted to timestamp: ${alarmTimeMs}`);
87
+ // ===== Validate and set optional parameters with defaults =====
88
+ // alarmTitle - default to "闹钟"
89
+ const alarmTitle = params.alarmTitle && typeof params.alarmTitle === "string"
90
+ ? params.alarmTitle
91
+ : "闹钟";
92
+ logger.log(`[CREATE_ALARM_TOOL] - alarmTitle: ${alarmTitle}`);
93
+ // alarmSnoozeDuration - default 10
94
+ let alarmSnoozeDuration = 10;
95
+ if (params.alarmSnoozeDuration !== undefined && params.alarmSnoozeDuration !== null) {
96
+ if (typeof params.alarmSnoozeDuration !== "number") {
97
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration type`);
98
+ throw new Error("alarmSnoozeDuration must be a number");
99
+ }
100
+ if (!ALARM_SNOOZE_DURATION_VALUES.includes(params.alarmSnoozeDuration)) {
101
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration value: ${params.alarmSnoozeDuration}`);
102
+ throw new Error(`alarmSnoozeDuration must be one of: ${ALARM_SNOOZE_DURATION_VALUES.join(", ")}`);
103
+ }
104
+ alarmSnoozeDuration = params.alarmSnoozeDuration;
105
+ }
106
+ logger.log(`[CREATE_ALARM_TOOL] - alarmSnoozeDuration: ${alarmSnoozeDuration}`);
107
+ // alarmSnoozeTotal - default 0
108
+ let alarmSnoozeTotal = 0;
109
+ if (params.alarmSnoozeTotal !== undefined && params.alarmSnoozeTotal !== null) {
110
+ if (typeof params.alarmSnoozeTotal !== "number") {
111
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal type`);
112
+ throw new Error("alarmSnoozeTotal must be a number");
113
+ }
114
+ if (!ALARM_SNOOZE_TOTAL_VALUES.includes(params.alarmSnoozeTotal)) {
115
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal value: ${params.alarmSnoozeTotal}`);
116
+ throw new Error(`alarmSnoozeTotal must be one of: ${ALARM_SNOOZE_TOTAL_VALUES.join(", ")}`);
117
+ }
118
+ alarmSnoozeTotal = params.alarmSnoozeTotal;
119
+ }
120
+ logger.log(`[CREATE_ALARM_TOOL] - alarmSnoozeTotal: ${alarmSnoozeTotal}`);
121
+ // alarmRingDuration - default 20
122
+ let alarmRingDuration = 20;
123
+ if (params.alarmRingDuration !== undefined && params.alarmRingDuration !== null) {
124
+ if (typeof params.alarmRingDuration !== "number") {
125
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmRingDuration type`);
126
+ throw new Error("alarmRingDuration must be a number");
127
+ }
128
+ if (!ALARM_RING_DURATION_VALUES.includes(params.alarmRingDuration)) {
129
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmRingDuration value: ${params.alarmRingDuration}`);
130
+ throw new Error(`alarmRingDuration must be one of: ${ALARM_RING_DURATION_VALUES.join(", ")}`);
131
+ }
132
+ alarmRingDuration = params.alarmRingDuration;
133
+ }
134
+ logger.log(`[CREATE_ALARM_TOOL] - alarmRingDuration: ${alarmRingDuration}`);
135
+ // daysOfWakeType - default 0
136
+ let daysOfWakeType = 0;
137
+ if (params.daysOfWakeType !== undefined && params.daysOfWakeType !== null) {
138
+ if (typeof params.daysOfWakeType !== "number") {
139
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWakeType type`);
140
+ throw new Error("daysOfWakeType must be a number");
141
+ }
142
+ if (!DAYS_OF_WAKE_TYPE_VALUES.includes(params.daysOfWakeType)) {
143
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWakeType value: ${params.daysOfWakeType}`);
144
+ throw new Error(`daysOfWakeType must be one of: ${DAYS_OF_WAKE_TYPE_VALUES.join(", ")}`);
145
+ }
146
+ daysOfWakeType = params.daysOfWakeType;
147
+ }
148
+ logger.log(`[CREATE_ALARM_TOOL] - daysOfWakeType: ${daysOfWakeType}`);
149
+ // daysOfWeek - only required when daysOfWakeType is 3
150
+ let daysOfWeek = [];
151
+ if (daysOfWakeType === 3) {
152
+ if (!params.daysOfWeek) {
153
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Missing daysOfWeek when daysOfWakeType=3`);
154
+ throw new Error("daysOfWeek is required when daysOfWakeType is 3 (custom)");
155
+ }
156
+ // ===== 参数规范化:兼容数组和 JSON 字符串 =====
157
+ let normalizedDaysOfWeek = null;
158
+ // 情况1: 已经是数组
159
+ if (Array.isArray(params.daysOfWeek)) {
160
+ logger.log(`[CREATE_ALARM_TOOL] ✅ daysOfWeek is already an array`);
161
+ normalizedDaysOfWeek = params.daysOfWeek;
162
+ }
163
+ // 情况2: 是字符串,尝试解析为 JSON 数组
164
+ else if (typeof params.daysOfWeek === 'string') {
165
+ logger.log(`[CREATE_ALARM_TOOL] 🔄 daysOfWeek is a string, attempting to parse as JSON...`);
166
+ try {
167
+ const parsed = JSON.parse(params.daysOfWeek);
168
+ if (Array.isArray(parsed)) {
169
+ logger.log(`[CREATE_ALARM_TOOL] ✅ Successfully parsed JSON string to array`);
170
+ normalizedDaysOfWeek = parsed;
171
+ }
172
+ else {
173
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Parsed JSON is not an array:`, typeof parsed);
174
+ throw new Error("daysOfWeek must be an array or a JSON string representing an array");
175
+ }
176
+ }
177
+ catch (parseError) {
178
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Failed to parse daysOfWeek as JSON:`, parseError);
179
+ throw new Error(`daysOfWeek must be a valid JSON array string. Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
180
+ }
181
+ }
182
+ // 情况3: 其他类型,报错
183
+ else {
184
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWeek type:`, typeof params.daysOfWeek);
185
+ throw new Error(`daysOfWeek must be an array or a JSON string, got ${typeof params.daysOfWeek}`);
186
+ }
187
+ // 验证数组非空
188
+ if (!normalizedDaysOfWeek || normalizedDaysOfWeek.length === 0) {
189
+ logger.error(`[CREATE_ALARM_TOOL] ❌ daysOfWeek array is empty`);
190
+ throw new Error("daysOfWeek array cannot be empty");
191
+ }
192
+ // 验证数组长度必须为1
193
+ if (normalizedDaysOfWeek.length !== 1) {
194
+ logger.error(`[CREATE_ALARM_TOOL] ❌ daysOfWeek array length must be 1, got ${normalizedDaysOfWeek.length}`);
195
+ throw new Error("daysOfWeek 仅支持长度为1的数组。如果需要一周中不同的几天,需要多次调用此工具");
196
+ }
197
+ // Validate each day
198
+ for (const day of normalizedDaysOfWeek) {
199
+ if (typeof day !== "string" || !DAYS_OF_WEEK_VALUES.includes(day)) {
200
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid day value: ${day}`);
201
+ throw new Error(`daysOfWeek must contain only: ${DAYS_OF_WEEK_VALUES.join(", ")}`);
202
+ }
203
+ }
204
+ daysOfWeek = normalizedDaysOfWeek;
205
+ logger.log(`[CREATE_ALARM_TOOL] - daysOfWeek: ${daysOfWeek.join(", ")}`);
206
+ }
207
+ else {
208
+ // daysOfWakeType is not 3, daysOfWeek should not be provided
209
+ if (params.daysOfWeek) {
210
+ logger.warn(`[CREATE_ALARM_TOOL] ⚠️ daysOfWeek parameter is ignored when daysOfWakeType is not 3 (current: ${daysOfWakeType}). Please remove daysOfWeek parameter.`);
211
+ }
212
+ // Explicitly set to empty array
213
+ daysOfWeek = [];
214
+ }
215
+ // Get session context
216
+ logger.log(`[CREATE_ALARM_TOOL] 🔍 Attempting to get session context...`);
217
+ const sessionContext = getCurrentSessionContext();
218
+ if (!sessionContext) {
219
+ logger.error(`[CREATE_ALARM_TOOL] ❌ FAILED: No active session found!`);
220
+ logger.error(`[CREATE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
221
+ throw new Error("No active XY session found. Create alarm tool can only be used during an active conversation.");
222
+ }
223
+ logger.log(`[CREATE_ALARM_TOOL] ✅ Session context found`);
224
+ logger.log(`[CREATE_ALARM_TOOL] - sessionId: ${sessionContext.sessionId}`);
225
+ logger.log(`[CREATE_ALARM_TOOL] - taskId: ${sessionContext.taskId}`);
226
+ logger.log(`[CREATE_ALARM_TOOL] - messageId: ${sessionContext.messageId}`);
227
+ const { config, sessionId, taskId, messageId } = sessionContext;
228
+ // Get WebSocket manager
229
+ logger.log(`[CREATE_ALARM_TOOL] 🔌 Getting WebSocket manager...`);
230
+ const wsManager = getXYWebSocketManager(config);
231
+ logger.log(`[CREATE_ALARM_TOOL] ✅ WebSocket manager obtained`);
232
+ // Build CreateAlarm command
233
+ logger.log(`[CREATE_ALARM_TOOL] 📦 Building CreateAlarm command...`);
234
+ // Build intentParam - only include daysOfWeek when daysOfWakeType is 3
235
+ const intentParam = {
236
+ entityName: "Alarm",
237
+ alarmTime: alarmTimeMs,
238
+ alarmTitle: alarmTitle,
239
+ alarmSnoozeDuration: alarmSnoozeDuration,
240
+ alarmSnoozeTotal: alarmSnoozeTotal,
241
+ alarmRingDuration: alarmRingDuration,
242
+ daysOfWakeType: daysOfWakeType,
243
+ };
244
+ // Only include daysOfWeek when daysOfWakeType is 3
245
+ if (daysOfWakeType === 3 && daysOfWeek.length > 0) {
246
+ intentParam.daysOfWeek = daysOfWeek;
247
+ logger.log(`[CREATE_ALARM_TOOL] - Including daysOfWeek in intentParam: ${daysOfWeek.join(", ")}`);
248
+ }
249
+ else {
250
+ logger.log(`[CREATE_ALARM_TOOL] - Excluding daysOfWeek from intentParam (daysOfWakeType=${daysOfWakeType})`);
251
+ }
252
+ const command = {
253
+ header: {
254
+ namespace: "Common",
255
+ name: "Action",
256
+ },
257
+ payload: {
258
+ cardParam: {},
259
+ executeParam: {
260
+ executeMode: "background",
261
+ intentName: "CreateAlarm",
262
+ bundleName: "com.huawei.hmos.clock",
263
+ needUnlock: true,
264
+ actionResponse: true,
265
+ appType: "OHOS_APP",
266
+ timeOut: 5,
267
+ intentParam: intentParam,
268
+ permissionId: [],
269
+ achieveType: "INTENT",
270
+ },
271
+ responses: [
272
+ {
273
+ resultCode: "",
274
+ displayText: "",
275
+ ttsText: "",
276
+ },
277
+ ],
278
+ needUploadResult: true,
279
+ noHalfPage: false,
280
+ pageControlRelated: false,
281
+ },
282
+ };
283
+ // Send command and wait for response (60 second timeout)
284
+ logger.log(`[CREATE_ALARM_TOOL] ⏳ Setting up promise to wait for alarm creation response...`);
285
+ logger.log(`[CREATE_ALARM_TOOL] - Timeout: 60 seconds`);
286
+ return new Promise((resolve, reject) => {
287
+ const timeout = setTimeout(() => {
288
+ logger.error(`[CREATE_ALARM_TOOL] ⏰ Timeout: No response received within 60 seconds`);
289
+ wsManager.off("data-event", handler);
290
+ reject(new Error("创建闹钟超时(60秒)"));
291
+ }, 60000);
292
+ // Listen for data events from WebSocket
293
+ const handler = (event) => {
294
+ logger.log(`[CREATE_ALARM_TOOL] 📨 Received data event:`, JSON.stringify(event));
295
+ if (event.intentName === "CreateAlarm") {
296
+ logger.log(`[CREATE_ALARM_TOOL] 🎯 CreateAlarm event received`);
297
+ logger.log(`[CREATE_ALARM_TOOL] - status: ${event.status}`);
298
+ clearTimeout(timeout);
299
+ wsManager.off("data-event", handler);
300
+ if (event.status === "success" && event.outputs) {
301
+ logger.log(`[CREATE_ALARM_TOOL] ✅ Alarm creation completed successfully`);
302
+ logger.log(`[CREATE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs));
303
+ // Check for error code in outputs
304
+ const code = event.outputs.code !== undefined ? event.outputs.code : null;
305
+ if (code !== null && code !== 0) {
306
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Device returned error`);
307
+ logger.error(`[CREATE_ALARM_TOOL] - code: ${code}`);
308
+ const errorMsg = event.outputs.errorMsg || event.outputs.errMsg || "未知错误";
309
+ logger.error(`[CREATE_ALARM_TOOL] - errorMsg: ${errorMsg}`);
310
+ reject(new Error(`创建闹钟失败: ${errorMsg} (错误代码: ${code})`));
311
+ return;
312
+ }
313
+ // Extract result with safe navigation
314
+ const result = event.outputs.result || {};
315
+ logger.log(`[CREATE_ALARM_TOOL] 📋 Alarm result:`, JSON.stringify(result));
316
+ resolve({
317
+ content: [
318
+ {
319
+ type: "text",
320
+ text: JSON.stringify({
321
+ success: true,
322
+ alarm: {
323
+ entityId: result.entityId,
324
+ entityName: result.entityName,
325
+ alarmTitle: result.alarmTitle,
326
+ alarmTime: result.alarmTime,
327
+ alarmState: result.alarmState,
328
+ alarmRingDuration: result.alarmRingDuration,
329
+ alarmSnoozeDuration: result.alarmSnoozeDuration,
330
+ alarmSnoozeTotal: result.alarmSnoozeTotal,
331
+ daysOfWakeType: result.daysOfWakeType,
332
+ },
333
+ code,
334
+ }),
335
+ },
336
+ ],
337
+ });
338
+ }
339
+ else {
340
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Alarm creation failed`);
341
+ logger.error(`[CREATE_ALARM_TOOL] - status: ${event.status}`);
342
+ logger.error(`[CREATE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
343
+ reject(new Error(`创建闹钟失败: ${event.status}`));
344
+ }
345
+ }
346
+ };
347
+ // Register event handler
348
+ logger.log(`[CREATE_ALARM_TOOL] 📡 Registering data-event handler on WebSocket manager`);
349
+ wsManager.on("data-event", handler);
350
+ // Send the command
351
+ logger.log(`[CREATE_ALARM_TOOL] 📤 Sending CreateAlarm command...`);
352
+ sendCommand({
353
+ config,
354
+ sessionId,
355
+ taskId,
356
+ messageId,
357
+ command,
358
+ })
359
+ .then(() => {
360
+ logger.log(`[CREATE_ALARM_TOOL] ✅ Command sent successfully, waiting for response...`);
361
+ })
362
+ .catch((error) => {
363
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Failed to send command:`, error);
364
+ clearTimeout(timeout);
365
+ wsManager.off("data-event", handler);
366
+ reject(error);
367
+ });
368
+ });
369
+ },
370
+ };
371
+ /**
372
+ * Parse alarmTime string (YYYYMMDD hhmmss) to timestamp in milliseconds
373
+ * @param alarmTime - Time string in format "YYYYMMDD hhmmss" (e.g., "20240315 143000")
374
+ * @returns Timestamp in milliseconds, or null if parsing fails
375
+ */
376
+ function parseAlarmTimeToTimestamp(alarmTime) {
377
+ try {
378
+ // Expected format: YYYYMMDD hhmmss
379
+ // Example: 20240315 143000
380
+ const trimmed = alarmTime.trim();
381
+ // Check basic format (should have at least 13 characters: YYYYMMDD hhmmss)
382
+ if (trimmed.length < 13) {
383
+ logger.error(`[CREATE_ALARM_TOOL] ❌ alarmTime too short: ${trimmed}`);
384
+ return null;
385
+ }
386
+ // Extract date and time parts
387
+ // Format: YYYYMMDD hhmmss
388
+ const datePart = trimmed.substring(0, 8); // YYYYMMDD
389
+ const timePart = trimmed.substring(8).trim(); // hhmmss (may have leading space)
390
+ logger.log(`[CREATE_ALARM_TOOL] - datePart: ${datePart}, timePart: ${timePart}`);
391
+ // Validate lengths
392
+ if (datePart.length !== 8 || timePart.length !== 6) {
393
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid part lengths: datePart=${datePart.length}, timePart=${timePart.length}`);
394
+ return null;
395
+ }
396
+ // Parse components
397
+ const year = parseInt(datePart.substring(0, 4), 10);
398
+ const month = parseInt(datePart.substring(4, 6), 10);
399
+ const day = parseInt(datePart.substring(6, 8), 10);
400
+ const hour = parseInt(timePart.substring(0, 2), 10);
401
+ const minute = parseInt(timePart.substring(2, 4), 10);
402
+ const second = parseInt(timePart.substring(4, 6), 10);
403
+ logger.log(`[CREATE_ALARM_TOOL] - Parsed: ${year}-${month}-${day} ${hour}:${minute}:${second}`);
404
+ // Validate values
405
+ if (isNaN(year) || isNaN(month) || isNaN(day) ||
406
+ isNaN(hour) || isNaN(minute) || isNaN(second)) {
407
+ logger.error(`[CREATE_ALARM_TOOL] ❌ NaN detected in parsed values`);
408
+ return null;
409
+ }
410
+ // Validate ranges
411
+ if (month < 1 || month > 12) {
412
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid month: ${month}`);
413
+ return null;
414
+ }
415
+ if (day < 1 || day > 31) {
416
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid day: ${day}`);
417
+ return null;
418
+ }
419
+ if (hour < 0 || hour > 23) {
420
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid hour: ${hour}`);
421
+ return null;
422
+ }
423
+ if (minute < 0 || minute > 59) {
424
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid minute: ${minute}`);
425
+ return null;
426
+ }
427
+ if (second < 0 || second > 59) {
428
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid second: ${second}`);
429
+ return null;
430
+ }
431
+ // Create Date object and get timestamp
432
+ const date = new Date(year, month - 1, day, hour, minute, second);
433
+ const timestamp = date.getTime();
434
+ if (isNaN(timestamp)) {
435
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Generated timestamp is NaN`);
436
+ return null;
437
+ }
438
+ return timestamp;
439
+ }
440
+ catch (error) {
441
+ logger.error(`[CREATE_ALARM_TOOL] ❌ Exception in parseAlarmTimeToTimestamp:`, error);
442
+ return null;
443
+ }
444
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * XY delete alarm tool - deletes existing alarms on user's device.
3
+ * Requires entityId(s) from search_alarm or create_alarm tool as prerequisite.
4
+ *
5
+ * Prerequisites:
6
+ * 1. Call search_alarm or create_alarm tool first to get entityId(s) of alarms
7
+ * 2. Use the entityId(s) to delete those alarms
8
+ *
9
+ * Supports deleting single or multiple alarms in one call.
10
+ */
11
+ export declare const deleteAlarmTool: any;