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,83 @@
1
+ import { loadConfig } from "../config/config.js";
2
+ import { mediaKindFromMime } from "../media/constants.js";
3
+ import { saveMediaBuffer } from "../media/store.js";
4
+ import { loadWebMedia } from "../web/media.js";
5
+ import { createIMessageRpcClient } from "./client.js";
6
+ import { formatIMessageChatTarget, parseIMessageTarget, } from "./targets.js";
7
+ function resolveCliPath(explicit) {
8
+ const cfg = loadConfig();
9
+ return explicit?.trim() || cfg.imessage?.cliPath?.trim() || "imsg";
10
+ }
11
+ function resolveDbPath(explicit) {
12
+ const cfg = loadConfig();
13
+ return explicit?.trim() || cfg.imessage?.dbPath?.trim() || undefined;
14
+ }
15
+ function resolveService(explicit) {
16
+ const cfg = loadConfig();
17
+ return (explicit || cfg.imessage?.service || "auto");
18
+ }
19
+ function resolveRegion(explicit) {
20
+ const cfg = loadConfig();
21
+ return explicit?.trim() || cfg.imessage?.region?.trim() || "US";
22
+ }
23
+ async function resolveAttachment(mediaUrl, maxBytes) {
24
+ const media = await loadWebMedia(mediaUrl, maxBytes);
25
+ const saved = await saveMediaBuffer(media.buffer, media.contentType ?? undefined, "outbound", maxBytes);
26
+ return { path: saved.path, contentType: saved.contentType };
27
+ }
28
+ export async function sendMessageIMessage(to, text, opts = {}) {
29
+ const cliPath = resolveCliPath(opts.cliPath);
30
+ const dbPath = resolveDbPath(opts.dbPath);
31
+ const target = parseIMessageTarget(opts.chatId ? formatIMessageChatTarget(opts.chatId) : to);
32
+ const service = opts.service ?? (target.kind === "handle" ? target.service : undefined);
33
+ const region = resolveRegion(opts.region);
34
+ const maxBytes = opts.maxBytes ?? 16 * 1024 * 1024;
35
+ let message = text ?? "";
36
+ let filePath;
37
+ if (opts.mediaUrl?.trim()) {
38
+ const resolved = await resolveAttachment(opts.mediaUrl.trim(), maxBytes);
39
+ filePath = resolved.path;
40
+ if (!message.trim()) {
41
+ const kind = mediaKindFromMime(resolved.contentType ?? undefined);
42
+ if (kind)
43
+ message = kind === "image" ? "<media:image>" : `<media:${kind}>`;
44
+ }
45
+ }
46
+ if (!message.trim() && !filePath) {
47
+ throw new Error("iMessage send requires text or media");
48
+ }
49
+ const params = {
50
+ text: message,
51
+ service: resolveService(service),
52
+ region,
53
+ };
54
+ if (filePath)
55
+ params.file = filePath;
56
+ if (target.kind === "chat_id") {
57
+ params.chat_id = target.chatId;
58
+ }
59
+ else if (target.kind === "chat_guid") {
60
+ params.chat_guid = target.chatGuid;
61
+ }
62
+ else if (target.kind === "chat_identifier") {
63
+ params.chat_identifier = target.chatIdentifier;
64
+ }
65
+ else {
66
+ params.to = target.to;
67
+ }
68
+ const client = opts.client ?? (await createIMessageRpcClient({ cliPath, dbPath }));
69
+ const shouldClose = !opts.client;
70
+ try {
71
+ const result = await client.request("send", params, {
72
+ timeoutMs: opts.timeoutMs,
73
+ });
74
+ return {
75
+ messageId: result?.ok ? "ok" : "unknown",
76
+ };
77
+ }
78
+ finally {
79
+ if (shouldClose) {
80
+ await client.stop();
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,176 @@
1
+ import { normalizeE164 } from "../utils.js";
2
+ const CHAT_ID_PREFIXES = ["chat_id:", "chatid:", "chat:"];
3
+ const CHAT_GUID_PREFIXES = ["chat_guid:", "chatguid:", "guid:"];
4
+ const CHAT_IDENTIFIER_PREFIXES = [
5
+ "chat_identifier:",
6
+ "chatidentifier:",
7
+ "chatident:",
8
+ ];
9
+ const SERVICE_PREFIXES = [
10
+ { prefix: "imessage:", service: "imessage" },
11
+ { prefix: "sms:", service: "sms" },
12
+ { prefix: "auto:", service: "auto" },
13
+ ];
14
+ function stripPrefix(value, prefix) {
15
+ return value.slice(prefix.length).trim();
16
+ }
17
+ export function normalizeIMessageHandle(raw) {
18
+ const trimmed = raw.trim();
19
+ if (!trimmed)
20
+ return "";
21
+ const lowered = trimmed.toLowerCase();
22
+ if (lowered.startsWith("imessage:"))
23
+ return normalizeIMessageHandle(trimmed.slice(9));
24
+ if (lowered.startsWith("sms:"))
25
+ return normalizeIMessageHandle(trimmed.slice(4));
26
+ if (lowered.startsWith("auto:"))
27
+ return normalizeIMessageHandle(trimmed.slice(5));
28
+ if (trimmed.includes("@"))
29
+ return trimmed.toLowerCase();
30
+ const normalized = normalizeE164(trimmed);
31
+ if (normalized)
32
+ return normalized;
33
+ return trimmed.replace(/\s+/g, "");
34
+ }
35
+ export function parseIMessageTarget(raw) {
36
+ const trimmed = raw.trim();
37
+ if (!trimmed)
38
+ throw new Error("iMessage target is required");
39
+ const lower = trimmed.toLowerCase();
40
+ for (const { prefix, service } of SERVICE_PREFIXES) {
41
+ if (lower.startsWith(prefix)) {
42
+ const remainder = stripPrefix(trimmed, prefix);
43
+ if (!remainder)
44
+ throw new Error(`${prefix} target is required`);
45
+ const remainderLower = remainder.toLowerCase();
46
+ const isChatTarget = CHAT_ID_PREFIXES.some((p) => remainderLower.startsWith(p)) ||
47
+ CHAT_GUID_PREFIXES.some((p) => remainderLower.startsWith(p)) ||
48
+ CHAT_IDENTIFIER_PREFIXES.some((p) => remainderLower.startsWith(p)) ||
49
+ remainderLower.startsWith("group:");
50
+ if (isChatTarget) {
51
+ return parseIMessageTarget(remainder);
52
+ }
53
+ return { kind: "handle", to: remainder, service };
54
+ }
55
+ }
56
+ for (const prefix of CHAT_ID_PREFIXES) {
57
+ if (lower.startsWith(prefix)) {
58
+ const value = stripPrefix(trimmed, prefix);
59
+ const chatId = Number.parseInt(value, 10);
60
+ if (!Number.isFinite(chatId)) {
61
+ throw new Error(`Invalid chat_id: ${value}`);
62
+ }
63
+ return { kind: "chat_id", chatId };
64
+ }
65
+ }
66
+ for (const prefix of CHAT_GUID_PREFIXES) {
67
+ if (lower.startsWith(prefix)) {
68
+ const value = stripPrefix(trimmed, prefix);
69
+ if (!value)
70
+ throw new Error("chat_guid is required");
71
+ return { kind: "chat_guid", chatGuid: value };
72
+ }
73
+ }
74
+ for (const prefix of CHAT_IDENTIFIER_PREFIXES) {
75
+ if (lower.startsWith(prefix)) {
76
+ const value = stripPrefix(trimmed, prefix);
77
+ if (!value)
78
+ throw new Error("chat_identifier is required");
79
+ return { kind: "chat_identifier", chatIdentifier: value };
80
+ }
81
+ }
82
+ if (lower.startsWith("group:")) {
83
+ const value = stripPrefix(trimmed, "group:");
84
+ const chatId = Number.parseInt(value, 10);
85
+ if (Number.isFinite(chatId)) {
86
+ return { kind: "chat_id", chatId };
87
+ }
88
+ if (!value)
89
+ throw new Error("group target is required");
90
+ return { kind: "chat_guid", chatGuid: value };
91
+ }
92
+ return { kind: "handle", to: trimmed, service: "auto" };
93
+ }
94
+ export function parseIMessageAllowTarget(raw) {
95
+ const trimmed = raw.trim();
96
+ if (!trimmed)
97
+ return { kind: "handle", handle: "" };
98
+ const lower = trimmed.toLowerCase();
99
+ for (const { prefix } of SERVICE_PREFIXES) {
100
+ if (lower.startsWith(prefix)) {
101
+ const remainder = stripPrefix(trimmed, prefix);
102
+ if (!remainder)
103
+ return { kind: "handle", handle: "" };
104
+ return parseIMessageAllowTarget(remainder);
105
+ }
106
+ }
107
+ for (const prefix of CHAT_ID_PREFIXES) {
108
+ if (lower.startsWith(prefix)) {
109
+ const value = stripPrefix(trimmed, prefix);
110
+ const chatId = Number.parseInt(value, 10);
111
+ if (Number.isFinite(chatId))
112
+ return { kind: "chat_id", chatId };
113
+ }
114
+ }
115
+ for (const prefix of CHAT_GUID_PREFIXES) {
116
+ if (lower.startsWith(prefix)) {
117
+ const value = stripPrefix(trimmed, prefix);
118
+ if (value)
119
+ return { kind: "chat_guid", chatGuid: value };
120
+ }
121
+ }
122
+ for (const prefix of CHAT_IDENTIFIER_PREFIXES) {
123
+ if (lower.startsWith(prefix)) {
124
+ const value = stripPrefix(trimmed, prefix);
125
+ if (value)
126
+ return { kind: "chat_identifier", chatIdentifier: value };
127
+ }
128
+ }
129
+ if (lower.startsWith("group:")) {
130
+ const value = stripPrefix(trimmed, "group:");
131
+ const chatId = Number.parseInt(value, 10);
132
+ if (Number.isFinite(chatId))
133
+ return { kind: "chat_id", chatId };
134
+ if (value)
135
+ return { kind: "chat_guid", chatGuid: value };
136
+ }
137
+ return { kind: "handle", handle: normalizeIMessageHandle(trimmed) };
138
+ }
139
+ export function isAllowedIMessageSender(params) {
140
+ const allowFrom = params.allowFrom.map((entry) => String(entry).trim());
141
+ if (allowFrom.length === 0)
142
+ return true;
143
+ if (allowFrom.includes("*"))
144
+ return true;
145
+ const senderNormalized = normalizeIMessageHandle(params.sender);
146
+ const chatId = params.chatId ?? undefined;
147
+ const chatGuid = params.chatGuid?.trim();
148
+ const chatIdentifier = params.chatIdentifier?.trim();
149
+ for (const entry of allowFrom) {
150
+ if (!entry)
151
+ continue;
152
+ const parsed = parseIMessageAllowTarget(entry);
153
+ if (parsed.kind === "chat_id" && chatId !== undefined) {
154
+ if (parsed.chatId === chatId)
155
+ return true;
156
+ }
157
+ else if (parsed.kind === "chat_guid" && chatGuid) {
158
+ if (parsed.chatGuid === chatGuid)
159
+ return true;
160
+ }
161
+ else if (parsed.kind === "chat_identifier" && chatIdentifier) {
162
+ if (parsed.chatIdentifier === chatIdentifier)
163
+ return true;
164
+ }
165
+ else if (parsed.kind === "handle" && senderNormalized) {
166
+ if (parsed.handle === senderNormalized)
167
+ return true;
168
+ }
169
+ }
170
+ return false;
171
+ }
172
+ export function formatIMessageChatTarget(chatId) {
173
+ if (!chatId || !Number.isFinite(chatId))
174
+ return "";
175
+ return `chat_id:${chatId}`;
176
+ }
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import process from "node:process";
3
+ import { fileURLToPath } from "node:url";
4
+ import dotenv from "dotenv";
5
+ import { getReplyFromConfig } from "./auto-reply/reply.js";
6
+ import { applyTemplate } from "./auto-reply/templating.js";
7
+ import { createDefaultDeps } from "./cli/deps.js";
8
+ import { promptYesNo } from "./cli/prompt.js";
9
+ import { waitForever } from "./cli/wait.js";
10
+ import { loadConfig } from "./config/config.js";
11
+ import { deriveSessionKey, loadSessionStore, resolveSessionKey, resolveStorePath, saveSessionStore, } from "./config/sessions.js";
12
+ import { ensureBinary } from "./infra/binaries.js";
13
+ import { normalizeEnv } from "./infra/env.js";
14
+ import { isMainModule } from "./infra/is-main.js";
15
+ import { ensureClawdbotCliOnPath } from "./infra/path-env.js";
16
+ import { describePortOwner, ensurePortAvailable, handlePortError, PortInUseError, } from "./infra/ports.js";
17
+ import { assertSupportedRuntime } from "./infra/runtime-guard.js";
18
+ import { enableConsoleCapture } from "./logging.js";
19
+ import { runCommandWithTimeout, runExec } from "./process/exec.js";
20
+ import { monitorWebProvider } from "./provider-web.js";
21
+ import { assertProvider, normalizeE164, toWhatsappJid } from "./utils.js";
22
+ dotenv.config({ quiet: true });
23
+ normalizeEnv();
24
+ ensureClawdbotCliOnPath();
25
+ // Capture all console output into structured logs while keeping stdout/stderr behavior.
26
+ enableConsoleCapture();
27
+ // Enforce the minimum supported runtime before doing any work.
28
+ assertSupportedRuntime();
29
+ import { buildProgram } from "./cli/program.js";
30
+ const program = buildProgram();
31
+ export { assertProvider, applyTemplate, createDefaultDeps, deriveSessionKey, describePortOwner, ensureBinary, ensurePortAvailable, getReplyFromConfig, handlePortError, loadConfig, loadSessionStore, monitorWebProvider, normalizeE164, PortInUseError, promptYesNo, resolveSessionKey, resolveStorePath, runCommandWithTimeout, runExec, saveSessionStore, toWhatsappJid, waitForever, };
32
+ const isMain = isMainModule({
33
+ currentFile: fileURLToPath(import.meta.url),
34
+ });
35
+ if (isMain) {
36
+ // Global error handlers to prevent silent crashes from unhandled rejections/exceptions.
37
+ // These log the error and exit gracefully instead of crashing without trace.
38
+ process.on("unhandledRejection", (reason, _promise) => {
39
+ console.error("[clawdbot] Unhandled promise rejection:", reason instanceof Error ? (reason.stack ?? reason.message) : reason);
40
+ process.exit(1);
41
+ });
42
+ process.on("uncaughtException", (error) => {
43
+ console.error("[clawdbot] Uncaught exception:", error.stack ?? error.message);
44
+ process.exit(1);
45
+ });
46
+ void program.parseAsync(process.argv).catch((err) => {
47
+ console.error("[clawdbot] CLI failed:", err instanceof Error ? (err.stack ?? err.message) : err);
48
+ process.exit(1);
49
+ });
50
+ }
@@ -0,0 +1,46 @@
1
+ // Keep per-run counters so streams stay strictly monotonic per runId.
2
+ const seqByRun = new Map();
3
+ const listeners = new Set();
4
+ const runContextById = new Map();
5
+ export function registerAgentRunContext(runId, context) {
6
+ if (!runId)
7
+ return;
8
+ const existing = runContextById.get(runId);
9
+ if (!existing) {
10
+ runContextById.set(runId, { ...context });
11
+ return;
12
+ }
13
+ if (context.sessionKey && existing.sessionKey !== context.sessionKey) {
14
+ existing.sessionKey = context.sessionKey;
15
+ }
16
+ }
17
+ export function getAgentRunContext(runId) {
18
+ return runContextById.get(runId);
19
+ }
20
+ export function clearAgentRunContext(runId) {
21
+ runContextById.delete(runId);
22
+ }
23
+ export function resetAgentRunContextForTest() {
24
+ runContextById.clear();
25
+ }
26
+ export function emitAgentEvent(event) {
27
+ const nextSeq = (seqByRun.get(event.runId) ?? 0) + 1;
28
+ seqByRun.set(event.runId, nextSeq);
29
+ const enriched = {
30
+ ...event,
31
+ seq: nextSeq,
32
+ ts: Date.now(),
33
+ };
34
+ for (const listener of listeners) {
35
+ try {
36
+ listener(enriched);
37
+ }
38
+ catch {
39
+ /* ignore */
40
+ }
41
+ }
42
+ }
43
+ export function onAgentEvent(listener) {
44
+ listeners.add(listener);
45
+ return () => listeners.delete(listener);
46
+ }
@@ -0,0 +1,9 @@
1
+ import { runExec } from "../process/exec.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
+ export async function ensureBinary(name, exec = runExec, runtime = defaultRuntime) {
4
+ // Abort early if a required CLI tool is missing.
5
+ await exec("which", [name]).catch(() => {
6
+ runtime.error(`Missing required binary: ${name}. Please install it.`);
7
+ runtime.exit(1);
8
+ });
9
+ }
@@ -0,0 +1,163 @@
1
+ import { runCommandWithTimeout } from "../process/exec.js";
2
+ const DEFAULT_TIMEOUT_MS = 2000;
3
+ function parseIntOrNull(value) {
4
+ if (!value)
5
+ return undefined;
6
+ const parsed = Number.parseInt(value, 10);
7
+ return Number.isFinite(parsed) ? parsed : undefined;
8
+ }
9
+ function parseTxtTokens(tokens) {
10
+ const txt = {};
11
+ for (const token of tokens) {
12
+ const idx = token.indexOf("=");
13
+ if (idx <= 0)
14
+ continue;
15
+ const key = token.slice(0, idx).trim();
16
+ const value = token.slice(idx + 1).trim();
17
+ if (!key)
18
+ continue;
19
+ txt[key] = value;
20
+ }
21
+ return txt;
22
+ }
23
+ function parseDnsSdBrowse(stdout) {
24
+ const instances = new Set();
25
+ for (const raw of stdout.split("\n")) {
26
+ const line = raw.trim();
27
+ if (!line || !line.includes("_clawdbot-bridge._tcp"))
28
+ continue;
29
+ if (!line.includes("Add"))
30
+ continue;
31
+ const match = line.match(/_clawdbot-bridge\._tcp\.?\s+(.+)$/);
32
+ if (match?.[1]) {
33
+ instances.add(match[1].trim());
34
+ }
35
+ }
36
+ return Array.from(instances.values());
37
+ }
38
+ function parseDnsSdResolve(stdout, instanceName) {
39
+ const beacon = { instanceName };
40
+ let txt = {};
41
+ for (const raw of stdout.split("\n")) {
42
+ const line = raw.trim();
43
+ if (!line)
44
+ continue;
45
+ if (line.includes("can be reached at")) {
46
+ const match = line.match(/can be reached at\s+([^\s:]+):(\d+)/i);
47
+ if (match?.[1]) {
48
+ beacon.host = match[1].replace(/\.$/, "");
49
+ }
50
+ if (match?.[2]) {
51
+ beacon.port = parseIntOrNull(match[2]);
52
+ }
53
+ continue;
54
+ }
55
+ if (line.startsWith("txt") || line.includes("txtvers=")) {
56
+ const tokens = line.split(/\s+/).filter(Boolean);
57
+ txt = parseTxtTokens(tokens);
58
+ }
59
+ }
60
+ beacon.txt = Object.keys(txt).length ? txt : undefined;
61
+ if (txt.displayName)
62
+ beacon.displayName = txt.displayName;
63
+ if (txt.lanHost)
64
+ beacon.lanHost = txt.lanHost;
65
+ if (txt.tailnetDns)
66
+ beacon.tailnetDns = txt.tailnetDns;
67
+ if (txt.cliPath)
68
+ beacon.cliPath = txt.cliPath;
69
+ beacon.bridgePort = parseIntOrNull(txt.bridgePort);
70
+ beacon.gatewayPort = parseIntOrNull(txt.gatewayPort);
71
+ beacon.sshPort = parseIntOrNull(txt.sshPort);
72
+ if (!beacon.displayName)
73
+ beacon.displayName = instanceName;
74
+ return beacon;
75
+ }
76
+ async function discoverViaDnsSd(timeoutMs) {
77
+ const browse = await runCommandWithTimeout(["dns-sd", "-B", "_clawdbot-bridge._tcp", "local."], { timeoutMs });
78
+ const instances = parseDnsSdBrowse(browse.stdout);
79
+ const results = [];
80
+ for (const instance of instances) {
81
+ const resolved = await runCommandWithTimeout(["dns-sd", "-L", instance, "_clawdbot-bridge._tcp", "local."], { timeoutMs });
82
+ const parsed = parseDnsSdResolve(resolved.stdout, instance);
83
+ if (parsed)
84
+ results.push(parsed);
85
+ }
86
+ return results;
87
+ }
88
+ function parseAvahiBrowse(stdout) {
89
+ const results = [];
90
+ let current = null;
91
+ for (const raw of stdout.split("\n")) {
92
+ const line = raw.trimEnd();
93
+ if (!line)
94
+ continue;
95
+ if (line.startsWith("=") && line.includes("_clawdbot-bridge._tcp")) {
96
+ if (current)
97
+ results.push(current);
98
+ const marker = " _clawdbot-bridge._tcp";
99
+ const idx = line.indexOf(marker);
100
+ const left = idx >= 0 ? line.slice(0, idx).trim() : line;
101
+ const parts = left.split(/\s+/);
102
+ const instanceName = parts.length > 3 ? parts.slice(3).join(" ") : left;
103
+ current = {
104
+ instanceName,
105
+ displayName: instanceName,
106
+ };
107
+ continue;
108
+ }
109
+ if (!current)
110
+ continue;
111
+ const trimmed = line.trim();
112
+ if (trimmed.startsWith("hostname =")) {
113
+ const match = trimmed.match(/hostname\s*=\s*\[([^\]]+)\]/);
114
+ if (match?.[1])
115
+ current.host = match[1];
116
+ continue;
117
+ }
118
+ if (trimmed.startsWith("port =")) {
119
+ const match = trimmed.match(/port\s*=\s*\[(\d+)\]/);
120
+ if (match?.[1])
121
+ current.port = parseIntOrNull(match[1]);
122
+ continue;
123
+ }
124
+ if (trimmed.startsWith("txt =")) {
125
+ const tokens = Array.from(trimmed.matchAll(/"([^"]*)"/g), (m) => m[1]);
126
+ const txt = parseTxtTokens(tokens);
127
+ current.txt = Object.keys(txt).length ? txt : undefined;
128
+ if (txt.displayName)
129
+ current.displayName = txt.displayName;
130
+ if (txt.lanHost)
131
+ current.lanHost = txt.lanHost;
132
+ if (txt.tailnetDns)
133
+ current.tailnetDns = txt.tailnetDns;
134
+ if (txt.cliPath)
135
+ current.cliPath = txt.cliPath;
136
+ current.bridgePort = parseIntOrNull(txt.bridgePort);
137
+ current.gatewayPort = parseIntOrNull(txt.gatewayPort);
138
+ current.sshPort = parseIntOrNull(txt.sshPort);
139
+ }
140
+ }
141
+ if (current)
142
+ results.push(current);
143
+ return results;
144
+ }
145
+ async function discoverViaAvahi(timeoutMs) {
146
+ const browse = await runCommandWithTimeout(["avahi-browse", "-rt", "_clawdbot-bridge._tcp"], { timeoutMs });
147
+ return parseAvahiBrowse(browse.stdout);
148
+ }
149
+ export async function discoverGatewayBeacons(opts = {}) {
150
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
151
+ try {
152
+ if (process.platform === "darwin") {
153
+ return await discoverViaDnsSd(timeoutMs);
154
+ }
155
+ if (process.platform === "linux") {
156
+ return await discoverViaAvahi(timeoutMs);
157
+ }
158
+ }
159
+ catch {
160
+ return [];
161
+ }
162
+ return [];
163
+ }