@poolzin/pool-bot 2026.2.24 → 2026.2.26

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 (646) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/acp/client.js +207 -18
  3. package/dist/acp/event-mapper.js +87 -22
  4. package/dist/acp/meta.js +12 -6
  5. package/dist/acp/secret-file.js +22 -0
  6. package/dist/agents/agent-paths.js +8 -9
  7. package/dist/agents/agent-scope.js +17 -5
  8. package/dist/agents/auth-profiles/oauth.js +148 -64
  9. package/dist/agents/auth-profiles/session-override.js +13 -7
  10. package/dist/agents/bash-process-registry.test-helpers.js +29 -0
  11. package/dist/agents/bash-tools.exec-approval-request.js +20 -0
  12. package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
  13. package/dist/agents/bash-tools.exec-host-node.js +235 -0
  14. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  15. package/dist/agents/bash-tools.exec-types.js +1 -0
  16. package/dist/agents/bash-tools.process.js +224 -218
  17. package/dist/agents/bedrock-discovery.js +3 -1
  18. package/dist/agents/byteplus-models.js +97 -0
  19. package/dist/agents/chutes-oauth.js +1 -0
  20. package/dist/agents/cli-runner/helpers.js +4 -0
  21. package/dist/agents/compaction.js +41 -14
  22. package/dist/agents/content-blocks.js +16 -0
  23. package/dist/agents/doubao-models.js +121 -0
  24. package/dist/agents/failover-error.js +2 -0
  25. package/dist/agents/huggingface-models.js +5 -3
  26. package/dist/agents/live-model-filter.js +5 -0
  27. package/dist/agents/minimax-vlm.js +10 -8
  28. package/dist/agents/model-auth.js +6 -0
  29. package/dist/agents/model-catalog.js +3 -1
  30. package/dist/agents/model-fallback.js +96 -101
  31. package/dist/agents/model-selection.js +7 -1
  32. package/dist/agents/models-config.providers.js +364 -165
  33. package/dist/agents/ollama-stream.js +117 -4
  34. package/dist/agents/opencode-zen-models.js +22 -11
  35. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  36. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  37. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  38. package/dist/agents/pi-embedded-helpers.js +1 -1
  39. package/dist/agents/pi-embedded-payloads.js +1 -0
  40. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  41. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  42. package/dist/agents/pi-embedded-runner/google.js +20 -8
  43. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  44. package/dist/agents/pi-embedded-runner/run.js +71 -12
  45. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
  46. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  47. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  48. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  49. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  50. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  51. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  52. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  53. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  54. package/dist/agents/pi-embedded-subscribe.js +9 -4
  55. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  56. package/dist/agents/pi-embedded-utils.js +3 -0
  57. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  58. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  59. package/dist/agents/pi-settings.js +40 -0
  60. package/dist/agents/pi-tools.policy.js +2 -1
  61. package/dist/agents/provider/config-loader.js +1 -1
  62. package/dist/agents/sandbox/browser.js +170 -33
  63. package/dist/agents/sandbox/config-hash.js +14 -27
  64. package/dist/agents/sandbox/config.js +21 -2
  65. package/dist/agents/sandbox/constants.js +2 -0
  66. package/dist/agents/sandbox/docker.js +16 -2
  67. package/dist/agents/sandbox/novnc-auth.js +62 -0
  68. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  69. package/dist/agents/sandbox/shared.js +10 -6
  70. package/dist/agents/sandbox-paths.js +24 -11
  71. package/dist/agents/schema/clean-for-gemini.js +132 -85
  72. package/dist/agents/session-slug.js +10 -5
  73. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  74. package/dist/agents/session-tool-result-guard.js +3 -1
  75. package/dist/agents/session-transcript-repair.js +40 -6
  76. package/dist/agents/skills/bundled-dir.js +19 -5
  77. package/dist/agents/skills/env-overrides.js +124 -43
  78. package/dist/agents/skills/frontmatter.js +6 -6
  79. package/dist/agents/skills/plugin-skills.js +14 -7
  80. package/dist/agents/skills/workspace.js +1 -0
  81. package/dist/agents/skills.test-helpers.js +13 -0
  82. package/dist/agents/stable-stringify.js +12 -0
  83. package/dist/agents/subagent-announce.js +251 -49
  84. package/dist/agents/subagent-lifecycle-events.js +19 -0
  85. package/dist/agents/subagent-registry-cleanup.js +31 -0
  86. package/dist/agents/subagent-registry-completion.js +68 -0
  87. package/dist/agents/subagent-registry-queries.js +117 -0
  88. package/dist/agents/subagent-registry-state.js +46 -0
  89. package/dist/agents/subagent-registry.js +252 -221
  90. package/dist/agents/subagent-registry.mocks.shared.js +12 -0
  91. package/dist/agents/subagent-registry.store.js +1 -0
  92. package/dist/agents/subagent-registry.types.js +1 -0
  93. package/dist/agents/subagent-spawn.js +195 -7
  94. package/dist/agents/system-prompt.js +22 -6
  95. package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
  96. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  97. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  98. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
  99. package/dist/agents/timeout.js +18 -6
  100. package/dist/agents/tool-call-id.js +1 -1
  101. package/dist/agents/tool-display-common.js +162 -29
  102. package/dist/agents/tool-images.js +82 -9
  103. package/dist/agents/tool-policy-shared.js +108 -0
  104. package/dist/agents/tool-policy.js +51 -26
  105. package/dist/agents/tools/browser-tool.js +160 -54
  106. package/dist/agents/tools/canvas-tool.js +27 -1
  107. package/dist/agents/tools/common.js +45 -0
  108. package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
  109. package/dist/agents/tools/discord-actions-guild.js +4 -1
  110. package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
  111. package/dist/agents/tools/gateway-tool.js +3 -1
  112. package/dist/agents/tools/image-tool.js +214 -99
  113. package/dist/agents/tools/nodes-utils.js +1 -10
  114. package/dist/agents/tools/sessions-history-tool.js +140 -108
  115. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  116. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  117. package/dist/agents/tools/subagents-tool.js +2 -1
  118. package/dist/agents/tools/whatsapp-actions.js +10 -2
  119. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  120. package/dist/agents/transcript-policy.js +22 -8
  121. package/dist/agents/venice-models.js +11 -3
  122. package/dist/agents/workspace.js +222 -46
  123. package/dist/auto-reply/commands-registry.data.js +51 -0
  124. package/dist/auto-reply/commands-registry.js +19 -21
  125. package/dist/auto-reply/fallback-state.js +114 -0
  126. package/dist/auto-reply/group-activation.js +10 -5
  127. package/dist/auto-reply/inbound-debounce.js +10 -5
  128. package/dist/auto-reply/model-runtime.js +68 -0
  129. package/dist/auto-reply/reply/abort.js +1 -1
  130. package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
  131. package/dist/auto-reply/reply/agent-runner.js +165 -39
  132. package/dist/auto-reply/reply/bash-command.js +41 -39
  133. package/dist/auto-reply/reply/command-gates.js +25 -0
  134. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  135. package/dist/auto-reply/reply/commands-bash.js +6 -5
  136. package/dist/auto-reply/reply/commands-config.js +30 -28
  137. package/dist/auto-reply/reply/commands-core.js +2 -1
  138. package/dist/auto-reply/reply/commands-info.js +1 -0
  139. package/dist/auto-reply/reply/commands-models.js +65 -14
  140. package/dist/auto-reply/reply/commands-session.js +237 -82
  141. package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
  142. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  143. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  144. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  145. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  146. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  147. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  148. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  149. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  150. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  151. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  152. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  153. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  154. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  155. package/dist/auto-reply/reply/commands-tts.js +10 -5
  156. package/dist/auto-reply/reply/config-value.js +10 -5
  157. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  158. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  159. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  160. package/dist/auto-reply/reply/followup-runner.js +1 -0
  161. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  162. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  163. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  164. package/dist/auto-reply/reply/get-reply.js +71 -12
  165. package/dist/auto-reply/reply/model-selection.js +80 -39
  166. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  167. package/dist/auto-reply/reply/queue/state.js +13 -12
  168. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  169. package/dist/auto-reply/reply/reply-reference.js +9 -8
  170. package/dist/auto-reply/reply/route-reply.js +15 -8
  171. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  172. package/dist/auto-reply/reply/session.js +22 -6
  173. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  174. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  175. package/dist/auto-reply/reply/typing.js +46 -21
  176. package/dist/auto-reply/send-policy.js +14 -7
  177. package/dist/auto-reply/status.js +140 -16
  178. package/dist/auto-reply/templating.js +10 -5
  179. package/dist/auto-reply/thinking.js +7 -16
  180. package/dist/auto-reply/tokens.js +21 -5
  181. package/dist/browser/bridge-server.js +36 -20
  182. package/dist/browser/cdp.helpers.js +7 -14
  183. package/dist/browser/cdp.js +35 -15
  184. package/dist/browser/chrome.profile-decoration.js +7 -4
  185. package/dist/browser/config.js +30 -0
  186. package/dist/browser/extension-relay-auth.js +55 -0
  187. package/dist/browser/extension-relay.js +74 -29
  188. package/dist/browser/navigation-guard.js +39 -0
  189. package/dist/browser/paths.js +77 -0
  190. package/dist/browser/profiles.js +13 -8
  191. package/dist/browser/pw-ai-module.js +10 -5
  192. package/dist/browser/pw-session.js +76 -39
  193. package/dist/browser/pw-tools-core.interactions.js +14 -7
  194. package/dist/browser/pw-tools-core.state.js +12 -6
  195. package/dist/browser/routes/agent.act.js +431 -424
  196. package/dist/browser/routes/agent.shared.js +47 -3
  197. package/dist/browser/routes/agent.snapshot.js +122 -116
  198. package/dist/browser/routes/agent.storage.js +303 -297
  199. package/dist/browser/routes/tabs.js +154 -100
  200. package/dist/browser/server-context.js +7 -0
  201. package/dist/browser/server-lifecycle.js +37 -0
  202. package/dist/build-info.json +3 -3
  203. package/dist/channels/allow-from.js +26 -0
  204. package/dist/channels/allowlists/resolve-utils.js +43 -19
  205. package/dist/channels/channel-config.js +14 -7
  206. package/dist/channels/draft-stream-loop.js +7 -0
  207. package/dist/channels/model-overrides.js +82 -0
  208. package/dist/channels/plugins/account-action-gate.js +13 -0
  209. package/dist/channels/plugins/message-actions.js +10 -0
  210. package/dist/channels/plugins/normalize/imessage.js +14 -7
  211. package/dist/channels/plugins/normalize/slack.js +10 -5
  212. package/dist/channels/plugins/normalize/telegram.js +14 -7
  213. package/dist/channels/plugins/outbound/discord.js +80 -8
  214. package/dist/channels/plugins/outbound/signal.js +11 -11
  215. package/dist/channels/plugins/setup-helpers.js +10 -5
  216. package/dist/channels/sender-label.js +14 -7
  217. package/dist/channels/session.js +4 -2
  218. package/dist/channels/status-reactions.js +297 -0
  219. package/dist/channels/telegram/api.js +18 -0
  220. package/dist/cli/argv.js +84 -21
  221. package/dist/cli/banner.js +3 -2
  222. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  223. package/dist/cli/cli-name.js +11 -11
  224. package/dist/cli/cli-utils.js +13 -3
  225. package/dist/cli/command-format.js +1 -1
  226. package/dist/cli/config-cli.js +1 -1
  227. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  228. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  229. package/dist/cli/daemon-cli/restart-health.js +126 -0
  230. package/dist/cli/daemon-cli/status.gather.js +9 -13
  231. package/dist/cli/daemon-cli/status.print.js +2 -10
  232. package/dist/cli/deps.js +27 -22
  233. package/dist/cli/exec-approvals-cli.js +92 -124
  234. package/dist/cli/gateway-cli/run-loop.js +23 -5
  235. package/dist/cli/memory-cli.js +158 -61
  236. package/dist/cli/node-cli/register.js +14 -5
  237. package/dist/cli/nodes-cli/register.push.js +63 -0
  238. package/dist/cli/nodes-media-utils.js +26 -0
  239. package/dist/cli/outbound-send-deps.js +2 -9
  240. package/dist/cli/outbound-send-mapping.js +11 -0
  241. package/dist/cli/pairing-cli.js +40 -14
  242. package/dist/cli/plugins-cli.js +250 -73
  243. package/dist/cli/ports.js +11 -10
  244. package/dist/cli/program/build-program.js +3 -1
  245. package/dist/cli/program/command-registry.js +214 -136
  246. package/dist/cli/program/command-tree.js +16 -0
  247. package/dist/cli/program/help.js +43 -12
  248. package/dist/cli/program/preaction.js +13 -9
  249. package/dist/cli/program/register.configure.js +3 -18
  250. package/dist/cli/program/register.maintenance.js +2 -2
  251. package/dist/cli/program/register.onboard.js +2 -0
  252. package/dist/cli/program/register.status-health-sessions.js +16 -17
  253. package/dist/cli/program/register.subclis.js +93 -52
  254. package/dist/cli/route.js +12 -8
  255. package/dist/cli/system-cli.js +36 -46
  256. package/dist/cli/test-runtime-capture.js +24 -0
  257. package/dist/cli/update-cli/shared.js +22 -9
  258. package/dist/cli/update-cli/update-command.js +89 -14
  259. package/dist/cli/update-cli/wizard.js +6 -12
  260. package/dist/commands/agent/run-context.js +18 -5
  261. package/dist/commands/agent/session-store.js +17 -4
  262. package/dist/commands/agent.js +185 -89
  263. package/dist/commands/agents.bindings.js +14 -7
  264. package/dist/commands/agents.commands.add.js +13 -9
  265. package/dist/commands/agents.commands.identity.js +12 -6
  266. package/dist/commands/agents.commands.list.js +11 -6
  267. package/dist/commands/agents.config.js +8 -10
  268. package/dist/commands/agents.providers.js +12 -6
  269. package/dist/commands/auth-choice-options.js +103 -75
  270. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  271. package/dist/commands/auth-choice.apply.js +4 -0
  272. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  273. package/dist/commands/auth-choice.apply.openai.js +3 -1
  274. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  275. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  276. package/dist/commands/channels/remove.js +13 -6
  277. package/dist/commands/channels/shared.js +4 -14
  278. package/dist/commands/channels.mock-harness.js +23 -0
  279. package/dist/commands/configure.commands.js +14 -0
  280. package/dist/commands/configure.gateway.js +2 -4
  281. package/dist/commands/configure.js +1 -1
  282. package/dist/commands/configure.shared.js +11 -0
  283. package/dist/commands/daemon-install-helpers.js +2 -2
  284. package/dist/commands/daemon-install-runtime-warning.js +11 -0
  285. package/dist/commands/dashboard.js +12 -10
  286. package/dist/commands/docs.js +14 -8
  287. package/dist/commands/doctor-config-flow.js +11 -9
  288. package/dist/commands/doctor-legacy-config.js +281 -0
  289. package/dist/commands/doctor-state-integrity.js +99 -23
  290. package/dist/commands/doctor-update.js +12 -9
  291. package/dist/commands/models/list.list-command.js +7 -5
  292. package/dist/commands/models/set-image.js +2 -21
  293. package/dist/commands/node-daemon-install-helpers.js +10 -8
  294. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  295. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  296. package/dist/commands/onboard-auth.credentials.js +90 -13
  297. package/dist/commands/onboard-auth.js +1 -1
  298. package/dist/commands/onboard-auth.models.js +6 -5
  299. package/dist/commands/onboard-hooks.js +1 -1
  300. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  301. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  302. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  303. package/dist/commands/onboard-remote.js +14 -7
  304. package/dist/commands/onboard.js +11 -13
  305. package/dist/commands/sandbox-display.js +6 -5
  306. package/dist/commands/sessions.test-helpers.js +61 -0
  307. package/dist/commands/status-all/diagnosis.js +14 -10
  308. package/dist/commands/status-all/format.js +1 -0
  309. package/dist/commands/status.gateway-probe.js +1 -16
  310. package/dist/commands/systemd-linger.js +12 -6
  311. package/dist/config/agent-limits.js +2 -0
  312. package/dist/config/commands.js +32 -15
  313. package/dist/config/config-paths.js +9 -11
  314. package/dist/config/config.js +1 -1
  315. package/dist/config/defaults.js +22 -2
  316. package/dist/config/discord-preview-streaming.js +104 -0
  317. package/dist/config/env-substitution.js +62 -34
  318. package/dist/config/env-vars.js +45 -7
  319. package/dist/config/includes.js +4 -0
  320. package/dist/config/io.js +656 -171
  321. package/dist/config/legacy.migrations.part-1.js +189 -78
  322. package/dist/config/legacy.shared.js +3 -1
  323. package/dist/config/merge-patch.js +54 -4
  324. package/dist/config/prototype-keys.js +4 -0
  325. package/dist/config/redact-snapshot.js +404 -76
  326. package/dist/config/schema.help.js +44 -7
  327. package/dist/config/schema.js +58 -570
  328. package/dist/config/schema.labels.js +38 -6
  329. package/dist/config/sessions/delivery-info.js +10 -3
  330. package/dist/config/sessions/main-session.js +10 -5
  331. package/dist/config/sessions/session-file.js +33 -0
  332. package/dist/config/sessions/session-key.js +10 -5
  333. package/dist/config/sessions/store.js +1 -1
  334. package/dist/config/sessions.js +1 -0
  335. package/dist/config/validation.js +140 -85
  336. package/dist/config/zod-schema.agent-runtime.js +11 -0
  337. package/dist/config/zod-schema.hooks.js +40 -11
  338. package/dist/config/zod-schema.installs.js +20 -0
  339. package/dist/config/zod-schema.js +156 -20
  340. package/dist/config/zod-schema.providers-core.js +78 -4
  341. package/dist/config/zod-schema.providers.js +6 -1
  342. package/dist/config/zod-schema.session.js +41 -2
  343. package/dist/cron/run-log.js +3 -0
  344. package/dist/cron/schedule.js +21 -10
  345. package/dist/cron/service/ops.js +35 -21
  346. package/dist/cron/service/timer.js +116 -16
  347. package/dist/cron/stagger.js +3 -1
  348. package/dist/daemon/cmd-argv.js +21 -0
  349. package/dist/daemon/cmd-set.js +58 -0
  350. package/dist/daemon/service-types.js +1 -0
  351. package/dist/discord/api.js +12 -6
  352. package/dist/discord/draft-chunking.js +22 -0
  353. package/dist/discord/draft-stream.js +124 -0
  354. package/dist/discord/monitor/agent-components.js +1 -1
  355. package/dist/discord/monitor/commands.js +5 -0
  356. package/dist/discord/monitor/exec-approvals.js +357 -162
  357. package/dist/discord/monitor/gateway-plugin.js +2 -1
  358. package/dist/discord/monitor/listeners.js +37 -27
  359. package/dist/discord/monitor/message-handler.js +4 -1
  360. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  361. package/dist/discord/monitor/message-handler.process.js +246 -217
  362. package/dist/discord/monitor/message-utils.js +143 -6
  363. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  364. package/dist/discord/monitor/model-picker.js +651 -0
  365. package/dist/discord/monitor/native-command.js +573 -16
  366. package/dist/discord/monitor/provider.allowlist.js +223 -0
  367. package/dist/discord/monitor/provider.js +275 -347
  368. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  369. package/dist/discord/monitor/reply-delivery.js +123 -16
  370. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  371. package/dist/discord/monitor/thread-bindings.js +4 -0
  372. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  373. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  374. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  375. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  376. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  377. package/dist/discord/resolve-users.js +33 -21
  378. package/dist/discord/send.channels.js +15 -0
  379. package/dist/discord/send.js +3 -2
  380. package/dist/discord/send.outbound.js +82 -26
  381. package/dist/discord/send.permissions.js +83 -30
  382. package/dist/discord/send.reactions.js +8 -4
  383. package/dist/discord/token.js +10 -5
  384. package/dist/discord/voice/command.js +263 -0
  385. package/dist/discord/voice/manager.js +531 -0
  386. package/dist/gateway/auth.js +72 -13
  387. package/dist/gateway/call.js +152 -83
  388. package/dist/gateway/canvas-capability.js +75 -0
  389. package/dist/gateway/client.js +28 -4
  390. package/dist/gateway/config-reload.js +3 -4
  391. package/dist/gateway/control-plane-audit.js +28 -0
  392. package/dist/gateway/control-plane-rate-limit.js +53 -0
  393. package/dist/gateway/control-ui.js +219 -96
  394. package/dist/gateway/events.js +1 -0
  395. package/dist/gateway/hooks-mapping.js +88 -38
  396. package/dist/gateway/hooks.js +109 -54
  397. package/dist/gateway/http-auth-helpers.js +3 -2
  398. package/dist/gateway/http-common.js +22 -0
  399. package/dist/gateway/http-endpoint-helpers.js +1 -0
  400. package/dist/gateway/method-scopes.js +169 -0
  401. package/dist/gateway/net.js +74 -9
  402. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  403. package/dist/gateway/node-registry.js +10 -5
  404. package/dist/gateway/openai-http.js +1 -0
  405. package/dist/gateway/openresponses-http.js +121 -110
  406. package/dist/gateway/origin-check.js +1 -18
  407. package/dist/gateway/probe-auth.js +2 -0
  408. package/dist/gateway/protocol/index.js +4 -2
  409. package/dist/gateway/protocol/schema/cron.js +1 -0
  410. package/dist/gateway/protocol/schema/devices.js +1 -0
  411. package/dist/gateway/protocol/schema/protocol-schemas.js +4 -1
  412. package/dist/gateway/protocol/schema/push.js +18 -0
  413. package/dist/gateway/protocol/schema/sessions.js +6 -0
  414. package/dist/gateway/protocol/schema.js +1 -0
  415. package/dist/gateway/role-policy.js +17 -0
  416. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  417. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  418. package/dist/gateway/server-chat.js +83 -25
  419. package/dist/gateway/server-constants.js +10 -9
  420. package/dist/gateway/server-cron.js +1 -0
  421. package/dist/gateway/server-http.js +247 -54
  422. package/dist/gateway/server-maintenance.js +20 -5
  423. package/dist/gateway/server-methods/agent.js +162 -24
  424. package/dist/gateway/server-methods/chat.js +465 -130
  425. package/dist/gateway/server-methods/config.js +193 -152
  426. package/dist/gateway/server-methods/devices.js +17 -3
  427. package/dist/gateway/server-methods/models.js +11 -1
  428. package/dist/gateway/server-methods/nodes.helpers.js +12 -0
  429. package/dist/gateway/server-methods/nodes.js +251 -69
  430. package/dist/gateway/server-methods/push.js +53 -0
  431. package/dist/gateway/server-methods/sessions.js +64 -8
  432. package/dist/gateway/server-methods/usage.js +162 -75
  433. package/dist/gateway/server-node-events.js +29 -0
  434. package/dist/gateway/server-reload-handlers.js +2 -3
  435. package/dist/gateway/server-runtime-config.js +39 -13
  436. package/dist/gateway/server-runtime-state.js +2 -0
  437. package/dist/gateway/server-startup-memory.js +17 -11
  438. package/dist/gateway/server-ws-runtime.js +1 -0
  439. package/dist/gateway/server.impl.js +296 -139
  440. package/dist/gateway/session-preview.test-helpers.js +11 -0
  441. package/dist/gateway/session-utils.fs.js +32 -34
  442. package/dist/gateway/sessions-resolve.js +17 -5
  443. package/dist/gateway/startup-auth.js +126 -0
  444. package/dist/gateway/test-helpers.agent-results.js +15 -0
  445. package/dist/gateway/test-helpers.mocks.js +37 -14
  446. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  447. package/dist/gateway/test-helpers.server.js +161 -77
  448. package/dist/gateway/tools-invoke-http.js +21 -10
  449. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  450. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  451. package/dist/hooks/bundled/session-memory/handler.js +170 -38
  452. package/dist/hooks/frontmatter.js +6 -6
  453. package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
  454. package/dist/hooks/gmail-watcher.js +11 -6
  455. package/dist/hooks/internal-hooks.js +11 -1
  456. package/dist/hooks/llm-slug-generator.js +4 -1
  457. package/dist/hooks/workspace.js +47 -17
  458. package/dist/imessage/accounts.js +9 -20
  459. package/dist/imessage/monitor/inbound-processing.js +2 -1
  460. package/dist/infra/archive-path.js +49 -0
  461. package/dist/infra/archive.js +174 -73
  462. package/dist/infra/control-ui-assets.js +14 -6
  463. package/dist/infra/device-pairing.js +204 -144
  464. package/dist/infra/env.js +10 -5
  465. package/dist/infra/exec-approvals-allowlist.js +141 -70
  466. package/dist/infra/exec-approvals-analysis.js +78 -20
  467. package/dist/infra/exec-approvals.js +5 -17
  468. package/dist/infra/exec-safe-bin-policy.js +277 -0
  469. package/dist/infra/fixed-window-rate-limit.js +33 -0
  470. package/dist/infra/fs-safe.js +71 -39
  471. package/dist/infra/gateway-lock.js +6 -2
  472. package/dist/infra/git-root.js +61 -0
  473. package/dist/infra/heartbeat-active-hours.js +2 -2
  474. package/dist/infra/heartbeat-reason.js +40 -0
  475. package/dist/infra/heartbeat-runner.js +72 -32
  476. package/dist/infra/heartbeat-wake.js +6 -12
  477. package/dist/infra/host-env-security-policy.json +19 -0
  478. package/dist/infra/host-env-security.js +66 -0
  479. package/dist/infra/install-source-utils.js +91 -7
  480. package/dist/infra/net/ssrf.js +131 -38
  481. package/dist/infra/node-pairing.js +50 -105
  482. package/dist/infra/npm-integrity.js +45 -0
  483. package/dist/infra/npm-pack-install.js +40 -0
  484. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  485. package/dist/infra/outbound/channel-adapters.js +20 -7
  486. package/dist/infra/outbound/channel-selection.js +12 -6
  487. package/dist/infra/outbound/envelope.js +1 -1
  488. package/dist/infra/outbound/format.js +12 -6
  489. package/dist/infra/outbound/message-action-runner.js +107 -327
  490. package/dist/infra/outbound/message.js +59 -36
  491. package/dist/infra/outbound/outbound-policy.js +52 -25
  492. package/dist/infra/outbound/outbound-send-service.js +58 -71
  493. package/dist/infra/outbound/payloads.js +14 -7
  494. package/dist/infra/outbound/session-binding-service.js +123 -0
  495. package/dist/infra/pairing-files.js +10 -0
  496. package/dist/infra/path-guards.js +25 -0
  497. package/dist/infra/plain-object.js +9 -0
  498. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  499. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  500. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  501. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  502. package/dist/infra/push-apns.js +365 -0
  503. package/dist/infra/restart-sentinel.js +16 -1
  504. package/dist/infra/restart.js +229 -26
  505. package/dist/infra/retry-policy.js +4 -2
  506. package/dist/infra/retry.js +9 -5
  507. package/dist/infra/scp-host.js +54 -0
  508. package/dist/infra/session-cost-usage.js +107 -59
  509. package/dist/infra/session-maintenance-warning.js +3 -1
  510. package/dist/infra/shell-env.js +98 -34
  511. package/dist/infra/ssh-config.js +12 -6
  512. package/dist/infra/system-run-command.js +49 -4
  513. package/dist/infra/update-channels.js +10 -5
  514. package/dist/infra/update-startup.js +86 -9
  515. package/dist/line/accounts.js +5 -7
  516. package/dist/line/bot-access.js +8 -20
  517. package/dist/line/bot-handlers.js +3 -1
  518. package/dist/link-understanding/detect.js +15 -7
  519. package/dist/media/constants.js +15 -6
  520. package/dist/media/image-ops.js +7 -0
  521. package/dist/media/inbound-path-policy.js +114 -0
  522. package/dist/media/input-files.js +16 -0
  523. package/dist/media/local-roots.js +3 -2
  524. package/dist/media-understanding/apply.js +4 -1
  525. package/dist/media-understanding/concurrency.js +8 -20
  526. package/dist/memory/backend-config.js +45 -6
  527. package/dist/memory/embeddings.js +10 -4
  528. package/dist/memory/fs-utils.js +23 -0
  529. package/dist/memory/manager-search.js +12 -6
  530. package/dist/memory/manager-sync-ops.js +12 -2
  531. package/dist/memory/qmd-manager.js +466 -53
  532. package/dist/memory/query-expansion.js +167 -3
  533. package/dist/memory/status-format.js +10 -5
  534. package/dist/memory/sync-memory-files.js +1 -1
  535. package/dist/memory/test-manager.js +8 -0
  536. package/dist/node-host/invoke-system-run.js +281 -0
  537. package/dist/node-host/invoke.js +55 -337
  538. package/dist/pairing/pairing-store.js +22 -0
  539. package/dist/plugin-sdk/allow-from.js +1 -1
  540. package/dist/plugin-sdk/command-auth.js +3 -1
  541. package/dist/plugin-sdk/index.js +6 -3
  542. package/dist/plugin-sdk/temp-path.js +47 -0
  543. package/dist/plugin-sdk/webhook-targets.js +32 -0
  544. package/dist/plugins/bundled-dir.js +9 -6
  545. package/dist/plugins/discovery.js +217 -23
  546. package/dist/plugins/hook-runner-global.js +16 -0
  547. package/dist/plugins/hooks.js +50 -0
  548. package/dist/plugins/install.js +28 -16
  549. package/dist/plugins/loader.js +192 -26
  550. package/dist/plugins/logger.js +8 -0
  551. package/dist/plugins/manifest-registry.js +3 -0
  552. package/dist/plugins/path-safety.js +34 -0
  553. package/dist/plugins/registry.js +5 -2
  554. package/dist/plugins/runtime/index.js +271 -206
  555. package/dist/plugins/runtime.js +3 -17
  556. package/dist/plugins/update.js +78 -12
  557. package/dist/process/spawn-utils.js +14 -7
  558. package/dist/providers/github-copilot-models.js +4 -1
  559. package/dist/providers/github-copilot-token.js +11 -6
  560. package/dist/providers/qwen-portal-oauth.js +14 -6
  561. package/dist/routing/account-id.js +30 -0
  562. package/dist/routing/resolve-route.js +3 -7
  563. package/dist/routing/session-key.js +2 -16
  564. package/dist/security/audit-channel.js +100 -20
  565. package/dist/security/audit-extra.async.js +505 -179
  566. package/dist/security/audit-extra.js +12 -2
  567. package/dist/security/audit-extra.sync.js +421 -35
  568. package/dist/security/audit-fs.js +31 -13
  569. package/dist/security/audit.js +180 -370
  570. package/dist/security/dm-policy-shared.js +68 -0
  571. package/dist/security/external-content.js +46 -14
  572. package/dist/security/fix.js +49 -85
  573. package/dist/security/scan-paths.js +20 -0
  574. package/dist/security/secret-equal.js +3 -7
  575. package/dist/security/windows-acl.js +30 -15
  576. package/dist/shared/entry-status.js +6 -0
  577. package/dist/shared/frontmatter.js +5 -5
  578. package/dist/shared/node-list-parse.js +13 -0
  579. package/dist/shared/node-match.js +11 -4
  580. package/dist/shared/operator-scope-compat.js +42 -0
  581. package/dist/shared/text-chunking.js +29 -0
  582. package/dist/signal/accounts.js +7 -20
  583. package/dist/signal/monitor/event-handler.js +3 -1
  584. package/dist/slack/accounts.js +6 -19
  585. package/dist/slack/actions.js +11 -3
  586. package/dist/slack/blocks.test-helpers.js +31 -0
  587. package/dist/slack/monitor/auth.js +1 -1
  588. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  589. package/dist/slack/monitor/mrkdwn.js +8 -0
  590. package/dist/slack/monitor/replies.js +15 -7
  591. package/dist/slack/monitor/slash.js +22 -13
  592. package/dist/slack/resolve-channels.js +10 -5
  593. package/dist/slack/send.js +102 -12
  594. package/dist/slack/stream-mode.js +10 -0
  595. package/dist/slack/streaming.js +4 -2
  596. package/dist/telegram/accounts.js +19 -14
  597. package/dist/telegram/bot/helpers.js +3 -5
  598. package/dist/telegram/bot-access.js +35 -36
  599. package/dist/telegram/bot-handlers.js +120 -148
  600. package/dist/telegram/bot-message-context.js +68 -9
  601. package/dist/telegram/bot-message-dispatch.js +477 -210
  602. package/dist/telegram/bot-native-commands.js +16 -0
  603. package/dist/telegram/draft-stream.js +44 -8
  604. package/dist/telegram/inline-buttons.js +5 -15
  605. package/dist/telegram/monitor.js +11 -7
  606. package/dist/telegram/network-config.js +19 -7
  607. package/dist/telegram/reasoning-lane-coordinator.js +128 -0
  608. package/dist/telegram/send.js +3 -2
  609. package/dist/telegram/sent-message-cache.js +5 -6
  610. package/dist/telegram/status-reaction-variants.js +208 -0
  611. package/dist/telegram/sticker-cache.js +11 -9
  612. package/dist/terminal/prompt-select-styled.js +9 -0
  613. package/dist/terminal/theme.js +12 -12
  614. package/dist/test-utils/command-runner.js +6 -0
  615. package/dist/test-utils/internal-hook-event-payload.js +10 -0
  616. package/dist/test-utils/model-auth-mock.js +12 -0
  617. package/dist/test-utils/provider-usage-fetch.js +14 -0
  618. package/dist/test-utils/temp-home.js +33 -0
  619. package/dist/tts/tts.js +80 -567
  620. package/dist/tui/components/chat-log.js +50 -8
  621. package/dist/tui/theme/theme.js +10 -12
  622. package/dist/tui/tui-command-handlers.js +36 -27
  623. package/dist/tui/tui-event-handlers.js +122 -32
  624. package/dist/tui/tui-local-shell.js +16 -6
  625. package/dist/tui/tui.js +236 -48
  626. package/dist/utils/account-id.js +2 -4
  627. package/dist/utils/boolean.js +10 -5
  628. package/dist/utils/directive-tags.js +11 -0
  629. package/dist/utils/mask-api-key.js +10 -0
  630. package/dist/utils/queue-helpers.js +67 -12
  631. package/dist/utils/run-with-concurrency.js +39 -0
  632. package/dist/web/auto-reply/deliver-reply.js +8 -4
  633. package/dist/web/auto-reply/mentions.js +10 -5
  634. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  635. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  636. package/dist/web/inbound/access-control.js +5 -2
  637. package/dist/web/login-qr.js +12 -6
  638. package/dist/web/media.js +126 -15
  639. package/docs/tools/slash-commands.md +5 -1
  640. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  641. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  642. package/extensions/feishu/src/external-keys.ts +19 -0
  643. package/extensions/lobster/src/windows-spawn.ts +193 -0
  644. package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
  645. package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
  646. package/package.json +1 -1
@@ -16,6 +16,30 @@ function normalizeTimeoutMs(raw, fallback) {
16
16
  const value = typeof raw === "number" && Number.isFinite(raw) ? Math.floor(raw) : fallback;
17
17
  return value < 0 ? fallback : value;
18
18
  }
19
+ function normalizeStringList(raw) {
20
+ if (!Array.isArray(raw) || raw.length === 0) {
21
+ return undefined;
22
+ }
23
+ const values = raw
24
+ .map((value) => value.trim())
25
+ .filter((value) => value.length > 0);
26
+ return values.length > 0 ? values : undefined;
27
+ }
28
+ function resolveBrowserSsrFPolicy(cfg) {
29
+ const allowPrivateNetwork = cfg?.ssrfPolicy?.allowPrivateNetwork;
30
+ const allowedHostnames = normalizeStringList(cfg?.ssrfPolicy?.allowedHostnames);
31
+ const hostnameAllowlist = normalizeStringList(cfg?.ssrfPolicy?.hostnameAllowlist);
32
+ if (allowPrivateNetwork === undefined &&
33
+ allowedHostnames === undefined &&
34
+ hostnameAllowlist === undefined) {
35
+ return undefined;
36
+ }
37
+ return {
38
+ ...(allowPrivateNetwork === true ? { allowPrivateNetwork: true } : {}),
39
+ ...(allowedHostnames ? { allowedHostnames } : {}),
40
+ ...(hostnameAllowlist ? { hostnameAllowlist } : {}),
41
+ };
42
+ }
19
43
  export function parseHttpUrl(raw, label) {
20
44
  const trimmed = raw.trim();
21
45
  const parsed = new URL(trimmed);
@@ -113,6 +137,10 @@ export function resolveBrowserConfig(cfg, rootConfig) {
113
137
  (profiles[DEFAULT_BROWSER_DEFAULT_PROFILE_NAME]
114
138
  ? DEFAULT_BROWSER_DEFAULT_PROFILE_NAME
115
139
  : DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
140
+ const ssrfPolicy = resolveBrowserSsrFPolicy(cfg);
141
+ const extraArgs = Array.isArray(cfg?.extraArgs)
142
+ ? cfg.extraArgs.filter((a) => typeof a === "string" && a.trim().length > 0)
143
+ : [];
116
144
  return {
117
145
  enabled,
118
146
  evaluateEnabled,
@@ -129,6 +157,8 @@ export function resolveBrowserConfig(cfg, rootConfig) {
129
157
  attachOnly,
130
158
  defaultProfile,
131
159
  profiles,
160
+ ssrfPolicy,
161
+ extraArgs,
132
162
  };
133
163
  }
134
164
  /**
@@ -0,0 +1,55 @@
1
+ import { createHmac } from "node:crypto";
2
+ import { loadConfig } from "../config/config.js";
3
+ const RELAY_TOKEN_CONTEXT = "poolbot-extension-relay-v1";
4
+ const DEFAULT_RELAY_PROBE_TIMEOUT_MS = 500;
5
+ const POOLBOT_RELAY_BROWSER = "PoolBot/extension-relay";
6
+ function resolveGatewayAuthToken() {
7
+ const envToken = process.env.POOLBOT_GATEWAY_TOKEN?.trim() ?? process.env.CLAWDBOT_GATEWAY_TOKEN?.trim();
8
+ if (envToken) {
9
+ return envToken;
10
+ }
11
+ try {
12
+ const cfg = loadConfig();
13
+ const configToken = cfg.gateway?.auth?.token?.trim();
14
+ if (configToken) {
15
+ return configToken;
16
+ }
17
+ }
18
+ catch {
19
+ // ignore config read failures; caller can fallback to per-process random token
20
+ }
21
+ return null;
22
+ }
23
+ function deriveRelayAuthToken(gatewayToken, port) {
24
+ return createHmac("sha256", gatewayToken).update(`${RELAY_TOKEN_CONTEXT}:${port}`).digest("hex");
25
+ }
26
+ export function resolveRelayAuthTokenForPort(port) {
27
+ const gatewayToken = resolveGatewayAuthToken();
28
+ if (gatewayToken) {
29
+ return deriveRelayAuthToken(gatewayToken, port);
30
+ }
31
+ throw new Error("extension relay requires gateway auth token (set gateway.auth.token or POOLBOT_GATEWAY_TOKEN)");
32
+ }
33
+ export async function probeAuthenticatedPoolBotRelay(params) {
34
+ const ctrl = new AbortController();
35
+ const timer = setTimeout(() => ctrl.abort(), params.timeoutMs ?? DEFAULT_RELAY_PROBE_TIMEOUT_MS);
36
+ try {
37
+ const versionUrl = new URL("/json/version", `${params.baseUrl}/`).toString();
38
+ const res = await fetch(versionUrl, {
39
+ signal: ctrl.signal,
40
+ headers: { [params.relayAuthHeader]: params.relayAuthToken },
41
+ });
42
+ if (!res.ok) {
43
+ return false;
44
+ }
45
+ const body = (await res.json());
46
+ const browserName = typeof body?.Browser === "string" ? body.Browser.trim() : "";
47
+ return browserName === POOLBOT_RELAY_BROWSER;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ finally {
53
+ clearTimeout(timer);
54
+ }
55
+ }
@@ -1,8 +1,8 @@
1
- import { randomBytes } from "node:crypto";
2
1
  import { createServer } from "node:http";
3
2
  import WebSocket, { WebSocketServer } from "ws";
4
3
  import { isLoopbackAddress, isLoopbackHost } from "../gateway/net.js";
5
4
  import { rawDataToString } from "../infra/ws.js";
5
+ import { probeAuthenticatedPoolBotRelay, resolveRelayAuthTokenForPort, } from "./extension-relay-auth.js";
6
6
  const RELAY_AUTH_HEADER = "x-poolbot-relay-token";
7
7
  function headerValue(value) {
8
8
  if (!value) {
@@ -16,14 +16,32 @@ function headerValue(value) {
16
16
  function getHeader(req, name) {
17
17
  return headerValue(req.headers[name.toLowerCase()]);
18
18
  }
19
+ function getRelayAuthTokenFromRequest(req, url) {
20
+ const headerToken = getHeader(req, RELAY_AUTH_HEADER)?.trim();
21
+ if (headerToken) {
22
+ return headerToken;
23
+ }
24
+ const queryToken = url?.searchParams.get("token")?.trim();
25
+ if (queryToken) {
26
+ return queryToken;
27
+ }
28
+ return undefined;
29
+ }
30
+ function parseUrlPort(parsed) {
31
+ const port = parsed.port?.trim() !== "" ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80;
32
+ if (!Number.isFinite(port) || port <= 0 || port > 65535) {
33
+ return null;
34
+ }
35
+ return port;
36
+ }
19
37
  function parseBaseUrl(raw) {
20
38
  const parsed = new URL(raw.trim().replace(/\/$/, ""));
21
39
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
22
40
  throw new Error(`extension relay cdpUrl must be http(s), got ${parsed.protocol}`);
23
41
  }
24
42
  const host = parsed.hostname;
25
- const port = parsed.port?.trim() !== "" ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80;
26
- if (!Number.isFinite(port) || port <= 0 || port > 65535) {
43
+ const port = parseUrlPort(parsed);
44
+ if (!port) {
27
45
  throw new Error(`extension relay cdpUrl has invalid port: ${parsed.port || "(empty)"}`);
28
46
  }
29
47
  return { host, port, baseUrl: parsed.toString().replace(/\/$/, "") };
@@ -47,23 +65,24 @@ function rejectUpgrade(socket, status, bodyText) {
47
65
  // ignore
48
66
  }
49
67
  }
50
- const serversByPort = new Map();
51
- const relayAuthByPort = new Map();
68
+ const relayRuntimeByPort = new Map();
69
+ function isAddrInUseError(err) {
70
+ return (typeof err === "object" &&
71
+ err !== null &&
72
+ "code" in err &&
73
+ err.code === "EADDRINUSE");
74
+ }
52
75
  function relayAuthTokenForUrl(url) {
53
76
  try {
54
77
  const parsed = new URL(url);
55
78
  if (!isLoopbackHost(parsed.hostname)) {
56
79
  return null;
57
80
  }
58
- const port = parsed.port?.trim() !== ""
59
- ? Number(parsed.port)
60
- : parsed.protocol === "https:" || parsed.protocol === "wss:"
61
- ? 443
62
- : 80;
63
- if (!Number.isFinite(port)) {
81
+ const port = parseUrlPort(parsed);
82
+ if (!port) {
64
83
  return null;
65
84
  }
66
- return relayAuthByPort.get(port) ?? null;
85
+ return relayRuntimeByPort.get(port)?.relayAuthToken ?? null;
67
86
  }
68
87
  catch {
69
88
  return null;
@@ -81,10 +100,11 @@ export async function ensureChromeExtensionRelayServer(opts) {
81
100
  if (!isLoopbackHost(info.host)) {
82
101
  throw new Error(`extension relay requires loopback cdpUrl host (got ${info.host})`);
83
102
  }
84
- const existing = serversByPort.get(info.port);
103
+ const existing = relayRuntimeByPort.get(info.port);
85
104
  if (existing) {
86
- return existing;
105
+ return existing.server;
87
106
  }
107
+ const relayAuthToken = resolveRelayAuthTokenForPort(info.port);
88
108
  let extensionWs = null;
89
109
  const cdpClients = new Set();
90
110
  const connectedTargets = new Map();
@@ -144,9 +164,9 @@ export async function ensureChromeExtensionRelayServer(opts) {
144
164
  case "Browser.getVersion":
145
165
  return {
146
166
  protocolVersion: "1.3",
147
- product: "Chrome/PoolBot-Extension-Relay",
167
+ product: "Chrome/Pool Bot-Extension-Relay",
148
168
  revision: "0",
149
- userAgent: "PoolBot-Extension-Relay",
169
+ userAgent: "Pool Bot-Extension-Relay",
150
170
  jsVersion: "V8",
151
171
  };
152
172
  case "Browser.setDownloadBehavior":
@@ -207,7 +227,6 @@ export async function ensureChromeExtensionRelayServer(opts) {
207
227
  }
208
228
  }
209
229
  };
210
- const relayAuthToken = randomBytes(32).toString("base64url");
211
230
  const server = createServer((req, res) => {
212
231
  const url = new URL(req.url ?? "/", info.baseUrl);
213
232
  const path = url.pathname;
@@ -333,6 +352,11 @@ export async function ensureChromeExtensionRelayServer(opts) {
333
352
  return;
334
353
  }
335
354
  if (pathname === "/extension") {
355
+ const token = getRelayAuthTokenFromRequest(req, url);
356
+ if (!token || token !== relayAuthToken) {
357
+ rejectUpgrade(socket, 401, "Unauthorized");
358
+ return;
359
+ }
336
360
  if (extensionWs) {
337
361
  rejectUpgrade(socket, 409, "Extension already connected");
338
362
  return;
@@ -343,7 +367,7 @@ export async function ensureChromeExtensionRelayServer(opts) {
343
367
  return;
344
368
  }
345
369
  if (pathname === "/cdp") {
346
- const token = getHeader(req, RELAY_AUTH_HEADER);
370
+ const token = getRelayAuthTokenFromRequest(req, url);
347
371
  if (!token || token !== relayAuthToken) {
348
372
  rejectUpgrade(socket, 401, "Unauthorized");
349
373
  return;
@@ -548,10 +572,34 @@ export async function ensureChromeExtensionRelayServer(opts) {
548
572
  cdpClients.delete(ws);
549
573
  });
550
574
  });
551
- await new Promise((resolve, reject) => {
552
- server.listen(info.port, info.host, () => resolve());
553
- server.once("error", reject);
554
- });
575
+ try {
576
+ await new Promise((resolve, reject) => {
577
+ server.listen(info.port, info.host, () => resolve());
578
+ server.once("error", reject);
579
+ });
580
+ }
581
+ catch (err) {
582
+ if (isAddrInUseError(err) &&
583
+ (await probeAuthenticatedPoolBotRelay({
584
+ baseUrl: info.baseUrl,
585
+ relayAuthHeader: RELAY_AUTH_HEADER,
586
+ relayAuthToken,
587
+ }))) {
588
+ const existingRelay = {
589
+ host: info.host,
590
+ port: info.port,
591
+ baseUrl: info.baseUrl,
592
+ cdpWsUrl: `ws://${info.host}:${info.port}/cdp`,
593
+ extensionConnected: () => false,
594
+ stop: async () => {
595
+ relayRuntimeByPort.delete(info.port);
596
+ },
597
+ };
598
+ relayRuntimeByPort.set(info.port, { server: existingRelay, relayAuthToken });
599
+ return existingRelay;
600
+ }
601
+ throw err;
602
+ }
555
603
  const addr = server.address();
556
604
  const port = addr?.port ?? info.port;
557
605
  const host = info.host;
@@ -563,8 +611,7 @@ export async function ensureChromeExtensionRelayServer(opts) {
563
611
  cdpWsUrl: `ws://${host}:${port}/cdp`,
564
612
  extensionConnected: () => Boolean(extensionWs),
565
613
  stop: async () => {
566
- serversByPort.delete(port);
567
- relayAuthByPort.delete(port);
614
+ relayRuntimeByPort.delete(port);
568
615
  try {
569
616
  extensionWs?.close(1001, "server stopping");
570
617
  }
@@ -586,17 +633,15 @@ export async function ensureChromeExtensionRelayServer(opts) {
586
633
  wssCdp.close();
587
634
  },
588
635
  };
589
- relayAuthByPort.set(port, relayAuthToken);
590
- serversByPort.set(port, relay);
636
+ relayRuntimeByPort.set(port, { server: relay, relayAuthToken });
591
637
  return relay;
592
638
  }
593
639
  export async function stopChromeExtensionRelayServer(opts) {
594
640
  const info = parseBaseUrl(opts.cdpUrl);
595
- const existing = serversByPort.get(info.port);
641
+ const existing = relayRuntimeByPort.get(info.port);
596
642
  if (!existing) {
597
643
  return false;
598
644
  }
599
- await existing.stop();
600
- relayAuthByPort.delete(info.port);
645
+ await existing.server.stop();
601
646
  return true;
602
647
  }
@@ -0,0 +1,39 @@
1
+ import { resolvePinnedHostnameWithPolicy, } from "../infra/net/ssrf.js";
2
+ const NETWORK_NAVIGATION_PROTOCOLS = new Set(["http:", "https:"]);
3
+ const SAFE_NON_NETWORK_URLS = new Set(["about:blank"]);
4
+ function isAllowedNonNetworkNavigationUrl(parsed) {
5
+ // Keep non-network navigation explicit; about:blank is the only allowed bootstrap URL.
6
+ return SAFE_NON_NETWORK_URLS.has(parsed.href);
7
+ }
8
+ export class InvalidBrowserNavigationUrlError extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "InvalidBrowserNavigationUrlError";
12
+ }
13
+ }
14
+ export function withBrowserNavigationPolicy(ssrfPolicy) {
15
+ return ssrfPolicy ? { ssrfPolicy } : {};
16
+ }
17
+ export async function assertBrowserNavigationAllowed(opts) {
18
+ const rawUrl = String(opts.url ?? "").trim();
19
+ if (!rawUrl) {
20
+ throw new InvalidBrowserNavigationUrlError("url is required");
21
+ }
22
+ let parsed;
23
+ try {
24
+ parsed = new URL(rawUrl);
25
+ }
26
+ catch {
27
+ throw new InvalidBrowserNavigationUrlError(`Invalid URL: ${rawUrl}`);
28
+ }
29
+ if (!NETWORK_NAVIGATION_PROTOCOLS.has(parsed.protocol)) {
30
+ if (isAllowedNonNetworkNavigationUrl(parsed)) {
31
+ return;
32
+ }
33
+ throw new InvalidBrowserNavigationUrlError(`Navigation blocked: unsupported protocol "${parsed.protocol}"`);
34
+ }
35
+ await resolvePinnedHostnameWithPolicy(parsed.hostname, {
36
+ lookupFn: opts.lookupFn,
37
+ policy: opts.ssrfPolicy,
38
+ });
39
+ }
@@ -1,4 +1,6 @@
1
+ import fs from "node:fs/promises";
1
2
  import path from "node:path";
3
+ import { SafeOpenError, openFileWithinRoot } from "../infra/fs-safe.js";
2
4
  import { resolvePreferredPoolbotTmpDir } from "../infra/tmp-poolbot-dir.js";
3
5
  export const DEFAULT_BROWSER_TMP_DIR = resolvePreferredPoolbotTmpDir();
4
6
  export const DEFAULT_TRACE_DIR = DEFAULT_BROWSER_TMP_DIR;
@@ -35,3 +37,78 @@ export function resolvePathsWithinRoot(params) {
35
37
  }
36
38
  return { ok: true, paths: resolvedPaths };
37
39
  }
40
+ export async function resolveExistingPathsWithinRoot(params) {
41
+ const rootDir = path.resolve(params.rootDir);
42
+ let rootRealPath;
43
+ try {
44
+ rootRealPath = await fs.realpath(rootDir);
45
+ }
46
+ catch {
47
+ // Keep historical behavior for missing roots and rely on openFileWithinRoot for final checks.
48
+ rootRealPath = undefined;
49
+ }
50
+ const isInRoot = (relativePath) => Boolean(relativePath) && !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
51
+ const resolveExistingRelativePath = async (requestedPath) => {
52
+ const raw = requestedPath.trim();
53
+ const lexicalPathResult = resolvePathWithinRoot({
54
+ rootDir,
55
+ requestedPath,
56
+ scopeLabel: params.scopeLabel,
57
+ });
58
+ if (lexicalPathResult.ok) {
59
+ return {
60
+ ok: true,
61
+ relativePath: path.relative(rootDir, lexicalPathResult.path),
62
+ fallbackPath: lexicalPathResult.path,
63
+ };
64
+ }
65
+ if (!rootRealPath || !raw || !path.isAbsolute(raw)) {
66
+ return lexicalPathResult;
67
+ }
68
+ try {
69
+ const resolvedExistingPath = await fs.realpath(raw);
70
+ const relativePath = path.relative(rootRealPath, resolvedExistingPath);
71
+ if (!isInRoot(relativePath)) {
72
+ return lexicalPathResult;
73
+ }
74
+ return {
75
+ ok: true,
76
+ relativePath,
77
+ fallbackPath: resolvedExistingPath,
78
+ };
79
+ }
80
+ catch {
81
+ return lexicalPathResult;
82
+ }
83
+ };
84
+ const resolvedPaths = [];
85
+ for (const raw of params.requestedPaths) {
86
+ const pathResult = await resolveExistingRelativePath(raw);
87
+ if (!pathResult.ok) {
88
+ return { ok: false, error: pathResult.error };
89
+ }
90
+ let opened;
91
+ try {
92
+ opened = await openFileWithinRoot({
93
+ rootDir,
94
+ relativePath: pathResult.relativePath,
95
+ });
96
+ resolvedPaths.push(opened.realPath);
97
+ }
98
+ catch (err) {
99
+ if (err instanceof SafeOpenError && err.code === "not-found") {
100
+ // Preserve historical behavior for paths that do not exist yet.
101
+ resolvedPaths.push(pathResult.fallbackPath);
102
+ continue;
103
+ }
104
+ return {
105
+ ok: false,
106
+ error: `Invalid path: must stay within ${params.scopeLabel} and be a regular non-symlink file`,
107
+ };
108
+ }
109
+ finally {
110
+ await opened?.handle.close().catch(() => { });
111
+ }
112
+ }
113
+ return { ok: true, paths: resolvedPaths };
114
+ }
@@ -15,8 +15,9 @@ export const CDP_PORT_RANGE_START = 18800;
15
15
  export const CDP_PORT_RANGE_END = 18899;
16
16
  export const PROFILE_NAME_REGEX = /^[a-z0-9][a-z0-9-]*$/;
17
17
  export function isValidProfileName(name) {
18
- if (!name || name.length > 64)
18
+ if (!name || name.length > 64) {
19
19
  return false;
20
+ }
20
21
  return PROFILE_NAME_REGEX.test(name);
21
22
  }
22
23
  export function allocateCdpPort(usedPorts, range) {
@@ -25,17 +26,20 @@ export function allocateCdpPort(usedPorts, range) {
25
26
  if (!Number.isFinite(start) || !Number.isFinite(end) || start <= 0 || end <= 0) {
26
27
  return null;
27
28
  }
28
- if (start > end)
29
+ if (start > end) {
29
30
  return null;
31
+ }
30
32
  for (let port = start; port <= end; port++) {
31
- if (!usedPorts.has(port))
33
+ if (!usedPorts.has(port)) {
32
34
  return port;
35
+ }
33
36
  }
34
37
  return null;
35
38
  }
36
39
  export function getUsedPorts(profiles) {
37
- if (!profiles)
40
+ if (!profiles) {
38
41
  return new Set();
42
+ }
39
43
  const used = new Set();
40
44
  for (const profile of Object.values(profiles)) {
41
45
  if (typeof profile.cdpPort === "number") {
@@ -43,8 +47,9 @@ export function getUsedPorts(profiles) {
43
47
  continue;
44
48
  }
45
49
  const rawUrl = profile.cdpUrl?.trim();
46
- if (!rawUrl)
50
+ if (!rawUrl) {
47
51
  continue;
52
+ }
48
53
  try {
49
54
  const parsed = new URL(rawUrl);
50
55
  const port = parsed.port && Number.parseInt(parsed.port, 10) > 0
@@ -63,7 +68,7 @@ export function getUsedPorts(profiles) {
63
68
  return used;
64
69
  }
65
70
  export const PROFILE_COLORS = [
66
- "#A855F7", // Purple (poolbot default)
71
+ "#FF4500", // Orange-red (poolbot default)
67
72
  "#0066CC", // Blue
68
73
  "#00AA00", // Green
69
74
  "#9933FF", // Purple
@@ -83,11 +88,11 @@ export function allocateColor(usedColors) {
83
88
  }
84
89
  // All colors used, cycle based on count
85
90
  const index = usedColors.size % PROFILE_COLORS.length;
86
- // biome-ignore lint/style/noNonNullAssertion: Array is non-empty constant
87
91
  return PROFILE_COLORS[index] ?? PROFILE_COLORS[0];
88
92
  }
89
93
  export function getUsedColors(profiles) {
90
- if (!profiles)
94
+ if (!profiles) {
91
95
  return new Set();
96
+ }
92
97
  return new Set(Object.values(profiles).map((p) => p.color.toUpperCase()));
93
98
  }
@@ -3,8 +3,9 @@ let pwAiModuleSoft = null;
3
3
  let pwAiModuleStrict = null;
4
4
  function isModuleNotFoundError(err) {
5
5
  const code = extractErrorCode(err);
6
- if (code === "ERR_MODULE_NOT_FOUND")
6
+ if (code === "ERR_MODULE_NOT_FOUND") {
7
7
  return true;
8
+ }
8
9
  const msg = formatErrorMessage(err);
9
10
  return (msg.includes("Cannot find module") ||
10
11
  msg.includes("Cannot find package") ||
@@ -17,21 +18,25 @@ async function loadPwAiModule(mode) {
17
18
  return await import("./pw-ai.js");
18
19
  }
19
20
  catch (err) {
20
- if (mode === "soft")
21
+ if (mode === "soft") {
21
22
  return null;
22
- if (isModuleNotFoundError(err))
23
+ }
24
+ if (isModuleNotFoundError(err)) {
23
25
  return null;
26
+ }
24
27
  throw err;
25
28
  }
26
29
  }
27
30
  export async function getPwAiModule(opts) {
28
31
  const mode = opts?.mode ?? "soft";
29
32
  if (mode === "soft") {
30
- if (!pwAiModuleSoft)
33
+ if (!pwAiModuleSoft) {
31
34
  pwAiModuleSoft = loadPwAiModule("soft");
35
+ }
32
36
  return await pwAiModuleSoft;
33
37
  }
34
- if (!pwAiModuleStrict)
38
+ if (!pwAiModuleStrict) {
35
39
  pwAiModuleStrict = loadPwAiModule("strict");
40
+ }
36
41
  return await pwAiModuleStrict;
37
42
  }