@ynhcj/xiaoyi-channel 0.0.51-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/src/bot.js +0 -16
- package/dist/src/client.js +0 -2
- package/dist/src/formatter.js +3 -23
- package/dist/src/heartbeat.js +0 -1
- package/dist/src/reply-dispatcher.js +32 -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 -8
- package/package.json +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
3
|
import { getCurrentSessionContext } from "./session-manager.js";
|
|
4
|
-
import { logger } from "../utils/logger.js";
|
|
5
4
|
// Enum definitions for alarm parameters
|
|
6
5
|
const ALARM_SNOOZE_DURATION_VALUES = [5, 10, 15, 20, 25, 30];
|
|
7
6
|
const ALARM_SNOOZE_TOTAL_VALUES = [0, 1, 3, 5, 10];
|
|
@@ -32,7 +31,9 @@ export const createAlarmTool = {
|
|
|
32
31
|
|
|
33
32
|
注意事项:
|
|
34
33
|
a. 操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。
|
|
35
|
-
b.
|
|
34
|
+
b. 使用该工具之前需获取当前真实时间
|
|
35
|
+
|
|
36
|
+
回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。`,
|
|
36
37
|
parameters: {
|
|
37
38
|
type: "object",
|
|
38
39
|
properties: {
|
|
@@ -69,170 +70,127 @@ b. 使用该工具之前需获取当前真实时间`,
|
|
|
69
70
|
required: ["alarmTime"],
|
|
70
71
|
},
|
|
71
72
|
async execute(toolCallId, params) {
|
|
72
|
-
logger.log(`[CREATE_ALARM_TOOL] 🚀 Starting execution`);
|
|
73
|
-
logger.log(`[CREATE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
74
|
-
logger.log(`[CREATE_ALARM_TOOL] - params:`, JSON.stringify(params));
|
|
75
|
-
logger.log(`[CREATE_ALARM_TOOL] - timestamp: ${new Date().toISOString()}`);
|
|
76
73
|
// ===== Validate required parameter: alarmTime =====
|
|
77
74
|
if (!params.alarmTime || typeof params.alarmTime !== "string") {
|
|
78
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Missing or invalid alarmTime`);
|
|
79
75
|
throw new Error("Missing required parameter: alarmTime must be a string in format YYYYMMDD hhmmss");
|
|
80
76
|
}
|
|
81
77
|
// Parse and convert alarmTime to timestamp
|
|
82
|
-
logger.log(`[CREATE_ALARM_TOOL] 🕒 Parsing alarmTime: ${params.alarmTime}`);
|
|
83
78
|
const alarmTimeMs = parseAlarmTimeToTimestamp(params.alarmTime);
|
|
84
79
|
if (alarmTimeMs === null) {
|
|
85
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmTime format`);
|
|
86
80
|
throw new Error("Invalid alarmTime format. Required format: YYYYMMDD hhmmss (e.g., 20240315 143000)");
|
|
87
81
|
}
|
|
88
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ alarmTime converted to timestamp: ${alarmTimeMs}`);
|
|
89
82
|
// ===== Validate and set optional parameters with defaults =====
|
|
90
83
|
// alarmTitle - default to "闹钟"
|
|
91
84
|
const alarmTitle = params.alarmTitle && typeof params.alarmTitle === "string"
|
|
92
85
|
? params.alarmTitle
|
|
93
86
|
: "闹钟";
|
|
94
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmTitle: ${alarmTitle}`);
|
|
95
87
|
// alarmSnoozeDuration - default 10
|
|
96
88
|
let alarmSnoozeDuration = 10;
|
|
97
89
|
if (params.alarmSnoozeDuration !== undefined && params.alarmSnoozeDuration !== null) {
|
|
98
90
|
if (typeof params.alarmSnoozeDuration !== "number") {
|
|
99
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration type`);
|
|
100
91
|
throw new Error("alarmSnoozeDuration must be a number");
|
|
101
92
|
}
|
|
102
93
|
if (!ALARM_SNOOZE_DURATION_VALUES.includes(params.alarmSnoozeDuration)) {
|
|
103
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration value: ${params.alarmSnoozeDuration}`);
|
|
104
94
|
throw new Error(`alarmSnoozeDuration must be one of: ${ALARM_SNOOZE_DURATION_VALUES.join(", ")}`);
|
|
105
95
|
}
|
|
106
96
|
alarmSnoozeDuration = params.alarmSnoozeDuration;
|
|
107
97
|
}
|
|
108
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmSnoozeDuration: ${alarmSnoozeDuration}`);
|
|
109
98
|
// alarmSnoozeTotal - default 0
|
|
110
99
|
let alarmSnoozeTotal = 0;
|
|
111
100
|
if (params.alarmSnoozeTotal !== undefined && params.alarmSnoozeTotal !== null) {
|
|
112
101
|
if (typeof params.alarmSnoozeTotal !== "number") {
|
|
113
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal type`);
|
|
114
102
|
throw new Error("alarmSnoozeTotal must be a number");
|
|
115
103
|
}
|
|
116
104
|
if (!ALARM_SNOOZE_TOTAL_VALUES.includes(params.alarmSnoozeTotal)) {
|
|
117
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal value: ${params.alarmSnoozeTotal}`);
|
|
118
105
|
throw new Error(`alarmSnoozeTotal must be one of: ${ALARM_SNOOZE_TOTAL_VALUES.join(", ")}`);
|
|
119
106
|
}
|
|
120
107
|
alarmSnoozeTotal = params.alarmSnoozeTotal;
|
|
121
108
|
}
|
|
122
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmSnoozeTotal: ${alarmSnoozeTotal}`);
|
|
123
109
|
// alarmRingDuration - default 20
|
|
124
110
|
let alarmRingDuration = 20;
|
|
125
111
|
if (params.alarmRingDuration !== undefined && params.alarmRingDuration !== null) {
|
|
126
112
|
if (typeof params.alarmRingDuration !== "number") {
|
|
127
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmRingDuration type`);
|
|
128
113
|
throw new Error("alarmRingDuration must be a number");
|
|
129
114
|
}
|
|
130
115
|
if (!ALARM_RING_DURATION_VALUES.includes(params.alarmRingDuration)) {
|
|
131
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmRingDuration value: ${params.alarmRingDuration}`);
|
|
132
116
|
throw new Error(`alarmRingDuration must be one of: ${ALARM_RING_DURATION_VALUES.join(", ")}`);
|
|
133
117
|
}
|
|
134
118
|
alarmRingDuration = params.alarmRingDuration;
|
|
135
119
|
}
|
|
136
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmRingDuration: ${alarmRingDuration}`);
|
|
137
120
|
// daysOfWakeType - default 0
|
|
138
121
|
let daysOfWakeType = 0;
|
|
139
122
|
if (params.daysOfWakeType !== undefined && params.daysOfWakeType !== null) {
|
|
140
123
|
if (typeof params.daysOfWakeType !== "number") {
|
|
141
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWakeType type`);
|
|
142
124
|
throw new Error("daysOfWakeType must be a number");
|
|
143
125
|
}
|
|
144
126
|
if (!DAYS_OF_WAKE_TYPE_VALUES.includes(params.daysOfWakeType)) {
|
|
145
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWakeType value: ${params.daysOfWakeType}`);
|
|
146
127
|
throw new Error(`daysOfWakeType must be one of: ${DAYS_OF_WAKE_TYPE_VALUES.join(", ")}`);
|
|
147
128
|
}
|
|
148
129
|
daysOfWakeType = params.daysOfWakeType;
|
|
149
130
|
}
|
|
150
|
-
logger.log(`[CREATE_ALARM_TOOL] - daysOfWakeType: ${daysOfWakeType}`);
|
|
151
131
|
// daysOfWeek - only required when daysOfWakeType is 3
|
|
152
132
|
let daysOfWeek = [];
|
|
153
133
|
if (daysOfWakeType === 3) {
|
|
154
134
|
if (!params.daysOfWeek) {
|
|
155
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Missing daysOfWeek when daysOfWakeType=3`);
|
|
156
135
|
throw new Error("daysOfWeek is required when daysOfWakeType is 3 (custom)");
|
|
157
136
|
}
|
|
158
137
|
// ===== 参数规范化:兼容数组和 JSON 字符串 =====
|
|
159
138
|
let normalizedDaysOfWeek = null;
|
|
160
139
|
// 情况1: 已经是数组
|
|
161
140
|
if (Array.isArray(params.daysOfWeek)) {
|
|
162
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ daysOfWeek is already an array`);
|
|
163
141
|
normalizedDaysOfWeek = params.daysOfWeek;
|
|
164
142
|
}
|
|
165
143
|
// 情况2: 是字符串,尝试解析为 JSON 数组
|
|
166
144
|
else if (typeof params.daysOfWeek === 'string') {
|
|
167
|
-
logger.log(`[CREATE_ALARM_TOOL] 🔄 daysOfWeek is a string, attempting to parse as JSON...`);
|
|
168
145
|
try {
|
|
169
146
|
const parsed = JSON.parse(params.daysOfWeek);
|
|
170
147
|
if (Array.isArray(parsed)) {
|
|
171
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ Successfully parsed JSON string to array`);
|
|
172
148
|
normalizedDaysOfWeek = parsed;
|
|
173
149
|
}
|
|
174
150
|
else {
|
|
175
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Parsed JSON is not an array:`, typeof parsed);
|
|
176
151
|
throw new Error("daysOfWeek must be an array or a JSON string representing an array");
|
|
177
152
|
}
|
|
178
153
|
}
|
|
179
154
|
catch (parseError) {
|
|
180
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Failed to parse daysOfWeek as JSON:`, parseError);
|
|
181
155
|
throw new Error(`daysOfWeek must be a valid JSON array string. Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
182
156
|
}
|
|
183
157
|
}
|
|
184
158
|
// 情况3: 其他类型,报错
|
|
185
159
|
else {
|
|
186
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWeek type:`, typeof params.daysOfWeek);
|
|
187
160
|
throw new Error(`daysOfWeek must be an array or a JSON string, got ${typeof params.daysOfWeek}`);
|
|
188
161
|
}
|
|
189
162
|
// 验证数组非空
|
|
190
163
|
if (!normalizedDaysOfWeek || normalizedDaysOfWeek.length === 0) {
|
|
191
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ daysOfWeek array is empty`);
|
|
192
164
|
throw new Error("daysOfWeek array cannot be empty");
|
|
193
165
|
}
|
|
194
166
|
// 验证数组长度必须为1
|
|
195
167
|
if (normalizedDaysOfWeek.length !== 1) {
|
|
196
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ daysOfWeek array length must be 1, got ${normalizedDaysOfWeek.length}`);
|
|
197
168
|
throw new Error("daysOfWeek 仅支持长度为1的数组。如果需要一周中不同的几天,需要多次调用此工具");
|
|
198
169
|
}
|
|
199
170
|
// Validate each day
|
|
200
171
|
for (const day of normalizedDaysOfWeek) {
|
|
201
172
|
if (typeof day !== "string" || !DAYS_OF_WEEK_VALUES.includes(day)) {
|
|
202
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid day value: ${day}`);
|
|
203
173
|
throw new Error(`daysOfWeek must contain only: ${DAYS_OF_WEEK_VALUES.join(", ")}`);
|
|
204
174
|
}
|
|
205
175
|
}
|
|
206
176
|
daysOfWeek = normalizedDaysOfWeek;
|
|
207
|
-
logger.log(`[CREATE_ALARM_TOOL] - daysOfWeek: ${daysOfWeek.join(", ")}`);
|
|
208
177
|
}
|
|
209
178
|
else {
|
|
210
179
|
// daysOfWakeType is not 3, daysOfWeek should not be provided
|
|
211
180
|
if (params.daysOfWeek) {
|
|
212
|
-
logger.warn(`[CREATE_ALARM_TOOL] ⚠️ daysOfWeek parameter is ignored when daysOfWakeType is not 3 (current: ${daysOfWakeType}). Please remove daysOfWeek parameter.`);
|
|
213
181
|
}
|
|
214
182
|
// Explicitly set to empty array
|
|
215
183
|
daysOfWeek = [];
|
|
216
184
|
}
|
|
217
185
|
// Get session context
|
|
218
|
-
logger.log(`[CREATE_ALARM_TOOL] 🔍 Attempting to get session context...`);
|
|
219
186
|
const sessionContext = getCurrentSessionContext();
|
|
220
187
|
if (!sessionContext) {
|
|
221
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ FAILED: No active session found!`);
|
|
222
|
-
logger.error(`[CREATE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
223
188
|
throw new Error("No active XY session found. Create alarm tool can only be used during an active conversation.");
|
|
224
189
|
}
|
|
225
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ Session context found`);
|
|
226
|
-
logger.log(`[CREATE_ALARM_TOOL] - sessionId: ${sessionContext.sessionId}`);
|
|
227
|
-
logger.log(`[CREATE_ALARM_TOOL] - taskId: ${sessionContext.taskId}`);
|
|
228
|
-
logger.log(`[CREATE_ALARM_TOOL] - messageId: ${sessionContext.messageId}`);
|
|
229
190
|
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
230
191
|
// Get WebSocket manager
|
|
231
|
-
logger.log(`[CREATE_ALARM_TOOL] 🔌 Getting WebSocket manager...`);
|
|
232
192
|
const wsManager = getXYWebSocketManager(config);
|
|
233
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ WebSocket manager obtained`);
|
|
234
193
|
// Build CreateAlarm command
|
|
235
|
-
logger.log(`[CREATE_ALARM_TOOL] 📦 Building CreateAlarm command...`);
|
|
236
194
|
// Build intentParam - only include daysOfWeek when daysOfWakeType is 3
|
|
237
195
|
const intentParam = {
|
|
238
196
|
entityName: "Alarm",
|
|
@@ -246,10 +204,8 @@ b. 使用该工具之前需获取当前真实时间`,
|
|
|
246
204
|
// Only include daysOfWeek when daysOfWakeType is 3
|
|
247
205
|
if (daysOfWakeType === 3 && daysOfWeek.length > 0) {
|
|
248
206
|
intentParam.daysOfWeek = daysOfWeek;
|
|
249
|
-
logger.log(`[CREATE_ALARM_TOOL] - Including daysOfWeek in intentParam: ${daysOfWeek.join(", ")}`);
|
|
250
207
|
}
|
|
251
208
|
else {
|
|
252
|
-
logger.log(`[CREATE_ALARM_TOOL] - Excluding daysOfWeek from intentParam (daysOfWakeType=${daysOfWakeType})`);
|
|
253
209
|
}
|
|
254
210
|
const command = {
|
|
255
211
|
header: {
|
|
@@ -283,25 +239,17 @@ b. 使用该工具之前需获取当前真实时间`,
|
|
|
283
239
|
},
|
|
284
240
|
};
|
|
285
241
|
// Send command and wait for response (60 second timeout)
|
|
286
|
-
logger.log(`[CREATE_ALARM_TOOL] ⏳ Setting up promise to wait for alarm creation response...`);
|
|
287
|
-
logger.log(`[CREATE_ALARM_TOOL] - Timeout: 60 seconds`);
|
|
288
242
|
return new Promise((resolve, reject) => {
|
|
289
243
|
const timeout = setTimeout(() => {
|
|
290
|
-
logger.error(`[CREATE_ALARM_TOOL] ⏰ Timeout: No response received within 60 seconds`);
|
|
291
244
|
wsManager.off("data-event", handler);
|
|
292
245
|
reject(new Error("创建闹钟超时(60秒)"));
|
|
293
246
|
}, 60000);
|
|
294
247
|
// Listen for data events from WebSocket
|
|
295
248
|
const handler = (event) => {
|
|
296
|
-
logger.log(`[CREATE_ALARM_TOOL] 📨 Received data event:`, JSON.stringify(event));
|
|
297
249
|
if (event.intentName === "CreateAlarm") {
|
|
298
|
-
logger.log(`[CREATE_ALARM_TOOL] 🎯 CreateAlarm event received`);
|
|
299
|
-
logger.log(`[CREATE_ALARM_TOOL] - status: ${event.status}`);
|
|
300
250
|
clearTimeout(timeout);
|
|
301
251
|
wsManager.off("data-event", handler);
|
|
302
252
|
if (event.status === "success" && event.outputs) {
|
|
303
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ Alarm creation completed successfully`);
|
|
304
|
-
logger.log(`[CREATE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs));
|
|
305
253
|
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
306
254
|
resolve({
|
|
307
255
|
content: [
|
|
@@ -313,18 +261,13 @@ b. 使用该工具之前需获取当前真实时间`,
|
|
|
313
261
|
});
|
|
314
262
|
}
|
|
315
263
|
else {
|
|
316
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Alarm creation failed`);
|
|
317
|
-
logger.error(`[CREATE_ALARM_TOOL] - status: ${event.status}`);
|
|
318
|
-
logger.error(`[CREATE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
|
|
319
264
|
reject(new Error(`创建闹钟失败: ${event.status}`));
|
|
320
265
|
}
|
|
321
266
|
}
|
|
322
267
|
};
|
|
323
268
|
// Register event handler
|
|
324
|
-
logger.log(`[CREATE_ALARM_TOOL] 📡 Registering data-event handler on WebSocket manager`);
|
|
325
269
|
wsManager.on("data-event", handler);
|
|
326
270
|
// Send the command
|
|
327
|
-
logger.log(`[CREATE_ALARM_TOOL] 📤 Sending CreateAlarm command...`);
|
|
328
271
|
sendCommand({
|
|
329
272
|
config,
|
|
330
273
|
sessionId,
|
|
@@ -333,10 +276,8 @@ b. 使用该工具之前需获取当前真实时间`,
|
|
|
333
276
|
command,
|
|
334
277
|
})
|
|
335
278
|
.then(() => {
|
|
336
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ Command sent successfully, waiting for response...`);
|
|
337
279
|
})
|
|
338
280
|
.catch((error) => {
|
|
339
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Failed to send command:`, error);
|
|
340
281
|
clearTimeout(timeout);
|
|
341
282
|
wsManager.off("data-event", handler);
|
|
342
283
|
reject(error);
|
|
@@ -356,17 +297,14 @@ function parseAlarmTimeToTimestamp(alarmTime) {
|
|
|
356
297
|
const trimmed = alarmTime.trim();
|
|
357
298
|
// Check basic format (should have at least 13 characters: YYYYMMDD hhmmss)
|
|
358
299
|
if (trimmed.length < 13) {
|
|
359
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ alarmTime too short: ${trimmed}`);
|
|
360
300
|
return null;
|
|
361
301
|
}
|
|
362
302
|
// Extract date and time parts
|
|
363
303
|
// Format: YYYYMMDD hhmmss
|
|
364
304
|
const datePart = trimmed.substring(0, 8); // YYYYMMDD
|
|
365
305
|
const timePart = trimmed.substring(8).trim(); // hhmmss (may have leading space)
|
|
366
|
-
logger.log(`[CREATE_ALARM_TOOL] - datePart: ${datePart}, timePart: ${timePart}`);
|
|
367
306
|
// Validate lengths
|
|
368
307
|
if (datePart.length !== 8 || timePart.length !== 6) {
|
|
369
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid part lengths: datePart=${datePart.length}, timePart=${timePart.length}`);
|
|
370
308
|
return null;
|
|
371
309
|
}
|
|
372
310
|
// Parse components
|
|
@@ -376,45 +314,36 @@ function parseAlarmTimeToTimestamp(alarmTime) {
|
|
|
376
314
|
const hour = parseInt(timePart.substring(0, 2), 10);
|
|
377
315
|
const minute = parseInt(timePart.substring(2, 4), 10);
|
|
378
316
|
const second = parseInt(timePart.substring(4, 6), 10);
|
|
379
|
-
logger.log(`[CREATE_ALARM_TOOL] - Parsed: ${year}-${month}-${day} ${hour}:${minute}:${second}`);
|
|
380
317
|
// Validate values
|
|
381
318
|
if (isNaN(year) || isNaN(month) || isNaN(day) ||
|
|
382
319
|
isNaN(hour) || isNaN(minute) || isNaN(second)) {
|
|
383
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ NaN detected in parsed values`);
|
|
384
320
|
return null;
|
|
385
321
|
}
|
|
386
322
|
// Validate ranges
|
|
387
323
|
if (month < 1 || month > 12) {
|
|
388
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid month: ${month}`);
|
|
389
324
|
return null;
|
|
390
325
|
}
|
|
391
326
|
if (day < 1 || day > 31) {
|
|
392
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid day: ${day}`);
|
|
393
327
|
return null;
|
|
394
328
|
}
|
|
395
329
|
if (hour < 0 || hour > 23) {
|
|
396
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid hour: ${hour}`);
|
|
397
330
|
return null;
|
|
398
331
|
}
|
|
399
332
|
if (minute < 0 || minute > 59) {
|
|
400
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid minute: ${minute}`);
|
|
401
333
|
return null;
|
|
402
334
|
}
|
|
403
335
|
if (second < 0 || second > 59) {
|
|
404
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid second: ${second}`);
|
|
405
336
|
return null;
|
|
406
337
|
}
|
|
407
338
|
// Create Date object and get timestamp
|
|
408
339
|
const date = new Date(year, month - 1, day, hour, minute, second);
|
|
409
340
|
const timestamp = date.getTime();
|
|
410
341
|
if (isNaN(timestamp)) {
|
|
411
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Generated timestamp is NaN`);
|
|
412
342
|
return null;
|
|
413
343
|
}
|
|
414
344
|
return timestamp;
|
|
415
345
|
}
|
|
416
346
|
catch (error) {
|
|
417
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Exception in parseAlarmTimeToTimestamp:`, error);
|
|
418
347
|
return null;
|
|
419
348
|
}
|
|
420
349
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
3
|
import { getCurrentSessionContext } from "./session-manager.js";
|
|
4
|
-
import { logger } from "../utils/logger.js";
|
|
5
4
|
/**
|
|
6
5
|
* XY delete alarm tool - deletes existing alarms on user's device.
|
|
7
6
|
* Requires entityId(s) from search_alarm or create_alarm tool as prerequisite.
|
|
@@ -27,7 +26,9 @@ export const deleteAlarmTool = {
|
|
|
27
26
|
注意事项:
|
|
28
27
|
1. 操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。
|
|
29
28
|
2. 删除操作不可撤销,请确认 entityId 正确后再删除。
|
|
30
|
-
3. items 参数支持数组或 JSON
|
|
29
|
+
3. items 参数支持数组或 JSON 字符串格式,代码会自动解析。
|
|
30
|
+
|
|
31
|
+
回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。`,
|
|
31
32
|
parameters: {
|
|
32
33
|
type: "object",
|
|
33
34
|
properties: {
|
|
@@ -40,85 +41,57 @@ export const deleteAlarmTool = {
|
|
|
40
41
|
required: ["items"],
|
|
41
42
|
},
|
|
42
43
|
async execute(toolCallId, params) {
|
|
43
|
-
logger.log(`[DELETE_ALARM_TOOL] 🚀 Starting execution`);
|
|
44
|
-
logger.log(`[DELETE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
45
|
-
logger.log(`[DELETE_ALARM_TOOL] - params (raw):`, JSON.stringify(params));
|
|
46
|
-
logger.log(`[DELETE_ALARM_TOOL] - params.items type:`, typeof params.items);
|
|
47
|
-
logger.log(`[DELETE_ALARM_TOOL] - timestamp: ${new Date().toISOString()}`);
|
|
48
44
|
// ===== 参数规范化:兼容数组和 JSON 字符串 =====
|
|
49
45
|
let items = null;
|
|
50
46
|
if (!params.items) {
|
|
51
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Missing parameter: items`);
|
|
52
47
|
throw new Error("Missing required parameter: items");
|
|
53
48
|
}
|
|
54
49
|
// 情况1: 已经是数组
|
|
55
50
|
if (Array.isArray(params.items)) {
|
|
56
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ items is already an array`);
|
|
57
51
|
items = params.items;
|
|
58
52
|
}
|
|
59
53
|
// 情况2: 是字符串,尝试解析为 JSON 数组
|
|
60
54
|
else if (typeof params.items === 'string') {
|
|
61
|
-
logger.log(`[DELETE_ALARM_TOOL] 🔄 items is a string, attempting to parse as JSON...`);
|
|
62
55
|
try {
|
|
63
56
|
const parsed = JSON.parse(params.items);
|
|
64
57
|
if (Array.isArray(parsed)) {
|
|
65
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ Successfully parsed JSON string to array`);
|
|
66
58
|
items = parsed;
|
|
67
59
|
}
|
|
68
60
|
else {
|
|
69
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Parsed JSON is not an array:`, typeof parsed);
|
|
70
61
|
throw new Error("items must be an array or a JSON string representing an array");
|
|
71
62
|
}
|
|
72
63
|
}
|
|
73
64
|
catch (parseError) {
|
|
74
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Failed to parse items as JSON:`, parseError);
|
|
75
65
|
throw new Error(`items must be a valid JSON array string. Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
76
66
|
}
|
|
77
67
|
}
|
|
78
68
|
// 情况3: 其他类型,报错
|
|
79
69
|
else {
|
|
80
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Invalid items type:`, typeof params.items);
|
|
81
70
|
throw new Error(`items must be an array or a JSON string, got ${typeof params.items}`);
|
|
82
71
|
}
|
|
83
72
|
// 验证数组非空
|
|
84
73
|
if (!items || items.length === 0) {
|
|
85
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ items array is empty`);
|
|
86
74
|
throw new Error("items array cannot be empty");
|
|
87
75
|
}
|
|
88
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ Normalized items:`, JSON.stringify(items));
|
|
89
76
|
// 验证每个 item 是否有有效的 entityId
|
|
90
77
|
for (let i = 0; i < items.length; i++) {
|
|
91
78
|
const item = items[i];
|
|
92
79
|
if (!item || typeof item !== 'object') {
|
|
93
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Item at index ${i} is not an object`);
|
|
94
80
|
throw new Error(`items[${i}] must be an object with entityId property`);
|
|
95
81
|
}
|
|
96
82
|
if (!item.entityId || typeof item.entityId !== 'string') {
|
|
97
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Item at index ${i} missing or invalid entityId`);
|
|
98
83
|
throw new Error(`items[${i}] must have a valid entityId string property`);
|
|
99
84
|
}
|
|
100
85
|
}
|
|
101
|
-
logger.log(`[DELETE_ALARM_TOOL] - items count: ${items.length}`);
|
|
102
|
-
logger.log(`[DELETE_ALARM_TOOL] - entityIds:`, items.map(item => item.entityId).join(", "));
|
|
103
86
|
// Get session context
|
|
104
|
-
logger.log(`[DELETE_ALARM_TOOL] 🔍 Attempting to get session context...`);
|
|
105
87
|
const sessionContext = getCurrentSessionContext();
|
|
106
88
|
if (!sessionContext) {
|
|
107
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ FAILED: No active session found!`);
|
|
108
|
-
logger.error(`[DELETE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
109
89
|
throw new Error("No active XY session found. Delete alarm tool can only be used during an active conversation.");
|
|
110
90
|
}
|
|
111
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ Session context found`);
|
|
112
|
-
logger.log(`[DELETE_ALARM_TOOL] - sessionId: ${sessionContext.sessionId}`);
|
|
113
|
-
logger.log(`[DELETE_ALARM_TOOL] - taskId: ${sessionContext.taskId}`);
|
|
114
|
-
logger.log(`[DELETE_ALARM_TOOL] - messageId: ${sessionContext.messageId}`);
|
|
115
91
|
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
116
92
|
// Get WebSocket manager
|
|
117
|
-
logger.log(`[DELETE_ALARM_TOOL] 🔌 Getting WebSocket manager...`);
|
|
118
93
|
const wsManager = getXYWebSocketManager(config);
|
|
119
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ WebSocket manager obtained`);
|
|
120
94
|
// Build DeleteAlarm command
|
|
121
|
-
logger.log(`[DELETE_ALARM_TOOL] 📦 Building DeleteAlarm command...`);
|
|
122
95
|
const command = {
|
|
123
96
|
header: {
|
|
124
97
|
namespace: "Common",
|
|
@@ -153,25 +126,17 @@ export const deleteAlarmTool = {
|
|
|
153
126
|
},
|
|
154
127
|
};
|
|
155
128
|
// Send command and wait for response (60 second timeout)
|
|
156
|
-
logger.log(`[DELETE_ALARM_TOOL] ⏳ Setting up promise to wait for alarm deletion response...`);
|
|
157
|
-
logger.log(`[DELETE_ALARM_TOOL] - Timeout: 60 seconds`);
|
|
158
129
|
return new Promise((resolve, reject) => {
|
|
159
130
|
const timeout = setTimeout(() => {
|
|
160
|
-
logger.error(`[DELETE_ALARM_TOOL] ⏰ Timeout: No response received within 60 seconds`);
|
|
161
131
|
wsManager.off("data-event", handler);
|
|
162
132
|
reject(new Error("删除闹钟超时(60秒)"));
|
|
163
133
|
}, 60000);
|
|
164
134
|
// Listen for data events from WebSocket
|
|
165
135
|
const handler = (event) => {
|
|
166
|
-
logger.log(`[DELETE_ALARM_TOOL] 📨 Received data event:`, JSON.stringify(event));
|
|
167
136
|
if (event.intentName === "DeleteAlarm") {
|
|
168
|
-
logger.log(`[DELETE_ALARM_TOOL] 🎯 DeleteAlarm event received`);
|
|
169
|
-
logger.log(`[DELETE_ALARM_TOOL] - status: ${event.status}`);
|
|
170
137
|
clearTimeout(timeout);
|
|
171
138
|
wsManager.off("data-event", handler);
|
|
172
139
|
if (event.status === "success" && event.outputs) {
|
|
173
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ Alarm deletion completed successfully`);
|
|
174
|
-
logger.log(`[DELETE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs));
|
|
175
140
|
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
176
141
|
resolve({
|
|
177
142
|
content: [
|
|
@@ -183,18 +148,13 @@ export const deleteAlarmTool = {
|
|
|
183
148
|
});
|
|
184
149
|
}
|
|
185
150
|
else {
|
|
186
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Alarm deletion failed`);
|
|
187
|
-
logger.error(`[DELETE_ALARM_TOOL] - status: ${event.status}`);
|
|
188
|
-
logger.error(`[DELETE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
|
|
189
151
|
reject(new Error(`删除闹钟失败: ${event.status}`));
|
|
190
152
|
}
|
|
191
153
|
}
|
|
192
154
|
};
|
|
193
155
|
// Register event handler
|
|
194
|
-
logger.log(`[DELETE_ALARM_TOOL] 📡 Registering data-event handler on WebSocket manager`);
|
|
195
156
|
wsManager.on("data-event", handler);
|
|
196
157
|
// Send the command
|
|
197
|
-
logger.log(`[DELETE_ALARM_TOOL] 📤 Sending DeleteAlarm command...`);
|
|
198
158
|
sendCommand({
|
|
199
159
|
config,
|
|
200
160
|
sessionId,
|
|
@@ -203,10 +163,8 @@ export const deleteAlarmTool = {
|
|
|
203
163
|
command,
|
|
204
164
|
})
|
|
205
165
|
.then(() => {
|
|
206
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ Command sent successfully, waiting for response...`);
|
|
207
166
|
})
|
|
208
167
|
.catch((error) => {
|
|
209
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Failed to send command:`, error);
|
|
210
168
|
clearTimeout(timeout);
|
|
211
169
|
wsManager.off("data-event", handler);
|
|
212
170
|
reject(error);
|