@ynhcj/xiaoyi-channel 0.0.44-beta → 0.0.44-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.d.ts +1 -0
- package/dist/src/bot.js +59 -61
- package/dist/src/channel.js +30 -4
- package/dist/src/client.js +0 -9
- 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 +2 -0
- package/dist/src/formatter.js +13 -30
- package/dist/src/heartbeat.js +0 -4
- package/dist/src/monitor.js +8 -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 +1 -19
- package/dist/src/parser.d.ts +6 -0
- package/dist/src/parser.js +16 -0
- package/dist/src/push.js +0 -21
- package/dist/src/reply-dispatcher.d.ts +4 -0
- package/dist/src/reply-dispatcher.js +46 -8
- 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 +2 -37
- package/dist/src/tools/call-phone-tool.js +3 -60
- package/dist/src/tools/create-alarm-tool.js +8 -109
- package/dist/src/tools/delete-alarm-tool.js +5 -69
- package/dist/src/tools/device-tool-map.d.ts +4 -0
- package/dist/src/tools/device-tool-map.js +24 -0
- 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 +8 -114
- 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 +12 -118
- package/dist/src/tools/search-calendar-tool.js +4 -81
- 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 +8 -57
- package/dist/src/tools/send-command-to-car-tool.d.ts +5 -0
- package/dist/src/tools/send-command-to-car-tool.js +85 -0
- 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.d.ts +1 -0
- 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.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/utils/runtime-manager.d.ts +7 -0
- package/dist/src/utils/runtime-manager.js +42 -0
- package/dist/src/websocket.js +33 -13
- package/package.json +3 -4
- 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,13 +1,12 @@
|
|
|
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 (same as create-alarm-tool)
|
|
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];
|
|
8
7
|
const ALARM_RING_DURATION_VALUES = [1, 5, 10, 15, 20, 30];
|
|
9
8
|
const DAYS_OF_WAKE_TYPE_VALUES = [0, 1, 2, 3, 4];
|
|
10
|
-
const DAYS_OF_WEEK_VALUES = ["Mon", "
|
|
9
|
+
const DAYS_OF_WEEK_VALUES = ["Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"];
|
|
11
10
|
/**
|
|
12
11
|
* XY modify alarm tool - modifies an existing alarm on user's device.
|
|
13
12
|
* Requires entityId from search_alarm or create_alarm tool.
|
|
@@ -32,14 +31,16 @@ export const modifyAlarmTool = {
|
|
|
32
31
|
- alarmSnoozeTotal: 再响次数,枚举值:0,1,3,5,10
|
|
33
32
|
- alarmRingDuration: 响铃时长(分钟),枚举值:1,5,10,15,20,30
|
|
34
33
|
- daysOfWakeType: 闹钟响铃类型,枚举值:0=单次,1=法定节假日,2=每天,3=自定义,4=法定工作日
|
|
35
|
-
- daysOfWeek: 自定义响铃星期,仅当daysOfWakeType=3(自定义时间)时必需且有效,其他情况不要传递此参数。数组或JSON字符串,枚举值:Mon,
|
|
34
|
+
- daysOfWeek: 自定义响铃星期,仅当daysOfWakeType=3(自定义时间)时必需且有效,其他情况不要传递此参数。数组或JSON字符串,枚举值:Mon,Tues,Wed,Thur,Fri,Sat,Sun。
|
|
36
35
|
|
|
37
36
|
使用流程:
|
|
38
37
|
1. 先调用 search_alarm 工具查询闹钟,获取 entityId,
|
|
39
38
|
2. 调用此工具修改闹钟,传入 entityId 和需要修改的参数
|
|
40
39
|
3. 其余不涉及需改的参数,如果search_alarm 或 create_alarm的结果中有相应的值,需要一并填上,需要与原有的保持一致,防止不填采用默认值
|
|
41
40
|
|
|
42
|
-
注意事项:操作超时时间为60
|
|
41
|
+
注意事项:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。
|
|
42
|
+
|
|
43
|
+
回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。`,
|
|
43
44
|
parameters: {
|
|
44
45
|
type: "object",
|
|
45
46
|
properties: {
|
|
@@ -78,22 +79,16 @@ export const modifyAlarmTool = {
|
|
|
78
79
|
daysOfWeek: {
|
|
79
80
|
// 不指定 type,允许传入数组或 JSON 字符串
|
|
80
81
|
// 具体的类型验证和转换在 execute 函数内部进行
|
|
81
|
-
description: "自定义响铃星期(仅当daysOfWakeType=3时需要,其他情况不要传递),数组或JSON字符串,枚举值:Mon,
|
|
82
|
+
description: "自定义响铃星期(仅当daysOfWakeType=3时需要,其他情况不要传递),数组或JSON字符串,枚举值:Mon,Tues,Wed,Thur,Fri,Sat,Sun。",
|
|
82
83
|
},
|
|
83
84
|
},
|
|
84
85
|
required: ["entityId"],
|
|
85
86
|
},
|
|
86
87
|
async execute(toolCallId, params) {
|
|
87
|
-
logger.log(`[MODIFY_ALARM_TOOL] 🚀 Starting execution`);
|
|
88
|
-
logger.log(`[MODIFY_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
89
|
-
logger.log(`[MODIFY_ALARM_TOOL] - params:`, JSON.stringify(params));
|
|
90
|
-
logger.log(`[MODIFY_ALARM_TOOL] - timestamp: ${new Date().toISOString()}`);
|
|
91
88
|
// ===== Validate required parameter: entityId =====
|
|
92
89
|
if (!params.entityId || typeof params.entityId !== "string") {
|
|
93
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Missing or invalid entityId`);
|
|
94
90
|
throw new Error("Missing required parameter: entityId must be a string obtained from search_alarm or create_alarm");
|
|
95
91
|
}
|
|
96
|
-
logger.log(`[MODIFY_ALARM_TOOL] - entityId: ${params.entityId}`);
|
|
97
92
|
// ===== Build intentParam with provided parameters =====
|
|
98
93
|
const intentParam = {
|
|
99
94
|
entityName: "Alarm",
|
|
@@ -102,98 +97,76 @@ export const modifyAlarmTool = {
|
|
|
102
97
|
// Parse and convert alarmTime if provided
|
|
103
98
|
if (params.alarmTime !== undefined && params.alarmTime !== null) {
|
|
104
99
|
if (typeof params.alarmTime !== "string") {
|
|
105
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmTime type`);
|
|
106
100
|
throw new Error("alarmTime must be a string in format YYYYMMDD hhmmss");
|
|
107
101
|
}
|
|
108
|
-
logger.log(`[MODIFY_ALARM_TOOL] 🕒 Parsing alarmTime: ${params.alarmTime}`);
|
|
109
102
|
const alarmTimeMs = parseAlarmTimeToTimestamp(params.alarmTime);
|
|
110
103
|
if (alarmTimeMs === null) {
|
|
111
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmTime format`);
|
|
112
104
|
throw new Error("Invalid alarmTime format. Required format: YYYYMMDD hhmmss (e.g., 20240315 143000)");
|
|
113
105
|
}
|
|
114
106
|
intentParam.alarmTime = alarmTimeMs;
|
|
115
|
-
logger.log(`[MODIFY_ALARM_TOOL] ✅ alarmTime converted to timestamp: ${alarmTimeMs}`);
|
|
116
107
|
}
|
|
117
108
|
// Add alarmTitle if provided
|
|
118
109
|
if (params.alarmTitle !== undefined && params.alarmTitle !== null) {
|
|
119
110
|
if (typeof params.alarmTitle !== "string") {
|
|
120
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmTitle type`);
|
|
121
111
|
throw new Error("alarmTitle must be a string");
|
|
122
112
|
}
|
|
123
113
|
intentParam.alarmTitle = params.alarmTitle;
|
|
124
|
-
logger.log(`[MODIFY_ALARM_TOOL] - alarmTitle: ${params.alarmTitle}`);
|
|
125
114
|
}
|
|
126
115
|
// Add alarmState if provided
|
|
127
116
|
if (params.alarmState !== undefined && params.alarmState !== null) {
|
|
128
117
|
if (typeof params.alarmState !== "number") {
|
|
129
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmState type`);
|
|
130
118
|
throw new Error("alarmState must be a number");
|
|
131
119
|
}
|
|
132
120
|
if (!ALARM_STATE_VALUES.includes(params.alarmState)) {
|
|
133
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmState value: ${params.alarmState}`);
|
|
134
121
|
throw new Error(`alarmState must be one of: ${ALARM_STATE_VALUES.join(", ")}`);
|
|
135
122
|
}
|
|
136
123
|
intentParam.alarmState = params.alarmState;
|
|
137
|
-
logger.log(`[MODIFY_ALARM_TOOL] - alarmState: ${params.alarmState}`);
|
|
138
124
|
}
|
|
139
125
|
// Add alarmSnoozeDuration if provided
|
|
140
126
|
if (params.alarmSnoozeDuration !== undefined && params.alarmSnoozeDuration !== null) {
|
|
141
127
|
if (typeof params.alarmSnoozeDuration !== "number") {
|
|
142
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration type`);
|
|
143
128
|
throw new Error("alarmSnoozeDuration must be a number");
|
|
144
129
|
}
|
|
145
130
|
if (!ALARM_SNOOZE_DURATION_VALUES.includes(params.alarmSnoozeDuration)) {
|
|
146
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmSnoozeDuration value: ${params.alarmSnoozeDuration}`);
|
|
147
131
|
throw new Error(`alarmSnoozeDuration must be one of: ${ALARM_SNOOZE_DURATION_VALUES.join(", ")}`);
|
|
148
132
|
}
|
|
149
133
|
intentParam.alarmSnoozeDuration = params.alarmSnoozeDuration;
|
|
150
|
-
logger.log(`[MODIFY_ALARM_TOOL] - alarmSnoozeDuration: ${params.alarmSnoozeDuration}`);
|
|
151
134
|
}
|
|
152
135
|
// Add alarmSnoozeTotal if provided
|
|
153
136
|
if (params.alarmSnoozeTotal !== undefined && params.alarmSnoozeTotal !== null) {
|
|
154
137
|
if (typeof params.alarmSnoozeTotal !== "number") {
|
|
155
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal type`);
|
|
156
138
|
throw new Error("alarmSnoozeTotal must be a number");
|
|
157
139
|
}
|
|
158
140
|
if (!ALARM_SNOOZE_TOTAL_VALUES.includes(params.alarmSnoozeTotal)) {
|
|
159
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmSnoozeTotal value: ${params.alarmSnoozeTotal}`);
|
|
160
141
|
throw new Error(`alarmSnoozeTotal must be one of: ${ALARM_SNOOZE_TOTAL_VALUES.join(", ")}`);
|
|
161
142
|
}
|
|
162
143
|
intentParam.alarmSnoozeTotal = params.alarmSnoozeTotal;
|
|
163
|
-
logger.log(`[MODIFY_ALARM_TOOL] - alarmSnoozeTotal: ${params.alarmSnoozeTotal}`);
|
|
164
144
|
}
|
|
165
145
|
// Add alarmRingDuration if provided
|
|
166
146
|
if (params.alarmRingDuration !== undefined && params.alarmRingDuration !== null) {
|
|
167
147
|
if (typeof params.alarmRingDuration !== "number") {
|
|
168
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmRingDuration type`);
|
|
169
148
|
throw new Error("alarmRingDuration must be a number");
|
|
170
149
|
}
|
|
171
150
|
if (!ALARM_RING_DURATION_VALUES.includes(params.alarmRingDuration)) {
|
|
172
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid alarmRingDuration value: ${params.alarmRingDuration}`);
|
|
173
151
|
throw new Error(`alarmRingDuration must be one of: ${ALARM_RING_DURATION_VALUES.join(", ")}`);
|
|
174
152
|
}
|
|
175
153
|
intentParam.alarmRingDuration = params.alarmRingDuration;
|
|
176
|
-
logger.log(`[MODIFY_ALARM_TOOL] - alarmRingDuration: ${params.alarmRingDuration}`);
|
|
177
154
|
}
|
|
178
155
|
// Add daysOfWakeType if provided
|
|
179
156
|
if (params.daysOfWakeType !== undefined && params.daysOfWakeType !== null) {
|
|
180
157
|
if (typeof params.daysOfWakeType !== "number") {
|
|
181
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid daysOfWakeType type`);
|
|
182
158
|
throw new Error("daysOfWakeType must be a number");
|
|
183
159
|
}
|
|
184
160
|
if (!DAYS_OF_WAKE_TYPE_VALUES.includes(params.daysOfWakeType)) {
|
|
185
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid daysOfWakeType value: ${params.daysOfWakeType}`);
|
|
186
161
|
throw new Error(`daysOfWakeType must be one of: ${DAYS_OF_WAKE_TYPE_VALUES.join(", ")}`);
|
|
187
162
|
}
|
|
188
163
|
intentParam.daysOfWakeType = params.daysOfWakeType;
|
|
189
|
-
logger.log(`[MODIFY_ALARM_TOOL] - daysOfWakeType: ${params.daysOfWakeType}`);
|
|
190
164
|
}
|
|
191
165
|
// Add daysOfWeek if provided - only valid when daysOfWakeType is 3
|
|
192
166
|
if (params.daysOfWeek !== undefined && params.daysOfWeek !== null) {
|
|
193
167
|
// Check if daysOfWakeType is 3 or will be set to 3
|
|
194
168
|
const targetDaysOfWakeType = params.daysOfWakeType !== undefined ? params.daysOfWakeType : null;
|
|
195
169
|
if (targetDaysOfWakeType !== null && targetDaysOfWakeType !== 3) {
|
|
196
|
-
logger.warn(`[MODIFY_ALARM_TOOL] ⚠️ daysOfWeek parameter is ignored when daysOfWakeType is not 3 (current: ${targetDaysOfWakeType}). Please remove daysOfWeek parameter.`);
|
|
197
170
|
// Skip processing daysOfWeek when daysOfWakeType is not 3
|
|
198
171
|
}
|
|
199
172
|
else {
|
|
@@ -201,73 +174,49 @@ export const modifyAlarmTool = {
|
|
|
201
174
|
let normalizedDaysOfWeek = null;
|
|
202
175
|
// 情况1: 已经是数组
|
|
203
176
|
if (Array.isArray(params.daysOfWeek)) {
|
|
204
|
-
logger.log(`[MODIFY_ALARM_TOOL] ✅ daysOfWeek is already an array`);
|
|
205
177
|
normalizedDaysOfWeek = params.daysOfWeek;
|
|
206
178
|
}
|
|
207
179
|
// 情况2: 是字符串,尝试解析为 JSON 数组
|
|
208
180
|
else if (typeof params.daysOfWeek === 'string') {
|
|
209
|
-
logger.log(`[MODIFY_ALARM_TOOL] 🔄 daysOfWeek is a string, attempting to parse as JSON...`);
|
|
210
181
|
try {
|
|
211
182
|
const parsed = JSON.parse(params.daysOfWeek);
|
|
212
183
|
if (Array.isArray(parsed)) {
|
|
213
|
-
logger.log(`[MODIFY_ALARM_TOOL] ✅ Successfully parsed JSON string to array`);
|
|
214
184
|
normalizedDaysOfWeek = parsed;
|
|
215
185
|
}
|
|
216
186
|
else {
|
|
217
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Parsed JSON is not an array:`, typeof parsed);
|
|
218
187
|
throw new Error("daysOfWeek must be an array or a JSON string representing an array");
|
|
219
188
|
}
|
|
220
189
|
}
|
|
221
190
|
catch (parseError) {
|
|
222
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Failed to parse daysOfWeek as JSON:`, parseError);
|
|
223
191
|
throw new Error(`daysOfWeek must be a valid JSON array string. Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
224
192
|
}
|
|
225
193
|
}
|
|
226
194
|
// 情况3: 其他类型,报错
|
|
227
195
|
else {
|
|
228
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid daysOfWeek type:`, typeof params.daysOfWeek);
|
|
229
196
|
throw new Error(`daysOfWeek must be an array or a JSON string, got ${typeof params.daysOfWeek}`);
|
|
230
197
|
}
|
|
231
198
|
// 验证数组非空
|
|
232
199
|
if (!normalizedDaysOfWeek || normalizedDaysOfWeek.length === 0) {
|
|
233
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ daysOfWeek array is empty`);
|
|
234
200
|
throw new Error("daysOfWeek array cannot be empty");
|
|
235
201
|
}
|
|
236
|
-
// 验证数组长度必须为1
|
|
237
|
-
if (normalizedDaysOfWeek.length !== 1) {
|
|
238
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ daysOfWeek array length must be 1, got ${normalizedDaysOfWeek.length}`);
|
|
239
|
-
throw new Error("daysOfWeek 仅支持长度为1的数组。如果需要一周中不同的几天,需要多次调用此工具");
|
|
240
|
-
}
|
|
241
202
|
// Validate each day
|
|
242
203
|
for (const day of normalizedDaysOfWeek) {
|
|
243
204
|
if (typeof day !== "string" || !DAYS_OF_WEEK_VALUES.includes(day)) {
|
|
244
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid day value: ${day}`);
|
|
245
205
|
throw new Error(`daysOfWeek must contain only: ${DAYS_OF_WEEK_VALUES.join(", ")}`);
|
|
246
206
|
}
|
|
247
207
|
}
|
|
248
208
|
intentParam.daysOfWeek = normalizedDaysOfWeek;
|
|
249
|
-
logger.log(`[MODIFY_ALARM_TOOL] - daysOfWeek: ${normalizedDaysOfWeek.join(", ")}`);
|
|
250
209
|
}
|
|
251
210
|
}
|
|
252
211
|
// Get session context
|
|
253
|
-
logger.log(`[MODIFY_ALARM_TOOL] 🔍 Attempting to get session context...`);
|
|
254
212
|
const sessionContext = getCurrentSessionContext();
|
|
255
213
|
if (!sessionContext) {
|
|
256
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ FAILED: No active session found!`);
|
|
257
|
-
logger.error(`[MODIFY_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
258
214
|
throw new Error("No active XY session found. Modify alarm tool can only be used during an active conversation.");
|
|
259
215
|
}
|
|
260
|
-
logger.log(`[MODIFY_ALARM_TOOL] ✅ Session context found`);
|
|
261
|
-
logger.log(`[MODIFY_ALARM_TOOL] - sessionId: ${sessionContext.sessionId}`);
|
|
262
|
-
logger.log(`[MODIFY_ALARM_TOOL] - taskId: ${sessionContext.taskId}`);
|
|
263
|
-
logger.log(`[MODIFY_ALARM_TOOL] - messageId: ${sessionContext.messageId}`);
|
|
264
216
|
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
265
217
|
// Get WebSocket manager
|
|
266
|
-
logger.log(`[MODIFY_ALARM_TOOL] 🔌 Getting WebSocket manager...`);
|
|
267
218
|
const wsManager = getXYWebSocketManager(config);
|
|
268
|
-
logger.log(`[MODIFY_ALARM_TOOL] ✅ WebSocket manager obtained`);
|
|
269
219
|
// Build ModifyAlarm command
|
|
270
|
-
logger.log(`[MODIFY_ALARM_TOOL] 📦 Building ModifyAlarm command...`);
|
|
271
220
|
const command = {
|
|
272
221
|
header: {
|
|
273
222
|
namespace: "Common",
|
|
@@ -300,76 +249,35 @@ export const modifyAlarmTool = {
|
|
|
300
249
|
},
|
|
301
250
|
};
|
|
302
251
|
// Send command and wait for response (60 second timeout)
|
|
303
|
-
logger.log(`[MODIFY_ALARM_TOOL] ⏳ Setting up promise to wait for alarm modification response...`);
|
|
304
|
-
logger.log(`[MODIFY_ALARM_TOOL] - Timeout: 60 seconds`);
|
|
305
252
|
return new Promise((resolve, reject) => {
|
|
306
253
|
const timeout = setTimeout(() => {
|
|
307
|
-
logger.error(`[MODIFY_ALARM_TOOL] ⏰ Timeout: No response received within 60 seconds`);
|
|
308
254
|
wsManager.off("data-event", handler);
|
|
309
255
|
reject(new Error("修改闹钟超时(60秒)"));
|
|
310
256
|
}, 60000);
|
|
311
257
|
// Listen for data events from WebSocket
|
|
312
258
|
const handler = (event) => {
|
|
313
|
-
logger.log(`[MODIFY_ALARM_TOOL] 📨 Received data event:`, JSON.stringify(event));
|
|
314
259
|
if (event.intentName === "ModifyAlarm") {
|
|
315
|
-
logger.log(`[MODIFY_ALARM_TOOL] 🎯 ModifyAlarm event received`);
|
|
316
|
-
logger.log(`[MODIFY_ALARM_TOOL] - status: ${event.status}`);
|
|
317
260
|
clearTimeout(timeout);
|
|
318
261
|
wsManager.off("data-event", handler);
|
|
319
262
|
if (event.status === "success" && event.outputs) {
|
|
320
|
-
|
|
321
|
-
logger.log(`[MODIFY_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs));
|
|
322
|
-
// Check for error code in outputs
|
|
323
|
-
const code = event.outputs.code !== undefined ? event.outputs.code : null;
|
|
324
|
-
if (code !== null && code !== 0) {
|
|
325
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Device returned error`);
|
|
326
|
-
logger.error(`[MODIFY_ALARM_TOOL] - code: ${code}`);
|
|
327
|
-
const errorMsg = event.outputs.errorMsg || event.outputs.errMsg || "未知错误";
|
|
328
|
-
logger.error(`[MODIFY_ALARM_TOOL] - errorMsg: ${errorMsg}`);
|
|
329
|
-
reject(new Error(`修改闹钟失败: ${errorMsg} (错误代码: ${code})`));
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
// Extract result with safe navigation
|
|
333
|
-
const result = event.outputs.result || {};
|
|
334
|
-
logger.log(`[MODIFY_ALARM_TOOL] 📋 Alarm result:`, JSON.stringify(result));
|
|
335
|
-
// Build response with safe navigation
|
|
336
|
-
const response = {
|
|
337
|
-
success: true,
|
|
338
|
-
alarm: {
|
|
339
|
-
entityId: result.entityId || params.entityId,
|
|
340
|
-
entityType: result.entityType || result.entityName,
|
|
341
|
-
alarmTitle: result.alarmTitle,
|
|
342
|
-
alarmTime: result.alarmTime,
|
|
343
|
-
alarmState: result.alarmState,
|
|
344
|
-
alarmRingDuration: result.alarmRingDuration,
|
|
345
|
-
alarmSnoozeDuration: result.alarmSnoozeDuration,
|
|
346
|
-
alarmSnoozeTotal: result.alarmSnoozeTotal,
|
|
347
|
-
daysOfWakeType: result.daysOfWakeType,
|
|
348
|
-
},
|
|
349
|
-
code,
|
|
350
|
-
};
|
|
263
|
+
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
351
264
|
resolve({
|
|
352
265
|
content: [
|
|
353
266
|
{
|
|
354
267
|
type: "text",
|
|
355
|
-
text: JSON.stringify(
|
|
268
|
+
text: JSON.stringify(event.outputs),
|
|
356
269
|
},
|
|
357
270
|
],
|
|
358
271
|
});
|
|
359
272
|
}
|
|
360
273
|
else {
|
|
361
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Alarm modification failed`);
|
|
362
|
-
logger.error(`[MODIFY_ALARM_TOOL] - status: ${event.status}`);
|
|
363
|
-
logger.error(`[MODIFY_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
|
|
364
274
|
reject(new Error(`修改闹钟失败: ${event.status}`));
|
|
365
275
|
}
|
|
366
276
|
}
|
|
367
277
|
};
|
|
368
278
|
// Register event handler
|
|
369
|
-
logger.log(`[MODIFY_ALARM_TOOL] 📡 Registering data-event handler on WebSocket manager`);
|
|
370
279
|
wsManager.on("data-event", handler);
|
|
371
280
|
// Send the command
|
|
372
|
-
logger.log(`[MODIFY_ALARM_TOOL] 📤 Sending ModifyAlarm command...`);
|
|
373
281
|
sendCommand({
|
|
374
282
|
config,
|
|
375
283
|
sessionId,
|
|
@@ -378,10 +286,8 @@ export const modifyAlarmTool = {
|
|
|
378
286
|
command,
|
|
379
287
|
})
|
|
380
288
|
.then(() => {
|
|
381
|
-
logger.log(`[MODIFY_ALARM_TOOL] ✅ Command sent successfully, waiting for response...`);
|
|
382
289
|
})
|
|
383
290
|
.catch((error) => {
|
|
384
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Failed to send command:`, error);
|
|
385
291
|
clearTimeout(timeout);
|
|
386
292
|
wsManager.off("data-event", handler);
|
|
387
293
|
reject(error);
|
|
@@ -403,17 +309,14 @@ function parseAlarmTimeToTimestamp(alarmTime) {
|
|
|
403
309
|
const trimmed = alarmTime.trim();
|
|
404
310
|
// Check basic format (should have at least 13 characters: YYYYMMDD hhmmss)
|
|
405
311
|
if (trimmed.length < 13) {
|
|
406
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ alarmTime too short: ${trimmed}`);
|
|
407
312
|
return null;
|
|
408
313
|
}
|
|
409
314
|
// Extract date and time parts
|
|
410
315
|
// Format: YYYYMMDD hhmmss
|
|
411
316
|
const datePart = trimmed.substring(0, 8); // YYYYMMDD
|
|
412
317
|
const timePart = trimmed.substring(8).trim(); // hhmmss (may have leading space)
|
|
413
|
-
logger.log(`[MODIFY_ALARM_TOOL] - datePart: ${datePart}, timePart: ${timePart}`);
|
|
414
318
|
// Validate lengths
|
|
415
319
|
if (datePart.length !== 8 || timePart.length !== 6) {
|
|
416
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid part lengths: datePart=${datePart.length}, timePart=${timePart.length}`);
|
|
417
320
|
return null;
|
|
418
321
|
}
|
|
419
322
|
// Parse components
|
|
@@ -423,45 +326,36 @@ function parseAlarmTimeToTimestamp(alarmTime) {
|
|
|
423
326
|
const hour = parseInt(timePart.substring(0, 2), 10);
|
|
424
327
|
const minute = parseInt(timePart.substring(2, 4), 10);
|
|
425
328
|
const second = parseInt(timePart.substring(4, 6), 10);
|
|
426
|
-
logger.log(`[MODIFY_ALARM_TOOL] - Parsed: ${year}-${month}-${day} ${hour}:${minute}:${second}`);
|
|
427
329
|
// Validate values
|
|
428
330
|
if (isNaN(year) || isNaN(month) || isNaN(day) ||
|
|
429
331
|
isNaN(hour) || isNaN(minute) || isNaN(second)) {
|
|
430
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ NaN detected in parsed values`);
|
|
431
332
|
return null;
|
|
432
333
|
}
|
|
433
334
|
// Validate ranges
|
|
434
335
|
if (month < 1 || month > 12) {
|
|
435
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid month: ${month}`);
|
|
436
336
|
return null;
|
|
437
337
|
}
|
|
438
338
|
if (day < 1 || day > 31) {
|
|
439
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid day: ${day}`);
|
|
440
339
|
return null;
|
|
441
340
|
}
|
|
442
341
|
if (hour < 0 || hour > 23) {
|
|
443
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid hour: ${hour}`);
|
|
444
342
|
return null;
|
|
445
343
|
}
|
|
446
344
|
if (minute < 0 || minute > 59) {
|
|
447
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid minute: ${minute}`);
|
|
448
345
|
return null;
|
|
449
346
|
}
|
|
450
347
|
if (second < 0 || second > 59) {
|
|
451
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Invalid second: ${second}`);
|
|
452
348
|
return null;
|
|
453
349
|
}
|
|
454
350
|
// Create Date object and get timestamp
|
|
455
351
|
const date = new Date(year, month - 1, day, hour, minute, second);
|
|
456
352
|
const timestamp = date.getTime();
|
|
457
353
|
if (isNaN(timestamp)) {
|
|
458
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Generated timestamp is NaN`);
|
|
459
354
|
return null;
|
|
460
355
|
}
|
|
461
356
|
return timestamp;
|
|
462
357
|
}
|
|
463
358
|
catch (error) {
|
|
464
|
-
logger.error(`[MODIFY_ALARM_TOOL] ❌ Exception in parseAlarmTimeToTimestamp:`, error);
|
|
465
359
|
return null;
|
|
466
360
|
}
|
|
467
361
|
}
|
|
@@ -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 modify note tool - appends content to an existing note on user's device.
|
|
7
6
|
* Requires entityId from search_notes tool as prerequisite.
|
|
@@ -13,7 +12,7 @@ import { logger } from "../utils/logger.js";
|
|
|
13
12
|
export const modifyNoteTool = {
|
|
14
13
|
name: "modify_note",
|
|
15
14
|
label: "Modify Note",
|
|
16
|
-
description: "在指定备忘录中追加新内容。使用前必须先调用 search_notes 工具获取备忘录的 entityId。参数说明:entityId 是备忘录的唯一标识符(从 search_notes 工具获取),text 是要追加的文本内容。注意:操作超时时间为60
|
|
15
|
+
description: "在指定备忘录中追加新内容。使用前必须先调用 search_notes 工具获取备忘录的 entityId。参数说明:entityId 是备忘录的唯一标识符(从 search_notes 工具获取),text 是要追加的文本内容。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。",
|
|
17
16
|
parameters: {
|
|
18
17
|
type: "object",
|
|
19
18
|
properties: {
|
|
@@ -29,34 +28,19 @@ export const modifyNoteTool = {
|
|
|
29
28
|
required: ["entityId", "text"],
|
|
30
29
|
},
|
|
31
30
|
async execute(toolCallId, params) {
|
|
32
|
-
logger.log(`[MODIFY_NOTE_TOOL] 🚀 Starting execution`);
|
|
33
|
-
logger.log(`[MODIFY_NOTE_TOOL] - toolCallId: ${toolCallId}`);
|
|
34
|
-
logger.log(`[MODIFY_NOTE_TOOL] - params:`, JSON.stringify(params));
|
|
35
|
-
logger.log(`[MODIFY_NOTE_TOOL] - timestamp: ${new Date().toISOString()}`);
|
|
36
31
|
// Validate parameters
|
|
37
32
|
if (!params.entityId || !params.text) {
|
|
38
|
-
logger.error(`[MODIFY_NOTE_TOOL] ❌ Missing required parameters`);
|
|
39
33
|
throw new Error("Missing required parameters: entityId and text are required");
|
|
40
34
|
}
|
|
41
35
|
// Get session context
|
|
42
|
-
logger.log(`[MODIFY_NOTE_TOOL] 🔍 Attempting to get session context...`);
|
|
43
36
|
const sessionContext = getCurrentSessionContext();
|
|
44
37
|
if (!sessionContext) {
|
|
45
|
-
logger.error(`[MODIFY_NOTE_TOOL] ❌ FAILED: No active session found!`);
|
|
46
|
-
logger.error(`[MODIFY_NOTE_TOOL] - toolCallId: ${toolCallId}`);
|
|
47
38
|
throw new Error("No active XY session found. Modify note tool can only be used during an active conversation.");
|
|
48
39
|
}
|
|
49
|
-
logger.log(`[MODIFY_NOTE_TOOL] ✅ Session context found`);
|
|
50
|
-
logger.log(`[MODIFY_NOTE_TOOL] - sessionId: ${sessionContext.sessionId}`);
|
|
51
|
-
logger.log(`[MODIFY_NOTE_TOOL] - taskId: ${sessionContext.taskId}`);
|
|
52
|
-
logger.log(`[MODIFY_NOTE_TOOL] - messageId: ${sessionContext.messageId}`);
|
|
53
40
|
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
54
41
|
// Get WebSocket manager
|
|
55
|
-
logger.log(`[MODIFY_NOTE_TOOL] 🔌 Getting WebSocket manager...`);
|
|
56
42
|
const wsManager = getXYWebSocketManager(config);
|
|
57
|
-
logger.log(`[MODIFY_NOTE_TOOL] ✅ WebSocket manager obtained`);
|
|
58
43
|
// Build ModifyNote command
|
|
59
|
-
logger.log(`[MODIFY_NOTE_TOOL] 📦 Building ModifyNote command...`);
|
|
60
44
|
const command = {
|
|
61
45
|
header: {
|
|
62
46
|
namespace: "Common",
|
|
@@ -92,56 +76,36 @@ export const modifyNoteTool = {
|
|
|
92
76
|
pageControlRelated: false,
|
|
93
77
|
},
|
|
94
78
|
};
|
|
95
|
-
logger.log(`[MODIFY_NOTE_TOOL] - entityId: ${params.entityId}`);
|
|
96
|
-
logger.log(`[MODIFY_NOTE_TOOL] - contentType: 1 (append mode)`);
|
|
97
|
-
logger.log(`[MODIFY_NOTE_TOOL] - text length: ${params.text.length} characters`);
|
|
98
79
|
// Send command and wait for response (60 second timeout)
|
|
99
|
-
logger.log(`[MODIFY_NOTE_TOOL] ⏳ Setting up promise to wait for note modification response...`);
|
|
100
|
-
logger.log(`[MODIFY_NOTE_TOOL] - Timeout: 60 seconds`);
|
|
101
80
|
return new Promise((resolve, reject) => {
|
|
102
81
|
const timeout = setTimeout(() => {
|
|
103
|
-
logger.error(`[MODIFY_NOTE_TOOL] ⏰ Timeout: No response received within 60 seconds`);
|
|
104
82
|
wsManager.off("data-event", handler);
|
|
105
83
|
reject(new Error("修改备忘录超时(60秒)"));
|
|
106
84
|
}, 60000);
|
|
107
85
|
// Listen for data events from WebSocket
|
|
108
86
|
const handler = (event) => {
|
|
109
|
-
logger.log(`[MODIFY_NOTE_TOOL] 📨 Received data event:`, JSON.stringify(event));
|
|
110
87
|
if (event.intentName === "ModifyNote") {
|
|
111
|
-
logger.log(`[MODIFY_NOTE_TOOL] 🎯 ModifyNote event received`);
|
|
112
|
-
logger.log(`[MODIFY_NOTE_TOOL] - status: ${event.status}`);
|
|
113
88
|
clearTimeout(timeout);
|
|
114
89
|
wsManager.off("data-event", handler);
|
|
115
90
|
if (event.status === "success" && event.outputs) {
|
|
116
|
-
|
|
117
|
-
logger.log(`[MODIFY_NOTE_TOOL] - outputs:`, JSON.stringify(event.outputs));
|
|
118
|
-
// Return the result directly as requested
|
|
119
|
-
const result = event.outputs.result;
|
|
120
|
-
logger.log(`[MODIFY_NOTE_TOOL] 📝 Note updated:`);
|
|
121
|
-
logger.log(`[MODIFY_NOTE_TOOL] - entityId: ${result?.entityId}`);
|
|
122
|
-
logger.log(`[MODIFY_NOTE_TOOL] - title: ${result?.title}`);
|
|
123
|
-
logger.log(`[MODIFY_NOTE_TOOL] - modifiedDate: ${result?.modifiedDate}`);
|
|
91
|
+
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
124
92
|
resolve({
|
|
125
93
|
content: [
|
|
126
94
|
{
|
|
127
95
|
type: "text",
|
|
128
|
-
text: JSON.stringify(
|
|
96
|
+
text: JSON.stringify(event.outputs),
|
|
129
97
|
},
|
|
130
98
|
],
|
|
131
99
|
});
|
|
132
100
|
}
|
|
133
101
|
else {
|
|
134
|
-
logger.error(`[MODIFY_NOTE_TOOL] ❌ Note modification failed`);
|
|
135
|
-
logger.error(`[MODIFY_NOTE_TOOL] - status: ${event.status}`);
|
|
136
102
|
reject(new Error(`修改备忘录失败: ${event.status}`));
|
|
137
103
|
}
|
|
138
104
|
}
|
|
139
105
|
};
|
|
140
106
|
// Register event handler
|
|
141
|
-
logger.log(`[MODIFY_NOTE_TOOL] 📡 Registering data-event handler on WebSocket manager`);
|
|
142
107
|
wsManager.on("data-event", handler);
|
|
143
108
|
// Send the command
|
|
144
|
-
logger.log(`[MODIFY_NOTE_TOOL] 📤 Sending ModifyNote command...`);
|
|
145
109
|
sendCommand({
|
|
146
110
|
config,
|
|
147
111
|
sessionId,
|
|
@@ -150,10 +114,8 @@ export const modifyNoteTool = {
|
|
|
150
114
|
command,
|
|
151
115
|
})
|
|
152
116
|
.then(() => {
|
|
153
|
-
logger.log(`[MODIFY_NOTE_TOOL] ✅ Command sent successfully, waiting for response...`);
|
|
154
117
|
})
|
|
155
118
|
.catch((error) => {
|
|
156
|
-
logger.error(`[MODIFY_NOTE_TOOL] ❌ Failed to send command:`, error);
|
|
157
119
|
clearTimeout(timeout);
|
|
158
120
|
wsManager.off("data-event", handler);
|
|
159
121
|
reject(error);
|
|
@@ -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
|
* Duck-typed ToolInputError: openclaw 按 .name 字段匹配,不用 instanceof。
|
|
7
6
|
* 抛出此错误会让 openclaw 返回 HTTP 400 而非 500,
|
|
@@ -26,6 +25,8 @@ export const noteTool = {
|
|
|
26
25
|
a. 操作超时时间为60秒,请勿重复调用此工具
|
|
27
26
|
b. 如果遇到各类调用失败场景,最多只能重试一次,不可以重复调用多次。
|
|
28
27
|
c. 调用工具前需认真检查调用参数是否满足工具要求
|
|
28
|
+
|
|
29
|
+
回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。
|
|
29
30
|
`,
|
|
30
31
|
parameters: {
|
|
31
32
|
type: "object",
|
|
@@ -42,7 +43,6 @@ export const noteTool = {
|
|
|
42
43
|
required: ["title", "content"],
|
|
43
44
|
},
|
|
44
45
|
async execute(toolCallId, params) {
|
|
45
|
-
logger.debug("Executing note tool, toolCallId:", toolCallId);
|
|
46
46
|
// Validate parameters — 抛 ToolInputError 而非普通 Error,
|
|
47
47
|
// 让 openclaw 返回 400 而非 500,明确告知 LLM 这是参数错误,不应重试。
|
|
48
48
|
if (typeof params.title !== "string" || !params.title) {
|
|
@@ -101,28 +101,16 @@ export const noteTool = {
|
|
|
101
101
|
}, 60000);
|
|
102
102
|
// Listen for data events from WebSocket
|
|
103
103
|
const handler = (event) => {
|
|
104
|
-
logger.debug("Received data event:", event);
|
|
105
104
|
if (event.intentName === "CreateNote") {
|
|
106
105
|
clearTimeout(timeout);
|
|
107
106
|
wsManager.off("data-event", handler);
|
|
108
107
|
if (event.status === "success" && event.outputs) {
|
|
109
|
-
|
|
110
|
-
logger.log(`Note created: title=${result?.title}, id=${result?.entityId}`);
|
|
108
|
+
// 成功,直接返回完整的 event.outputs JSON 字符串
|
|
111
109
|
resolve({
|
|
112
110
|
content: [
|
|
113
111
|
{
|
|
114
112
|
type: "text",
|
|
115
|
-
text: JSON.stringify(
|
|
116
|
-
success: true,
|
|
117
|
-
note: {
|
|
118
|
-
entityId: result?.entityId,
|
|
119
|
-
title: result?.title,
|
|
120
|
-
content: result?.content,
|
|
121
|
-
entityName: result?.entityName,
|
|
122
|
-
modifiedDate: result?.modifiedDate,
|
|
123
|
-
},
|
|
124
|
-
code,
|
|
125
|
-
}),
|
|
113
|
+
text: JSON.stringify(event.outputs),
|
|
126
114
|
},
|
|
127
115
|
],
|
|
128
116
|
});
|