@ynhcj/xiaoyi-channel 0.0.35-beta → 0.0.35-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.
- package/dist/index.d.ts +0 -2
- package/dist/index.js +42 -2
- package/dist/src/bot.js +53 -47
- package/dist/src/channel.js +24 -8
- package/dist/src/client.js +11 -33
- package/dist/src/config.js +2 -2
- package/dist/src/cspl/call-api.d.ts +3 -0
- package/dist/src/cspl/call-api.js +86 -0
- package/dist/src/cspl/config.d.ts +19 -0
- package/dist/src/cspl/config.js +50 -0
- package/dist/src/cspl/constants.d.ts +43 -0
- package/dist/src/cspl/constants.js +22 -0
- package/dist/src/cspl/utils.d.ts +10 -0
- package/dist/src/cspl/utils.js +57 -0
- package/dist/src/file-upload.d.ts +5 -0
- package/dist/src/file-upload.js +88 -6
- package/dist/src/formatter.d.ts +14 -0
- package/dist/src/formatter.js +49 -28
- package/dist/src/heartbeat.js +0 -4
- package/dist/src/monitor.js +19 -10
- package/dist/src/onboarding.d.ts +3 -4
- package/dist/src/onboarding.js +2 -2
- package/dist/src/outbound.d.ts +2 -1
- package/dist/src/outbound.js +119 -103
- package/dist/src/parser.d.ts +7 -0
- package/dist/src/parser.js +22 -0
- package/dist/src/push.d.ts +8 -1
- package/dist/src/push.js +27 -40
- package/dist/src/reply-dispatcher.d.ts +4 -0
- package/dist/src/reply-dispatcher.js +43 -7
- package/dist/src/steer-injector.d.ts +16 -0
- package/dist/src/steer-injector.js +74 -0
- package/dist/src/thread-bindings.d.ts +54 -0
- package/dist/src/thread-bindings.js +214 -0
- package/dist/src/tools/calendar-tool.js +5 -38
- package/dist/src/tools/call-phone-tool.js +1 -42
- package/dist/src/tools/create-alarm-tool.js +9 -108
- package/dist/src/tools/delete-alarm-tool.js +5 -69
- package/dist/src/tools/image-reading-tool.d.ts +5 -0
- package/dist/src/tools/image-reading-tool.js +328 -0
- package/dist/src/tools/location-tool.js +6 -40
- package/dist/src/tools/modify-alarm-tool.js +7 -113
- package/dist/src/tools/modify-note-tool.js +3 -41
- package/dist/src/tools/note-tool.js +4 -16
- package/dist/src/tools/search-alarm-tool.js +14 -118
- package/dist/src/tools/search-calendar-tool.js +8 -82
- package/dist/src/tools/search-contact-tool.js +2 -55
- package/dist/src/tools/search-file-tool.js +4 -61
- package/dist/src/tools/search-message-tool.js +2 -59
- package/dist/src/tools/search-note-tool.js +4 -22
- package/dist/src/tools/search-photo-gallery-tool.js +38 -59
- package/dist/src/tools/send-file-to-user-tool.js +1 -39
- package/dist/src/tools/send-message-tool.js +5 -56
- package/dist/src/tools/session-manager.js +0 -45
- package/dist/src/tools/timestamp-to-utc8-tool.d.ts +12 -0
- package/dist/src/tools/timestamp-to-utc8-tool.js +104 -0
- 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.d.ts +5 -0
- package/dist/src/tools/view-push-result-tool.js +107 -0
- package/dist/src/tools/xiaoyi-collection-tool.d.ts +5 -0
- package/dist/src/tools/xiaoyi-collection-tool.js +112 -0
- package/dist/src/tools/xiaoyi-gui-tool.js +0 -34
- package/dist/src/trigger-handler.d.ts +22 -0
- package/dist/src/trigger-handler.js +59 -0
- package/dist/src/types.d.ts +1 -8
- package/dist/src/types.js +4 -0
- package/dist/src/utils/pushdata-manager.d.ts +28 -0
- package/dist/src/utils/pushdata-manager.js +171 -0
- package/dist/src/utils/pushid-manager.d.ts +12 -0
- package/dist/src/utils/pushid-manager.js +105 -0
- package/dist/src/websocket.d.ts +25 -31
- package/dist/src/websocket.js +239 -271
- package/package.json +2 -2
- package/dist/src/tools/search-photo-tool.d.ts +0 -9
- package/dist/src/tools/search-photo-tool.js +0 -270
- package/dist/src/utils/session.d.ts +0 -34
- package/dist/src/utils/session.js +0 -50
|
@@ -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];
|
|
@@ -28,9 +27,13 @@ export const createAlarmTool = {
|
|
|
28
27
|
- alarmSnoozeTotal: 再响次数,枚举值:0,1,3,5,10,默认0(表示不再响)
|
|
29
28
|
- alarmRingDuration: 响铃时长(分钟),枚举值:1,5,10,15,20,30,默认5
|
|
30
29
|
- daysOfWakeType: 闹钟响铃类型,枚举值:0=单次响铃,1=法定节假日,2=每天,3=自定义时间,4=法定工作日,默认0
|
|
31
|
-
- daysOfWeek: 自定义响铃星期,仅当daysOfWakeType=3(自定义时间)时必需且有效,其他情况不要传递此参数。数组或JSON字符串,枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun
|
|
30
|
+
- daysOfWeek: 自定义响铃星期,仅当daysOfWakeType=3(自定义时间)时必需且有效,其他情况不要传递此参数。数组或JSON字符串,枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun。
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
注意事项:
|
|
33
|
+
a. 操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。
|
|
34
|
+
b. 使用该工具之前需获取当前真实时间
|
|
35
|
+
|
|
36
|
+
回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。`,
|
|
34
37
|
parameters: {
|
|
35
38
|
type: "object",
|
|
36
39
|
properties: {
|
|
@@ -61,176 +64,129 @@ export const createAlarmTool = {
|
|
|
61
64
|
daysOfWeek: {
|
|
62
65
|
// 不指定 type,允许传入数组或 JSON 字符串
|
|
63
66
|
// 具体的类型验证和转换在 execute 函数内部进行
|
|
64
|
-
description: "自定义响铃星期(仅当daysOfWakeType=3时需要,其他情况不要传递),数组或JSON字符串,枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun
|
|
67
|
+
description: "自定义响铃星期(仅当daysOfWakeType=3时需要,其他情况不要传递),数组或JSON字符串,枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun。",
|
|
65
68
|
},
|
|
66
69
|
},
|
|
67
70
|
required: ["alarmTime"],
|
|
68
71
|
},
|
|
69
72
|
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
73
|
// ===== Validate required parameter: alarmTime =====
|
|
75
74
|
if (!params.alarmTime || typeof params.alarmTime !== "string") {
|
|
76
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Missing or invalid alarmTime`);
|
|
77
75
|
throw new Error("Missing required parameter: alarmTime must be a string in format YYYYMMDD hhmmss");
|
|
78
76
|
}
|
|
79
77
|
// Parse and convert alarmTime to timestamp
|
|
80
|
-
logger.log(`[CREATE_ALARM_TOOL] 🕒 Parsing alarmTime: ${params.alarmTime}`);
|
|
81
78
|
const alarmTimeMs = parseAlarmTimeToTimestamp(params.alarmTime);
|
|
82
79
|
if (alarmTimeMs === null) {
|
|
83
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmTime format`);
|
|
84
80
|
throw new Error("Invalid alarmTime format. Required format: YYYYMMDD hhmmss (e.g., 20240315 143000)");
|
|
85
81
|
}
|
|
86
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ alarmTime converted to timestamp: ${alarmTimeMs}`);
|
|
87
82
|
// ===== Validate and set optional parameters with defaults =====
|
|
88
83
|
// alarmTitle - default to "闹钟"
|
|
89
84
|
const alarmTitle = params.alarmTitle && typeof params.alarmTitle === "string"
|
|
90
85
|
? params.alarmTitle
|
|
91
86
|
: "闹钟";
|
|
92
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmTitle: ${alarmTitle}`);
|
|
93
87
|
// alarmSnoozeDuration - default 10
|
|
94
88
|
let alarmSnoozeDuration = 10;
|
|
95
89
|
if (params.alarmSnoozeDuration !== undefined && params.alarmSnoozeDuration !== null) {
|
|
96
90
|
if (typeof params.alarmSnoozeDuration !== "number") {
|
|
97
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration type`);
|
|
98
91
|
throw new Error("alarmSnoozeDuration must be a number");
|
|
99
92
|
}
|
|
100
93
|
if (!ALARM_SNOOZE_DURATION_VALUES.includes(params.alarmSnoozeDuration)) {
|
|
101
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration value: ${params.alarmSnoozeDuration}`);
|
|
102
94
|
throw new Error(`alarmSnoozeDuration must be one of: ${ALARM_SNOOZE_DURATION_VALUES.join(", ")}`);
|
|
103
95
|
}
|
|
104
96
|
alarmSnoozeDuration = params.alarmSnoozeDuration;
|
|
105
97
|
}
|
|
106
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmSnoozeDuration: ${alarmSnoozeDuration}`);
|
|
107
98
|
// alarmSnoozeTotal - default 0
|
|
108
99
|
let alarmSnoozeTotal = 0;
|
|
109
100
|
if (params.alarmSnoozeTotal !== undefined && params.alarmSnoozeTotal !== null) {
|
|
110
101
|
if (typeof params.alarmSnoozeTotal !== "number") {
|
|
111
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal type`);
|
|
112
102
|
throw new Error("alarmSnoozeTotal must be a number");
|
|
113
103
|
}
|
|
114
104
|
if (!ALARM_SNOOZE_TOTAL_VALUES.includes(params.alarmSnoozeTotal)) {
|
|
115
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal value: ${params.alarmSnoozeTotal}`);
|
|
116
105
|
throw new Error(`alarmSnoozeTotal must be one of: ${ALARM_SNOOZE_TOTAL_VALUES.join(", ")}`);
|
|
117
106
|
}
|
|
118
107
|
alarmSnoozeTotal = params.alarmSnoozeTotal;
|
|
119
108
|
}
|
|
120
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmSnoozeTotal: ${alarmSnoozeTotal}`);
|
|
121
109
|
// alarmRingDuration - default 20
|
|
122
110
|
let alarmRingDuration = 20;
|
|
123
111
|
if (params.alarmRingDuration !== undefined && params.alarmRingDuration !== null) {
|
|
124
112
|
if (typeof params.alarmRingDuration !== "number") {
|
|
125
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmRingDuration type`);
|
|
126
113
|
throw new Error("alarmRingDuration must be a number");
|
|
127
114
|
}
|
|
128
115
|
if (!ALARM_RING_DURATION_VALUES.includes(params.alarmRingDuration)) {
|
|
129
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid alarmRingDuration value: ${params.alarmRingDuration}`);
|
|
130
116
|
throw new Error(`alarmRingDuration must be one of: ${ALARM_RING_DURATION_VALUES.join(", ")}`);
|
|
131
117
|
}
|
|
132
118
|
alarmRingDuration = params.alarmRingDuration;
|
|
133
119
|
}
|
|
134
|
-
logger.log(`[CREATE_ALARM_TOOL] - alarmRingDuration: ${alarmRingDuration}`);
|
|
135
120
|
// daysOfWakeType - default 0
|
|
136
121
|
let daysOfWakeType = 0;
|
|
137
122
|
if (params.daysOfWakeType !== undefined && params.daysOfWakeType !== null) {
|
|
138
123
|
if (typeof params.daysOfWakeType !== "number") {
|
|
139
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWakeType type`);
|
|
140
124
|
throw new Error("daysOfWakeType must be a number");
|
|
141
125
|
}
|
|
142
126
|
if (!DAYS_OF_WAKE_TYPE_VALUES.includes(params.daysOfWakeType)) {
|
|
143
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWakeType value: ${params.daysOfWakeType}`);
|
|
144
127
|
throw new Error(`daysOfWakeType must be one of: ${DAYS_OF_WAKE_TYPE_VALUES.join(", ")}`);
|
|
145
128
|
}
|
|
146
129
|
daysOfWakeType = params.daysOfWakeType;
|
|
147
130
|
}
|
|
148
|
-
logger.log(`[CREATE_ALARM_TOOL] - daysOfWakeType: ${daysOfWakeType}`);
|
|
149
131
|
// daysOfWeek - only required when daysOfWakeType is 3
|
|
150
132
|
let daysOfWeek = [];
|
|
151
133
|
if (daysOfWakeType === 3) {
|
|
152
134
|
if (!params.daysOfWeek) {
|
|
153
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Missing daysOfWeek when daysOfWakeType=3`);
|
|
154
135
|
throw new Error("daysOfWeek is required when daysOfWakeType is 3 (custom)");
|
|
155
136
|
}
|
|
156
137
|
// ===== 参数规范化:兼容数组和 JSON 字符串 =====
|
|
157
138
|
let normalizedDaysOfWeek = null;
|
|
158
139
|
// 情况1: 已经是数组
|
|
159
140
|
if (Array.isArray(params.daysOfWeek)) {
|
|
160
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ daysOfWeek is already an array`);
|
|
161
141
|
normalizedDaysOfWeek = params.daysOfWeek;
|
|
162
142
|
}
|
|
163
143
|
// 情况2: 是字符串,尝试解析为 JSON 数组
|
|
164
144
|
else if (typeof params.daysOfWeek === 'string') {
|
|
165
|
-
logger.log(`[CREATE_ALARM_TOOL] 🔄 daysOfWeek is a string, attempting to parse as JSON...`);
|
|
166
145
|
try {
|
|
167
146
|
const parsed = JSON.parse(params.daysOfWeek);
|
|
168
147
|
if (Array.isArray(parsed)) {
|
|
169
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ Successfully parsed JSON string to array`);
|
|
170
148
|
normalizedDaysOfWeek = parsed;
|
|
171
149
|
}
|
|
172
150
|
else {
|
|
173
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Parsed JSON is not an array:`, typeof parsed);
|
|
174
151
|
throw new Error("daysOfWeek must be an array or a JSON string representing an array");
|
|
175
152
|
}
|
|
176
153
|
}
|
|
177
154
|
catch (parseError) {
|
|
178
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Failed to parse daysOfWeek as JSON:`, parseError);
|
|
179
155
|
throw new Error(`daysOfWeek must be a valid JSON array string. Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
180
156
|
}
|
|
181
157
|
}
|
|
182
158
|
// 情况3: 其他类型,报错
|
|
183
159
|
else {
|
|
184
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid daysOfWeek type:`, typeof params.daysOfWeek);
|
|
185
160
|
throw new Error(`daysOfWeek must be an array or a JSON string, got ${typeof params.daysOfWeek}`);
|
|
186
161
|
}
|
|
187
162
|
// 验证数组非空
|
|
188
163
|
if (!normalizedDaysOfWeek || normalizedDaysOfWeek.length === 0) {
|
|
189
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ daysOfWeek array is empty`);
|
|
190
164
|
throw new Error("daysOfWeek array cannot be empty");
|
|
191
165
|
}
|
|
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
166
|
// Validate each day
|
|
198
167
|
for (const day of normalizedDaysOfWeek) {
|
|
199
168
|
if (typeof day !== "string" || !DAYS_OF_WEEK_VALUES.includes(day)) {
|
|
200
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid day value: ${day}`);
|
|
201
169
|
throw new Error(`daysOfWeek must contain only: ${DAYS_OF_WEEK_VALUES.join(", ")}`);
|
|
202
170
|
}
|
|
203
171
|
}
|
|
204
172
|
daysOfWeek = normalizedDaysOfWeek;
|
|
205
|
-
logger.log(`[CREATE_ALARM_TOOL] - daysOfWeek: ${daysOfWeek.join(", ")}`);
|
|
206
173
|
}
|
|
207
174
|
else {
|
|
208
175
|
// daysOfWakeType is not 3, daysOfWeek should not be provided
|
|
209
176
|
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
177
|
}
|
|
212
178
|
// Explicitly set to empty array
|
|
213
179
|
daysOfWeek = [];
|
|
214
180
|
}
|
|
215
181
|
// Get session context
|
|
216
|
-
logger.log(`[CREATE_ALARM_TOOL] 🔍 Attempting to get session context...`);
|
|
217
182
|
const sessionContext = getCurrentSessionContext();
|
|
218
183
|
if (!sessionContext) {
|
|
219
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ FAILED: No active session found!`);
|
|
220
|
-
logger.error(`[CREATE_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
221
184
|
throw new Error("No active XY session found. Create alarm tool can only be used during an active conversation.");
|
|
222
185
|
}
|
|
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
186
|
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
228
187
|
// Get WebSocket manager
|
|
229
|
-
logger.log(`[CREATE_ALARM_TOOL] 🔌 Getting WebSocket manager...`);
|
|
230
188
|
const wsManager = getXYWebSocketManager(config);
|
|
231
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ WebSocket manager obtained`);
|
|
232
189
|
// Build CreateAlarm command
|
|
233
|
-
logger.log(`[CREATE_ALARM_TOOL] 📦 Building CreateAlarm command...`);
|
|
234
190
|
// Build intentParam - only include daysOfWeek when daysOfWakeType is 3
|
|
235
191
|
const intentParam = {
|
|
236
192
|
entityName: "Alarm",
|
|
@@ -244,10 +200,8 @@ export const createAlarmTool = {
|
|
|
244
200
|
// Only include daysOfWeek when daysOfWakeType is 3
|
|
245
201
|
if (daysOfWakeType === 3 && daysOfWeek.length > 0) {
|
|
246
202
|
intentParam.daysOfWeek = daysOfWeek;
|
|
247
|
-
logger.log(`[CREATE_ALARM_TOOL] - Including daysOfWeek in intentParam: ${daysOfWeek.join(", ")}`);
|
|
248
203
|
}
|
|
249
204
|
else {
|
|
250
|
-
logger.log(`[CREATE_ALARM_TOOL] - Excluding daysOfWeek from intentParam (daysOfWakeType=${daysOfWakeType})`);
|
|
251
205
|
}
|
|
252
206
|
const command = {
|
|
253
207
|
header: {
|
|
@@ -281,74 +235,35 @@ export const createAlarmTool = {
|
|
|
281
235
|
},
|
|
282
236
|
};
|
|
283
237
|
// 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
238
|
return new Promise((resolve, reject) => {
|
|
287
239
|
const timeout = setTimeout(() => {
|
|
288
|
-
logger.error(`[CREATE_ALARM_TOOL] ⏰ Timeout: No response received within 60 seconds`);
|
|
289
240
|
wsManager.off("data-event", handler);
|
|
290
241
|
reject(new Error("创建闹钟超时(60秒)"));
|
|
291
242
|
}, 60000);
|
|
292
243
|
// Listen for data events from WebSocket
|
|
293
244
|
const handler = (event) => {
|
|
294
|
-
logger.log(`[CREATE_ALARM_TOOL] 📨 Received data event:`, JSON.stringify(event));
|
|
295
245
|
if (event.intentName === "CreateAlarm") {
|
|
296
|
-
logger.log(`[CREATE_ALARM_TOOL] 🎯 CreateAlarm event received`);
|
|
297
|
-
logger.log(`[CREATE_ALARM_TOOL] - status: ${event.status}`);
|
|
298
246
|
clearTimeout(timeout);
|
|
299
247
|
wsManager.off("data-event", handler);
|
|
300
248
|
if (event.status === "success" && event.outputs) {
|
|
301
|
-
|
|
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));
|
|
249
|
+
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
316
250
|
resolve({
|
|
317
251
|
content: [
|
|
318
252
|
{
|
|
319
253
|
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
|
-
}),
|
|
254
|
+
text: JSON.stringify(event.outputs),
|
|
335
255
|
},
|
|
336
256
|
],
|
|
337
257
|
});
|
|
338
258
|
}
|
|
339
259
|
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
260
|
reject(new Error(`创建闹钟失败: ${event.status}`));
|
|
344
261
|
}
|
|
345
262
|
}
|
|
346
263
|
};
|
|
347
264
|
// Register event handler
|
|
348
|
-
logger.log(`[CREATE_ALARM_TOOL] 📡 Registering data-event handler on WebSocket manager`);
|
|
349
265
|
wsManager.on("data-event", handler);
|
|
350
266
|
// Send the command
|
|
351
|
-
logger.log(`[CREATE_ALARM_TOOL] 📤 Sending CreateAlarm command...`);
|
|
352
267
|
sendCommand({
|
|
353
268
|
config,
|
|
354
269
|
sessionId,
|
|
@@ -357,10 +272,8 @@ export const createAlarmTool = {
|
|
|
357
272
|
command,
|
|
358
273
|
})
|
|
359
274
|
.then(() => {
|
|
360
|
-
logger.log(`[CREATE_ALARM_TOOL] ✅ Command sent successfully, waiting for response...`);
|
|
361
275
|
})
|
|
362
276
|
.catch((error) => {
|
|
363
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Failed to send command:`, error);
|
|
364
277
|
clearTimeout(timeout);
|
|
365
278
|
wsManager.off("data-event", handler);
|
|
366
279
|
reject(error);
|
|
@@ -380,17 +293,14 @@ function parseAlarmTimeToTimestamp(alarmTime) {
|
|
|
380
293
|
const trimmed = alarmTime.trim();
|
|
381
294
|
// Check basic format (should have at least 13 characters: YYYYMMDD hhmmss)
|
|
382
295
|
if (trimmed.length < 13) {
|
|
383
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ alarmTime too short: ${trimmed}`);
|
|
384
296
|
return null;
|
|
385
297
|
}
|
|
386
298
|
// Extract date and time parts
|
|
387
299
|
// Format: YYYYMMDD hhmmss
|
|
388
300
|
const datePart = trimmed.substring(0, 8); // YYYYMMDD
|
|
389
301
|
const timePart = trimmed.substring(8).trim(); // hhmmss (may have leading space)
|
|
390
|
-
logger.log(`[CREATE_ALARM_TOOL] - datePart: ${datePart}, timePart: ${timePart}`);
|
|
391
302
|
// Validate lengths
|
|
392
303
|
if (datePart.length !== 8 || timePart.length !== 6) {
|
|
393
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid part lengths: datePart=${datePart.length}, timePart=${timePart.length}`);
|
|
394
304
|
return null;
|
|
395
305
|
}
|
|
396
306
|
// Parse components
|
|
@@ -400,45 +310,36 @@ function parseAlarmTimeToTimestamp(alarmTime) {
|
|
|
400
310
|
const hour = parseInt(timePart.substring(0, 2), 10);
|
|
401
311
|
const minute = parseInt(timePart.substring(2, 4), 10);
|
|
402
312
|
const second = parseInt(timePart.substring(4, 6), 10);
|
|
403
|
-
logger.log(`[CREATE_ALARM_TOOL] - Parsed: ${year}-${month}-${day} ${hour}:${minute}:${second}`);
|
|
404
313
|
// Validate values
|
|
405
314
|
if (isNaN(year) || isNaN(month) || isNaN(day) ||
|
|
406
315
|
isNaN(hour) || isNaN(minute) || isNaN(second)) {
|
|
407
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ NaN detected in parsed values`);
|
|
408
316
|
return null;
|
|
409
317
|
}
|
|
410
318
|
// Validate ranges
|
|
411
319
|
if (month < 1 || month > 12) {
|
|
412
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid month: ${month}`);
|
|
413
320
|
return null;
|
|
414
321
|
}
|
|
415
322
|
if (day < 1 || day > 31) {
|
|
416
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid day: ${day}`);
|
|
417
323
|
return null;
|
|
418
324
|
}
|
|
419
325
|
if (hour < 0 || hour > 23) {
|
|
420
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid hour: ${hour}`);
|
|
421
326
|
return null;
|
|
422
327
|
}
|
|
423
328
|
if (minute < 0 || minute > 59) {
|
|
424
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid minute: ${minute}`);
|
|
425
329
|
return null;
|
|
426
330
|
}
|
|
427
331
|
if (second < 0 || second > 59) {
|
|
428
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Invalid second: ${second}`);
|
|
429
332
|
return null;
|
|
430
333
|
}
|
|
431
334
|
// Create Date object and get timestamp
|
|
432
335
|
const date = new Date(year, month - 1, day, hour, minute, second);
|
|
433
336
|
const timestamp = date.getTime();
|
|
434
337
|
if (isNaN(timestamp)) {
|
|
435
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Generated timestamp is NaN`);
|
|
436
338
|
return null;
|
|
437
339
|
}
|
|
438
340
|
return timestamp;
|
|
439
341
|
}
|
|
440
342
|
catch (error) {
|
|
441
|
-
logger.error(`[CREATE_ALARM_TOOL] ❌ Exception in parseAlarmTimeToTimestamp:`, error);
|
|
442
343
|
return null;
|
|
443
344
|
}
|
|
444
345
|
}
|
|
@@ -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,70 +126,35 @@ 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
|
-
|
|
174
|
-
logger.log(`[DELETE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs));
|
|
175
|
-
// Check for error code in outputs
|
|
176
|
-
const code = event.outputs.code !== undefined ? event.outputs.code : null;
|
|
177
|
-
if (code !== null && code !== 0) {
|
|
178
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Device returned error`);
|
|
179
|
-
logger.error(`[DELETE_ALARM_TOOL] - code: ${code}`);
|
|
180
|
-
const errorMsg = event.outputs.errorMsg || event.outputs.errMsg || "未知错误";
|
|
181
|
-
logger.error(`[DELETE_ALARM_TOOL] - errorMsg: ${errorMsg}`);
|
|
182
|
-
reject(new Error(`删除闹钟失败: ${errorMsg} (错误代码: ${code})`));
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
// Extract result with safe navigation
|
|
186
|
-
const result = event.outputs.result || {};
|
|
187
|
-
logger.log(`[DELETE_ALARM_TOOL] 📋 Deletion result:`, JSON.stringify(result));
|
|
188
|
-
// Build response with safe navigation
|
|
189
|
-
const response = {
|
|
190
|
-
success: true,
|
|
191
|
-
entityName: result.entityName || "Alarm",
|
|
192
|
-
message: result.message || "Alarm deleted successfully",
|
|
193
|
-
deletedCount: items.length,
|
|
194
|
-
};
|
|
195
|
-
// Add entityIds from request for reference
|
|
196
|
-
response.deletedIds = items.map(item => item.entityId);
|
|
197
|
-
logger.log(`[DELETE_ALARM_TOOL] 🎉 Successfully deleted ${items.length} alarm(s)`);
|
|
140
|
+
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
198
141
|
resolve({
|
|
199
142
|
content: [
|
|
200
143
|
{
|
|
201
144
|
type: "text",
|
|
202
|
-
text: JSON.stringify(
|
|
145
|
+
text: JSON.stringify(event.outputs),
|
|
203
146
|
},
|
|
204
147
|
],
|
|
205
148
|
});
|
|
206
149
|
}
|
|
207
150
|
else {
|
|
208
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Alarm deletion failed`);
|
|
209
|
-
logger.error(`[DELETE_ALARM_TOOL] - status: ${event.status}`);
|
|
210
|
-
logger.error(`[DELETE_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
|
|
211
151
|
reject(new Error(`删除闹钟失败: ${event.status}`));
|
|
212
152
|
}
|
|
213
153
|
}
|
|
214
154
|
};
|
|
215
155
|
// Register event handler
|
|
216
|
-
logger.log(`[DELETE_ALARM_TOOL] 📡 Registering data-event handler on WebSocket manager`);
|
|
217
156
|
wsManager.on("data-event", handler);
|
|
218
157
|
// Send the command
|
|
219
|
-
logger.log(`[DELETE_ALARM_TOOL] 📤 Sending DeleteAlarm command...`);
|
|
220
158
|
sendCommand({
|
|
221
159
|
config,
|
|
222
160
|
sessionId,
|
|
@@ -225,10 +163,8 @@ export const deleteAlarmTool = {
|
|
|
225
163
|
command,
|
|
226
164
|
})
|
|
227
165
|
.then(() => {
|
|
228
|
-
logger.log(`[DELETE_ALARM_TOOL] ✅ Command sent successfully, waiting for response...`);
|
|
229
166
|
})
|
|
230
167
|
.catch((error) => {
|
|
231
|
-
logger.error(`[DELETE_ALARM_TOOL] ❌ Failed to send command:`, error);
|
|
232
168
|
clearTimeout(timeout);
|
|
233
169
|
wsManager.off("data-event", handler);
|
|
234
170
|
reject(error);
|