hyperclaw 4.0.1 → 4.0.2

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 (148) hide show
  1. package/README.md +7 -4
  2. package/dist/a2ui-protocol-CT_jDEU9.js +75 -0
  3. package/dist/agents-routing-683Q2JGp.js +129 -0
  4. package/dist/agents-routing-BpZBswBH.js +4 -0
  5. package/dist/api-keys-guide-Dq5Obbp4.js +149 -0
  6. package/dist/audit-BYxPlnTQ.js +248 -0
  7. package/dist/bounty-tools-C6LyzxM-.js +211 -0
  8. package/dist/browser-tools-CQBSbIuO.js +5 -0
  9. package/dist/browser-tools-YQmwRLLM.js +179 -0
  10. package/dist/claw-tasks-BRLUvFRD.js +80 -0
  11. package/dist/connector-3HnyH8fn.js +167 -0
  12. package/dist/connector-6PMZo5Ky.js +189 -0
  13. package/dist/connector-B6eoF3DD.js +181 -0
  14. package/dist/connector-B9tLG8UZ.js +196 -0
  15. package/dist/connector-BOlqjXWP.js +182 -0
  16. package/dist/connector-BP8zsbP8.js +189 -0
  17. package/dist/connector-BPoSevxp.js +286 -0
  18. package/dist/connector-BRHj773i.js +163 -0
  19. package/dist/connector-BToxU-jV.js +267 -0
  20. package/dist/connector-BliDVsJQ.js +239 -0
  21. package/dist/connector-Bv6s9oP7.js +88 -0
  22. package/dist/connector-By5wWGTR.js +343 -0
  23. package/dist/connector-C1BaFFgN.js +213 -0
  24. package/dist/connector-CRRWY5Wv.js +167 -0
  25. package/dist/connector-CXPQVGyI.js +85 -0
  26. package/dist/connector-Cdk1CXKi.js +194 -0
  27. package/dist/connector-CwlgFgjx.js +181 -0
  28. package/dist/connector-DFchk6l7.js +178 -0
  29. package/dist/connector-DKw7tRAy.js +192 -0
  30. package/dist/connector-DRv1ahC_.js +2 -2
  31. package/dist/connector-DU63KW94.js +165 -0
  32. package/dist/connector-Dbvb1Cj9.js +280 -0
  33. package/dist/connector-DcZdQcgR.js +173 -0
  34. package/dist/connector-DxKL8VvZ.js +182 -0
  35. package/dist/connector-T_YdZtzv.js +162 -0
  36. package/dist/connector-i4gOS9xL.js +154 -0
  37. package/dist/connector-rHXE1ZD2.js +167 -0
  38. package/dist/connector-wdUXChwa.js +172 -0
  39. package/dist/cost-tracker-pVE15Yq4.js +103 -0
  40. package/dist/credentials-store-BvnMPJwi.js +4 -0
  41. package/dist/credentials-store-sb-TRLwR.js +77 -0
  42. package/dist/cron-tasks-BvDFNyiE.js +82 -0
  43. package/dist/delivery-D5Z98EVq.js +95 -0
  44. package/dist/delivery-DCOXhXEO.js +5 -0
  45. package/dist/destructive-gate-m-dWqUFg.js +101 -0
  46. package/dist/developer-keys-JaJK3T27.js +127 -0
  47. package/dist/developer-keys-kyqmtWK3.js +8 -0
  48. package/dist/doctor-3oi89QIc.js +175 -0
  49. package/dist/doctor-Cf1XSfp9.js +4 -0
  50. package/dist/engine-B4eMiTgl.js +7 -0
  51. package/dist/engine-B8M7dYul.js +7 -0
  52. package/dist/engine-BhT-1M9W.js +256 -0
  53. package/dist/engine-D49jnSd_.js +256 -0
  54. package/dist/env-resolve-DWOQ45jG.js +9 -0
  55. package/dist/env-resolve-szSWl0UF.js +94 -0
  56. package/dist/extraction-tools-D3qDFBJ1.js +91 -0
  57. package/dist/extraction-tools-DLr_AEwq.js +5 -0
  58. package/dist/form_data-B_hIUrxU.js +8657 -0
  59. package/dist/gmail-watch-setup-Czt8rXaX.js +40 -0
  60. package/dist/heartbeat-engine-CRqfPcFM.js +83 -0
  61. package/dist/hub-DTsqe5Bt.js +6 -0
  62. package/dist/hub-FrPTA33j.js +515 -0
  63. package/dist/hyperclawbot-D9KCtc4P.js +480 -0
  64. package/dist/hyperclawbot-Dw27pJo4.js +480 -0
  65. package/dist/inference-CTWJeX9Q.js +922 -0
  66. package/dist/inference-ix607p7k.js +6 -0
  67. package/dist/knowledge-graph-DqA-Fztl.js +131 -0
  68. package/dist/loader-CISCqBto.js +400 -0
  69. package/dist/loader-CYMQ8VOS.js +4 -0
  70. package/dist/logger-8tEtAd3y.js +83 -0
  71. package/dist/manager-CPjeRe-6.js +4 -0
  72. package/dist/manager-Cwzj7w5R.js +105 -0
  73. package/dist/manager-DLmZI-9R.js +6 -0
  74. package/dist/manager-DSGhn5i3.js +117 -0
  75. package/dist/manager-DgyF52mg.js +218 -0
  76. package/dist/manager-Dm8nrMFx.js +40 -0
  77. package/dist/mcp-B_9Ber63.js +139 -0
  78. package/dist/mcp-loader-DSM5UiFG.js +94 -0
  79. package/dist/mcp-loader-j5ZLLw5O.js +94 -0
  80. package/dist/memory-BI1kPkAN.js +4 -0
  81. package/dist/memory-BVFGkxxK.js +270 -0
  82. package/dist/memory-auto-Bc7euou4.js +306 -0
  83. package/dist/memory-auto-DPfbkMVt.js +5 -0
  84. package/dist/memory-integration-DZExqWr4.js +91 -0
  85. package/dist/moltbook-B6ZeGN5_.js +81 -0
  86. package/dist/node-pwL6O_KX.js +222 -0
  87. package/dist/nodes-registry-CsPm_-CJ.js +52 -0
  88. package/dist/oauth-flow-CpWlgvNB.js +150 -0
  89. package/dist/oauth-provider-BZb6qOw5.js +110 -0
  90. package/dist/observability-B43YvNQV.js +89 -0
  91. package/dist/onboard-Bd_wsYdi.js +4086 -0
  92. package/dist/onboard-CAN7x3me.js +3026 -0
  93. package/dist/onboard-DnegOHMh.js +4 -4
  94. package/dist/onboard-RYtDlYBw.js +9 -0
  95. package/dist/onboard-aTwlQs-4.js +9 -0
  96. package/dist/orchestrator-BSp2M5EU.js +189 -0
  97. package/dist/orchestrator-C7ko5tWa.js +6 -0
  98. package/dist/orchestrator-DfPkIx2Z.js +6 -0
  99. package/dist/orchestrator-NJQsmiBE.js +189 -0
  100. package/dist/pairing-DU0_J28n.js +87 -0
  101. package/dist/pairing-DWllbSbO.js +4 -0
  102. package/dist/pc-access-Ly-uA8mn.js +8 -0
  103. package/dist/pc-access-NxBvTrRj.js +819 -0
  104. package/dist/pending-approval-DIHvwwWS.js +22 -0
  105. package/dist/puppeteer-2o3QOwAy.js +2 -2
  106. package/dist/puppeteer-BYTMp3BI.js +2 -2
  107. package/dist/puppeteer-DQ45qwWk.js +2 -2
  108. package/dist/reminders-store-D79qdfN0.js +58 -0
  109. package/dist/renderer-pqlDRKbH.js +225 -0
  110. package/dist/rules-BooT_qFP.js +103 -0
  111. package/dist/run-main.js +289 -1031
  112. package/dist/runner-D1rjuMTJ.js +810 -0
  113. package/dist/sdk/index.js +2 -2
  114. package/dist/sdk/index.mjs +2 -2
  115. package/dist/security-C-5URby1.js +73 -0
  116. package/dist/security-_xve79aq.js +4 -0
  117. package/dist/server-0kgyELx4.js +1047 -0
  118. package/dist/server-BIuTobTC.js +4 -0
  119. package/dist/server-BRlCEjyT.js +1047 -0
  120. package/dist/server-CCI1hv45.js +2 -2
  121. package/dist/server-DU9POoWc.js +4 -0
  122. package/dist/session-store-CujxByI6.js +113 -0
  123. package/dist/session-store-qpJUg2M1.js +5 -0
  124. package/dist/sessions-tools-CB2qbwIk.js +5 -0
  125. package/dist/sessions-tools-DHMaTZIs.js +95 -0
  126. package/dist/skill-loader-BkceKkIg.js +7 -0
  127. package/dist/skill-loader-DhgIwK4J.js +159 -0
  128. package/dist/skill-runtime--LqxWrp5.js +102 -0
  129. package/dist/skill-runtime-C5l0Tgt-.js +5 -0
  130. package/dist/skill-runtime-DsXK_HYG.js +102 -0
  131. package/dist/skill-runtime-IVTiqrMR.js +5 -0
  132. package/dist/src-BEVLgaF1.js +63 -0
  133. package/dist/src-Bgu_OxTQ.js +458 -0
  134. package/dist/src-Bq-oKt7Z.js +458 -0
  135. package/dist/src-DWCUhnD4.js +20 -0
  136. package/dist/src-cfRTjFef.js +63 -0
  137. package/dist/sub-agent-tools-BD9DF8_g.js +39 -0
  138. package/dist/sub-agent-tools-V7b3T9_s.js +39 -0
  139. package/dist/tool-policy-DNvNRnve.js +189 -0
  140. package/dist/tts-elevenlabs-BUOGKL-k.js +61 -0
  141. package/dist/update-check-BD4qH7Am.js +81 -0
  142. package/dist/vision-DRq-f-Dj.js +121 -0
  143. package/dist/vision-tools-CFZEpQKm.js +5 -0
  144. package/dist/vision-tools-CQnBI9aa.js +51 -0
  145. package/dist/voice-transcription-CgWq54hn.js +138 -0
  146. package/dist/website-watch-tools-Bk_TnwuE.js +5 -0
  147. package/dist/website-watch-tools-DraMPxdl.js +139 -0
  148. package/package.json +1 -1
@@ -0,0 +1,819 @@
1
+ const require_chunk = require('./chunk-jS-bbMI5.js');
2
+ const require_paths = require('./paths-AIyBxIzm.js');
3
+ const require_src = require('./src-DWCUhnD4.js');
4
+ const fs_extra = require_chunk.__toESM(require("fs-extra"));
5
+ const path = require_chunk.__toESM(require("path"));
6
+ const os = require_chunk.__toESM(require("os"));
7
+ const child_process = require_chunk.__toESM(require("child_process"));
8
+ const util = require_chunk.__toESM(require("util"));
9
+
10
+ //#region packages/core/src/agent/pc-access.ts
11
+ function getLogFile() {
12
+ return path.default.join(require_paths.getHyperClawDir(), "logs", "pc-access.log");
13
+ }
14
+ async function logAction(tool, input, result) {
15
+ try {
16
+ const LOG_FILE = getLogFile();
17
+ await fs_extra.default.ensureDir(path.default.dirname(LOG_FILE));
18
+ const entry = JSON.stringify({
19
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
20
+ tool,
21
+ input,
22
+ result: result.slice(0, 500)
23
+ }) + "\n";
24
+ await fs_extra.default.appendFile(LOG_FILE, entry);
25
+ } catch {}
26
+ }
27
+ function getPCAccessTools(opts) {
28
+ const dockerSandbox = opts?.dockerSandbox ?? false;
29
+ return [
30
+ {
31
+ name: "run_shell",
32
+ description: "Run ANY shell command on the user's computer. Can run bash scripts, python, node, git, brew, apt, etc. Returns stdout+stderr. Use this for tasks like: install software, run scripts, check system status, manipulate files via CLI.",
33
+ input_schema: {
34
+ type: "object",
35
+ properties: {
36
+ command: {
37
+ type: "string",
38
+ description: "Shell command to run. Examples: \"ls -la ~/Desktop\", \"python3 script.py\", \"git status\", \"brew install jq\""
39
+ },
40
+ cwd: {
41
+ type: "string",
42
+ description: "Working directory (optional, default: home dir)"
43
+ },
44
+ timeout: {
45
+ type: "string",
46
+ description: "Timeout in seconds (optional, default: 30)"
47
+ }
48
+ },
49
+ required: ["command"]
50
+ },
51
+ handler: async (input) => {
52
+ const cmd = input.command;
53
+ const cwd = input.cwd || os.default.homedir();
54
+ const timeout = parseInt(input.timeout || "30") * 1e3;
55
+ let result = "";
56
+ if (dockerSandbox) {
57
+ const scriptPath = path.default.join(os.default.tmpdir(), `hyperclaw-run-${Date.now()}.sh`);
58
+ try {
59
+ const absCwd = path.default.resolve(cwd.replace(/^~/, os.default.homedir()));
60
+ await fs_extra.default.writeFile(scriptPath, `#!/bin/sh\n${cmd}\n`, { mode: 448 });
61
+ const dockerCmd = `docker run --rm -v "${absCwd}:/workspace" -v "${scriptPath}:/script.sh" -w /workspace alpine sh /script.sh`;
62
+ const { stdout, stderr } = await execAsync(dockerCmd, {
63
+ timeout: Math.min(timeout, 6e4),
64
+ maxBuffer: 10 * 1024 * 1024
65
+ });
66
+ result = (stdout + stderr).trim().slice(0, 8e3) || "(no output)";
67
+ } catch (e) {
68
+ if (e.message?.includes("Cannot connect to the Docker daemon")) result = "Error: Docker not running. Start Docker or disable tools.dockerSandbox.";
69
+ else result = `Exit code ${e.code || 1}:\n${(e.stdout || "") + (e.stderr || e.message || "")}`.trim().slice(0, 8e3);
70
+ } finally {
71
+ await fs_extra.default.remove(scriptPath).catch(() => {});
72
+ }
73
+ } else try {
74
+ const { stdout, stderr } = await execAsync(cmd, {
75
+ cwd,
76
+ timeout,
77
+ env: {
78
+ ...process.env,
79
+ TERM: "xterm-256color"
80
+ },
81
+ maxBuffer: 10 * 1024 * 1024
82
+ });
83
+ result = (stdout + stderr).trim().slice(0, 8e3) || "(no output)";
84
+ } catch (e) {
85
+ result = `Exit code ${e.code || 1}:\n${(e.stdout || "") + (e.stderr || e.message || "")}`.trim().slice(0, 8e3);
86
+ }
87
+ await logAction("run_shell", {
88
+ command: cmd,
89
+ cwd,
90
+ dockerSandbox
91
+ }, result);
92
+ return result;
93
+ }
94
+ },
95
+ {
96
+ name: "read_file",
97
+ description: "Read the contents of any file on the computer. Supports text files, code, config files, etc.",
98
+ input_schema: {
99
+ type: "object",
100
+ properties: {
101
+ path: {
102
+ type: "string",
103
+ description: "Absolute or ~ path to file. E.g. ~/Documents/notes.txt or /etc/hosts"
104
+ },
105
+ lines: {
106
+ type: "string",
107
+ description: "Max lines to return (optional, default: 500)"
108
+ }
109
+ },
110
+ required: ["path"]
111
+ },
112
+ handler: async (input) => {
113
+ const filePath = input.path.replace(/^~/, os.default.homedir());
114
+ const maxLines = parseInt(input.lines || "500");
115
+ try {
116
+ const stat = await fs_extra.default.stat(filePath);
117
+ if (stat.isDirectory()) {
118
+ const entries = await fs_extra.default.readdir(filePath);
119
+ return `Directory listing:\n${entries.join("\n")}`;
120
+ }
121
+ const content = await fs_extra.default.readFile(filePath, "utf8");
122
+ const lines = content.split("\n");
123
+ const truncated = lines.slice(0, maxLines).join("\n");
124
+ const suffix = lines.length > maxLines ? `\n\n... (${lines.length - maxLines} more lines)` : "";
125
+ const result = truncated + suffix;
126
+ await logAction("read_file", { path: filePath }, `${lines.length} lines`);
127
+ return result;
128
+ } catch (e) {
129
+ return `Error: ${e.message}`;
130
+ }
131
+ }
132
+ },
133
+ {
134
+ name: "write_file",
135
+ description: "Write content to a file. Creates the file and any missing parent directories. Can overwrite existing files.",
136
+ input_schema: {
137
+ type: "object",
138
+ properties: {
139
+ path: {
140
+ type: "string",
141
+ description: "Path to file. E.g. ~/Desktop/script.py or /tmp/test.txt"
142
+ },
143
+ content: {
144
+ type: "string",
145
+ description: "Content to write to the file"
146
+ },
147
+ append: {
148
+ type: "string",
149
+ description: "\"true\" to append instead of overwrite (optional)"
150
+ }
151
+ },
152
+ required: ["path", "content"]
153
+ },
154
+ handler: async (input) => {
155
+ const filePath = input.path.replace(/^~/, os.default.homedir());
156
+ const content = input.content;
157
+ const append = input.append === "true";
158
+ try {
159
+ await fs_extra.default.ensureDir(path.default.dirname(filePath));
160
+ if (append) await fs_extra.default.appendFile(filePath, content);
161
+ else await fs_extra.default.writeFile(filePath, content, "utf8");
162
+ const result = `${append ? "Appended" : "Written"} ${content.length} chars to ${filePath}`;
163
+ await logAction("write_file", {
164
+ path: filePath,
165
+ append
166
+ }, result);
167
+ return result;
168
+ } catch (e) {
169
+ return `Error: ${e.message}`;
170
+ }
171
+ }
172
+ },
173
+ {
174
+ name: "edit_file",
175
+ description: "Search and replace text in a file. Useful for editing code or config.",
176
+ input_schema: {
177
+ type: "object",
178
+ properties: {
179
+ path: {
180
+ type: "string",
181
+ description: "Path to file. E.g. ~/project/config.json"
182
+ },
183
+ oldString: {
184
+ type: "string",
185
+ description: "Exact string to find"
186
+ },
187
+ newString: {
188
+ type: "string",
189
+ description: "Replacement string"
190
+ },
191
+ replaceAll: {
192
+ type: "string",
193
+ description: "\"true\" to replace all occurrences"
194
+ }
195
+ },
196
+ required: [
197
+ "path",
198
+ "oldString",
199
+ "newString"
200
+ ]
201
+ },
202
+ handler: async (input) => {
203
+ const filePath = input.path.replace(/^~/, os.default.homedir());
204
+ const oldStr = input.oldString;
205
+ const newStr = input.newString;
206
+ const replaceAll = input.replaceAll === "true";
207
+ try {
208
+ let content = await fs_extra.default.readFile(filePath, "utf8");
209
+ let count = 0;
210
+ if (replaceAll) {
211
+ const parts = content.split(oldStr);
212
+ count = parts.length - 1;
213
+ if (count === 0) return `Pattern not found in ${filePath}`;
214
+ content = parts.join(newStr);
215
+ } else {
216
+ const idx = content.indexOf(oldStr);
217
+ if (idx === -1) return `Pattern not found in ${filePath}`;
218
+ content = content.slice(0, idx) + newStr + content.slice(idx + oldStr.length);
219
+ count = 1;
220
+ }
221
+ await fs_extra.default.writeFile(filePath, content, "utf8");
222
+ const result = `Edited ${filePath}: ${count} replacement(s)`;
223
+ await logAction("edit_file", {
224
+ path: filePath,
225
+ count
226
+ }, result);
227
+ return result;
228
+ } catch (e) {
229
+ return `Error: ${e.message}`;
230
+ }
231
+ }
232
+ },
233
+ {
234
+ name: "list_directory",
235
+ description: "List files and folders in a directory with details (size, date, permissions).",
236
+ input_schema: {
237
+ type: "object",
238
+ properties: {
239
+ path: {
240
+ type: "string",
241
+ description: "Directory path. E.g. ~/Desktop or /var/log"
242
+ },
243
+ hidden: {
244
+ type: "string",
245
+ description: "\"true\" to show hidden files (optional)"
246
+ }
247
+ },
248
+ required: ["path"]
249
+ },
250
+ handler: async (input) => {
251
+ const dirPath = input.path.replace(/^~/, os.default.homedir());
252
+ const showHidden = input.hidden === "true";
253
+ try {
254
+ const entries = await fs_extra.default.readdir(dirPath, { withFileTypes: true });
255
+ const filtered = showHidden ? entries : entries.filter((e) => !e.name.startsWith("."));
256
+ const lines = await Promise.all(filtered.map(async (e) => {
257
+ try {
258
+ const stat = await fs_extra.default.stat(path.default.join(dirPath, e.name));
259
+ const size = e.isDirectory() ? "<dir>" : formatBytes(stat.size);
260
+ const date = stat.mtime.toISOString().slice(0, 10);
261
+ const type = e.isDirectory() ? "📁" : "📄";
262
+ return `${type} ${e.name.padEnd(40)} ${size.padStart(10)} ${date}`;
263
+ } catch {
264
+ return ` ${e.name}`;
265
+ }
266
+ }));
267
+ return `${dirPath} (${filtered.length} items):\n\n${lines.join("\n")}`;
268
+ } catch (e) {
269
+ return `Error: ${e.message}`;
270
+ }
271
+ }
272
+ },
273
+ {
274
+ name: "delete_file",
275
+ description: "Delete a file or empty directory.",
276
+ input_schema: {
277
+ type: "object",
278
+ properties: {
279
+ path: {
280
+ type: "string",
281
+ description: "Path to file or directory to delete"
282
+ },
283
+ recursive: {
284
+ type: "string",
285
+ description: "\"true\" to delete non-empty directories recursively (careful!)"
286
+ }
287
+ },
288
+ required: ["path"]
289
+ },
290
+ handler: async (input) => {
291
+ const filePath = input.path.replace(/^~/, os.default.homedir());
292
+ const recursive = input.recursive === "true";
293
+ try {
294
+ if (recursive) await fs_extra.default.remove(filePath);
295
+ else await fs_extra.default.unlink(filePath);
296
+ const result = `Deleted: ${filePath}`;
297
+ await logAction("delete_file", {
298
+ path: filePath,
299
+ recursive
300
+ }, result);
301
+ return result;
302
+ } catch (e) {
303
+ return `Error: ${e.message}`;
304
+ }
305
+ }
306
+ },
307
+ {
308
+ name: "kill_process",
309
+ description: "Kill a process by PID. Use system_info with \"processes\" to find PIDs.",
310
+ input_schema: {
311
+ type: "object",
312
+ properties: {
313
+ pid: {
314
+ type: "string",
315
+ description: "Process ID to kill"
316
+ },
317
+ signal: {
318
+ type: "string",
319
+ description: "Signal: SIGTERM (default) or SIGKILL"
320
+ }
321
+ },
322
+ required: ["pid"]
323
+ },
324
+ handler: async (input) => {
325
+ const pid = parseInt(input.pid, 10);
326
+ const sig = input.signal || "SIGTERM";
327
+ if (isNaN(pid) || pid < 1) return "Invalid PID.";
328
+ try {
329
+ process.kill(pid, sig);
330
+ const result = `Sent ${sig} to PID ${pid}`;
331
+ await logAction("kill_process", {
332
+ pid,
333
+ sig
334
+ }, result);
335
+ return result;
336
+ } catch (e) {
337
+ if (e.code === "ESRCH") return `Process ${pid} not found.`;
338
+ return `Error: ${e.message}`;
339
+ }
340
+ }
341
+ },
342
+ {
343
+ name: "system_info",
344
+ description: "Get system information: OS, CPU, memory, disk usage, running processes, network.",
345
+ input_schema: {
346
+ type: "object",
347
+ properties: { what: {
348
+ type: "string",
349
+ description: "What to check: \"overview\", \"processes\", \"disk\", \"network\", \"memory\"",
350
+ enum: [
351
+ "overview",
352
+ "processes",
353
+ "disk",
354
+ "network",
355
+ "memory"
356
+ ]
357
+ } },
358
+ required: ["what"]
359
+ },
360
+ handler: async (input) => {
361
+ const what = input.what;
362
+ const cmds = {
363
+ overview: `uname -a && echo "---" && uptime && echo "---" && whoami && echo "---" && df -h / | tail -1`,
364
+ processes: process.platform === "darwin" ? "ps aux | head -20" : "ps aux --sort=-%cpu | head -20",
365
+ disk: "df -h",
366
+ network: process.platform === "darwin" ? "ifconfig | grep -E \"inet |flags\"" : "ip addr show | grep -E \"inet |state\"",
367
+ memory: process.platform === "darwin" ? "vm_stat && echo \"---\" && sysctl hw.memsize" : "free -h && echo \"---\" && cat /proc/meminfo | head -10"
368
+ };
369
+ const cmd = cmds[what] || cmds.overview;
370
+ try {
371
+ const { stdout, stderr } = await execAsync(cmd, { timeout: 1e4 });
372
+ return (stdout + stderr).trim().slice(0, 4e3);
373
+ } catch (e) {
374
+ return `Error: ${e.message}`;
375
+ }
376
+ }
377
+ },
378
+ {
379
+ name: "open",
380
+ description: "Open a file, folder, URL, or application on the user's computer.",
381
+ input_schema: {
382
+ type: "object",
383
+ properties: { target: {
384
+ type: "string",
385
+ description: "What to open: URL (https://...), file path, app name (macOS: \"Safari\", Linux: \"firefox\"), or folder path"
386
+ } },
387
+ required: ["target"]
388
+ },
389
+ handler: async (input) => {
390
+ const target = input.target;
391
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
392
+ try {
393
+ await execAsync(`${openCmd} "${target.replace(/"/g, "\\\"")}"`, { timeout: 5e3 });
394
+ const result = `Opened: ${target}`;
395
+ await logAction("open", { target }, result);
396
+ return result;
397
+ } catch (e) {
398
+ return `Error opening ${target}: ${e.message}`;
399
+ }
400
+ }
401
+ },
402
+ {
403
+ name: "clipboard",
404
+ description: "Read from or write to the system clipboard.",
405
+ input_schema: {
406
+ type: "object",
407
+ properties: {
408
+ action: {
409
+ type: "string",
410
+ description: "\"read\" to get clipboard content, \"write\" to set it",
411
+ enum: ["read", "write"]
412
+ },
413
+ content: {
414
+ type: "string",
415
+ description: "Content to write (only for action=write)"
416
+ }
417
+ },
418
+ required: ["action"]
419
+ },
420
+ handler: async (input) => {
421
+ const action = input.action;
422
+ if (action === "read") {
423
+ const cmd = process.platform === "darwin" ? "pbpaste" : process.platform === "linux" ? "xclip -selection clipboard -o" : "powershell Get-Clipboard";
424
+ try {
425
+ const { stdout } = await execAsync(cmd, { timeout: 5e3 });
426
+ return stdout.trim().slice(0, 4e3) || "(empty clipboard)";
427
+ } catch {
428
+ return "Error: clipboard not available (try installing xclip on Linux)";
429
+ }
430
+ }
431
+ if (action === "write" && input.content) {
432
+ const content = input.content;
433
+ const cmd = process.platform === "darwin" ? `echo "${content.replace(/"/g, "\\\"")}" | pbcopy` : process.platform === "linux" ? `echo "${content.replace(/"/g, "\\\"")}" | xclip -selection clipboard` : `powershell Set-Clipboard "${content.replace(/"/g, "\\\"")}"`;
434
+ try {
435
+ await execAsync(cmd, { timeout: 5e3 });
436
+ return `Copied to clipboard: ${content.slice(0, 100)}${content.length > 100 ? "..." : ""}`;
437
+ } catch {
438
+ return "Error: clipboard write failed";
439
+ }
440
+ }
441
+ return "Error: invalid action";
442
+ }
443
+ },
444
+ {
445
+ name: "search_files",
446
+ description: "Search for files by name or content on the computer.",
447
+ input_schema: {
448
+ type: "object",
449
+ properties: {
450
+ query: {
451
+ type: "string",
452
+ description: "Search query (filename or text content)"
453
+ },
454
+ dir: {
455
+ type: "string",
456
+ description: "Directory to search in (optional, default: home dir)"
457
+ },
458
+ type: {
459
+ type: "string",
460
+ description: "\"name\" to search by filename, \"content\" to search inside files",
461
+ enum: ["name", "content"]
462
+ }
463
+ },
464
+ required: ["query", "type"]
465
+ },
466
+ handler: async (input) => {
467
+ const query = input.query;
468
+ const dir = (input.dir || os.default.homedir()).replace(/^~/, os.default.homedir());
469
+ const type = input.type;
470
+ try {
471
+ let cmd;
472
+ if (type === "name") cmd = `find "${dir}" -name "*${query}*" -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -50`;
473
+ else cmd = `grep -rl "${query}" "${dir}" --include="*.ts" --include="*.js" --include="*.py" --include="*.txt" --include="*.md" --exclude-dir=node_modules --exclude-dir=.git 2>/dev/null | head -30`;
474
+ const { stdout } = await execAsync(cmd, { timeout: 15e3 });
475
+ return stdout.trim() || `No results for "${query}" in ${dir}`;
476
+ } catch (e) {
477
+ return `Error: ${e.message}`;
478
+ }
479
+ }
480
+ },
481
+ {
482
+ name: "screenshot",
483
+ description: "Take a screenshot of the screen and save it to a file.",
484
+ input_schema: {
485
+ type: "object",
486
+ properties: { output: {
487
+ type: "string",
488
+ description: "Output file path (optional, default: ~/Desktop/screenshot.png)"
489
+ } }
490
+ },
491
+ handler: async (input) => {
492
+ const output = (input.output || "~/Desktop/screenshot.png").replace(/^~/, os.default.homedir());
493
+ await fs_extra.default.ensureDir(path.default.dirname(output));
494
+ try {
495
+ let cmd;
496
+ if (process.platform === "darwin") cmd = `screencapture -x "${output}"`;
497
+ else if (process.platform === "linux") cmd = `import -window root "${output}" 2>/dev/null || scrot "${output}"`;
498
+ else return "Screenshot not supported on this platform via CLI";
499
+ await execAsync(cmd, { timeout: 1e4 });
500
+ const result = `Screenshot saved to ${output}`;
501
+ await logAction("screenshot", { output }, result);
502
+ return result;
503
+ } catch (e) {
504
+ return `Error: ${e.message}`;
505
+ }
506
+ }
507
+ },
508
+ {
509
+ name: "camera_capture",
510
+ description: "Take a photo with the device webcam. macOS: imagesnap or ffmpeg; Linux: ffmpeg. Requires imagesnap (brew install imagesnap) on macOS.",
511
+ input_schema: {
512
+ type: "object",
513
+ properties: { output: {
514
+ type: "string",
515
+ description: "Output file path (optional, default: ~/Desktop/webcam.jpg)"
516
+ } }
517
+ },
518
+ handler: async (input) => {
519
+ const output = (input.output || "~/Desktop/webcam.jpg").replace(/^~/, os.default.homedir());
520
+ await fs_extra.default.ensureDir(path.default.dirname(output));
521
+ try {
522
+ let cmd;
523
+ if (process.platform === "darwin") cmd = `imagesnap -q "${output}" 2>/dev/null || ffmpeg -f avfoundation -framerate 1 -i "0" -vframes 1 -y "${output}" 2>/dev/null`;
524
+ else if (process.platform === "linux") cmd = `ffmpeg -f v4l2 -i /dev/video0 -vframes 1 -y "${output}" 2>/dev/null`;
525
+ else return "Camera capture not supported on this platform";
526
+ await execAsync(cmd, { timeout: 15e3 });
527
+ const result = `Webcam photo saved to ${output}`;
528
+ await logAction("camera_capture", { output }, result);
529
+ return result;
530
+ } catch (e) {
531
+ return `Error: ${e.message}. Install imagesnap (brew install imagesnap) or ffmpeg for macOS.`;
532
+ }
533
+ }
534
+ },
535
+ {
536
+ name: "screen_record",
537
+ description: "Record the screen for a given duration. macOS only. Uses screencapture -V.",
538
+ input_schema: {
539
+ type: "object",
540
+ properties: {
541
+ duration: {
542
+ type: "string",
543
+ description: "Recording duration in seconds (default 10)"
544
+ },
545
+ output: {
546
+ type: "string",
547
+ description: "Output path (optional, default ~/Desktop/screen-record.mov)"
548
+ }
549
+ }
550
+ },
551
+ handler: async (input) => {
552
+ const duration = parseInt(input.duration || "10", 10);
553
+ const output = (input.output || "~/Desktop/screen-record.mov").replace(/^~/, os.default.homedir());
554
+ if (process.platform !== "darwin") return "Screen recording supported on macOS only (screencapture -V)";
555
+ try {
556
+ await execAsync(`screencapture -V ${Math.min(60, Math.max(1, duration))} -v "${output}"`, { timeout: (duration + 5) * 1e3 });
557
+ const result = `Screen recording saved to ${output}`;
558
+ await logAction("screen_record", {
559
+ duration,
560
+ output
561
+ }, result);
562
+ return result;
563
+ } catch (e) {
564
+ return `Error: ${e.message}`;
565
+ }
566
+ }
567
+ },
568
+ {
569
+ name: "contacts_list",
570
+ description: "List contacts from the system address book. macOS only. Returns name and primary phone/email.",
571
+ input_schema: {
572
+ type: "object",
573
+ properties: {
574
+ limit: {
575
+ type: "string",
576
+ description: "Max contacts to return (default 50)"
577
+ },
578
+ search: {
579
+ type: "string",
580
+ description: "Filter by name (optional)"
581
+ }
582
+ }
583
+ },
584
+ handler: async (input) => {
585
+ if (process.platform !== "darwin") return "Contacts available on macOS only";
586
+ const limit = parseInt(input.limit || "50", 10);
587
+ const search = (input.search || "").replace(/"/g, "\\\"");
588
+ const tmp = path.default.join(os.default.tmpdir(), `hc-contacts-${Date.now()}.scpt`);
589
+ const script = `tell application "Contacts" to get name of every person`;
590
+ try {
591
+ await fs_extra.default.writeFile(tmp, script, "utf8");
592
+ const { stdout } = await execAsync(`osascript "${tmp}"`, { timeout: 1e4 });
593
+ await fs_extra.default.remove(tmp).catch(() => {});
594
+ let names = (stdout || "").trim().split(", ").filter(Boolean);
595
+ if (search) names = names.filter((n) => n.toLowerCase().includes(search.toLowerCase()));
596
+ const result = names.slice(0, limit).join("\n") || "No contacts found";
597
+ await logAction("contacts_list", {
598
+ limit,
599
+ search
600
+ }, `${names.length} contacts`);
601
+ return result;
602
+ } catch (e) {
603
+ await fs_extra.default.remove(tmp).catch(() => {});
604
+ return `Error: ${e.message}. Grant Contacts access to Terminal if prompted.`;
605
+ }
606
+ }
607
+ },
608
+ {
609
+ name: "calendar_events",
610
+ description: "List upcoming calendar events. macOS only. Uses icalBuddy if installed, else basic iCal.",
611
+ input_schema: {
612
+ type: "object",
613
+ properties: {
614
+ days: {
615
+ type: "string",
616
+ description: "Number of days ahead (default 7)"
617
+ },
618
+ limit: {
619
+ type: "string",
620
+ description: "Max events (default 20)"
621
+ }
622
+ }
623
+ },
624
+ handler: async (input) => {
625
+ if (process.platform !== "darwin") return "Calendar available on macOS only";
626
+ const days = parseInt(input.days || "7", 10);
627
+ const limit = parseInt(input.limit || "20", 10);
628
+ try {
629
+ const { stdout } = await execAsync(`icalBuddy -n -ec -nc -nrd -df "%a %H:%M" -sd -ecc eventsToday+${days} 2>/dev/null | head -${limit * 2}`, { timeout: 1e4 }).catch(() => execAsync(`osascript -e 'tell application "Calendar" to return summary of (every event whose start date > (current date))'`, { timeout: 1e4 }));
630
+ const result = (stdout || "").trim() || "No upcoming events (install icalBuddy for richer output: brew install ical-buddy)";
631
+ await logAction("calendar_events", {
632
+ days,
633
+ limit
634
+ }, result.slice(0, 200));
635
+ return result;
636
+ } catch (e) {
637
+ return `Error: ${e.message}. Grant Calendar access if prompted.`;
638
+ }
639
+ }
640
+ },
641
+ {
642
+ name: "photos_recent",
643
+ description: "List recent photos from Photos library. macOS only. Uses mdfind on Photos library.",
644
+ input_schema: {
645
+ type: "object",
646
+ properties: { limit: {
647
+ type: "string",
648
+ description: "Max photos (default 20)"
649
+ } }
650
+ },
651
+ handler: async (input) => {
652
+ if (process.platform !== "darwin") return "Photos available on macOS only";
653
+ const limit = parseInt(input.limit || "20", 10);
654
+ try {
655
+ const lib = path.default.join(os.default.homedir(), "Pictures", "Photos Library.photoslibrary");
656
+ const { stdout } = await execAsync(`mdfind -onlyin "${lib}" "kMDItemContentType == 'public.jpeg' || kMDItemContentType == 'public.png'" 2>/dev/null | head -${limit}`, { timeout: 15e3 }).catch(() => ({ stdout: "" }));
657
+ const lines = (stdout || "").trim().split("\n").filter(Boolean);
658
+ const result = lines.length ? lines.map((f) => path.default.basename(f)).join("\n") : "No photos found";
659
+ await logAction("photos_recent", { limit }, result.slice(0, 200));
660
+ return result;
661
+ } catch (e) {
662
+ return `Error: ${e.message}`;
663
+ }
664
+ }
665
+ },
666
+ {
667
+ name: "app_updates",
668
+ description: "Check for available app updates. Uses Homebrew (macOS/Linux) and optionally Mac App Store (mas) on macOS.",
669
+ input_schema: {
670
+ type: "object",
671
+ properties: { apply: {
672
+ type: "string",
673
+ description: "\"true\" to actually run the updates (default: false, dry-run)"
674
+ } }
675
+ },
676
+ handler: async (input) => {
677
+ const apply = input.apply === "true";
678
+ try {
679
+ let out = "";
680
+ const { stdout: brewOut } = await execAsync("brew update 2>/dev/null; brew outdated 2>/dev/null || true", { timeout: 6e4 });
681
+ out += "Homebrew outdated:\n" + (brewOut.trim() || "(none)") + "\n\n";
682
+ if (process.platform === "darwin") try {
683
+ const { stdout: masOut } = await execAsync("mas outdated 2>/dev/null || true", { timeout: 1e4 });
684
+ out += "Mac App Store outdated:\n" + (masOut.trim() || "(none)");
685
+ } catch {
686
+ out += "Mac App Store: mas not installed (brew install mas)";
687
+ }
688
+ if (apply && brewOut.trim()) {
689
+ await execAsync("brew upgrade", { timeout: 3e5 });
690
+ out += "\n\nHomebrew upgrade completed.";
691
+ }
692
+ await logAction("app_updates", { apply }, out.slice(0, 300));
693
+ return out;
694
+ } catch (e) {
695
+ return `Error: ${e.message}`;
696
+ }
697
+ }
698
+ },
699
+ {
700
+ name: "notify",
701
+ description: "Send a desktop notification to the user.",
702
+ input_schema: {
703
+ type: "object",
704
+ properties: {
705
+ title: {
706
+ type: "string",
707
+ description: "Notification title"
708
+ },
709
+ message: {
710
+ type: "string",
711
+ description: "Notification message body"
712
+ }
713
+ },
714
+ required: ["title", "message"]
715
+ },
716
+ handler: async (input) => {
717
+ const title = input.title;
718
+ const message = input.message;
719
+ try {
720
+ let cmd;
721
+ if (process.platform === "darwin") cmd = `osascript -e 'display notification "${message.replace(/"/g, "\\\"")}" with title "${title.replace(/"/g, "\\\"")}"'`;
722
+ else if (process.platform === "linux") cmd = `notify-send "${title.replace(/"/g, "\\\"")}" "${message.replace(/"/g, "\\\"")}"`;
723
+ else return "Notifications not supported";
724
+ await execAsync(cmd, { timeout: 5e3 });
725
+ return `Notification sent: ${title} — ${message}`;
726
+ } catch (e) {
727
+ return `Error: ${e.message}`;
728
+ }
729
+ }
730
+ }
731
+ ];
732
+ }
733
+ function formatBytes(bytes) {
734
+ if (bytes < 1024) return `${bytes}B`;
735
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
736
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
737
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(1)}GB`;
738
+ }
739
+ /**
740
+ * HyperClaw (OpenClaw-style) behaviour: daemon starts with FULL pc access by default.
741
+ * The user opted in by running `hyperclaw init` and accepting the risk screen.
742
+ * Config in hyperclaw.json can override to read-only or sandboxed.
743
+ * When daemonMode is true, PC access is forced enabled/full so daemon has full access like OpenClaw.
744
+ */
745
+ async function loadPCAccessConfig(opts) {
746
+ const daemonDefault = {
747
+ enabled: true,
748
+ level: "full",
749
+ confirmDestructive: false,
750
+ maxOutputBytes: 5e4
751
+ };
752
+ if (opts?.daemonMode) return daemonDefault;
753
+ try {
754
+ const cfgFile = require_paths.getConfigPath();
755
+ const cfg = await fs_extra.default.readJson(cfgFile);
756
+ if (cfg.pcAccess) return cfg.pcAccess;
757
+ } catch {}
758
+ return daemonDefault;
759
+ }
760
+ async function showPCAccessStatus() {
761
+ const chalk = (await import("chalk")).default;
762
+ const cfg = await loadPCAccessConfig();
763
+ console.log(chalk.bold.cyan("\n PC ACCESS STATUS\n"));
764
+ console.log(` Enabled: ${cfg.enabled ? chalk.green("Yes") : chalk.red("No")}`);
765
+ console.log(` Level: ${cfg.level}`);
766
+ if (cfg.allowedPaths?.length) console.log(` Paths: ${cfg.allowedPaths.join(", ")}`);
767
+ if (cfg.allowedCommands?.length) console.log(` Commands: ${cfg.allowedCommands.join(", ")}`);
768
+ console.log();
769
+ }
770
+ async function savePCAccessConfig(updates) {
771
+ const cfgFile = require_paths.getConfigPath();
772
+ let cfg = {};
773
+ try {
774
+ cfg = await fs_extra.default.readJson(cfgFile);
775
+ } catch {}
776
+ cfg.pcAccess = {
777
+ ...cfg.pcAccess || {},
778
+ ...updates
779
+ };
780
+ await fs_extra.default.ensureDir(path.default.dirname(cfgFile));
781
+ await fs_extra.default.writeJson(cfgFile, cfg, { spaces: 2 });
782
+ }
783
+ var execAsync;
784
+ var init_pc_access = require_chunk.__esm({ "packages/core/src/agent/pc-access.ts"() {
785
+ require_src.init_src();
786
+ execAsync = (0, util.promisify)(child_process.exec);
787
+ } });
788
+
789
+ //#endregion
790
+ Object.defineProperty(exports, 'getPCAccessTools', {
791
+ enumerable: true,
792
+ get: function () {
793
+ return getPCAccessTools;
794
+ }
795
+ });
796
+ Object.defineProperty(exports, 'init_pc_access', {
797
+ enumerable: true,
798
+ get: function () {
799
+ return init_pc_access;
800
+ }
801
+ });
802
+ Object.defineProperty(exports, 'loadPCAccessConfig', {
803
+ enumerable: true,
804
+ get: function () {
805
+ return loadPCAccessConfig;
806
+ }
807
+ });
808
+ Object.defineProperty(exports, 'savePCAccessConfig', {
809
+ enumerable: true,
810
+ get: function () {
811
+ return savePCAccessConfig;
812
+ }
813
+ });
814
+ Object.defineProperty(exports, 'showPCAccessStatus', {
815
+ enumerable: true,
816
+ get: function () {
817
+ return showPCAccessStatus;
818
+ }
819
+ });