@ynhcj/xiaoyi-channel 0.0.99-beta → 0.0.99-next
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -10
- package/dist/index.js +76 -66
- package/dist/provider-discovery.d.ts +2 -0
- package/dist/provider-discovery.js +4 -0
- package/dist/src/bot.js +29 -4
- package/dist/src/channel.js +2 -20
- package/dist/src/client.js +31 -22
- package/dist/src/cspl/call-api.js +6 -5
- package/dist/src/file-download.js +4 -3
- package/dist/src/file-upload.js +19 -18
- package/dist/src/formatter.d.ts +2 -0
- package/dist/src/formatter.js +9 -28
- package/dist/src/heartbeat.js +1 -1
- package/dist/src/message-queue.d.ts +17 -0
- package/dist/src/message-queue.js +51 -0
- package/dist/src/monitor.js +63 -14
- package/dist/src/outbound.js +19 -18
- package/dist/src/provider.d.ts +2 -1
- package/dist/src/provider.js +211 -41
- package/dist/src/push.js +16 -15
- package/dist/src/reply-dispatcher.js +12 -3
- package/dist/src/runtime.d.ts +3 -11
- package/dist/src/runtime.js +6 -18
- package/dist/src/self-evolution-handler.d.ts +6 -0
- package/dist/src/self-evolution-handler.js +100 -7
- package/dist/src/self-evolution-keyword.d.ts +9 -0
- package/dist/src/self-evolution-keyword.js +147 -0
- package/dist/src/self-evolution-tool-result-nudge.d.ts +3 -0
- package/dist/src/self-evolution-tool-result-nudge.js +96 -0
- package/dist/src/skill-retriever/hooks.js +8 -12
- package/dist/src/skill-retriever/tool-search.js +22 -8
- package/dist/src/skill-retriever/types.d.ts +2 -0
- package/dist/src/steer-injector.js +1 -1
- package/dist/src/task-manager.d.ts +4 -0
- package/dist/src/task-manager.js +12 -1
- package/dist/src/tools/calendar-tool.d.ts +2 -1
- package/dist/src/tools/calendar-tool.js +112 -116
- package/dist/src/tools/call-device-tool.d.ts +2 -1
- package/dist/src/tools/call-device-tool.js +126 -103
- package/dist/src/tools/call-phone-tool.d.ts +2 -1
- package/dist/src/tools/call-phone-tool.js +109 -113
- package/dist/src/tools/create-alarm-tool.d.ts +2 -1
- package/dist/src/tools/create-alarm-tool.js +227 -231
- package/dist/src/tools/create-all-tools.d.ts +16 -0
- package/dist/src/tools/create-all-tools.js +50 -0
- package/dist/src/tools/delete-alarm-tool.d.ts +2 -1
- package/dist/src/tools/delete-alarm-tool.js +131 -135
- package/dist/src/tools/get-alarm-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-alarm-tool-schema.js +16 -10
- package/dist/src/tools/get-calendar-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-calendar-tool-schema.js +12 -8
- package/dist/src/tools/get-collection-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-collection-tool-schema.js +11 -9
- package/dist/src/tools/get-contact-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-contact-tool-schema.js +16 -10
- package/dist/src/tools/get-device-file-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-device-file-tool-schema.js +13 -9
- package/dist/src/tools/get-email-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-email-tool-schema.js +11 -8
- package/dist/src/tools/get-note-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-note-tool-schema.js +14 -9
- package/dist/src/tools/get-photo-tool-schema.d.ts +2 -1
- package/dist/src/tools/get-photo-tool-schema.js +12 -9
- package/dist/src/tools/image-reading-tool.d.ts +2 -1
- package/dist/src/tools/image-reading-tool.js +86 -90
- package/dist/src/tools/location-tool.d.ts +2 -1
- package/dist/src/tools/location-tool.js +87 -91
- package/dist/src/tools/login-token-tool.d.ts +3 -2
- package/dist/src/tools/login-token-tool.js +114 -117
- package/dist/src/tools/modify-alarm-tool.d.ts +2 -1
- package/dist/src/tools/modify-alarm-tool.js +232 -236
- package/dist/src/tools/modify-note-tool.d.ts +2 -1
- package/dist/src/tools/modify-note-tool.js +104 -108
- package/dist/src/tools/note-tool.d.ts +2 -1
- package/dist/src/tools/note-tool.js +103 -107
- package/dist/src/tools/query-app-message-tool.d.ts +2 -1
- package/dist/src/tools/query-app-message-tool.js +108 -111
- package/dist/src/tools/query-memory-data-tool.d.ts +2 -1
- package/dist/src/tools/query-memory-data-tool.js +109 -112
- package/dist/src/tools/query-todo-task-tool.d.ts +2 -1
- package/dist/src/tools/query-todo-task-tool.js +103 -106
- package/dist/src/tools/save-file-to-phone-tool.d.ts +2 -1
- package/dist/src/tools/save-file-to-phone-tool.js +127 -131
- package/dist/src/tools/save-media-to-gallery-tool.d.ts +2 -1
- package/dist/src/tools/save-media-to-gallery-tool.js +134 -138
- package/dist/src/tools/save-self-evolution-skill-tool.d.ts +2 -0
- package/dist/src/tools/save-self-evolution-skill-tool.js +410 -0
- package/dist/src/tools/search-alarm-tool.d.ts +2 -1
- package/dist/src/tools/search-alarm-tool.js +171 -175
- package/dist/src/tools/search-calendar-tool.d.ts +2 -1
- package/dist/src/tools/search-calendar-tool.js +145 -149
- package/dist/src/tools/search-contact-tool.d.ts +2 -1
- package/dist/src/tools/search-contact-tool.js +98 -102
- package/dist/src/tools/search-email-tool.d.ts +2 -1
- package/dist/src/tools/search-email-tool.js +107 -111
- package/dist/src/tools/search-file-tool.d.ts +2 -1
- package/dist/src/tools/search-file-tool.js +99 -103
- package/dist/src/tools/search-message-tool.d.ts +2 -1
- package/dist/src/tools/search-message-tool.js +100 -104
- package/dist/src/tools/search-note-tool.d.ts +2 -1
- package/dist/src/tools/search-note-tool.js +95 -99
- package/dist/src/tools/search-photo-gallery-tool.d.ts +2 -1
- package/dist/src/tools/search-photo-gallery-tool.js +34 -38
- package/dist/src/tools/send-email-tool.d.ts +2 -1
- package/dist/src/tools/send-email-tool.js +105 -108
- package/dist/src/tools/send-file-to-user-tool.d.ts +2 -1
- package/dist/src/tools/send-file-to-user-tool.js +154 -155
- package/dist/src/tools/send-message-tool.d.ts +2 -1
- package/dist/src/tools/send-message-tool.js +119 -123
- package/dist/src/tools/session-manager.d.ts +21 -6
- package/dist/src/tools/session-manager.js +147 -18
- package/dist/src/tools/upload-file-tool.d.ts +2 -1
- package/dist/src/tools/upload-file-tool.js +78 -82
- package/dist/src/tools/upload-photo-tool.d.ts +2 -1
- package/dist/src/tools/upload-photo-tool.js +69 -73
- package/dist/src/tools/xiaoyi-add-collection-tool.d.ts +2 -1
- package/dist/src/tools/xiaoyi-add-collection-tool.js +143 -147
- package/dist/src/tools/xiaoyi-collection-tool.d.ts +2 -1
- package/dist/src/tools/xiaoyi-collection-tool.js +111 -115
- package/dist/src/tools/xiaoyi-delete-collection-tool.d.ts +2 -1
- package/dist/src/tools/xiaoyi-delete-collection-tool.js +124 -128
- package/dist/src/tools/xiaoyi-gui-tool.d.ts +2 -1
- package/dist/src/tools/xiaoyi-gui-tool.js +84 -88
- package/dist/src/utils/logger.js +20 -18
- package/dist/src/utils/runtime-manager.js +24 -2
- package/dist/src/utils/self-evolution-manager.d.ts +10 -0
- package/dist/src/utils/self-evolution-manager.js +69 -0
- package/dist/src/utils/tool-call-nudge-manager.d.ts +16 -0
- package/dist/src/utils/tool-call-nudge-manager.js +47 -0
- package/dist/src/websocket.d.ts +3 -0
- package/dist/src/websocket.js +81 -28
- package/openclaw.plugin.json +22 -0
- package/package.json +3 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
-
|
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
|
3
|
+
const XIAOYIRUNTIME_PATH = "/home/sandbox/.openclaw/.xiaoyiruntime";
|
|
3
4
|
export function handleSelfEvolutionEvent(context, runtime) {
|
|
4
5
|
const log = runtime?.log ?? console.log;
|
|
5
6
|
const error = runtime?.error ?? console.error;
|
|
@@ -12,12 +13,12 @@ export function handleSelfEvolutionEvent(context, runtime) {
|
|
|
12
13
|
log(`[SELF_EVOLUTION] received state: ${state}`);
|
|
13
14
|
let content;
|
|
14
15
|
try {
|
|
15
|
-
content = readFileSync(
|
|
16
|
+
content = readFileSync(XIAOYIRUNTIME_PATH, "utf-8");
|
|
16
17
|
}
|
|
17
18
|
catch {
|
|
18
19
|
// File doesn't exist yet — create it
|
|
19
|
-
log(`[SELF_EVOLUTION] ${
|
|
20
|
-
writeFileSync(
|
|
20
|
+
log(`[SELF_EVOLUTION] ${XIAOYIRUNTIME_PATH} not found, creating new file`);
|
|
21
|
+
writeFileSync(XIAOYIRUNTIME_PATH, `selfEvolutionState=${state}\n`, "utf-8");
|
|
21
22
|
log(`[SELF_EVOLUTION] wrote selfEvolutionState=${state}`);
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
@@ -34,14 +35,106 @@ export function handleSelfEvolutionEvent(context, runtime) {
|
|
|
34
35
|
if (!found) {
|
|
35
36
|
// Ensure trailing newline before appending
|
|
36
37
|
const trimmed = content.trimEnd();
|
|
37
|
-
writeFileSync(
|
|
38
|
+
writeFileSync(XIAOYIRUNTIME_PATH, `${trimmed}\n${key}=${state}\n`, "utf-8");
|
|
38
39
|
}
|
|
39
40
|
else {
|
|
40
|
-
writeFileSync(
|
|
41
|
+
writeFileSync(XIAOYIRUNTIME_PATH, updated.join("\n"), "utf-8");
|
|
41
42
|
}
|
|
42
|
-
log(`[SELF_EVOLUTION] updated selfEvolutionState=${state} in ${
|
|
43
|
+
log(`[SELF_EVOLUTION] updated selfEvolutionState=${state} in ${XIAOYIRUNTIME_PATH}`);
|
|
43
44
|
}
|
|
44
45
|
catch (err) {
|
|
45
46
|
error("[SELF_EVOLUTION] failed to handle event:", err);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* 读取 .xiaoyiruntime 中的 selfEvolutionState 并直接通过 wsManager 下发指令回复设备
|
|
51
|
+
* 参考trigger实现:直接使用当前已连接的 wsManager 发送消息,避免 getXYWebSocketManager 返回未连接实例
|
|
52
|
+
*/
|
|
53
|
+
export async function handleSelfEvolutionStateGetEvent(context, cfg, runtime, wsManager) {
|
|
54
|
+
const log = runtime?.log ?? console.log;
|
|
55
|
+
const error = runtime?.error ?? console.error;
|
|
56
|
+
try {
|
|
57
|
+
const { sessionId, taskId } = context;
|
|
58
|
+
const messageId = context.messageId ?? uuidv4();
|
|
59
|
+
// 读取 selfEvolutionState
|
|
60
|
+
let state = "false";
|
|
61
|
+
try {
|
|
62
|
+
const content = readFileSync(XIAOYIRUNTIME_PATH, "utf-8");
|
|
63
|
+
for (const line of content.split("\n")) {
|
|
64
|
+
const trimmed = line.trim();
|
|
65
|
+
if (trimmed.startsWith("selfEvolutionState=")) {
|
|
66
|
+
state = trimmed.slice("selfEvolutionState=".length).trim();
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// 文件不存在,使用默认值 false
|
|
73
|
+
}
|
|
74
|
+
log(`[SELF_EVOLUTION_GET] read selfEvolutionState=${state}, sending command back`);
|
|
75
|
+
const command = {
|
|
76
|
+
header: {
|
|
77
|
+
namespace: "Common",
|
|
78
|
+
name: "Action",
|
|
79
|
+
},
|
|
80
|
+
payload: {
|
|
81
|
+
cardParam: {},
|
|
82
|
+
executeParam: {
|
|
83
|
+
executeMode: "background",
|
|
84
|
+
intentName: "ClawSelfEvolutionStateGet",
|
|
85
|
+
bundleName: "com.huawei.hmos.vassistant",
|
|
86
|
+
needUnlock: true,
|
|
87
|
+
actionResponse: true,
|
|
88
|
+
timeOut: 5,
|
|
89
|
+
intentParam: {
|
|
90
|
+
selfEvolutionState: state,
|
|
91
|
+
},
|
|
92
|
+
permissionId: [],
|
|
93
|
+
achieveType: "INTENT",
|
|
94
|
+
},
|
|
95
|
+
responses: [{
|
|
96
|
+
resultCode: "",
|
|
97
|
+
displayText: "",
|
|
98
|
+
ttsText: "",
|
|
99
|
+
}],
|
|
100
|
+
needUploadResult: true,
|
|
101
|
+
noHalfPage: false,
|
|
102
|
+
pageControlRelated: false,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
// 构造 artifact update 消息,直接通过当前 wsManager 发送
|
|
106
|
+
const jsonRpcResponse = {
|
|
107
|
+
jsonrpc: "2.0",
|
|
108
|
+
id: messageId,
|
|
109
|
+
result: {
|
|
110
|
+
taskId,
|
|
111
|
+
kind: "artifact-update",
|
|
112
|
+
append: false,
|
|
113
|
+
lastChunk: true,
|
|
114
|
+
final: false,
|
|
115
|
+
artifact: {
|
|
116
|
+
artifactId: uuidv4(),
|
|
117
|
+
parts: [{
|
|
118
|
+
kind: "data",
|
|
119
|
+
data: {
|
|
120
|
+
commands: [command],
|
|
121
|
+
},
|
|
122
|
+
}],
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
const outboundMessage = {
|
|
127
|
+
msgType: "agent_response",
|
|
128
|
+
agentId: cfg.agentId,
|
|
129
|
+
sessionId,
|
|
130
|
+
taskId,
|
|
131
|
+
msgDetail: JSON.stringify(jsonRpcResponse),
|
|
132
|
+
};
|
|
133
|
+
log(`[A2A_COMMAND] 📤 Sending A2A command: taskId: ${taskId}`);
|
|
134
|
+
await wsManager.sendMessage(sessionId, outboundMessage);
|
|
135
|
+
log(`[SELF_EVOLUTION_GET] command sent successfully`);
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
error("[SELF_EVOLUTION_GET] failed to handle event:", err);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const SELF_EVOLUTION_KEYWORD_NUDGE_MESSAGE = "[\u7CFB\u7EDF\u6D88\u606F\uFF0C\u975E\u7528\u6237\u53D1\u8A00\uFF0C\u65E0\u9700\u4E3B\u52A8\u544A\u77E5\u7528\u6237] \u5F53\u524D\u7528\u6237\u8BF7\u6C42\u4E2D\u53EF\u80FD\u5305\u542B\u5E0C\u671B\u6C89\u6DC0\u7ECF\u9A8C\u3001\u957F\u671F\u8BB0\u5FC6\u3001\u907F\u514D\u91CD\u590D\u8E29\u5751\u3001\u7EA0\u9519\u7B49\u610F\u56FE\u3002\u5982\u679C\u4F60\u4ECE\u5F53\u524D\u4EFB\u52A1\u8FC7\u7A0B\u4E2D\u8BC6\u522B\u51FA\u53EF\u957F\u671F\u8BB0\u5FC6\u3001\u53EF\u590D\u7528\u7684\u5904\u7406\u89C4\u5219\u6216\u6392\u9519\u7ECF\u9A8C\u7B49\uFF0C\u53EF\u4EE5\u5728\u5B8C\u6210\u5F53\u524D\u4E3B\u8981\u4EFB\u52A1\u540E\uFF0C\u6B63\u5F0F\u56DE\u590D\u7528\u6237\u524D\uFF0C\u9605\u8BFBxiaoyi-self-evolution\u6280\u80FD\u4E86\u89E3\u81EA\u8FDB\u5316\u89C4\u5219\u3002\u6CE8\u610F\uFF0C\u4E0D\u8981\u6253\u65AD\u5F53\u524D\u4E3B\u4EFB\u52A1\uFF0C\u4EE5\u5B8C\u6210\u4EFB\u52A1\u4E3A\u6700\u9AD8\u4F18\u5148\u7EA7\u3002";
|
|
2
|
+
export declare const SELF_EVOLUTION_KEYWORD_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
3
|
+
export declare const SELF_EVOLUTION_MECHANISM_DISCUSSION_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
4
|
+
export declare function isSelfEvolutionMechanismDiscussion(text: string): boolean;
|
|
5
|
+
export declare function shouldNudgeForSelfEvolutionKeyword(text: string): boolean;
|
|
6
|
+
export declare function appendSelfEvolutionKeywordNudge(text: string): {
|
|
7
|
+
text: string;
|
|
8
|
+
appended: boolean;
|
|
9
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export const SELF_EVOLUTION_KEYWORD_NUDGE_MESSAGE = "[系统消息,非用户发言,无需主动告知用户] 当前用户请求中可能包含希望沉淀经验、长期记忆、避免重复踩坑、纠错等意图。如果你从当前任务过程中识别出可长期记忆、可复用的处理规则或排错经验等,可以在完成当前主要任务后,正式回复用户前,阅读xiaoyi-self-evolution技能了解自进化规则。注意,不要打断当前主任务,以完成任务为最高优先级。";
|
|
2
|
+
export const SELF_EVOLUTION_KEYWORD_PATTERNS = [
|
|
3
|
+
/进化/u,
|
|
4
|
+
/沉淀/u,
|
|
5
|
+
/记住/u,
|
|
6
|
+
/固化/u,
|
|
7
|
+
/下次都/u,
|
|
8
|
+
/记下来/u,
|
|
9
|
+
/记一个/u,
|
|
10
|
+
/记一下/u,
|
|
11
|
+
/给我记住/u,
|
|
12
|
+
/给我记下来/u,
|
|
13
|
+
/把(?:这个|这条|这点|这个要求|这个偏好)(?:记住|记下来|记录下来)/u,
|
|
14
|
+
/以后都/u,
|
|
15
|
+
/以后必须/u,
|
|
16
|
+
/以后统一/u,
|
|
17
|
+
/后面都/u,
|
|
18
|
+
/后续都/u,
|
|
19
|
+
/以后默认/u,
|
|
20
|
+
/下次默认/u,
|
|
21
|
+
/之后默认/u,
|
|
22
|
+
/后续默认/u,
|
|
23
|
+
/长期记住/u,
|
|
24
|
+
/永久记住/u,
|
|
25
|
+
/永远记住/u,
|
|
26
|
+
/记住我的(?:偏好|习惯|要求|规范|规则)/u,
|
|
27
|
+
/记住我(?:喜欢|不喜欢|习惯|偏好|要求|希望|倾向于)/u,
|
|
28
|
+
/记住(?:我|用户)(?:以后|之后|后续)?(?:喜欢|不喜欢|习惯|偏好|要求|希望|倾向于)/u,
|
|
29
|
+
/(?:我的|用户的)(?:偏好|习惯|要求|规范|规则)(?:要)?(?:记住|记录|保留|沿用)/u,
|
|
30
|
+
/以后按(?:我的)?(?:偏好|习惯|要求|规范|规则)/u,
|
|
31
|
+
/(?:以后|下次|后续|之后)(?:都|统一|默认)?(?:按|照|遵循|沿用)(?:我的|用户的)(?:偏好|习惯|要求|规范|规则)/u,
|
|
32
|
+
/形成规范/u,
|
|
33
|
+
/固化下来/u,
|
|
34
|
+
/固定下来/u,
|
|
35
|
+
/固定成(?:规范|规则|流程|模板|标准)/u,
|
|
36
|
+
/列为(?:规范|规则|流程|标准|最佳实践)/u,
|
|
37
|
+
/作为(?:规范|规则|流程|标准|最佳实践)(?:保存|沉淀|记录|保留)/u,
|
|
38
|
+
/记成规则/u,
|
|
39
|
+
/写成规则/u,
|
|
40
|
+
/定成规则/u,
|
|
41
|
+
/定为(?:规则|规范|流程|标准|模板)/u,
|
|
42
|
+
/纳入经验/u,
|
|
43
|
+
/写入经验/u,
|
|
44
|
+
/写进(?:经验|规则|规范|流程|最佳实践)/u,
|
|
45
|
+
/记录到(?:经验|规则|规范|流程|最佳实践)/u,
|
|
46
|
+
/加入(?:经验|规则|规范|流程|最佳实践)/u,
|
|
47
|
+
/保存成(?:经验|规则|规范|流程|模板|最佳实践)/u,
|
|
48
|
+
/沉淀成(?:经验|规则|规范|流程)/u,
|
|
49
|
+
/总结成(?:经验|规则|规范|流程|步骤|模板|最佳实践)/u,
|
|
50
|
+
/归纳成(?:经验|规则|规范|流程|模板|最佳实践)/u,
|
|
51
|
+
/提炼成(?:经验|规则|规范|流程|模板|最佳实践)/u,
|
|
52
|
+
/以后都按这个来/u,
|
|
53
|
+
/下次都这样处理/u,
|
|
54
|
+
/以后统一这样/u,
|
|
55
|
+
/后面都这样/u,
|
|
56
|
+
/以后照这个来/u,
|
|
57
|
+
/下次照这个来/u,
|
|
58
|
+
/后续照这个来/u,
|
|
59
|
+
/之后照这个来/u,
|
|
60
|
+
/以后就这么办/u,
|
|
61
|
+
/下次就这么办/u,
|
|
62
|
+
/以后就这样办/u,
|
|
63
|
+
/下次就这样办/u,
|
|
64
|
+
/以后沿用/u,
|
|
65
|
+
/下次沿用/u,
|
|
66
|
+
/后续沿用/u,
|
|
67
|
+
/后续按这个(?:规范|流程|模板|方案)/u,
|
|
68
|
+
/(?:以后|下次|后续|之后)(?:就)?(?:按|照|沿用|复用)(?:这个|这种|上述|前面这个|刚才这个)(?:规范|流程|模板|方案|格式|标准|做法|套路|模式)/u,
|
|
69
|
+
/(?:以后|下次|后续|之后)(?:回复|回答|输出|生成|整理|总结)(?:时)?(?:都|就|统一|默认|必须|要)(?:按|照|遵循|沿用|使用)(?:这个|这种|上述|当前)?(?:格式|模板|风格|口径|结构|标准)/u,
|
|
70
|
+
/(?:这个|这种|上述|当前)(?:格式|模板|风格|口径|结构|标准)(?:以后|下次|后续|之后)(?:都|就|统一|默认|复用|沿用)/u,
|
|
71
|
+
/以后(?:遇到|碰到)这种情况/u,
|
|
72
|
+
/类似(?:问题|情况|场景)都这样/u,
|
|
73
|
+
/类似(?:问题|情况|场景)都这样处理/u,
|
|
74
|
+
/类似(?:问题|情况|场景)(?:以后|下次|后续|之后)(?:都|就|统一|默认)/u,
|
|
75
|
+
/(?:同类|类似|这种|这类)(?:需求|任务|问题|情况|场景)(?:以后|下次|后续|之后)(?:都|就|统一|默认|按这个|照这个)/u,
|
|
76
|
+
/(?:这类|这种|类似|同类)(?:需求|任务|问题|场景)(?:处理|解决|回答|回复)(?:方式|流程|方法)(?:记住|固定|沉淀|沿用)/u,
|
|
77
|
+
/避免(?:再次|以后|下次)/u,
|
|
78
|
+
/避免再(?:犯错|踩坑|出错)/u,
|
|
79
|
+
/防止以后再犯/u,
|
|
80
|
+
/防止(?:以后|下次|后续|之后)(?:再)?(?:犯错|出错|踩坑|漏掉|遗漏|忘记)/u,
|
|
81
|
+
/别再(?:出错|犯错|踩坑|漏掉|忘记)/u,
|
|
82
|
+
/不要再(?:出错|犯错|踩坑|漏掉|忘记)/u,
|
|
83
|
+
/别再(?:这样|这么)(?:做|处理|回答|回复|输出|写|改)/u,
|
|
84
|
+
/不要再(?:这样|这么)(?:做|处理|回答|回复|输出|写|改)/u,
|
|
85
|
+
/以后别(?:这样|这么)(?:做|处理|回答|回复|输出|写|改)/u,
|
|
86
|
+
/以后不要(?:这样|这么)(?:做|处理|回答|回复|输出|写|改)/u,
|
|
87
|
+
/下次别再/u,
|
|
88
|
+
/以后不要再/u,
|
|
89
|
+
/以后别再/u,
|
|
90
|
+
/(?:下次|以后|后续|之后)(?:不要|别|不能|不许|禁止)(?:再)?(?:这样|这么)?(?:出错|犯错|踩坑|漏掉|遗漏|忘记)/u,
|
|
91
|
+
/(?:下次|以后|后续|之后)(?:不要|别|不能|不许|禁止)(?:再)?(?:省略|跳过|漏掉|遗漏)(?:检查|确认|验证|测试|构建|说明|引用|来源|步骤)/u,
|
|
92
|
+
/(?:下次|以后|后续|之后)(?:记得|一定要|务必|必须)(?:先|先去|优先|默认)?(?:检查|确认|使用|采用|调用|遵循|按照|参考|避免|不要|别|记住|保留|验证|测试|构建|运行)/u,
|
|
93
|
+
/(?:下次|以后|后续|之后)(?:先|优先|默认)(?:检查|确认|查找|搜索|读取|运行|验证|测试|构建|调用|使用)/u,
|
|
94
|
+
/这个坑(?:要)?记住/u,
|
|
95
|
+
/这(?:个|次)?(?:坑|错误|问题|教训)(?:别忘|不要忘|不能忘|得记住)/u,
|
|
96
|
+
/(?:踩坑|翻车|犯错|出错)(?:点|原因|教训)?(?:记住|记下来|沉淀|复盘)/u,
|
|
97
|
+
/吸取这次(?:教训|经验)/u,
|
|
98
|
+
/把(?:这个|这次|上述|刚才的)?(?:坑|问题|错误|教训|经验|做法|流程|规范|要求|偏好|格式|模板|标准)(?:记住|记下来|沉淀下来|固化下来|保存下来|记录下来)/u,
|
|
99
|
+
/(?:以后|下次|后续|之后)(?:遇到|碰到)(?:同类|类似|这种|这类)(?:需求|任务|问题|情况|场景)(?:时)?(?:都|就|统一|默认|应该|要|必须)/u,
|
|
100
|
+
/(?:以后|下次|后续|之后)(?:做|处理|执行)(?:同类|类似|这种|这类)(?:需求|任务|问题|情况|场景)(?:时)?(?:都|就|统一|默认|应该|要|必须)/u,
|
|
101
|
+
/(?:以后|下次|后续|之后)(?:都|统一|默认|应该|要)(?:按这个|这样|这么)(?:来|做|处理|执行)/u,
|
|
102
|
+
/(?:以后|下次|后续|之后)(?:都|统一|默认|应该|要|必须)(?:先|优先|总是|固定)?(?:使用|采用|走|遵循|参考|套用|复用|沿用)(?:这个|这种|上述|当前)?(?:方法|流程|规范|规则|模板|标准|方案|做法|模式|套路)/u,
|
|
103
|
+
/(?:以后|下次|后续|之后)(?:遇到|碰到)(?:类似)?(?:问题|情况|场景)(?:时)?(?:都|就)(?:按这个|这样|这么)(?:来|做|处理|执行)/u,
|
|
104
|
+
/(?:别再|不要再|避免)(?:犯错|出错|踩坑|漏掉|遗漏|忘记)/u,
|
|
105
|
+
/(?:总结|归纳|提炼|沉淀|复盘)(?:一个|一下|下)?(?:这次|这个|上述|刚才的)?(?:经验|教训|问题|规则|规范|流程|模板|标准|最佳实践)?/u,
|
|
106
|
+
/(?:把)?这次(?:经验|教训|规则|做法|流程|格式|模板|标准)(?:记住|记下来|沉淀下来|固化下来|记录下来)/u,
|
|
107
|
+
/(?:形成|整理成|沉淀成|提炼成)(?:一套|一个|一份)?(?:规则|规范|流程|步骤|模板|标准|最佳实践|操作手册|检查清单|checklist)/u,
|
|
108
|
+
/(?:作为|当作|用作)(?:以后|下次|后续|之后)(?:的)?(?:参考|模板|范例|案例|标准|最佳实践|默认做法)/u,
|
|
109
|
+
/(?:这次|这个|上述|刚才的)(?:处理方式|做法|流程|方案|模板|格式|标准|口径|风格)(?:以后|下次|后续|之后)(?:复用|沿用|照着来|照这个来|继续用)/u,
|
|
110
|
+
/(?:以后|下次|后续|之后)(?:工具|skill|技能|命令|脚本|流程)(?:选择|调用|使用)(?:都|就|统一|默认|优先|必须|要)/u,
|
|
111
|
+
/(?:以后|下次|后续|之后)(?:优先|默认|固定)(?:用|使用|调用)(?:这个|这种|上述|当前)?(?:工具|skill|技能|命令|脚本|流程|方法)/u,
|
|
112
|
+
/(?:这个|这种|上述|当前)(?:工具|skill|技能|命令|脚本|流程|方法)(?:以后|下次|后续|之后)(?:优先|默认|固定|继续)(?:用|使用|调用)/u,
|
|
113
|
+
];
|
|
114
|
+
export const SELF_EVOLUTION_MECHANISM_DISCUSSION_PATTERNS = [
|
|
115
|
+
/自进化(?:机制|功能|流程|原理|实现|设计|架构|链路|优化点|改进点)/u,
|
|
116
|
+
/(?:分析|讨论|了解|解释|看看|研究|检查|梳理|优化|改进|评估)(?:.{0,12})自进化/u,
|
|
117
|
+
/自进化(?:.{0,12})(?:怎么|如何|是否|能否|有没有|为什么)/u,
|
|
118
|
+
/自进化(?:是啥|是什么|的)/u,
|
|
119
|
+
/什么是自进化/u,
|
|
120
|
+
/啥是自进化/u,
|
|
121
|
+
/xiaoyi-self-evolution(?:-skill)?(?:.{0,12})(?:机制|功能|流程|原理|实现|设计|优化点|改进点)/iu,
|
|
122
|
+
];
|
|
123
|
+
export function isSelfEvolutionMechanismDiscussion(text) {
|
|
124
|
+
return SELF_EVOLUTION_MECHANISM_DISCUSSION_PATTERNS.some((pattern) => pattern.test(text));
|
|
125
|
+
}
|
|
126
|
+
export function shouldNudgeForSelfEvolutionKeyword(text) {
|
|
127
|
+
if (!text) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if (isSelfEvolutionMechanismDiscussion(text)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return SELF_EVOLUTION_KEYWORD_PATTERNS.some((pattern) => pattern.test(text));
|
|
134
|
+
}
|
|
135
|
+
export function appendSelfEvolutionKeywordNudge(text) {
|
|
136
|
+
const trimmed = text.trim();
|
|
137
|
+
if (!trimmed) {
|
|
138
|
+
return { text, appended: false };
|
|
139
|
+
}
|
|
140
|
+
if (trimmed.includes(SELF_EVOLUTION_KEYWORD_NUDGE_MESSAGE)) {
|
|
141
|
+
return { text, appended: false };
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
text: `${trimmed}\n\n${SELF_EVOLUTION_KEYWORD_NUDGE_MESSAGE}`,
|
|
145
|
+
appended: true,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
export declare const SELF_EVOLUTION_TOOL_COUNT_NUDGE_MESSAGE = "[\u7CFB\u7EDF\u6D88\u606F] \u5F53\u524D\u4EFB\u52A1\u5DF2\u7ECF\u8C03\u7528\u4E86\u8F83\u591A\u6B21\u6570\u7684\u5DE5\u5177\u3002\u8BF7\u5728\u5B8C\u6210\u4EFB\u52A1\u540E\uFF0C\u5224\u65AD\u662F\u5426\u6709\u7A33\u5B9A\u3001\u901A\u7528\u3001\u53EF\u590D\u7528\u7684\u6D41\u7A0B\u3001\u6392\u9519\u7ECF\u9A8C\u6216\u8E29\u5751\u70B9\uFF0C\u5E76\u8003\u8651\u9605\u8BFB xiaoyi-self-evolution skill \u542F\u52A8\u81EA\u8FDB\u5316\u3002";
|
|
3
|
+
export declare function registerSelfEvolutionToolResultNudge(api: OpenClawPluginApi): void;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { selfEvolutionManager } from "./utils/self-evolution-manager.js";
|
|
2
|
+
import { toolCallNudgeManager, TOOL_CALL_NUDGE_THRESHOLD } from "./utils/tool-call-nudge-manager.js";
|
|
3
|
+
export const SELF_EVOLUTION_TOOL_COUNT_NUDGE_MESSAGE = "[系统消息] 当前任务已经调用了较多次数的工具。请在完成任务后,判断是否有稳定、通用、可复用的流程、排错经验或踩坑点,并考虑阅读 xiaoyi-self-evolution skill 启动自进化。";
|
|
4
|
+
function shouldCountToolCall(toolName) {
|
|
5
|
+
if (toolName === "save_self_evolution_skill") {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
if (toolName === "call_device_tool") {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (toolName.endsWith("_tool_schema")) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
function appendNudgeToToolResultPayload(message, nudge) {
|
|
17
|
+
const msg = message;
|
|
18
|
+
const nudgeTrim = nudge.trim();
|
|
19
|
+
if (!nudgeTrim) {
|
|
20
|
+
return message;
|
|
21
|
+
}
|
|
22
|
+
const content = msg.content;
|
|
23
|
+
if (typeof content === "string") {
|
|
24
|
+
if (content.includes(nudgeTrim)) {
|
|
25
|
+
return message;
|
|
26
|
+
}
|
|
27
|
+
return { ...msg, content: `${content}\n\n${nudge}` };
|
|
28
|
+
}
|
|
29
|
+
if (!Array.isArray(content)) {
|
|
30
|
+
return {
|
|
31
|
+
...msg,
|
|
32
|
+
content: [{ type: "text", text: nudge }],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const newContent = content.map((block) => block && typeof block === "object" ? { ...block } : block);
|
|
36
|
+
for (let i = newContent.length - 1; i >= 0; i--) {
|
|
37
|
+
const block = newContent[i];
|
|
38
|
+
if (!block || typeof block !== "object") {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const rec = block;
|
|
42
|
+
if (rec.type !== "text") {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const text = rec.text;
|
|
46
|
+
if (typeof text !== "string") {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (text.includes(nudgeTrim)) {
|
|
50
|
+
return message;
|
|
51
|
+
}
|
|
52
|
+
newContent[i] = { ...rec, type: "text", text: `${text}\n\n${nudge}` };
|
|
53
|
+
return { ...msg, content: newContent };
|
|
54
|
+
}
|
|
55
|
+
newContent.push({ type: "text", text: nudge });
|
|
56
|
+
return { ...msg, content: newContent };
|
|
57
|
+
}
|
|
58
|
+
export function registerSelfEvolutionToolResultNudge(api) {
|
|
59
|
+
api.on("tool_result_persist", (event, ctx) => {
|
|
60
|
+
const message = event.message;
|
|
61
|
+
if (message.role !== "toolResult") {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
if (event.isSynthetic) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const sessionKey = ctx?.sessionKey;
|
|
68
|
+
if (!sessionKey || sessionKey.includes(":subagent:")) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
if (!selfEvolutionManager.isEnabledSync()) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const toolName = (event.toolName ?? message.toolName ?? "").trim();
|
|
75
|
+
if (!toolName || !shouldCountToolCall(toolName)) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
let shouldNudge;
|
|
79
|
+
let count = 0;
|
|
80
|
+
try {
|
|
81
|
+
const result = toolCallNudgeManager.recordToolCall(sessionKey);
|
|
82
|
+
shouldNudge = result.shouldNudge;
|
|
83
|
+
count = result.count;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
api.logger.debug?.(`[SELF_EVOLUTION] tool_result_persist: tool=${toolName}, count=${count}, threshold=${TOOL_CALL_NUDGE_THRESHOLD}, sessionKey=${sessionKey}, shouldNudge=${shouldNudge}`);
|
|
89
|
+
if (!shouldNudge) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
api.logger.info?.(`[SELF_EVOLUTION] Tool call threshold reached, appending nudge to tool result: tool=${toolName}, count=${count}, sessionKey=${sessionKey}`);
|
|
93
|
+
const next = appendNudgeToToolResultPayload(event.message, SELF_EVOLUTION_TOOL_COUNT_NUDGE_MESSAGE);
|
|
94
|
+
return { message: next };
|
|
95
|
+
});
|
|
96
|
+
}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { searchTools, formatToolsForContext, extractUserQuery } from "./tool-search.js";
|
|
2
|
-
|
|
2
|
+
import { logger } from "../utils/logger.js";
|
|
3
|
+
const TOOL_RETRIEVER_HEADER = `[系统消息,非用户发言]
|
|
3
4
|
|
|
4
5
|
`;
|
|
5
6
|
const TOOL_RETRIEVER_FOOTER = `
|
|
6
|
-
|
|
7
|
-
对于强相关skill,你需要主动提醒用户可以考虑安装,但禁止直接给用户安装。用户明确希望安装后,使用find-skill执行安装。
|
|
8
|
-
若用户已有的skill已能很好地完成当前任务,则无需提醒安装功能相似的skill。
|
|
7
|
+
以上是检索到的、与当前用户请求相关但用户尚未安装的skill,请按照TOOLS.md中find-skills中的[隐式推荐触发规则]来判断是否要给用户推荐。
|
|
9
8
|
---以下是用户原始请求---
|
|
10
9
|
`;
|
|
11
10
|
const PLUGIN_LOG_PREFIX = "[skill-retriever]";
|
|
12
|
-
const SKIP_KEYWORDS = ["安装", "装一下", "下载", "查询", "查找", "install", "卸载", "删除", "重载"];
|
|
11
|
+
const SKIP_KEYWORDS = ["安装", "装一下", "下载", "查询", "查找", "install", "卸载", "删除", "重载", "定时任务", "重装", "进化"];
|
|
13
12
|
const SKIP_PATTERNS = [
|
|
14
|
-
"/new",
|
|
15
|
-
"/reset",
|
|
16
|
-
"session was started",
|
|
17
|
-
"a new session was started",
|
|
13
|
+
"/new", "/reset", "/compact", "/stop", "/think", "/model", "/fast", "/verbose", "/config", "/debug", "/status", "/tasks", "/whoami", "/context", "/skill", "/commands", "/tools"
|
|
18
14
|
];
|
|
19
15
|
function shouldSkipSearch(prompt) {
|
|
20
16
|
const trimmedPrompt = prompt.trim();
|
|
@@ -68,10 +64,10 @@ export function createBeforePromptBuildHandler(config) {
|
|
|
68
64
|
if (!searchResult || searchResult.tools.length === 0) {
|
|
69
65
|
return undefined;
|
|
70
66
|
}
|
|
71
|
-
|
|
67
|
+
logger.log(`${PLUGIN_LOG_PREFIX} [RESULT] Found ${searchResult.tools.length} skills, building context...`);
|
|
72
68
|
const toolsContext = formatToolsForContext(searchResult, config.includeUninstalledOnly);
|
|
73
69
|
if (!toolsContext) {
|
|
74
|
-
|
|
70
|
+
logger.log(`${PLUGIN_LOG_PREFIX} [ERROR] Failed to format skills context`);
|
|
75
71
|
return undefined;
|
|
76
72
|
}
|
|
77
73
|
return {
|
|
@@ -80,7 +76,7 @@ export function createBeforePromptBuildHandler(config) {
|
|
|
80
76
|
}
|
|
81
77
|
catch (error) {
|
|
82
78
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
83
|
-
|
|
79
|
+
logger.error(`${PLUGIN_LOG_PREFIX} [ERROR] ${errorMessage}, original query: "${extractedQuery}"`);
|
|
84
80
|
return undefined;
|
|
85
81
|
}
|
|
86
82
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as os from "os";
|
|
4
|
+
import { logger } from "../utils/logger.js";
|
|
4
5
|
const SKILL_ID = "celia_find_skills";
|
|
5
6
|
const PLUGIN_LOG_PREFIX = "[skill-retriever]";
|
|
6
7
|
export function extractUserQuery(fullPrompt) {
|
|
@@ -12,6 +13,9 @@ export function extractUserQuery(fullPrompt) {
|
|
|
12
13
|
if (!afterLastNewline || afterLastNewline === "```") {
|
|
13
14
|
return "";
|
|
14
15
|
}
|
|
16
|
+
if (fullPrompt.toLowerCase().includes("cron")) {
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
15
19
|
return afterLastNewline;
|
|
16
20
|
}
|
|
17
21
|
function expandPath(filePath) {
|
|
@@ -73,6 +77,7 @@ function formatSkillData(rawSkills, installedSkills) {
|
|
|
73
77
|
skillDesc: skill.skillDesc,
|
|
74
78
|
downloadPath: skill.packUrl,
|
|
75
79
|
status: isInstalled ? "已安装" : "未安装",
|
|
80
|
+
rrfScore: skill.rrfScore,
|
|
76
81
|
});
|
|
77
82
|
}
|
|
78
83
|
return formattedSkills;
|
|
@@ -85,7 +90,7 @@ export async function searchTools(options) {
|
|
|
85
90
|
const apiKey = configApiKey ?? envConfig.PERSONAL_API_KEY;
|
|
86
91
|
const uid = configUid ?? envConfig.PERSONAL_UID;
|
|
87
92
|
if (!serviceUrl || !apiKey || !uid) {
|
|
88
|
-
|
|
93
|
+
logger.warn(`${PLUGIN_LOG_PREFIX} Missing required configuration. serviceUrl: "${serviceUrl}", apiKey: "${apiKey ? '(set)' : '(missing)'} ", uid: "${uid ? '(set)' : '(missing)'}"`);
|
|
89
94
|
return null;
|
|
90
95
|
}
|
|
91
96
|
const traceId = crypto.randomUUID();
|
|
@@ -107,10 +112,10 @@ export async function searchTools(options) {
|
|
|
107
112
|
signal: AbortSignal.timeout(timeoutMs),
|
|
108
113
|
});
|
|
109
114
|
if (!response.ok) {
|
|
110
|
-
|
|
115
|
+
logger.warn(`${PLUGIN_LOG_PREFIX} HTTP error: ${response.status} ${response.statusText}`);
|
|
111
116
|
return null;
|
|
112
117
|
}
|
|
113
|
-
|
|
118
|
+
logger.log(`${PLUGIN_LOG_PREFIX} Received response, status: ${response.status}`);
|
|
114
119
|
const responseData = await response.json();
|
|
115
120
|
if (responseData.errorCode === "0" &&
|
|
116
121
|
responseData.content &&
|
|
@@ -121,18 +126,27 @@ export async function searchTools(options) {
|
|
|
121
126
|
const topTools = formattedData.slice(0, 2);
|
|
122
127
|
const allInstalled = topTools.every((tool) => tool.status === "已安装");
|
|
123
128
|
if (allInstalled) {
|
|
124
|
-
|
|
129
|
+
logger.log(`${PLUGIN_LOG_PREFIX} [DEBUG] All top 2 skills are installed, returning null`);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const hasInstalledWithHighScore = topTools.some((tool) => tool.status === "已安装" && (tool.rrfScore ?? 0) >= 0.016);
|
|
133
|
+
if (hasInstalledWithHighScore) {
|
|
134
|
+
logger.log(`${PLUGIN_LOG_PREFIX} [DEBUG] Top 2 has installed skill with rrfScore >= 0.016, returning null`);
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
let filteredTools = topTools.filter((tool) => tool.status === "未安装" && (tool.rrfScore ?? 0) >= 0.016);
|
|
138
|
+
logger.log(`${PLUGIN_LOG_PREFIX} [DEBUG] After filtering uninstalled with rrfScore >= 0.016: ${filteredTools.length}, details: ${filteredTools.map((t) => `${t.skillId}(rrfScore=${t.rrfScore})`).join(", ")}`);
|
|
139
|
+
if (filteredTools.length === 0) {
|
|
140
|
+
logger.log(`${PLUGIN_LOG_PREFIX} [DEBUG] No uninstalled skills with rrfScore >= 0.016, returning null`);
|
|
125
141
|
return null;
|
|
126
142
|
}
|
|
127
|
-
let filteredTools = topTools.filter((tool) => tool.status === "未安装");
|
|
128
|
-
console.log(`${PLUGIN_LOG_PREFIX} [DEBUG] After filtering uninstalled: ${filteredTools.length}, ids: ${filteredTools.map((t) => t.skillId).join(", ")}`);
|
|
129
143
|
return {
|
|
130
144
|
tools: filteredTools,
|
|
131
145
|
query,
|
|
132
146
|
timestamp: Date.now(),
|
|
133
147
|
};
|
|
134
148
|
}
|
|
135
|
-
|
|
149
|
+
logger.warn(`${PLUGIN_LOG_PREFIX} Invalid response format: ${JSON.stringify(responseData).slice(0, 200)}`);
|
|
136
150
|
return null;
|
|
137
151
|
}
|
|
138
152
|
catch (error) {
|
|
@@ -140,7 +154,7 @@ export async function searchTools(options) {
|
|
|
140
154
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
141
155
|
const errorCause = error instanceof Error && error.cause ? JSON.stringify(error.cause) : "N/A";
|
|
142
156
|
const errorStack = error instanceof Error ? error.stack?.split("\n").slice(0, 3).join(" | ") : "N/A";
|
|
143
|
-
|
|
157
|
+
logger.warn(`${PLUGIN_LOG_PREFIX} [ERROR] Fetch failed - name: ${errorName}, message: ${errorMessage}, cause: ${errorCause}, stack: ${errorStack}`);
|
|
144
158
|
return null;
|
|
145
159
|
}
|
|
146
160
|
}
|
|
@@ -13,6 +13,7 @@ export interface RawSkill {
|
|
|
13
13
|
skillName: string;
|
|
14
14
|
skillDesc: string;
|
|
15
15
|
packUrl: string;
|
|
16
|
+
rrfScore?: number;
|
|
16
17
|
}
|
|
17
18
|
export interface FormattedSkill {
|
|
18
19
|
skillId: string;
|
|
@@ -20,6 +21,7 @@ export interface FormattedSkill {
|
|
|
20
21
|
skillDesc: string;
|
|
21
22
|
downloadPath: string;
|
|
22
23
|
status: "已安装" | "未安装";
|
|
24
|
+
rrfScore?: number;
|
|
23
25
|
}
|
|
24
26
|
export interface ToolSearchResult {
|
|
25
27
|
tools: FormattedSkill[];
|
|
@@ -57,7 +57,7 @@ export async function tryInjectSteer(sessionKey, message) {
|
|
|
57
57
|
},
|
|
58
58
|
},
|
|
59
59
|
};
|
|
60
|
-
|
|
60
|
+
logger.log(`[STEER] Injecting steer for sessionId=${sessionId}, taskId=${syntheticMessage.params.id}`);
|
|
61
61
|
try {
|
|
62
62
|
await handleXYMessage({
|
|
63
63
|
cfg: cachedCfg,
|
|
@@ -48,6 +48,10 @@ export declare function hasActiveTask(sessionId: string): boolean;
|
|
|
48
48
|
* 获取完整的binding信息(用于调试)
|
|
49
49
|
*/
|
|
50
50
|
export declare function getTaskIdBinding(sessionId: string): TaskIdBinding | null;
|
|
51
|
+
/**
|
|
52
|
+
* 获取所有活跃的 task bindings(用于 gateway_stop 通知等场景)
|
|
53
|
+
*/
|
|
54
|
+
export declare function getAllActiveTaskBindings(): TaskIdBinding[];
|
|
51
55
|
/**
|
|
52
56
|
* 强制清理(错误恢复用)
|
|
53
57
|
*/
|
package/dist/src/task-manager.js
CHANGED
|
@@ -5,8 +5,13 @@ import { logger } from "./utils/logger.js";
|
|
|
5
5
|
* Session到活跃TaskId的映射
|
|
6
6
|
* Key: sessionId (注意:这里用sessionId,不是sessionKey)
|
|
7
7
|
* Value: TaskIdBinding
|
|
8
|
+
* Uses globalThis to ensure a single Map across all module copies.
|
|
8
9
|
*/
|
|
9
|
-
const
|
|
10
|
+
const _g = globalThis;
|
|
11
|
+
if (!_g.__xyActiveTaskIds) {
|
|
12
|
+
_g.__xyActiveTaskIds = new Map();
|
|
13
|
+
}
|
|
14
|
+
const activeTaskIds = _g.__xyActiveTaskIds;
|
|
10
15
|
/**
|
|
11
16
|
* 注册或更新session的活跃taskId
|
|
12
17
|
* 返回是否是更新(用于判断是否是第二条消息)
|
|
@@ -127,6 +132,12 @@ export function hasActiveTask(sessionId) {
|
|
|
127
132
|
export function getTaskIdBinding(sessionId) {
|
|
128
133
|
return activeTaskIds.get(sessionId) ?? null;
|
|
129
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* 获取所有活跃的 task bindings(用于 gateway_stop 通知等场景)
|
|
137
|
+
*/
|
|
138
|
+
export function getAllActiveTaskBindings() {
|
|
139
|
+
return Array.from(activeTaskIds.values());
|
|
140
|
+
}
|
|
130
141
|
/**
|
|
131
142
|
* 强制清理(错误恢复用)
|
|
132
143
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { SessionContext } from "./session-manager.js";
|
|
1
2
|
/**
|
|
2
3
|
* XY calendar event tool - creates a calendar event on user's device.
|
|
3
4
|
* Requires title, dtStart (start time), and dtEnd (end time) parameters.
|
|
4
5
|
* Time format must be: yyyy-mm-dd hh:mm:ss
|
|
5
6
|
*/
|
|
6
|
-
export declare
|
|
7
|
+
export declare function createCalendarTool(ctx: SessionContext): any;
|