clawdbot 2026.1.4-1

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 (550) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/LICENSE +21 -0
  3. package/README-header.png +0 -0
  4. package/README.md +297 -0
  5. package/dist/agents/agent-paths.js +17 -0
  6. package/dist/agents/bash-process-registry.js +126 -0
  7. package/dist/agents/bash-tools.js +837 -0
  8. package/dist/agents/clawdbot-tools.js +30 -0
  9. package/dist/agents/clawdis-tools.js +27 -0
  10. package/dist/agents/context.js +34 -0
  11. package/dist/agents/defaults.js +6 -0
  12. package/dist/agents/model-auth.js +112 -0
  13. package/dist/agents/model-catalog.js +55 -0
  14. package/dist/agents/model-fallback.js +191 -0
  15. package/dist/agents/model-scan.js +263 -0
  16. package/dist/agents/model-selection.js +116 -0
  17. package/dist/agents/models-config.js +49 -0
  18. package/dist/agents/pi-embedded-helpers.js +74 -0
  19. package/dist/agents/pi-embedded-runner.js +407 -0
  20. package/dist/agents/pi-embedded-subscribe.js +568 -0
  21. package/dist/agents/pi-embedded-utils.js +20 -0
  22. package/dist/agents/pi-embedded.js +1 -0
  23. package/dist/agents/pi-oauth.js +88 -0
  24. package/dist/agents/pi-tools.js +433 -0
  25. package/dist/agents/sandbox-paths.js +68 -0
  26. package/dist/agents/sandbox.js +644 -0
  27. package/dist/agents/shell-utils.js +53 -0
  28. package/dist/agents/skills-install.js +244 -0
  29. package/dist/agents/skills-status.js +157 -0
  30. package/dist/agents/skills.js +470 -0
  31. package/dist/agents/steerable-agent-loop.js +338 -0
  32. package/dist/agents/steerable-provider-transport.js +48 -0
  33. package/dist/agents/system-prompt.js +104 -0
  34. package/dist/agents/tool-display.js +162 -0
  35. package/dist/agents/tool-images.js +138 -0
  36. package/dist/agents/tools/browser-tool.js +339 -0
  37. package/dist/agents/tools/canvas-tool.js +193 -0
  38. package/dist/agents/tools/common.js +88 -0
  39. package/dist/agents/tools/cron-tool.js +124 -0
  40. package/dist/agents/tools/discord-actions-guild.js +186 -0
  41. package/dist/agents/tools/discord-actions-messaging.js +285 -0
  42. package/dist/agents/tools/discord-actions-moderation.js +70 -0
  43. package/dist/agents/tools/discord-actions.js +56 -0
  44. package/dist/agents/tools/discord-schema.js +199 -0
  45. package/dist/agents/tools/discord-tool.js +16 -0
  46. package/dist/agents/tools/gateway-tool.js +46 -0
  47. package/dist/agents/tools/gateway.js +27 -0
  48. package/dist/agents/tools/image-tool.js +132 -0
  49. package/dist/agents/tools/nodes-tool.js +413 -0
  50. package/dist/agents/tools/nodes-utils.js +92 -0
  51. package/dist/agents/tools/sessions-helpers.js +88 -0
  52. package/dist/agents/tools/sessions-history-tool.js +53 -0
  53. package/dist/agents/tools/sessions-list-tool.js +143 -0
  54. package/dist/agents/tools/sessions-send-helpers.js +100 -0
  55. package/dist/agents/tools/sessions-send-tool.js +347 -0
  56. package/dist/agents/tools/slack-actions.js +129 -0
  57. package/dist/agents/tools/slack-schema.js +59 -0
  58. package/dist/agents/tools/slack-tool.js +16 -0
  59. package/dist/agents/usage.js +39 -0
  60. package/dist/agents/workspace.js +241 -0
  61. package/dist/auto-reply/chunk.js +76 -0
  62. package/dist/auto-reply/envelope.js +38 -0
  63. package/dist/auto-reply/group-activation.js +20 -0
  64. package/dist/auto-reply/heartbeat.js +57 -0
  65. package/dist/auto-reply/model.js +14 -0
  66. package/dist/auto-reply/reply/abort.js +14 -0
  67. package/dist/auto-reply/reply/agent-runner.js +371 -0
  68. package/dist/auto-reply/reply/block-streaming.js +34 -0
  69. package/dist/auto-reply/reply/body.js +29 -0
  70. package/dist/auto-reply/reply/commands.js +207 -0
  71. package/dist/auto-reply/reply/directive-handling.js +361 -0
  72. package/dist/auto-reply/reply/directives.js +47 -0
  73. package/dist/auto-reply/reply/followup-runner.js +149 -0
  74. package/dist/auto-reply/reply/groups.js +91 -0
  75. package/dist/auto-reply/reply/mentions.js +38 -0
  76. package/dist/auto-reply/reply/model-selection.js +114 -0
  77. package/dist/auto-reply/reply/queue.js +399 -0
  78. package/dist/auto-reply/reply/reply-tags.js +26 -0
  79. package/dist/auto-reply/reply/session-updates.js +87 -0
  80. package/dist/auto-reply/reply/session.js +160 -0
  81. package/dist/auto-reply/reply/typing.js +75 -0
  82. package/dist/auto-reply/reply.js +535 -0
  83. package/dist/auto-reply/send-policy.js +28 -0
  84. package/dist/auto-reply/status.js +158 -0
  85. package/dist/auto-reply/templating.js +9 -0
  86. package/dist/auto-reply/thinking.js +49 -0
  87. package/dist/auto-reply/tokens.js +2 -0
  88. package/dist/auto-reply/tool-meta.js +74 -0
  89. package/dist/auto-reply/transcription.js +57 -0
  90. package/dist/auto-reply/types.js +1 -0
  91. package/dist/browser/bridge-server.js +37 -0
  92. package/dist/browser/cdp.js +382 -0
  93. package/dist/browser/chrome.js +432 -0
  94. package/dist/browser/client-actions-core.js +67 -0
  95. package/dist/browser/client-actions-observe.js +24 -0
  96. package/dist/browser/client-actions-types.js +1 -0
  97. package/dist/browser/client-actions.js +3 -0
  98. package/dist/browser/client-fetch.js +43 -0
  99. package/dist/browser/client.js +105 -0
  100. package/dist/browser/config.js +140 -0
  101. package/dist/browser/constants.js +4 -0
  102. package/dist/browser/profiles-service.js +122 -0
  103. package/dist/browser/profiles.js +85 -0
  104. package/dist/browser/pw-ai.js +2 -0
  105. package/dist/browser/pw-session.js +144 -0
  106. package/dist/browser/pw-tools-core.js +363 -0
  107. package/dist/browser/routes/agent.js +535 -0
  108. package/dist/browser/routes/basic.js +155 -0
  109. package/dist/browser/routes/index.js +8 -0
  110. package/dist/browser/routes/tabs.js +105 -0
  111. package/dist/browser/routes/utils.js +62 -0
  112. package/dist/browser/screenshot.js +40 -0
  113. package/dist/browser/server-context.js +377 -0
  114. package/dist/browser/server.js +81 -0
  115. package/dist/browser/target-id.js +18 -0
  116. package/dist/browser/trash.js +21 -0
  117. package/dist/canvas-host/a2ui/.bundle.hash +1 -0
  118. package/dist/canvas-host/a2ui/a2ui.bundle.js +17768 -0
  119. package/dist/canvas-host/a2ui/index.html +246 -0
  120. package/dist/canvas-host/a2ui.js +187 -0
  121. package/dist/canvas-host/server.js +382 -0
  122. package/dist/cli/browser-cli-actions-input.js +459 -0
  123. package/dist/cli/browser-cli-actions-observe.js +56 -0
  124. package/dist/cli/browser-cli-examples.js +31 -0
  125. package/dist/cli/browser-cli-inspect.js +97 -0
  126. package/dist/cli/browser-cli-manage.js +286 -0
  127. package/dist/cli/browser-cli-shared.js +1 -0
  128. package/dist/cli/browser-cli.js +26 -0
  129. package/dist/cli/canvas-cli.js +416 -0
  130. package/dist/cli/cron-cli.js +454 -0
  131. package/dist/cli/deps.js +17 -0
  132. package/dist/cli/dns-cli.js +180 -0
  133. package/dist/cli/gateway-cli.js +489 -0
  134. package/dist/cli/gateway-rpc.js +20 -0
  135. package/dist/cli/hooks-cli.js +135 -0
  136. package/dist/cli/models-cli.js +248 -0
  137. package/dist/cli/nodes-camera.js +57 -0
  138. package/dist/cli/nodes-canvas.js +26 -0
  139. package/dist/cli/nodes-cli.js +946 -0
  140. package/dist/cli/nodes-screen.js +37 -0
  141. package/dist/cli/parse-duration.js +20 -0
  142. package/dist/cli/ports.js +97 -0
  143. package/dist/cli/program.js +406 -0
  144. package/dist/cli/prompt.js +19 -0
  145. package/dist/cli/tui-cli.js +35 -0
  146. package/dist/cli/wait.js +8 -0
  147. package/dist/commands/agent.js +645 -0
  148. package/dist/commands/antigravity-oauth.js +327 -0
  149. package/dist/commands/configure.js +480 -0
  150. package/dist/commands/doctor.js +484 -0
  151. package/dist/commands/health.js +108 -0
  152. package/dist/commands/models/aliases.js +64 -0
  153. package/dist/commands/models/fallbacks.js +99 -0
  154. package/dist/commands/models/image-fallbacks.js +99 -0
  155. package/dist/commands/models/list.js +323 -0
  156. package/dist/commands/models/scan.js +266 -0
  157. package/dist/commands/models/set-image.js +23 -0
  158. package/dist/commands/models/set.js +23 -0
  159. package/dist/commands/models/shared.js +72 -0
  160. package/dist/commands/models.js +7 -0
  161. package/dist/commands/onboard-auth.js +70 -0
  162. package/dist/commands/onboard-helpers.js +295 -0
  163. package/dist/commands/onboard-interactive.js +17 -0
  164. package/dist/commands/onboard-non-interactive.js +202 -0
  165. package/dist/commands/onboard-providers.js +634 -0
  166. package/dist/commands/onboard-remote.js +120 -0
  167. package/dist/commands/onboard-skills.js +148 -0
  168. package/dist/commands/onboard-types.js +1 -0
  169. package/dist/commands/onboard.js +12 -0
  170. package/dist/commands/send.js +124 -0
  171. package/dist/commands/sessions.js +212 -0
  172. package/dist/commands/setup.js +58 -0
  173. package/dist/commands/signal-install.js +135 -0
  174. package/dist/commands/status.js +207 -0
  175. package/dist/commands/update.js +16 -0
  176. package/dist/config/config.js +6 -0
  177. package/dist/config/defaults.js +61 -0
  178. package/dist/config/io.js +147 -0
  179. package/dist/config/legacy-migrate.js +13 -0
  180. package/dist/config/legacy.js +159 -0
  181. package/dist/config/paths.js +71 -0
  182. package/dist/config/schema.js +150 -0
  183. package/dist/config/sessions.js +282 -0
  184. package/dist/config/talk.js +31 -0
  185. package/dist/config/types.js +1 -0
  186. package/dist/config/validation.js +29 -0
  187. package/dist/config/zod-schema.js +831 -0
  188. package/dist/control-ui/assets/index-BFID3yAA.css +1 -0
  189. package/dist/control-ui/assets/index-CE_axlTS.js +2235 -0
  190. package/dist/control-ui/assets/index-CE_axlTS.js.map +1 -0
  191. package/dist/control-ui/index.html +15 -0
  192. package/dist/cron/isolated-agent.js +499 -0
  193. package/dist/cron/run-log.js +72 -0
  194. package/dist/cron/schedule.js +24 -0
  195. package/dist/cron/service.js +471 -0
  196. package/dist/cron/store.js +43 -0
  197. package/dist/cron/types.js +1 -0
  198. package/dist/daemon/constants.js +10 -0
  199. package/dist/daemon/launchd.js +276 -0
  200. package/dist/daemon/legacy.js +63 -0
  201. package/dist/daemon/program-args.js +76 -0
  202. package/dist/daemon/schtasks.js +257 -0
  203. package/dist/daemon/service.js +60 -0
  204. package/dist/daemon/systemd.js +266 -0
  205. package/dist/discord/index.js +2 -0
  206. package/dist/discord/monitor.js +1188 -0
  207. package/dist/discord/probe.js +54 -0
  208. package/dist/discord/send.js +577 -0
  209. package/dist/discord/token.js +8 -0
  210. package/dist/gateway/auth.js +121 -0
  211. package/dist/gateway/call.js +94 -0
  212. package/dist/gateway/chat-attachments.js +41 -0
  213. package/dist/gateway/client.js +180 -0
  214. package/dist/gateway/config-reload.js +274 -0
  215. package/dist/gateway/control-ui.js +184 -0
  216. package/dist/gateway/hooks-mapping.js +282 -0
  217. package/dist/gateway/hooks.js +168 -0
  218. package/dist/gateway/net.js +29 -0
  219. package/dist/gateway/protocol/index.js +61 -0
  220. package/dist/gateway/protocol/schema.js +560 -0
  221. package/dist/gateway/server-bridge-subscriptions.js +93 -0
  222. package/dist/gateway/server-bridge.js +1013 -0
  223. package/dist/gateway/server-browser.js +12 -0
  224. package/dist/gateway/server-chat.js +159 -0
  225. package/dist/gateway/server-constants.js +8 -0
  226. package/dist/gateway/server-discovery.js +62 -0
  227. package/dist/gateway/server-http.js +165 -0
  228. package/dist/gateway/server-methods/agent-job.js +125 -0
  229. package/dist/gateway/server-methods/agent.js +250 -0
  230. package/dist/gateway/server-methods/chat.js +200 -0
  231. package/dist/gateway/server-methods/config.js +50 -0
  232. package/dist/gateway/server-methods/connect.js +6 -0
  233. package/dist/gateway/server-methods/cron.js +83 -0
  234. package/dist/gateway/server-methods/health.js +28 -0
  235. package/dist/gateway/server-methods/models.js +16 -0
  236. package/dist/gateway/server-methods/nodes.js +294 -0
  237. package/dist/gateway/server-methods/providers.js +217 -0
  238. package/dist/gateway/server-methods/send.js +166 -0
  239. package/dist/gateway/server-methods/sessions.js +305 -0
  240. package/dist/gateway/server-methods/skills.js +83 -0
  241. package/dist/gateway/server-methods/system.js +118 -0
  242. package/dist/gateway/server-methods/talk.js +22 -0
  243. package/dist/gateway/server-methods/types.js +1 -0
  244. package/dist/gateway/server-methods/voicewake.js +30 -0
  245. package/dist/gateway/server-methods/web.js +58 -0
  246. package/dist/gateway/server-methods/wizard.js +100 -0
  247. package/dist/gateway/server-methods.js +53 -0
  248. package/dist/gateway/server-providers.js +644 -0
  249. package/dist/gateway/server-shared.js +1 -0
  250. package/dist/gateway/server-utils.js +35 -0
  251. package/dist/gateway/server.js +1437 -0
  252. package/dist/gateway/session-utils.js +216 -0
  253. package/dist/gateway/ws-log.js +349 -0
  254. package/dist/gateway/ws-logging.js +8 -0
  255. package/dist/globals.js +41 -0
  256. package/dist/hooks/gmail-ops.js +236 -0
  257. package/dist/hooks/gmail-setup-utils.js +278 -0
  258. package/dist/hooks/gmail-watcher.js +175 -0
  259. package/dist/hooks/gmail.js +177 -0
  260. package/dist/imessage/client.js +165 -0
  261. package/dist/imessage/index.js +3 -0
  262. package/dist/imessage/monitor.js +272 -0
  263. package/dist/imessage/probe.js +26 -0
  264. package/dist/imessage/send.js +83 -0
  265. package/dist/imessage/targets.js +176 -0
  266. package/dist/index.js +50 -0
  267. package/dist/infra/agent-events.js +46 -0
  268. package/dist/infra/binaries.js +9 -0
  269. package/dist/infra/bonjour-discovery.js +163 -0
  270. package/dist/infra/bonjour.js +200 -0
  271. package/dist/infra/bridge/server.js +562 -0
  272. package/dist/infra/canvas-host-url.js +54 -0
  273. package/dist/infra/env.js +8 -0
  274. package/dist/infra/errors.js +28 -0
  275. package/dist/infra/gateway-lock.js +8 -0
  276. package/dist/infra/heartbeat-events.js +21 -0
  277. package/dist/infra/heartbeat-runner.js +453 -0
  278. package/dist/infra/heartbeat-wake.js +61 -0
  279. package/dist/infra/is-main.js +37 -0
  280. package/dist/infra/machine-name.js +40 -0
  281. package/dist/infra/node-pairing.js +211 -0
  282. package/dist/infra/pam.js +42 -0
  283. package/dist/infra/path-env.js +92 -0
  284. package/dist/infra/ports.js +87 -0
  285. package/dist/infra/provider-summary.js +80 -0
  286. package/dist/infra/restart.js +29 -0
  287. package/dist/infra/retry.js +16 -0
  288. package/dist/infra/runtime-guard.js +59 -0
  289. package/dist/infra/system-events.js +44 -0
  290. package/dist/infra/system-presence.js +216 -0
  291. package/dist/infra/tailnet.js +46 -0
  292. package/dist/infra/tailscale.js +149 -0
  293. package/dist/infra/voicewake.js +77 -0
  294. package/dist/infra/widearea-dns.js +123 -0
  295. package/dist/infra/ws.js +13 -0
  296. package/dist/logger.js +52 -0
  297. package/dist/logging.js +490 -0
  298. package/dist/macos/gateway-daemon.js +141 -0
  299. package/dist/macos/relay.js +46 -0
  300. package/dist/media/constants.js +33 -0
  301. package/dist/media/host.js +42 -0
  302. package/dist/media/image-ops.js +121 -0
  303. package/dist/media/mime.js +115 -0
  304. package/dist/media/parse.js +81 -0
  305. package/dist/media/server.js +64 -0
  306. package/dist/media/store.js +139 -0
  307. package/dist/process/command-queue.js +97 -0
  308. package/dist/process/exec.js +75 -0
  309. package/dist/protocol.schema.json +2918 -0
  310. package/dist/provider-web.js +8 -0
  311. package/dist/providers/web/index.js +2 -0
  312. package/dist/runtime.js +8 -0
  313. package/dist/sessions/send-policy.js +68 -0
  314. package/dist/signal/client.js +134 -0
  315. package/dist/signal/daemon.js +69 -0
  316. package/dist/signal/index.js +3 -0
  317. package/dist/signal/monitor.js +336 -0
  318. package/dist/signal/probe.js +46 -0
  319. package/dist/signal/send.js +91 -0
  320. package/dist/slack/actions.js +97 -0
  321. package/dist/slack/index.js +5 -0
  322. package/dist/slack/monitor.js +1029 -0
  323. package/dist/slack/probe.js +47 -0
  324. package/dist/slack/send.js +131 -0
  325. package/dist/slack/token.js +10 -0
  326. package/dist/telegram/bot.js +394 -0
  327. package/dist/telegram/download.js +34 -0
  328. package/dist/telegram/index.js +4 -0
  329. package/dist/telegram/monitor.js +47 -0
  330. package/dist/telegram/probe.js +63 -0
  331. package/dist/telegram/proxy.js +9 -0
  332. package/dist/telegram/send.js +138 -0
  333. package/dist/telegram/token.js +30 -0
  334. package/dist/telegram/webhook-set.js +12 -0
  335. package/dist/telegram/webhook.js +56 -0
  336. package/dist/tui/commands.js +74 -0
  337. package/dist/tui/components/assistant-message.js +16 -0
  338. package/dist/tui/components/chat-log.js +92 -0
  339. package/dist/tui/components/custom-editor.js +53 -0
  340. package/dist/tui/components/selectors.js +8 -0
  341. package/dist/tui/components/tool-execution.js +111 -0
  342. package/dist/tui/components/user-message.js +17 -0
  343. package/dist/tui/gateway-chat.js +140 -0
  344. package/dist/tui/layout.js +41 -0
  345. package/dist/tui/message-list.js +57 -0
  346. package/dist/tui/theme/theme.js +80 -0
  347. package/dist/tui/theme.js +25 -0
  348. package/dist/tui/tui.js +708 -0
  349. package/dist/utils.js +133 -0
  350. package/dist/version.js +18 -0
  351. package/dist/web/active-listener.js +7 -0
  352. package/dist/web/auto-reply.js +1203 -0
  353. package/dist/web/inbound.js +481 -0
  354. package/dist/web/login-qr.js +204 -0
  355. package/dist/web/login.js +59 -0
  356. package/dist/web/media.js +148 -0
  357. package/dist/web/outbound.js +67 -0
  358. package/dist/web/qr-image.js +97 -0
  359. package/dist/web/reconnect.js +60 -0
  360. package/dist/web/reply-heartbeat-wake.js +61 -0
  361. package/dist/web/session.js +346 -0
  362. package/dist/wizard/clack-prompter.js +56 -0
  363. package/dist/wizard/onboarding.js +452 -0
  364. package/dist/wizard/prompts.js +6 -0
  365. package/dist/wizard/session.js +203 -0
  366. package/docs/AGENTS.default.md +116 -0
  367. package/docs/CNAME +1 -0
  368. package/docs/RELEASING.md +64 -0
  369. package/docs/_config.yml +51 -0
  370. package/docs/_layouts/default.html +145 -0
  371. package/docs/agent-send.md +21 -0
  372. package/docs/agent.md +104 -0
  373. package/docs/android/connect.md +131 -0
  374. package/docs/architecture.md +89 -0
  375. package/docs/assets/markdown.css +130 -0
  376. package/docs/assets/pixel-lobster.svg +60 -0
  377. package/docs/assets/terminal.css +497 -0
  378. package/docs/assets/theme.js +55 -0
  379. package/docs/audio.md +50 -0
  380. package/docs/background-process.md +74 -0
  381. package/docs/bash.md +32 -0
  382. package/docs/bonjour.md +159 -0
  383. package/docs/browser.md +289 -0
  384. package/docs/camera.md +152 -0
  385. package/docs/clawd.md +199 -0
  386. package/docs/clawdbot-mac.md +104 -0
  387. package/docs/configuration.md +1177 -0
  388. package/docs/control-api.md +49 -0
  389. package/docs/control-ui.md +83 -0
  390. package/docs/cron.md +374 -0
  391. package/docs/dashboard.md +17 -0
  392. package/docs/device-models.md +46 -0
  393. package/docs/discord.md +293 -0
  394. package/docs/discovery.md +112 -0
  395. package/docs/docker.md +251 -0
  396. package/docs/docs.json +86 -0
  397. package/docs/doctor.md +47 -0
  398. package/docs/elevated.md +31 -0
  399. package/docs/faq.md +640 -0
  400. package/docs/gateway/pairing.md +109 -0
  401. package/docs/gateway-lock.md +28 -0
  402. package/docs/gateway.md +174 -0
  403. package/docs/gmail-pubsub.md +191 -0
  404. package/docs/grammy.md +27 -0
  405. package/docs/group-messages.md +71 -0
  406. package/docs/groups.md +78 -0
  407. package/docs/health.md +28 -0
  408. package/docs/heartbeat.md +64 -0
  409. package/docs/images.md +52 -0
  410. package/docs/imessage.md +63 -0
  411. package/docs/index.md +182 -0
  412. package/docs/ios/connect.md +177 -0
  413. package/docs/ios/spec.md +236 -0
  414. package/docs/location-command.md +95 -0
  415. package/docs/logging.md +99 -0
  416. package/docs/lore.md +131 -0
  417. package/docs/mac/bun.md +133 -0
  418. package/docs/mac/canvas.md +161 -0
  419. package/docs/mac/child-process.md +72 -0
  420. package/docs/mac/dev-setup.md +81 -0
  421. package/docs/mac/health.md +28 -0
  422. package/docs/mac/icon.md +26 -0
  423. package/docs/mac/logging.md +51 -0
  424. package/docs/mac/menu-bar.md +69 -0
  425. package/docs/mac/peekaboo.md +170 -0
  426. package/docs/mac/permissions.md +40 -0
  427. package/docs/mac/release.md +76 -0
  428. package/docs/mac/remote.md +57 -0
  429. package/docs/mac/signing.md +41 -0
  430. package/docs/mac/skills.md +27 -0
  431. package/docs/mac/voice-overlay.md +52 -0
  432. package/docs/mac/voicewake.md +56 -0
  433. package/docs/mac/webchat.md +27 -0
  434. package/docs/mac/xpc.md +40 -0
  435. package/docs/models.md +90 -0
  436. package/docs/nix.md +49 -0
  437. package/docs/nodes.md +157 -0
  438. package/docs/onboarding-config-protocol.md +29 -0
  439. package/docs/onboarding.md +185 -0
  440. package/docs/presence.md +133 -0
  441. package/docs/queue.md +78 -0
  442. package/docs/refactor/browser-control-simplification.md +58 -0
  443. package/docs/refactor/canvas-a2ui.md +93 -0
  444. package/docs/refactor/cli-unification.md +64 -0
  445. package/docs/refactor/gateway-client.md +31 -0
  446. package/docs/refactor/gateway.md +99 -0
  447. package/docs/refactor/new-arch.md +171 -0
  448. package/docs/refactor/tui.md +26 -0
  449. package/docs/refactor/web-gateway-troubleshooting.md +37 -0
  450. package/docs/refactor/webagent-session.md +46 -0
  451. package/docs/remote-gateway-readme.md +148 -0
  452. package/docs/remote.md +66 -0
  453. package/docs/research/memory.md +227 -0
  454. package/docs/rpc.md +35 -0
  455. package/docs/security.md +168 -0
  456. package/docs/session-tool.md +119 -0
  457. package/docs/session.md +84 -0
  458. package/docs/sessions.md +8 -0
  459. package/docs/setup.md +118 -0
  460. package/docs/signal.md +113 -0
  461. package/docs/skills-config.md +58 -0
  462. package/docs/skills.md +149 -0
  463. package/docs/slack.md +158 -0
  464. package/docs/surface.md +20 -0
  465. package/docs/tailscale.md +71 -0
  466. package/docs/talk.md +79 -0
  467. package/docs/telegram.md +90 -0
  468. package/docs/templates/AGENTS.md +126 -0
  469. package/docs/templates/BOOTSTRAP.md +53 -0
  470. package/docs/templates/IDENTITY.md +17 -0
  471. package/docs/templates/SOUL.md +41 -0
  472. package/docs/templates/TOOLS.md +41 -0
  473. package/docs/templates/USER.md +22 -0
  474. package/docs/test.md +35 -0
  475. package/docs/thinking.md +46 -0
  476. package/docs/tools.md +248 -0
  477. package/docs/troubleshooting.md +227 -0
  478. package/docs/tui.md +69 -0
  479. package/docs/typebox.md +42 -0
  480. package/docs/voicewake.md +61 -0
  481. package/docs/web.md +115 -0
  482. package/docs/webchat.md +34 -0
  483. package/docs/webhook.md +132 -0
  484. package/docs/whatsapp-clawd.jpg +0 -0
  485. package/docs/whatsapp.md +142 -0
  486. package/docs/wizard.md +158 -0
  487. package/package.json +186 -0
  488. package/skills/apple-notes/SKILL.md +50 -0
  489. package/skills/apple-reminders/SKILL.md +67 -0
  490. package/skills/bear-notes/SKILL.md +79 -0
  491. package/skills/bird/SKILL.md +25 -0
  492. package/skills/blogwatcher/SKILL.md +46 -0
  493. package/skills/blucli/SKILL.md +27 -0
  494. package/skills/brave-search/SKILL.md +30 -0
  495. package/skills/brave-search/scripts/content.mjs +53 -0
  496. package/skills/brave-search/scripts/search.mjs +79 -0
  497. package/skills/camsnap/SKILL.md +25 -0
  498. package/skills/clawdhub/SKILL.md +53 -0
  499. package/skills/coding-agent/SKILL.md +275 -0
  500. package/skills/discord/SKILL.md +369 -0
  501. package/skills/eightctl/SKILL.md +29 -0
  502. package/skills/food-order/SKILL.md +41 -0
  503. package/skills/gemini/SKILL.md +23 -0
  504. package/skills/gifgrep/SKILL.md +47 -0
  505. package/skills/github/SKILL.md +47 -0
  506. package/skills/gog/SKILL.md +36 -0
  507. package/skills/goplaces/SKILL.md +30 -0
  508. package/skills/imsg/SKILL.md +25 -0
  509. package/skills/local-places/SERVER_README.md +101 -0
  510. package/skills/local-places/SKILL.md +91 -0
  511. package/skills/local-places/pyproject.toml +27 -0
  512. package/skills/local-places/src/local_places/__init__.py +2 -0
  513. package/skills/local-places/src/local_places/__pycache__/__init__.cpython-314.pyc +0 -0
  514. package/skills/local-places/src/local_places/__pycache__/google_places.cpython-314.pyc +0 -0
  515. package/skills/local-places/src/local_places/__pycache__/main.cpython-314.pyc +0 -0
  516. package/skills/local-places/src/local_places/__pycache__/schemas.cpython-314.pyc +0 -0
  517. package/skills/local-places/src/local_places/google_places.py +314 -0
  518. package/skills/local-places/src/local_places/main.py +65 -0
  519. package/skills/local-places/src/local_places/schemas.py +107 -0
  520. package/skills/mcporter/SKILL.md +38 -0
  521. package/skills/nano-banana-pro/SKILL.md +29 -0
  522. package/skills/nano-banana-pro/scripts/generate_image.py +167 -0
  523. package/skills/nano-pdf/SKILL.md +20 -0
  524. package/skills/notion/SKILL.md +156 -0
  525. package/skills/obsidian/SKILL.md +55 -0
  526. package/skills/openai-image-gen/SKILL.md +31 -0
  527. package/skills/openai-image-gen/scripts/gen.py +173 -0
  528. package/skills/openai-whisper/SKILL.md +19 -0
  529. package/skills/openai-whisper-api/SKILL.md +43 -0
  530. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  531. package/skills/openhue/SKILL.md +30 -0
  532. package/skills/oracle/SKILL.md +105 -0
  533. package/skills/ordercli/SKILL.md +47 -0
  534. package/skills/peekaboo/SKILL.md +153 -0
  535. package/skills/qmd/SKILL.md +26 -0
  536. package/skills/sag/SKILL.md +62 -0
  537. package/skills/slack/SKILL.md +143 -0
  538. package/skills/songsee/SKILL.md +29 -0
  539. package/skills/sonoscli/SKILL.md +26 -0
  540. package/skills/spotify-player/SKILL.md +34 -0
  541. package/skills/summarize/SKILL.md +49 -0
  542. package/skills/things-mac/SKILL.md +61 -0
  543. package/skills/tmux/SKILL.md +121 -0
  544. package/skills/tmux/scripts/find-sessions.sh +112 -0
  545. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  546. package/skills/trello/SKILL.md +84 -0
  547. package/skills/video-frames/SKILL.md +29 -0
  548. package/skills/video-frames/scripts/frame.sh +81 -0
  549. package/skills/wacli/SKILL.md +42 -0
  550. package/skills/weather/SKILL.md +49 -0
@@ -0,0 +1,432 @@
1
+ import { spawn } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import WebSocket from "ws";
6
+ import { ensurePortAvailable } from "../infra/ports.js";
7
+ import { createSubsystemLogger } from "../logging.js";
8
+ import { CONFIG_DIR } from "../utils.js";
9
+ import { normalizeCdpWsUrl } from "./cdp.js";
10
+ import { DEFAULT_CLAWD_BROWSER_COLOR, DEFAULT_CLAWD_BROWSER_PROFILE_NAME, } from "./constants.js";
11
+ const log = createSubsystemLogger("browser").child("chrome");
12
+ function exists(filePath) {
13
+ try {
14
+ return fs.existsSync(filePath);
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ export function findChromeExecutableMac() {
21
+ const candidates = [
22
+ {
23
+ kind: "canary",
24
+ path: "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
25
+ },
26
+ {
27
+ kind: "canary",
28
+ path: path.join(os.homedir(), "Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"),
29
+ },
30
+ {
31
+ kind: "chromium",
32
+ path: "/Applications/Chromium.app/Contents/MacOS/Chromium",
33
+ },
34
+ {
35
+ kind: "chromium",
36
+ path: path.join(os.homedir(), "Applications/Chromium.app/Contents/MacOS/Chromium"),
37
+ },
38
+ {
39
+ kind: "chrome",
40
+ path: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
41
+ },
42
+ {
43
+ kind: "chrome",
44
+ path: path.join(os.homedir(), "Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
45
+ },
46
+ ];
47
+ for (const candidate of candidates) {
48
+ if (exists(candidate.path))
49
+ return candidate;
50
+ }
51
+ return null;
52
+ }
53
+ export function findChromeExecutableLinux() {
54
+ const candidates = [
55
+ { kind: "chrome", path: "/usr/bin/google-chrome" },
56
+ { kind: "chrome", path: "/usr/bin/google-chrome-stable" },
57
+ { kind: "chromium", path: "/usr/bin/chromium" },
58
+ { kind: "chromium", path: "/usr/bin/chromium-browser" },
59
+ { kind: "chromium", path: "/snap/bin/chromium" },
60
+ { kind: "chrome", path: "/usr/bin/chrome" },
61
+ ];
62
+ for (const candidate of candidates) {
63
+ if (exists(candidate.path))
64
+ return candidate;
65
+ }
66
+ return null;
67
+ }
68
+ function resolveBrowserExecutable(resolved) {
69
+ if (resolved.executablePath) {
70
+ if (!exists(resolved.executablePath)) {
71
+ throw new Error(`browser.executablePath not found: ${resolved.executablePath}`);
72
+ }
73
+ return { kind: "custom", path: resolved.executablePath };
74
+ }
75
+ if (process.platform === "darwin")
76
+ return findChromeExecutableMac();
77
+ if (process.platform === "linux")
78
+ return findChromeExecutableLinux();
79
+ return null;
80
+ }
81
+ export function resolveClawdUserDataDir(profileName = DEFAULT_CLAWD_BROWSER_PROFILE_NAME) {
82
+ return path.join(CONFIG_DIR, "browser", profileName, "user-data");
83
+ }
84
+ function decoratedMarkerPath(userDataDir) {
85
+ return path.join(userDataDir, ".clawd-profile-decorated");
86
+ }
87
+ function safeReadJson(filePath) {
88
+ try {
89
+ if (!exists(filePath))
90
+ return null;
91
+ const raw = fs.readFileSync(filePath, "utf-8");
92
+ const parsed = JSON.parse(raw);
93
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
94
+ return null;
95
+ return parsed;
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ }
101
+ function safeWriteJson(filePath, data) {
102
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
103
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
104
+ }
105
+ function cdpUrlForPort(cdpPort) {
106
+ return `http://127.0.0.1:${cdpPort}`;
107
+ }
108
+ function setDeep(obj, keys, value) {
109
+ let node = obj;
110
+ for (const key of keys.slice(0, -1)) {
111
+ const next = node[key];
112
+ if (typeof next !== "object" || next === null || Array.isArray(next)) {
113
+ node[key] = {};
114
+ }
115
+ node = node[key];
116
+ }
117
+ node[keys[keys.length - 1] ?? ""] = value;
118
+ }
119
+ function parseHexRgbToSignedArgbInt(hex) {
120
+ const cleaned = hex.trim().replace(/^#/, "");
121
+ if (!/^[0-9a-fA-F]{6}$/.test(cleaned))
122
+ return null;
123
+ const rgb = Number.parseInt(cleaned, 16);
124
+ const argbUnsigned = (0xff << 24) | rgb;
125
+ // Chrome stores colors as signed 32-bit ints (SkColor).
126
+ return argbUnsigned > 0x7fffffff
127
+ ? argbUnsigned - 0x1_0000_0000
128
+ : argbUnsigned;
129
+ }
130
+ function isProfileDecorated(userDataDir, desiredName, desiredColorHex) {
131
+ const desiredColorInt = parseHexRgbToSignedArgbInt(desiredColorHex);
132
+ const localStatePath = path.join(userDataDir, "Local State");
133
+ const preferencesPath = path.join(userDataDir, "Default", "Preferences");
134
+ const localState = safeReadJson(localStatePath);
135
+ const profile = localState?.profile;
136
+ const infoCache = typeof profile === "object" && profile !== null && !Array.isArray(profile)
137
+ ? profile.info_cache
138
+ : null;
139
+ const info = typeof infoCache === "object" &&
140
+ infoCache !== null &&
141
+ !Array.isArray(infoCache) &&
142
+ typeof infoCache.Default === "object" &&
143
+ infoCache.Default !== null &&
144
+ !Array.isArray(infoCache.Default)
145
+ ? infoCache.Default
146
+ : null;
147
+ const prefs = safeReadJson(preferencesPath);
148
+ const browserTheme = (() => {
149
+ const browser = prefs?.browser;
150
+ const theme = typeof browser === "object" && browser !== null && !Array.isArray(browser)
151
+ ? browser.theme
152
+ : null;
153
+ return typeof theme === "object" && theme !== null && !Array.isArray(theme)
154
+ ? theme
155
+ : null;
156
+ })();
157
+ const autogeneratedTheme = (() => {
158
+ const autogenerated = prefs?.autogenerated;
159
+ const theme = typeof autogenerated === "object" &&
160
+ autogenerated !== null &&
161
+ !Array.isArray(autogenerated)
162
+ ? autogenerated.theme
163
+ : null;
164
+ return typeof theme === "object" && theme !== null && !Array.isArray(theme)
165
+ ? theme
166
+ : null;
167
+ })();
168
+ const nameOk = typeof info?.name === "string" ? info.name === desiredName : true;
169
+ if (desiredColorInt == null) {
170
+ // If the user provided a non-#RRGGBB value, we can only do best-effort.
171
+ return nameOk;
172
+ }
173
+ const localSeedOk = typeof info?.profile_color_seed === "number"
174
+ ? info.profile_color_seed === desiredColorInt
175
+ : false;
176
+ const prefOk = (typeof browserTheme?.user_color2 === "number" &&
177
+ browserTheme.user_color2 === desiredColorInt) ||
178
+ (typeof autogeneratedTheme?.color === "number" &&
179
+ autogeneratedTheme.color === desiredColorInt);
180
+ return nameOk && localSeedOk && prefOk;
181
+ }
182
+ /**
183
+ * Best-effort profile decoration (name + lobster-orange). Chrome preference keys
184
+ * vary by version; we keep this conservative and idempotent.
185
+ */
186
+ export function decorateClawdProfile(userDataDir, opts) {
187
+ const desiredName = opts?.name ?? DEFAULT_CLAWD_BROWSER_PROFILE_NAME;
188
+ const desiredColor = (opts?.color ?? DEFAULT_CLAWD_BROWSER_COLOR).toUpperCase();
189
+ const desiredColorInt = parseHexRgbToSignedArgbInt(desiredColor);
190
+ const localStatePath = path.join(userDataDir, "Local State");
191
+ const preferencesPath = path.join(userDataDir, "Default", "Preferences");
192
+ const localState = safeReadJson(localStatePath) ?? {};
193
+ // Common-ish shape: profile.info_cache.Default
194
+ setDeep(localState, ["profile", "info_cache", "Default", "name"], desiredName);
195
+ setDeep(localState, ["profile", "info_cache", "Default", "shortcut_name"], desiredName);
196
+ setDeep(localState, ["profile", "info_cache", "Default", "user_name"], desiredName);
197
+ // Color keys are best-effort (Chrome changes these frequently).
198
+ setDeep(localState, ["profile", "info_cache", "Default", "profile_color"], desiredColor);
199
+ setDeep(localState, ["profile", "info_cache", "Default", "user_color"], desiredColor);
200
+ if (desiredColorInt != null) {
201
+ // These are the fields Chrome actually uses for profile/avatar tinting.
202
+ setDeep(localState, ["profile", "info_cache", "Default", "profile_color_seed"], desiredColorInt);
203
+ setDeep(localState, ["profile", "info_cache", "Default", "profile_highlight_color"], desiredColorInt);
204
+ setDeep(localState, ["profile", "info_cache", "Default", "default_avatar_fill_color"], desiredColorInt);
205
+ setDeep(localState, ["profile", "info_cache", "Default", "default_avatar_stroke_color"], desiredColorInt);
206
+ }
207
+ safeWriteJson(localStatePath, localState);
208
+ const prefs = safeReadJson(preferencesPath) ?? {};
209
+ setDeep(prefs, ["profile", "name"], desiredName);
210
+ setDeep(prefs, ["profile", "profile_color"], desiredColor);
211
+ setDeep(prefs, ["profile", "user_color"], desiredColor);
212
+ if (desiredColorInt != null) {
213
+ // Chrome refresh stores the autogenerated theme in these prefs (SkColor ints).
214
+ setDeep(prefs, ["autogenerated", "theme", "color"], desiredColorInt);
215
+ // User-selected browser theme color (pref name: browser.theme.user_color2).
216
+ setDeep(prefs, ["browser", "theme", "user_color2"], desiredColorInt);
217
+ }
218
+ safeWriteJson(preferencesPath, prefs);
219
+ try {
220
+ fs.writeFileSync(decoratedMarkerPath(userDataDir), `${Date.now()}\n`, "utf-8");
221
+ }
222
+ catch {
223
+ // ignore
224
+ }
225
+ }
226
+ export async function isChromeReachable(cdpUrl, timeoutMs = 500) {
227
+ const version = await fetchChromeVersion(cdpUrl, timeoutMs);
228
+ return Boolean(version);
229
+ }
230
+ async function fetchChromeVersion(cdpUrl, timeoutMs = 500) {
231
+ const ctrl = new AbortController();
232
+ const t = setTimeout(() => ctrl.abort(), timeoutMs);
233
+ try {
234
+ const base = cdpUrl.replace(/\/$/, "");
235
+ const res = await fetch(`${base}/json/version`, {
236
+ signal: ctrl.signal,
237
+ });
238
+ if (!res.ok)
239
+ return null;
240
+ const data = (await res.json());
241
+ if (!data || typeof data !== "object")
242
+ return null;
243
+ return data;
244
+ }
245
+ catch {
246
+ return null;
247
+ }
248
+ finally {
249
+ clearTimeout(t);
250
+ }
251
+ }
252
+ export async function getChromeWebSocketUrl(cdpUrl, timeoutMs = 500) {
253
+ const version = await fetchChromeVersion(cdpUrl, timeoutMs);
254
+ const wsUrl = String(version?.webSocketDebuggerUrl ?? "").trim();
255
+ if (!wsUrl)
256
+ return null;
257
+ return normalizeCdpWsUrl(wsUrl, cdpUrl);
258
+ }
259
+ async function canOpenWebSocket(wsUrl, timeoutMs = 800) {
260
+ return await new Promise((resolve) => {
261
+ const ws = new WebSocket(wsUrl, { handshakeTimeout: timeoutMs });
262
+ const timer = setTimeout(() => {
263
+ try {
264
+ ws.terminate();
265
+ }
266
+ catch {
267
+ // ignore
268
+ }
269
+ resolve(false);
270
+ }, Math.max(50, timeoutMs + 25));
271
+ ws.once("open", () => {
272
+ clearTimeout(timer);
273
+ try {
274
+ ws.close();
275
+ }
276
+ catch {
277
+ // ignore
278
+ }
279
+ resolve(true);
280
+ });
281
+ ws.once("error", () => {
282
+ clearTimeout(timer);
283
+ resolve(false);
284
+ });
285
+ });
286
+ }
287
+ export async function isChromeCdpReady(cdpUrl, timeoutMs = 500, handshakeTimeoutMs = 800) {
288
+ const wsUrl = await getChromeWebSocketUrl(cdpUrl, timeoutMs);
289
+ if (!wsUrl)
290
+ return false;
291
+ return await canOpenWebSocket(wsUrl, handshakeTimeoutMs);
292
+ }
293
+ export async function launchClawdChrome(resolved, profile) {
294
+ if (!profile.cdpIsLoopback) {
295
+ throw new Error(`Profile "${profile.name}" is remote; cannot launch local Chrome.`);
296
+ }
297
+ await ensurePortAvailable(profile.cdpPort);
298
+ const exe = resolveBrowserExecutable(resolved);
299
+ if (!exe) {
300
+ throw new Error("No supported browser found (Chrome/Chromium on macOS or Linux).");
301
+ }
302
+ const userDataDir = resolveClawdUserDataDir(profile.name);
303
+ fs.mkdirSync(userDataDir, { recursive: true });
304
+ const needsDecorate = !isProfileDecorated(userDataDir, profile.name, (profile.color ?? DEFAULT_CLAWD_BROWSER_COLOR).toUpperCase());
305
+ // First launch to create preference files if missing, then decorate and relaunch.
306
+ const spawnOnce = () => {
307
+ const args = [
308
+ `--remote-debugging-port=${profile.cdpPort}`,
309
+ `--user-data-dir=${userDataDir}`,
310
+ "--no-first-run",
311
+ "--no-default-browser-check",
312
+ "--disable-sync",
313
+ "--disable-background-networking",
314
+ "--disable-component-update",
315
+ "--disable-features=Translate,MediaRouter",
316
+ "--password-store=basic",
317
+ ];
318
+ if (resolved.headless) {
319
+ // Best-effort; older Chromes may ignore.
320
+ args.push("--headless=new");
321
+ args.push("--disable-gpu");
322
+ }
323
+ if (resolved.noSandbox) {
324
+ args.push("--no-sandbox");
325
+ args.push("--disable-setuid-sandbox");
326
+ }
327
+ if (process.platform === "linux") {
328
+ args.push("--disable-dev-shm-usage");
329
+ }
330
+ // Always open a blank tab to ensure a target exists.
331
+ args.push("about:blank");
332
+ return spawn(exe.path, args, {
333
+ stdio: "pipe",
334
+ env: {
335
+ ...process.env,
336
+ // Reduce accidental sharing with the user's env.
337
+ HOME: os.homedir(),
338
+ },
339
+ });
340
+ };
341
+ const startedAt = Date.now();
342
+ const localStatePath = path.join(userDataDir, "Local State");
343
+ const preferencesPath = path.join(userDataDir, "Default", "Preferences");
344
+ const needsBootstrap = !exists(localStatePath) || !exists(preferencesPath);
345
+ // If the profile doesn't exist yet, bootstrap it once so Chrome creates defaults.
346
+ // Then decorate (if needed) before the "real" run.
347
+ if (needsBootstrap) {
348
+ const bootstrap = spawnOnce();
349
+ const deadline = Date.now() + 10_000;
350
+ while (Date.now() < deadline) {
351
+ if (exists(localStatePath) && exists(preferencesPath))
352
+ break;
353
+ await new Promise((r) => setTimeout(r, 100));
354
+ }
355
+ try {
356
+ bootstrap.kill("SIGTERM");
357
+ }
358
+ catch {
359
+ // ignore
360
+ }
361
+ const exitDeadline = Date.now() + 5000;
362
+ while (Date.now() < exitDeadline) {
363
+ if (bootstrap.exitCode != null)
364
+ break;
365
+ await new Promise((r) => setTimeout(r, 50));
366
+ }
367
+ }
368
+ if (needsDecorate) {
369
+ try {
370
+ decorateClawdProfile(userDataDir, {
371
+ name: profile.name,
372
+ color: profile.color,
373
+ });
374
+ log.info(`🦞 clawd browser profile decorated (${profile.color})`);
375
+ }
376
+ catch (err) {
377
+ log.warn(`clawd browser profile decoration failed: ${String(err)}`);
378
+ }
379
+ }
380
+ const proc = spawnOnce();
381
+ // Wait for CDP to come up.
382
+ const readyDeadline = Date.now() + 15_000;
383
+ while (Date.now() < readyDeadline) {
384
+ if (await isChromeReachable(profile.cdpUrl, 500))
385
+ break;
386
+ await new Promise((r) => setTimeout(r, 200));
387
+ }
388
+ if (!(await isChromeReachable(profile.cdpUrl, 500))) {
389
+ try {
390
+ proc.kill("SIGKILL");
391
+ }
392
+ catch {
393
+ // ignore
394
+ }
395
+ throw new Error(`Failed to start Chrome CDP on port ${profile.cdpPort} for profile "${profile.name}".`);
396
+ }
397
+ const pid = proc.pid ?? -1;
398
+ log.info(`🦞 clawd browser started (${exe.kind}) profile "${profile.name}" on 127.0.0.1:${profile.cdpPort} (pid ${pid})`);
399
+ return {
400
+ pid,
401
+ exe,
402
+ userDataDir,
403
+ cdpPort: profile.cdpPort,
404
+ startedAt,
405
+ proc,
406
+ };
407
+ }
408
+ export async function stopClawdChrome(running, timeoutMs = 2500) {
409
+ const proc = running.proc;
410
+ if (proc.killed)
411
+ return;
412
+ try {
413
+ proc.kill("SIGTERM");
414
+ }
415
+ catch {
416
+ // ignore
417
+ }
418
+ const start = Date.now();
419
+ while (Date.now() - start < timeoutMs) {
420
+ if (!proc.exitCode && proc.killed)
421
+ break;
422
+ if (!(await isChromeReachable(cdpUrlForPort(running.cdpPort), 200)))
423
+ return;
424
+ await new Promise((r) => setTimeout(r, 100));
425
+ }
426
+ try {
427
+ proc.kill("SIGKILL");
428
+ }
429
+ catch {
430
+ // ignore
431
+ }
432
+ }
@@ -0,0 +1,67 @@
1
+ import { fetchBrowserJson } from "./client-fetch.js";
2
+ function buildProfileQuery(profile) {
3
+ return profile ? `?profile=${encodeURIComponent(profile)}` : "";
4
+ }
5
+ export async function browserNavigate(baseUrl, opts) {
6
+ const q = buildProfileQuery(opts.profile);
7
+ return await fetchBrowserJson(`${baseUrl}/navigate${q}`, {
8
+ method: "POST",
9
+ headers: { "Content-Type": "application/json" },
10
+ body: JSON.stringify({ url: opts.url, targetId: opts.targetId }),
11
+ timeoutMs: 20000,
12
+ });
13
+ }
14
+ export async function browserArmDialog(baseUrl, opts) {
15
+ const q = buildProfileQuery(opts.profile);
16
+ return await fetchBrowserJson(`${baseUrl}/hooks/dialog${q}`, {
17
+ method: "POST",
18
+ headers: { "Content-Type": "application/json" },
19
+ body: JSON.stringify({
20
+ accept: opts.accept,
21
+ promptText: opts.promptText,
22
+ targetId: opts.targetId,
23
+ timeoutMs: opts.timeoutMs,
24
+ }),
25
+ timeoutMs: 20000,
26
+ });
27
+ }
28
+ export async function browserArmFileChooser(baseUrl, opts) {
29
+ const q = buildProfileQuery(opts.profile);
30
+ return await fetchBrowserJson(`${baseUrl}/hooks/file-chooser${q}`, {
31
+ method: "POST",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify({
34
+ paths: opts.paths,
35
+ ref: opts.ref,
36
+ inputRef: opts.inputRef,
37
+ element: opts.element,
38
+ targetId: opts.targetId,
39
+ timeoutMs: opts.timeoutMs,
40
+ }),
41
+ timeoutMs: 20000,
42
+ });
43
+ }
44
+ export async function browserAct(baseUrl, req, opts) {
45
+ const q = buildProfileQuery(opts?.profile);
46
+ return await fetchBrowserJson(`${baseUrl}/act${q}`, {
47
+ method: "POST",
48
+ headers: { "Content-Type": "application/json" },
49
+ body: JSON.stringify(req),
50
+ timeoutMs: 20000,
51
+ });
52
+ }
53
+ export async function browserScreenshotAction(baseUrl, opts) {
54
+ const q = buildProfileQuery(opts.profile);
55
+ return await fetchBrowserJson(`${baseUrl}/screenshot${q}`, {
56
+ method: "POST",
57
+ headers: { "Content-Type": "application/json" },
58
+ body: JSON.stringify({
59
+ targetId: opts.targetId,
60
+ fullPage: opts.fullPage,
61
+ ref: opts.ref,
62
+ element: opts.element,
63
+ type: opts.type,
64
+ }),
65
+ timeoutMs: 20000,
66
+ });
67
+ }
@@ -0,0 +1,24 @@
1
+ import { fetchBrowserJson } from "./client-fetch.js";
2
+ function buildProfileQuery(profile) {
3
+ return profile ? `?profile=${encodeURIComponent(profile)}` : "";
4
+ }
5
+ export async function browserConsoleMessages(baseUrl, opts = {}) {
6
+ const q = new URLSearchParams();
7
+ if (opts.level)
8
+ q.set("level", opts.level);
9
+ if (opts.targetId)
10
+ q.set("targetId", opts.targetId);
11
+ if (opts.profile)
12
+ q.set("profile", opts.profile);
13
+ const suffix = q.toString() ? `?${q.toString()}` : "";
14
+ return await fetchBrowserJson(`${baseUrl}/console${suffix}`, { timeoutMs: 20000 });
15
+ }
16
+ export async function browserPdfSave(baseUrl, opts = {}) {
17
+ const q = buildProfileQuery(opts.profile);
18
+ return await fetchBrowserJson(`${baseUrl}/pdf${q}`, {
19
+ method: "POST",
20
+ headers: { "Content-Type": "application/json" },
21
+ body: JSON.stringify({ targetId: opts.targetId }),
22
+ timeoutMs: 20000,
23
+ });
24
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from "./client-actions-core.js";
2
+ export * from "./client-actions-observe.js";
3
+ export * from "./client-actions-types.js";
@@ -0,0 +1,43 @@
1
+ import { extractErrorCode, formatErrorMessage } from "../infra/errors.js";
2
+ function unwrapCause(err) {
3
+ if (!err || typeof err !== "object")
4
+ return null;
5
+ const cause = err.cause;
6
+ return cause ?? null;
7
+ }
8
+ function enhanceBrowserFetchError(url, err, timeoutMs) {
9
+ const cause = unwrapCause(err);
10
+ const code = extractErrorCode(cause) ?? extractErrorCode(err) ?? "";
11
+ const hint = "Start (or restart) the Clawdbot gateway (Clawdbot.app menubar, or `clawdbot gateway`) and try again.";
12
+ if (code === "ECONNREFUSED") {
13
+ return new Error(`Can't reach the clawd browser control server at ${url} (connection refused). ${hint}`);
14
+ }
15
+ if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT") {
16
+ return new Error(`Can't reach the clawd browser control server at ${url} (timed out after ${timeoutMs}ms). ${hint}`);
17
+ }
18
+ const msg = formatErrorMessage(err);
19
+ if (msg.toLowerCase().includes("abort")) {
20
+ return new Error(`Can't reach the clawd browser control server at ${url} (timed out after ${timeoutMs}ms). ${hint}`);
21
+ }
22
+ return new Error(`Can't reach the clawd browser control server at ${url}. ${hint} (${msg})`);
23
+ }
24
+ export async function fetchBrowserJson(url, init) {
25
+ const timeoutMs = init?.timeoutMs ?? 5000;
26
+ const ctrl = new AbortController();
27
+ const t = setTimeout(() => ctrl.abort(), timeoutMs);
28
+ let res;
29
+ try {
30
+ res = await fetch(url, { ...init, signal: ctrl.signal });
31
+ }
32
+ catch (err) {
33
+ throw enhanceBrowserFetchError(url, err, timeoutMs);
34
+ }
35
+ finally {
36
+ clearTimeout(t);
37
+ }
38
+ if (!res.ok) {
39
+ const text = await res.text().catch(() => "");
40
+ throw new Error(text ? `${res.status}: ${text}` : `HTTP ${res.status}`);
41
+ }
42
+ return (await res.json());
43
+ }
@@ -0,0 +1,105 @@
1
+ import { loadConfig } from "../config/config.js";
2
+ import { fetchBrowserJson } from "./client-fetch.js";
3
+ import { resolveBrowserConfig } from "./config.js";
4
+ export function resolveBrowserControlUrl(overrideUrl) {
5
+ const cfg = loadConfig();
6
+ const resolved = resolveBrowserConfig(cfg.browser);
7
+ const url = overrideUrl?.trim() ? overrideUrl.trim() : resolved.controlUrl;
8
+ return url.replace(/\/$/, "");
9
+ }
10
+ function buildProfileQuery(profile) {
11
+ return profile ? `?profile=${encodeURIComponent(profile)}` : "";
12
+ }
13
+ export async function browserStatus(baseUrl, opts) {
14
+ const q = buildProfileQuery(opts?.profile);
15
+ return await fetchBrowserJson(`${baseUrl}/${q}`, {
16
+ timeoutMs: 1500,
17
+ });
18
+ }
19
+ export async function browserProfiles(baseUrl) {
20
+ const res = await fetchBrowserJson(`${baseUrl}/profiles`, { timeoutMs: 3000 });
21
+ return res.profiles ?? [];
22
+ }
23
+ export async function browserStart(baseUrl, opts) {
24
+ const q = buildProfileQuery(opts?.profile);
25
+ await fetchBrowserJson(`${baseUrl}/start${q}`, {
26
+ method: "POST",
27
+ timeoutMs: 15000,
28
+ });
29
+ }
30
+ export async function browserStop(baseUrl, opts) {
31
+ const q = buildProfileQuery(opts?.profile);
32
+ await fetchBrowserJson(`${baseUrl}/stop${q}`, {
33
+ method: "POST",
34
+ timeoutMs: 15000,
35
+ });
36
+ }
37
+ export async function browserResetProfile(baseUrl, opts) {
38
+ const q = buildProfileQuery(opts?.profile);
39
+ return await fetchBrowserJson(`${baseUrl}/reset-profile${q}`, {
40
+ method: "POST",
41
+ timeoutMs: 20000,
42
+ });
43
+ }
44
+ export async function browserCreateProfile(baseUrl, opts) {
45
+ return await fetchBrowserJson(`${baseUrl}/profiles/create`, {
46
+ method: "POST",
47
+ headers: { "Content-Type": "application/json" },
48
+ body: JSON.stringify({
49
+ name: opts.name,
50
+ color: opts.color,
51
+ cdpUrl: opts.cdpUrl,
52
+ }),
53
+ timeoutMs: 10000,
54
+ });
55
+ }
56
+ export async function browserDeleteProfile(baseUrl, profile) {
57
+ return await fetchBrowserJson(`${baseUrl}/profiles/${encodeURIComponent(profile)}`, {
58
+ method: "DELETE",
59
+ timeoutMs: 20000,
60
+ });
61
+ }
62
+ export async function browserTabs(baseUrl, opts) {
63
+ const q = buildProfileQuery(opts?.profile);
64
+ const res = await fetchBrowserJson(`${baseUrl}/tabs${q}`, { timeoutMs: 3000 });
65
+ return res.tabs ?? [];
66
+ }
67
+ export async function browserOpenTab(baseUrl, url, opts) {
68
+ const q = buildProfileQuery(opts?.profile);
69
+ return await fetchBrowserJson(`${baseUrl}/tabs/open${q}`, {
70
+ method: "POST",
71
+ headers: { "Content-Type": "application/json" },
72
+ body: JSON.stringify({ url }),
73
+ timeoutMs: 15000,
74
+ });
75
+ }
76
+ export async function browserFocusTab(baseUrl, targetId, opts) {
77
+ const q = buildProfileQuery(opts?.profile);
78
+ await fetchBrowserJson(`${baseUrl}/tabs/focus${q}`, {
79
+ method: "POST",
80
+ headers: { "Content-Type": "application/json" },
81
+ body: JSON.stringify({ targetId }),
82
+ timeoutMs: 5000,
83
+ });
84
+ }
85
+ export async function browserCloseTab(baseUrl, targetId, opts) {
86
+ const q = buildProfileQuery(opts?.profile);
87
+ await fetchBrowserJson(`${baseUrl}/tabs/${encodeURIComponent(targetId)}${q}`, {
88
+ method: "DELETE",
89
+ timeoutMs: 5000,
90
+ });
91
+ }
92
+ export async function browserSnapshot(baseUrl, opts) {
93
+ const q = new URLSearchParams();
94
+ q.set("format", opts.format);
95
+ if (opts.targetId)
96
+ q.set("targetId", opts.targetId);
97
+ if (typeof opts.limit === "number")
98
+ q.set("limit", String(opts.limit));
99
+ if (opts.profile)
100
+ q.set("profile", opts.profile);
101
+ return await fetchBrowserJson(`${baseUrl}/snapshot?${q.toString()}`, {
102
+ timeoutMs: 20000,
103
+ });
104
+ }
105
+ // Actions beyond the basic read-only commands live in client-actions.ts.