@ynhcj/xiaoyi-channel 0.0.9 โ 0.0.10-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/src/bot.js +153 -48
- package/dist/src/channel.js +23 -4
- package/dist/src/client.d.ts +15 -0
- package/dist/src/client.js +81 -0
- package/dist/src/config.js +2 -2
- package/dist/src/file-download.js +10 -1
- package/dist/src/formatter.d.ts +31 -0
- package/dist/src/formatter.js +93 -1
- package/dist/src/heartbeat.d.ts +2 -1
- package/dist/src/heartbeat.js +6 -1
- package/dist/src/monitor.d.ts +5 -0
- package/dist/src/monitor.js +101 -9
- package/dist/src/outbound.js +97 -7
- package/dist/src/parser.d.ts +12 -0
- package/dist/src/parser.js +37 -0
- package/dist/src/push.d.ts +13 -1
- package/dist/src/push.js +125 -19
- package/dist/src/reply-dispatcher.d.ts +1 -0
- package/dist/src/reply-dispatcher.js +206 -51
- package/dist/src/task-manager.d.ts +55 -0
- package/dist/src/task-manager.js +136 -0
- package/dist/src/tools/calendar-tool.d.ts +6 -0
- package/dist/src/tools/calendar-tool.js +169 -0
- package/dist/src/tools/call-phone-tool.d.ts +5 -0
- package/dist/src/tools/call-phone-tool.js +183 -0
- package/dist/src/tools/create-alarm-tool.d.ts +7 -0
- package/dist/src/tools/create-alarm-tool.js +446 -0
- package/dist/src/tools/delete-alarm-tool.d.ts +11 -0
- package/dist/src/tools/delete-alarm-tool.js +238 -0
- package/dist/src/tools/location-tool.js +18 -8
- package/dist/src/tools/modify-alarm-tool.d.ts +9 -0
- package/dist/src/tools/modify-alarm-tool.js +467 -0
- package/dist/src/tools/modify-note-tool.d.ts +9 -0
- package/dist/src/tools/modify-note-tool.js +163 -0
- package/dist/src/tools/note-tool.js +32 -11
- package/dist/src/tools/search-alarm-tool.d.ts +8 -0
- package/dist/src/tools/search-alarm-tool.js +391 -0
- package/dist/src/tools/search-calendar-tool.d.ts +12 -0
- package/dist/src/tools/search-calendar-tool.js +262 -0
- package/dist/src/tools/search-contact-tool.d.ts +5 -0
- package/dist/src/tools/search-contact-tool.js +168 -0
- package/dist/src/tools/search-file-tool.d.ts +5 -0
- package/dist/src/tools/search-file-tool.js +185 -0
- package/dist/src/tools/search-message-tool.d.ts +5 -0
- package/dist/src/tools/search-message-tool.js +173 -0
- package/dist/src/tools/search-note-tool.js +6 -6
- package/dist/src/tools/search-photo-gallery-tool.d.ts +8 -0
- package/dist/src/tools/search-photo-gallery-tool.js +212 -0
- package/dist/src/tools/search-photo-tool.d.ts +9 -0
- package/dist/src/tools/search-photo-tool.js +270 -0
- package/dist/src/tools/send-file-to-user-tool.d.ts +5 -0
- package/dist/src/tools/send-file-to-user-tool.js +318 -0
- package/dist/src/tools/send-message-tool.d.ts +5 -0
- package/dist/src/tools/send-message-tool.js +189 -0
- package/dist/src/tools/session-manager.d.ts +15 -0
- package/dist/src/tools/session-manager.js +101 -13
- package/dist/src/tools/upload-file-tool.d.ts +13 -0
- package/dist/src/tools/upload-file-tool.js +265 -0
- package/dist/src/tools/upload-photo-tool.d.ts +9 -0
- package/dist/src/tools/upload-photo-tool.js +223 -0
- package/dist/src/tools/view-push-result-tool.d.ts +5 -0
- package/dist/src/tools/view-push-result-tool.js +118 -0
- package/dist/src/tools/xiaoyi-collection-tool.d.ts +5 -0
- package/dist/src/tools/xiaoyi-collection-tool.js +190 -0
- package/dist/src/tools/xiaoyi-gui-tool.d.ts +6 -0
- package/dist/src/tools/xiaoyi-gui-tool.js +151 -0
- package/dist/src/trigger-handler.d.ts +22 -0
- package/dist/src/trigger-handler.js +59 -0
- package/dist/src/types.d.ts +6 -17
- package/dist/src/types.js +4 -0
- package/dist/src/utils/config-manager.d.ts +26 -0
- package/dist/src/utils/config-manager.js +56 -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 +59 -25
- package/dist/src/websocket.js +315 -257
- package/package.json +1 -1
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getCurrentSessionContext } from "./session-manager.js";
|
|
4
4
|
import { logger } from "../utils/logger.js";
|
|
5
|
+
/**
|
|
6
|
+
* Duck-typed ToolInputError: openclaw ๆ .name ๅญๆฎตๅน้
๏ผไธ็จ instanceofใ
|
|
7
|
+
* ๆๅบๆญค้่ฏฏไผ่ฎฉ openclaw ่ฟๅ HTTP 400 ่้ 500๏ผ
|
|
8
|
+
* LLM ไผๅฐๅ
ถ่ฏๅซไธบๅๆฐ้่ฏฏ่้็ฌๆถๆ
้๏ผไธไผ่งฆๅ้่ฏใ
|
|
9
|
+
*/
|
|
10
|
+
class ToolInputError extends Error {
|
|
11
|
+
status = 400;
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "ToolInputError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
5
17
|
/**
|
|
6
18
|
* XY note tool - creates a note on user's device.
|
|
7
19
|
* Requires title and content parameters.
|
|
@@ -9,29 +21,38 @@ import { logger } from "../utils/logger.js";
|
|
|
9
21
|
export const noteTool = {
|
|
10
22
|
name: "create_note",
|
|
11
23
|
label: "Create Note",
|
|
12
|
-
description:
|
|
24
|
+
description: `ๅจ็จๆท่ฎพๅคไธๅๅปบๅคๅฟๅฝใ้่ฆๆไพๅคๅฟๅฝๆ ้ขๅๅ
ๅฎนใ
|
|
25
|
+
ๆณจๆ:
|
|
26
|
+
a. ๆไฝ่ถ
ๆถๆถ้ดไธบ60็ง,่ฏทๅฟ้ๅค่ฐ็จๆญคๅทฅๅ
ท
|
|
27
|
+
b. ๅฆๆ้ๅฐๅ็ฑป่ฐ็จๅคฑ่ดฅๅบๆฏ,ๆๅคๅช่ฝ้่ฏไธๆฌก๏ผไธๅฏไปฅ้ๅค่ฐ็จๅคๆฌกใ
|
|
28
|
+
c. ่ฐ็จๅทฅๅ
ทๅ้่ฎค็ๆฃๆฅ่ฐ็จๅๆฐๆฏๅฆๆปก่ถณๅทฅๅ
ท่ฆๆฑ
|
|
29
|
+
`,
|
|
13
30
|
parameters: {
|
|
14
31
|
type: "object",
|
|
15
32
|
properties: {
|
|
16
33
|
title: {
|
|
17
34
|
type: "string",
|
|
18
|
-
description: "
|
|
35
|
+
description: "ๅคๅฟๅฝๆ ้ข๏ผๅฟ
ๅกซ",
|
|
19
36
|
},
|
|
20
37
|
content: {
|
|
21
38
|
type: "string",
|
|
22
|
-
description: "
|
|
39
|
+
description: "ๅคๅฟๅฝๅ
ๅฎน๏ผๅฟ
ๅกซ",
|
|
23
40
|
},
|
|
24
41
|
},
|
|
25
42
|
required: ["title", "content"],
|
|
26
43
|
},
|
|
27
44
|
async execute(toolCallId, params) {
|
|
28
45
|
logger.debug("Executing note tool, toolCallId:", toolCallId);
|
|
29
|
-
// Validate parameters
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
// Validate parameters โ ๆ ToolInputError ่้ๆฎ้ Error๏ผ
|
|
47
|
+
// ่ฎฉ openclaw ่ฟๅ 400 ่้ 500๏ผๆ็กฎๅ็ฅ LLM ่ฟๆฏๅๆฐ้่ฏฏ๏ผไธๅบ้่ฏใ
|
|
48
|
+
if (typeof params.title !== "string" || !params.title) {
|
|
49
|
+
throw new ToolInputError("็ผบๅฐๅฟ
ๅกซๅๆฐ title๏ผๅคๅฟๅฝๆ ้ข๏ผ");
|
|
50
|
+
}
|
|
51
|
+
if (typeof params.content !== "string" || !params.content) {
|
|
52
|
+
throw new ToolInputError("็ผบๅฐๅฟ
ๅกซๅๆฐ content๏ผๅคๅฟๅฝๅ
ๅฎน๏ผ");
|
|
32
53
|
}
|
|
33
54
|
// Get session context
|
|
34
|
-
const sessionContext =
|
|
55
|
+
const sessionContext = getCurrentSessionContext();
|
|
35
56
|
if (!sessionContext) {
|
|
36
57
|
throw new Error("No active XY session found. Note tool can only be used during an active conversation.");
|
|
37
58
|
}
|
|
@@ -72,12 +93,12 @@ export const noteTool = {
|
|
|
72
93
|
pageControlRelated: false,
|
|
73
94
|
},
|
|
74
95
|
};
|
|
75
|
-
// Send command and wait for response (
|
|
96
|
+
// Send command and wait for response (60 second timeout)
|
|
76
97
|
return new Promise((resolve, reject) => {
|
|
77
98
|
const timeout = setTimeout(() => {
|
|
78
99
|
wsManager.off("data-event", handler);
|
|
79
|
-
reject(new Error("ๅๅปบๅคๅฟๅฝ่ถ
ๆถ๏ผ
|
|
80
|
-
},
|
|
100
|
+
reject(new Error("ๅๅปบๅคๅฟๅฝ่ถ
ๆถ๏ผ60็ง๏ผ"));
|
|
101
|
+
}, 60000);
|
|
81
102
|
// Listen for data events from WebSocket
|
|
82
103
|
const handler = (event) => {
|
|
83
104
|
logger.debug("Received data event:", event);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XY search alarm tool - searches alarms on user's device.
|
|
3
|
+
* Returns matching alarms based on various filter criteria.
|
|
4
|
+
*
|
|
5
|
+
* At least one search criterion must be provided.
|
|
6
|
+
* Multiple criteria can be combined.
|
|
7
|
+
*/
|
|
8
|
+
export declare const searchAlarmTool: any;
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { getXYWebSocketManager } from "../client.js";
|
|
2
|
+
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from "./session-manager.js";
|
|
4
|
+
import { logger } from "../utils/logger.js";
|
|
5
|
+
// Enum definitions for alarm search parameters
|
|
6
|
+
const RANGE_TYPE_VALUES = ["all", "next", "current"];
|
|
7
|
+
const ALARM_STATE_VALUES = [0, 1];
|
|
8
|
+
const DAYS_OF_WAKE_TYPE_VALUES = [0, 1, 2, 3, 4];
|
|
9
|
+
/**
|
|
10
|
+
* XY search alarm tool - searches alarms on user's device.
|
|
11
|
+
* Returns matching alarms based on various filter criteria.
|
|
12
|
+
*
|
|
13
|
+
* At least one search criterion must be provided.
|
|
14
|
+
* Multiple criteria can be combined.
|
|
15
|
+
*/
|
|
16
|
+
export const searchAlarmTool = {
|
|
17
|
+
name: "search_alarm",
|
|
18
|
+
label: "Search Alarm",
|
|
19
|
+
description: `ๆฃ็ดข็จๆท่ฎพๅคไธ็้น้ใๆฏๆๅค็งๆฃ็ดขๆกไปถ๏ผ่ณๅฐ้่ฆๆไพไธไธชๆฃ็ดขๆกไปถ๏ผๅคไธชๆกไปถๅฏไปฅ็ปๅไฝฟ็จใ
|
|
20
|
+
|
|
21
|
+
ๆฃ็ดขๆกไปถ๏ผ่ณๅฐๆไพไธไธช๏ผ๏ผ
|
|
22
|
+
- rangeType: ๆฅ่ฏข่ๅด๏ผๆไธพๅผ๏ผall=ๆฅ่ฏขๆๆ้น้๏ผnext=ๆฅๆพไธไธไธชๅ้้น้๏ผcurrent=ไธๅฐๆถๅ
ๆ่ฟไธๆฌกๅขๆฅๆน็้น้
|
|
23
|
+
- alarmState: ้น้ๅผๅฏ็ถๆ๏ผ0=ๅ
ณ้ญ๏ผ1=ๅผๅฏ
|
|
24
|
+
- daysOfWakeType: ้น้ๅ้็ฑปๅ๏ผ0=ๅๆฌกๅ้๏ผ1=ๆณๅฎ่ๅๆฅ๏ผ2=ๆฏๅคฉ๏ผ3=่ชๅฎไนๆถ้ด๏ผ4=ๆณๅฎๅทฅไฝๆฅ
|
|
25
|
+
- startTime: ๆถ้ด้ด้ๅผๅง๏ผๆ ผๅผ YYYYMMDD hhmmss๏ผไพๅฆ๏ผ20240315 000000๏ผ๏ผ้่ฆไธ endTime ไธ่ตทไฝฟ็จ
|
|
26
|
+
- endTime: ๆถ้ด้ด้็ปๆ๏ผๆ ผๅผ YYYYMMDD hhmmss๏ผไพๅฆ๏ผ20240315 235959๏ผ๏ผ้่ฆไธ startTime ไธ่ตทไฝฟ็จ
|
|
27
|
+
|
|
28
|
+
ไฝฟ็จ็คบไพ๏ผ
|
|
29
|
+
- ๆฅ่ฏขๆๆ้น้๏ผ{"rangeType": "all"}
|
|
30
|
+
- ๆฅ่ฏขๅทฒๅผๅฏ็้น้๏ผ{"alarmState": 1}
|
|
31
|
+
- ๆฅ่ฏขๆฏๅคฉๅ้็้น้๏ผ{"daysOfWakeType": 2}
|
|
32
|
+
- ๆฅ่ฏขๆไธชๆถ้ดๆฎต็้น้๏ผ{"startTime": "20240315 000000", "endTime": "20240315 235959"}
|
|
33
|
+
|
|
34
|
+
ๆณจๆ๏ผ
|
|
35
|
+
a. ๆไฝ่ถ
ๆถๆถ้ดไธบ60็ง๏ผ่ฏทๅฟ้ๅค่ฐ็จๆญคๅทฅๅ
ท๏ผๅฆๆ่ถ
ๆถๆๅคฑ่ดฅ๏ผๆๅค้่ฏไธๆฌกใ
|
|
36
|
+
b. ไฝฟ็จ่ฏฅๅทฅๅ
ทไนๅ้่ทๅๅฝๅ็ๅฎๆถ้ด`,
|
|
37
|
+
parameters: {
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {
|
|
40
|
+
rangeType: {
|
|
41
|
+
type: "string",
|
|
42
|
+
enum: ["all", "next", "current"],
|
|
43
|
+
description: "ๆฅ่ฏข่ๅด๏ผall=ๆๆ้น้๏ผnext=ไธไธไธชๅ้้น้๏ผcurrent=ไธๅฐๆถๅ
ๆ่ฟไฟฎๆน็้น้",
|
|
44
|
+
},
|
|
45
|
+
alarmState: {
|
|
46
|
+
type: "number",
|
|
47
|
+
enum: [0, 1],
|
|
48
|
+
description: "้น้ๅผๅฏ็ถๆ๏ผ0=ๅ
ณ้ญ๏ผ1=ๅผๅฏ",
|
|
49
|
+
},
|
|
50
|
+
daysOfWakeType: {
|
|
51
|
+
type: "number",
|
|
52
|
+
enum: [0, 1, 2, 3, 4],
|
|
53
|
+
description: "้น้ๅ้็ฑปๅ๏ผ0=ๅๆฌก๏ผ1=ๆณๅฎ่ๅๆฅ๏ผ2=ๆฏๅคฉ๏ผ3=่ชๅฎไน๏ผ4=ๆณๅฎๅทฅไฝๆฅ",
|
|
54
|
+
},
|
|
55
|
+
startTime: {
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "ๆถ้ด้ด้ๅผๅง๏ผๆ ผๅผ YYYYMMDD hhmmss๏ผไพๅฆ๏ผ20240315 000000๏ผ๏ผๅฟ
้กปไธ endTime ไธ่ตทไฝฟ็จ",
|
|
58
|
+
},
|
|
59
|
+
endTime: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "ๆถ้ด้ด้็ปๆ๏ผๆ ผๅผ YYYYMMDD hhmmss๏ผไพๅฆ๏ผ20240315 235959๏ผ๏ผๅฟ
้กปไธ startTime ไธ่ตทไฝฟ็จ",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
async execute(toolCallId, params) {
|
|
66
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Starting execution`);
|
|
67
|
+
logger.log(`[SEARCH_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
68
|
+
logger.log(`[SEARCH_ALARM_TOOL] - params:`, JSON.stringify(params));
|
|
69
|
+
logger.log(`[SEARCH_ALARM_TOOL] - timestamp: ${new Date().toISOString()}`);
|
|
70
|
+
// ===== Validate at least one search criterion is provided =====
|
|
71
|
+
const hasRangeType = params.rangeType !== undefined && params.rangeType !== null;
|
|
72
|
+
const hasAlarmState = params.alarmState !== undefined && params.alarmState !== null;
|
|
73
|
+
const hasDaysOfWakeType = params.daysOfWakeType !== undefined && params.daysOfWakeType !== null;
|
|
74
|
+
const hasStartTime = params.startTime !== undefined && params.startTime !== null;
|
|
75
|
+
const hasEndTime = params.endTime !== undefined && params.endTime !== null;
|
|
76
|
+
if (!hasRangeType && !hasAlarmState && !hasDaysOfWakeType && !hasStartTime && !hasEndTime) {
|
|
77
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ No search criteria provided`);
|
|
78
|
+
throw new Error("่ณๅฐ้่ฆๆไพไธไธชๆฃ็ดขๆกไปถ๏ผrangeTypeใalarmStateใdaysOfWakeType ๆๆถ้ด่ๅด๏ผstartTime + endTime๏ผ");
|
|
79
|
+
}
|
|
80
|
+
// ===== Validate rangeType =====
|
|
81
|
+
if (hasRangeType) {
|
|
82
|
+
if (typeof params.rangeType !== "string") {
|
|
83
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid rangeType type`);
|
|
84
|
+
throw new Error("rangeType must be a string");
|
|
85
|
+
}
|
|
86
|
+
if (!RANGE_TYPE_VALUES.includes(params.rangeType)) {
|
|
87
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid rangeType value: ${params.rangeType}`);
|
|
88
|
+
throw new Error(`rangeType must be one of: ${RANGE_TYPE_VALUES.join(", ")}`);
|
|
89
|
+
}
|
|
90
|
+
logger.log(`[SEARCH_ALARM_TOOL] - rangeType: ${params.rangeType}`);
|
|
91
|
+
}
|
|
92
|
+
// ===== Validate alarmState =====
|
|
93
|
+
if (hasAlarmState) {
|
|
94
|
+
if (typeof params.alarmState !== "number") {
|
|
95
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid alarmState type`);
|
|
96
|
+
throw new Error("alarmState must be a number");
|
|
97
|
+
}
|
|
98
|
+
if (!ALARM_STATE_VALUES.includes(params.alarmState)) {
|
|
99
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid alarmState value: ${params.alarmState}`);
|
|
100
|
+
throw new Error(`alarmState must be one of: ${ALARM_STATE_VALUES.join(", ")}`);
|
|
101
|
+
}
|
|
102
|
+
logger.log(`[SEARCH_ALARM_TOOL] - alarmState: ${params.alarmState}`);
|
|
103
|
+
}
|
|
104
|
+
// ===== Validate daysOfWakeType =====
|
|
105
|
+
if (hasDaysOfWakeType) {
|
|
106
|
+
if (typeof params.daysOfWakeType !== "number") {
|
|
107
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid daysOfWakeType type`);
|
|
108
|
+
throw new Error("daysOfWakeType must be a number");
|
|
109
|
+
}
|
|
110
|
+
if (!DAYS_OF_WAKE_TYPE_VALUES.includes(params.daysOfWakeType)) {
|
|
111
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid daysOfWakeType value: ${params.daysOfWakeType}`);
|
|
112
|
+
throw new Error(`daysOfWakeType must be one of: ${DAYS_OF_WAKE_TYPE_VALUES.join(", ")}`);
|
|
113
|
+
}
|
|
114
|
+
logger.log(`[SEARCH_ALARM_TOOL] - daysOfWakeType: ${params.daysOfWakeType}`);
|
|
115
|
+
}
|
|
116
|
+
// ===== Validate time interval (startTime and endTime must be provided together) =====
|
|
117
|
+
if (hasStartTime !== hasEndTime) {
|
|
118
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ startTime and endTime must be provided together`);
|
|
119
|
+
throw new Error("startTime ๅ endTime ๅฟ
้กปไธ่ตทๆไพ");
|
|
120
|
+
}
|
|
121
|
+
let timeInterval = null;
|
|
122
|
+
if (hasStartTime && hasEndTime) {
|
|
123
|
+
// Parse and convert startTime and endTime to timestamps
|
|
124
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Parsing time interval...`);
|
|
125
|
+
logger.log(`[SEARCH_ALARM_TOOL] - startTime input: ${params.startTime}`);
|
|
126
|
+
logger.log(`[SEARCH_ALARM_TOOL] - endTime input: ${params.endTime}`);
|
|
127
|
+
const startTimeMs = parseAlarmTimeToTimestamp(params.startTime);
|
|
128
|
+
const endTimeMs = parseAlarmTimeToTimestamp(params.endTime);
|
|
129
|
+
if (startTimeMs === null) {
|
|
130
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid startTime format`);
|
|
131
|
+
throw new Error("Invalid startTime format. Required format: YYYYMMDD hhmmss (e.g., 20240315 000000)");
|
|
132
|
+
}
|
|
133
|
+
if (endTimeMs === null) {
|
|
134
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid endTime format`);
|
|
135
|
+
throw new Error("Invalid endTime format. Required format: YYYYMMDD hhmmss (e.g., 20240315 235959)");
|
|
136
|
+
}
|
|
137
|
+
if (startTimeMs >= endTimeMs) {
|
|
138
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ startTime must be before endTime`);
|
|
139
|
+
throw new Error("startTime ๅฟ
้กปๆฉไบ endTime");
|
|
140
|
+
}
|
|
141
|
+
timeInterval = [startTimeMs, endTimeMs];
|
|
142
|
+
logger.log(`[SEARCH_ALARM_TOOL] โ
Time interval parsed: [${startTimeMs}, ${endTimeMs}]`);
|
|
143
|
+
}
|
|
144
|
+
// Get session context
|
|
145
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Attempting to get session context...`);
|
|
146
|
+
const sessionContext = getCurrentSessionContext();
|
|
147
|
+
if (!sessionContext) {
|
|
148
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ FAILED: No active session found!`);
|
|
149
|
+
logger.error(`[SEARCH_ALARM_TOOL] - toolCallId: ${toolCallId}`);
|
|
150
|
+
throw new Error("No active XY session found. Search alarm tool can only be used during an active conversation.");
|
|
151
|
+
}
|
|
152
|
+
logger.log(`[SEARCH_ALARM_TOOL] โ
Session context found`);
|
|
153
|
+
logger.log(`[SEARCH_ALARM_TOOL] - sessionId: ${sessionContext.sessionId}`);
|
|
154
|
+
logger.log(`[SEARCH_ALARM_TOOL] - taskId: ${sessionContext.taskId}`);
|
|
155
|
+
logger.log(`[SEARCH_ALARM_TOOL] - messageId: ${sessionContext.messageId}`);
|
|
156
|
+
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
157
|
+
// Get WebSocket manager
|
|
158
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Getting WebSocket manager...`);
|
|
159
|
+
const wsManager = getXYWebSocketManager(config);
|
|
160
|
+
logger.log(`[SEARCH_ALARM_TOOL] โ
WebSocket manager obtained`);
|
|
161
|
+
// Build SearchAlarm command
|
|
162
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ฆ Building SearchAlarm command...`);
|
|
163
|
+
// Build intentParam with provided search criteria
|
|
164
|
+
const intentParam = {};
|
|
165
|
+
if (hasRangeType) {
|
|
166
|
+
intentParam.rangeType = params.rangeType;
|
|
167
|
+
}
|
|
168
|
+
if (hasAlarmState) {
|
|
169
|
+
intentParam.alarmState = params.alarmState;
|
|
170
|
+
}
|
|
171
|
+
if (hasDaysOfWakeType) {
|
|
172
|
+
intentParam.daysOfWakeType = params.daysOfWakeType;
|
|
173
|
+
}
|
|
174
|
+
if (timeInterval) {
|
|
175
|
+
intentParam.timeInterval = timeInterval;
|
|
176
|
+
}
|
|
177
|
+
const command = {
|
|
178
|
+
header: {
|
|
179
|
+
namespace: "Common",
|
|
180
|
+
name: "Action",
|
|
181
|
+
},
|
|
182
|
+
payload: {
|
|
183
|
+
cardParam: {},
|
|
184
|
+
executeParam: {
|
|
185
|
+
executeMode: "background",
|
|
186
|
+
intentName: "SearchAlarm",
|
|
187
|
+
bundleName: "com.huawei.hmos.clock",
|
|
188
|
+
needUnlock: true,
|
|
189
|
+
actionResponse: true,
|
|
190
|
+
appType: "OHOS_APP",
|
|
191
|
+
timeOut: 5,
|
|
192
|
+
intentParam,
|
|
193
|
+
permissionId: [],
|
|
194
|
+
achieveType: "INTENT",
|
|
195
|
+
},
|
|
196
|
+
responses: [
|
|
197
|
+
{
|
|
198
|
+
resultCode: "",
|
|
199
|
+
displayText: "",
|
|
200
|
+
ttsText: "",
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
needUploadResult: true,
|
|
204
|
+
noHalfPage: false,
|
|
205
|
+
pageControlRelated: false,
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
// Send command and wait for response (60 second timeout)
|
|
209
|
+
logger.log(`[SEARCH_ALARM_TOOL] โณ Setting up promise to wait for alarm search response...`);
|
|
210
|
+
logger.log(`[SEARCH_ALARM_TOOL] - Timeout: 60 seconds`);
|
|
211
|
+
return new Promise((resolve, reject) => {
|
|
212
|
+
const timeout = setTimeout(() => {
|
|
213
|
+
logger.error(`[SEARCH_ALARM_TOOL] โฐ Timeout: No response received within 60 seconds`);
|
|
214
|
+
wsManager.off("data-event", handler);
|
|
215
|
+
reject(new Error("ๆฃ็ดข้น้่ถ
ๆถ๏ผ60็ง๏ผ"));
|
|
216
|
+
}, 60000);
|
|
217
|
+
// Listen for data events from WebSocket
|
|
218
|
+
const handler = (event) => {
|
|
219
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐จ Received data event:`, JSON.stringify(event));
|
|
220
|
+
if (event.intentName === "SearchAlarm") {
|
|
221
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ฏ SearchAlarm event received`);
|
|
222
|
+
logger.log(`[SEARCH_ALARM_TOOL] - status: ${event.status}`);
|
|
223
|
+
clearTimeout(timeout);
|
|
224
|
+
wsManager.off("data-event", handler);
|
|
225
|
+
if (event.status === "success" && event.outputs) {
|
|
226
|
+
logger.log(`[SEARCH_ALARM_TOOL] โ
Alarm search completed successfully`);
|
|
227
|
+
logger.log(`[SEARCH_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs));
|
|
228
|
+
// Check for error code in outputs
|
|
229
|
+
const code = event.outputs.code !== undefined ? event.outputs.code : null;
|
|
230
|
+
if (code !== null && code !== 0) {
|
|
231
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Device returned error`);
|
|
232
|
+
logger.error(`[SEARCH_ALARM_TOOL] - code: ${code}`);
|
|
233
|
+
const errorMsg = event.outputs.errorMsg || event.outputs.errMsg || "ๆช็ฅ้่ฏฏ";
|
|
234
|
+
logger.error(`[SEARCH_ALARM_TOOL] - errorMsg: ${errorMsg}`);
|
|
235
|
+
reject(new Error(`ๆฃ็ดข้น้ๅคฑ่ดฅ: ${errorMsg} (้่ฏฏไปฃ็ : ${code})`));
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// Extract result.items with safe checks
|
|
239
|
+
const result = event.outputs.result;
|
|
240
|
+
let items = [];
|
|
241
|
+
if (result && typeof result === "object" && Array.isArray(result.items)) {
|
|
242
|
+
items = result.items;
|
|
243
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Found ${items.length} alarm(s)`);
|
|
244
|
+
// Parse JSON strings in items array
|
|
245
|
+
// Items are returned as JSON strings that need to be parsed
|
|
246
|
+
const parsedItems = items.map((itemStr, index) => {
|
|
247
|
+
if (typeof itemStr !== "string") {
|
|
248
|
+
logger.warn(`[SEARCH_ALARM_TOOL] โ ๏ธ Item at index ${index} is not a string:`, typeof itemStr);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const parsed = JSON.parse(itemStr);
|
|
253
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Parsed alarm [${index}]:`, JSON.stringify(parsed));
|
|
254
|
+
return parsed;
|
|
255
|
+
}
|
|
256
|
+
catch (parseError) {
|
|
257
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Failed to parse item at index ${index}:`, parseError);
|
|
258
|
+
logger.error(`[SEARCH_ALARM_TOOL] - itemStr: ${itemStr}`);
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
}).filter((item) => item !== null);
|
|
262
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ Successfully parsed ${parsedItems.length} alarm(s)`);
|
|
263
|
+
resolve({
|
|
264
|
+
content: [
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
text: JSON.stringify(parsedItems),
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
logger.warn(`[SEARCH_ALARM_TOOL] โ ๏ธ No items found in result or result is invalid`);
|
|
274
|
+
logger.warn(`[SEARCH_ALARM_TOOL] - result:`, JSON.stringify(result || {}));
|
|
275
|
+
// Return empty array
|
|
276
|
+
resolve({
|
|
277
|
+
content: [
|
|
278
|
+
{
|
|
279
|
+
type: "text",
|
|
280
|
+
text: "[]",
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Alarm search failed`);
|
|
288
|
+
logger.error(`[SEARCH_ALARM_TOOL] - status: ${event.status}`);
|
|
289
|
+
logger.error(`[SEARCH_ALARM_TOOL] - outputs:`, JSON.stringify(event.outputs || {}));
|
|
290
|
+
reject(new Error(`ๆฃ็ดข้น้ๅคฑ่ดฅ: ${event.status}`));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
// Register event handler
|
|
295
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ก Registering data-event handler on WebSocket manager`);
|
|
296
|
+
wsManager.on("data-event", handler);
|
|
297
|
+
// Send the command
|
|
298
|
+
logger.log(`[SEARCH_ALARM_TOOL] ๐ค Sending SearchAlarm command...`);
|
|
299
|
+
sendCommand({
|
|
300
|
+
config,
|
|
301
|
+
sessionId,
|
|
302
|
+
taskId,
|
|
303
|
+
messageId,
|
|
304
|
+
command,
|
|
305
|
+
})
|
|
306
|
+
.then(() => {
|
|
307
|
+
logger.log(`[SEARCH_ALARM_TOOL] โ
Command sent successfully, waiting for response...`);
|
|
308
|
+
})
|
|
309
|
+
.catch((error) => {
|
|
310
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Failed to send command:`, error);
|
|
311
|
+
clearTimeout(timeout);
|
|
312
|
+
wsManager.off("data-event", handler);
|
|
313
|
+
reject(error);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* Parse alarmTime string (YYYYMMDD hhmmss) to timestamp in milliseconds
|
|
320
|
+
* @param alarmTime - Time string in format "YYYYMMDD hhmmss" (e.g., "20240315 143000")
|
|
321
|
+
* @returns Timestamp in milliseconds, or null if parsing fails
|
|
322
|
+
*/
|
|
323
|
+
function parseAlarmTimeToTimestamp(alarmTime) {
|
|
324
|
+
try {
|
|
325
|
+
// Expected format: YYYYMMDD hhmmss
|
|
326
|
+
// Example: 20240315 143000
|
|
327
|
+
const trimmed = alarmTime.trim();
|
|
328
|
+
// Check basic format (should have at least 13 characters: YYYYMMDD hhmmss)
|
|
329
|
+
if (trimmed.length < 13) {
|
|
330
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ alarmTime too short: ${trimmed}`);
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
// Extract date and time parts
|
|
334
|
+
// Format: YYYYMMDD hhmmss
|
|
335
|
+
const datePart = trimmed.substring(0, 8); // YYYYMMDD
|
|
336
|
+
const timePart = trimmed.substring(8).trim(); // hhmmss (may have leading space)
|
|
337
|
+
logger.log(`[SEARCH_ALARM_TOOL] - datePart: ${datePart}, timePart: ${timePart}`);
|
|
338
|
+
// Validate lengths
|
|
339
|
+
if (datePart.length !== 8 || timePart.length !== 6) {
|
|
340
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid part lengths: datePart=${datePart.length}, timePart=${timePart.length}`);
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
// Parse components
|
|
344
|
+
const year = parseInt(datePart.substring(0, 4), 10);
|
|
345
|
+
const month = parseInt(datePart.substring(4, 6), 10);
|
|
346
|
+
const day = parseInt(datePart.substring(6, 8), 10);
|
|
347
|
+
const hour = parseInt(timePart.substring(0, 2), 10);
|
|
348
|
+
const minute = parseInt(timePart.substring(2, 4), 10);
|
|
349
|
+
const second = parseInt(timePart.substring(4, 6), 10);
|
|
350
|
+
logger.log(`[SEARCH_ALARM_TOOL] - Parsed: ${year}-${month}-${day} ${hour}:${minute}:${second}`);
|
|
351
|
+
// Validate values
|
|
352
|
+
if (isNaN(year) || isNaN(month) || isNaN(day) ||
|
|
353
|
+
isNaN(hour) || isNaN(minute) || isNaN(second)) {
|
|
354
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ NaN detected in parsed values`);
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
// Validate ranges
|
|
358
|
+
if (month < 1 || month > 12) {
|
|
359
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid month: ${month}`);
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
if (day < 1 || day > 31) {
|
|
363
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid day: ${day}`);
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
if (hour < 0 || hour > 23) {
|
|
367
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid hour: ${hour}`);
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
if (minute < 0 || minute > 59) {
|
|
371
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid minute: ${minute}`);
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
if (second < 0 || second > 59) {
|
|
375
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Invalid second: ${second}`);
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
// Create Date object and get timestamp
|
|
379
|
+
const date = new Date(year, month - 1, day, hour, minute, second);
|
|
380
|
+
const timestamp = date.getTime();
|
|
381
|
+
if (isNaN(timestamp)) {
|
|
382
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Generated timestamp is NaN`);
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
return timestamp;
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
logger.error(`[SEARCH_ALARM_TOOL] โ Exception in parseAlarmTimeToTimestamp:`, error);
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XY search calendar event tool - searches calendar events on user's device.
|
|
3
|
+
* Returns matching events based on time range and optional title filter.
|
|
4
|
+
*
|
|
5
|
+
* Time range guidelines:
|
|
6
|
+
* - For a specific day: use 00:00:00 to 23:59:59 of that day
|
|
7
|
+
* - For morning: 06:00:00 to 12:00:00
|
|
8
|
+
* - For afternoon: 12:00:00 to 18:00:00
|
|
9
|
+
* - For evening: 18:00:00 to 24:00:00
|
|
10
|
+
* - For a specific time: use ยฑ1 hour range (e.g., for 3PM, use 14:00:00 to 16:00:00)
|
|
11
|
+
*/
|
|
12
|
+
export declare const searchCalendarTool: any;
|