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,454 @@
1
+ import { danger } from "../globals.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
+ import { addGatewayClientOptions, callGatewayFromCli } from "./gateway-rpc.js";
4
+ async function warnIfCronSchedulerDisabled(opts) {
5
+ try {
6
+ const res = (await callGatewayFromCli("cron.status", opts, {}));
7
+ if (res?.enabled === true)
8
+ return;
9
+ const store = typeof res?.storePath === "string" ? res.storePath : "";
10
+ defaultRuntime.error([
11
+ "warning: cron scheduler is disabled in the Gateway; jobs are saved but will not run automatically.",
12
+ "Re-enable with `cron.enabled: true` (or remove `cron.enabled: false`) and restart the Gateway.",
13
+ store ? `store: ${store}` : "",
14
+ ]
15
+ .filter(Boolean)
16
+ .join("\n"));
17
+ }
18
+ catch {
19
+ // Ignore status failures (older gateway, offline, etc.)
20
+ }
21
+ }
22
+ function parseDurationMs(input) {
23
+ const raw = input.trim();
24
+ if (!raw)
25
+ return null;
26
+ const match = raw.match(/^(\d+(?:\.\d+)?)(ms|s|m|h|d)$/i);
27
+ if (!match)
28
+ return null;
29
+ const n = Number.parseFloat(match[1] ?? "");
30
+ if (!Number.isFinite(n) || n <= 0)
31
+ return null;
32
+ const unit = (match[2] ?? "").toLowerCase();
33
+ const factor = unit === "ms"
34
+ ? 1
35
+ : unit === "s"
36
+ ? 1000
37
+ : unit === "m"
38
+ ? 60_000
39
+ : unit === "h"
40
+ ? 3_600_000
41
+ : 86_400_000;
42
+ return Math.floor(n * factor);
43
+ }
44
+ function parseAtMs(input) {
45
+ const raw = input.trim();
46
+ if (!raw)
47
+ return null;
48
+ const asNum = Number(raw);
49
+ if (Number.isFinite(asNum) && asNum > 0)
50
+ return Math.floor(asNum);
51
+ const parsed = Date.parse(raw);
52
+ if (Number.isFinite(parsed))
53
+ return parsed;
54
+ const dur = parseDurationMs(raw);
55
+ if (dur)
56
+ return Date.now() + dur;
57
+ return null;
58
+ }
59
+ export function registerCronCli(program) {
60
+ addGatewayClientOptions(program
61
+ .command("wake")
62
+ .description("Enqueue a system event and optionally trigger an immediate heartbeat")
63
+ .requiredOption("--text <text>", "System event text")
64
+ .option("--mode <mode>", "Wake mode (now|next-heartbeat)", "next-heartbeat")
65
+ .option("--json", "Output JSON", false)).action(async (opts) => {
66
+ try {
67
+ const result = await callGatewayFromCli("wake", opts, { mode: opts.mode, text: opts.text }, { expectFinal: false });
68
+ if (opts.json)
69
+ defaultRuntime.log(JSON.stringify(result, null, 2));
70
+ else
71
+ defaultRuntime.log("ok");
72
+ }
73
+ catch (err) {
74
+ defaultRuntime.error(danger(String(err)));
75
+ defaultRuntime.exit(1);
76
+ }
77
+ });
78
+ const cron = program
79
+ .command("cron")
80
+ .description("Manage cron jobs (via Gateway)");
81
+ addGatewayClientOptions(cron
82
+ .command("status")
83
+ .description("Show cron scheduler status")
84
+ .option("--json", "Output JSON", false)
85
+ .action(async (opts) => {
86
+ try {
87
+ const res = await callGatewayFromCli("cron.status", opts, {});
88
+ defaultRuntime.log(JSON.stringify(res, null, 2));
89
+ }
90
+ catch (err) {
91
+ defaultRuntime.error(danger(String(err)));
92
+ defaultRuntime.exit(1);
93
+ }
94
+ }));
95
+ addGatewayClientOptions(cron
96
+ .command("list")
97
+ .description("List cron jobs")
98
+ .option("--all", "Include disabled jobs", false)
99
+ .option("--json", "Output JSON", false)
100
+ .action(async (opts) => {
101
+ try {
102
+ const res = await callGatewayFromCli("cron.list", opts, {
103
+ includeDisabled: Boolean(opts.all),
104
+ });
105
+ defaultRuntime.log(JSON.stringify(res, null, 2));
106
+ }
107
+ catch (err) {
108
+ defaultRuntime.error(danger(String(err)));
109
+ defaultRuntime.exit(1);
110
+ }
111
+ }));
112
+ addGatewayClientOptions(cron
113
+ .command("add")
114
+ .description("Add a cron job")
115
+ .requiredOption("--name <name>", "Job name")
116
+ .option("--description <text>", "Optional description")
117
+ .option("--disabled", "Create job disabled", false)
118
+ .option("--session <target>", "Session target (main|isolated)", "main")
119
+ .option("--wake <mode>", "Wake mode (now|next-heartbeat)", "next-heartbeat")
120
+ .option("--at <when>", "Run once at time (ISO) or +duration (e.g. 20m)")
121
+ .option("--every <duration>", "Run every duration (e.g. 10m, 1h)")
122
+ .option("--cron <expr>", "Cron expression (5-field)")
123
+ .option("--tz <iana>", "Timezone for cron expressions (IANA)", "")
124
+ .option("--system-event <text>", "System event payload (main session)")
125
+ .option("--message <text>", "Agent message payload")
126
+ .option("--thinking <level>", "Thinking level for agent jobs (off|minimal|low|medium|high)")
127
+ .option("--timeout-seconds <n>", "Timeout seconds for agent jobs")
128
+ .option("--deliver", "Deliver agent output", false)
129
+ .option("--channel <channel>", "Delivery channel (last|whatsapp|telegram|discord|signal|imessage)", "last")
130
+ .option("--to <dest>", "Delivery destination (E.164, Telegram chatId, or Discord channel/user)")
131
+ .option("--best-effort-deliver", "Do not fail the job if delivery fails", false)
132
+ .option("--post-prefix <prefix>", "Prefix for summary system event", "Cron")
133
+ .option("--json", "Output JSON", false)
134
+ .action(async (opts) => {
135
+ try {
136
+ const schedule = (() => {
137
+ const at = typeof opts.at === "string" ? opts.at : "";
138
+ const every = typeof opts.every === "string" ? opts.every : "";
139
+ const cronExpr = typeof opts.cron === "string" ? opts.cron : "";
140
+ const chosen = [
141
+ Boolean(at),
142
+ Boolean(every),
143
+ Boolean(cronExpr),
144
+ ].filter(Boolean).length;
145
+ if (chosen !== 1) {
146
+ throw new Error("Choose exactly one schedule: --at, --every, or --cron");
147
+ }
148
+ if (at) {
149
+ const atMs = parseAtMs(at);
150
+ if (!atMs)
151
+ throw new Error("Invalid --at; use ISO time or duration like 20m");
152
+ return { kind: "at", atMs };
153
+ }
154
+ if (every) {
155
+ const everyMs = parseDurationMs(every);
156
+ if (!everyMs)
157
+ throw new Error("Invalid --every; use e.g. 10m, 1h, 1d");
158
+ return { kind: "every", everyMs };
159
+ }
160
+ return {
161
+ kind: "cron",
162
+ expr: cronExpr,
163
+ tz: typeof opts.tz === "string" && opts.tz.trim()
164
+ ? opts.tz.trim()
165
+ : undefined,
166
+ };
167
+ })();
168
+ const sessionTarget = String(opts.session ?? "main");
169
+ if (sessionTarget !== "main" && sessionTarget !== "isolated") {
170
+ throw new Error("--session must be main or isolated");
171
+ }
172
+ const wakeMode = String(opts.wake ?? "next-heartbeat");
173
+ if (wakeMode !== "now" && wakeMode !== "next-heartbeat") {
174
+ throw new Error("--wake must be now or next-heartbeat");
175
+ }
176
+ const payload = (() => {
177
+ const systemEvent = typeof opts.systemEvent === "string"
178
+ ? opts.systemEvent.trim()
179
+ : "";
180
+ const message = typeof opts.message === "string" ? opts.message.trim() : "";
181
+ const chosen = [Boolean(systemEvent), Boolean(message)].filter(Boolean).length;
182
+ if (chosen !== 1) {
183
+ throw new Error("Choose exactly one payload: --system-event or --message");
184
+ }
185
+ if (systemEvent)
186
+ return { kind: "systemEvent", text: systemEvent };
187
+ const timeoutSeconds = opts.timeoutSeconds
188
+ ? Number.parseInt(String(opts.timeoutSeconds), 10)
189
+ : undefined;
190
+ return {
191
+ kind: "agentTurn",
192
+ message,
193
+ thinking: typeof opts.thinking === "string" && opts.thinking.trim()
194
+ ? opts.thinking.trim()
195
+ : undefined,
196
+ timeoutSeconds: timeoutSeconds && Number.isFinite(timeoutSeconds)
197
+ ? timeoutSeconds
198
+ : undefined,
199
+ deliver: Boolean(opts.deliver),
200
+ channel: typeof opts.channel === "string" ? opts.channel : "last",
201
+ to: typeof opts.to === "string" && opts.to.trim()
202
+ ? opts.to.trim()
203
+ : undefined,
204
+ bestEffortDeliver: Boolean(opts.bestEffortDeliver),
205
+ };
206
+ })();
207
+ if (sessionTarget === "main" && payload.kind !== "systemEvent") {
208
+ throw new Error("Main jobs require --system-event (systemEvent).");
209
+ }
210
+ if (sessionTarget === "isolated" && payload.kind !== "agentTurn") {
211
+ throw new Error("Isolated jobs require --message (agentTurn).");
212
+ }
213
+ const isolation = sessionTarget === "isolated"
214
+ ? {
215
+ postToMainPrefix: typeof opts.postPrefix === "string" &&
216
+ opts.postPrefix.trim()
217
+ ? opts.postPrefix.trim()
218
+ : "Cron",
219
+ }
220
+ : undefined;
221
+ const name = String(opts.name ?? "").trim();
222
+ if (!name)
223
+ throw new Error("--name is required");
224
+ const description = typeof opts.description === "string" && opts.description.trim()
225
+ ? opts.description.trim()
226
+ : undefined;
227
+ const params = {
228
+ name,
229
+ description,
230
+ enabled: !opts.disabled,
231
+ schedule,
232
+ sessionTarget,
233
+ wakeMode,
234
+ payload,
235
+ isolation,
236
+ };
237
+ const res = await callGatewayFromCli("cron.add", opts, params);
238
+ defaultRuntime.log(JSON.stringify(res, null, 2));
239
+ await warnIfCronSchedulerDisabled(opts);
240
+ }
241
+ catch (err) {
242
+ defaultRuntime.error(danger(String(err)));
243
+ defaultRuntime.exit(1);
244
+ }
245
+ }));
246
+ addGatewayClientOptions(cron
247
+ .command("rm")
248
+ .description("Remove a cron job")
249
+ .argument("<id>", "Job id")
250
+ .option("--json", "Output JSON", false)
251
+ .action(async (id, opts) => {
252
+ try {
253
+ const res = await callGatewayFromCli("cron.remove", opts, { id });
254
+ defaultRuntime.log(JSON.stringify(res, null, 2));
255
+ }
256
+ catch (err) {
257
+ defaultRuntime.error(danger(String(err)));
258
+ defaultRuntime.exit(1);
259
+ }
260
+ }));
261
+ addGatewayClientOptions(cron
262
+ .command("enable")
263
+ .description("Enable a cron job")
264
+ .argument("<id>", "Job id")
265
+ .action(async (id, opts) => {
266
+ try {
267
+ const res = await callGatewayFromCli("cron.update", opts, {
268
+ id,
269
+ patch: { enabled: true },
270
+ });
271
+ defaultRuntime.log(JSON.stringify(res, null, 2));
272
+ await warnIfCronSchedulerDisabled(opts);
273
+ }
274
+ catch (err) {
275
+ defaultRuntime.error(danger(String(err)));
276
+ defaultRuntime.exit(1);
277
+ }
278
+ }));
279
+ addGatewayClientOptions(cron
280
+ .command("disable")
281
+ .description("Disable a cron job")
282
+ .argument("<id>", "Job id")
283
+ .action(async (id, opts) => {
284
+ try {
285
+ const res = await callGatewayFromCli("cron.update", opts, {
286
+ id,
287
+ patch: { enabled: false },
288
+ });
289
+ defaultRuntime.log(JSON.stringify(res, null, 2));
290
+ await warnIfCronSchedulerDisabled(opts);
291
+ }
292
+ catch (err) {
293
+ defaultRuntime.error(danger(String(err)));
294
+ defaultRuntime.exit(1);
295
+ }
296
+ }));
297
+ addGatewayClientOptions(cron
298
+ .command("runs")
299
+ .description("Show cron run history (JSONL-backed)")
300
+ .requiredOption("--id <id>", "Job id")
301
+ .option("--limit <n>", "Max entries (default 50)", "50")
302
+ .action(async (opts) => {
303
+ try {
304
+ const limitRaw = Number.parseInt(String(opts.limit ?? "50"), 10);
305
+ const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? limitRaw : 50;
306
+ const id = String(opts.id);
307
+ const res = await callGatewayFromCli("cron.runs", opts, {
308
+ id,
309
+ limit,
310
+ });
311
+ defaultRuntime.log(JSON.stringify(res, null, 2));
312
+ }
313
+ catch (err) {
314
+ defaultRuntime.error(danger(String(err)));
315
+ defaultRuntime.exit(1);
316
+ }
317
+ }));
318
+ addGatewayClientOptions(cron
319
+ .command("edit")
320
+ .description("Edit a cron job (patch fields)")
321
+ .argument("<id>", "Job id")
322
+ .option("--name <name>", "Set name")
323
+ .option("--description <text>", "Set description")
324
+ .option("--enable", "Enable job", false)
325
+ .option("--disable", "Disable job", false)
326
+ .option("--session <target>", "Session target (main|isolated)")
327
+ .option("--wake <mode>", "Wake mode (now|next-heartbeat)")
328
+ .option("--at <when>", "Set one-shot time (ISO) or duration like 20m")
329
+ .option("--every <duration>", "Set interval duration like 10m")
330
+ .option("--cron <expr>", "Set cron expression")
331
+ .option("--tz <iana>", "Timezone for cron expressions (IANA)")
332
+ .option("--system-event <text>", "Set systemEvent payload")
333
+ .option("--message <text>", "Set agentTurn payload message")
334
+ .option("--thinking <level>", "Thinking level for agent jobs")
335
+ .option("--timeout-seconds <n>", "Timeout seconds for agent jobs")
336
+ .option("--deliver", "Deliver agent output", false)
337
+ .option("--channel <channel>", "Delivery channel (last|whatsapp|telegram|discord|signal|imessage)")
338
+ .option("--to <dest>", "Delivery destination (E.164, Telegram chatId, or Discord channel/user)")
339
+ .option("--best-effort-deliver", "Do not fail job if delivery fails", false)
340
+ .option("--post-prefix <prefix>", "Prefix for summary system event")
341
+ .action(async (id, opts) => {
342
+ try {
343
+ if (opts.session === "main" && opts.message) {
344
+ throw new Error("Main jobs cannot use --message; use --system-event or --session isolated.");
345
+ }
346
+ if (opts.session === "isolated" && opts.systemEvent) {
347
+ throw new Error("Isolated jobs cannot use --system-event; use --message or --session main.");
348
+ }
349
+ if (opts.session === "main" && typeof opts.postPrefix === "string") {
350
+ throw new Error("--post-prefix only applies to isolated jobs.");
351
+ }
352
+ const patch = {};
353
+ if (typeof opts.name === "string")
354
+ patch.name = opts.name;
355
+ if (typeof opts.description === "string")
356
+ patch.description = opts.description;
357
+ if (opts.enable && opts.disable)
358
+ throw new Error("Choose --enable or --disable, not both");
359
+ if (opts.enable)
360
+ patch.enabled = true;
361
+ if (opts.disable)
362
+ patch.enabled = false;
363
+ if (typeof opts.session === "string")
364
+ patch.sessionTarget = opts.session;
365
+ if (typeof opts.wake === "string")
366
+ patch.wakeMode = opts.wake;
367
+ const scheduleChosen = [opts.at, opts.every, opts.cron].filter(Boolean).length;
368
+ if (scheduleChosen > 1)
369
+ throw new Error("Choose at most one schedule change");
370
+ if (opts.at) {
371
+ const atMs = parseAtMs(String(opts.at));
372
+ if (!atMs)
373
+ throw new Error("Invalid --at");
374
+ patch.schedule = { kind: "at", atMs };
375
+ }
376
+ else if (opts.every) {
377
+ const everyMs = parseDurationMs(String(opts.every));
378
+ if (!everyMs)
379
+ throw new Error("Invalid --every");
380
+ patch.schedule = { kind: "every", everyMs };
381
+ }
382
+ else if (opts.cron) {
383
+ patch.schedule = {
384
+ kind: "cron",
385
+ expr: String(opts.cron),
386
+ tz: typeof opts.tz === "string" && opts.tz.trim()
387
+ ? opts.tz.trim()
388
+ : undefined,
389
+ };
390
+ }
391
+ const payloadChosen = [opts.systemEvent, opts.message].filter(Boolean).length;
392
+ if (payloadChosen > 1)
393
+ throw new Error("Choose at most one payload change");
394
+ if (opts.systemEvent) {
395
+ patch.payload = {
396
+ kind: "systemEvent",
397
+ text: String(opts.systemEvent),
398
+ };
399
+ }
400
+ else if (opts.message) {
401
+ const timeoutSeconds = opts.timeoutSeconds
402
+ ? Number.parseInt(String(opts.timeoutSeconds), 10)
403
+ : undefined;
404
+ patch.payload = {
405
+ kind: "agentTurn",
406
+ message: String(opts.message),
407
+ thinking: typeof opts.thinking === "string" ? opts.thinking : undefined,
408
+ timeoutSeconds: timeoutSeconds && Number.isFinite(timeoutSeconds)
409
+ ? timeoutSeconds
410
+ : undefined,
411
+ deliver: Boolean(opts.deliver),
412
+ channel: typeof opts.channel === "string" ? opts.channel : undefined,
413
+ to: typeof opts.to === "string" ? opts.to : undefined,
414
+ bestEffortDeliver: Boolean(opts.bestEffortDeliver),
415
+ };
416
+ }
417
+ if (typeof opts.postPrefix === "string") {
418
+ patch.isolation = {
419
+ postToMainPrefix: opts.postPrefix.trim()
420
+ ? opts.postPrefix
421
+ : "Cron",
422
+ };
423
+ }
424
+ const res = await callGatewayFromCli("cron.update", opts, {
425
+ id,
426
+ patch,
427
+ });
428
+ defaultRuntime.log(JSON.stringify(res, null, 2));
429
+ await warnIfCronSchedulerDisabled(opts);
430
+ }
431
+ catch (err) {
432
+ defaultRuntime.error(danger(String(err)));
433
+ defaultRuntime.exit(1);
434
+ }
435
+ }));
436
+ addGatewayClientOptions(cron
437
+ .command("run")
438
+ .description("Run a cron job now (debug)")
439
+ .argument("<id>", "Job id")
440
+ .option("--force", "Run even if not due", false)
441
+ .action(async (id, opts) => {
442
+ try {
443
+ const res = await callGatewayFromCli("cron.run", opts, {
444
+ id,
445
+ mode: opts.force ? "force" : "due",
446
+ });
447
+ defaultRuntime.log(JSON.stringify(res, null, 2));
448
+ }
449
+ catch (err) {
450
+ defaultRuntime.error(danger(String(err)));
451
+ defaultRuntime.exit(1);
452
+ }
453
+ }));
454
+ }
@@ -0,0 +1,17 @@
1
+ import { sendMessageDiscord } from "../discord/send.js";
2
+ import { sendMessageIMessage } from "../imessage/send.js";
3
+ import { logWebSelfId, sendMessageWhatsApp } from "../providers/web/index.js";
4
+ import { sendMessageSignal } from "../signal/send.js";
5
+ import { sendMessageSlack } from "../slack/send.js";
6
+ import { sendMessageTelegram } from "../telegram/send.js";
7
+ export function createDefaultDeps() {
8
+ return {
9
+ sendMessageWhatsApp,
10
+ sendMessageTelegram,
11
+ sendMessageDiscord,
12
+ sendMessageSlack,
13
+ sendMessageSignal,
14
+ sendMessageIMessage,
15
+ };
16
+ }
17
+ export { logWebSelfId };
@@ -0,0 +1,180 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { loadConfig } from "../config/config.js";
5
+ import { pickPrimaryTailnetIPv4, pickPrimaryTailnetIPv6, } from "../infra/tailnet.js";
6
+ import { getWideAreaZonePath, WIDE_AREA_DISCOVERY_DOMAIN, } from "../infra/widearea-dns.js";
7
+ function run(cmd, args, opts) {
8
+ const res = spawnSync(cmd, args, {
9
+ encoding: "utf-8",
10
+ stdio: opts?.inherit ? "inherit" : "pipe",
11
+ });
12
+ if (res.error)
13
+ throw res.error;
14
+ if (!opts?.allowFailure && res.status !== 0) {
15
+ const errText = typeof res.stderr === "string" && res.stderr.trim()
16
+ ? res.stderr.trim()
17
+ : `exit ${res.status ?? "unknown"}`;
18
+ throw new Error(`${cmd} ${args.join(" ")} failed: ${errText}`);
19
+ }
20
+ return typeof res.stdout === "string" ? res.stdout : "";
21
+ }
22
+ function writeFileSudoIfNeeded(filePath, content) {
23
+ try {
24
+ fs.writeFileSync(filePath, content, "utf-8");
25
+ return;
26
+ }
27
+ catch (err) {
28
+ const code = err.code;
29
+ if (code !== "EACCES" && code !== "EPERM") {
30
+ throw err instanceof Error ? err : new Error(String(err));
31
+ }
32
+ }
33
+ const res = spawnSync("sudo", ["tee", filePath], {
34
+ input: content,
35
+ encoding: "utf-8",
36
+ stdio: ["pipe", "ignore", "inherit"],
37
+ });
38
+ if (res.error)
39
+ throw res.error;
40
+ if (res.status !== 0) {
41
+ throw new Error(`sudo tee ${filePath} failed: exit ${res.status ?? "unknown"}`);
42
+ }
43
+ }
44
+ function mkdirSudoIfNeeded(dirPath) {
45
+ try {
46
+ fs.mkdirSync(dirPath, { recursive: true });
47
+ return;
48
+ }
49
+ catch (err) {
50
+ const code = err.code;
51
+ if (code !== "EACCES" && code !== "EPERM") {
52
+ throw err instanceof Error ? err : new Error(String(err));
53
+ }
54
+ }
55
+ run("sudo", ["mkdir", "-p", dirPath], { inherit: true });
56
+ }
57
+ function zoneFileNeedsBootstrap(zonePath) {
58
+ if (!fs.existsSync(zonePath))
59
+ return true;
60
+ try {
61
+ const content = fs.readFileSync(zonePath, "utf-8");
62
+ return !/\bSOA\b/.test(content) || !/\bNS\b/.test(content);
63
+ }
64
+ catch {
65
+ return true;
66
+ }
67
+ }
68
+ function detectBrewPrefix() {
69
+ const out = run("brew", ["--prefix"]);
70
+ const prefix = out.trim();
71
+ if (!prefix)
72
+ throw new Error("failed to resolve Homebrew prefix");
73
+ return prefix;
74
+ }
75
+ function ensureImportLine(corefilePath, importGlob) {
76
+ const existing = fs.readFileSync(corefilePath, "utf-8");
77
+ if (existing.includes(importGlob))
78
+ return false;
79
+ const next = `${existing.replace(/\s*$/, "")}\n\nimport ${importGlob}\n`;
80
+ writeFileSudoIfNeeded(corefilePath, next);
81
+ return true;
82
+ }
83
+ export function registerDnsCli(program) {
84
+ const dns = program
85
+ .command("dns")
86
+ .description("DNS helpers for wide-area discovery (Tailscale + CoreDNS)");
87
+ dns
88
+ .command("setup")
89
+ .description("Set up CoreDNS to serve clawdbot.internal for unicast DNS-SD (Wide-Area Bonjour)")
90
+ .option("--apply", "Install/update CoreDNS config and (re)start the service (requires sudo)", false)
91
+ .action(async (opts) => {
92
+ const cfg = loadConfig();
93
+ const tailnetIPv4 = pickPrimaryTailnetIPv4();
94
+ const tailnetIPv6 = pickPrimaryTailnetIPv6();
95
+ const zonePath = getWideAreaZonePath();
96
+ console.log(`Domain: ${WIDE_AREA_DISCOVERY_DOMAIN}`);
97
+ console.log(`Zone file (gateway-owned): ${zonePath}`);
98
+ console.log(`Detected tailnet IP: ${tailnetIPv4 ?? "—"}${tailnetIPv6 ? ` (v6 ${tailnetIPv6})` : ""}`);
99
+ console.log("");
100
+ console.log("Recommended ~/.clawdbot/clawdbot.json:");
101
+ console.log(JSON.stringify({
102
+ bridge: { bind: "tailnet" },
103
+ discovery: { wideArea: { enabled: true } },
104
+ }, null, 2));
105
+ console.log("");
106
+ console.log("Tailscale admin (DNS → Nameservers):");
107
+ console.log(`- Add nameserver: ${tailnetIPv4 ?? "<this machine's tailnet IPv4>"}`);
108
+ console.log(`- Restrict to domain (Split DNS): clawdbot.internal`);
109
+ if (!opts.apply) {
110
+ console.log("");
111
+ console.log("Run with --apply to install CoreDNS and configure it.");
112
+ return;
113
+ }
114
+ if (process.platform !== "darwin") {
115
+ throw new Error("dns setup is currently supported on macOS only");
116
+ }
117
+ if (!tailnetIPv4 && !tailnetIPv6) {
118
+ throw new Error("no tailnet IP detected; ensure Tailscale is running on this machine");
119
+ }
120
+ const prefix = detectBrewPrefix();
121
+ const etcDir = path.join(prefix, "etc", "coredns");
122
+ const corefilePath = path.join(etcDir, "Corefile");
123
+ const confDir = path.join(etcDir, "conf.d");
124
+ const importGlob = path.join(confDir, "*.server");
125
+ const serverPath = path.join(confDir, "clawdbot.internal.server");
126
+ run("brew", ["list", "coredns"], { allowFailure: true });
127
+ run("brew", ["install", "coredns"], {
128
+ inherit: true,
129
+ allowFailure: true,
130
+ });
131
+ mkdirSudoIfNeeded(confDir);
132
+ if (!fs.existsSync(corefilePath)) {
133
+ writeFileSudoIfNeeded(corefilePath, `import ${importGlob}\n`);
134
+ }
135
+ else {
136
+ ensureImportLine(corefilePath, importGlob);
137
+ }
138
+ const bindArgs = [tailnetIPv4, tailnetIPv6].filter((v) => Boolean(v?.trim()));
139
+ const server = [
140
+ `${WIDE_AREA_DISCOVERY_DOMAIN.replace(/\.$/, "")}:53 {`,
141
+ ` bind ${bindArgs.join(" ")}`,
142
+ ` file ${zonePath} {`,
143
+ ` reload 10s`,
144
+ ` }`,
145
+ ` errors`,
146
+ ` log`,
147
+ `}`,
148
+ ``,
149
+ ].join("\n");
150
+ writeFileSudoIfNeeded(serverPath, server);
151
+ // Ensure the gateway can write its zone file path.
152
+ await fs.promises.mkdir(path.dirname(zonePath), { recursive: true });
153
+ if (zoneFileNeedsBootstrap(zonePath)) {
154
+ const y = new Date().getUTCFullYear();
155
+ const m = String(new Date().getUTCMonth() + 1).padStart(2, "0");
156
+ const d = String(new Date().getUTCDate()).padStart(2, "0");
157
+ const serial = `${y}${m}${d}01`;
158
+ const zoneLines = [
159
+ `; created by clawdbot dns setup (will be overwritten by the gateway when wide-area discovery is enabled)`,
160
+ `$ORIGIN ${WIDE_AREA_DISCOVERY_DOMAIN}`,
161
+ `$TTL 60`,
162
+ `@ IN SOA ns1 hostmaster ${serial} 7200 3600 1209600 60`,
163
+ `@ IN NS ns1`,
164
+ tailnetIPv4 ? `ns1 IN A ${tailnetIPv4}` : null,
165
+ tailnetIPv6 ? `ns1 IN AAAA ${tailnetIPv6}` : null,
166
+ ``,
167
+ ].filter((line) => Boolean(line));
168
+ fs.writeFileSync(zonePath, zoneLines.join("\n"), "utf-8");
169
+ }
170
+ console.log("");
171
+ console.log("Starting CoreDNS (sudo)…");
172
+ run("sudo", ["brew", "services", "restart", "coredns"], {
173
+ inherit: true,
174
+ });
175
+ if (cfg.discovery?.wideArea?.enabled !== true) {
176
+ console.log("");
177
+ console.log("Note: enable discovery.wideArea.enabled in ~/.clawdbot/clawdbot.json on the gateway and restart the gateway so it writes the DNS-SD zone.");
178
+ }
179
+ });
180
+ }