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,140 @@
1
+ import { DEFAULT_CLAWD_BROWSER_COLOR, DEFAULT_CLAWD_BROWSER_CONTROL_URL, DEFAULT_CLAWD_BROWSER_ENABLED, DEFAULT_CLAWD_BROWSER_PROFILE_NAME, } from "./constants.js";
2
+ import { CDP_PORT_RANGE_START } from "./profiles.js";
3
+ function isLoopbackHost(host) {
4
+ const h = host.trim().toLowerCase();
5
+ return (h === "localhost" ||
6
+ h === "127.0.0.1" ||
7
+ h === "0.0.0.0" ||
8
+ h === "[::1]" ||
9
+ h === "::1" ||
10
+ h === "[::]" ||
11
+ h === "::");
12
+ }
13
+ function normalizeHexColor(raw) {
14
+ const value = (raw ?? "").trim();
15
+ if (!value)
16
+ return DEFAULT_CLAWD_BROWSER_COLOR;
17
+ const normalized = value.startsWith("#") ? value : `#${value}`;
18
+ if (!/^#[0-9a-fA-F]{6}$/.test(normalized))
19
+ return DEFAULT_CLAWD_BROWSER_COLOR;
20
+ return normalized.toUpperCase();
21
+ }
22
+ export function parseHttpUrl(raw, label) {
23
+ const trimmed = raw.trim();
24
+ const parsed = new URL(trimmed);
25
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
26
+ throw new Error(`${label} must be http(s), got: ${parsed.protocol.replace(":", "")}`);
27
+ }
28
+ const port = parsed.port && Number.parseInt(parsed.port, 10) > 0
29
+ ? Number.parseInt(parsed.port, 10)
30
+ : parsed.protocol === "https:"
31
+ ? 443
32
+ : 80;
33
+ if (Number.isNaN(port) || port <= 0 || port > 65535) {
34
+ throw new Error(`${label} has invalid port: ${parsed.port}`);
35
+ }
36
+ return {
37
+ parsed,
38
+ port,
39
+ normalized: parsed.toString().replace(/\/$/, ""),
40
+ };
41
+ }
42
+ /**
43
+ * Ensure the default "clawd" profile exists in the profiles map.
44
+ * Auto-creates it with the legacy CDP port (from browser.cdpUrl) or first port if missing.
45
+ */
46
+ function ensureDefaultProfile(profiles, defaultColor, legacyCdpPort) {
47
+ const result = { ...profiles };
48
+ if (!result[DEFAULT_CLAWD_BROWSER_PROFILE_NAME]) {
49
+ result[DEFAULT_CLAWD_BROWSER_PROFILE_NAME] = {
50
+ cdpPort: legacyCdpPort ?? CDP_PORT_RANGE_START,
51
+ color: defaultColor,
52
+ };
53
+ }
54
+ return result;
55
+ }
56
+ export function resolveBrowserConfig(cfg) {
57
+ const enabled = cfg?.enabled ?? DEFAULT_CLAWD_BROWSER_ENABLED;
58
+ const controlInfo = parseHttpUrl(cfg?.controlUrl ?? DEFAULT_CLAWD_BROWSER_CONTROL_URL, "browser.controlUrl");
59
+ const controlPort = controlInfo.port;
60
+ const defaultColor = normalizeHexColor(cfg?.color);
61
+ const rawCdpUrl = (cfg?.cdpUrl ?? "").trim();
62
+ let cdpInfo;
63
+ if (rawCdpUrl) {
64
+ cdpInfo = parseHttpUrl(rawCdpUrl, "browser.cdpUrl");
65
+ }
66
+ else {
67
+ const derivedPort = controlPort + 1;
68
+ if (derivedPort > 65535) {
69
+ throw new Error(`browser.controlUrl port (${controlPort}) is too high; cannot derive CDP port (${derivedPort})`);
70
+ }
71
+ const derived = new URL(controlInfo.normalized);
72
+ derived.port = String(derivedPort);
73
+ cdpInfo = {
74
+ parsed: derived,
75
+ port: derivedPort,
76
+ normalized: derived.toString().replace(/\/$/, ""),
77
+ };
78
+ }
79
+ const headless = cfg?.headless === true;
80
+ const noSandbox = cfg?.noSandbox === true;
81
+ const attachOnly = cfg?.attachOnly === true;
82
+ const executablePath = cfg?.executablePath?.trim() || undefined;
83
+ const defaultProfile = cfg?.defaultProfile ?? DEFAULT_CLAWD_BROWSER_PROFILE_NAME;
84
+ // Use legacy cdpUrl port for backward compatibility when no profiles configured
85
+ const legacyCdpPort = rawCdpUrl ? cdpInfo.port : undefined;
86
+ const profiles = ensureDefaultProfile(cfg?.profiles, defaultColor, legacyCdpPort);
87
+ const cdpProtocol = cdpInfo.parsed.protocol === "https:" ? "https" : "http";
88
+ return {
89
+ enabled,
90
+ controlUrl: controlInfo.normalized,
91
+ controlHost: controlInfo.parsed.hostname,
92
+ controlPort,
93
+ cdpProtocol,
94
+ cdpHost: cdpInfo.parsed.hostname,
95
+ cdpIsLoopback: isLoopbackHost(cdpInfo.parsed.hostname),
96
+ color: defaultColor,
97
+ executablePath,
98
+ headless,
99
+ noSandbox,
100
+ attachOnly,
101
+ defaultProfile,
102
+ profiles,
103
+ };
104
+ }
105
+ /**
106
+ * Resolve a profile by name from the config.
107
+ * Returns null if the profile doesn't exist.
108
+ */
109
+ export function resolveProfile(resolved, profileName) {
110
+ const profile = resolved.profiles[profileName];
111
+ if (!profile)
112
+ return null;
113
+ const rawProfileUrl = profile.cdpUrl?.trim() ?? "";
114
+ let cdpHost = resolved.cdpHost;
115
+ let cdpPort = profile.cdpPort ?? 0;
116
+ let cdpUrl = "";
117
+ if (rawProfileUrl) {
118
+ const parsed = parseHttpUrl(rawProfileUrl, `browser.profiles.${profileName}.cdpUrl`);
119
+ cdpHost = parsed.parsed.hostname;
120
+ cdpPort = parsed.port;
121
+ cdpUrl = parsed.normalized;
122
+ }
123
+ else if (cdpPort) {
124
+ cdpUrl = `${resolved.cdpProtocol}://${resolved.cdpHost}:${cdpPort}`;
125
+ }
126
+ else {
127
+ throw new Error(`Profile "${profileName}" must define cdpPort or cdpUrl.`);
128
+ }
129
+ return {
130
+ name: profileName,
131
+ cdpPort,
132
+ cdpUrl,
133
+ cdpHost,
134
+ cdpIsLoopback: isLoopbackHost(cdpHost),
135
+ color: profile.color,
136
+ };
137
+ }
138
+ export function shouldStartLocalBrowserServer(resolved) {
139
+ return isLoopbackHost(resolved.controlHost);
140
+ }
@@ -0,0 +1,4 @@
1
+ export const DEFAULT_CLAWD_BROWSER_ENABLED = true;
2
+ export const DEFAULT_CLAWD_BROWSER_CONTROL_URL = "http://127.0.0.1:18791";
3
+ export const DEFAULT_CLAWD_BROWSER_COLOR = "#FF4500";
4
+ export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd";
@@ -0,0 +1,122 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { loadConfig, writeConfigFile } from "../config/config.js";
4
+ import { resolveClawdUserDataDir } from "./chrome.js";
5
+ import { parseHttpUrl, resolveProfile } from "./config.js";
6
+ import { allocateCdpPort, allocateColor, getUsedColors, getUsedPorts, isValidProfileName, } from "./profiles.js";
7
+ import { movePathToTrash } from "./trash.js";
8
+ const HEX_COLOR_RE = /^#[0-9A-Fa-f]{6}$/;
9
+ export function createBrowserProfilesService(ctx) {
10
+ const listProfiles = async () => {
11
+ return await ctx.listProfiles();
12
+ };
13
+ const createProfile = async (params) => {
14
+ const name = params.name.trim();
15
+ const rawCdpUrl = params.cdpUrl?.trim() || undefined;
16
+ if (!isValidProfileName(name)) {
17
+ throw new Error("invalid profile name: use lowercase letters, numbers, and hyphens only");
18
+ }
19
+ const state = ctx.state();
20
+ const resolvedProfiles = state.resolved.profiles;
21
+ if (name in resolvedProfiles) {
22
+ throw new Error(`profile "${name}" already exists`);
23
+ }
24
+ const cfg = loadConfig();
25
+ const rawProfiles = cfg.browser?.profiles ?? {};
26
+ if (name in rawProfiles) {
27
+ throw new Error(`profile "${name}" already exists`);
28
+ }
29
+ const usedColors = getUsedColors(resolvedProfiles);
30
+ const profileColor = params.color && HEX_COLOR_RE.test(params.color)
31
+ ? params.color
32
+ : allocateColor(usedColors);
33
+ let profileConfig;
34
+ if (rawCdpUrl) {
35
+ const parsed = parseHttpUrl(rawCdpUrl, "browser.profiles.cdpUrl");
36
+ profileConfig = { cdpUrl: parsed.normalized, color: profileColor };
37
+ }
38
+ else {
39
+ const usedPorts = getUsedPorts(resolvedProfiles);
40
+ const cdpPort = allocateCdpPort(usedPorts);
41
+ if (cdpPort === null) {
42
+ throw new Error("no available CDP ports in range");
43
+ }
44
+ profileConfig = { cdpPort, color: profileColor };
45
+ }
46
+ const nextConfig = {
47
+ ...cfg,
48
+ browser: {
49
+ ...cfg.browser,
50
+ profiles: {
51
+ ...rawProfiles,
52
+ [name]: profileConfig,
53
+ },
54
+ },
55
+ };
56
+ await writeConfigFile(nextConfig);
57
+ state.resolved.profiles[name] = profileConfig;
58
+ const resolved = resolveProfile(state.resolved, name);
59
+ if (!resolved) {
60
+ throw new Error(`profile "${name}" not found after creation`);
61
+ }
62
+ return {
63
+ ok: true,
64
+ profile: name,
65
+ cdpPort: resolved.cdpPort,
66
+ cdpUrl: resolved.cdpUrl,
67
+ color: resolved.color,
68
+ isRemote: !resolved.cdpIsLoopback,
69
+ };
70
+ };
71
+ const deleteProfile = async (nameRaw) => {
72
+ const name = nameRaw.trim();
73
+ if (!name)
74
+ throw new Error("profile name is required");
75
+ if (!isValidProfileName(name)) {
76
+ throw new Error("invalid profile name");
77
+ }
78
+ const cfg = loadConfig();
79
+ const profiles = cfg.browser?.profiles ?? {};
80
+ if (!(name in profiles)) {
81
+ throw new Error(`profile "${name}" not found`);
82
+ }
83
+ const defaultProfile = cfg.browser?.defaultProfile ?? "clawd";
84
+ if (name === defaultProfile) {
85
+ throw new Error(`cannot delete the default profile "${name}"; change browser.defaultProfile first`);
86
+ }
87
+ let deleted = false;
88
+ const state = ctx.state();
89
+ const resolved = resolveProfile(state.resolved, name);
90
+ if (resolved?.cdpIsLoopback) {
91
+ try {
92
+ await ctx.forProfile(name).stopRunningBrowser();
93
+ }
94
+ catch {
95
+ // ignore
96
+ }
97
+ const userDataDir = resolveClawdUserDataDir(name);
98
+ const profileDir = path.dirname(userDataDir);
99
+ if (fs.existsSync(profileDir)) {
100
+ await movePathToTrash(profileDir);
101
+ deleted = true;
102
+ }
103
+ }
104
+ const { [name]: _removed, ...remainingProfiles } = profiles;
105
+ const nextConfig = {
106
+ ...cfg,
107
+ browser: {
108
+ ...cfg.browser,
109
+ profiles: remainingProfiles,
110
+ },
111
+ };
112
+ await writeConfigFile(nextConfig);
113
+ delete state.resolved.profiles[name];
114
+ state.profiles.delete(name);
115
+ return { ok: true, profile: name, deleted };
116
+ };
117
+ return {
118
+ listProfiles,
119
+ createProfile,
120
+ deleteProfile,
121
+ };
122
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * CDP port allocation for browser profiles.
3
+ *
4
+ * Port range: 18800-18899 (100 profiles max)
5
+ * Ports are allocated once at profile creation and persisted in config.
6
+ *
7
+ * Reserved ports (do not use for CDP):
8
+ * 18789 - Gateway WebSocket
9
+ * 18790 - Bridge
10
+ * 18791 - Browser control server
11
+ * 18792-18799 - Reserved for future one-off services (canvas at 18793)
12
+ */
13
+ export const CDP_PORT_RANGE_START = 18800;
14
+ export const CDP_PORT_RANGE_END = 18899;
15
+ export const PROFILE_NAME_REGEX = /^[a-z0-9][a-z0-9-]*$/;
16
+ export function isValidProfileName(name) {
17
+ if (!name || name.length > 64)
18
+ return false;
19
+ return PROFILE_NAME_REGEX.test(name);
20
+ }
21
+ export function allocateCdpPort(usedPorts) {
22
+ for (let port = CDP_PORT_RANGE_START; port <= CDP_PORT_RANGE_END; port++) {
23
+ if (!usedPorts.has(port))
24
+ return port;
25
+ }
26
+ return null;
27
+ }
28
+ export function getUsedPorts(profiles) {
29
+ if (!profiles)
30
+ return new Set();
31
+ const used = new Set();
32
+ for (const profile of Object.values(profiles)) {
33
+ if (typeof profile.cdpPort === "number") {
34
+ used.add(profile.cdpPort);
35
+ continue;
36
+ }
37
+ const rawUrl = profile.cdpUrl?.trim();
38
+ if (!rawUrl)
39
+ continue;
40
+ try {
41
+ const parsed = new URL(rawUrl);
42
+ const port = parsed.port && Number.parseInt(parsed.port, 10) > 0
43
+ ? Number.parseInt(parsed.port, 10)
44
+ : parsed.protocol === "https:"
45
+ ? 443
46
+ : 80;
47
+ if (!Number.isNaN(port) && port > 0 && port <= 65535) {
48
+ used.add(port);
49
+ }
50
+ }
51
+ catch {
52
+ // ignore invalid URLs
53
+ }
54
+ }
55
+ return used;
56
+ }
57
+ export const PROFILE_COLORS = [
58
+ "#FF4500", // Orange-red (clawd default)
59
+ "#0066CC", // Blue
60
+ "#00AA00", // Green
61
+ "#9933FF", // Purple
62
+ "#FF6699", // Pink
63
+ "#00CCCC", // Cyan
64
+ "#FF9900", // Orange
65
+ "#6666FF", // Indigo
66
+ "#CC3366", // Magenta
67
+ "#339966", // Teal
68
+ ];
69
+ export function allocateColor(usedColors) {
70
+ // Find first unused color from palette
71
+ for (const color of PROFILE_COLORS) {
72
+ if (!usedColors.has(color.toUpperCase())) {
73
+ return color;
74
+ }
75
+ }
76
+ // All colors used, cycle based on count
77
+ const index = usedColors.size % PROFILE_COLORS.length;
78
+ // biome-ignore lint/style/noNonNullAssertion: Array is non-empty constant
79
+ return PROFILE_COLORS[index] ?? PROFILE_COLORS[0];
80
+ }
81
+ export function getUsedColors(profiles) {
82
+ if (!profiles)
83
+ return new Set();
84
+ return new Set(Object.values(profiles).map((p) => p.color.toUpperCase()));
85
+ }
@@ -0,0 +1,2 @@
1
+ export { closePlaywrightBrowserConnection, ensurePageState, getPageForTargetId, refLocator, } from "./pw-session.js";
2
+ export { armDialogViaPlaywright, armFileUploadViaPlaywright, clickViaPlaywright, closePageViaPlaywright, dragViaPlaywright, evaluateViaPlaywright, fillFormViaPlaywright, getConsoleMessagesViaPlaywright, hoverViaPlaywright, navigateViaPlaywright, pdfViaPlaywright, pressKeyViaPlaywright, resizeViewportViaPlaywright, selectOptionViaPlaywright, setInputFilesViaPlaywright, snapshotAiViaPlaywright, takeScreenshotViaPlaywright, typeViaPlaywright, waitForViaPlaywright, } from "./pw-tools-core.js";
@@ -0,0 +1,144 @@
1
+ import { chromium } from "playwright-core";
2
+ import { formatErrorMessage } from "../infra/errors.js";
3
+ import { getChromeWebSocketUrl } from "./chrome.js";
4
+ const pageStates = new WeakMap();
5
+ const observedContexts = new WeakSet();
6
+ const observedPages = new WeakSet();
7
+ const MAX_CONSOLE_MESSAGES = 500;
8
+ let cached = null;
9
+ let connecting = null;
10
+ function normalizeCdpUrl(raw) {
11
+ return raw.replace(/\/$/, "");
12
+ }
13
+ export function ensurePageState(page) {
14
+ const existing = pageStates.get(page);
15
+ if (existing)
16
+ return existing;
17
+ const state = {
18
+ console: [],
19
+ armIdUpload: 0,
20
+ armIdDialog: 0,
21
+ };
22
+ pageStates.set(page, state);
23
+ if (!observedPages.has(page)) {
24
+ observedPages.add(page);
25
+ page.on("console", (msg) => {
26
+ const entry = {
27
+ type: msg.type(),
28
+ text: msg.text(),
29
+ timestamp: new Date().toISOString(),
30
+ location: msg.location(),
31
+ };
32
+ state.console.push(entry);
33
+ if (state.console.length > MAX_CONSOLE_MESSAGES)
34
+ state.console.shift();
35
+ });
36
+ page.on("close", () => {
37
+ pageStates.delete(page);
38
+ observedPages.delete(page);
39
+ });
40
+ }
41
+ return state;
42
+ }
43
+ function observeContext(context) {
44
+ if (observedContexts.has(context))
45
+ return;
46
+ observedContexts.add(context);
47
+ for (const page of context.pages())
48
+ ensurePageState(page);
49
+ context.on("page", (page) => ensurePageState(page));
50
+ }
51
+ function observeBrowser(browser) {
52
+ for (const context of browser.contexts())
53
+ observeContext(context);
54
+ }
55
+ async function connectBrowser(cdpUrl) {
56
+ const normalized = normalizeCdpUrl(cdpUrl);
57
+ if (cached?.cdpUrl === normalized)
58
+ return cached;
59
+ if (connecting)
60
+ return await connecting;
61
+ const connectWithRetry = async () => {
62
+ let lastErr;
63
+ for (let attempt = 0; attempt < 3; attempt += 1) {
64
+ try {
65
+ const timeout = 5000 + attempt * 2000;
66
+ const wsUrl = await getChromeWebSocketUrl(normalized, timeout).catch(() => null);
67
+ const endpoint = wsUrl ?? normalized;
68
+ const browser = await chromium.connectOverCDP(endpoint, { timeout });
69
+ const connected = { browser, cdpUrl: normalized };
70
+ cached = connected;
71
+ observeBrowser(browser);
72
+ browser.on("disconnected", () => {
73
+ if (cached?.browser === browser)
74
+ cached = null;
75
+ });
76
+ return connected;
77
+ }
78
+ catch (err) {
79
+ lastErr = err;
80
+ const delay = 250 + attempt * 250;
81
+ await new Promise((r) => setTimeout(r, delay));
82
+ }
83
+ }
84
+ if (lastErr instanceof Error) {
85
+ throw lastErr;
86
+ }
87
+ const message = lastErr
88
+ ? formatErrorMessage(lastErr)
89
+ : "CDP connect failed";
90
+ throw new Error(message);
91
+ };
92
+ connecting = connectWithRetry().finally(() => {
93
+ connecting = null;
94
+ });
95
+ return await connecting;
96
+ }
97
+ async function getAllPages(browser) {
98
+ const contexts = browser.contexts();
99
+ const pages = contexts.flatMap((c) => c.pages());
100
+ return pages;
101
+ }
102
+ async function pageTargetId(page) {
103
+ const session = await page.context().newCDPSession(page);
104
+ try {
105
+ const info = (await session.send("Target.getTargetInfo"));
106
+ const targetId = String(info?.targetInfo?.targetId ?? "").trim();
107
+ return targetId || null;
108
+ }
109
+ finally {
110
+ await session.detach().catch(() => { });
111
+ }
112
+ }
113
+ async function findPageByTargetId(browser, targetId) {
114
+ const pages = await getAllPages(browser);
115
+ for (const page of pages) {
116
+ const tid = await pageTargetId(page).catch(() => null);
117
+ if (tid && tid === targetId)
118
+ return page;
119
+ }
120
+ return null;
121
+ }
122
+ export async function getPageForTargetId(opts) {
123
+ const { browser } = await connectBrowser(opts.cdpUrl);
124
+ const pages = await getAllPages(browser);
125
+ if (!pages.length)
126
+ throw new Error("No pages available in the connected browser.");
127
+ const first = pages[0];
128
+ if (!opts.targetId)
129
+ return first;
130
+ const found = await findPageByTargetId(browser, opts.targetId);
131
+ if (!found)
132
+ throw new Error("tab not found");
133
+ return found;
134
+ }
135
+ export function refLocator(page, ref) {
136
+ return page.locator(`aria-ref=${ref}`);
137
+ }
138
+ export async function closePlaywrightBrowserConnection() {
139
+ const cur = cached;
140
+ cached = null;
141
+ if (!cur)
142
+ return;
143
+ await cur.browser.close().catch(() => { });
144
+ }