@ynhcj/xiaoyi-channel 0.0.50-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.
Files changed (42) hide show
  1. package/dist/index.js +42 -0
  2. package/dist/src/bot.js +3 -16
  3. package/dist/src/client.js +0 -3
  4. package/dist/src/cspl/call-api.d.ts +3 -0
  5. package/dist/src/cspl/call-api.js +79 -0
  6. package/dist/src/cspl/config.d.ts +19 -0
  7. package/dist/src/cspl/config.js +50 -0
  8. package/dist/src/cspl/constants.d.ts +43 -0
  9. package/dist/src/cspl/constants.js +22 -0
  10. package/dist/src/cspl/utils.d.ts +10 -0
  11. package/dist/src/cspl/utils.js +57 -0
  12. package/dist/src/formatter.js +3 -23
  13. package/dist/src/heartbeat.js +0 -4
  14. package/dist/src/reply-dispatcher.js +32 -0
  15. package/dist/src/steer-injector.d.ts +16 -0
  16. package/dist/src/steer-injector.js +74 -0
  17. package/dist/src/tools/calendar-tool.js +2 -37
  18. package/dist/src/tools/call-phone-tool.js +1 -42
  19. package/dist/src/tools/create-alarm-tool.js +3 -74
  20. package/dist/src/tools/delete-alarm-tool.js +3 -45
  21. package/dist/src/tools/image-reading-tool.js +0 -47
  22. package/dist/src/tools/location-tool.js +1 -32
  23. package/dist/src/tools/modify-alarm-tool.js +3 -77
  24. package/dist/src/tools/modify-note-tool.js +1 -34
  25. package/dist/src/tools/note-tool.js +2 -4
  26. package/dist/src/tools/search-alarm-tool.js +3 -61
  27. package/dist/src/tools/search-calendar-tool.js +2 -39
  28. package/dist/src/tools/search-contact-tool.js +0 -30
  29. package/dist/src/tools/search-file-tool.js +0 -33
  30. package/dist/src/tools/search-message-tool.js +0 -33
  31. package/dist/src/tools/search-note-tool.js +1 -26
  32. package/dist/src/tools/search-photo-gallery-tool.js +2 -31
  33. package/dist/src/tools/send-file-to-user-tool.js +0 -39
  34. package/dist/src/tools/send-message-tool.js +1 -39
  35. package/dist/src/tools/session-manager.js +0 -45
  36. package/dist/src/tools/upload-file-tool.js +0 -49
  37. package/dist/src/tools/upload-photo-tool.js +0 -42
  38. package/dist/src/tools/view-push-result-tool.js +0 -11
  39. package/dist/src/tools/xiaoyi-collection-tool.js +4 -82
  40. package/dist/src/tools/xiaoyi-gui-tool.js +0 -34
  41. package/dist/src/websocket.js +24 -10
  42. 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
  /**
6
5
  * XY calendar event tool - creates a calendar event on user's device.
7
6
  * Requires title, dtStart (start time), and dtEnd (end time) parameters.
@@ -12,6 +11,8 @@ export const calendarTool = {
12
11
  label: "Create Calendar Event",
13
12
  description: `在用户设备上创建日程。需要提供日程标题、开始时间和结束时间。时间格式必须为:yyyy-mm-dd hh:mm:ss(例如:2024-01-15 14:30:00)。注意:该工具执行时间较长(最多60秒),请勿重复调用,超时或失败时最多重试一次。
14
13
  注意事项:使用该工具之前需获取当前真实时间
14
+
15
+ 回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。
15
16
  `,
16
17
  parameters: {
17
18
  type: "object",
@@ -32,47 +33,25 @@ export const calendarTool = {
32
33
  required: ["title", "dtStart", "dtEnd"],
33
34
  },
34
35
  async execute(toolCallId, params) {
35
- logger.log(`[CALENDAR_TOOL] 🚀 Starting execution`);
36
- logger.log(`[CALENDAR_TOOL] - toolCallId: ${toolCallId}`);
37
- logger.log(`[CALENDAR_TOOL] - params:`, JSON.stringify(params));
38
- logger.log(`[CALENDAR_TOOL] - timestamp: ${new Date().toISOString()}`);
39
36
  // Validate parameters
40
37
  if (!params.title || !params.dtStart || !params.dtEnd) {
41
- logger.error(`[CALENDAR_TOOL] ❌ Missing required parameters`);
42
38
  throw new Error("Missing required parameters: title, dtStart, and dtEnd are required");
43
39
  }
44
40
  // Convert time strings to millisecond timestamps
45
- logger.log(`[CALENDAR_TOOL] 🕒 Converting time strings to timestamps...`);
46
- logger.log(`[CALENDAR_TOOL] - dtStart input: ${params.dtStart}`);
47
- logger.log(`[CALENDAR_TOOL] - dtEnd input: ${params.dtEnd}`);
48
41
  const dtStartMs = new Date(params.dtStart).getTime();
49
42
  const dtEndMs = new Date(params.dtEnd).getTime();
50
43
  if (isNaN(dtStartMs) || isNaN(dtEndMs)) {
51
- logger.error(`[CALENDAR_TOOL] ❌ Invalid time format`);
52
44
  throw new Error("Invalid time format. Required format: yyyy-mm-dd hh:mm:ss (e.g., 2024-01-15 14:30:00)");
53
45
  }
54
- logger.log(`[CALENDAR_TOOL] ✅ Time conversion successful`);
55
- logger.log(`[CALENDAR_TOOL] - dtStart timestamp: ${dtStartMs}`);
56
- logger.log(`[CALENDAR_TOOL] - dtEnd timestamp: ${dtEndMs}`);
57
46
  // Get session context
58
- logger.log(`[CALENDAR_TOOL] 🔍 Attempting to get session context...`);
59
47
  const sessionContext = getCurrentSessionContext();
60
48
  if (!sessionContext) {
61
- logger.error(`[CALENDAR_TOOL] ❌ FAILED: No active session found!`);
62
- logger.error(`[CALENDAR_TOOL] - toolCallId: ${toolCallId}`);
63
49
  throw new Error("No active XY session found. Calendar tool can only be used during an active conversation.");
64
50
  }
65
- logger.log(`[CALENDAR_TOOL] ✅ Session context found`);
66
- logger.log(`[CALENDAR_TOOL] - sessionId: ${sessionContext.sessionId}`);
67
- logger.log(`[CALENDAR_TOOL] - taskId: ${sessionContext.taskId}`);
68
- logger.log(`[CALENDAR_TOOL] - messageId: ${sessionContext.messageId}`);
69
51
  const { config, sessionId, taskId, messageId } = sessionContext;
70
52
  // Get WebSocket manager
71
- logger.log(`[CALENDAR_TOOL] 🔌 Getting WebSocket manager...`);
72
53
  const wsManager = getXYWebSocketManager(config);
73
- logger.log(`[CALENDAR_TOOL] ✅ WebSocket manager obtained`);
74
54
  // Build CreateCalendarEvent command
75
- logger.log(`[CALENDAR_TOOL] 📦 Building CreateCalendarEvent command...`);
76
55
  const command = {
77
56
  header: {
78
57
  namespace: "Common",
@@ -108,25 +87,17 @@ export const calendarTool = {
108
87
  },
109
88
  };
110
89
  // Send command and wait for response (60 second timeout)
111
- logger.log(`[CALENDAR_TOOL] ⏳ Setting up promise to wait for calendar event response...`);
112
- logger.log(`[CALENDAR_TOOL] - Timeout: 60 seconds`);
113
90
  return new Promise((resolve, reject) => {
114
91
  const timeout = setTimeout(() => {
115
- logger.error(`[CALENDAR_TOOL] ⏰ Timeout: No response received within 60 seconds`);
116
92
  wsManager.off("data-event", handler);
117
93
  reject(new Error("创建日程超时(60秒)"));
118
94
  }, 60000);
119
95
  // Listen for data events from WebSocket
120
96
  const handler = (event) => {
121
- logger.log(`[CALENDAR_TOOL] 📨 Received data event:`, JSON.stringify(event));
122
97
  if (event.intentName === "CreateCalendarEvent") {
123
- logger.log(`[CALENDAR_TOOL] 🎯 CreateCalendarEvent event received`);
124
- logger.log(`[CALENDAR_TOOL] - status: ${event.status}`);
125
98
  clearTimeout(timeout);
126
99
  wsManager.off("data-event", handler);
127
100
  if (event.status === "success" && event.outputs) {
128
- logger.log(`[CALENDAR_TOOL] ✅ Calendar event created successfully`);
129
- logger.log(`[CALENDAR_TOOL] - outputs:`, JSON.stringify(event.outputs));
130
101
  resolve({
131
102
  content: [
132
103
  {
@@ -137,17 +108,13 @@ export const calendarTool = {
137
108
  });
138
109
  }
139
110
  else {
140
- logger.error(`[CALENDAR_TOOL] ❌ Calendar event creation failed`);
141
- logger.error(`[CALENDAR_TOOL] - status: ${event.status}`);
142
111
  reject(new Error(`创建日程失败: ${event.status}`));
143
112
  }
144
113
  }
145
114
  };
146
115
  // Register event handler
147
- logger.log(`[CALENDAR_TOOL] 📡 Registering data-event handler on WebSocket manager`);
148
116
  wsManager.on("data-event", handler);
149
117
  // Send the command
150
- logger.log(`[CALENDAR_TOOL] 📤 Sending CreateCalendarEvent command...`);
151
118
  sendCommand({
152
119
  config,
153
120
  sessionId,
@@ -156,10 +123,8 @@ export const calendarTool = {
156
123
  command,
157
124
  })
158
125
  .then(() => {
159
- logger.log(`[CALENDAR_TOOL] ✅ Command sent successfully, waiting for response...`);
160
126
  })
161
127
  .catch((error) => {
162
- logger.error(`[CALENDAR_TOOL] ❌ Failed to send command:`, error);
163
128
  clearTimeout(timeout);
164
129
  wsManager.off("data-event", handler);
165
130
  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
  * XY call phone tool - makes a phone call on user's device.
7
6
  * Requires phoneNumber parameter and optional slotId (0 for primary SIM, 1 for secondary SIM).
@@ -9,7 +8,7 @@ import { logger } from "../utils/logger.js";
9
8
  export const callPhoneTool = {
10
9
  name: "call_phone",
11
10
  label: "Call Phone",
12
- description: "拨打电话。需要提供要拨打的电话号码。slotId参数可选,默认为0(主卡),如果用户明确要求使用副卡则设置为1。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。",
11
+ description: "拨打电话。需要提供要拨打的电话号码。slotId参数可选,默认为0(主卡),如果用户明确要求使用副卡则设置为1。注意:操作超时时间为60秒,请勿重复调用此工具,如果超时或失败,最多重试一次。回复约束:如果工具返回没有授权或者其他报错,只需要完整描述没有授权或者其他报错内容即可,不需要主动给用户提供解决方案,例如告诉用户如何授权,如何解决报错等都是不需要的,请严格遵守。",
13
12
  parameters: {
14
13
  type: "object",
15
14
  properties: {
@@ -26,43 +25,25 @@ export const callPhoneTool = {
26
25
  required: ["phoneNumber"],
27
26
  },
28
27
  async execute(toolCallId, params) {
29
- logger.log(`[CALL_PHONE_TOOL] 🚀 Starting execution`);
30
- logger.log(`[CALL_PHONE_TOOL] - toolCallId: ${toolCallId}`);
31
- logger.log(`[CALL_PHONE_TOOL] - params:`, JSON.stringify(params));
32
- logger.log(`[CALL_PHONE_TOOL] - timestamp: ${new Date().toISOString()}`);
33
28
  // Validate phoneNumber parameter
34
29
  if (!params.phoneNumber || typeof params.phoneNumber !== "string" || params.phoneNumber.trim() === "") {
35
- logger.error(`[CALL_PHONE_TOOL] ❌ Missing or invalid phoneNumber parameter`);
36
30
  throw new Error("Missing required parameter: phoneNumber must be a non-empty string");
37
31
  }
38
32
  // Set default slotId if not provided
39
33
  const slotId = params.slotId !== undefined && params.slotId !== null ? params.slotId : 0;
40
34
  // Validate slotId (must be 0 or 1)
41
35
  if (slotId !== 0 && slotId !== 1) {
42
- logger.error(`[CALL_PHONE_TOOL] ❌ Invalid slotId: ${slotId}`);
43
36
  throw new Error("Invalid slotId: must be 0 (primary SIM) or 1 (secondary SIM)");
44
37
  }
45
- logger.log(`[CALL_PHONE_TOOL] 📞 Preparing to call phone number: ${params.phoneNumber}`);
46
- logger.log(`[CALL_PHONE_TOOL] - slotId: ${slotId} (${slotId === 0 ? "主卡" : "副卡"})`);
47
38
  // Get session context
48
- logger.log(`[CALL_PHONE_TOOL] 🔍 Attempting to get session context...`);
49
39
  const sessionContext = getCurrentSessionContext();
50
40
  if (!sessionContext) {
51
- logger.error(`[CALL_PHONE_TOOL] ❌ FAILED: No active session found!`);
52
- logger.error(`[CALL_PHONE_TOOL] - toolCallId: ${toolCallId}`);
53
41
  throw new Error("No active XY session found. Call phone tool can only be used during an active conversation.");
54
42
  }
55
- logger.log(`[CALL_PHONE_TOOL] ✅ Session context found`);
56
- logger.log(`[CALL_PHONE_TOOL] - sessionId: ${sessionContext.sessionId}`);
57
- logger.log(`[CALL_PHONE_TOOL] - taskId: ${sessionContext.taskId}`);
58
- logger.log(`[CALL_PHONE_TOOL] - messageId: ${sessionContext.messageId}`);
59
43
  const { config, sessionId, taskId, messageId } = sessionContext;
60
44
  // Get WebSocket manager
61
- logger.log(`[CALL_PHONE_TOOL] 🔌 Getting WebSocket manager...`);
62
45
  const wsManager = getXYWebSocketManager(config);
63
- logger.log(`[CALL_PHONE_TOOL] ✅ WebSocket manager obtained`);
64
46
  // Build StartCall command
65
- logger.log(`[CALL_PHONE_TOOL] 📦 Building StartCall command...`);
66
47
  const command = {
67
48
  header: {
68
49
  namespace: "Common",
@@ -97,34 +78,22 @@ export const callPhoneTool = {
97
78
  pageControlRelated: false,
98
79
  },
99
80
  };
100
- logger.log(`[CALL_PHONE_TOOL] 📋 Command details:`, JSON.stringify(command, null, 2));
101
81
  // Send command and wait for response (60 second timeout)
102
- logger.log(`[CALL_PHONE_TOOL] ⏳ Setting up promise to wait for call response...`);
103
- logger.log(`[CALL_PHONE_TOOL] - Timeout: 60 seconds`);
104
82
  return new Promise((resolve, reject) => {
105
83
  const timeout = setTimeout(() => {
106
- logger.error(`[CALL_PHONE_TOOL] ⏰ Timeout: No response received within 60 seconds`);
107
84
  wsManager.off("data-event", handler);
108
85
  reject(new Error("拨打电话超时(60秒)"));
109
86
  }, 60000);
110
87
  // Listen for data events from WebSocket
111
88
  const handler = (event) => {
112
- logger.log(`[CALL_PHONE_TOOL] 📨 Received data event:`, JSON.stringify(event));
113
89
  if (event.intentName === "StartCall") {
114
- logger.log(`[CALL_PHONE_TOOL] 🎯 StartCall event received`);
115
- logger.log(`[CALL_PHONE_TOOL] - status: ${event.status}`);
116
90
  clearTimeout(timeout);
117
91
  wsManager.off("data-event", handler);
118
92
  if (event.status === "success" && event.outputs) {
119
- logger.log(`[CALL_PHONE_TOOL] ✅ Call response received`);
120
- logger.log(`[CALL_PHONE_TOOL] - outputs:`, JSON.stringify(event.outputs));
121
93
  // Check for error code in outputs
122
94
  const code = event.outputs.code !== undefined ? event.outputs.code : null;
123
95
  if (code !== null && code !== 0) {
124
- logger.error(`[CALL_PHONE_TOOL] ❌ Device returned error`);
125
- logger.error(`[CALL_PHONE_TOOL] - code: ${code}`);
126
96
  const errorMsg = event.outputs.errorMsg || event.outputs.errMsg || "未知错误";
127
- logger.error(`[CALL_PHONE_TOOL] - errorMsg: ${errorMsg}`);
128
97
  reject(new Error(`拨打电话失败: ${errorMsg} (错误代码: ${code})`));
129
98
  return;
130
99
  }
@@ -136,9 +105,6 @@ export const callPhoneTool = {
136
105
  slotId: slotId,
137
106
  message: "电话拨打成功",
138
107
  };
139
- logger.log(`[CALL_PHONE_TOOL] 🎉 Call initiated successfully`);
140
- logger.log(`[CALL_PHONE_TOOL] - phoneNumber: ${params.phoneNumber}`);
141
- logger.log(`[CALL_PHONE_TOOL] - slotId: ${slotId}`);
142
108
  resolve({
143
109
  content: [
144
110
  {
@@ -149,19 +115,14 @@ export const callPhoneTool = {
149
115
  });
150
116
  }
151
117
  else {
152
- logger.error(`[CALL_PHONE_TOOL] ❌ Call failed`);
153
- logger.error(`[CALL_PHONE_TOOL] - status: ${event.status}`);
154
- logger.error(`[CALL_PHONE_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
155
118
  const errorDetail = event.outputs ? JSON.stringify(event.outputs) : event.status;
156
119
  reject(new Error(`拨打电话失败: ${errorDetail}`));
157
120
  }
158
121
  }
159
122
  };
160
123
  // Register event handler
161
- logger.log(`[CALL_PHONE_TOOL] 📡 Registering data-event handler on WebSocket manager`);
162
124
  wsManager.on("data-event", handler);
163
125
  // Send the command
164
- logger.log(`[CALL_PHONE_TOOL] 📤 Sending StartCall command...`);
165
126
  sendCommand({
166
127
  config,
167
128
  sessionId,
@@ -170,10 +131,8 @@ export const callPhoneTool = {
170
131
  command,
171
132
  })
172
133
  .then(() => {
173
- logger.log(`[CALL_PHONE_TOOL] ✅ Command sent successfully, waiting for response...`);
174
134
  })
175
135
  .catch((error) => {
176
- logger.error(`[CALL_PHONE_TOOL] ❌ Failed to send command:`, error);
177
136
  clearTimeout(timeout);
178
137
  wsManager.off("data-event", handler);
179
138
  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
  // 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
  }