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,159 @@
1
+ const LEGACY_CONFIG_RULES = [
2
+ {
3
+ path: ["routing", "allowFrom"],
4
+ message: "routing.allowFrom was removed; use whatsapp.allowFrom instead (run `clawdbot doctor` to migrate).",
5
+ },
6
+ {
7
+ path: ["routing", "groupChat", "requireMention"],
8
+ message: 'routing.groupChat.requireMention was removed; use whatsapp/telegram/imessage groups defaults (e.g. whatsapp.groups."*".requireMention) instead (run `clawdbot doctor` to migrate).',
9
+ },
10
+ {
11
+ path: ["telegram", "requireMention"],
12
+ message: 'telegram.requireMention was removed; use telegram.groups."*".requireMention instead (run `clawdbot doctor` to migrate).',
13
+ },
14
+ ];
15
+ const LEGACY_CONFIG_MIGRATIONS = [
16
+ {
17
+ id: "routing.allowFrom->whatsapp.allowFrom",
18
+ describe: "Move routing.allowFrom to whatsapp.allowFrom",
19
+ apply: (raw, changes) => {
20
+ const routing = raw.routing;
21
+ if (!routing || typeof routing !== "object")
22
+ return;
23
+ const allowFrom = routing.allowFrom;
24
+ if (allowFrom === undefined)
25
+ return;
26
+ const whatsapp = raw.whatsapp && typeof raw.whatsapp === "object"
27
+ ? raw.whatsapp
28
+ : {};
29
+ if (whatsapp.allowFrom === undefined) {
30
+ whatsapp.allowFrom = allowFrom;
31
+ changes.push("Moved routing.allowFrom → whatsapp.allowFrom.");
32
+ }
33
+ else {
34
+ changes.push("Removed routing.allowFrom (whatsapp.allowFrom already set).");
35
+ }
36
+ delete routing.allowFrom;
37
+ if (Object.keys(routing).length === 0) {
38
+ delete raw.routing;
39
+ }
40
+ raw.whatsapp = whatsapp;
41
+ },
42
+ },
43
+ {
44
+ id: "routing.groupChat.requireMention->groups.*.requireMention",
45
+ describe: "Move routing.groupChat.requireMention to whatsapp/telegram/imessage groups",
46
+ apply: (raw, changes) => {
47
+ const routing = raw.routing;
48
+ if (!routing || typeof routing !== "object")
49
+ return;
50
+ const groupChat = routing.groupChat &&
51
+ typeof routing.groupChat === "object"
52
+ ? routing.groupChat
53
+ : null;
54
+ if (!groupChat)
55
+ return;
56
+ const requireMention = groupChat.requireMention;
57
+ if (requireMention === undefined)
58
+ return;
59
+ const applyTo = (key) => {
60
+ const section = raw[key] && typeof raw[key] === "object"
61
+ ? raw[key]
62
+ : {};
63
+ const groups = section.groups && typeof section.groups === "object"
64
+ ? section.groups
65
+ : {};
66
+ const defaultKey = "*";
67
+ const entry = groups[defaultKey] && typeof groups[defaultKey] === "object"
68
+ ? groups[defaultKey]
69
+ : {};
70
+ if (entry.requireMention === undefined) {
71
+ entry.requireMention = requireMention;
72
+ groups[defaultKey] = entry;
73
+ section.groups = groups;
74
+ raw[key] = section;
75
+ changes.push(`Moved routing.groupChat.requireMention → ${key}.groups."*".requireMention.`);
76
+ }
77
+ else {
78
+ changes.push(`Removed routing.groupChat.requireMention (${key}.groups."*" already set).`);
79
+ }
80
+ };
81
+ applyTo("whatsapp");
82
+ applyTo("telegram");
83
+ applyTo("imessage");
84
+ delete groupChat.requireMention;
85
+ if (Object.keys(groupChat).length === 0) {
86
+ delete routing.groupChat;
87
+ }
88
+ if (Object.keys(routing).length === 0) {
89
+ delete raw.routing;
90
+ }
91
+ },
92
+ },
93
+ {
94
+ id: "telegram.requireMention->telegram.groups.*.requireMention",
95
+ describe: "Move telegram.requireMention to telegram.groups.*.requireMention",
96
+ apply: (raw, changes) => {
97
+ const telegram = raw.telegram;
98
+ if (!telegram || typeof telegram !== "object")
99
+ return;
100
+ const requireMention = telegram
101
+ .requireMention;
102
+ if (requireMention === undefined)
103
+ return;
104
+ const groups = telegram.groups &&
105
+ typeof telegram.groups === "object"
106
+ ? telegram.groups
107
+ : {};
108
+ const defaultKey = "*";
109
+ const entry = groups[defaultKey] && typeof groups[defaultKey] === "object"
110
+ ? groups[defaultKey]
111
+ : {};
112
+ if (entry.requireMention === undefined) {
113
+ entry.requireMention = requireMention;
114
+ groups[defaultKey] = entry;
115
+ telegram.groups = groups;
116
+ changes.push('Moved telegram.requireMention → telegram.groups."*".requireMention.');
117
+ }
118
+ else {
119
+ changes.push('Removed telegram.requireMention (telegram.groups."*" already set).');
120
+ }
121
+ delete telegram.requireMention;
122
+ if (Object.keys(telegram).length === 0) {
123
+ delete raw.telegram;
124
+ }
125
+ },
126
+ },
127
+ ];
128
+ export function findLegacyConfigIssues(raw) {
129
+ if (!raw || typeof raw !== "object")
130
+ return [];
131
+ const root = raw;
132
+ const issues = [];
133
+ for (const rule of LEGACY_CONFIG_RULES) {
134
+ let cursor = root;
135
+ for (const key of rule.path) {
136
+ if (!cursor || typeof cursor !== "object") {
137
+ cursor = undefined;
138
+ break;
139
+ }
140
+ cursor = cursor[key];
141
+ }
142
+ if (cursor !== undefined) {
143
+ issues.push({ path: rule.path.join("."), message: rule.message });
144
+ }
145
+ }
146
+ return issues;
147
+ }
148
+ export function applyLegacyMigrations(raw) {
149
+ if (!raw || typeof raw !== "object")
150
+ return { next: null, changes: [] };
151
+ const next = structuredClone(raw);
152
+ const changes = [];
153
+ for (const migration of LEGACY_CONFIG_MIGRATIONS) {
154
+ migration.apply(next, changes);
155
+ }
156
+ if (changes.length === 0)
157
+ return { next: null, changes: [] };
158
+ return { next, changes };
159
+ }
@@ -0,0 +1,71 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import { resolveUserPath } from "../utils.js";
4
+ /**
5
+ * Nix mode detection: When CLAWDBOT_NIX_MODE=1, the gateway is running under Nix.
6
+ * In this mode:
7
+ * - No auto-install flows should be attempted
8
+ * - Missing dependencies should produce actionable Nix-specific error messages
9
+ * - Config is managed externally (read-only from Nix perspective)
10
+ */
11
+ export function resolveIsNixMode(env = process.env) {
12
+ return env.CLAWDBOT_NIX_MODE === "1";
13
+ }
14
+ export const isNixMode = resolveIsNixMode();
15
+ /**
16
+ * State directory for mutable data (sessions, logs, caches).
17
+ * Can be overridden via CLAWDBOT_STATE_DIR environment variable.
18
+ * Default: ~/.clawdbot
19
+ */
20
+ export function resolveStateDir(env = process.env, homedir = os.homedir) {
21
+ const override = env.CLAWDBOT_STATE_DIR?.trim();
22
+ if (override)
23
+ return override;
24
+ return path.join(homedir(), ".clawdbot");
25
+ }
26
+ export const STATE_DIR_CLAWDBOT = resolveStateDir();
27
+ /**
28
+ * Config file path (JSON5).
29
+ * Can be overridden via CLAWDBOT_CONFIG_PATH environment variable.
30
+ * Default: ~/.clawdbot/clawdbot.json (or $CLAWDBOT_STATE_DIR/clawdbot.json)
31
+ */
32
+ export function resolveConfigPath(env = process.env, stateDir = resolveStateDir(env, os.homedir)) {
33
+ const override = env.CLAWDBOT_CONFIG_PATH?.trim();
34
+ if (override)
35
+ return override;
36
+ return path.join(stateDir, "clawdbot.json");
37
+ }
38
+ export const CONFIG_PATH_CLAWDBOT = resolveConfigPath();
39
+ export const DEFAULT_GATEWAY_PORT = 18789;
40
+ const OAUTH_FILENAME = "oauth.json";
41
+ /**
42
+ * OAuth credentials storage directory.
43
+ *
44
+ * Precedence:
45
+ * - `CLAWDBOT_OAUTH_DIR` (explicit override)
46
+ * - `CLAWDBOT_STATE_DIR/credentials` (canonical server/default)
47
+ * - `~/.clawdbot/credentials` (legacy default)
48
+ */
49
+ export function resolveOAuthDir(env = process.env, stateDir = resolveStateDir(env, os.homedir)) {
50
+ const override = env.CLAWDBOT_OAUTH_DIR?.trim();
51
+ if (override)
52
+ return resolveUserPath(override);
53
+ return path.join(stateDir, "credentials");
54
+ }
55
+ export function resolveOAuthPath(env = process.env, stateDir = resolveStateDir(env, os.homedir)) {
56
+ return path.join(resolveOAuthDir(env, stateDir), OAUTH_FILENAME);
57
+ }
58
+ export function resolveGatewayPort(cfg, env = process.env) {
59
+ const envRaw = env.CLAWDBOT_GATEWAY_PORT?.trim();
60
+ if (envRaw) {
61
+ const parsed = Number.parseInt(envRaw, 10);
62
+ if (Number.isFinite(parsed) && parsed > 0)
63
+ return parsed;
64
+ }
65
+ const configPort = cfg?.gateway?.port;
66
+ if (typeof configPort === "number" && Number.isFinite(configPort)) {
67
+ if (configPort > 0)
68
+ return configPort;
69
+ }
70
+ return DEFAULT_GATEWAY_PORT;
71
+ }
@@ -0,0 +1,150 @@
1
+ import { VERSION } from "../version.js";
2
+ import { ClawdbotSchema } from "./zod-schema.js";
3
+ const GROUP_LABELS = {
4
+ identity: "Identity",
5
+ wizard: "Wizard",
6
+ logging: "Logging",
7
+ gateway: "Gateway",
8
+ agent: "Agent",
9
+ models: "Models",
10
+ routing: "Routing",
11
+ messages: "Messages",
12
+ session: "Session",
13
+ cron: "Cron",
14
+ hooks: "Hooks",
15
+ ui: "UI",
16
+ browser: "Browser",
17
+ talk: "Talk",
18
+ telegram: "Telegram",
19
+ discord: "Discord",
20
+ slack: "Slack",
21
+ signal: "Signal",
22
+ imessage: "iMessage",
23
+ whatsapp: "WhatsApp",
24
+ skills: "Skills",
25
+ discovery: "Discovery",
26
+ presence: "Presence",
27
+ voicewake: "Voice Wake",
28
+ };
29
+ const GROUP_ORDER = {
30
+ identity: 10,
31
+ wizard: 20,
32
+ gateway: 30,
33
+ agent: 40,
34
+ models: 50,
35
+ routing: 60,
36
+ messages: 70,
37
+ session: 80,
38
+ cron: 90,
39
+ hooks: 100,
40
+ ui: 110,
41
+ browser: 120,
42
+ talk: 130,
43
+ telegram: 140,
44
+ discord: 150,
45
+ slack: 155,
46
+ signal: 160,
47
+ imessage: 170,
48
+ whatsapp: 180,
49
+ skills: 190,
50
+ discovery: 200,
51
+ presence: 210,
52
+ voicewake: 220,
53
+ logging: 900,
54
+ };
55
+ const FIELD_LABELS = {
56
+ "gateway.remote.url": "Remote Gateway URL",
57
+ "gateway.remote.token": "Remote Gateway Token",
58
+ "gateway.remote.password": "Remote Gateway Password",
59
+ "gateway.auth.token": "Gateway Token",
60
+ "gateway.auth.password": "Gateway Password",
61
+ "gateway.controlUi.basePath": "Control UI Base Path",
62
+ "gateway.reload.mode": "Config Reload Mode",
63
+ "gateway.reload.debounceMs": "Config Reload Debounce (ms)",
64
+ "agent.workspace": "Workspace",
65
+ "agent.model": "Default Model",
66
+ "agent.imageModel": "Image Model",
67
+ "agent.modelFallbacks": "Model Fallbacks",
68
+ "agent.imageModelFallbacks": "Image Model Fallbacks",
69
+ "ui.seamColor": "Accent Color",
70
+ "browser.controlUrl": "Browser Control URL",
71
+ "session.agentToAgent.maxPingPongTurns": "Agent-to-Agent Ping-Pong Turns",
72
+ "talk.apiKey": "Talk API Key",
73
+ "telegram.botToken": "Telegram Bot Token",
74
+ "discord.token": "Discord Bot Token",
75
+ "slack.botToken": "Slack Bot Token",
76
+ "slack.appToken": "Slack App Token",
77
+ "signal.account": "Signal Account",
78
+ "imessage.cliPath": "iMessage CLI Path",
79
+ };
80
+ const FIELD_HELP = {
81
+ "gateway.remote.url": "Remote Gateway WebSocket URL (ws:// or wss://).",
82
+ "gateway.auth.token": "Required for multi-machine access or non-loopback binds.",
83
+ "gateway.auth.password": "Required for Tailscale funnel.",
84
+ "gateway.controlUi.basePath": "Optional URL prefix where the Control UI is served (e.g. /clawdbot).",
85
+ "gateway.reload.mode": 'Hot reload strategy for config changes ("hybrid" recommended).',
86
+ "gateway.reload.debounceMs": "Debounce window (ms) before applying config changes.",
87
+ "agent.modelFallbacks": "Ordered fallback models (provider/model). Used when the primary model fails.",
88
+ "agent.imageModel": "Optional image-capable model (provider/model) used by the image tool.",
89
+ "agent.imageModelFallbacks": "Ordered fallback image models (provider/model) used by the image tool.",
90
+ "session.agentToAgent.maxPingPongTurns": "Max reply-back turns between requester and target (0–5).",
91
+ };
92
+ const FIELD_PLACEHOLDERS = {
93
+ "gateway.remote.url": "ws://host:18789",
94
+ "gateway.controlUi.basePath": "/clawdbot",
95
+ };
96
+ const SENSITIVE_PATTERNS = [/token/i, /password/i, /secret/i, /api.?key/i];
97
+ function isSensitivePath(path) {
98
+ return SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));
99
+ }
100
+ function buildBaseHints() {
101
+ const hints = {};
102
+ for (const [group, label] of Object.entries(GROUP_LABELS)) {
103
+ hints[group] = {
104
+ label,
105
+ group: label,
106
+ order: GROUP_ORDER[group],
107
+ };
108
+ }
109
+ for (const [path, label] of Object.entries(FIELD_LABELS)) {
110
+ const current = hints[path];
111
+ hints[path] = current ? { ...current, label } : { label };
112
+ }
113
+ for (const [path, help] of Object.entries(FIELD_HELP)) {
114
+ const current = hints[path];
115
+ hints[path] = current ? { ...current, help } : { help };
116
+ }
117
+ for (const [path, placeholder] of Object.entries(FIELD_PLACEHOLDERS)) {
118
+ const current = hints[path];
119
+ hints[path] = current ? { ...current, placeholder } : { placeholder };
120
+ }
121
+ return hints;
122
+ }
123
+ function applySensitiveHints(hints) {
124
+ const next = { ...hints };
125
+ for (const key of Object.keys(next)) {
126
+ if (isSensitivePath(key)) {
127
+ next[key] = { ...next[key], sensitive: true };
128
+ }
129
+ }
130
+ return next;
131
+ }
132
+ let cached = null;
133
+ export function buildConfigSchema() {
134
+ if (cached)
135
+ return cached;
136
+ const schema = ClawdbotSchema.toJSONSchema({
137
+ target: "draft-07",
138
+ unrepresentable: "any",
139
+ });
140
+ schema.title = "ClawdbotConfig";
141
+ const hints = applySensitiveHints(buildBaseHints());
142
+ const next = {
143
+ schema,
144
+ uiHints: hints,
145
+ version: VERSION,
146
+ generatedAt: new Date().toISOString(),
147
+ };
148
+ cached = next;
149
+ return next;
150
+ }
@@ -0,0 +1,282 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import JSON5 from "json5";
6
+ import { normalizeE164 } from "../utils.js";
7
+ const GROUP_SURFACES = new Set([
8
+ "whatsapp",
9
+ "telegram",
10
+ "discord",
11
+ "signal",
12
+ "imessage",
13
+ "webchat",
14
+ "slack",
15
+ ]);
16
+ export function resolveSessionTranscriptsDir() {
17
+ return path.join(os.homedir(), ".clawdbot", "sessions");
18
+ }
19
+ export function resolveDefaultSessionStorePath() {
20
+ return path.join(resolveSessionTranscriptsDir(), "sessions.json");
21
+ }
22
+ export const DEFAULT_RESET_TRIGGER = "/new";
23
+ export const DEFAULT_RESET_TRIGGERS = ["/new", "/reset"];
24
+ export const DEFAULT_IDLE_MINUTES = 60;
25
+ export function resolveSessionTranscriptPath(sessionId) {
26
+ return path.join(resolveSessionTranscriptsDir(), `${sessionId}.jsonl`);
27
+ }
28
+ export function resolveStorePath(store) {
29
+ if (!store)
30
+ return resolveDefaultSessionStorePath();
31
+ if (store.startsWith("~"))
32
+ return path.resolve(store.replace("~", os.homedir()));
33
+ return path.resolve(store);
34
+ }
35
+ export function resolveMainSessionKey(cfg) {
36
+ if (cfg?.session?.scope === "global")
37
+ return "global";
38
+ return "main";
39
+ }
40
+ function normalizeGroupLabel(raw) {
41
+ const trimmed = raw?.trim().toLowerCase() ?? "";
42
+ if (!trimmed)
43
+ return "";
44
+ const dashed = trimmed.replace(/\s+/g, "-");
45
+ const cleaned = dashed.replace(/[^a-z0-9#@._+-]+/g, "-");
46
+ return cleaned.replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "");
47
+ }
48
+ function shortenGroupId(value) {
49
+ const trimmed = value?.trim() ?? "";
50
+ if (!trimmed)
51
+ return "";
52
+ if (trimmed.length <= 14)
53
+ return trimmed;
54
+ return `${trimmed.slice(0, 6)}...${trimmed.slice(-4)}`;
55
+ }
56
+ export function buildGroupDisplayName(params) {
57
+ const surfaceKey = (params.surface?.trim().toLowerCase() || "group").trim();
58
+ const room = params.room?.trim();
59
+ const space = params.space?.trim();
60
+ const subject = params.subject?.trim();
61
+ const detail = (room && space
62
+ ? `${space}${room.startsWith("#") ? "" : "#"}${room}`
63
+ : room || subject || space || "") || "";
64
+ const fallbackId = params.id?.trim() || params.key.replace(/^group:/, "");
65
+ const rawLabel = detail || fallbackId;
66
+ let token = normalizeGroupLabel(rawLabel);
67
+ if (!token) {
68
+ token = normalizeGroupLabel(shortenGroupId(rawLabel));
69
+ }
70
+ if (!params.room && token.startsWith("#")) {
71
+ token = token.replace(/^#+/, "");
72
+ }
73
+ if (token &&
74
+ !/^[@#]/.test(token) &&
75
+ !token.startsWith("g-") &&
76
+ !token.includes("#")) {
77
+ token = `g-${token}`;
78
+ }
79
+ return token ? `${surfaceKey}:${token}` : surfaceKey;
80
+ }
81
+ export function resolveGroupSessionKey(ctx) {
82
+ const from = typeof ctx.From === "string" ? ctx.From.trim() : "";
83
+ if (!from)
84
+ return null;
85
+ const chatType = ctx.ChatType?.trim().toLowerCase();
86
+ const isGroup = chatType === "group" ||
87
+ from.startsWith("group:") ||
88
+ from.includes("@g.us") ||
89
+ from.includes(":group:") ||
90
+ from.includes(":channel:");
91
+ if (!isGroup)
92
+ return null;
93
+ const surfaceHint = ctx.Surface?.trim().toLowerCase();
94
+ const hasLegacyGroupPrefix = from.startsWith("group:");
95
+ const raw = (hasLegacyGroupPrefix ? from.slice("group:".length) : from).trim();
96
+ let surface;
97
+ let kind;
98
+ let id = "";
99
+ const parseKind = (value) => {
100
+ if (value === "channel")
101
+ return "channel";
102
+ return "group";
103
+ };
104
+ const parseParts = (parts) => {
105
+ if (parts.length >= 2 && GROUP_SURFACES.has(parts[0])) {
106
+ surface = parts[0];
107
+ if (parts.length >= 3) {
108
+ const kindCandidate = parts[1];
109
+ if (["group", "channel"].includes(kindCandidate)) {
110
+ kind = parseKind(kindCandidate);
111
+ id = parts.slice(2).join(":");
112
+ }
113
+ else {
114
+ id = parts.slice(1).join(":");
115
+ }
116
+ }
117
+ else {
118
+ id = parts[1];
119
+ }
120
+ return;
121
+ }
122
+ if (parts.length >= 2 && ["group", "channel"].includes(parts[0])) {
123
+ kind = parseKind(parts[0]);
124
+ id = parts.slice(1).join(":");
125
+ }
126
+ };
127
+ if (hasLegacyGroupPrefix) {
128
+ const legacyParts = raw.split(":").filter(Boolean);
129
+ if (legacyParts.length > 1) {
130
+ parseParts(legacyParts);
131
+ }
132
+ else {
133
+ id = raw;
134
+ }
135
+ }
136
+ else if (from.includes("@g.us") && !from.includes(":")) {
137
+ id = from;
138
+ }
139
+ else {
140
+ parseParts(from.split(":").filter(Boolean));
141
+ if (!id) {
142
+ id = raw || from;
143
+ }
144
+ }
145
+ const resolvedSurface = surface ?? surfaceHint;
146
+ if (!resolvedSurface) {
147
+ const legacy = hasLegacyGroupPrefix ? `group:${raw}` : `group:${from}`;
148
+ return {
149
+ key: legacy,
150
+ id: raw || from,
151
+ legacyKey: legacy,
152
+ chatType: "group",
153
+ };
154
+ }
155
+ const resolvedKind = kind === "channel" ? "channel" : "group";
156
+ const key = `${resolvedSurface}:${resolvedKind}:${id || raw || from}`;
157
+ let legacyKey;
158
+ if (hasLegacyGroupPrefix || from.includes("@g.us")) {
159
+ legacyKey = `group:${id || raw || from}`;
160
+ }
161
+ return {
162
+ key,
163
+ legacyKey,
164
+ surface: resolvedSurface,
165
+ id: id || raw || from,
166
+ chatType: resolvedKind === "channel" ? "room" : "group",
167
+ };
168
+ }
169
+ export function loadSessionStore(storePath) {
170
+ try {
171
+ const raw = fs.readFileSync(storePath, "utf-8");
172
+ const parsed = JSON5.parse(raw);
173
+ if (parsed && typeof parsed === "object") {
174
+ return parsed;
175
+ }
176
+ }
177
+ catch {
178
+ // ignore missing/invalid store; we'll recreate it
179
+ }
180
+ return {};
181
+ }
182
+ export async function saveSessionStore(storePath, store) {
183
+ await fs.promises.mkdir(path.dirname(storePath), { recursive: true });
184
+ const json = JSON.stringify(store, null, 2);
185
+ const tmp = `${storePath}.${process.pid}.${crypto.randomUUID()}.tmp`;
186
+ try {
187
+ await fs.promises.writeFile(tmp, json, "utf-8");
188
+ await fs.promises.rename(tmp, storePath);
189
+ }
190
+ catch (err) {
191
+ const code = err && typeof err === "object" && "code" in err
192
+ ? String(err.code)
193
+ : null;
194
+ if (code === "ENOENT") {
195
+ // In tests the temp session-store directory may be deleted while writes are in-flight.
196
+ // Best-effort: try a direct write (recreating the parent dir), otherwise ignore.
197
+ try {
198
+ await fs.promises.mkdir(path.dirname(storePath), { recursive: true });
199
+ await fs.promises.writeFile(storePath, json, "utf-8");
200
+ }
201
+ catch (err2) {
202
+ const code2 = err2 && typeof err2 === "object" && "code" in err2
203
+ ? String(err2.code)
204
+ : null;
205
+ if (code2 === "ENOENT")
206
+ return;
207
+ throw err2;
208
+ }
209
+ return;
210
+ }
211
+ throw err;
212
+ }
213
+ finally {
214
+ await fs.promises.rm(tmp, { force: true });
215
+ }
216
+ }
217
+ export async function updateLastRoute(params) {
218
+ const { storePath, sessionKey, channel, to } = params;
219
+ const store = loadSessionStore(storePath);
220
+ const existing = store[sessionKey];
221
+ const now = Date.now();
222
+ const next = {
223
+ sessionId: existing?.sessionId ?? crypto.randomUUID(),
224
+ updatedAt: Math.max(existing?.updatedAt ?? 0, now),
225
+ systemSent: existing?.systemSent,
226
+ abortedLastRun: existing?.abortedLastRun,
227
+ thinkingLevel: existing?.thinkingLevel,
228
+ verboseLevel: existing?.verboseLevel,
229
+ providerOverride: existing?.providerOverride,
230
+ modelOverride: existing?.modelOverride,
231
+ sendPolicy: existing?.sendPolicy,
232
+ queueMode: existing?.queueMode,
233
+ inputTokens: existing?.inputTokens,
234
+ outputTokens: existing?.outputTokens,
235
+ totalTokens: existing?.totalTokens,
236
+ modelProvider: existing?.modelProvider,
237
+ model: existing?.model,
238
+ contextTokens: existing?.contextTokens,
239
+ displayName: existing?.displayName,
240
+ chatType: existing?.chatType,
241
+ surface: existing?.surface,
242
+ subject: existing?.subject,
243
+ room: existing?.room,
244
+ space: existing?.space,
245
+ skillsSnapshot: existing?.skillsSnapshot,
246
+ lastChannel: channel,
247
+ lastTo: to?.trim() ? to.trim() : undefined,
248
+ };
249
+ store[sessionKey] = next;
250
+ await saveSessionStore(storePath, store);
251
+ return next;
252
+ }
253
+ // Decide which session bucket to use (per-sender vs global).
254
+ export function deriveSessionKey(scope, ctx) {
255
+ if (scope === "global")
256
+ return "global";
257
+ const resolvedGroup = resolveGroupSessionKey(ctx);
258
+ if (resolvedGroup)
259
+ return resolvedGroup.key;
260
+ const from = ctx.From ? normalizeE164(ctx.From) : "";
261
+ return from || "unknown";
262
+ }
263
+ /**
264
+ * Resolve the session key with a canonical direct-chat bucket (default: "main").
265
+ * All non-group direct chats collapse to this bucket; groups stay isolated.
266
+ */
267
+ export function resolveSessionKey(scope, ctx, mainKey) {
268
+ const explicit = ctx.SessionKey?.trim();
269
+ if (explicit)
270
+ return explicit;
271
+ const raw = deriveSessionKey(scope, ctx);
272
+ if (scope === "global")
273
+ return raw;
274
+ // Default to a single shared direct-chat session called "main"; groups stay isolated.
275
+ const canonical = (mainKey ?? "main").trim() || "main";
276
+ const isGroup = raw.startsWith("group:") ||
277
+ raw.includes(":group:") ||
278
+ raw.includes(":channel:");
279
+ if (!isGroup)
280
+ return canonical;
281
+ return raw;
282
+ }
@@ -0,0 +1,31 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ export function readTalkApiKeyFromProfile(deps = {}) {
5
+ const fsImpl = deps.fs ?? fs;
6
+ const osImpl = deps.os ?? os;
7
+ const pathImpl = deps.path ?? path;
8
+ const home = osImpl.homedir();
9
+ const candidates = [".profile", ".zprofile", ".zshrc", ".bashrc"].map((name) => pathImpl.join(home, name));
10
+ for (const candidate of candidates) {
11
+ if (!fsImpl.existsSync(candidate))
12
+ continue;
13
+ try {
14
+ const text = fsImpl.readFileSync(candidate, "utf-8");
15
+ const match = text.match(/(?:^|\n)\s*(?:export\s+)?ELEVENLABS_API_KEY\s*=\s*["']?([^\n"']+)["']?/);
16
+ const value = match?.[1]?.trim();
17
+ if (value)
18
+ return value;
19
+ }
20
+ catch {
21
+ // Ignore profile read errors.
22
+ }
23
+ }
24
+ return null;
25
+ }
26
+ export function resolveTalkApiKey(env = process.env, deps = {}) {
27
+ const envValue = (env.ELEVENLABS_API_KEY ?? "").trim();
28
+ if (envValue)
29
+ return envValue;
30
+ return readTalkApiKeyFromProfile(deps);
31
+ }
@@ -0,0 +1 @@
1
+ export {};