@honor-claw/yoyo 2026.9.4-beta.2 → 2026.9.4-beta.4
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/capabilities/cron/service.mjs +43 -40
- package/dist/capabilities/cron/timezone.mjs +16 -0
- package/dist/cloud-channel/handlers/context/cron.mjs +2 -1
- package/dist/command/mock/handler.mjs +1 -0
- package/dist/core/prompt/builder.mjs +11 -9
- package/dist/core/prompt/cron.mjs +23 -14
- package/dist/core/prompt/skill-fallback.mjs +34 -0
- package/dist/modules/configs/plugin-init.mjs +15 -11
- package/dist/provisioning/toolset/index.mjs +1 -0
- package/dist/provisioning/toolset/skill-catalog.mjs +61 -0
- package/openclaw.plugin.json +2 -1
- package/package.json +2 -1
- package/skills/yoyo-phone-control/mcptools/active_memory.json +6 -6
- package/skills/yoyo-phone-control/mcptools/check_alarm.json +13 -1
- package/skills/yoyo-phone-control/mcptools/close_alarm.json +1 -5
- package/skills/yoyo-phone-control/mcptools/search_message.json +5 -1
|
@@ -5,71 +5,74 @@ import { resolveChatIdFromTo as r } from "../../messaging/target/outbound.mjs";
|
|
|
5
5
|
import "../../messaging/target/index.mjs";
|
|
6
6
|
import { CronRunStatus as i } from "../../messaging/notification/types.mjs";
|
|
7
7
|
import "../../messaging/notification/index.mjs";
|
|
8
|
+
import { resolveListTimezone as a } from "./timezone.mjs";
|
|
8
9
|
//#region src/capabilities/cron/service.ts
|
|
9
|
-
var
|
|
10
|
-
function
|
|
11
|
-
|
|
10
|
+
var o = t("cron"), s = 50, c;
|
|
11
|
+
function l(e) {
|
|
12
|
+
c = e, o.info("cron service handle updated", { available: e !== void 0 });
|
|
12
13
|
}
|
|
13
|
-
function
|
|
14
|
-
|
|
14
|
+
function u() {
|
|
15
|
+
c = void 0;
|
|
15
16
|
}
|
|
16
|
-
async function
|
|
17
|
+
async function d(t, r) {
|
|
17
18
|
let i = await n(t, r);
|
|
18
|
-
if (!i) return
|
|
19
|
+
if (!i) return o.info("cron list: request device has no chat mapping, empty result", {
|
|
19
20
|
accountId: t,
|
|
20
21
|
requestDeviceId: r
|
|
21
22
|
}), {
|
|
22
23
|
ok: !0,
|
|
23
24
|
jobs: [],
|
|
24
|
-
total: 0
|
|
25
|
+
total: 0,
|
|
26
|
+
timezone: a()
|
|
25
27
|
};
|
|
26
|
-
let
|
|
27
|
-
if (!
|
|
28
|
+
let l = c;
|
|
29
|
+
if (!l) return {
|
|
28
30
|
ok: !1,
|
|
29
31
|
error: "cron_unavailable"
|
|
30
32
|
};
|
|
31
|
-
let
|
|
33
|
+
let u;
|
|
32
34
|
try {
|
|
33
|
-
|
|
35
|
+
u = await l.list({ includeDisabled: !0 });
|
|
34
36
|
} catch (t) {
|
|
35
|
-
return
|
|
37
|
+
return o.error("cron list failed", t), {
|
|
36
38
|
ok: !1,
|
|
37
39
|
error: e(t)
|
|
38
40
|
};
|
|
39
41
|
}
|
|
40
|
-
let
|
|
41
|
-
for (let e of
|
|
42
|
-
if (!await
|
|
43
|
-
let n =
|
|
44
|
-
n &&
|
|
42
|
+
let d = [];
|
|
43
|
+
for (let e of u) {
|
|
44
|
+
if (!await h(e, t, i)) continue;
|
|
45
|
+
let n = g(e);
|
|
46
|
+
n && d.push(n);
|
|
45
47
|
}
|
|
46
|
-
return
|
|
48
|
+
return o.info("cron list for chat", {
|
|
47
49
|
accountId: t,
|
|
48
50
|
requestDeviceId: r,
|
|
49
51
|
requestChatId: i,
|
|
50
|
-
total:
|
|
51
|
-
owned:
|
|
52
|
-
returned: Math.min(
|
|
52
|
+
total: u.length,
|
|
53
|
+
owned: d.length,
|
|
54
|
+
returned: Math.min(d.length, s)
|
|
53
55
|
}), {
|
|
54
56
|
ok: !0,
|
|
55
|
-
jobs:
|
|
56
|
-
total:
|
|
57
|
+
jobs: d.slice(0, s),
|
|
58
|
+
total: u.length,
|
|
59
|
+
timezone: a()
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
|
-
async function
|
|
60
|
-
let n =
|
|
62
|
+
async function f(t) {
|
|
63
|
+
let n = c;
|
|
61
64
|
if (n) try {
|
|
62
65
|
return (await n.list({ includeDisabled: !1 })).find((e) => e?.id === t);
|
|
63
66
|
} catch (n) {
|
|
64
|
-
|
|
67
|
+
o.warn("cron job lookup failed", {
|
|
65
68
|
jobId: t,
|
|
66
69
|
error: e(n)
|
|
67
70
|
});
|
|
68
71
|
return;
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
|
-
async function
|
|
72
|
-
let n =
|
|
74
|
+
async function p(t) {
|
|
75
|
+
let n = c;
|
|
73
76
|
if (!n) return {
|
|
74
77
|
ok: !1,
|
|
75
78
|
error: "cron_unavailable"
|
|
@@ -80,36 +83,36 @@ async function f(t) {
|
|
|
80
83
|
removed: (await n.remove(t))?.removed === !0
|
|
81
84
|
};
|
|
82
85
|
} catch (r) {
|
|
83
|
-
return await
|
|
86
|
+
return await m(n, t) === !1 ? (o.warn("cron remove errored but job no longer exists, treated as success", {
|
|
84
87
|
jobId: t,
|
|
85
88
|
error: e(r)
|
|
86
89
|
}), {
|
|
87
90
|
ok: !0,
|
|
88
91
|
removed: !1
|
|
89
|
-
}) : (
|
|
92
|
+
}) : (o.error("cron remove failed", r, { jobId: t }), {
|
|
90
93
|
ok: !1,
|
|
91
94
|
error: e(r)
|
|
92
95
|
});
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
|
-
async function
|
|
98
|
+
async function m(t, n) {
|
|
96
99
|
try {
|
|
97
100
|
return (await t.list({ includeDisabled: !0 })).some((e) => e?.id === n);
|
|
98
101
|
} catch (t) {
|
|
99
|
-
|
|
102
|
+
o.warn("cron job presence lookup failed", {
|
|
100
103
|
jobId: n,
|
|
101
104
|
error: e(t)
|
|
102
105
|
});
|
|
103
106
|
return;
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
|
-
async function
|
|
109
|
+
async function h(e, t, n) {
|
|
107
110
|
let i = e.delivery?.to;
|
|
108
111
|
return typeof i != "string" || i.length === 0 ? !1 : await r(i, t) === n;
|
|
109
112
|
}
|
|
110
|
-
function
|
|
113
|
+
function g(e) {
|
|
111
114
|
if (e.enabled !== !0) return;
|
|
112
|
-
let t =
|
|
115
|
+
let t = _(e.schedule);
|
|
113
116
|
if (!t) return;
|
|
114
117
|
let n = e.state, r = n?.lastRunAtMs;
|
|
115
118
|
if (r != null) {
|
|
@@ -122,11 +125,11 @@ function h(e) {
|
|
|
122
125
|
...e.description ? { description: e.description } : {},
|
|
123
126
|
schedule: t,
|
|
124
127
|
nextRunAtMs: n?.nextRunAtMs ?? null,
|
|
125
|
-
...n?.lastRunStatus === void 0 ? {} : { lastRunStatus:
|
|
128
|
+
...n?.lastRunStatus === void 0 ? {} : { lastRunStatus: v(n.lastRunStatus) },
|
|
126
129
|
...r === void 0 ? {} : { lastRunAtMs: r }
|
|
127
130
|
};
|
|
128
131
|
}
|
|
129
|
-
function
|
|
132
|
+
function _(e) {
|
|
130
133
|
switch (e?.kind) {
|
|
131
134
|
case "cron": return {
|
|
132
135
|
kind: "cron",
|
|
@@ -146,7 +149,7 @@ function g(e) {
|
|
|
146
149
|
default: return;
|
|
147
150
|
}
|
|
148
151
|
}
|
|
149
|
-
function
|
|
152
|
+
function v(e) {
|
|
150
153
|
switch (e) {
|
|
151
154
|
case "ok": return i.Success;
|
|
152
155
|
case "error": return i.Failed;
|
|
@@ -154,4 +157,4 @@ function _(e) {
|
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
//#endregion
|
|
157
|
-
export {
|
|
160
|
+
export { l as captureCronService, f as findCronJobById, d as listCronJobsForChat, u as releaseCronService, p as removeCronJob };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getRuntimeConfig as e } from "openclaw/plugin-sdk/config-runtime";
|
|
2
|
+
//#region src/capabilities/cron/timezone.ts
|
|
3
|
+
function t() {
|
|
4
|
+
let t = e().agents?.defaults?.userTimezone, r = typeof t == "string" ? t.trim() : "";
|
|
5
|
+
return n(r) ? r : Intl.DateTimeFormat().resolvedOptions().timeZone?.trim() || "UTC";
|
|
6
|
+
}
|
|
7
|
+
function n(e) {
|
|
8
|
+
if (!e) return !1;
|
|
9
|
+
try {
|
|
10
|
+
return new Intl.DateTimeFormat("en-US", { timeZone: e }).format(/* @__PURE__ */ new Date()), !0;
|
|
11
|
+
} catch {
|
|
12
|
+
return !1;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { t as resolveListTimezone };
|
|
@@ -51,6 +51,7 @@ function m(e, t) {
|
|
|
51
51
|
` 请求方:account=\`${t.accountId}\` deviceId=\`${t.deviceId}\``,
|
|
52
52
|
` 归属过滤键:\`chat:${t.chatId}\`(delivery.to 归一后等于该 chatId 的任务才返回)`,
|
|
53
53
|
` 任务统计:网关共 ${e.total} 条,归属当前会话 ${e.jobs.length} 条`,
|
|
54
|
+
` 展示时区:\`${e.timezone}\`(at/every 墙钟换算)`,
|
|
54
55
|
""
|
|
55
56
|
];
|
|
56
57
|
return e.jobs.length === 0 ? (n.push(e.total > 0 ? `(当前会话无归属任务;网关另有 ${e.total} 条任务,其 delivery.to 未指向 \`chat:${t.chatId}\`)` : "(网关无任何任务)", "", "验证提示:端侧任务列表应同样为空"), n.join("\n")) : (n.push("| # | 名称 | jobId | 调度 | 下次执行 | 上次执行 |", "| --- | --- | --- | --- | --- | --- |", ...e.jobs.map((e, t) => p(t + 1, e)), "", " ", "", "验证提示:", "- 端侧任务列表应与上表一致(列即端侧 DTO 投影,无 delivery 等内部字段)", "- 删除验证:`/yoyo mock cron remove <jobId>` 后重新执行本命令,对应任务应消失"), n.join("\n"));
|
|
@@ -2,27 +2,29 @@ import { resolveAgentPromptContribution as e } from "./agent.mjs";
|
|
|
2
2
|
import { resolveCloudToolPromptContribution as t } from "./cloud-tool.mjs";
|
|
3
3
|
import { resolveCronDeliveryPromptContribution as n } from "./cron.mjs";
|
|
4
4
|
import { resolveLocationPromptContribution as r } from "./location.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveCronSkillFallbackContribution as i } from "./skill-fallback.mjs";
|
|
6
|
+
import { resolveSkillPromptContribution as a } from "./skill.mjs";
|
|
6
7
|
//#region src/core/prompt/builder.ts
|
|
7
|
-
function
|
|
8
|
+
function o(e) {
|
|
8
9
|
let t = e.filter((e) => !!e);
|
|
9
10
|
return t.length > 0 ? t.join("\n\n") : void 0;
|
|
10
11
|
}
|
|
11
|
-
function
|
|
12
|
-
let t =
|
|
12
|
+
function s(e) {
|
|
13
|
+
let t = o(e.map((e) => e.prependSystemContext)), n = o(e.map((e) => e.prependContext));
|
|
13
14
|
return {
|
|
14
15
|
...t ? { prependSystemContext: t } : {},
|
|
15
16
|
...n ? { prependContext: n } : {}
|
|
16
17
|
};
|
|
17
18
|
}
|
|
18
|
-
async function
|
|
19
|
-
return
|
|
19
|
+
async function c(o) {
|
|
20
|
+
return s([
|
|
20
21
|
t(),
|
|
21
22
|
e(),
|
|
22
|
-
n(
|
|
23
|
-
await
|
|
23
|
+
n(o),
|
|
24
|
+
await a(),
|
|
25
|
+
await i(o),
|
|
24
26
|
r()
|
|
25
27
|
]);
|
|
26
28
|
}
|
|
27
29
|
//#endregion
|
|
28
|
-
export {
|
|
30
|
+
export { c as resolvePromptBuildContribution };
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import "../../
|
|
2
|
-
import { looksLikeChatId as
|
|
3
|
-
import { readChatIdFromSessionKey as
|
|
1
|
+
import { clawLogger as e } from "../../utils/claw-logger.mjs";
|
|
2
|
+
import { looksLikeChatId as t } from "../../messaging/target/chat-id.mjs";
|
|
3
|
+
import { readChatIdFromSessionKey as n } from "../../messaging/target/address.mjs";
|
|
4
4
|
import "../../messaging/target/index.mjs";
|
|
5
5
|
//#region src/core/prompt/cron.ts
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
var r = e("cron");
|
|
7
|
+
function i(e) {
|
|
8
|
+
return e.chatId && t(e.chatId) ? e.chatId : void 0;
|
|
8
9
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
function a(e) {
|
|
11
|
+
let t = e ? n(e.sessionKey) : void 0, a = t || (e ? i(e) : void 0);
|
|
12
|
+
return !e || !a ? (r.debug("cron delivery prompt skipped: no resolvable chatId", {
|
|
13
|
+
sessionKey: e?.sessionKey ?? null,
|
|
14
|
+
turnChatId: e?.chatId ?? null
|
|
15
|
+
}), {}) : (r.info("cron delivery prompt injected", {
|
|
16
|
+
sessionKey: e.sessionKey ?? null,
|
|
17
|
+
chatId: a,
|
|
18
|
+
source: t ? "sessionKey" : "turn"
|
|
19
|
+
}), { prependSystemContext: `# 定时任务投递目标
|
|
20
|
+
当前对话来自 YOYO 手机侧会话(chatId: ${a}),在本会话中创建定时任务时:
|
|
21
|
+
- 创建方式优先使用 automations 或 cron 工具;两者都不可用时再考虑使用 openclaw cron 命令行,尽量不要使用 subagent。
|
|
22
|
+
- 无论用哪种方式创建,delivery 必须完整包含以下三个字段,缺一不可:
|
|
23
|
+
{mode:"announce", channel:"yoyo", to:"chat:${a}"}
|
|
24
|
+
- 特别注意 to 字段必须显式写为 "chat:${a}"。即使工具或命令行看起来能自动推断投递目标,也不省略 to —— 缺少 to 的任务执行结果无法推送回本会话。
|
|
25
|
+
- 当用户显式指定投递给其他手机、设备或者 channel 时,可以不按当前规则处理,to 也可以为目标设备对应的 device:{deviceId}` });
|
|
17
26
|
}
|
|
18
27
|
//#endregion
|
|
19
|
-
export {
|
|
28
|
+
export { a as resolveCronDeliveryPromptContribution };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { clawLogger as e } from "../../utils/claw-logger.mjs";
|
|
2
|
+
import { loadYoyoSkillCatalog as t } from "../../provisioning/toolset/skill-catalog.mjs";
|
|
3
|
+
//#region src/core/prompt/skill-fallback.ts
|
|
4
|
+
var n = e("hooks"), r = new Set(["yoyo-update"]);
|
|
5
|
+
async function i(e) {
|
|
6
|
+
if (!e || e.trigger !== "cron" || e.channel !== "yoyo") return n.debug("cron skill fallback skipped: not a yoyo cron turn", {
|
|
7
|
+
trigger: e?.trigger ?? null,
|
|
8
|
+
channel: e?.channel ?? null
|
|
9
|
+
}), {};
|
|
10
|
+
let i = (await t())?.filter((e) => !r.has(e.name)) ?? [];
|
|
11
|
+
return i.length === 0 ? (n.warn("cron skill fallback skipped: empty skill catalog"), {}) : (n.info("cron skill fallback prompt injected", {
|
|
12
|
+
sessionKey: e.sessionKey ?? null,
|
|
13
|
+
skillCount: i.length
|
|
14
|
+
}), { prependSystemContext: a(i) });
|
|
15
|
+
}
|
|
16
|
+
function a(e) {
|
|
17
|
+
return `# 定时任务技能目录
|
|
18
|
+
当前会话由定时任务触发,系统提示词中可能缺少技能目录。以下是 YOYO 插件自带技能,使用规则与常规会话一致:
|
|
19
|
+
- 先扫描 <available_skills>:与当前任务明确匹配的技能,用 read 工具按 <location> 的绝对路径读取 SKILL.md 全文,并严格遵守其内容执行;没有匹配则不读取。
|
|
20
|
+
- 多个匹配时只选最贴切的一个,最多预读一个;禁止编造路径。
|
|
21
|
+
- 技能正文引用相对路径时,以 SKILL.md 所在目录为基准解析为绝对路径后再调用工具。
|
|
22
|
+
|
|
23
|
+
<available_skills>
|
|
24
|
+
${e.map((e) => {
|
|
25
|
+
let t = [" <skill>", ` <name>${o(e.name)}</name>`];
|
|
26
|
+
return e.description && t.push(` <description>${o(e.description)}</description>`), t.push(` <location>${o(e.location)}</location>`, " </skill>"), t.join("\n");
|
|
27
|
+
}).join("\n")}
|
|
28
|
+
</available_skills>`;
|
|
29
|
+
}
|
|
30
|
+
function o(e) {
|
|
31
|
+
return e.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { i as resolveCronSkillFallbackContribution };
|
|
@@ -30,19 +30,23 @@ async function p(e) {
|
|
|
30
30
|
count: Object.keys(M).length,
|
|
31
31
|
mapping: Object.entries(M).map(([e, t]) => `${e} -> ${t}`).join(", ")
|
|
32
32
|
});
|
|
33
|
-
let P = c(t), F = P.changed;
|
|
34
|
-
if (!g && !_ && !O && !j && !N && !F && !y) return;
|
|
35
|
-
let
|
|
36
|
-
g && delete
|
|
37
|
-
let
|
|
33
|
+
let P = c(t), F = P.changed, I = t.plugins?.entries?.[e]?.hooks?.allowConversationAccess !== !0;
|
|
34
|
+
if (!g && !_ && !O && !j && !N && !F && !y && !I) return;
|
|
35
|
+
let L = { ...t.plugins };
|
|
36
|
+
g && delete L.allow;
|
|
37
|
+
let R = {
|
|
38
38
|
...t,
|
|
39
39
|
plugins: {
|
|
40
|
-
...
|
|
40
|
+
...L,
|
|
41
41
|
entries: {
|
|
42
42
|
...t.plugins?.entries,
|
|
43
43
|
[e]: {
|
|
44
44
|
...t.plugins?.entries?.[e],
|
|
45
45
|
enabled: !0,
|
|
46
|
+
...I ? { hooks: {
|
|
47
|
+
...t.plugins?.entries?.[e]?.hooks,
|
|
48
|
+
allowConversationAccess: !0
|
|
49
|
+
} } : {},
|
|
46
50
|
config: A
|
|
47
51
|
}
|
|
48
52
|
}
|
|
@@ -52,11 +56,11 @@ async function p(e) {
|
|
|
52
56
|
alsoAllow: b
|
|
53
57
|
} } : {}
|
|
54
58
|
};
|
|
55
|
-
F && (
|
|
56
|
-
...
|
|
59
|
+
F && (R = {
|
|
60
|
+
...R,
|
|
57
61
|
agents: P.agents
|
|
58
|
-
}, d.info("refreshed agents.defaults values", { changes: P.changes.join(", ") })), _ && (
|
|
59
|
-
...
|
|
62
|
+
}, d.info("refreshed agents.defaults values", { changes: P.changes.join(", ") })), _ && (R = {
|
|
63
|
+
...R,
|
|
60
64
|
skills: {
|
|
61
65
|
...r,
|
|
62
66
|
load: {
|
|
@@ -64,7 +68,7 @@ async function p(e) {
|
|
|
64
68
|
watch: !1
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
|
-
}, d.info("disabled skills.load.watch for plugin")), N && (
|
|
71
|
+
}, d.info("disabled skills.load.watch for plugin")), N && (R = u(R, M), d.info("provider renaming completed")), await a(R);
|
|
68
72
|
} catch (e) {
|
|
69
73
|
throw t(e, "failed to initialize plugin config");
|
|
70
74
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { clawLogger as e } from "../../utils/claw-logger.mjs";
|
|
2
|
+
import { normalizeString as t } from "../../utils/normalize.mjs";
|
|
3
|
+
import { resolveExtensionRoot as n } from "../../utils/home-dir.mjs";
|
|
4
|
+
import r from "node:path";
|
|
5
|
+
import i from "node:fs/promises";
|
|
6
|
+
import { parseDocument as a } from "yaml";
|
|
7
|
+
//#region src/provisioning/toolset/skill-catalog.ts
|
|
8
|
+
var o = e("toolset"), s = "skills", c = "SKILL.md", l;
|
|
9
|
+
async function u() {
|
|
10
|
+
if (l) return l;
|
|
11
|
+
try {
|
|
12
|
+
l = await d();
|
|
13
|
+
} catch (e) {
|
|
14
|
+
o.warn("skill catalog scan failed", { error: String(e) });
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
return l;
|
|
18
|
+
}
|
|
19
|
+
async function d() {
|
|
20
|
+
let e = r.join(n(), s), t = await i.readdir(e, { withFileTypes: !0 }), a = [];
|
|
21
|
+
for (let n of t) {
|
|
22
|
+
if (!n.isDirectory()) continue;
|
|
23
|
+
let t = r.join(e, n.name, c), i = await f(t);
|
|
24
|
+
if (!i) {
|
|
25
|
+
o.warn("skill catalog entry skipped: missing or incomplete frontmatter", { skillPath: t });
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
a.push({
|
|
29
|
+
...i,
|
|
30
|
+
location: t
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return a.sort((e, t) => e.name.localeCompare(t.name)), a;
|
|
34
|
+
}
|
|
35
|
+
async function f(e) {
|
|
36
|
+
let t;
|
|
37
|
+
try {
|
|
38
|
+
t = await i.readFile(e, "utf8");
|
|
39
|
+
} catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
return p(t);
|
|
43
|
+
}
|
|
44
|
+
function p(e) {
|
|
45
|
+
let n = /^---\r?\n([\s\S]*?)\r?\n---/.exec(e);
|
|
46
|
+
if (!n) return;
|
|
47
|
+
let r = a(n[1], {
|
|
48
|
+
schema: "core",
|
|
49
|
+
prettyErrors: !1
|
|
50
|
+
});
|
|
51
|
+
if (r.errors.length > 0) return;
|
|
52
|
+
let i = r.toJS();
|
|
53
|
+
if (typeof i != "object" || !i) return;
|
|
54
|
+
let o = i, s = t(o.name) || void 0, c = t(o.description) || void 0;
|
|
55
|
+
return s && c ? {
|
|
56
|
+
name: s,
|
|
57
|
+
description: c
|
|
58
|
+
} : void 0;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { u as loadYoyoSkillCatalog };
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@honor-claw/yoyo",
|
|
3
|
-
"version": "2026.9.4-beta.
|
|
3
|
+
"version": "2026.9.4-beta.4",
|
|
4
4
|
"description": "OpenClaw Honor Yoyo connection plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"undici": "^7.3.0",
|
|
49
49
|
"winreg": "^1.2.5",
|
|
50
50
|
"ws": "^8.18.0",
|
|
51
|
+
"yaml": "^2.9.0",
|
|
51
52
|
"zod": "^4.3.6"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"imageUrls": {
|
|
14
14
|
"type": "array",
|
|
15
|
-
"description": "
|
|
15
|
+
"description": "参数表示当前记忆操作可能的图片标识,优先填写图片URL,无可用URL时填写图片名称。默认传入图片是上下文相关的,必须传入图片URL。如果用户提到\\\"图1/图2/第N张/这x张/最后一张/上一张\\\"时需提供对应图片URL, 否则默认传最后一个图片。格式为长度最多为 1 的字符串数组。无图片时不传该参数。",
|
|
16
16
|
"items": {
|
|
17
17
|
"type": "string",
|
|
18
18
|
"description": "图片URL或图片名称"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"docUrls": {
|
|
22
22
|
"type": "array",
|
|
23
|
-
"description": "
|
|
23
|
+
"description": "参数表示当前记忆操作可能的文件标识,优先填写文件URL,无可用URL时填写文件名称。默认传入文件是上下文相关的,必须传入文件URL。如果用户提到\\\"文件1/文件2/第N个/这x个/最后一个/上一个\\\"时需提供对应文件URL, 否则默认传最后一个文件。格式为长度最多为 1 的字符串数组。无文件时不传该参数。",
|
|
24
24
|
"items": {
|
|
25
25
|
"type": "string",
|
|
26
26
|
"description": "文件URL或文件名称"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"图片",
|
|
43
43
|
"文件"
|
|
44
44
|
],
|
|
45
|
-
"description": "
|
|
45
|
+
"description": "需要处理的记忆载体类型:`文本` 为仅涉及纯文字信息,没有传入任何图片和文件;`图片` 为本次操作涉及任何图片时填写,并传入图片参数;`文件` 为本次操作涉及任何非图片文件时填写,并传入文件参数。"
|
|
46
46
|
},
|
|
47
47
|
"confirmState": {
|
|
48
48
|
"type": "string",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"confirm",
|
|
51
51
|
"cancel"
|
|
52
52
|
],
|
|
53
|
-
"description": "二次确认结果:confirm
|
|
53
|
+
"description": "二次确认结果:confirm表示确认执行,cancel表示在确认环节取消操作。仅当用户亲自对记忆操作执行的追问内容进行回复时填写,非确认场景勿传。若用户在记忆完成后下一句话立即提出对这条记忆的 修改/删除 指令,默认视为确认执行,传 confirm。传 confirm 或 cancel 时,query 均须结合对话上下文还原待确认的记忆操作并保留对应动作词,memoryAction 与待确认操作类型一致。"
|
|
54
54
|
},
|
|
55
55
|
"memoryContent": {
|
|
56
56
|
"type": "string",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"memorySourceContent": {
|
|
60
60
|
"type": "string",
|
|
61
|
-
"description": "
|
|
61
|
+
"description": "仅修改时填写需被替换的修改前原内容;如“把 A 改成 B”,此字段填 A。不要填写修改后的结果,也不要混入新增内容或删除内容。若用户未明确提供需要修改的原内容,或本次仅为新增和删除记忆,则不传该字段。"
|
|
62
62
|
},
|
|
63
63
|
"confirmedMemoryIdList": {
|
|
64
64
|
"type": "array",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"query": "把我的心情记录从紧张改成轻松,再记一下小红爱运动 [工具调用 1/2]",
|
|
120
|
-
"arguments": "{\n \"query\": \"修改我的心情记录是轻松\",\n \"memoryContent\": \"我的心情记录是轻松\",\n \"memoryAction\": \"修改\",\n \"memoMode\": \"文本\"\n}"
|
|
120
|
+
"arguments": "{\n \"query\": \"修改我的心情记录是轻松\",\n \"memoryContent\": \"我的心情记录是轻松\",\n \"memoryAction\": \"修改\",\n \"memoMode\": \"文本\"\n,\n \"memorySourceContent\": \"我的心情记录是紧张\"\n}"
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
"query": "把我的心情记录从紧张改成轻松,再记一下小红爱运动 [工具调用 2/2]",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "1a1258b7-0cdb-48cc-80ec-1f063287807c",
|
|
3
3
|
"type": "function",
|
|
4
4
|
"name": "check_alarm",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "用于查看闹钟的工具。当用户意图涉及查询闹钟或闹铃时,可以使用该工具。支持按日期时间、事件、序号、启用状态,以及查询最近一个闹钟等条件进行查询。不适用于创建、修改、删除、开启、关闭闹钟等非查询操作场景。",
|
|
6
6
|
"inputSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"properties": {
|
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
"type": "string",
|
|
15
15
|
"description": "参数表示用户查询的闹钟日期或时间条件。包括具体的日期时间(年月日、时间点)、泛指的时间(如上午)、周期性时间(如'每天'、'每周'、'大小周'、'单休工作日'、'节假日及周末'、'法定工作日'、'轮班制')。填写时保留用户原始时间表达,不进行改写或标准化。填写格式为自然语言时间文本。"
|
|
16
16
|
},
|
|
17
|
+
"sequenceList": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"description": "用于表达用户通过序号方式查询需要操作的闹钟对象,表示查询的闹钟序号列表(整数数组),序号按照闹钟列表顺序从 1 开始计数。当用户在 query 中明确表达序号相关选择时填写,例如“第一个”“第二个”“前两个”等,用于用户在首次指令中直接给出序号表达的场景,例如“查询第一个闹钟”。填写格式为整数数组,例如 [1] 表示查询第一个闹钟,[1,2] 表示查询前两个闹钟;当该参数被填写时不应同时填写 rangeType,若同时出现以 rangeType 为准。",
|
|
20
|
+
"items": {
|
|
21
|
+
"type": "integer",
|
|
22
|
+
"description": "闹钟在候选列表中的序号,从1开始计数"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
17
25
|
"rangeType": {
|
|
18
26
|
"type": "string",
|
|
19
27
|
"enum": [
|
|
@@ -65,6 +73,10 @@
|
|
|
65
73
|
{
|
|
66
74
|
"query": "帮忙看看后天的闹钟",
|
|
67
75
|
"arguments": "{\"datetime\": \"后天\"}"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"query": "你帮我看看第三个闹钟呢",
|
|
79
|
+
"arguments": "{\"sequenceList\": [3]}"
|
|
68
80
|
}
|
|
69
81
|
]
|
|
70
82
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "c21bd3bb-2661-4d09-b7ed-a7b04dcc6687",
|
|
3
3
|
"type": "function",
|
|
4
4
|
"name": "close_alarm",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "用于关闭闹钟的工具,可根据标题、时间、最近一次引用及当前开关状态筛选目标闹钟,支持关闭单个或多个闹钟。当用户意图涉及关闭闹钟或闹铃时,可以使用该工具。",
|
|
6
6
|
"inputSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"properties": {
|
|
@@ -74,10 +74,6 @@
|
|
|
74
74
|
"query": "关闭起床的闹钟",
|
|
75
75
|
"arguments": "{\"event\": \"起床\"}"
|
|
76
76
|
},
|
|
77
|
-
{
|
|
78
|
-
"query": "取消闹钟",
|
|
79
|
-
"arguments": "{}"
|
|
80
|
-
},
|
|
81
77
|
{
|
|
82
78
|
"query": "关闭全部看电影的闹钟",
|
|
83
79
|
"arguments": "{\"event\": \"看电影\", \"selectState\": \"all\"}"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "4533bf77-7da7-43e4-9e76-9af3640d17ae",
|
|
3
3
|
"type": "function",
|
|
4
4
|
"name": "search_message",
|
|
5
|
-
"description": "支持查看短信服务,可按联系人、电话号码、短信内容或时间范围检索短信。contact、phoneNumber、content、datetime
|
|
5
|
+
"description": "支持查看短信服务,可按联系人、电话号码、短信内容或时间范围检索短信。contact、phoneNumber、content、datetime 均为可选筛选条件,可单独或组合使用;均为空时(如仅说“查找短信”)默认查找最近30天的短信。",
|
|
6
6
|
"inputSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"properties": {
|
|
@@ -70,6 +70,10 @@
|
|
|
70
70
|
{
|
|
71
71
|
"query": "查询今天下午1点到2点的短信",
|
|
72
72
|
"arguments": "{\"datetime\": \"今天下午1点到2点\"}"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"query": "查找短信",
|
|
76
|
+
"arguments": "{}"
|
|
73
77
|
}
|
|
74
78
|
]
|
|
75
79
|
}
|