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,489 @@
1
+ import fs from "node:fs";
2
+ import { CONFIG_PATH_CLAWDBOT, loadConfig, resolveGatewayPort, } from "../config/config.js";
3
+ import { callGateway, randomIdempotencyKey } from "../gateway/call.js";
4
+ import { startGatewayServer } from "../gateway/server.js";
5
+ import { setGatewayWsLogStyle, } from "../gateway/ws-logging.js";
6
+ import { setVerbose } from "../globals.js";
7
+ import { GatewayLockError } from "../infra/gateway-lock.js";
8
+ import { createSubsystemLogger } from "../logging.js";
9
+ import { defaultRuntime } from "../runtime.js";
10
+ import { createDefaultDeps } from "./deps.js";
11
+ import { forceFreePortAndWait } from "./ports.js";
12
+ const gatewayLog = createSubsystemLogger("gateway");
13
+ function parsePort(raw) {
14
+ if (raw === undefined || raw === null)
15
+ return null;
16
+ const value = typeof raw === "string"
17
+ ? raw
18
+ : typeof raw === "number" || typeof raw === "bigint"
19
+ ? raw.toString()
20
+ : null;
21
+ if (value === null)
22
+ return null;
23
+ const parsed = Number.parseInt(value, 10);
24
+ if (!Number.isFinite(parsed) || parsed <= 0)
25
+ return null;
26
+ return parsed;
27
+ }
28
+ async function runGatewayLoop(params) {
29
+ let server = null;
30
+ let shuttingDown = false;
31
+ let restartResolver = null;
32
+ const cleanupSignals = () => {
33
+ process.removeListener("SIGTERM", onSigterm);
34
+ process.removeListener("SIGINT", onSigint);
35
+ process.removeListener("SIGUSR1", onSigusr1);
36
+ };
37
+ const request = (action, signal) => {
38
+ if (shuttingDown) {
39
+ gatewayLog.info(`received ${signal} during shutdown; ignoring`);
40
+ return;
41
+ }
42
+ shuttingDown = true;
43
+ const isRestart = action === "restart";
44
+ gatewayLog.info(`received ${signal}; ${isRestart ? "restarting" : "shutting down"}`);
45
+ const forceExitTimer = setTimeout(() => {
46
+ gatewayLog.error("shutdown timed out; exiting without full cleanup");
47
+ cleanupSignals();
48
+ params.runtime.exit(0);
49
+ }, 5000);
50
+ void (async () => {
51
+ try {
52
+ await server?.close({
53
+ reason: isRestart ? "gateway restarting" : "gateway stopping",
54
+ restartExpectedMs: isRestart ? 1500 : null,
55
+ });
56
+ }
57
+ catch (err) {
58
+ gatewayLog.error(`shutdown error: ${String(err)}`);
59
+ }
60
+ finally {
61
+ clearTimeout(forceExitTimer);
62
+ server = null;
63
+ if (isRestart) {
64
+ shuttingDown = false;
65
+ restartResolver?.();
66
+ }
67
+ else {
68
+ cleanupSignals();
69
+ params.runtime.exit(0);
70
+ }
71
+ }
72
+ })();
73
+ };
74
+ const onSigterm = () => request("stop", "SIGTERM");
75
+ const onSigint = () => request("stop", "SIGINT");
76
+ const onSigusr1 = () => request("restart", "SIGUSR1");
77
+ process.on("SIGTERM", onSigterm);
78
+ process.on("SIGINT", onSigint);
79
+ process.on("SIGUSR1", onSigusr1);
80
+ try {
81
+ // Keep process alive; SIGUSR1 triggers an in-process restart (no supervisor required).
82
+ // SIGTERM/SIGINT still exit after a graceful shutdown.
83
+ // eslint-disable-next-line no-constant-condition
84
+ while (true) {
85
+ server = await params.start();
86
+ await new Promise((resolve) => {
87
+ restartResolver = resolve;
88
+ });
89
+ }
90
+ }
91
+ finally {
92
+ cleanupSignals();
93
+ }
94
+ }
95
+ const gatewayCallOpts = (cmd) => cmd
96
+ .option("--url <url>", "Gateway WebSocket URL (defaults to gateway.remote.url when configured)")
97
+ .option("--token <token>", "Gateway token (if required)")
98
+ .option("--password <password>", "Gateway password (password auth)")
99
+ .option("--timeout <ms>", "Timeout in ms", "10000")
100
+ .option("--expect-final", "Wait for final response (agent)", false);
101
+ const callGatewayCli = async (method, opts, params) => callGateway({
102
+ url: opts.url,
103
+ token: opts.token,
104
+ password: opts.password,
105
+ method,
106
+ params,
107
+ expectFinal: Boolean(opts.expectFinal),
108
+ timeoutMs: Number(opts.timeout ?? 10_000),
109
+ clientName: "cli",
110
+ mode: "cli",
111
+ });
112
+ export function registerGatewayCli(program) {
113
+ program
114
+ .command("gateway-daemon")
115
+ .description("Run the WebSocket Gateway as a long-lived daemon")
116
+ .option("--port <port>", "Port for the gateway WebSocket", "18789")
117
+ .option("--bind <mode>", 'Bind mode ("loopback"|"tailnet"|"lan"|"auto"). Defaults to config gateway.bind (or loopback).')
118
+ .option("--token <token>", "Shared token required in connect.params.auth.token (default: CLAWDBOT_GATEWAY_TOKEN env if set)")
119
+ .option("--auth <mode>", 'Gateway auth mode ("token"|"password")')
120
+ .option("--password <password>", "Password for auth mode=password")
121
+ .option("--tailscale <mode>", 'Tailscale exposure mode ("off"|"serve"|"funnel")')
122
+ .option("--tailscale-reset-on-exit", "Reset Tailscale serve/funnel configuration on shutdown", false)
123
+ .option("--verbose", "Verbose logging to stdout/stderr", false)
124
+ .option("--ws-log <style>", 'WebSocket log style ("auto"|"full"|"compact")', "auto")
125
+ .option("--compact", 'Alias for "--ws-log compact"', false)
126
+ .action(async (opts) => {
127
+ setVerbose(Boolean(opts.verbose));
128
+ const wsLogRaw = (opts.compact ? "compact" : opts.wsLog);
129
+ const wsLogStyle = wsLogRaw === "compact"
130
+ ? "compact"
131
+ : wsLogRaw === "full"
132
+ ? "full"
133
+ : "auto";
134
+ if (wsLogRaw !== undefined &&
135
+ wsLogRaw !== "auto" &&
136
+ wsLogRaw !== "compact" &&
137
+ wsLogRaw !== "full") {
138
+ defaultRuntime.error('Invalid --ws-log (use "auto", "full", "compact")');
139
+ defaultRuntime.exit(1);
140
+ }
141
+ setGatewayWsLogStyle(wsLogStyle);
142
+ const cfg = loadConfig();
143
+ const portOverride = parsePort(opts.port);
144
+ if (opts.port !== undefined && portOverride === null) {
145
+ defaultRuntime.error("Invalid port");
146
+ defaultRuntime.exit(1);
147
+ return;
148
+ }
149
+ const port = portOverride ?? resolveGatewayPort(cfg);
150
+ if (!Number.isFinite(port) || port <= 0) {
151
+ defaultRuntime.error("Invalid port");
152
+ defaultRuntime.exit(1);
153
+ return;
154
+ }
155
+ if (opts.token) {
156
+ process.env.CLAWDBOT_GATEWAY_TOKEN = String(opts.token);
157
+ }
158
+ const authModeRaw = opts.auth ? String(opts.auth) : undefined;
159
+ const authMode = authModeRaw === "token" || authModeRaw === "password"
160
+ ? authModeRaw
161
+ : null;
162
+ if (authModeRaw && !authMode) {
163
+ defaultRuntime.error('Invalid --auth (use "token" or "password")');
164
+ defaultRuntime.exit(1);
165
+ return;
166
+ }
167
+ const tailscaleRaw = opts.tailscale ? String(opts.tailscale) : undefined;
168
+ const tailscaleMode = tailscaleRaw === "off" ||
169
+ tailscaleRaw === "serve" ||
170
+ tailscaleRaw === "funnel"
171
+ ? tailscaleRaw
172
+ : null;
173
+ if (tailscaleRaw && !tailscaleMode) {
174
+ defaultRuntime.error('Invalid --tailscale (use "off", "serve", or "funnel")');
175
+ defaultRuntime.exit(1);
176
+ return;
177
+ }
178
+ const bindRaw = String(opts.bind ?? cfg.gateway?.bind ?? "loopback");
179
+ const bind = bindRaw === "loopback" ||
180
+ bindRaw === "tailnet" ||
181
+ bindRaw === "lan" ||
182
+ bindRaw === "auto"
183
+ ? bindRaw
184
+ : null;
185
+ if (!bind) {
186
+ defaultRuntime.error('Invalid --bind (use "loopback", "tailnet", "lan", or "auto")');
187
+ defaultRuntime.exit(1);
188
+ return;
189
+ }
190
+ try {
191
+ await runGatewayLoop({
192
+ runtime: defaultRuntime,
193
+ start: async () => await startGatewayServer(port, {
194
+ bind,
195
+ auth: authMode || opts.password || authModeRaw
196
+ ? {
197
+ mode: authMode ?? undefined,
198
+ password: opts.password
199
+ ? String(opts.password)
200
+ : undefined,
201
+ }
202
+ : undefined,
203
+ tailscale: tailscaleMode || opts.tailscaleResetOnExit
204
+ ? {
205
+ mode: tailscaleMode ?? undefined,
206
+ resetOnExit: Boolean(opts.tailscaleResetOnExit),
207
+ }
208
+ : undefined,
209
+ }),
210
+ });
211
+ }
212
+ catch (err) {
213
+ if (err instanceof GatewayLockError) {
214
+ defaultRuntime.error(`Gateway failed to start: ${err.message}`);
215
+ defaultRuntime.exit(1);
216
+ return;
217
+ }
218
+ defaultRuntime.error(`Gateway failed to start: ${String(err)}`);
219
+ defaultRuntime.exit(1);
220
+ }
221
+ });
222
+ const gateway = program
223
+ .command("gateway")
224
+ .description("Run the WebSocket Gateway")
225
+ .option("--port <port>", "Port for the gateway WebSocket", "18789")
226
+ .option("--bind <mode>", 'Bind mode ("loopback"|"tailnet"|"lan"|"auto"). Defaults to config gateway.bind (or loopback).')
227
+ .option("--token <token>", "Shared token required in connect.params.auth.token (default: CLAWDBOT_GATEWAY_TOKEN env if set)")
228
+ .option("--auth <mode>", 'Gateway auth mode ("token"|"password")')
229
+ .option("--password <password>", "Password for auth mode=password")
230
+ .option("--tailscale <mode>", 'Tailscale exposure mode ("off"|"serve"|"funnel")')
231
+ .option("--tailscale-reset-on-exit", "Reset Tailscale serve/funnel configuration on shutdown", false)
232
+ .option("--allow-unconfigured", "Allow gateway start without gateway.mode=local in config", false)
233
+ .option("--force", "Kill any existing listener on the target port before starting", false)
234
+ .option("--verbose", "Verbose logging to stdout/stderr", false)
235
+ .option("--ws-log <style>", 'WebSocket log style ("auto"|"full"|"compact")', "auto")
236
+ .option("--compact", 'Alias for "--ws-log compact"', false)
237
+ .action(async (opts) => {
238
+ setVerbose(Boolean(opts.verbose));
239
+ const wsLogRaw = (opts.compact ? "compact" : opts.wsLog);
240
+ const wsLogStyle = wsLogRaw === "compact"
241
+ ? "compact"
242
+ : wsLogRaw === "full"
243
+ ? "full"
244
+ : "auto";
245
+ if (wsLogRaw !== undefined &&
246
+ wsLogRaw !== "auto" &&
247
+ wsLogRaw !== "compact" &&
248
+ wsLogRaw !== "full") {
249
+ defaultRuntime.error('Invalid --ws-log (use "auto", "full", "compact")');
250
+ defaultRuntime.exit(1);
251
+ }
252
+ setGatewayWsLogStyle(wsLogStyle);
253
+ const cfg = loadConfig();
254
+ const portOverride = parsePort(opts.port);
255
+ if (opts.port !== undefined && portOverride === null) {
256
+ defaultRuntime.error("Invalid port");
257
+ defaultRuntime.exit(1);
258
+ }
259
+ const port = portOverride ?? resolveGatewayPort(cfg);
260
+ if (!Number.isFinite(port) || port <= 0) {
261
+ defaultRuntime.error("Invalid port");
262
+ defaultRuntime.exit(1);
263
+ }
264
+ if (opts.force) {
265
+ try {
266
+ const { killed, waitedMs, escalatedToSigkill } = await forceFreePortAndWait(port, {
267
+ timeoutMs: 2000,
268
+ intervalMs: 100,
269
+ sigtermTimeoutMs: 700,
270
+ });
271
+ if (killed.length === 0) {
272
+ gatewayLog.info(`force: no listeners on port ${port}`);
273
+ }
274
+ else {
275
+ for (const proc of killed) {
276
+ gatewayLog.info(`force: killed pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""} on port ${port}`);
277
+ }
278
+ if (escalatedToSigkill) {
279
+ gatewayLog.info(`force: escalated to SIGKILL while freeing port ${port}`);
280
+ }
281
+ if (waitedMs > 0) {
282
+ gatewayLog.info(`force: waited ${waitedMs}ms for port ${port} to free`);
283
+ }
284
+ }
285
+ }
286
+ catch (err) {
287
+ defaultRuntime.error(`Force: ${String(err)}`);
288
+ defaultRuntime.exit(1);
289
+ return;
290
+ }
291
+ }
292
+ if (opts.token) {
293
+ process.env.CLAWDBOT_GATEWAY_TOKEN = String(opts.token);
294
+ }
295
+ const authModeRaw = opts.auth ? String(opts.auth) : undefined;
296
+ const authMode = authModeRaw === "token" || authModeRaw === "password"
297
+ ? authModeRaw
298
+ : null;
299
+ if (authModeRaw && !authMode) {
300
+ defaultRuntime.error('Invalid --auth (use "token" or "password")');
301
+ defaultRuntime.exit(1);
302
+ return;
303
+ }
304
+ const tailscaleRaw = opts.tailscale ? String(opts.tailscale) : undefined;
305
+ const tailscaleMode = tailscaleRaw === "off" ||
306
+ tailscaleRaw === "serve" ||
307
+ tailscaleRaw === "funnel"
308
+ ? tailscaleRaw
309
+ : null;
310
+ if (tailscaleRaw && !tailscaleMode) {
311
+ defaultRuntime.error('Invalid --tailscale (use "off", "serve", or "funnel")');
312
+ defaultRuntime.exit(1);
313
+ return;
314
+ }
315
+ const configExists = fs.existsSync(CONFIG_PATH_CLAWDBOT);
316
+ const mode = cfg.gateway?.mode;
317
+ if (!opts.allowUnconfigured && mode !== "local") {
318
+ if (!configExists) {
319
+ defaultRuntime.error("Missing config. Run `clawdbot setup` or set gateway.mode=local (or pass --allow-unconfigured).");
320
+ }
321
+ else {
322
+ defaultRuntime.error("Gateway start blocked: set gateway.mode=local (or pass --allow-unconfigured).");
323
+ }
324
+ defaultRuntime.exit(1);
325
+ return;
326
+ }
327
+ const bindRaw = String(opts.bind ?? cfg.gateway?.bind ?? "loopback");
328
+ const bind = bindRaw === "loopback" ||
329
+ bindRaw === "tailnet" ||
330
+ bindRaw === "lan" ||
331
+ bindRaw === "auto"
332
+ ? bindRaw
333
+ : null;
334
+ if (!bind) {
335
+ defaultRuntime.error('Invalid --bind (use "loopback", "tailnet", "lan", or "auto")');
336
+ defaultRuntime.exit(1);
337
+ return;
338
+ }
339
+ try {
340
+ await runGatewayLoop({
341
+ runtime: defaultRuntime,
342
+ start: async () => await startGatewayServer(port, {
343
+ bind,
344
+ auth: authMode || opts.password || authModeRaw
345
+ ? {
346
+ mode: authMode ?? undefined,
347
+ password: opts.password
348
+ ? String(opts.password)
349
+ : undefined,
350
+ }
351
+ : undefined,
352
+ tailscale: tailscaleMode || opts.tailscaleResetOnExit
353
+ ? {
354
+ mode: tailscaleMode ?? undefined,
355
+ resetOnExit: Boolean(opts.tailscaleResetOnExit),
356
+ }
357
+ : undefined,
358
+ }),
359
+ });
360
+ }
361
+ catch (err) {
362
+ if (err instanceof GatewayLockError) {
363
+ defaultRuntime.error(`Gateway failed to start: ${err.message}`);
364
+ defaultRuntime.exit(1);
365
+ return;
366
+ }
367
+ defaultRuntime.error(`Gateway failed to start: ${String(err)}`);
368
+ defaultRuntime.exit(1);
369
+ }
370
+ });
371
+ gatewayCallOpts(gateway
372
+ .command("call")
373
+ .description("Call a Gateway method and print JSON")
374
+ .argument("<method>", "Method name (health/status/system-presence/send/agent/cron.*)")
375
+ .option("--params <json>", "JSON object string for params", "{}")
376
+ .action(async (method, opts) => {
377
+ try {
378
+ const params = JSON.parse(String(opts.params ?? "{}"));
379
+ const result = await callGatewayCli(method, opts, params);
380
+ defaultRuntime.log(JSON.stringify(result, null, 2));
381
+ }
382
+ catch (err) {
383
+ defaultRuntime.error(`Gateway call failed: ${String(err)}`);
384
+ defaultRuntime.exit(1);
385
+ }
386
+ }));
387
+ gatewayCallOpts(gateway
388
+ .command("health")
389
+ .description("Fetch Gateway health")
390
+ .action(async (opts) => {
391
+ try {
392
+ const result = await callGatewayCli("health", opts);
393
+ defaultRuntime.log(JSON.stringify(result, null, 2));
394
+ }
395
+ catch (err) {
396
+ defaultRuntime.error(String(err));
397
+ defaultRuntime.exit(1);
398
+ }
399
+ }));
400
+ gatewayCallOpts(gateway
401
+ .command("status")
402
+ .description("Fetch Gateway status")
403
+ .action(async (opts) => {
404
+ try {
405
+ const result = await callGatewayCli("status", opts);
406
+ defaultRuntime.log(JSON.stringify(result, null, 2));
407
+ }
408
+ catch (err) {
409
+ defaultRuntime.error(String(err));
410
+ defaultRuntime.exit(1);
411
+ }
412
+ }));
413
+ gatewayCallOpts(gateway
414
+ .command("wake")
415
+ .description("Enqueue a system event and optionally trigger a heartbeat")
416
+ .requiredOption("--text <text>", "System event text")
417
+ .option("--mode <mode>", "Wake mode (now|next-heartbeat)", "next-heartbeat")
418
+ .action(async (opts) => {
419
+ try {
420
+ const result = await callGatewayCli("wake", opts, {
421
+ mode: opts.mode,
422
+ text: opts.text,
423
+ });
424
+ defaultRuntime.log(JSON.stringify(result, null, 2));
425
+ }
426
+ catch (err) {
427
+ defaultRuntime.error(String(err));
428
+ defaultRuntime.exit(1);
429
+ }
430
+ }));
431
+ gatewayCallOpts(gateway
432
+ .command("send")
433
+ .description("Send a message via the Gateway")
434
+ .requiredOption("--to <jidOrPhone>", "Destination (E.164 or jid)")
435
+ .requiredOption("--message <text>", "Message text")
436
+ .option("--media-url <url>", "Optional media URL")
437
+ .option("--gif-playback", "Treat video media as GIF playback", false)
438
+ .option("--idempotency-key <key>", "Idempotency key")
439
+ .action(async (opts) => {
440
+ try {
441
+ const idempotencyKey = opts.idempotencyKey ?? randomIdempotencyKey();
442
+ const result = await callGatewayCli("send", opts, {
443
+ to: opts.to,
444
+ message: opts.message,
445
+ mediaUrl: opts.mediaUrl,
446
+ gifPlayback: opts.gifPlayback,
447
+ idempotencyKey,
448
+ });
449
+ defaultRuntime.log(JSON.stringify(result, null, 2));
450
+ }
451
+ catch (err) {
452
+ defaultRuntime.error(String(err));
453
+ defaultRuntime.exit(1);
454
+ }
455
+ }));
456
+ gatewayCallOpts(gateway
457
+ .command("agent")
458
+ .description("Run an agent turn via the Gateway (waits for final)")
459
+ .requiredOption("--message <text>", "User message")
460
+ .option("--to <jidOrPhone>", "Destination")
461
+ .option("--session-id <id>", "Session id")
462
+ .option("--thinking <level>", "Thinking level")
463
+ .option("--deliver", "Deliver response", false)
464
+ .option("--timeout-seconds <n>", "Agent timeout seconds")
465
+ .option("--idempotency-key <key>", "Idempotency key")
466
+ .action(async (opts) => {
467
+ try {
468
+ const idempotencyKey = opts.idempotencyKey ?? randomIdempotencyKey();
469
+ const result = await callGatewayCli("agent", { ...opts, expectFinal: true }, {
470
+ message: opts.message,
471
+ to: opts.to,
472
+ sessionId: opts.sessionId,
473
+ thinking: opts.thinking,
474
+ deliver: Boolean(opts.deliver),
475
+ timeout: opts.timeoutSeconds
476
+ ? Number.parseInt(String(opts.timeoutSeconds), 10)
477
+ : undefined,
478
+ idempotencyKey,
479
+ });
480
+ defaultRuntime.log(JSON.stringify(result, null, 2));
481
+ }
482
+ catch (err) {
483
+ defaultRuntime.error(String(err));
484
+ defaultRuntime.exit(1);
485
+ }
486
+ }));
487
+ // Build default deps (keeps parity with other commands; future-proofing).
488
+ void createDefaultDeps();
489
+ }
@@ -0,0 +1,20 @@
1
+ import { callGateway } from "../gateway/call.js";
2
+ export function addGatewayClientOptions(cmd) {
3
+ return cmd
4
+ .option("--url <url>", "Gateway WebSocket URL (defaults to gateway.remote.url when configured)")
5
+ .option("--token <token>", "Gateway token (if required)")
6
+ .option("--timeout <ms>", "Timeout in ms", "10000")
7
+ .option("--expect-final", "Wait for final response (agent)", false);
8
+ }
9
+ export async function callGatewayFromCli(method, opts, params, extra) {
10
+ return await callGateway({
11
+ url: opts.url,
12
+ token: opts.token,
13
+ method,
14
+ params,
15
+ expectFinal: extra?.expectFinal ?? Boolean(opts.expectFinal),
16
+ timeoutMs: Number(opts.timeout ?? 10_000),
17
+ clientName: "cli",
18
+ mode: "cli",
19
+ });
20
+ }
@@ -0,0 +1,135 @@
1
+ import { danger } from "../globals.js";
2
+ import { DEFAULT_GMAIL_LABEL, DEFAULT_GMAIL_MAX_BYTES, DEFAULT_GMAIL_RENEW_MINUTES, DEFAULT_GMAIL_SERVE_BIND, DEFAULT_GMAIL_SERVE_PATH, DEFAULT_GMAIL_SERVE_PORT, DEFAULT_GMAIL_SUBSCRIPTION, DEFAULT_GMAIL_TOPIC, } from "../hooks/gmail.js";
3
+ import { runGmailService, runGmailSetup, } from "../hooks/gmail-ops.js";
4
+ import { defaultRuntime } from "../runtime.js";
5
+ export function registerHooksCli(program) {
6
+ const hooks = program
7
+ .command("hooks")
8
+ .description("Webhook helpers and hook-based integrations");
9
+ const gmail = hooks
10
+ .command("gmail")
11
+ .description("Gmail Pub/Sub hooks (via gogcli)");
12
+ gmail
13
+ .command("setup")
14
+ .description("Configure Gmail watch + Pub/Sub + Clawdbot hooks")
15
+ .requiredOption("--account <email>", "Gmail account to watch")
16
+ .option("--project <id>", "GCP project id (OAuth client owner)")
17
+ .option("--topic <name>", "Pub/Sub topic name", DEFAULT_GMAIL_TOPIC)
18
+ .option("--subscription <name>", "Pub/Sub subscription name", DEFAULT_GMAIL_SUBSCRIPTION)
19
+ .option("--label <label>", "Gmail label to watch", DEFAULT_GMAIL_LABEL)
20
+ .option("--hook-url <url>", "Clawdbot hook URL")
21
+ .option("--hook-token <token>", "Clawdbot hook token")
22
+ .option("--push-token <token>", "Push token for gog watch serve")
23
+ .option("--bind <host>", "gog watch serve bind host", DEFAULT_GMAIL_SERVE_BIND)
24
+ .option("--port <port>", "gog watch serve port", String(DEFAULT_GMAIL_SERVE_PORT))
25
+ .option("--path <path>", "gog watch serve path", DEFAULT_GMAIL_SERVE_PATH)
26
+ .option("--include-body", "Include email body snippets", true)
27
+ .option("--max-bytes <n>", "Max bytes for body snippets", String(DEFAULT_GMAIL_MAX_BYTES))
28
+ .option("--renew-minutes <n>", "Renew watch every N minutes", String(DEFAULT_GMAIL_RENEW_MINUTES))
29
+ .option("--tailscale <mode>", "Expose push endpoint via tailscale (funnel|serve|off)", "funnel")
30
+ .option("--tailscale-path <path>", "Path for tailscale serve/funnel")
31
+ .option("--push-endpoint <url>", "Explicit Pub/Sub push endpoint")
32
+ .option("--json", "Output JSON summary", false)
33
+ .action(async (opts) => {
34
+ try {
35
+ const parsed = parseGmailSetupOptions(opts);
36
+ await runGmailSetup(parsed);
37
+ }
38
+ catch (err) {
39
+ defaultRuntime.error(danger(String(err)));
40
+ defaultRuntime.exit(1);
41
+ }
42
+ });
43
+ gmail
44
+ .command("run")
45
+ .description("Run gog watch serve + auto-renew loop")
46
+ .option("--account <email>", "Gmail account to watch")
47
+ .option("--topic <topic>", "Pub/Sub topic path (projects/.../topics/..)")
48
+ .option("--subscription <name>", "Pub/Sub subscription name")
49
+ .option("--label <label>", "Gmail label to watch")
50
+ .option("--hook-url <url>", "Clawdbot hook URL")
51
+ .option("--hook-token <token>", "Clawdbot hook token")
52
+ .option("--push-token <token>", "Push token for gog watch serve")
53
+ .option("--bind <host>", "gog watch serve bind host")
54
+ .option("--port <port>", "gog watch serve port")
55
+ .option("--path <path>", "gog watch serve path")
56
+ .option("--include-body", "Include email body snippets")
57
+ .option("--max-bytes <n>", "Max bytes for body snippets")
58
+ .option("--renew-minutes <n>", "Renew watch every N minutes")
59
+ .option("--tailscale <mode>", "Expose push endpoint via tailscale (funnel|serve|off)")
60
+ .option("--tailscale-path <path>", "Path for tailscale serve/funnel")
61
+ .action(async (opts) => {
62
+ try {
63
+ const parsed = parseGmailRunOptions(opts);
64
+ await runGmailService(parsed);
65
+ }
66
+ catch (err) {
67
+ defaultRuntime.error(danger(String(err)));
68
+ defaultRuntime.exit(1);
69
+ }
70
+ });
71
+ }
72
+ function parseGmailSetupOptions(raw) {
73
+ const accountRaw = raw.account;
74
+ const account = typeof accountRaw === "string" ? accountRaw.trim() : "";
75
+ if (!account)
76
+ throw new Error("--account is required");
77
+ return {
78
+ account,
79
+ project: stringOption(raw.project),
80
+ topic: stringOption(raw.topic),
81
+ subscription: stringOption(raw.subscription),
82
+ label: stringOption(raw.label),
83
+ hookUrl: stringOption(raw.hookUrl),
84
+ hookToken: stringOption(raw.hookToken),
85
+ pushToken: stringOption(raw.pushToken),
86
+ bind: stringOption(raw.bind),
87
+ port: numberOption(raw.port),
88
+ path: stringOption(raw.path),
89
+ includeBody: booleanOption(raw.includeBody),
90
+ maxBytes: numberOption(raw.maxBytes),
91
+ renewEveryMinutes: numberOption(raw.renewMinutes),
92
+ tailscale: stringOption(raw.tailscale),
93
+ tailscalePath: stringOption(raw.tailscalePath),
94
+ pushEndpoint: stringOption(raw.pushEndpoint),
95
+ json: Boolean(raw.json),
96
+ };
97
+ }
98
+ function parseGmailRunOptions(raw) {
99
+ return {
100
+ account: stringOption(raw.account),
101
+ topic: stringOption(raw.topic),
102
+ subscription: stringOption(raw.subscription),
103
+ label: stringOption(raw.label),
104
+ hookUrl: stringOption(raw.hookUrl),
105
+ hookToken: stringOption(raw.hookToken),
106
+ pushToken: stringOption(raw.pushToken),
107
+ bind: stringOption(raw.bind),
108
+ port: numberOption(raw.port),
109
+ path: stringOption(raw.path),
110
+ includeBody: booleanOption(raw.includeBody),
111
+ maxBytes: numberOption(raw.maxBytes),
112
+ renewEveryMinutes: numberOption(raw.renewMinutes),
113
+ tailscale: stringOption(raw.tailscale),
114
+ tailscalePath: stringOption(raw.tailscalePath),
115
+ };
116
+ }
117
+ function stringOption(value) {
118
+ if (typeof value !== "string")
119
+ return undefined;
120
+ const trimmed = value.trim();
121
+ return trimmed ? trimmed : undefined;
122
+ }
123
+ function numberOption(value) {
124
+ if (value === undefined || value === null)
125
+ return undefined;
126
+ const n = typeof value === "number" ? value : Number(value);
127
+ if (!Number.isFinite(n) || n <= 0)
128
+ return undefined;
129
+ return Math.floor(n);
130
+ }
131
+ function booleanOption(value) {
132
+ if (value === undefined || value === null)
133
+ return undefined;
134
+ return Boolean(value);
135
+ }