@ynhcj/xiaoyi-channel 0.0.167-next → 0.0.168-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/reply-dispatcher.js +36 -29
- package/dist/src/task-manager.d.ts +11 -0
- package/dist/src/task-manager.js +17 -0
- package/dist/src/tools/agent-as-skill-tool.js +3 -1
- package/dist/src/tools/calendar-tool.js +3 -1
- package/dist/src/tools/call-device-tool.js +3 -1
- package/dist/src/tools/call-phone-tool.js +3 -1
- package/dist/src/tools/check-plugin-privilege-tool.js +3 -1
- package/dist/src/tools/create-alarm-tool.js +3 -1
- package/dist/src/tools/delete-alarm-tool.js +3 -1
- package/dist/src/tools/discover-cross-devices-tool.js +3 -1
- package/dist/src/tools/display-a2ui-card-tool.js +3 -1
- package/dist/src/tools/image-reading-tool.js +3 -1
- package/dist/src/tools/location-tool.js +3 -1
- package/dist/src/tools/login-token-tool.js +3 -1
- package/dist/src/tools/modify-alarm-tool.js +3 -1
- package/dist/src/tools/modify-note-tool.js +3 -1
- package/dist/src/tools/note-tool.js +3 -1
- package/dist/src/tools/query-app-message-tool.js +3 -1
- package/dist/src/tools/query-memory-data-tool.js +3 -1
- package/dist/src/tools/query-todo-task-tool.js +3 -1
- package/dist/src/tools/save-file-to-phone-tool.js +3 -1
- package/dist/src/tools/save-media-to-gallery-tool.js +3 -1
- package/dist/src/tools/save-self-evolution-skill-tool.js +3 -1
- package/dist/src/tools/search-alarm-tool.js +3 -1
- package/dist/src/tools/search-calendar-tool.js +3 -1
- package/dist/src/tools/search-contact-tool.js +3 -1
- package/dist/src/tools/search-email-tool.js +3 -1
- package/dist/src/tools/search-file-tool.js +3 -1
- package/dist/src/tools/search-message-tool.js +3 -1
- package/dist/src/tools/search-note-tool.js +3 -1
- package/dist/src/tools/search-photo-gallery-tool.js +3 -1
- package/dist/src/tools/send-cross-device-task-tool.js +3 -1
- package/dist/src/tools/send-email-tool.js +3 -1
- package/dist/src/tools/send-file-to-user-tool.d.ts +1 -1
- package/dist/src/tools/send-file-to-user-tool.js +3 -2
- package/dist/src/tools/send-html-card-tool.js +3 -1
- package/dist/src/tools/send-message-tool.js +3 -1
- package/dist/src/tools/session-manager.d.ts +6 -4
- package/dist/src/tools/session-manager.js +14 -4
- package/dist/src/tools/upload-file-tool.js +3 -1
- package/dist/src/tools/upload-photo-tool.js +3 -1
- package/dist/src/tools/xiaoyi-add-collection-tool.js +3 -1
- package/dist/src/tools/xiaoyi-collection-tool.js +3 -1
- package/dist/src/tools/xiaoyi-delete-collection-tool.js +3 -1
- package/dist/src/tools/xiaoyi-gui-tool.js +3 -2
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import { clearRunCrossTaskSentFiles, getCurrentSessionContext } from "./tools/se
|
|
|
5
5
|
import fs from "fs/promises";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { logger } from "./utils/logger.js";
|
|
8
|
+
import { getCurrentTaskId, getCurrentMessageId } from "./task-manager.js";
|
|
8
9
|
const TEMP_FILE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
9
10
|
const RUN_CROSS_TASK_LOG_TAG = "[RunCrossTask]";
|
|
10
11
|
function buildDistributionStatusCommand(context) {
|
|
@@ -99,8 +100,13 @@ export function createXYReplyDispatcher(params) {
|
|
|
99
100
|
// 初始taskId和messageId(作为fallback)
|
|
100
101
|
const initialTaskId = taskId;
|
|
101
102
|
const initialMessageId = messageId;
|
|
102
|
-
|
|
103
|
-
const
|
|
103
|
+
// 跨链读取:steer 消息通过 registerTaskId 更新 Map,这里读取最新 taskId
|
|
104
|
+
const getActiveTaskId = () => {
|
|
105
|
+
return getCurrentTaskId(sessionId) ?? initialTaskId;
|
|
106
|
+
};
|
|
107
|
+
const getActiveMessageId = () => {
|
|
108
|
+
return getCurrentMessageId(sessionId) ?? initialMessageId;
|
|
109
|
+
};
|
|
104
110
|
// Create a scoped logger that always uses this session's sessionId
|
|
105
111
|
// and dynamically resolves the latest taskId
|
|
106
112
|
const scopedLog = () => logger.withContext(sessionId, getActiveTaskId());
|
|
@@ -129,12 +135,13 @@ export function createXYReplyDispatcher(params) {
|
|
|
129
135
|
scopedLog().log(`[STATUS-INTERVAL] Starting interval`);
|
|
130
136
|
statusUpdateInterval = setInterval(() => {
|
|
131
137
|
// 🔑 使用动态taskId
|
|
132
|
-
|
|
138
|
+
const currentTaskId = getActiveTaskId();
|
|
139
|
+
scopedLog().log(`[STATUS-INTERVAL] Triggering status update, taskId=${currentTaskId}`);
|
|
133
140
|
void sendStatusUpdate({
|
|
134
141
|
config,
|
|
135
142
|
sessionId,
|
|
136
|
-
taskId,
|
|
137
|
-
messageId,
|
|
143
|
+
taskId: currentTaskId,
|
|
144
|
+
messageId: getActiveMessageId(),
|
|
138
145
|
text: "任务正在处理中,请稍候~",
|
|
139
146
|
state: "working",
|
|
140
147
|
}).catch((err) => {
|
|
@@ -184,8 +191,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
184
191
|
await sendA2AResponse({
|
|
185
192
|
config,
|
|
186
193
|
sessionId,
|
|
187
|
-
taskId,
|
|
188
|
-
messageId,
|
|
194
|
+
taskId: getActiveTaskId(),
|
|
195
|
+
messageId: getActiveMessageId(),
|
|
189
196
|
text,
|
|
190
197
|
append: true,
|
|
191
198
|
final: false,
|
|
@@ -208,8 +215,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
208
215
|
await sendStatusUpdate({
|
|
209
216
|
config,
|
|
210
217
|
sessionId,
|
|
211
|
-
taskId,
|
|
212
|
-
messageId,
|
|
218
|
+
taskId: getActiveTaskId(),
|
|
219
|
+
messageId: getActiveMessageId(),
|
|
213
220
|
text: "处理失败,请稍后重试",
|
|
214
221
|
state: "failed",
|
|
215
222
|
});
|
|
@@ -240,8 +247,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
240
247
|
await sendRunCrossTaskResult({
|
|
241
248
|
config,
|
|
242
249
|
sessionId,
|
|
243
|
-
taskId,
|
|
244
|
-
messageId,
|
|
250
|
+
taskId: getActiveTaskId(),
|
|
251
|
+
messageId: getActiveMessageId(),
|
|
245
252
|
context: runCrossTaskContext,
|
|
246
253
|
resultCode: "0",
|
|
247
254
|
resultMessage: crossTaskResultMessage,
|
|
@@ -251,8 +258,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
251
258
|
await sendStatusUpdate({
|
|
252
259
|
config,
|
|
253
260
|
sessionId,
|
|
254
|
-
taskId,
|
|
255
|
-
messageId,
|
|
261
|
+
taskId: getActiveTaskId(),
|
|
262
|
+
messageId: getActiveMessageId(),
|
|
256
263
|
text: "任务处理已完成~",
|
|
257
264
|
state: "completed",
|
|
258
265
|
});
|
|
@@ -261,8 +268,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
261
268
|
await sendA2AResponse({
|
|
262
269
|
config,
|
|
263
270
|
sessionId,
|
|
264
|
-
taskId,
|
|
265
|
-
messageId,
|
|
271
|
+
taskId: getActiveTaskId(),
|
|
272
|
+
messageId: getActiveMessageId(),
|
|
266
273
|
text: "",
|
|
267
274
|
append: true,
|
|
268
275
|
final: true,
|
|
@@ -283,8 +290,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
283
290
|
await sendRunCrossTaskResult({
|
|
284
291
|
config,
|
|
285
292
|
sessionId,
|
|
286
|
-
taskId,
|
|
287
|
-
messageId,
|
|
293
|
+
taskId: getActiveTaskId(),
|
|
294
|
+
messageId: getActiveMessageId(),
|
|
288
295
|
context: runCrossTaskContext,
|
|
289
296
|
resultCode: "1",
|
|
290
297
|
resultMessage: "任务执行异常,请重试",
|
|
@@ -293,8 +300,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
293
300
|
await sendStatusUpdate({
|
|
294
301
|
config,
|
|
295
302
|
sessionId,
|
|
296
|
-
taskId,
|
|
297
|
-
messageId,
|
|
303
|
+
taskId: getActiveTaskId(),
|
|
304
|
+
messageId: getActiveMessageId(),
|
|
298
305
|
text: "任务处理中断了~",
|
|
299
306
|
state: "failed",
|
|
300
307
|
});
|
|
@@ -302,8 +309,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
302
309
|
await sendA2AResponse({
|
|
303
310
|
config,
|
|
304
311
|
sessionId,
|
|
305
|
-
taskId,
|
|
306
|
-
messageId,
|
|
312
|
+
taskId: getActiveTaskId(),
|
|
313
|
+
messageId: getActiveMessageId(),
|
|
307
314
|
text: "任务执行异常,请重试~",
|
|
308
315
|
append: true,
|
|
309
316
|
final: true,
|
|
@@ -347,8 +354,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
347
354
|
await sendStatusUpdate({
|
|
348
355
|
config,
|
|
349
356
|
sessionId,
|
|
350
|
-
taskId,
|
|
351
|
-
messageId,
|
|
357
|
+
taskId: getActiveTaskId(),
|
|
358
|
+
messageId: getActiveMessageId(),
|
|
352
359
|
text: `正在使用工具: ${toolName}...`,
|
|
353
360
|
state: "working",
|
|
354
361
|
});
|
|
@@ -373,8 +380,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
373
380
|
await sendStatusUpdate({
|
|
374
381
|
config,
|
|
375
382
|
sessionId,
|
|
376
|
-
taskId,
|
|
377
|
-
messageId,
|
|
383
|
+
taskId: getActiveTaskId(),
|
|
384
|
+
messageId: getActiveMessageId(),
|
|
378
385
|
text: resultText,
|
|
379
386
|
state: "working",
|
|
380
387
|
});
|
|
@@ -401,8 +408,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
401
408
|
await sendReasoningTextUpdate({
|
|
402
409
|
config,
|
|
403
410
|
sessionId,
|
|
404
|
-
taskId,
|
|
405
|
-
messageId,
|
|
411
|
+
taskId: getActiveTaskId(),
|
|
412
|
+
messageId: getActiveMessageId(),
|
|
406
413
|
text,
|
|
407
414
|
append: false,
|
|
408
415
|
});
|
|
@@ -425,8 +432,8 @@ export function createXYReplyDispatcher(params) {
|
|
|
425
432
|
await sendA2AResponse({
|
|
426
433
|
config,
|
|
427
434
|
sessionId,
|
|
428
|
-
taskId,
|
|
429
|
-
messageId,
|
|
435
|
+
taskId: getActiveTaskId(),
|
|
436
|
+
messageId: getActiveMessageId(),
|
|
430
437
|
text,
|
|
431
438
|
append: false,
|
|
432
439
|
final: false,
|
|
@@ -13,6 +13,17 @@ export declare function registerTaskId(sessionId: string, taskId: string, messag
|
|
|
13
13
|
* 移除session的活跃taskId(消息处理完成时调用)。
|
|
14
14
|
*/
|
|
15
15
|
export declare function decrementTaskIdRef(sessionId: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* 获取session的当前活跃taskId。
|
|
18
|
+
* 仅供 reply-dispatcher 跨链读取 steer 更新后的 taskId。
|
|
19
|
+
* 工具和 sendCommand 应使用 ALS SessionContext.taskId。
|
|
20
|
+
*/
|
|
21
|
+
export declare function getCurrentTaskId(sessionId: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* 获取session的当前活跃messageId。
|
|
24
|
+
* 仅供 reply-dispatcher 跨链读取 steer 更新后的 messageId。
|
|
25
|
+
*/
|
|
26
|
+
export declare function getCurrentMessageId(sessionId: string): string | null;
|
|
16
27
|
/**
|
|
17
28
|
* 检查session是否有活跃的taskId
|
|
18
29
|
*/
|
package/dist/src/task-manager.js
CHANGED
|
@@ -43,6 +43,23 @@ export function decrementTaskIdRef(sessionId) {
|
|
|
43
43
|
logger.log(`[TASK_MANAGER] Removing taskId`);
|
|
44
44
|
activeTaskIds.delete(sessionId);
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* 获取session的当前活跃taskId。
|
|
48
|
+
* 仅供 reply-dispatcher 跨链读取 steer 更新后的 taskId。
|
|
49
|
+
* 工具和 sendCommand 应使用 ALS SessionContext.taskId。
|
|
50
|
+
*/
|
|
51
|
+
export function getCurrentTaskId(sessionId) {
|
|
52
|
+
const binding = activeTaskIds.get(sessionId);
|
|
53
|
+
return binding?.currentTaskId ?? null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 获取session的当前活跃messageId。
|
|
57
|
+
* 仅供 reply-dispatcher 跨链读取 steer 更新后的 messageId。
|
|
58
|
+
*/
|
|
59
|
+
export function getCurrentMessageId(sessionId) {
|
|
60
|
+
const binding = activeTaskIds.get(sessionId);
|
|
61
|
+
return binding?.currentMessageId ?? null;
|
|
62
|
+
}
|
|
46
63
|
/**
|
|
47
64
|
* 检查session是否有活跃的taskId
|
|
48
65
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Agent-as-skill tool implementation - invokes another agent as a skill
|
|
2
2
|
import { getXYWebSocketManager } from "../client.js";
|
|
3
3
|
import { sendCommand } from "../formatter.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import { logger } from "../utils/logger.js";
|
|
5
6
|
import { XYFileUploadService } from "../file-upload.js";
|
|
6
7
|
/**
|
|
@@ -9,7 +10,6 @@ import { XYFileUploadService } from "../file-upload.js";
|
|
|
9
10
|
* forwards the request to the target agent via WebSocket, and returns the result.
|
|
10
11
|
*/
|
|
11
12
|
export function createAgentAsSkillTool(ctx) {
|
|
12
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
13
13
|
return {
|
|
14
14
|
name: "agent_as_a_tool",
|
|
15
15
|
label: "Agent as Skill Tool",
|
|
@@ -65,6 +65,8 @@ export function createAgentAsSkillTool(ctx) {
|
|
|
65
65
|
required: ["agentId", "query"],
|
|
66
66
|
},
|
|
67
67
|
async execute(toolCallId, params) {
|
|
68
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
69
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
68
70
|
// Dynamic lookup: use latest taskId from task-manager (handles steer/interrupt)
|
|
69
71
|
// Validate parameters
|
|
70
72
|
if (!params.agentId || typeof params.agentId !== "string") {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* XY calendar event tool - creates a calendar event on user's device.
|
|
@@ -7,7 +8,6 @@ import { logger } from "../utils/logger.js";
|
|
|
7
8
|
* Time format must be: yyyy-mm-dd hh:mm:ss
|
|
8
9
|
*/
|
|
9
10
|
export function createCalendarTool(ctx) {
|
|
10
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
11
11
|
return {
|
|
12
12
|
name: "create_calendar_event",
|
|
13
13
|
label: "Create Calendar Event",
|
|
@@ -35,6 +35,8 @@ export function createCalendarTool(ctx) {
|
|
|
35
35
|
required: ["title", "dtStart", "dtEnd"],
|
|
36
36
|
},
|
|
37
37
|
async execute(toolCallId, params) {
|
|
38
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
39
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
38
40
|
// Validate parameters
|
|
39
41
|
if (!params.title || !params.dtStart || !params.dtEnd) {
|
|
40
42
|
throw new Error("Missing required parameters: title, dtStart, and dtEnd are required");
|
|
@@ -23,12 +23,12 @@ import { createSaveFileToPhoneTool } from "./save-file-to-phone-tool.js";
|
|
|
23
23
|
import { createSendEmailTool } from "./send-email-tool.js";
|
|
24
24
|
import { createSearchEmailTool } from "./search-email-tool.js";
|
|
25
25
|
import { sendStatusUpdate } from "../formatter.js";
|
|
26
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
26
27
|
/**
|
|
27
28
|
* call_device_tool - 通用端工具调度器。
|
|
28
29
|
* LLM 必须先通过 get_xxx_tool_schema 获取具体工具 schema,再用本工具执行。
|
|
29
30
|
*/
|
|
30
31
|
export function createCallDeviceTool(ctx) {
|
|
31
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
32
32
|
const noteTool = createNoteTool(ctx);
|
|
33
33
|
const modifyNoteTool = createModifyNoteTool(ctx);
|
|
34
34
|
const createAlarmTool = makeAlarmTool(ctx);
|
|
@@ -101,6 +101,8 @@ export function createCallDeviceTool(ctx) {
|
|
|
101
101
|
required: ["toolName", "arguments"],
|
|
102
102
|
},
|
|
103
103
|
async execute(toolCallId, params) {
|
|
104
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
105
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
104
106
|
const { toolName, arguments: toolArgs } = params;
|
|
105
107
|
// 向用户端发送具体工具名的状态更新
|
|
106
108
|
try {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* XY call phone tool - makes a phone call on user's device.
|
|
6
7
|
* Requires phoneNumber parameter and optional slotId (0 for primary SIM, 1 for secondary SIM).
|
|
7
8
|
*/
|
|
8
9
|
export function createCallPhoneTool(ctx) {
|
|
9
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
10
10
|
return {
|
|
11
11
|
name: "call_phone",
|
|
12
12
|
label: "Call Phone",
|
|
@@ -27,6 +27,8 @@ export function createCallPhoneTool(ctx) {
|
|
|
27
27
|
required: ["phoneNumber"],
|
|
28
28
|
},
|
|
29
29
|
async execute(toolCallId, params) {
|
|
30
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
31
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
30
32
|
// Validate phoneNumber parameter
|
|
31
33
|
if (!params.phoneNumber || typeof params.phoneNumber !== "string" || params.phoneNumber.trim() === "") {
|
|
32
34
|
throw new Error("Missing required parameter: phoneNumber must be a non-empty string");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Check plugin privilege tool implementation
|
|
2
2
|
import { getXYWebSocketManager } from "../client.js";
|
|
3
3
|
import { sendCommand } from "../formatter.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import { logger } from "../utils/logger.js";
|
|
5
6
|
/**
|
|
6
7
|
* Mapping from intent name to required permission IDs.
|
|
@@ -32,7 +33,6 @@ const INTENT_PERMISSION_MAP = {
|
|
|
32
33
|
* used in scheduled tasks.
|
|
33
34
|
*/
|
|
34
35
|
export function createCheckPluginPrivilegeTool(ctx) {
|
|
35
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
36
36
|
return {
|
|
37
37
|
name: "check_plugin_privilege",
|
|
38
38
|
label: "Check Plugin Privilege",
|
|
@@ -75,6 +75,8 @@ export function createCheckPluginPrivilegeTool(ctx) {
|
|
|
75
75
|
required: ["checkIntentName"],
|
|
76
76
|
},
|
|
77
77
|
async execute(toolCallId, params) {
|
|
78
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
79
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
78
80
|
const { checkIntentName } = params;
|
|
79
81
|
// Look up permission IDs for the given intent name
|
|
80
82
|
const permissionId = INTENT_PERMISSION_MAP[checkIntentName];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
// Enum definitions for alarm parameters
|
|
5
6
|
const ALARM_SNOOZE_DURATION_VALUES = [5, 10, 15, 20, 25, 30];
|
|
@@ -14,7 +15,6 @@ const DAYS_OF_WEEK_VALUES = ["Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"];
|
|
|
14
15
|
* Time format: YYYYMMDD hhmmss (e.g., 20240315 143000)
|
|
15
16
|
*/
|
|
16
17
|
export function makeAlarmTool(ctx) {
|
|
17
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
18
18
|
return {
|
|
19
19
|
name: "create_alarm",
|
|
20
20
|
label: "Create Alarm",
|
|
@@ -61,6 +61,8 @@ b. 使用该工具之前需获取当前真实时间
|
|
|
61
61
|
required: ["alarmTime"],
|
|
62
62
|
},
|
|
63
63
|
async execute(toolCallId, params) {
|
|
64
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
65
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
64
66
|
// ===== Validate required parameter: alarmTime =====
|
|
65
67
|
if (!params.alarmTime || typeof params.alarmTime !== "string") {
|
|
66
68
|
throw new Error("Missing required parameter: alarmTime must be a string in format YYYYMMDD hhmmss");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* XY delete alarm tool - deletes existing alarms on user's device.
|
|
@@ -12,7 +13,6 @@ import { logger } from "../utils/logger.js";
|
|
|
12
13
|
* Supports deleting single or multiple alarms in one call.
|
|
13
14
|
*/
|
|
14
15
|
export function createDeleteAlarmTool(ctx) {
|
|
15
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
16
16
|
return {
|
|
17
17
|
name: "delete_alarm",
|
|
18
18
|
label: "Delete Alarm",
|
|
@@ -40,6 +40,8 @@ export function createDeleteAlarmTool(ctx) {
|
|
|
40
40
|
required: ["items"],
|
|
41
41
|
},
|
|
42
42
|
async execute(toolCallId, params) {
|
|
43
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
44
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
43
45
|
// ===== 参数规范化:兼容数组和 JSON 字符串 =====
|
|
44
46
|
let items = null;
|
|
45
47
|
if (!params.items) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sendCommand, sendStatusUpdate } from "../formatter.js";
|
|
2
2
|
import { getXYWebSocketManager } from "../client.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
const DISCOVER_DEVICES_INTENT = "SearchAllDeviceInfo";
|
|
5
6
|
const DISCOVER_DEVICES_BUNDLE = "com.huawei.hmos.vassistant";
|
|
@@ -97,7 +98,6 @@ function recommendDevices(query, devices) {
|
|
|
97
98
|
};
|
|
98
99
|
}
|
|
99
100
|
export function createDiscoverCrossDevicesTool(ctx) {
|
|
100
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
101
101
|
return {
|
|
102
102
|
name: "discover_cross_devices",
|
|
103
103
|
label: "发现跨设备协作设备",
|
|
@@ -117,6 +117,8 @@ export function createDiscoverCrossDevicesTool(ctx) {
|
|
|
117
117
|
required: ["query"],
|
|
118
118
|
},
|
|
119
119
|
async execute(_toolCallId, params) {
|
|
120
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
121
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
120
122
|
const query = typeof params.query === "string" ? params.query.trim() : "";
|
|
121
123
|
logger.log(`${LOG_TAG} tool invoked`);
|
|
122
124
|
if (!query) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sendCommand } from "../formatter.js";
|
|
2
2
|
import { logger } from "../utils/logger.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
class ToolInputError extends Error {
|
|
4
5
|
status = 400;
|
|
5
6
|
constructor(message) {
|
|
@@ -11,7 +12,6 @@ function isJsonObjectOrArray(value) {
|
|
|
11
12
|
return !!value && typeof value === "object";
|
|
12
13
|
}
|
|
13
14
|
export function createDisplayA2UICardTool(ctx) {
|
|
14
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
15
15
|
return {
|
|
16
16
|
name: "displayA2UICard",
|
|
17
17
|
label: "Display A2UI Card",
|
|
@@ -34,6 +34,8 @@ export function createDisplayA2UICardTool(ctx) {
|
|
|
34
34
|
required: ["cardId", "cardData"],
|
|
35
35
|
},
|
|
36
36
|
async execute(toolCallId, params) {
|
|
37
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
38
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
37
39
|
const cardId = typeof params?.cardId === "string" ? params.cardId.trim() : "";
|
|
38
40
|
const cardData = params?.cardData;
|
|
39
41
|
if (!cardId) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Image Reading tool implementation
|
|
2
2
|
import { createHash } from "crypto";
|
|
3
3
|
import { XYFileUploadService } from "../file-upload.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import fetch from "node-fetch";
|
|
5
6
|
import fs from "fs/promises";
|
|
6
7
|
import { v4 as uuidv4 } from "uuid";
|
|
@@ -166,7 +167,6 @@ async function callImageUnderstandingAPI(imageUrls, text, apiKey, uid, fileUploa
|
|
|
166
167
|
* Supports both local file paths and remote URLs, up to 10 images at once.
|
|
167
168
|
*/
|
|
168
169
|
export function createImageReadingTool(ctx) {
|
|
169
|
-
const { config, sessionId } = ctx;
|
|
170
170
|
return {
|
|
171
171
|
name: "image_reading",
|
|
172
172
|
label: "Image Reading",
|
|
@@ -187,6 +187,8 @@ export function createImageReadingTool(ctx) {
|
|
|
187
187
|
required: ["images"],
|
|
188
188
|
},
|
|
189
189
|
async execute(toolCallId, params) {
|
|
190
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
191
|
+
const { config, sessionId } = _c;
|
|
190
192
|
// Normalize images param
|
|
191
193
|
const images = params.images
|
|
192
194
|
? (Array.isArray(params.images) ? params.images : [params.images])
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* XY location tool - gets user's current location.
|
|
6
7
|
* Returns WGS84 coordinates (latitude, longitude).
|
|
7
8
|
*/
|
|
8
9
|
export function createLocationTool(ctx) {
|
|
9
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
10
10
|
return {
|
|
11
11
|
name: "get_user_location",
|
|
12
12
|
label: "Get User Location",
|
|
@@ -17,6 +17,8 @@ export function createLocationTool(ctx) {
|
|
|
17
17
|
required: [],
|
|
18
18
|
},
|
|
19
19
|
async execute(toolCallId, params) {
|
|
20
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
21
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
20
22
|
// Get WebSocket manager
|
|
21
23
|
const wsManager = getXYWebSocketManager(config);
|
|
22
24
|
// Build GetCurrentLocation command
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Login Token tool - 自动获取用户授权信息
|
|
2
2
|
import { v4 as uuidv4 } from "uuid";
|
|
3
3
|
import { getXYWebSocketManager } from "../client.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import { readFileSync, existsSync } from "fs";
|
|
5
6
|
import { logger } from "../utils/logger.js";
|
|
6
7
|
const TOKEN_FILE_PATH = "/home/sandbox/.openclaw/.xiaoyitoken.json";
|
|
@@ -12,7 +13,6 @@ const TOKEN_VALIDITY_MS = 5 * 60 * 1000; // 5 minutes
|
|
|
12
13
|
* 当 skill 依赖用户获取鉴权信息时,此工具协助用户快速获取鉴权信息。
|
|
13
14
|
*/
|
|
14
15
|
export function createLoginTokenTool(ctx) {
|
|
15
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
16
16
|
return {
|
|
17
17
|
name: "huawei_id_tool",
|
|
18
18
|
label: "Get Login Token",
|
|
@@ -32,6 +32,8 @@ export function createLoginTokenTool(ctx) {
|
|
|
32
32
|
required: ["clientId", "skillName"],
|
|
33
33
|
},
|
|
34
34
|
async execute(toolCallId, params) {
|
|
35
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
36
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
35
37
|
const { clientId, skillName } = params;
|
|
36
38
|
if (!clientId || typeof clientId !== "string" || clientId.trim() === "") {
|
|
37
39
|
throw new Error("Missing required parameter: clientId must be a non-empty string");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
// Enum definitions for alarm parameters (same as create-alarm-tool)
|
|
5
6
|
const ALARM_SNOOZE_DURATION_VALUES = [5, 10, 15, 20, 25, 30];
|
|
@@ -16,7 +17,6 @@ const DAYS_OF_WEEK_VALUES = ["Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"];
|
|
|
16
17
|
* 2. Use the entityId to identify which alarm to modify
|
|
17
18
|
*/
|
|
18
19
|
export function createModifyAlarmTool(ctx) {
|
|
19
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
20
20
|
return {
|
|
21
21
|
name: "modify_alarm",
|
|
22
22
|
label: "Modify Alarm",
|
|
@@ -74,6 +74,8 @@ export function createModifyAlarmTool(ctx) {
|
|
|
74
74
|
required: ["entityId"],
|
|
75
75
|
},
|
|
76
76
|
async execute(toolCallId, params) {
|
|
77
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
78
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
77
79
|
// Coerce numeric string params to actual numbers
|
|
78
80
|
// The model may produce "1" instead of 1, which would fail typeof checks
|
|
79
81
|
const numericParams = [
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* XY modify note tool - appends content to an existing note on user's device.
|
|
@@ -10,7 +11,6 @@ import { logger } from "../utils/logger.js";
|
|
|
10
11
|
* 2. Use the entityId to append content to that note
|
|
11
12
|
*/
|
|
12
13
|
export function createModifyNoteTool(ctx) {
|
|
13
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
14
14
|
return {
|
|
15
15
|
name: "modify_note",
|
|
16
16
|
label: "Modify Note",
|
|
@@ -30,6 +30,8 @@ export function createModifyNoteTool(ctx) {
|
|
|
30
30
|
required: ["entityId", "text"],
|
|
31
31
|
},
|
|
32
32
|
async execute(toolCallId, params) {
|
|
33
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
34
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
33
35
|
// Validate parameters
|
|
34
36
|
if (!params.entityId || !params.text) {
|
|
35
37
|
throw new Error("Missing required parameters: entityId and text are required");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* Duck-typed ToolInputError: openclaw 按 .name 字段匹配,不用 instanceof。
|
|
@@ -18,7 +19,6 @@ class ToolInputError extends Error {
|
|
|
18
19
|
* Requires title and content parameters.
|
|
19
20
|
*/
|
|
20
21
|
export function createNoteTool(ctx) {
|
|
21
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
22
22
|
return {
|
|
23
23
|
name: "create_note",
|
|
24
24
|
label: "Create Note",
|
|
@@ -45,6 +45,8 @@ export function createNoteTool(ctx) {
|
|
|
45
45
|
required: ["title", "content"],
|
|
46
46
|
},
|
|
47
47
|
async execute(toolCallId, params) {
|
|
48
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
49
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
48
50
|
// Validate parameters — 抛 ToolInputError 而非普通 Error,
|
|
49
51
|
// 让 openclaw 返回 400 而非 500,明确告知 LLM 这是参数错误,不应重试。
|
|
50
52
|
if (typeof params.title !== "string" || !params.title) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// QueryAppMessage tool implementation
|
|
2
2
|
import { getXYWebSocketManager } from "../client.js";
|
|
3
3
|
import { sendCommand } from "../formatter.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import { logger } from "../utils/logger.js";
|
|
5
6
|
class ToolInputError extends Error {
|
|
6
7
|
status = 400;
|
|
@@ -13,7 +14,6 @@ class ToolInputError extends Error {
|
|
|
13
14
|
* 查询指定时间范围内的设备通知消息。
|
|
14
15
|
*/
|
|
15
16
|
export function createQueryAppMessageTool(ctx) {
|
|
16
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
17
17
|
return {
|
|
18
18
|
name: "query_app_message",
|
|
19
19
|
label: "Query App Message",
|
|
@@ -47,6 +47,8 @@ c. 调用工具前需认真检查调用参数是否满足工具要求
|
|
|
47
47
|
required: [],
|
|
48
48
|
},
|
|
49
49
|
async execute(toolCallId, params) {
|
|
50
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
51
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
50
52
|
const wsManager = getXYWebSocketManager(config);
|
|
51
53
|
const intentParam = {};
|
|
52
54
|
if (params.startTime !== undefined)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// QueryMemoryData tool implementation
|
|
2
2
|
import { getXYWebSocketManager } from "../client.js";
|
|
3
3
|
import { sendCommand } from "../formatter.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import { logger } from "../utils/logger.js";
|
|
5
6
|
class ToolInputError extends Error {
|
|
6
7
|
status = 400;
|
|
@@ -27,7 +28,6 @@ const VALID_SUB_CATEGORIES = {
|
|
|
27
28
|
* 查询存储在设备本地的结构化记忆数据。
|
|
28
29
|
*/
|
|
29
30
|
export function createQueryMemoryDataTool(ctx) {
|
|
30
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
31
31
|
return {
|
|
32
32
|
name: "query_memory_data",
|
|
33
33
|
label: "Query Memory Data",
|
|
@@ -56,6 +56,8 @@ c. 调用工具前需认真检查调用参数是否满足工具要求
|
|
|
56
56
|
required: [],
|
|
57
57
|
},
|
|
58
58
|
async execute(toolCallId, params) {
|
|
59
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
60
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
59
61
|
const { category, subCategory } = params;
|
|
60
62
|
// Validate category
|
|
61
63
|
if (category && !VALID_CATEGORIES.includes(category)) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// QueryTodoTask tool implementation
|
|
2
2
|
import { getXYWebSocketManager } from "../client.js";
|
|
3
3
|
import { sendCommand } from "../formatter.js";
|
|
4
|
+
import { getCurrentSessionContext } from './session-manager.js';
|
|
4
5
|
import { logger } from "../utils/logger.js";
|
|
5
6
|
class ToolInputError extends Error {
|
|
6
7
|
status = 400;
|
|
@@ -13,7 +14,6 @@ class ToolInputError extends Error {
|
|
|
13
14
|
* 获取指定时间范围内的全局待办任务列表。
|
|
14
15
|
*/
|
|
15
16
|
export function createQueryTodoTaskTool(ctx) {
|
|
16
|
-
const { config, sessionId, taskId, messageId } = ctx;
|
|
17
17
|
return {
|
|
18
18
|
name: "query_todo_task",
|
|
19
19
|
label: "Query Todo Task",
|
|
@@ -44,6 +44,8 @@ d. 当只传入 startTime 时,返回该时间点之后的所有任务;当只
|
|
|
44
44
|
required: [],
|
|
45
45
|
},
|
|
46
46
|
async execute(toolCallId, params) {
|
|
47
|
+
const _c = getCurrentSessionContext() ?? ctx;
|
|
48
|
+
const { config, sessionId, taskId, messageId } = _c;
|
|
47
49
|
const { status } = params;
|
|
48
50
|
if (status && !["all", "completed", "pending"].includes(status)) {
|
|
49
51
|
throw new ToolInputError('status 参数只能为 "all"、"completed" 或 "pending"');
|