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,177 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { DEFAULT_GATEWAY_PORT, resolveGatewayPort, } from "../config/config.js";
3
+ export const DEFAULT_GMAIL_LABEL = "INBOX";
4
+ export const DEFAULT_GMAIL_TOPIC = "gog-gmail-watch";
5
+ export const DEFAULT_GMAIL_SUBSCRIPTION = "gog-gmail-watch-push";
6
+ export const DEFAULT_GMAIL_SERVE_BIND = "127.0.0.1";
7
+ export const DEFAULT_GMAIL_SERVE_PORT = 8788;
8
+ export const DEFAULT_GMAIL_SERVE_PATH = "/gmail-pubsub";
9
+ export const DEFAULT_GMAIL_MAX_BYTES = 20_000;
10
+ export const DEFAULT_GMAIL_RENEW_MINUTES = 12 * 60;
11
+ export const DEFAULT_HOOKS_PATH = "/hooks";
12
+ export function generateHookToken(bytes = 24) {
13
+ return randomBytes(bytes).toString("hex");
14
+ }
15
+ export function mergeHookPresets(existing, preset) {
16
+ const next = new Set((existing ?? []).map((item) => item.trim()).filter(Boolean));
17
+ next.add(preset);
18
+ return Array.from(next);
19
+ }
20
+ export function normalizeHooksPath(raw) {
21
+ const base = raw?.trim() || DEFAULT_HOOKS_PATH;
22
+ if (base === "/")
23
+ return DEFAULT_HOOKS_PATH;
24
+ const withSlash = base.startsWith("/") ? base : `/${base}`;
25
+ return withSlash.replace(/\/+$/, "");
26
+ }
27
+ export function normalizeServePath(raw) {
28
+ const base = raw?.trim() || DEFAULT_GMAIL_SERVE_PATH;
29
+ // Tailscale funnel/serve strips the set-path prefix before proxying.
30
+ // To accept requests at /<path> externally, gog must listen on "/".
31
+ if (base === "/")
32
+ return "/";
33
+ const withSlash = base.startsWith("/") ? base : `/${base}`;
34
+ return withSlash.replace(/\/+$/, "");
35
+ }
36
+ export function buildDefaultHookUrl(hooksPath, port = DEFAULT_GATEWAY_PORT) {
37
+ const basePath = normalizeHooksPath(hooksPath);
38
+ const baseUrl = `http://127.0.0.1:${port}`;
39
+ return joinUrl(baseUrl, `${basePath}/gmail`);
40
+ }
41
+ export function resolveGmailHookRuntimeConfig(cfg, overrides) {
42
+ const hooks = cfg.hooks;
43
+ const gmail = hooks?.gmail;
44
+ const hookToken = overrides.hookToken ?? hooks?.token ?? "";
45
+ if (!hookToken) {
46
+ return { ok: false, error: "hooks.token missing (needed for gmail hook)" };
47
+ }
48
+ const account = overrides.account ?? gmail?.account ?? "";
49
+ if (!account) {
50
+ return { ok: false, error: "gmail account required" };
51
+ }
52
+ const topic = overrides.topic ?? gmail?.topic ?? "";
53
+ if (!topic) {
54
+ return { ok: false, error: "gmail topic required" };
55
+ }
56
+ const subscription = overrides.subscription ?? gmail?.subscription ?? DEFAULT_GMAIL_SUBSCRIPTION;
57
+ const pushToken = overrides.pushToken ?? gmail?.pushToken ?? "";
58
+ if (!pushToken) {
59
+ return { ok: false, error: "gmail push token required" };
60
+ }
61
+ const hookUrl = overrides.hookUrl ??
62
+ gmail?.hookUrl ??
63
+ buildDefaultHookUrl(hooks?.path, resolveGatewayPort(cfg));
64
+ const includeBody = overrides.includeBody ?? gmail?.includeBody ?? true;
65
+ const maxBytesRaw = overrides.maxBytes ?? gmail?.maxBytes;
66
+ const maxBytes = typeof maxBytesRaw === "number" &&
67
+ Number.isFinite(maxBytesRaw) &&
68
+ maxBytesRaw > 0
69
+ ? Math.floor(maxBytesRaw)
70
+ : DEFAULT_GMAIL_MAX_BYTES;
71
+ const renewEveryMinutesRaw = overrides.renewEveryMinutes ?? gmail?.renewEveryMinutes;
72
+ const renewEveryMinutes = typeof renewEveryMinutesRaw === "number" &&
73
+ Number.isFinite(renewEveryMinutesRaw) &&
74
+ renewEveryMinutesRaw > 0
75
+ ? Math.floor(renewEveryMinutesRaw)
76
+ : DEFAULT_GMAIL_RENEW_MINUTES;
77
+ const serveBind = overrides.serveBind ?? gmail?.serve?.bind ?? DEFAULT_GMAIL_SERVE_BIND;
78
+ const servePortRaw = overrides.servePort ?? gmail?.serve?.port;
79
+ const servePort = typeof servePortRaw === "number" &&
80
+ Number.isFinite(servePortRaw) &&
81
+ servePortRaw > 0
82
+ ? Math.floor(servePortRaw)
83
+ : DEFAULT_GMAIL_SERVE_PORT;
84
+ const servePathRaw = overrides.servePath ?? gmail?.serve?.path;
85
+ const hasExplicitServePath = typeof servePathRaw === "string" && servePathRaw.trim().length > 0;
86
+ const tailscaleMode = overrides.tailscaleMode ?? gmail?.tailscale?.mode ?? "off";
87
+ // When exposing the push endpoint via Tailscale, the public path is stripped
88
+ // before proxying; use "/" internally unless the user set a path explicitly.
89
+ const servePath = normalizeServePath(tailscaleMode !== "off" && !hasExplicitServePath ? "/" : servePathRaw);
90
+ const tailscalePathRaw = overrides.tailscalePath ?? gmail?.tailscale?.path;
91
+ const tailscalePath = normalizeServePath(tailscaleMode !== "off" && !tailscalePathRaw
92
+ ? hasExplicitServePath
93
+ ? servePathRaw
94
+ : DEFAULT_GMAIL_SERVE_PATH
95
+ : (tailscalePathRaw ?? servePath));
96
+ return {
97
+ ok: true,
98
+ value: {
99
+ account,
100
+ label: overrides.label ?? gmail?.label ?? DEFAULT_GMAIL_LABEL,
101
+ topic,
102
+ subscription,
103
+ pushToken,
104
+ hookToken,
105
+ hookUrl,
106
+ includeBody,
107
+ maxBytes,
108
+ renewEveryMinutes,
109
+ serve: {
110
+ bind: serveBind,
111
+ port: servePort,
112
+ path: servePath,
113
+ },
114
+ tailscale: {
115
+ mode: tailscaleMode,
116
+ path: tailscalePath,
117
+ },
118
+ },
119
+ };
120
+ }
121
+ export function buildGogWatchStartArgs(cfg) {
122
+ return [
123
+ "gmail",
124
+ "watch",
125
+ "start",
126
+ "--account",
127
+ cfg.account,
128
+ "--label",
129
+ cfg.label,
130
+ "--topic",
131
+ cfg.topic,
132
+ ];
133
+ }
134
+ export function buildGogWatchServeArgs(cfg) {
135
+ const args = [
136
+ "gmail",
137
+ "watch",
138
+ "serve",
139
+ "--account",
140
+ cfg.account,
141
+ "--bind",
142
+ cfg.serve.bind,
143
+ "--port",
144
+ String(cfg.serve.port),
145
+ "--path",
146
+ cfg.serve.path,
147
+ "--token",
148
+ cfg.pushToken,
149
+ "--hook-url",
150
+ cfg.hookUrl,
151
+ "--hook-token",
152
+ cfg.hookToken,
153
+ ];
154
+ if (cfg.includeBody) {
155
+ args.push("--include-body");
156
+ }
157
+ if (cfg.maxBytes > 0) {
158
+ args.push("--max-bytes", String(cfg.maxBytes));
159
+ }
160
+ return args;
161
+ }
162
+ export function buildTopicPath(projectId, topicName) {
163
+ return `projects/${projectId}/topics/${topicName}`;
164
+ }
165
+ export function parseTopicPath(topic) {
166
+ const match = topic.trim().match(/^projects\/([^/]+)\/topics\/([^/]+)$/i);
167
+ if (!match)
168
+ return null;
169
+ return { projectId: match[1] ?? "", topicName: match[2] ?? "" };
170
+ }
171
+ function joinUrl(base, path) {
172
+ const url = new URL(base);
173
+ const basePath = url.pathname.replace(/\/+$/, "");
174
+ const extra = path.startsWith("/") ? path : `/${path}`;
175
+ url.pathname = `${basePath}${extra}`;
176
+ return url.toString();
177
+ }
@@ -0,0 +1,165 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createInterface } from "node:readline";
3
+ import { resolveUserPath } from "../utils.js";
4
+ export class IMessageRpcClient {
5
+ cliPath;
6
+ dbPath;
7
+ runtime;
8
+ onNotification;
9
+ pending = new Map();
10
+ closed;
11
+ closedResolve = null;
12
+ child = null;
13
+ reader = null;
14
+ nextId = 1;
15
+ constructor(opts = {}) {
16
+ this.cliPath = opts.cliPath?.trim() || "imsg";
17
+ this.dbPath = opts.dbPath?.trim()
18
+ ? resolveUserPath(opts.dbPath)
19
+ : undefined;
20
+ this.runtime = opts.runtime;
21
+ this.onNotification = opts.onNotification;
22
+ this.closed = new Promise((resolve) => {
23
+ this.closedResolve = resolve;
24
+ });
25
+ }
26
+ async start() {
27
+ if (this.child)
28
+ return;
29
+ const args = ["rpc"];
30
+ if (this.dbPath) {
31
+ args.push("--db", this.dbPath);
32
+ }
33
+ const child = spawn(this.cliPath, args, {
34
+ stdio: ["pipe", "pipe", "pipe"],
35
+ });
36
+ this.child = child;
37
+ this.reader = createInterface({ input: child.stdout });
38
+ this.reader.on("line", (line) => {
39
+ const trimmed = line.trim();
40
+ if (!trimmed)
41
+ return;
42
+ this.handleLine(trimmed);
43
+ });
44
+ child.stderr?.on("data", (chunk) => {
45
+ const lines = chunk.toString().split(/\r?\n/);
46
+ for (const line of lines) {
47
+ if (!line.trim())
48
+ continue;
49
+ this.runtime?.error?.(`imsg rpc: ${line.trim()}`);
50
+ }
51
+ });
52
+ child.on("error", (err) => {
53
+ this.failAll(err instanceof Error ? err : new Error(String(err)));
54
+ this.closedResolve?.();
55
+ });
56
+ child.on("close", (code, signal) => {
57
+ if (code !== 0 && code !== null) {
58
+ const reason = signal ? `signal ${signal}` : `code ${code}`;
59
+ this.failAll(new Error(`imsg rpc exited (${reason})`));
60
+ }
61
+ else {
62
+ this.failAll(new Error("imsg rpc closed"));
63
+ }
64
+ this.closedResolve?.();
65
+ });
66
+ }
67
+ async stop() {
68
+ if (!this.child)
69
+ return;
70
+ this.reader?.close();
71
+ this.reader = null;
72
+ this.child.stdin?.end();
73
+ const child = this.child;
74
+ this.child = null;
75
+ await Promise.race([
76
+ this.closed,
77
+ new Promise((resolve) => {
78
+ setTimeout(() => {
79
+ if (!child.killed)
80
+ child.kill("SIGTERM");
81
+ resolve();
82
+ }, 500);
83
+ }),
84
+ ]);
85
+ }
86
+ async waitForClose() {
87
+ await this.closed;
88
+ }
89
+ async request(method, params, opts) {
90
+ if (!this.child || !this.child.stdin) {
91
+ throw new Error("imsg rpc not running");
92
+ }
93
+ const id = this.nextId++;
94
+ const payload = {
95
+ jsonrpc: "2.0",
96
+ id,
97
+ method,
98
+ params: params ?? {},
99
+ };
100
+ const line = `${JSON.stringify(payload)}\n`;
101
+ const timeoutMs = opts?.timeoutMs ?? 10_000;
102
+ const response = new Promise((resolve, reject) => {
103
+ const key = String(id);
104
+ const timer = timeoutMs > 0
105
+ ? setTimeout(() => {
106
+ this.pending.delete(key);
107
+ reject(new Error(`imsg rpc timeout (${method})`));
108
+ }, timeoutMs)
109
+ : undefined;
110
+ this.pending.set(key, {
111
+ resolve: (value) => resolve(value),
112
+ reject,
113
+ timer,
114
+ });
115
+ });
116
+ this.child.stdin.write(line);
117
+ return await response;
118
+ }
119
+ handleLine(line) {
120
+ let parsed;
121
+ try {
122
+ parsed = JSON.parse(line);
123
+ }
124
+ catch (err) {
125
+ const detail = err instanceof Error ? err.message : String(err);
126
+ this.runtime?.error?.(`imsg rpc: failed to parse ${line}: ${detail}`);
127
+ return;
128
+ }
129
+ if (parsed.id !== undefined && parsed.id !== null) {
130
+ const key = String(parsed.id);
131
+ const pending = this.pending.get(key);
132
+ if (!pending)
133
+ return;
134
+ if (pending.timer)
135
+ clearTimeout(pending.timer);
136
+ this.pending.delete(key);
137
+ if (parsed.error) {
138
+ const msg = parsed.error.message ?? "imsg rpc error";
139
+ pending.reject(new Error(msg));
140
+ return;
141
+ }
142
+ pending.resolve(parsed.result);
143
+ return;
144
+ }
145
+ if (parsed.method) {
146
+ this.onNotification?.({
147
+ method: parsed.method,
148
+ params: parsed.params,
149
+ });
150
+ }
151
+ }
152
+ failAll(err) {
153
+ for (const [key, pending] of this.pending.entries()) {
154
+ if (pending.timer)
155
+ clearTimeout(pending.timer);
156
+ pending.reject(err);
157
+ this.pending.delete(key);
158
+ }
159
+ }
160
+ }
161
+ export async function createIMessageRpcClient(opts = {}) {
162
+ const client = new IMessageRpcClient(opts);
163
+ await client.start();
164
+ return client;
165
+ }
@@ -0,0 +1,3 @@
1
+ export { monitorIMessageProvider } from "./monitor.js";
2
+ export { probeIMessage } from "./probe.js";
3
+ export { sendMessageIMessage } from "./send.js";
@@ -0,0 +1,272 @@
1
+ import { chunkText, resolveTextChunkLimit } from "../auto-reply/chunk.js";
2
+ import { formatAgentEnvelope } from "../auto-reply/envelope.js";
3
+ import { getReplyFromConfig } from "../auto-reply/reply.js";
4
+ import { loadConfig } from "../config/config.js";
5
+ import { resolveStorePath, updateLastRoute } from "../config/sessions.js";
6
+ import { danger, logVerbose, shouldLogVerbose } from "../globals.js";
7
+ import { mediaKindFromMime } from "../media/constants.js";
8
+ import { createIMessageRpcClient } from "./client.js";
9
+ import { sendMessageIMessage } from "./send.js";
10
+ import { formatIMessageChatTarget, isAllowedIMessageSender, normalizeIMessageHandle, } from "./targets.js";
11
+ function resolveRuntime(opts) {
12
+ return (opts.runtime ?? {
13
+ log: console.log,
14
+ error: console.error,
15
+ exit: (code) => {
16
+ throw new Error(`exit ${code}`);
17
+ },
18
+ });
19
+ }
20
+ function resolveAllowFrom(opts) {
21
+ const cfg = loadConfig();
22
+ const raw = opts.allowFrom ?? cfg.imessage?.allowFrom ?? [];
23
+ return raw.map((entry) => String(entry).trim()).filter(Boolean);
24
+ }
25
+ function resolveMentionRegexes(cfg) {
26
+ return (cfg.routing?.groupChat?.mentionPatterns
27
+ ?.map((pattern) => {
28
+ try {
29
+ return new RegExp(pattern, "i");
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ })
35
+ .filter((val) => Boolean(val)) ?? []);
36
+ }
37
+ function resolveGroupRequireMention(cfg, opts, chatId) {
38
+ if (typeof opts.requireMention === "boolean")
39
+ return opts.requireMention;
40
+ const groupId = chatId != null ? String(chatId) : undefined;
41
+ if (groupId) {
42
+ const groupConfig = cfg.imessage?.groups?.[groupId];
43
+ if (typeof groupConfig?.requireMention === "boolean") {
44
+ return groupConfig.requireMention;
45
+ }
46
+ }
47
+ const groupDefault = cfg.imessage?.groups?.["*"]?.requireMention;
48
+ if (typeof groupDefault === "boolean")
49
+ return groupDefault;
50
+ return true;
51
+ }
52
+ function isMentioned(text, regexes) {
53
+ if (!text)
54
+ return false;
55
+ const cleaned = text
56
+ .replace(/[\u200b-\u200f\u202a-\u202e\u2060-\u206f]/g, "")
57
+ .toLowerCase();
58
+ return regexes.some((re) => re.test(cleaned));
59
+ }
60
+ async function deliverReplies(params) {
61
+ const { replies, target, client, runtime, maxBytes, textLimit } = params;
62
+ for (const payload of replies) {
63
+ const mediaList = payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : []);
64
+ const text = payload.text ?? "";
65
+ if (!text && mediaList.length === 0)
66
+ continue;
67
+ if (mediaList.length === 0) {
68
+ for (const chunk of chunkText(text, textLimit)) {
69
+ await sendMessageIMessage(target, chunk, { maxBytes, client });
70
+ }
71
+ }
72
+ else {
73
+ let first = true;
74
+ for (const url of mediaList) {
75
+ const caption = first ? text : "";
76
+ first = false;
77
+ await sendMessageIMessage(target, caption, {
78
+ mediaUrl: url,
79
+ maxBytes,
80
+ client,
81
+ });
82
+ }
83
+ }
84
+ runtime.log?.(`imessage: delivered reply to ${target}`);
85
+ }
86
+ }
87
+ export async function monitorIMessageProvider(opts = {}) {
88
+ const runtime = resolveRuntime(opts);
89
+ const cfg = loadConfig();
90
+ const textLimit = resolveTextChunkLimit(cfg, "imessage");
91
+ const allowFrom = resolveAllowFrom(opts);
92
+ const mentionRegexes = resolveMentionRegexes(cfg);
93
+ const includeAttachments = opts.includeAttachments ?? cfg.imessage?.includeAttachments ?? false;
94
+ const mediaMaxBytes = (opts.mediaMaxMb ?? cfg.imessage?.mediaMaxMb ?? 16) * 1024 * 1024;
95
+ const handleMessage = async (raw) => {
96
+ const params = raw;
97
+ const message = params?.message ?? null;
98
+ if (!message)
99
+ return;
100
+ const senderRaw = message.sender ?? "";
101
+ const sender = senderRaw.trim();
102
+ if (!sender)
103
+ return;
104
+ if (message.is_from_me)
105
+ return;
106
+ const chatId = message.chat_id ?? undefined;
107
+ const chatGuid = message.chat_guid ?? undefined;
108
+ const chatIdentifier = message.chat_identifier ?? undefined;
109
+ const isGroup = Boolean(message.is_group);
110
+ if (isGroup && !chatId)
111
+ return;
112
+ if (!isAllowedIMessageSender({
113
+ allowFrom,
114
+ sender,
115
+ chatId: chatId ?? undefined,
116
+ chatGuid,
117
+ chatIdentifier,
118
+ })) {
119
+ logVerbose(`Blocked iMessage sender ${sender} (not in allowFrom)`);
120
+ return;
121
+ }
122
+ const messageText = (message.text ?? "").trim();
123
+ const mentioned = isGroup ? isMentioned(messageText, mentionRegexes) : true;
124
+ const requireMention = resolveGroupRequireMention(cfg, opts, chatId);
125
+ if (isGroup && requireMention && !mentioned) {
126
+ logVerbose(`imessage: skipping group message (no mention)`);
127
+ return;
128
+ }
129
+ const attachments = includeAttachments ? (message.attachments ?? []) : [];
130
+ const firstAttachment = attachments?.find((entry) => entry?.original_path && !entry?.missing);
131
+ const mediaPath = firstAttachment?.original_path ?? undefined;
132
+ const mediaType = firstAttachment?.mime_type ?? undefined;
133
+ const kind = mediaKindFromMime(mediaType ?? undefined);
134
+ const placeholder = kind
135
+ ? `<media:${kind}>`
136
+ : attachments?.length
137
+ ? "<media:attachment>"
138
+ : "";
139
+ const bodyText = messageText || placeholder;
140
+ if (!bodyText)
141
+ return;
142
+ const chatTarget = formatIMessageChatTarget(chatId);
143
+ const fromLabel = isGroup
144
+ ? `${message.chat_name || "iMessage Group"} id:${chatId ?? "unknown"}`
145
+ : `${normalizeIMessageHandle(sender)} id:${sender}`;
146
+ const createdAt = message.created_at
147
+ ? Date.parse(message.created_at)
148
+ : undefined;
149
+ const body = formatAgentEnvelope({
150
+ surface: "iMessage",
151
+ from: fromLabel,
152
+ timestamp: createdAt,
153
+ body: bodyText,
154
+ });
155
+ const ctxPayload = {
156
+ Body: body,
157
+ From: isGroup ? `group:${chatId}` : `imessage:${sender}`,
158
+ To: chatTarget || `imessage:${sender}`,
159
+ ChatType: isGroup ? "group" : "direct",
160
+ GroupSubject: isGroup ? (message.chat_name ?? undefined) : undefined,
161
+ GroupMembers: isGroup
162
+ ? (message.participants ?? []).filter(Boolean).join(", ")
163
+ : undefined,
164
+ SenderName: sender,
165
+ Surface: "imessage",
166
+ MessageSid: message.id ? String(message.id) : undefined,
167
+ Timestamp: createdAt,
168
+ MediaPath: mediaPath,
169
+ MediaType: mediaType,
170
+ MediaUrl: mediaPath,
171
+ WasMentioned: mentioned,
172
+ };
173
+ if (!isGroup) {
174
+ const sessionCfg = cfg.session;
175
+ const mainKey = (sessionCfg?.mainKey ?? "main").trim() || "main";
176
+ const storePath = resolveStorePath(sessionCfg?.store);
177
+ const to = chatTarget || sender;
178
+ if (to) {
179
+ await updateLastRoute({
180
+ storePath,
181
+ sessionKey: mainKey,
182
+ channel: "imessage",
183
+ to,
184
+ });
185
+ }
186
+ }
187
+ if (shouldLogVerbose()) {
188
+ const preview = body.slice(0, 200).replace(/\n/g, "\\n");
189
+ logVerbose(`imessage inbound: chatId=${chatId ?? "unknown"} from=${ctxPayload.From} len=${body.length} preview="${preview}"`);
190
+ }
191
+ let blockSendChain = Promise.resolve();
192
+ const sendBlockReply = (payload) => {
193
+ if (!payload?.text &&
194
+ !payload?.mediaUrl &&
195
+ !(payload?.mediaUrls?.length ?? 0)) {
196
+ return;
197
+ }
198
+ blockSendChain = blockSendChain
199
+ .then(async () => {
200
+ await deliverReplies({
201
+ replies: [payload],
202
+ target: ctxPayload.To,
203
+ client,
204
+ runtime,
205
+ maxBytes: mediaMaxBytes,
206
+ textLimit,
207
+ });
208
+ })
209
+ .catch((err) => {
210
+ runtime.error?.(danger(`imessage block reply failed: ${String(err)}`));
211
+ });
212
+ };
213
+ const replyResult = await getReplyFromConfig(ctxPayload, { onBlockReply: sendBlockReply }, cfg);
214
+ const replies = replyResult
215
+ ? Array.isArray(replyResult)
216
+ ? replyResult
217
+ : [replyResult]
218
+ : [];
219
+ await blockSendChain;
220
+ if (replies.length === 0)
221
+ return;
222
+ await deliverReplies({
223
+ replies,
224
+ target: ctxPayload.To,
225
+ client,
226
+ runtime,
227
+ maxBytes: mediaMaxBytes,
228
+ textLimit,
229
+ });
230
+ };
231
+ const client = await createIMessageRpcClient({
232
+ cliPath: opts.cliPath ?? cfg.imessage?.cliPath,
233
+ dbPath: opts.dbPath ?? cfg.imessage?.dbPath,
234
+ runtime,
235
+ onNotification: (msg) => {
236
+ if (msg.method === "message") {
237
+ void handleMessage(msg.params).catch((err) => {
238
+ runtime.error?.(`imessage: handler failed: ${String(err)}`);
239
+ });
240
+ }
241
+ else if (msg.method === "error") {
242
+ runtime.error?.(`imessage: watch error ${JSON.stringify(msg.params)}`);
243
+ }
244
+ },
245
+ });
246
+ let subscriptionId = null;
247
+ const abort = opts.abortSignal;
248
+ const onAbort = () => {
249
+ if (subscriptionId) {
250
+ void client.request("watch.unsubscribe", {
251
+ subscription: subscriptionId,
252
+ });
253
+ }
254
+ void client.stop();
255
+ };
256
+ abort?.addEventListener("abort", onAbort, { once: true });
257
+ try {
258
+ const result = await client.request("watch.subscribe", { attachments: includeAttachments });
259
+ subscriptionId = result?.subscription ?? null;
260
+ await client.waitForClose();
261
+ }
262
+ catch (err) {
263
+ if (abort?.aborted)
264
+ return;
265
+ runtime.error?.(danger(`imessage: monitor failed: ${String(err)}`));
266
+ throw err;
267
+ }
268
+ finally {
269
+ abort?.removeEventListener("abort", onAbort);
270
+ await client.stop();
271
+ }
272
+ }
@@ -0,0 +1,26 @@
1
+ import { detectBinary } from "../commands/onboard-helpers.js";
2
+ import { loadConfig } from "../config/config.js";
3
+ import { createIMessageRpcClient } from "./client.js";
4
+ export async function probeIMessage(timeoutMs = 2000) {
5
+ const cfg = loadConfig();
6
+ const cliPath = cfg.imessage?.cliPath?.trim() || "imsg";
7
+ const dbPath = cfg.imessage?.dbPath?.trim();
8
+ const detected = await detectBinary(cliPath);
9
+ if (!detected) {
10
+ return { ok: false, error: `imsg not found (${cliPath})` };
11
+ }
12
+ const client = await createIMessageRpcClient({
13
+ cliPath,
14
+ dbPath,
15
+ });
16
+ try {
17
+ await client.request("chats.list", { limit: 1 }, { timeoutMs });
18
+ return { ok: true };
19
+ }
20
+ catch (err) {
21
+ return { ok: false, error: String(err) };
22
+ }
23
+ finally {
24
+ await client.stop();
25
+ }
26
+ }