@honor-claw/yoyo 2026.6.9-alpha.21 → 2026.6.9-alpha.22

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.
@@ -1,19 +1,24 @@
1
1
  import { resolveAgentPromptContribution as e } from "./agent.mjs";
2
- import { resolveSkillPromptContribution as t } from "./skill.mjs";
2
+ import { resolveCloudToolPromptContribution as t } from "./cloud-tool.mjs";
3
+ import { resolveSkillPromptContribution as n } from "./skill.mjs";
3
4
  //#region src/core/prompt/builder.ts
4
- function n(e) {
5
+ function r(e) {
5
6
  let t = e.filter((e) => !!e);
6
7
  return t.length > 0 ? t.join("\n\n") : void 0;
7
8
  }
8
- function r(e) {
9
- let t = n(e.map((e) => e.prependSystemContext)), r = n(e.map((e) => e.prependContext));
9
+ function i(e) {
10
+ let t = r(e.map((e) => e.prependSystemContext)), n = r(e.map((e) => e.prependContext));
10
11
  return {
11
12
  ...t ? { prependSystemContext: t } : {},
12
- ...r ? { prependContext: r } : {}
13
+ ...n ? { prependContext: n } : {}
13
14
  };
14
15
  }
15
- async function i() {
16
- return r([e(), await t()]);
16
+ async function a() {
17
+ return i([
18
+ e(),
19
+ t(),
20
+ await n()
21
+ ]);
17
22
  }
18
23
  //#endregion
19
- export { i as resolvePromptBuildContribution };
24
+ export { a as resolvePromptBuildContribution };
@@ -0,0 +1,7 @@
1
+ //#region src/core/prompt/cloud-tool.ts
2
+ var e = "## Skill 使用云工具调用规则\n\n当已读取的 SKILL.md frontmatter 包含 allowed-tools 声明时:\n\n1. 根据用户意图从 allowed-tools 选择工具。\n2. 调用前必须读取当前 skill 目录下对应的 mcptools/<name>.json。\n3. 从 JSON 的 id 获取 toolId,按 inputSchema 提取 params。\n4. 如果工具定义明确说明不可实际调用,则按其说明结束或退出当前 skill 流程。\n5. 其余工具调用 cloud_invoke,传入 { toolId, params }。\n6. cloud_invoke 返回 ok=false 时读取 errorMessage;ok=true 时直接消费 result,不要对 result 执行 JSON.parse。\n7. ok=true 但 result.cpErrorCode 存在时,仍按三方业务错误处理。\n\n不得猜测 toolId,不得使用未在 allowed-tools 中声明的工具。";
3
+ function t() {
4
+ return { prependSystemContext: e };
5
+ }
6
+ //#endregion
7
+ export { t as resolveCloudToolPromptContribution };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honor-claw/yoyo",
3
- "version": "2026.6.9-alpha.21",
3
+ "version": "2026.6.9-alpha.22",
4
4
  "description": "OpenClaw Honor Yoyo connection plugin",
5
5
  "keywords": [
6
6
  "ai",
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: honor-smart-home
3
+ description: 当用户需要控制智能家居硬件设备或查询设备状态时调用此技能。不处理手机、平板、电脑上的应用操作,也不处理设备使用教程、技术参数咨询、购买建议、未来定时任务或自动化规则创建。
4
+ metadata: { "openclaw": { "emoji": "🔄", "always": true } }
5
+ allowed-tools: device_control,device_query,skill_exit
6
+ ---
7
+
8
+ # 荣耀智能家居技能
9
+
10
+ 本技能用于处理用户的智能家居设备相关请求,包含两大能力:**设备操控**(device_control)和**设备查询**(device_query)。技能根据用户意图自动判断调用相应工具,实现对家居设备的精准控制与信息获取。
11
+
12
+ ## 工具选择
13
+
14
+ | 用户意图特征 | 调用工具 |
15
+ | ----------------------------------------------------------------------------- | -------------- |
16
+ | 有操作动词,意图是"改变"设备状态 | device_control |
17
+ | 有疑问词(吗/多少/几度/什么)或查看类动词(看看/查看/查询),意图是"获取"信息 | device_query |
18
+ | 请求不属于设备操控或查询范畴 | skill_exit |
19
+
20
+ **必须调用 `skill_exit` 的详细场景**:
21
+
22
+ - **应用软件操作**: 如"打开微信"、"打开智慧空间"
23
+ - **使用指导与教学**: 如"空调怎么定时?"
24
+ - **技术参数咨询**: 如"这个灯的功率是多少?"
25
+ - **购买建议与推荐**: 如"哪款空气净化器好?"
26
+ - **定时、延时或周期任务**: 如"10分钟后关灯"、"每天早8点开窗帘"
27
+ - **自动化或条件触发规则**: 如"温度高于28度自动开空调"
28
+ - **非家居硬件设备请求**: 如"我想听音乐"(未指定智能音箱设备)
29
+
30
+ 明确智能家居播放器设备的硬件控制属于本技能;具体歌曲、视频、节目等内容播放或检索不属于本技能。
31
+
32
+ ## 参数构建与完整性校验规则
33
+
34
+ 两个工具均通过 `query` 参数接收自然语言指令,构建参数时遵循 **“明确意图 → 补全信息 → 风险评估 → 执行决策”** 的流程。
35
+
36
+ ### 核心原则
37
+
38
+ 1. **忠实原意**: `query` 必须严格遵循用户原始意图,不得擅自添加、减少或修改用户未明确表达的关键信息。可依据“多轮对话规则”利用上下文进行合理补全。
39
+ 2. **保留设备信息**: `query` 必须原样保留设备位置、品牌、名称/昵称(如“客厅的空调”、“小米插座”),由下游工具进行实体匹配。
40
+ 3. **规范化处理**:允许去除闲聊、礼貌或情绪化表达,简化为明确意图;但设备名称、昵称、位置、品牌必须保留原表达。
41
+
42
+ ### 分级校验流程
43
+
44
+ 对构建好的 `query` 进行层层递进校验,任何一环不通过则进入相应交互流程,不执行工具调用。
45
+
46
+ 1. **设备明确性校验**:若指令中无法解析出目标设备,必须追问具体设备。可结合上下文或用户设备列表进行引导,如:“您想控制哪里的灯?”
47
+
48
+ 2. **按操作类型判断是否需要参数**
49
+ - **无需参数的操作,直接调用**: 开、关、播放/暂停、停止、回充、上锁、下一首等动作本身即完整意图的操作,设备明确即可构建 query
50
+ - **需要具体参数的操作,缺失时追问**: 设置[值]、切换[到某状态]、调整[为某档位]等需要明确目标值的操作。如果用户未说明目标值,必须追问。如:“设置温度” → 追问:“您希望设置到多少度呢?”“切换模式” → 追问:“您想切换到什么模式?” “调整风速” → 追问:“您想调到几档风速?”
51
+ - **需相对参数的操作,直接调用**: 有明确方向的相对调节可直接调用工具;回复时只播报工具返回的实际结果。若工具未返回具体变化值,只说明“已帮您调高一点”。
52
+ - **无明确方向的调节**: 如“调一下”、“设置一下”,需追问用户具体目标或者参数。
53
+
54
+ 3. **风险与合理性校验**
55
+ - **常识合理性校验**: 参数明显超出合理范围(如空调设为0℃或40℃)时,暂停并提示用户确认。
56
+ - **高风险操作确认机制**: 对于打开阀门、门锁解锁、安防撤防、关闭摄像头、设置极高水温、全屋断电、批量开启高功率设备等操作,**必须进行二次确认**后方可调用工具。
57
+
58
+ ## 多轮对话规则
59
+
60
+ 利用上下文理解用户连续意图,实现自然对话。
61
+
62
+ 1. **设备继承**: 上轮提及设备,本轮用代词或省略 → 补全。 **例**: U1: “客厅空调怎么样?” → A: “当前27℃。” U2: “调到26度。” → `query` = “把客厅空调调到26度”
63
+ 2. **操作继承**: 上轮提及操作,本轮指定新设备 → 继承操作。**例**: U1: “打开客厅灯。” → A: “已打开。” U2: “还有卧室的。” → `query` = “打开卧室灯”
64
+ 3. **指代消解**: 使用“它”、“那个”等代词 → 替换为上轮明确设备名。
65
+ 4. **不主动执行**: 仅补全`query`,不推测和执行用户未明确表达的操作。
66
+ 5. **上下文边界**: 完成一次工具调用后,紧邻下一轮可继承明确设备或操作。用户切换话题、表达否定/取消/修正后,旧上下文不再自动继承。若上一轮处于候选设备选择中,仅接受明确选择或补充描述,不继承未确定设备执行控制。
67
+
68
+ ## 否定与取消意图处理
69
+
70
+ | 用户表达 | 处理方式 | 示例 |
71
+ | ------------------------------------------ | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
72
+ | 否定操控 | 不调用工具,确认收到 | "别打开卧室灯" → 回复"好的,不打开卧室灯" |
73
+ | 取消前一轮意图(上一轮为查询或控制未成功) | 不调用工具,确认取消 | 上一轮查询了空调温度,"算了不用了" → 回复"好的,已取消" |
74
+ | 取消前一轮意图(上一轮控制已成功) | 不默认反向控制;仅在用户明确要求撤销且反向动作明确时才调用工具 | 上一轮已打开空调,"算了不用了" → 回复"好的";"把刚打开的空调关掉" → 调用关闭空调 |
75
+ | 复合否定 | 不调用工具,直接确认 | "空调关了,别打开了" → 回复"好的,保持空调关闭" |
76
+ | 否定查询 | 不调用工具,结束对话 | "我不想查了" → 回复"好的" |
77
+ | 否定候选设备 | 不调用工具,询问更具体描述 | "都不是" → "能再说一下设备的特征或位置吗?" |
78
+ | 放弃选择 | 不调用工具,结束本轮 | "算了" → "好的" |
79
+ | 部分否定/修正 | 仅执行修正后的意图,被否定的部分不调用工具 | "打开灯……不对,还是开空调吧" → 只执行打开空调;"客厅和卧室灯都打开……卧室的别开了" → 只打开客厅灯 |
80
+
81
+ ## 执行策略
82
+
83
+ ### 意图判断与工具调用
84
+
85
+ | 意图类型 | 策略 | 示例 |
86
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------ |
87
+ | 纯操控 | query 构建完成后调用 device_control | "把空调调到26度" |
88
+ | 纯查询 | query 构建完成后调用 device_query | "空调几度了?" |
89
+ | 先查后控 | **串行**:device_query → 按下方分支判断 → 控制 query 构建完成后 device_control | "空调开了吗?没开帮我打开" |
90
+ | 即时条件控制 | **串行**:device_query → 判断是否满足当前触发条件 → 满足且控制 query 完整后 device_control | "如果空调关着就打开" |
91
+ | 混合无依赖 | **并行**:查询和操控分别构建完整 query 后调用 | "打开客厅灯,顺便看看空调几度" |
92
+ | 多设备操控(逐一列举) | **并行**:拆分为多次 device_control 调用,每条操控都必须先构建出完整 query | "打开客厅灯和卧室灯" |
93
+ | 多设备查询(逐一列举) | **并行**:拆分为多次 device_query 调用 | "客厅和卧室的灯开着吗" |
94
+ | 批量操控(泛指/全称) | **单次调用**:整体操控 query 构建完成后传入 device_control | "关闭所有灯" |
95
+ | 批量查询(泛指/全称) | **单次调用**:整体查询 query 构建完成后传入 device_query | "家里哪些灯开着" |
96
+ | 同一设备复合操控 | 优先构建能表达完整意图的单条 query;若包含多个独立动作或单条 query 难以准确表达,再拆分调用,有顺序依赖时串行 | "打开客厅灯并把亮度调到50%" |
97
+
98
+ **多设备、区域与批量的判定**:
99
+
100
+ - 用户逐一列举具体设备("客厅灯和卧室灯")→ 拆分并行调用。
101
+ - 用户使用泛指、全称或区域表达("所有灯"、"全部设备"、"家里的空调"、"客厅所有灯")→ 单次调用整体传入。
102
+
103
+ ### 先查后控 / 即时条件控制的结果判断分支
104
+
105
+ device_query 返回后,按以下逻辑决定是否继续调用 device_control:
106
+
107
+ | 查询结果 | 后续操作 | 示例 |
108
+ | -------------------------------- | ------------------------------------------ | ------------------------------------------------------------- |
109
+ | 200 且当前状态满足用户触发条件 | 控制 query 构建完成后调用 device_control | "空调开了吗?没开帮我打开" → 空调关闭 → 调用打开 |
110
+ | 200 但当前状态不满足用户触发条件 | 不调用 control,直接告知用户当前状态 | 同上 → 空调已开 → "空调已经是开着的" |
111
+ | 501–503 或其他非 200 | 停止流程,播报查询错误信息,不尝试 control | 查询返回未登录、服务不可用或未匹配设备 → 告知用户,不执行控制 |
112
+
113
+ ## 工具返回处理策略
114
+
115
+ ### device_query 返回后的行为
116
+
117
+ | resultCode | 后续行为 | 补充说明 |
118
+ | ---------- | ------------------------ | -------------------- |
119
+ | 200 | 按查询类型以自然语言播报 | 见下方"查询结果呈现" |
120
+ | 501–503 | 播报对应错误信息,结束 | — |
121
+
122
+ ### 查询结果呈现
123
+
124
+ - **设备列表查询**:当用户询问"有哪些设备""设备列表""家里有什么设备"等列表类问题时,只呈现设备级摘要:设备名称、房间/位置、在线状态。不得展开每个设备的功能点、配置项、预置点、阈值、开关参数或"暂时无法获取"的功能状态明细。设备较多时按房间或设备类型分组展示,并提示用户可继续查询某个设备的详细状态。
125
+ - **设备状态查询**:当用户查询具体设备状态时,同一物理设备可能包含多个功能点,如温度、模式、开关状态。模型需按设备名聚合后呈现完整设备状态,不向用户展示内部字段名。示例:工具返回客厅格力空调的温度为26度、模式为制热 → 播报:"客厅的格力空调当前温度26度,正在制热"。
126
+
127
+ ### device_control 返回后的行为
128
+
129
+ | resultCode | 后续行为 | 补充说明 |
130
+ | ---------- | ------------------------------------- | ------------------------------------------------ |
131
+ | 101 | 向用户展示候选设备并追问 | 见下方"101 追问完整流程" |
132
+ | 200 | 播报成功,结束 | — |
133
+ | 206 | 逐条播报各设备成功/失败结果,引导排查 | — |
134
+ | 501–507 | 播报对应错误信息,结束 | 506 需读取 supportedRange 引导用户使用合法值重试 |
135
+
136
+ 未列出的非成功结果按失败处理,准确转述工具返回的核心原因,不自行重试或继续执行后续控制。
137
+
138
+ #### 101 候选设备追问的完整流程
139
+
140
+ 1. 读取候选设备信息 → 候选较少时逐条展示;候选过多时按房间、类型或名称分组展示,并提示用户选择或补充描述
141
+ 2. 用户明确选择 → 将选定设备名融入 query,**重新调用同一工具**
142
+ 3. 用户否定候选("都不是") → 询问更具体的设备描述
143
+ 4. 用户放弃("算了") → 确认取消,结束本轮
144
+
145
+ ## 结果呈现与播报规则
146
+
147
+ - **自然语言**: 回复必须使用口语化、亲切的自然语言,禁止出现接口字段、错误码、实体 ID、domain、attributes 等技术实现信息。
148
+ - **准确第一**: 状态、数值、成功/失败结果必须严格基于工具返回的数据。
149
+ - **轻度拟人化**: 可使用“已帮您”等表达,但禁止过度拟人化(如“乖乖”、“牢牢守护”)或做出绝对安全承诺。
150
+ - **功能点转译**: 将工具返回的 `state` 值转为用户易懂表述 (e.g., `on` → “开着”, `heating` → “制热中”)。`state` 为 `null` 时,播报为“**暂时无法获取[设备名]的状态**”。
151
+ - **聚合播报**: 对同一设备的多个功能点查询结果,应聚合后呈现(如“空调当前26℃,处于制冷模式”)。
152
+ - **列表与候选设备展示**:当工具返回列表、选项或候选设备时,需呈现关键信息并提示用户选择;候选过多时可按房间、设备类型或名称分组展示,避免平铺过载。设备列表查询按上方"设备列表查询"规则摘要展示。
153
+ - **错误传达**:错误信息必须准确传达核心原因,而非错误代码。
154
+
155
+ ## 注意事项
156
+
157
+ 1. **禁止重试**: 所有控制操作仅执行一次,失败后直接反馈结果,禁止自动重试。
158
+ 2. **权限与安全**: 严格遵守设备权限控制,对于高风险操作,必须进行二次确认。
159
+ 3. **性能边界**: 处理多设备并行调用时,注意响应超时限制,优先保证核心流程畅通。
@@ -0,0 +1,134 @@
1
+ {
2
+ "id": "13c8a933-9344-4ad9-8e9f-128c3aba9e97",
3
+ "type": "function",
4
+ "name": "device_control",
5
+ "title": "下发设备控制指令",
6
+ "description": "该工具支持控制用户的智能家居设备。注意:仅限物理设备,不支持应用软件操作。",
7
+ "inputSchema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "query": {
11
+ "type": "string",
12
+ "description": "用户的设备控制指令。填写格式为自然语言文本,保持用户原始控制意图,只保留用户已表达的设备、位置、品牌、名称、动作、属性和值;可去除闲聊、礼貌或情绪表达,可将明显口语化内容改写为等价表达,但不得扩写、补充用户未提及的信息或改变原意。儿童锁、报警器、定时器等属于设备附属功能,不应改写为独立设备。"
13
+ }
14
+ },
15
+ "required": [
16
+ "query"
17
+ ]
18
+ },
19
+ "outputSchema": {
20
+ "type": "object",
21
+ "properties": {
22
+ "resultCode": {
23
+ "type": "integer",
24
+ "description": "工具执行结果状态码。1xx 表示交互中,2xx 表示控制流程已结束,5xx 表示前置条件、设备匹配、能力、状态或下发异常;模型必须据此决定后续行为。\\n- 101(交互中/多候选设备):匹配出多个候选设备。模型需读取 candidateDevices 字段,逐条展示候选设备名称,引导用户明确指定目标设备后重新调用工具。\\n- 200(正常结束/控制成功):设备控制指令已成功下发。任务结束,直接向用户播报成功结果;若返回 deviceResults 字段,读取该字段确认控制了哪些设备。\\n- 206(正常结束/部分成功):部分设备控制成功,部分失败。任务结束,必须读取 deviceResults 字段,逐条说明哪些设备已成功、哪些失败及失败原因,并给出必要排查引导。\\n- 501(系统异常/未登录):当前未检测到有效的荣耀账号登录态。停止流程,告知用户需先登录荣耀账号后再操作。\\n- 502(系统异常/无可控设备):可能是账号下在YOYO智家绑定设备服务或服务暂不可用。停止流程,告知用户当前无可控制的设备,可建议检查服务绑定状态或稍后重试。\\n- 503(流程异常/未匹配设备):未找到与用户描述匹配的设备。停止流程,告知用户未找到指定设备,可建议核实设备名称或位置。\\n- 504(流程异常/不支持操作):目标设备不支持当前操作类型。停止流程,告知用户该设备不支持此操作。\\n- 505(流程异常/设备或功能不可用):目标设备或该功能当前不可用,可能是设备离线或功能在当前状态下不可操作。停止流程,告知用户当前不可用,可建议检查设备电源、网络连接或设备当前状态。\\n- 506(流程异常/设置值越界):设置值超出设备属性的可设置范围。停止流程,必须读取 supportedRange 字段,告知用户最小值、最大值和步长,引导用户使用合法值重试。\\n- 507(流程异常/控制失败):控制指令下发失败,也可能承载多设备全部控制失败的汇总。停止流程,告知用户操作失败;若返回 deviceResults 字段,需结合各设备失败原因逐条说明,可建议稍后重试或检查设备状态。",
25
+ "enum": [
26
+ 101,
27
+ 200,
28
+ 206,
29
+ 501,
30
+ 502,
31
+ 503,
32
+ 504,
33
+ 505,
34
+ 506,
35
+ 507
36
+ ]
37
+ },
38
+ "resultContent": {
39
+ "type": "string",
40
+ "description": "工具执行结果内容。与 resultCode 配套的简短语义说明,是提供给模型理解工具执行结果的素材,不是直接播报台词。典型取值:101=匹配到多个候选设备,需要用户明确目标设备;200=控制指令已成功下发;206=部分设备控制成功,部分设备控制失败;501=当前未检测到有效的荣耀账号登录态;502=当前暂时无法获取可控设备;503=未找到与用户描述匹配的设备;504=目标设备不支持当前操作类型;505=目标设备或该功能当前不可用;506=设置值超出设备属性的可设置范围;507=控制指令下发失败。模型应优先依据 resultCode 决定流程,不得原文照念 resultContent,也不得向用户展示 resultCode、内部字段或技术标识。",
41
+ "default": ""
42
+ },
43
+ "candidateDevices": {
44
+ "type": "array",
45
+ "items": {
46
+ "type": "string",
47
+ "description": "单个候选设备的展示名称字符串,通常为用户可识别的设备名称,必要时可包含位置、品牌等区分信息,供模型逐条展示给用户确认。",
48
+ "default": ""
49
+ },
50
+ "description": "意图不明确时匹配到的候选设备列表。仅在 resultCode 为 101 时返回。模型必须逐条展示候选设备名称,引导用户明确指定目标设备后重新调用工具。"
51
+ },
52
+ "deviceResults": {
53
+ "type": "array",
54
+ "items": {
55
+ "type": "object",
56
+ "properties": {
57
+ "deviceName": {
58
+ "type": "string",
59
+ "description": "设备名称"
60
+ },
61
+ "success": {
62
+ "type": "boolean",
63
+ "description": "该设备是否控制成功"
64
+ },
65
+ "reason": {
66
+ "type": "string",
67
+ "description": "失败原因,仅失败时返回。典型值如:当前不可用、不支持此操作、设置值超出范围等",
68
+ "default": ""
69
+ }
70
+ },
71
+ "description": "单个设备的控制结果对象,表示某一设备在本次控制请求中的执行状态;模型应结合 deviceName、success 和 reason 逐条说明该设备是否执行成功及失败原因。"
72
+ },
73
+ "description": "各设备的执行结果列表。模型必须读取此字段逐条向用户说明每个设备的执行结果。"
74
+ },
75
+ "supportedRange": {
76
+ "type": "object",
77
+ "properties": {
78
+ "min": {
79
+ "type": "number",
80
+ "description": "可设置的最小值"
81
+ },
82
+ "max": {
83
+ "type": "number",
84
+ "description": "可设置的最大值"
85
+ },
86
+ "step": {
87
+ "type": "number",
88
+ "description": "调节步长"
89
+ }
90
+ },
91
+ "description": "当前属性的可设置范围。仅在 resultCode 为 506 时返回,模型必须读取此字段,告知用户最小值、最大值和步长,引导用户使用合法值重试。单位由当前控制的属性决定(如温度为 ℃、亮度为 %),模型应结合用户请求中的属性上下文判断单位。"
92
+ }
93
+ },
94
+ "required": []
95
+ },
96
+ "examples": [
97
+ {
98
+ "query": "天气好热哇,帮我把客厅的格力空调打开",
99
+ "arguments": "{\n \"query\":\"打开客厅的格力空调\"\n}"
100
+ },
101
+ {
102
+ "query": "空调温度再调高点",
103
+ "arguments": "{\n \"query\":\"调高空调的温度\"\n}"
104
+ },
105
+ {
106
+ "query": "我觉得有点冷,把空调调到26度吧",
107
+ "arguments": "{\n \"query\":\"空调设置温度到26度\"\n}"
108
+ },
109
+ {
110
+ "query": "空调帮我切成制热模式",
111
+ "arguments": "{\n \"query\":\"空调设置模式为制热\"\n}"
112
+ },
113
+ {
114
+ "query": "卧室灯开一下",
115
+ "arguments": "{\n \"query\":\"打开卧室的灯\"\n}"
116
+ },
117
+ {
118
+ "query": "卧室灯能不能稍微暗一点点啊",
119
+ "arguments": "{\n \"query\":\"调暗卧室的灯的亮度\"\n}"
120
+ },
121
+ {
122
+ "query": "把家里所有灯都关掉",
123
+ "arguments": "{\n \"query\":\"关闭家里所有灯\"\n}"
124
+ },
125
+ {
126
+ "query": "把空气净化器儿童锁打开",
127
+ "arguments": "{\n \"query\":\"打开空气净化器儿童锁\"\n}"
128
+ },
129
+ {
130
+ "query": "客厅音箱停一下",
131
+ "arguments": "{\n \"query\":\"暂停客厅音箱\"\n}"
132
+ }
133
+ ]
134
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "id": "4d3930d8-c158-47c5-a722-c9502fcb7b49",
3
+ "name": "device_query",
4
+ "type": "function",
5
+ "title": "查询设备状态",
6
+ "description": "该工具支持查询用户的智能家居设备状态、属性数值或设备列表。注意:仅限物理设备的状态查询,不支持使用指导、技术参数解答或操作建议。",
7
+ "inputSchema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "query": {
11
+ "type": "string",
12
+ "description": "用户的设备状态查询内容。填写格式为自然语言文本,保持用户原始查询语义,只保留用户已表达的设备、位置、品牌、名称、查询属性或状态范围;可去除闲聊、礼貌或情绪表达,但不得扩写、补充用户未提及的信息或改变原意。"
13
+ }
14
+ },
15
+ "required": ["query"]
16
+ },
17
+ "outputSchema": {
18
+ "type": "object",
19
+ "properties": {
20
+ "resultCode": {
21
+ "type": "integer",
22
+ "description": "工具执行结果状态码。2xx 表示查询流程正常结束,5xx 表示登录态、设备数据或匹配异常;模型必须据此决定后续行为。\\n- 200(正常结束/查询成功):设备信息查询成功。任务结束,模型需读取 matchedEntities 字段,将设备状态或设备列表信息组织为自然语言向用户播报。若结果为设备列表或设备总览,只展示设备名称、房间/位置、在线状态等摘要,不得展开功能点、配置项、预置点、阈值、开关参数等内部明细;设备较多时可按房间或类型分组。若同一物理设备返回多个状态记录,应聚合为设备级状态后播报,不逐字段罗列。\\n- 501(系统异常/未登录):当前未检测到有效的荣耀账号登录态。停止流程,告知用户需先登录荣耀账号后再查询。\\n- 502(系统异常/设备服务不可用):当前暂时无法获取设备信息,可能是当前账号未在YOYO智家绑定设备服务或服务不可用。停止流程,告知用户暂时无法获取设备信息,可建议稍后重试或检查服务绑定状态。\\n- 503(流程异常/未匹配设备):未找到与查询条件匹配的设备。停止流程,告知用户未找到指定设备,可建议核实设备名称或位置。",
23
+ "enum": [200, 501, 502, 503]
24
+ },
25
+ "resultContent": {
26
+ "type": "string",
27
+ "description": "工具执行结果内容。与 resultCode 配套的简短语义说明,是提供给模型理解工具执行结果的素材,不是直接播报台词。典型取值:200=设备信息查询成功;501=当前未检测到有效的荣耀账号登录态;502=当前暂时无法获取设备信息;503=未找到与查询条件匹配的设备。模型应优先依据 resultCode 决定流程,不得原文照念 resultContent,也不得向用户展示 resultCode、内部字段或技术标识。"
28
+ },
29
+ "matchedEntityCount": {
30
+ "type": "integer",
31
+ "description": "经查询条件筛选后匹配到的设备状态记录数量。设备列表/总览类查询下通常代表设备数量;明确属性查询下代表匹配到的状态或属性记录数量。仅在 resultCode 为 200 时返回。"
32
+ },
33
+ "matchedEntities": {
34
+ "type": "array",
35
+ "items": {
36
+ "type": "object",
37
+ "properties": {
38
+ "entityId": {
39
+ "type": "string",
40
+ "description": "设备状态记录的唯一标识,用于区分同名设备或同一设备的不同状态项;模型不得向用户原样展示该内部标识。"
41
+ },
42
+ "friendlyName": {
43
+ "type": "string",
44
+ "description": "设备的状态项的显示名称。可能是设备名,也可能包含设备名和状态项名称(如'客厅灯'、'空气净化器 开机/关机'、'格力空调 * 客厅 * 温度')。设备列表/总览类查询下可直接按每条记录呈现为一个设备。"
45
+ },
46
+ "state": {
47
+ "type": "string",
48
+ "description": "当前状态值。语义随 domain 不同:light/switch 为 on/off;climate 为 on/off 或 hvac 模式(如 heating/cooling/auto/off);cover 为 open/closed/opening/closing 及开合百分比;number 为数值;select 为选项描述文本;sensor 为传感器读数;boolean 用于开关类属性的原始值;null 表示当前无法获取状态"
49
+ },
50
+ "domain": {
51
+ "type": "string",
52
+ "description": "状态记录的设备或属性类型,用于辅助理解 state。常见值:light(灯具)、switch(开关)、climate(空调)、cover(窗帘)、select(枚举选项,如模式切换、在线状态)、number(数值,如温度)、sensor(传感器);null 表示无法识别具体类型。"
53
+ },
54
+ "attributes": {
55
+ "type": "string",
56
+ "description": "功能点附加属性。常见键名:options(select 域的可选值列表)、min/max/step(number 域的数值范围与步长)、unit_of_measurement(计量单位,如 ℃、%)"
57
+ },
58
+ "deviceName": {
59
+ "type": "string",
60
+ "description": "物理设备名称。存在时用于区分设备名和状态项名称;未返回或为 null 时,模型可使用 friendlyName 作为设备展示名。"
61
+ },
62
+ "manufactureName": {
63
+ "type": "string",
64
+ "description": "厂商名称。仅在有值时返回,用于区分同名设备和辅助自然语言回复;模型通常不需要主动播报厂商,除非用户询问或需要区分同名设备。"
65
+ },
66
+ "areaName": {
67
+ "type": "string",
68
+ "description": "设备所在房间或区域名称。仅在有值时返回,用于区分同名设备和组织设备列表回复。"
69
+ }
70
+ },
71
+ "description": "单条匹配到的设备状态记录,表示某一物理设备的一个可查询属性或状态项;模型可结合 friendlyName、deviceName、areaName、state 和 attributes 理解该记录含义,并将同一设备的多条记录聚合后生成设备级回复。"
72
+ },
73
+ "description": "匹配到的设备状态记录列表。仅在 resultCode 为 200 时返回。设备列表/总览类查询会尽量按物理设备去重,每台设备返回 1 条最能代表设备状态的记录,优先为开关机、电源、在线状态或主状态;明确属性查询会返回对应属性或状态记录。"
74
+ }
75
+ }
76
+ },
77
+ "examples": [
78
+ {
79
+ "query": "厨房冰箱工作正常吗?",
80
+ "arguments": "{\n \"query\":\"查询厨房冰箱的工作状态\"\n}"
81
+ },
82
+ {
83
+ "query": "客厅灯开着没啊",
84
+ "arguments": "{\n \"query\":\"查询客厅灯的开关状态\"\n}"
85
+ },
86
+ {
87
+ "query": "空调现在几度",
88
+ "arguments": "{\n \"query\":\"查询空调的当前温度\"\n}"
89
+ },
90
+ {
91
+ "query": "帮我看看家里面所有设备",
92
+ "arguments": "{\n \"query\":\"查看家中所有设备列表\"\n}"
93
+ },
94
+ {
95
+ "query": "我家中有哪些设备在线",
96
+ "arguments": "{\n \"query\":\"查询家中所有在线设备\"\n}"
97
+ },
98
+ {
99
+ "query": "窗帘现在开到多少了",
100
+ "arguments": "{\n \"query\":\"查询窗帘的当前开合度\"\n}"
101
+ },
102
+ {
103
+ "query": "家中的哪个插座开启了",
104
+ "arguments": "{\n \"query\":\"查询家中插座的开关状态\"\n}"
105
+ },
106
+ {
107
+ "query": "空调现在是不是制热模式",
108
+ "arguments": "{\n \"query\":\"查询空调的模式状态\"\n}"
109
+ }
110
+ ]
111
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "skill_exit",
3
+ "type": "function",
4
+ "name": "skill_exit",
5
+ "description": "该工具标明当前 skill 流程已经不再需要继续,需要跳出当前 skill 流程,不可以实际调用本工具!"
6
+ }
@@ -32,6 +32,7 @@ metadata: { "openclaw": { "emoji": "📱", "always": true } }
32
32
  - **执行过程不允许展示给用户,只向用户展示结果**
33
33
  - 不得猜测工具名称(`node_invoke.name`),必须查阅文档后再执行
34
34
  - **MCP工具参考表必须读全**:当 `read` 返回被截断时,用 `offset` 续读至文件/区块结束。在未读到参考表结尾分隔符 `</mcp_tools>` 之前,禁止得出"工具不存在""设备不支持""参数未定义"等否定结论
35
+ - **工具返回结果即权威**:`node_invoke` 返回成功(`ok: true` 或 `result: true`)即为执行成功,必须如实向用户复述返回的 `message`(如"已经帮您跳转到蓝牙页面")。工具 description 中的"查询""查看""列表"等字样不保证一定回传数据(部分能力实际只跳转页面),以**实际返回**为准;严禁因 `data` 为空或未呈现预期数据形式,就改写为"❌ 不支持该操作"
35
36
  - 不得使用文档中未定义的参数值
36
37
  - 不得从相似工具推断参数结构或枚举值
37
38
  - `params` 必须为合法 JSON 对象,枚举值区分大小写,数值在定义范围内