@honor-claw/yoyo 0.0.1-beta.2 → 0.0.1-beta.21

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.
Files changed (79) hide show
  1. package/index.ts +2 -2
  2. package/openclaw.plugin.json +7 -0
  3. package/package.json +20 -20
  4. package/skills/search/SKILL.md +182 -0
  5. package/skills/search/scripts/search.sh +69 -0
  6. package/skills/yoyo-control/SKILL.md +105 -120
  7. package/skills/yoyo-control/references/alarm-create.md +473 -0
  8. package/skills/yoyo-control/references/app-close.md +183 -0
  9. package/skills/yoyo-control/references/app-open.md +178 -0
  10. package/skills/yoyo-control/references/call-phone.md +250 -0
  11. package/skills/yoyo-control/references/capture-screenshot.md +205 -54
  12. package/skills/yoyo-control/references/contact-search.md +235 -0
  13. package/skills/yoyo-control/references/hotspot.md +208 -0
  14. package/skills/yoyo-control/references/local-search.md +224 -15
  15. package/skills/yoyo-control/references/message-send.md +246 -0
  16. package/skills/yoyo-control/references/mobile-data.md +248 -0
  17. package/skills/yoyo-control/references/no-disturb.md +239 -0
  18. package/skills/yoyo-control/references/quiet-mode.md +228 -0
  19. package/skills/yoyo-control/references/ringing-mode.md +223 -0
  20. package/skills/yoyo-control/references/screen-record.md +220 -0
  21. package/skills/yoyo-control/references/vibration-mode.md +235 -0
  22. package/skills/yoyo-control/references/volume-operate.md +274 -0
  23. package/skills/yoyo-control/scripts/invoke.js +33 -111
  24. package/src/agent/copy-templates.ts +56 -0
  25. package/src/agent/index.ts +3 -0
  26. package/src/agent/templates/AGENTS.md +223 -0
  27. package/src/apis/claw-cloud.ts +70 -23
  28. package/src/apis/honor-auth.ts +20 -10
  29. package/src/apis/types.ts +24 -1
  30. package/src/cloud-channel/channel.ts +245 -58
  31. package/src/cloud-channel/client.ts +87 -12
  32. package/src/cloud-channel/types.ts +30 -0
  33. package/src/commands/env/impl.ts +58 -0
  34. package/src/commands/env/index.ts +1 -0
  35. package/src/commands/index.ts +11 -1
  36. package/src/commands/login/impl.ts +17 -8
  37. package/src/commands/logout/impl.ts +23 -0
  38. package/src/commands/logout/index.ts +1 -53
  39. package/src/commands/status/index.ts +172 -42
  40. package/src/gateway-client/client.deprecated.ts +1 -1
  41. package/src/gateway-client/client.ts +15 -20
  42. package/src/gateway-client/types.ts +2 -2
  43. package/src/honor-auth/browser.ts +12 -15
  44. package/src/honor-auth/callback-server.ts +3 -6
  45. package/src/honor-auth/cloud.ts +65 -12
  46. package/src/honor-auth/config.ts +25 -17
  47. package/src/honor-auth/index.ts +1 -0
  48. package/src/honor-auth/token-manager.ts +24 -14
  49. package/src/modules/claw-configs/config-manager.ts +211 -11
  50. package/src/modules/claw-configs/hosts.ts +48 -0
  51. package/src/modules/claw-configs/index.ts +1 -0
  52. package/src/modules/claw-configs/types.ts +4 -0
  53. package/src/modules/device/device-info.ts +20 -9
  54. package/src/modules/device/providers/linux.ts +128 -0
  55. package/src/modules/device/providers/macos.ts +123 -0
  56. package/src/modules/device/providers/pad.ts +0 -16
  57. package/src/modules/device/registry.ts +12 -3
  58. package/src/modules/login/impl.ts +38 -16
  59. package/src/runtime.ts +44 -0
  60. package/src/schemas.ts +4 -1
  61. package/src/services/connection/impl.ts +89 -9
  62. package/src/services/connection/status-tracker/events.ts +127 -0
  63. package/src/services/connection/status-tracker/index.ts +31 -0
  64. package/src/services/connection/status-tracker/storage.ts +133 -0
  65. package/src/services/connection/status-tracker/tracker.ts +370 -0
  66. package/src/services/connection/status-tracker/types.ts +131 -0
  67. package/src/types.ts +0 -4
  68. package/src/utils/fs-safe.ts +544 -0
  69. package/src/utils/version.ts +29 -0
  70. package/src/utils/ws.ts +21 -0
  71. package/skills/yoyo-control/references/open-app.md +0 -54
  72. package/skills/yoyo-control/references/phone-call.md +0 -217
  73. package/skills/yoyo-control/references/schedule.md +0 -107
  74. package/skills/yoyo-control/references/screen-recorder.md +0 -67
  75. package/skills/yoyo-control/references/search-contact.md +0 -37
  76. package/skills/yoyo-control/references/send-message.md +0 -155
  77. package/skills/yoyo-control/references/volume.md +0 -536
  78. package/skills/yoyo-control/scripts/README.md +0 -103
  79. package/skills/yoyo-control/scripts/volume-up.json +0 -7
@@ -0,0 +1,274 @@
1
+ ---
2
+ name: volume.operate
3
+ description: >
4
+ 设备音量调节与管理工具。提供对设备音量的调节与管理功能,
5
+ 支持音量的设置、调高、调低、开启与关闭,以及当前音量状态的查询;
6
+ 可针对不同应用、不同设备及不同音量类型(如媒体、通话、通知等)进行精细化控制。
7
+ ---
8
+
9
+ # Volume Operate 音量调节与管理
10
+
11
+ ## Tool Command
12
+
13
+ ```bash
14
+ volume.operate
15
+ ```
16
+
17
+ ## 集成工作流
18
+
19
+ ### Step 1: 意图解析与参数组装
20
+
21
+ ```
22
+ ┌─────────────────────────────────────────────────────────────┐
23
+ │ 意图识别与参数提取 │
24
+ │ - 识别操作类型: 设置/查询/打开/关闭/调大/调小/设值 │
25
+ │ - 识别操作对象: 应用名称、设备名称、音量类型 │
26
+ │ - 提取数值信息: 数字、百分比、极值、级别、分数 │
27
+ │ - 特殊处理: "静音" → 关闭,"取消静音" → 打开 │
28
+ └─────────────────────────────────────────────────────────────┘
29
+
30
+ ┌─────────────────────────────────────────────────────────────┐
31
+ │ 消歧与槽位填充 │
32
+ │ - 多设备场景未指定设备时,默认操作当前设备 │
33
+ │ - 未指定音量类型时,默认操作系统主音量 │
34
+ │ - 数值表达需匹配对应的 numberType │
35
+ │ - "调到/设为" + 数值 → actionType 为设值 │
36
+ │ - "调大/调小" + 数值 → actionType 保持调大/调小(相对调整) │
37
+ └─────────────────────────────────────────────────────────────┘
38
+
39
+ ┌─────────────────────────────────────────────────────────────┐
40
+ │ 生成工具调用 │
41
+ │ - 组装 actionType 及可选参数 │
42
+ │ - 生成平台特定的命令格式 │
43
+ └─────────────────────────────────────────────────────────────┘
44
+ ```
45
+
46
+ ### Step 2: 执行调用
47
+
48
+ - 根据操作系统选择对应的命令格式
49
+ - Windows: Cmd 格式(双引号需转义)
50
+ - Linux: Bash 格式(单引号包裹)
51
+
52
+ ## 意图分类与参数映射
53
+
54
+ | 用户意图 | 关键词示例 | actionType | 可选参数 |
55
+ | :------------- | :---------------------------------- | :--------- | :---------------------------------------------------- |
56
+ | **设置音量** | 设置/调整/调节 + 音量 | `设置` | `app`, `device`, `volumeType` |
57
+ | **查询音量** | 查询/查看/当前 + 音量 | `查询` | `device`, `volumeType` |
58
+ | **打开音量** | 打开/开启/恢复/取消静音 + 音量/声音 | `打开` | `device`, `volumeType` |
59
+ | **关闭音量** | 关闭/静音/禁止 + 音量/声音 | `关闭` | `device`, `volumeType`, `time` |
60
+ | **调大音量** | 调大/提高/增大/放大 + 音量 | `调大` | `app`, `device`, `number`, `numberType`, `volumeType` |
61
+ | **调小音量** | 调小/降低/减小/下降 + 音量 | `调小` | `app`, `device`, `number`, `numberType`, `volumeType` |
62
+ | **设定具体值** | 设为/调到/调至 + 具体数值 | `设值` | `app`, `device`, `number`, `numberType`, `volumeType` |
63
+
64
+ ## 参数定义
65
+
66
+ ```json
67
+ {
68
+ "actionType": {
69
+ "type": "string",
70
+ "enum": ["设置", "查询", "打开", "关闭", "调大", "调小", "设值"],
71
+ "description": "音量操作的动作类型,用于明确本次指令的具体音量控制行为。当需要对音量进行开关、调整或设置具体数值时选择对应操作;当获取当前音量状态或大小时使用查询。"
72
+ },
73
+ "app": {
74
+ "type": "string",
75
+ "description": "指定需要进行音量控制的应用名称。当明确要求修改某个具体应用的音量时填写,用于限定音量操作的应用范围。"
76
+ },
77
+ "device": {
78
+ "type": "string",
79
+ "description": "指定执行音量操作的目标设备。当存在多个可控设备,或明确指出具体设备时填写,用于精确定位操作对象。"
80
+ },
81
+ "number": {
82
+ "type": "string",
83
+ "description": "音量调整的具体数值,用于设置或变化音量大小。当 actionType 为设值、调大或调小时,可结合 numberType 一同使用以明确调整幅度。"
84
+ },
85
+ "numberType": {
86
+ "type": "string",
87
+ "enum": ["数字", "极值", "百分比", "级别", "分数"],
88
+ "description": "音量数值的表达类型,用于说明 number 的含义。当采用不同计量方式描述音量大小时填写。"
89
+ },
90
+ "volumeType": {
91
+ "type": "string",
92
+ "enum": [
93
+ "来电",
94
+ "信息",
95
+ "通知",
96
+ "闹钟",
97
+ "音乐",
98
+ "视频",
99
+ "游戏",
100
+ "通话",
101
+ "YOYO助理",
102
+ "铃声",
103
+ "媒体",
104
+ "导航"
105
+ ],
106
+ "description": "需要操作或查询的音量类别,用于区分不同系统或场景音量。当需针对某一具体声音类型进行控制时填写。"
107
+ },
108
+ "time": {
109
+ "type": "string",
110
+ "description": "指定音量操作的执行时间,可用于定时或延时调整音量。当明确要求在某一时间点执行操作时填写。"
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### 参数注意事项
116
+
117
+ 1. **设值与调大/调小的区别**: `设值`为绝对值设定("调到50"),`调大`/`调小`为相对值调整("调大20")
118
+ 2. **numberType 匹配**: `number` 需与 `numberType` 配合使用——"50"对应数字、"50%"对应百分比、"最大/最小"对应极值、"3格/3档"对应级别、"1/3/三分之一"对应分数
119
+ 3. **音量类型缺省**: 未指定 `volumeType` 时,默认操作系统主音量
120
+ 4. **同义词映射**: "静音"→关闭、"取消静音"→打开、"声音设为零"→设值(number=零)
121
+
122
+ ## Query 示例及输出
123
+
124
+ ### 示例 1: 调大音量
125
+
126
+ **用户输入**: "调大播放音量"
127
+
128
+ **工具**: "volume.operate"
129
+
130
+ **JSON 参数**:
131
+
132
+ ```json
133
+ {
134
+ "actionType": "调大"
135
+ }
136
+ ```
137
+
138
+ **Windows (Cmd) 执行命令**:
139
+
140
+ ```bash
141
+ openclaw nodes invoke --node <ID> --command volume.operate --params "{\"actionType\":\"调大\"}"
142
+ ```
143
+
144
+ **Linux (Bash) 执行命令**:
145
+
146
+ ```bash
147
+ openclaw nodes invoke --node <ID> --command volume.operate --params '{"actionType":"调大"}'
148
+ ```
149
+
150
+ ---
151
+
152
+ ### 示例 2: 设定指定设备音量至百分比
153
+
154
+ **用户输入**: "电视音量调小到30%"
155
+
156
+ **工具**: "volume.operate"
157
+
158
+ **JSON 参数**:
159
+
160
+ ```json
161
+ {
162
+ "actionType": "设值",
163
+ "device": "电视",
164
+ "number": "0.3",
165
+ "numberType": "百分比"
166
+ }
167
+ ```
168
+
169
+ **Windows (Cmd) 执行命令**:
170
+
171
+ ```bash
172
+ openclaw nodes invoke --node <ID> --command volume.operate --params "{\"actionType\":\"设值\",\"device\":\"电视\",\"number\":\"0.3\",\"numberType\":\"百分比\"}"
173
+ ```
174
+
175
+ **Linux (Bash) 执行命令**:
176
+
177
+ ```bash
178
+ openclaw nodes invoke --node <ID> --command volume.operate --params '{"actionType":"设值","device":"电视","number":"0.3","numberType":"百分比"}'
179
+ ```
180
+
181
+ ---
182
+
183
+ ### 示例 3: 打开指定设备的音量类型
184
+
185
+ **用户输入**: "打开电视媒体音量"
186
+
187
+ **工具**: "volume.operate"
188
+
189
+ **JSON 参数**:
190
+
191
+ ```json
192
+ {
193
+ "actionType": "打开",
194
+ "device": "电视",
195
+ "volumeType": "媒体"
196
+ }
197
+ ```
198
+
199
+ **Windows (Cmd) 执行命令**:
200
+
201
+ ```bash
202
+ openclaw nodes invoke --node <ID> --command volume.operate --params "{\"actionType\":\"打开\",\"device\":\"电视\",\"volumeType\":\"媒体\"}"
203
+ ```
204
+
205
+ **Linux (Bash) 执行命令**:
206
+
207
+ ```bash
208
+ openclaw nodes invoke --node <ID> --command volume.operate --params '{"actionType":"打开","device":"电视","volumeType":"媒体"}'
209
+ ```
210
+
211
+ ---
212
+
213
+ ### 示例 4: 指定应用与设备精确设值
214
+
215
+ **用户输入**: "将车载导航的提示音减小至40%"
216
+
217
+ **工具**: "volume.operate"
218
+
219
+ **JSON 参数**:
220
+
221
+ ```json
222
+ {
223
+ "actionType": "设值",
224
+ "app": "导航",
225
+ "device": "车载",
226
+ "number": "0.4",
227
+ "numberType": "百分比",
228
+ "volumeType": "其他"
229
+ }
230
+ ```
231
+
232
+ **Windows (Cmd) 执行命令**:
233
+
234
+ ```bash
235
+ openclaw nodes invoke --node <ID> --command volume.operate --params "{\"actionType\":\"设值\",\"app\":\"导航\",\"device\":\"车载\",\"number\":\"0.4\",\"numberType\":\"百分比\",\"volumeType\":\"其他\"}"
236
+ ```
237
+
238
+ **Linux (Bash) 执行命令**:
239
+
240
+ ```bash
241
+ openclaw nodes invoke --node <ID> --command volume.operate --params '{"actionType":"设值","app":"导航","device":"车载","number":"0.4","numberType":"百分比","volumeType":"其他"}'
242
+ ```
243
+
244
+ ---
245
+
246
+ ### 示例 5: 查询指定设备音量类型
247
+
248
+ **用户输入**: "现在的电视通话音量"
249
+
250
+ **工具**: "volume.operate"
251
+
252
+ **JSON 参数**:
253
+
254
+ ```json
255
+ {
256
+ "actionType": "查询",
257
+ "device": "电视",
258
+ "volumeType": "通话"
259
+ }
260
+ ```
261
+
262
+ **Windows (Cmd) 执行命令**:
263
+
264
+ ```bash
265
+ openclaw nodes invoke --node <ID> --command volume.operate --params "{\"actionType\":\"查询\",\"device\":\"电视\",\"volumeType\":\"通话\"}"
266
+ ```
267
+
268
+ **Linux (Bash) 执行命令**:
269
+
270
+ ```bash
271
+ openclaw nodes invoke --node <ID> --command volume.operate --params '{"actionType":"查询","device":"电视","volumeType":"通话"}'
272
+ ```
273
+
274
+ ---
@@ -1,119 +1,41 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Device Control Invoke Script
4
- *
5
- * 封装 openclaw nodes invoke 命令,提供统一的设备控制接口
6
- * 使用配置文件方式避免 Windows PowerShell 对 JSON 参数的引号处理问题
7
- */
8
-
9
- import { exec } from "child_process";
10
- import { readFileSync } from "fs";
11
- import { resolve } from "path";
12
- import { promisify } from "util";
13
-
14
- const execAsync = promisify(exec);
15
-
16
- /**
17
- * 显示使用说明
18
- */
19
- function usage() {
20
- console.error("用法: node invoke.js <config_file> [--debug]");
21
- console.error("");
22
- console.error("参数:");
23
- console.error(" config_file - JSON 配置文件路径");
24
- console.error(" --debug - 启用调试模式");
25
- console.error("");
26
- console.error("配置文件格式:");
27
- console.error("{");
28
- console.error(' "nodeId": "设备ID",');
29
- console.error(' "command": "命令标识",');
30
- console.error(' "params": { ...参数对象 }');
31
- console.error("}");
32
- console.error("");
33
- console.error("示例:");
34
- console.error(" node invoke.js config.json");
35
- console.error(" node invoke.js config.json --debug");
36
- process.exit(2);
37
- }
38
-
39
- /**
40
- * 执行节点命令
41
- */
42
- async function invokeNode(nodeId, command, params, timeout = 15000, debug = false) {
43
- const paramsStr = JSON.stringify(params);
44
- const cmd = `npx openclaw nodes invoke --node ${nodeId} --command ${command} --params "${paramsStr.replace(/"/g, '\\"')}"`;
45
-
46
- if (debug) {
47
- console.log("=== 调试信息 ===");
48
- console.log("执行命令:", cmd);
49
- console.log("设备 ID:", nodeId);
50
- console.log("命令标识:", command);
51
- console.log("参数对象:", JSON.stringify(params, null, 2));
52
- console.log("================");
53
- }
54
-
55
- try {
56
- const { stdout, stderr } = await execAsync(cmd, {
57
- timeout,
58
- env: { ...process.env },
59
- cwd: process.cwd()
60
- });
61
-
62
- if (debug) {
63
- console.log("=== 执行结果 ===");
64
- console.log("标准输出:", stdout.trim());
65
- console.log("错误输出:", stderr.trim());
66
- console.log("================");
67
- }
68
-
69
- return {
70
- success: true,
71
- data: stdout.trim(),
72
- error: stderr.trim() || null
73
- };
74
- } catch (error) {
75
- if (debug) {
76
- console.log("=== 执行失败 ===");
77
- console.log("错误信息:", error.message);
78
- console.log("标准输出:", error.stdout?.trim() || "");
79
- console.log("错误输出:", error.stderr?.trim() || "");
80
- console.log("================");
81
- }
82
-
83
- return {
84
- success: false,
85
- data: error.stdout?.trim() || "",
86
- error: error.stderr?.trim() || error.message
87
- };
88
- }
2
+ import { execSync } from "child_process";
3
+ import { parseArgs } from "util";
4
+
5
+ const { values } = parseArgs({
6
+ options: {
7
+ node: { type: "string", short: "n" },
8
+ command: { type: "string", short: "c" },
9
+ params: { type: "string", short: "p", default: "{}" },
10
+ },
11
+ strict: true,
12
+ allowPositionals: true,
13
+ });
14
+
15
+ if (!values.node || !values.command) {
16
+ console.error("错误: 必须提供 --node 和 --command 参数");
17
+ console.error("用法: node invoke.js --node <nodeId> --command <command> [--params '<json>']");
18
+ process.exit(1);
89
19
  }
90
20
 
91
- // 主程序
92
- const args = process.argv.slice(2);
93
- const debugIndex = args.indexOf("--debug");
94
- const debug = debugIndex !== -1;
95
- if (debug) args.splice(debugIndex, 1);
21
+ const { node, command, params } = values;
22
+ const isWindows = process.platform === "win32";
23
+ const escapedParams = isWindows ? JSON.stringify(JSON.parse(params)).replace(/"/g, '\\"') : params;
24
+ const baseCmd = isWindows ?
25
+ `openclaw nodes invoke --node ${node} --command ${command} --params "${escapedParams}"` :
26
+ `openclaw nodes invoke --node ${node} --command ${command} --params '${escapedParams}'`;
96
27
 
97
- if (args.length === 0 || args[0] === "-h" || args[0] === "--help") {
98
- usage();
99
- }
100
-
101
- const configPath = resolve(args[0]);
28
+ console.log("BashCommand:", baseCmd);
102
29
 
103
30
  try {
104
- const configContent = readFileSync(configPath, "utf-8");
105
- const config = JSON.parse(configContent);
106
- const { nodeId, command, params } = config;
107
-
108
- if (!nodeId || !command) {
109
- console.error("错误: 配置文件缺少必要字段: nodeId command");
110
- process.exit(1);
111
- }
112
-
113
- const result = await invokeNode(nodeId, command, params || {}, 15000, debug);
114
- console.log(JSON.stringify(result, null, 2));
115
- process.exit(result.success ? 0 : 1);
116
- } catch (error) {
117
- console.error(`错误: ${error.message}`);
31
+ // Windows 环境使用 cmd.exe 执行
32
+ const execOptions = {
33
+ encoding: "utf8",
34
+ shell: isWindows ? "cmd.exe" : true,
35
+ };
36
+ const result = execSync(baseCmd, execOptions);
37
+ console.log("Node execute result:", result);
38
+ } catch (e) {
39
+ console.error("Execute error:", JSON.stringify(e));
118
40
  process.exit(1);
119
41
  }
@@ -0,0 +1,56 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "path";
3
+ import { OpenClawPluginApi } from "openclaw/plugin-sdk";
4
+ import { safeWriteFile, SafeFsError, type WriteMode } from "../utils/fs-safe.js";
5
+
6
+ type TemplateEntry = {
7
+ file: string;
8
+ mode: WriteMode;
9
+ };
10
+
11
+ const TEMPLATE_FILE_LIST: TemplateEntry[] = [
12
+ { file: "AGENTS.md", mode: "overwrite" },
13
+ ];
14
+
15
+ function resolveWorkspaceDir(api: OpenClawPluginApi): string {
16
+ const configuredWorkspace = api.config.agents?.defaults?.workspace?.trim();
17
+ if (configuredWorkspace) {
18
+ return api.resolvePath(configuredWorkspace);
19
+ }
20
+ return api.resolvePath("~/.openclaw/workspace");
21
+ }
22
+
23
+ export async function copyTemplateToWorkspace(api: OpenClawPluginApi): Promise<void> {
24
+ const pluginDir = path.dirname(api.source);
25
+ const templateDir = path.join(pluginDir, "src", "agent", "templates");
26
+ const workspaceDir = resolveWorkspaceDir(api);
27
+
28
+ for (const entry of TEMPLATE_FILE_LIST) {
29
+ const sourcePath = path.join(templateDir, entry.file);
30
+
31
+ try {
32
+ const content = await fs.readFile(sourcePath, "utf-8");
33
+
34
+ await safeWriteFile({
35
+ rootDir: workspaceDir,
36
+ relativePath: entry.file,
37
+ data: content,
38
+ mode: entry.mode,
39
+ mkdir: true,
40
+ });
41
+ api.logger.info(`Successfully wrote ${entry.file} to workspace (${entry.mode} mode)`);
42
+ } catch (error) {
43
+ if (error instanceof SafeFsError) {
44
+ if (error.code === "not-found") {
45
+ api.logger.warn(`Source file does not exist: ${sourcePath}`);
46
+ continue;
47
+ }
48
+ api.logger.error(`Failed to write ${entry.file}: ${error.message}`);
49
+ } else {
50
+ api.logger.error(
51
+ `Failed to write ${entry.file}: ${error instanceof Error ? error.message : String(error)}`
52
+ );
53
+ }
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,3 @@
1
+ import { copyTemplateToWorkspace } from "./copy-templates.js";
2
+
3
+ export { copyTemplateToWorkspace };