@poolzin/pool-bot 2026.2.17 → 2026.2.19

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 (488) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/agents/agent-scope.js +4 -0
  3. package/dist/agents/announce-idempotency.js +14 -0
  4. package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +23 -0
  5. package/dist/agents/bash-tools.exec-runtime.js +438 -0
  6. package/dist/agents/bash-tools.shared.js +6 -0
  7. package/dist/agents/cli-runner/reliability.js +61 -0
  8. package/dist/agents/cli-watchdog-defaults.js +11 -0
  9. package/dist/agents/command-poll-backoff.js +63 -0
  10. package/dist/agents/current-time.js +16 -0
  11. package/dist/agents/model-alias-lines.js +18 -0
  12. package/dist/agents/model-auth-label.js +61 -0
  13. package/dist/agents/models-config.e2e-harness.js +115 -0
  14. package/dist/agents/ollama-stream.js +11 -3
  15. package/dist/agents/openclaw-tools.js +135 -0
  16. package/dist/agents/pi-auth-json.js +118 -0
  17. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +147 -0
  18. package/dist/agents/pi-embedded-subscribe.e2e-harness.js +90 -0
  19. package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +63 -0
  20. package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +30 -0
  21. package/dist/agents/pi-extensions/session-manager-runtime-registry.js +23 -0
  22. package/dist/agents/pi-tools.js +2 -0
  23. package/dist/agents/queued-file-writer.js +22 -0
  24. package/dist/agents/sandbox/docker.js +133 -40
  25. package/dist/agents/sandbox/fs-bridge.js +146 -0
  26. package/dist/agents/sandbox/fs-paths.js +205 -0
  27. package/dist/agents/sandbox/hash.js +4 -0
  28. package/dist/agents/sandbox-paths.js +3 -0
  29. package/dist/agents/session-dirs.js +20 -0
  30. package/dist/agents/skills/filter.js +24 -0
  31. package/dist/agents/skills/tools-dir.js +9 -0
  32. package/dist/agents/skills-install-download.js +290 -0
  33. package/dist/agents/skills-install-output.js +30 -0
  34. package/dist/agents/skills-install.download-test-utils.js +36 -0
  35. package/dist/agents/skills.e2e-test-helpers.js +13 -0
  36. package/dist/agents/subagent-announce-queue.js +59 -15
  37. package/dist/agents/subagent-depth.js +137 -0
  38. package/dist/agents/subagent-registry.js +448 -96
  39. package/dist/agents/subagent-spawn.js +262 -0
  40. package/dist/agents/test-helpers/fast-tool-stubs.js +18 -0
  41. package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +74 -0
  42. package/dist/agents/tool-display-common.js +782 -0
  43. package/dist/agents/tools/image-tool.js +1 -1
  44. package/dist/agents/tools/sessions-access.js +178 -0
  45. package/dist/agents/tools/sessions-resolution.js +206 -0
  46. package/dist/agents/tools/subagents-tool.js +616 -0
  47. package/dist/agents/workspace-dir.js +18 -0
  48. package/dist/agents/workspace-dirs.js +14 -0
  49. package/dist/agents/workspace.js +70 -0
  50. package/dist/auto-reply/heartbeat-reply-payload.js +18 -0
  51. package/dist/auto-reply/reply/commands-export-session.js +163 -0
  52. package/dist/auto-reply/reply/commands-mesh.js +245 -0
  53. package/dist/auto-reply/reply/commands-setunset.js +28 -0
  54. package/dist/auto-reply/reply/commands-slash-parse.js +31 -0
  55. package/dist/auto-reply/reply/commands-system-prompt.js +117 -0
  56. package/dist/auto-reply/reply/directive-handling.levels.js +17 -0
  57. package/dist/auto-reply/reply/directive-handling.params.js +1 -0
  58. package/dist/auto-reply/reply/directive-parsing.js +36 -0
  59. package/dist/auto-reply/reply/dispatcher-registry.js +43 -0
  60. package/dist/auto-reply/reply/elevated-unavailable.js +20 -0
  61. package/dist/auto-reply/reply/reply-delivery.js +92 -0
  62. package/dist/auto-reply/reply/session-reset-prompt.js +1 -0
  63. package/dist/auto-reply/reply/session-run-accounting.js +33 -0
  64. package/dist/auto-reply/reply.directive.directive-behavior.e2e-harness.js +115 -0
  65. package/dist/auto-reply/reply.directive.directive-behavior.e2e-mocks.js +12 -0
  66. package/dist/browser/bridge-auth-registry.js +26 -0
  67. package/dist/browser/client-actions-url.js +10 -0
  68. package/dist/browser/control-auth.js +73 -0
  69. package/dist/browser/csrf.js +64 -0
  70. package/dist/browser/http-auth.js +52 -0
  71. package/dist/browser/paths.js +37 -0
  72. package/dist/browser/proxy-files.js +32 -0
  73. package/dist/browser/pw-ai-state.js +7 -0
  74. package/dist/browser/resolved-config-refresh.js +42 -0
  75. package/dist/browser/routes/path-output.js +1 -0
  76. package/dist/browser/server-context.chrome-test-harness.js +20 -0
  77. package/dist/browser/server-middleware.js +31 -0
  78. package/dist/browser/test-port.js +16 -0
  79. package/dist/build-info.json +3 -3
  80. package/dist/canvas-host/file-resolver.js +43 -0
  81. package/dist/channels/account-summary.js +19 -0
  82. package/dist/channels/draft-stream-loop.js +77 -0
  83. package/dist/channels/plugins/account-helpers.js +26 -0
  84. package/dist/channels/telegram/allow-from.js +10 -0
  85. package/dist/cli/browser-cli-resize.js +22 -0
  86. package/dist/cli/browser-cli-shared.js +8 -0
  87. package/dist/cli/clawbot-cli.js +5 -0
  88. package/dist/cli/completion-cli.js +566 -0
  89. package/dist/cli/config-cli.js +63 -5
  90. package/dist/cli/daemon-cli/lifecycle-core.js +256 -0
  91. package/dist/cli/daemon-cli/register-service-commands.js +60 -0
  92. package/dist/cli/daemon-cli-compat.js +80 -0
  93. package/dist/cli/nodes-cli/pairing-render.js +26 -0
  94. package/dist/cli/program/action-reparse.js +17 -0
  95. package/dist/cli/program/command-registry.js +17 -0
  96. package/dist/cli/program/program-context.js +8 -0
  97. package/dist/cli/program/register.subclis.js +7 -0
  98. package/dist/cli/program/routes.js +233 -0
  99. package/dist/cli/qr-cli.js +132 -0
  100. package/dist/cli/requirements-test-fixtures.js +17 -0
  101. package/dist/cli/respawn-policy.js +4 -0
  102. package/dist/cli/shared/parse-port.js +18 -0
  103. package/dist/cli/skills-cli.format.js +241 -0
  104. package/dist/cli/update-cli/progress.js +121 -0
  105. package/dist/cli/update-cli/restart-helper.js +108 -0
  106. package/dist/cli/update-cli/shared.js +196 -0
  107. package/dist/cli/update-cli/status.js +97 -0
  108. package/dist/cli/update-cli/suppress-deprecations.js +17 -0
  109. package/dist/cli/update-cli/update-command.js +506 -0
  110. package/dist/cli/update-cli/wizard.js +130 -0
  111. package/dist/cli/update-cli.js +3 -9
  112. package/dist/cli/windows-argv.js +69 -0
  113. package/dist/commands/auth-choice-legacy.js +20 -0
  114. package/dist/commands/auth-choice.apply-helpers.js +8 -0
  115. package/dist/commands/channel-test-helpers.js +19 -0
  116. package/dist/commands/cleanup-plan.js +10 -0
  117. package/dist/commands/cleanup-utils.js +7 -0
  118. package/dist/commands/config-validation.js +15 -0
  119. package/dist/commands/doctor-completion.js +112 -0
  120. package/dist/commands/doctor-memory-search.js +119 -0
  121. package/dist/commands/doctor-session-locks.js +73 -0
  122. package/dist/commands/doctor.e2e-harness.js +364 -0
  123. package/dist/commands/gateway-presence.js +19 -0
  124. package/dist/commands/model-default.js +35 -0
  125. package/dist/commands/models/fallbacks-shared.js +102 -0
  126. package/dist/commands/models/shared.js +24 -0
  127. package/dist/commands/onboard-auth.config-gateways.js +64 -0
  128. package/dist/commands/onboard-auth.config-litellm.js +45 -0
  129. package/dist/commands/onboard-auth.config-shared.js +116 -0
  130. package/dist/commands/onboard-config.js +16 -0
  131. package/dist/commands/onboard-non-interactive.test-helpers.js +31 -0
  132. package/dist/commands/onboard-provider-auth-flags.js +136 -0
  133. package/dist/commands/openai-codex-oauth.js +40 -0
  134. package/dist/commands/test-runtime-config-helpers.js +21 -0
  135. package/dist/commands/test-wizard-helpers.js +68 -0
  136. package/dist/commands/vllm-setup.js +66 -0
  137. package/dist/compat/legacy-names.js +2 -0
  138. package/dist/config/backup-rotation.js +19 -0
  139. package/dist/config/env-preserve.js +122 -0
  140. package/dist/config/includes-scan.js +78 -0
  141. package/dist/config/plugins-allowlist.js +13 -0
  142. package/dist/config/schema.help.js +256 -0
  143. package/dist/config/schema.hints.js +189 -0
  144. package/dist/config/schema.irc.js +20 -0
  145. package/dist/config/schema.labels.js +317 -0
  146. package/dist/config/sessions/delivery-info.js +40 -0
  147. package/dist/config/types.irc.js +1 -0
  148. package/dist/config/zod-schema.agent-model.js +10 -0
  149. package/dist/config/zod-schema.allowdeny.js +35 -0
  150. package/dist/config/zod-schema.sensitive.js +4 -0
  151. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  152. package/dist/cron/isolated-agent/skills-snapshot.js +26 -0
  153. package/dist/cron/isolated-agent/subagent-followup.js +127 -0
  154. package/dist/cron/isolated-agent.mocks.js +12 -0
  155. package/dist/cron/isolated-agent.test-setup.js +22 -0
  156. package/dist/cron/legacy-delivery.js +43 -0
  157. package/dist/cron/webhook-url.js +22 -0
  158. package/dist/daemon/arg-split.js +40 -0
  159. package/dist/daemon/exec-file.js +23 -0
  160. package/dist/daemon/output.js +6 -0
  161. package/dist/daemon/runtime-format.js +31 -0
  162. package/dist/daemon/schtasks-exec.js +4 -0
  163. package/dist/daemon/service-audit.js +22 -0
  164. package/dist/discord/client.js +41 -0
  165. package/dist/discord/components-registry.js +57 -0
  166. package/dist/discord/components.js +816 -0
  167. package/dist/discord/guilds.js +12 -0
  168. package/dist/discord/monitor/gateway-plugin.js +48 -0
  169. package/dist/discord/monitor/presence.js +30 -0
  170. package/dist/discord/send.components.js +115 -0
  171. package/dist/discord/send.shared.js +4 -0
  172. package/dist/discord/ui.js +26 -0
  173. package/dist/discord/voice-message.js +254 -0
  174. package/dist/gateway/agent-event-assistant-text.js +5 -0
  175. package/dist/gateway/agent-prompt.js +33 -0
  176. package/dist/gateway/auth-rate-limit.js +136 -0
  177. package/dist/gateway/channel-health-monitor.js +114 -0
  178. package/dist/gateway/control-ui-contract.js +1 -0
  179. package/dist/gateway/control-ui-csp.js +15 -0
  180. package/dist/gateway/gateway-config-prompts.shared.js +25 -0
  181. package/dist/gateway/http-auth-helpers.js +18 -0
  182. package/dist/gateway/http-common.js +18 -0
  183. package/dist/gateway/http-endpoint-helpers.js +27 -0
  184. package/dist/gateway/node-invoke-sanitize.js +11 -0
  185. package/dist/gateway/node-invoke-system-run-approval.js +205 -0
  186. package/dist/gateway/probe-auth.js +21 -0
  187. package/dist/gateway/protocol/index.js +7 -2
  188. package/dist/gateway/protocol/schema/mesh.js +54 -0
  189. package/dist/gateway/protocol/schema/protocol-schemas.js +7 -0
  190. package/dist/gateway/protocol/schema.js +1 -0
  191. package/dist/gateway/server/ws-connection/auth-messages.js +54 -0
  192. package/dist/gateway/server-channels.js +11 -0
  193. package/dist/gateway/server-methods/attachment-normalize.js +16 -0
  194. package/dist/gateway/server-methods/base-hash.js +8 -0
  195. package/dist/gateway/server-methods/mesh.js +700 -0
  196. package/dist/gateway/server-methods/nodes.handlers.invoke-result.js +55 -0
  197. package/dist/gateway/server-methods/restart-request.js +13 -0
  198. package/dist/gateway/server-methods/validation.js +8 -0
  199. package/dist/gateway/server.agent.gateway-server-agent.mocks.js +35 -0
  200. package/dist/gateway/server.e2e-registry-helpers.js +1 -0
  201. package/dist/gateway/server.e2e-ws-harness.js +20 -0
  202. package/dist/gateway/test-helpers.js +2 -0
  203. package/dist/gateway/test-helpers.server.js +3 -1
  204. package/dist/gateway/test-http-response.js +12 -0
  205. package/dist/gateway/test-openai-responses-model.js +20 -0
  206. package/dist/gateway/test-temp-config.js +30 -0
  207. package/dist/gateway/test-with-server.js +32 -0
  208. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +46 -0
  209. package/dist/imessage/monitor/abort-handler.js +23 -0
  210. package/dist/imessage/monitor/inbound-processing.js +346 -0
  211. package/dist/imessage/monitor/parse-notification.js +64 -0
  212. package/dist/imessage/target-parsing-helpers.js +92 -0
  213. package/dist/infra/archive.js +244 -20
  214. package/dist/infra/detect-package-manager.js +26 -0
  215. package/dist/infra/exec-approvals-allowlist.js +257 -0
  216. package/dist/infra/exec-approvals-analysis.js +770 -0
  217. package/dist/infra/exec-approvals.js +13 -0
  218. package/dist/infra/file-lock.js +1 -0
  219. package/dist/infra/gemini-auth.js +39 -0
  220. package/dist/infra/heartbeat-active-hours.js +85 -0
  221. package/dist/infra/heartbeat-events-filter.js +50 -0
  222. package/dist/infra/heartbeat-runner.test-utils.js +39 -0
  223. package/dist/infra/http-body.js +265 -0
  224. package/dist/infra/install-package-dir.js +50 -0
  225. package/dist/infra/install-safe-path.js +49 -0
  226. package/dist/infra/json-files.js +49 -0
  227. package/dist/infra/jsonl-socket.js +52 -0
  228. package/dist/infra/map-size.js +14 -0
  229. package/dist/infra/net/hostname.js +7 -0
  230. package/dist/infra/npm-registry-spec.js +39 -0
  231. package/dist/infra/openclaw-root.js +109 -0
  232. package/dist/infra/outbound/delivery-queue.js +214 -0
  233. package/dist/infra/outbound/identity.js +23 -0
  234. package/dist/infra/outbound/message-action-params.js +307 -0
  235. package/dist/infra/outbound/tool-payload.js +21 -0
  236. package/dist/infra/package-json.js +23 -0
  237. package/dist/infra/pairing-files.js +19 -0
  238. package/dist/infra/pairing-token.js +9 -0
  239. package/dist/infra/path-prepend.js +51 -0
  240. package/dist/infra/process-respawn.js +49 -0
  241. package/dist/infra/runtime-status.js +16 -0
  242. package/dist/infra/session-cost-usage.types.js +1 -0
  243. package/dist/infra/session-maintenance-warning.js +89 -0
  244. package/dist/infra/system-run-command.js +78 -0
  245. package/dist/infra/tmp-openclaw-dir.js +81 -0
  246. package/dist/infra/tmp-poolbot-dir.js +2 -0
  247. package/dist/infra/update-channels.js +19 -0
  248. package/dist/line/actions.js +45 -0
  249. package/dist/line/channel-access-token.js +9 -0
  250. package/dist/line/flex-templates/basic-cards.js +332 -0
  251. package/dist/line/flex-templates/common.js +18 -0
  252. package/dist/line/flex-templates/media-control-cards.js +453 -0
  253. package/dist/line/flex-templates/message.js +10 -0
  254. package/dist/line/flex-templates/schedule-cards.js +399 -0
  255. package/dist/line/flex-templates/types.js +1 -0
  256. package/dist/line/webhook-node.js +100 -0
  257. package/dist/line/webhook-utils.js +11 -0
  258. package/dist/logging/timestamps.js +14 -0
  259. package/dist/markdown/whatsapp.js +62 -0
  260. package/dist/media/base64.js +34 -0
  261. package/dist/media/local-roots.js +32 -0
  262. package/dist/media/outbound-attachment.js +10 -0
  263. package/dist/media/read-response-with-limit.js +41 -0
  264. package/dist/media/sniff-mime-from-base64.js +19 -0
  265. package/dist/media-understanding/audio-preflight.js +67 -0
  266. package/dist/media-understanding/fs.js +13 -0
  267. package/dist/media-understanding/output-extract.js +26 -0
  268. package/dist/media-understanding/providers/audio.test-helpers.js +34 -0
  269. package/dist/media-understanding/providers/google/inline-data.js +64 -0
  270. package/dist/media-understanding/providers/shared.js +7 -0
  271. package/dist/media-understanding/runner.entries.js +459 -0
  272. package/dist/memory/batch-error-utils.js +11 -0
  273. package/dist/memory/batch-http.js +27 -0
  274. package/dist/memory/batch-output.js +29 -0
  275. package/dist/memory/batch-runner.js +22 -0
  276. package/dist/memory/batch-upload.js +23 -0
  277. package/dist/memory/batch-utils.js +26 -0
  278. package/dist/memory/embeddings-debug.js +11 -0
  279. package/dist/memory/embeddings-remote-client.js +22 -0
  280. package/dist/memory/embeddings-remote-fetch.js +14 -0
  281. package/dist/memory/manager-embedding-ops.js +616 -0
  282. package/dist/memory/manager-sync-ops.js +953 -0
  283. package/dist/memory/qmd-manager.js +1061 -0
  284. package/dist/memory/qmd-query-parser.js +107 -0
  285. package/dist/memory/qmd-scope.js +93 -0
  286. package/dist/memory/search-manager.js +0 -1
  287. package/dist/memory/sync-index.js +21 -0
  288. package/dist/memory/sync-progress.js +22 -0
  289. package/dist/memory/sync-stale.js +30 -0
  290. package/dist/memory/test-embeddings-mock.js +16 -0
  291. package/dist/memory/test-manager-helpers.js +14 -0
  292. package/dist/memory/test-runtime-mocks.js +11 -0
  293. package/dist/node-host/invoke-browser.js +177 -0
  294. package/dist/node-host/invoke.js +685 -0
  295. package/dist/pairing/setup-code.js +285 -0
  296. package/dist/plugin-sdk/account-id.js +1 -0
  297. package/dist/plugin-sdk/agent-media-payload.js +13 -0
  298. package/dist/plugin-sdk/allow-from.js +47 -0
  299. package/dist/plugin-sdk/command-auth.js +23 -0
  300. package/dist/plugin-sdk/config-paths.js +9 -0
  301. package/dist/plugin-sdk/file-lock.js +116 -0
  302. package/dist/plugin-sdk/json-store.js +31 -0
  303. package/dist/plugin-sdk/onboarding.js +28 -0
  304. package/dist/plugin-sdk/provider-auth-result.js +29 -0
  305. package/dist/plugin-sdk/slack-message-actions.js +133 -0
  306. package/dist/plugin-sdk/status-helpers.js +35 -0
  307. package/dist/plugin-sdk/text-chunking.js +31 -0
  308. package/dist/plugin-sdk/tool-send.js +12 -0
  309. package/dist/plugin-sdk/webhook-path.js +27 -0
  310. package/dist/plugin-sdk/webhook-targets.js +34 -0
  311. package/dist/plugins/hooks.test-helpers.js +21 -0
  312. package/dist/plugins/uninstall.js +171 -0
  313. package/dist/process/supervisor/adapters/child.js +143 -0
  314. package/dist/process/supervisor/adapters/env.js +13 -0
  315. package/dist/process/supervisor/adapters/pty.js +148 -0
  316. package/dist/process/supervisor/index.js +10 -0
  317. package/dist/process/supervisor/registry.js +117 -0
  318. package/dist/process/supervisor/supervisor.js +244 -0
  319. package/dist/process/supervisor/types.js +1 -0
  320. package/dist/providers/google-shared.test-helpers.js +75 -0
  321. package/dist/security/audit-channel.js +419 -0
  322. package/dist/security/audit-tool-policy.js +1 -0
  323. package/dist/security/scan-paths.js +12 -0
  324. package/dist/sessions/input-provenance.js +55 -0
  325. package/dist/sessions/session-key-utils.js +7 -0
  326. package/dist/shared/chat-content.js +31 -0
  327. package/dist/shared/chat-envelope.js +45 -0
  328. package/dist/shared/config-eval.js +117 -0
  329. package/dist/shared/device-auth.js +16 -0
  330. package/dist/shared/entry-metadata.js +9 -0
  331. package/dist/shared/entry-status.js +25 -0
  332. package/dist/shared/frontmatter.js +98 -0
  333. package/dist/shared/model-param-b.js +19 -0
  334. package/dist/shared/net/ipv4.js +17 -0
  335. package/dist/shared/node-match.js +53 -0
  336. package/dist/shared/requirements.js +128 -0
  337. package/dist/shared/subagents-format.js +84 -0
  338. package/dist/shared/usage-aggregates.js +28 -0
  339. package/dist/signal/monitor/mentions.js +45 -0
  340. package/dist/signal/rpc-context.js +19 -0
  341. package/dist/slack/blocks-fallback.js +76 -0
  342. package/dist/slack/blocks-input.js +40 -0
  343. package/dist/slack/draft-stream.js +106 -0
  344. package/dist/slack/message-actions.js +51 -0
  345. package/dist/slack/modal-metadata.js +32 -0
  346. package/dist/slack/monitor/events/interactions.js +462 -0
  347. package/dist/slack/monitor/room-context.js +17 -0
  348. package/dist/slack/stream-mode.js +41 -0
  349. package/dist/telegram/bot-native-command-menu.js +64 -0
  350. package/dist/telegram/bot.media.e2e-harness.js +81 -0
  351. package/dist/telegram/button-types.js +1 -0
  352. package/dist/telegram/group-access.js +65 -0
  353. package/dist/telegram/outbound-params.js +21 -0
  354. package/dist/telegram/poll-vote-cache.js +21 -0
  355. package/dist/terminal/health-style.js +36 -0
  356. package/dist/test-utils/chunk-test-helpers.js +21 -0
  357. package/dist/test-utils/env.js +72 -0
  358. package/dist/test-utils/exec-assertions.js +12 -0
  359. package/dist/test-utils/imessage-test-plugin.js +54 -0
  360. package/dist/test-utils/mock-http-response.js +17 -0
  361. package/dist/test-utils/vitest-mock-fn.js +1 -0
  362. package/dist/tts/tts-core.js +550 -0
  363. package/dist/utils/chunk-items.js +10 -0
  364. package/dist/utils/reaction-level.js +52 -0
  365. package/dist/utils/safe-json.js +22 -0
  366. package/dist/utils/with-timeout.js +14 -0
  367. package/dist/web/media.js +17 -5
  368. package/dist/whatsapp/resolve-outbound-target.js +42 -0
  369. package/dist/wizard/onboarding.completion.js +74 -0
  370. package/extensions/bluebubbles/src/account-resolve.ts +29 -0
  371. package/extensions/bluebubbles/src/monitor-normalize.ts +796 -0
  372. package/extensions/bluebubbles/src/monitor-processing.ts +1007 -0
  373. package/extensions/bluebubbles/src/monitor-reply-cache.ts +185 -0
  374. package/extensions/bluebubbles/src/monitor-shared.ts +51 -0
  375. package/extensions/bluebubbles/src/multipart.ts +32 -0
  376. package/extensions/bluebubbles/src/send-helpers.ts +53 -0
  377. package/extensions/bluebubbles/src/test-harness.ts +50 -0
  378. package/extensions/bluebubbles/src/test-mocks.ts +11 -0
  379. package/extensions/device-pair/index.ts +554 -0
  380. package/extensions/device-pair/poolbot.plugin.json +20 -0
  381. package/extensions/discord/src/channel.js +366 -0
  382. package/extensions/discord/src/runtime.js +10 -0
  383. package/extensions/feishu/index.ts +63 -0
  384. package/extensions/feishu/package.json +37 -0
  385. package/extensions/feishu/poolbot.plugin.json +10 -0
  386. package/extensions/feishu/skills/feishu-doc/SKILL.md +105 -0
  387. package/extensions/feishu/skills/feishu-doc/references/block-types.md +103 -0
  388. package/extensions/feishu/skills/feishu-drive/SKILL.md +97 -0
  389. package/extensions/feishu/skills/feishu-perm/SKILL.md +119 -0
  390. package/extensions/feishu/skills/feishu-wiki/SKILL.md +111 -0
  391. package/extensions/feishu/src/accounts.ts +114 -0
  392. package/extensions/feishu/src/bitable.ts +739 -0
  393. package/extensions/feishu/src/bot.ts +965 -0
  394. package/extensions/feishu/src/channel.ts +351 -0
  395. package/extensions/feishu/src/client.ts +118 -0
  396. package/extensions/feishu/src/config-schema.ts +206 -0
  397. package/extensions/feishu/src/dedup.ts +33 -0
  398. package/extensions/feishu/src/directory.ts +177 -0
  399. package/extensions/feishu/src/doc-schema.ts +47 -0
  400. package/extensions/feishu/src/docx.ts +536 -0
  401. package/extensions/feishu/src/drive-schema.ts +46 -0
  402. package/extensions/feishu/src/drive.ts +227 -0
  403. package/extensions/feishu/src/dynamic-agent.ts +131 -0
  404. package/extensions/feishu/src/media.ts +449 -0
  405. package/extensions/feishu/src/mention.ts +126 -0
  406. package/extensions/feishu/src/monitor.ts +330 -0
  407. package/extensions/feishu/src/onboarding.ts +359 -0
  408. package/extensions/feishu/src/outbound.ts +55 -0
  409. package/extensions/feishu/src/perm-schema.ts +52 -0
  410. package/extensions/feishu/src/perm.ts +173 -0
  411. package/extensions/feishu/src/policy.ts +84 -0
  412. package/extensions/feishu/src/probe.ts +44 -0
  413. package/extensions/feishu/src/reactions.ts +160 -0
  414. package/extensions/feishu/src/reply-dispatcher.ts +239 -0
  415. package/extensions/feishu/src/runtime.ts +14 -0
  416. package/extensions/feishu/src/send-result.ts +29 -0
  417. package/extensions/feishu/src/send.ts +335 -0
  418. package/extensions/feishu/src/streaming-card.ts +223 -0
  419. package/extensions/feishu/src/targets.ts +78 -0
  420. package/extensions/feishu/src/tools-config.ts +21 -0
  421. package/extensions/feishu/src/types.ts +81 -0
  422. package/extensions/feishu/src/typing.ts +80 -0
  423. package/extensions/feishu/src/wiki-schema.ts +55 -0
  424. package/extensions/feishu/src/wiki.ts +232 -0
  425. package/extensions/imessage/src/channel.js +253 -0
  426. package/extensions/imessage/src/runtime.js +10 -0
  427. package/extensions/irc/index.ts +17 -0
  428. package/extensions/irc/package.json +14 -0
  429. package/extensions/irc/poolbot.plugin.json +9 -0
  430. package/extensions/irc/src/accounts.ts +268 -0
  431. package/extensions/irc/src/channel.ts +367 -0
  432. package/extensions/irc/src/client.ts +439 -0
  433. package/extensions/irc/src/config-schema.ts +97 -0
  434. package/extensions/irc/src/connect-options.ts +30 -0
  435. package/extensions/irc/src/control-chars.ts +22 -0
  436. package/extensions/irc/src/inbound.ts +334 -0
  437. package/extensions/irc/src/monitor.ts +147 -0
  438. package/extensions/irc/src/normalize.ts +117 -0
  439. package/extensions/irc/src/onboarding.ts +479 -0
  440. package/extensions/irc/src/policy.ts +157 -0
  441. package/extensions/irc/src/probe.ts +53 -0
  442. package/extensions/irc/src/protocol.ts +169 -0
  443. package/extensions/irc/src/runtime.ts +14 -0
  444. package/extensions/irc/src/send.ts +88 -0
  445. package/extensions/irc/src/types.ts +93 -0
  446. package/extensions/matrix/src/matrix/client-bootstrap.ts +39 -0
  447. package/extensions/mattermost/src/mattermost/monitor-onchar.ts +25 -0
  448. package/extensions/mattermost/src/mattermost/monitor-websocket.ts +221 -0
  449. package/extensions/mattermost/src/mattermost/reactions.ts +130 -0
  450. package/extensions/mattermost/src/mattermost/reconnect.ts +103 -0
  451. package/extensions/minimax-portal-auth/README.md +33 -0
  452. package/extensions/minimax-portal-auth/index.ts +161 -0
  453. package/extensions/minimax-portal-auth/oauth.ts +247 -0
  454. package/extensions/minimax-portal-auth/package.json +15 -0
  455. package/extensions/minimax-portal-auth/poolbot.plugin.json +9 -0
  456. package/extensions/msteams/src/file-lock.ts +1 -0
  457. package/extensions/msteams/src/graph.ts +92 -0
  458. package/extensions/msteams/src/mentions.ts +114 -0
  459. package/extensions/msteams/src/test-runtime.ts +16 -0
  460. package/extensions/openai-codex-auth/README.md +82 -0
  461. package/extensions/openai-codex-auth/index.ts +177 -0
  462. package/extensions/openai-codex-auth/package.json +15 -0
  463. package/extensions/openai-codex-auth/poolbot.plugin.json +9 -0
  464. package/extensions/phone-control/index.ts +421 -0
  465. package/extensions/phone-control/poolbot.plugin.json +10 -0
  466. package/extensions/shared/resolve-target-test-helpers.ts +66 -0
  467. package/extensions/signal/src/channel.js +273 -0
  468. package/extensions/signal/src/runtime.js +10 -0
  469. package/extensions/slack/src/channel.js +489 -0
  470. package/extensions/slack/src/runtime.js +10 -0
  471. package/extensions/talk-voice/index.ts +150 -0
  472. package/extensions/talk-voice/poolbot.plugin.json +10 -0
  473. package/extensions/telegram/src/channel.js +424 -0
  474. package/extensions/telegram/src/runtime.js +10 -0
  475. package/extensions/thread-ownership/index.ts +133 -0
  476. package/extensions/thread-ownership/poolbot.plugin.json +28 -0
  477. package/extensions/tlon/src/account-fields.ts +25 -0
  478. package/extensions/tlon/src/urbit/base-url.ts +57 -0
  479. package/extensions/tlon/src/urbit/channel-client.ts +157 -0
  480. package/extensions/tlon/src/urbit/channel-ops.ts +164 -0
  481. package/extensions/tlon/src/urbit/context.ts +47 -0
  482. package/extensions/tlon/src/urbit/errors.ts +51 -0
  483. package/extensions/tlon/src/urbit/fetch.ts +39 -0
  484. package/extensions/twitch/src/test-fixtures.ts +30 -0
  485. package/extensions/voice-call/src/allowlist.ts +19 -0
  486. package/extensions/whatsapp/src/channel.js +429 -0
  487. package/extensions/whatsapp/src/runtime.js +10 -0
  488. package/package.json +1 -1
@@ -0,0 +1,307 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { assertMediaNotDataUrl, resolveSandboxedMediaSource } from "../../agents/sandbox-paths.js";
5
+ import { readStringParam } from "../../agents/tools/common.js";
6
+ import { extensionForMime } from "../../media/mime.js";
7
+ import { parseSlackTarget } from "../../slack/targets.js";
8
+ import { parseTelegramTarget } from "../../telegram/targets.js";
9
+ import { loadWebMedia } from "../../web/media.js";
10
+ export function readBooleanParam(params, key) {
11
+ const raw = params[key];
12
+ if (typeof raw === "boolean") {
13
+ return raw;
14
+ }
15
+ if (typeof raw === "string") {
16
+ const trimmed = raw.trim().toLowerCase();
17
+ if (trimmed === "true") {
18
+ return true;
19
+ }
20
+ if (trimmed === "false") {
21
+ return false;
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ export function resolveSlackAutoThreadId(params) {
27
+ const context = params.toolContext;
28
+ if (!context?.currentThreadTs || !context.currentChannelId) {
29
+ return undefined;
30
+ }
31
+ // Only mirror auto-threading when Slack would reply in the active thread for this channel.
32
+ if (context.replyToMode !== "all" && context.replyToMode !== "first") {
33
+ return undefined;
34
+ }
35
+ const parsedTarget = parseSlackTarget(params.to, { defaultKind: "channel" });
36
+ if (!parsedTarget || parsedTarget.kind !== "channel") {
37
+ return undefined;
38
+ }
39
+ if (parsedTarget.id.toLowerCase() !== context.currentChannelId.toLowerCase()) {
40
+ return undefined;
41
+ }
42
+ if (context.replyToMode === "first" && context.hasRepliedRef?.value) {
43
+ return undefined;
44
+ }
45
+ return context.currentThreadTs;
46
+ }
47
+ /**
48
+ * Auto-inject Telegram forum topic thread ID when the message tool targets
49
+ * the same chat the session originated from. Mirrors the Slack auto-threading
50
+ * pattern so media, buttons, and other tool-sent messages land in the correct
51
+ * topic instead of the General Topic.
52
+ *
53
+ * Unlike Slack, we do not gate on `replyToMode` here: Telegram forum topics
54
+ * are persistent sub-channels (not ephemeral reply threads), so auto-injection
55
+ * should always apply when the target chat matches.
56
+ */
57
+ export function resolveTelegramAutoThreadId(params) {
58
+ const context = params.toolContext;
59
+ if (!context?.currentThreadTs || !context.currentChannelId) {
60
+ return undefined;
61
+ }
62
+ // Use parseTelegramTarget to extract canonical chatId from both sides,
63
+ // mirroring how Slack uses parseSlackTarget. This handles format variations
64
+ // like `telegram:group:123:topic:456` vs `telegram:123`.
65
+ const parsedTo = parseTelegramTarget(params.to);
66
+ const parsedChannel = parseTelegramTarget(context.currentChannelId);
67
+ if (parsedTo.chatId.toLowerCase() !== parsedChannel.chatId.toLowerCase()) {
68
+ return undefined;
69
+ }
70
+ return context.currentThreadTs;
71
+ }
72
+ function resolveAttachmentMaxBytes(params) {
73
+ const accountId = typeof params.accountId === "string" ? params.accountId.trim() : "";
74
+ const channelCfg = params.cfg.channels?.[params.channel];
75
+ const channelObj = channelCfg && typeof channelCfg === "object"
76
+ ? channelCfg
77
+ : undefined;
78
+ const channelMediaMax = typeof channelObj?.mediaMaxMb === "number" ? channelObj.mediaMaxMb : undefined;
79
+ const accountsObj = channelObj?.accounts && typeof channelObj.accounts === "object"
80
+ ? channelObj.accounts
81
+ : undefined;
82
+ const accountCfg = accountId && accountsObj ? accountsObj[accountId] : undefined;
83
+ const accountMediaMax = accountCfg && typeof accountCfg === "object"
84
+ ? accountCfg.mediaMaxMb
85
+ : undefined;
86
+ // Priority: account-specific > channel-level > global default
87
+ const limitMb = (typeof accountMediaMax === "number" ? accountMediaMax : undefined) ??
88
+ channelMediaMax ??
89
+ params.cfg.agents?.defaults?.mediaMaxMb;
90
+ return typeof limitMb === "number" ? limitMb * 1024 * 1024 : undefined;
91
+ }
92
+ function inferAttachmentFilename(params) {
93
+ const mediaHint = params.mediaHint?.trim();
94
+ if (mediaHint) {
95
+ try {
96
+ if (mediaHint.startsWith("file://")) {
97
+ const filePath = fileURLToPath(mediaHint);
98
+ const base = path.basename(filePath);
99
+ if (base) {
100
+ return base;
101
+ }
102
+ }
103
+ else if (/^https?:\/\//i.test(mediaHint)) {
104
+ const url = new URL(mediaHint);
105
+ const base = path.basename(url.pathname);
106
+ if (base) {
107
+ return base;
108
+ }
109
+ }
110
+ else {
111
+ const base = path.basename(mediaHint);
112
+ if (base) {
113
+ return base;
114
+ }
115
+ }
116
+ }
117
+ catch {
118
+ // fall through to content-type based default
119
+ }
120
+ }
121
+ const ext = params.contentType ? extensionForMime(params.contentType) : undefined;
122
+ return ext ? `attachment${ext}` : "attachment";
123
+ }
124
+ function normalizeBase64Payload(params) {
125
+ if (!params.base64) {
126
+ return { base64: params.base64, contentType: params.contentType };
127
+ }
128
+ const match = /^data:([^;]+);base64,(.*)$/i.exec(params.base64.trim());
129
+ if (!match) {
130
+ return { base64: params.base64, contentType: params.contentType };
131
+ }
132
+ const [, mime, payload] = match;
133
+ return {
134
+ base64: payload,
135
+ contentType: params.contentType ?? mime,
136
+ };
137
+ }
138
+ async function hydrateAttachmentPayload(params) {
139
+ const contentTypeParam = params.contentTypeParam ?? undefined;
140
+ const rawBuffer = readStringParam(params.args, "buffer", { trim: false });
141
+ const normalized = normalizeBase64Payload({
142
+ base64: rawBuffer,
143
+ contentType: contentTypeParam ?? undefined,
144
+ });
145
+ if (normalized.base64 !== rawBuffer && normalized.base64) {
146
+ params.args.buffer = normalized.base64;
147
+ if (normalized.contentType && !contentTypeParam) {
148
+ params.args.contentType = normalized.contentType;
149
+ }
150
+ }
151
+ const filename = readStringParam(params.args, "filename");
152
+ const mediaSource = (params.mediaHint ?? undefined) || (params.fileHint ?? undefined);
153
+ if (!params.dryRun && !readStringParam(params.args, "buffer", { trim: false }) && mediaSource) {
154
+ const maxBytes = resolveAttachmentMaxBytes({
155
+ cfg: params.cfg,
156
+ channel: params.channel,
157
+ accountId: params.accountId,
158
+ });
159
+ // mediaSource already validated by normalizeSandboxMediaList; allow bypass but force explicit readFile.
160
+ const media = await loadWebMedia(mediaSource, {
161
+ maxBytes,
162
+ sandboxValidated: true,
163
+ readFile: (filePath) => fs.readFile(filePath),
164
+ });
165
+ params.args.buffer = media.buffer.toString("base64");
166
+ if (!contentTypeParam && media.contentType) {
167
+ params.args.contentType = media.contentType;
168
+ }
169
+ if (!filename) {
170
+ params.args.filename = inferAttachmentFilename({
171
+ mediaHint: media.fileName ?? mediaSource,
172
+ contentType: media.contentType ?? contentTypeParam ?? undefined,
173
+ });
174
+ }
175
+ }
176
+ else if (!filename) {
177
+ params.args.filename = inferAttachmentFilename({
178
+ mediaHint: mediaSource,
179
+ contentType: contentTypeParam ?? undefined,
180
+ });
181
+ }
182
+ }
183
+ export async function normalizeSandboxMediaParams(params) {
184
+ const sandboxRoot = params.sandboxRoot?.trim();
185
+ const mediaKeys = ["media", "path", "filePath"];
186
+ for (const key of mediaKeys) {
187
+ const raw = readStringParam(params.args, key, { trim: false });
188
+ if (!raw) {
189
+ continue;
190
+ }
191
+ assertMediaNotDataUrl(raw);
192
+ if (!sandboxRoot) {
193
+ continue;
194
+ }
195
+ const normalized = await resolveSandboxedMediaSource({ media: raw, sandboxRoot });
196
+ if (normalized !== raw) {
197
+ params.args[key] = normalized;
198
+ }
199
+ }
200
+ }
201
+ export async function normalizeSandboxMediaList(params) {
202
+ const sandboxRoot = params.sandboxRoot?.trim();
203
+ const normalized = [];
204
+ const seen = new Set();
205
+ for (const value of params.values) {
206
+ const raw = value?.trim();
207
+ if (!raw) {
208
+ continue;
209
+ }
210
+ assertMediaNotDataUrl(raw);
211
+ const resolved = sandboxRoot
212
+ ? await resolveSandboxedMediaSource({ media: raw, sandboxRoot })
213
+ : raw;
214
+ if (seen.has(resolved)) {
215
+ continue;
216
+ }
217
+ seen.add(resolved);
218
+ normalized.push(resolved);
219
+ }
220
+ return normalized;
221
+ }
222
+ async function hydrateAttachmentActionPayload(params) {
223
+ const mediaHint = readStringParam(params.args, "media", { trim: false });
224
+ const fileHint = readStringParam(params.args, "path", { trim: false }) ??
225
+ readStringParam(params.args, "filePath", { trim: false });
226
+ const contentTypeParam = readStringParam(params.args, "contentType") ?? readStringParam(params.args, "mimeType");
227
+ if (params.allowMessageCaptionFallback) {
228
+ const caption = readStringParam(params.args, "caption", { allowEmpty: true })?.trim();
229
+ const message = readStringParam(params.args, "message", { allowEmpty: true })?.trim();
230
+ if (!caption && message) {
231
+ params.args.caption = message;
232
+ }
233
+ }
234
+ await hydrateAttachmentPayload({
235
+ cfg: params.cfg,
236
+ channel: params.channel,
237
+ accountId: params.accountId,
238
+ args: params.args,
239
+ dryRun: params.dryRun,
240
+ contentTypeParam,
241
+ mediaHint,
242
+ fileHint,
243
+ });
244
+ }
245
+ export async function hydrateSetGroupIconParams(params) {
246
+ if (params.action !== "setGroupIcon") {
247
+ return;
248
+ }
249
+ await hydrateAttachmentActionPayload(params);
250
+ }
251
+ export async function hydrateSendAttachmentParams(params) {
252
+ if (params.action !== "sendAttachment") {
253
+ return;
254
+ }
255
+ await hydrateAttachmentActionPayload({ ...params, allowMessageCaptionFallback: true });
256
+ }
257
+ export function parseButtonsParam(params) {
258
+ const raw = params.buttons;
259
+ if (typeof raw !== "string") {
260
+ return;
261
+ }
262
+ const trimmed = raw.trim();
263
+ if (!trimmed) {
264
+ delete params.buttons;
265
+ return;
266
+ }
267
+ try {
268
+ params.buttons = JSON.parse(trimmed);
269
+ }
270
+ catch {
271
+ throw new Error("--buttons must be valid JSON");
272
+ }
273
+ }
274
+ export function parseCardParam(params) {
275
+ const raw = params.card;
276
+ if (typeof raw !== "string") {
277
+ return;
278
+ }
279
+ const trimmed = raw.trim();
280
+ if (!trimmed) {
281
+ delete params.card;
282
+ return;
283
+ }
284
+ try {
285
+ params.card = JSON.parse(trimmed);
286
+ }
287
+ catch {
288
+ throw new Error("--card must be valid JSON");
289
+ }
290
+ }
291
+ export function parseComponentsParam(params) {
292
+ const raw = params.components;
293
+ if (typeof raw !== "string") {
294
+ return;
295
+ }
296
+ const trimmed = raw.trim();
297
+ if (!trimmed) {
298
+ delete params.components;
299
+ return;
300
+ }
301
+ try {
302
+ params.components = JSON.parse(trimmed);
303
+ }
304
+ catch {
305
+ throw new Error("--components must be valid JSON");
306
+ }
307
+ }
@@ -0,0 +1,21 @@
1
+ export function extractToolPayload(result) {
2
+ if (result.details !== undefined) {
3
+ return result.details;
4
+ }
5
+ const textBlock = Array.isArray(result.content)
6
+ ? result.content.find((block) => block &&
7
+ typeof block === "object" &&
8
+ block.type === "text" &&
9
+ typeof block.text === "string")
10
+ : undefined;
11
+ const text = textBlock?.text;
12
+ if (text) {
13
+ try {
14
+ return JSON.parse(text);
15
+ }
16
+ catch {
17
+ return text;
18
+ }
19
+ }
20
+ return result.content ?? result;
21
+ }
@@ -0,0 +1,23 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ export async function readPackageVersion(root) {
4
+ try {
5
+ const raw = await fs.readFile(path.join(root, "package.json"), "utf-8");
6
+ const parsed = JSON.parse(raw);
7
+ return typeof parsed?.version === "string" ? parsed.version : null;
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ export async function readPackageName(root) {
14
+ try {
15
+ const raw = await fs.readFile(path.join(root, "package.json"), "utf-8");
16
+ const parsed = JSON.parse(raw);
17
+ const name = parsed?.name?.trim();
18
+ return name ? name : null;
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
@@ -0,0 +1,19 @@
1
+ import path from "node:path";
2
+ import { resolveStateDir } from "../config/paths.js";
3
+ export { createAsyncLock, readJsonFile, writeJsonAtomic } from "./json-files.js";
4
+ export function resolvePairingPaths(baseDir, subdir) {
5
+ const root = baseDir ?? resolveStateDir();
6
+ const dir = path.join(root, subdir);
7
+ return {
8
+ dir,
9
+ pendingPath: path.join(dir, "pending.json"),
10
+ pairedPath: path.join(dir, "paired.json"),
11
+ };
12
+ }
13
+ export function pruneExpiredPending(pendingById, nowMs, ttlMs) {
14
+ for (const [id, req] of Object.entries(pendingById)) {
15
+ if (nowMs - req.ts > ttlMs) {
16
+ delete pendingById[id];
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,9 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { safeEqualSecret } from "../security/secret-equal.js";
3
+ export const PAIRING_TOKEN_BYTES = 32;
4
+ export function generatePairingToken() {
5
+ return randomBytes(PAIRING_TOKEN_BYTES).toString("base64url");
6
+ }
7
+ export function verifyPairingToken(provided, expected) {
8
+ return safeEqualSecret(provided, expected);
9
+ }
@@ -0,0 +1,51 @@
1
+ import path from "node:path";
2
+ export function normalizePathPrepend(entries) {
3
+ if (!Array.isArray(entries)) {
4
+ return [];
5
+ }
6
+ const seen = new Set();
7
+ const normalized = [];
8
+ for (const entry of entries) {
9
+ if (typeof entry !== "string") {
10
+ continue;
11
+ }
12
+ const trimmed = entry.trim();
13
+ if (!trimmed || seen.has(trimmed)) {
14
+ continue;
15
+ }
16
+ seen.add(trimmed);
17
+ normalized.push(trimmed);
18
+ }
19
+ return normalized;
20
+ }
21
+ export function mergePathPrepend(existing, prepend) {
22
+ if (prepend.length === 0) {
23
+ return existing;
24
+ }
25
+ const partsExisting = (existing ?? "")
26
+ .split(path.delimiter)
27
+ .map((part) => part.trim())
28
+ .filter(Boolean);
29
+ const merged = [];
30
+ const seen = new Set();
31
+ for (const part of [...prepend, ...partsExisting]) {
32
+ if (seen.has(part)) {
33
+ continue;
34
+ }
35
+ seen.add(part);
36
+ merged.push(part);
37
+ }
38
+ return merged.join(path.delimiter);
39
+ }
40
+ export function applyPathPrepend(env, prepend, options) {
41
+ if (!Array.isArray(prepend) || prepend.length === 0) {
42
+ return;
43
+ }
44
+ if (options?.requireExisting && !env.PATH) {
45
+ return;
46
+ }
47
+ const merged = mergePathPrepend(env.PATH, prepend);
48
+ if (merged) {
49
+ env.PATH = merged;
50
+ }
51
+ }
@@ -0,0 +1,49 @@
1
+ import { spawn } from "node:child_process";
2
+ const SUPERVISOR_HINT_ENV_VARS = [
3
+ "LAUNCH_JOB_LABEL",
4
+ "LAUNCH_JOB_NAME",
5
+ "INVOCATION_ID",
6
+ "SYSTEMD_EXEC_PID",
7
+ "JOURNAL_STREAM",
8
+ ];
9
+ function isTruthy(value) {
10
+ if (!value) {
11
+ return false;
12
+ }
13
+ const normalized = value.trim().toLowerCase();
14
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
15
+ }
16
+ function isLikelySupervisedProcess(env = process.env) {
17
+ return SUPERVISOR_HINT_ENV_VARS.some((key) => {
18
+ const value = env[key];
19
+ return typeof value === "string" && value.trim().length > 0;
20
+ });
21
+ }
22
+ /**
23
+ * Attempt to restart this process with a fresh PID.
24
+ * - supervised environments (launchd/systemd): caller should exit and let supervisor restart
25
+ * - POOLBOT_NO_RESPAWN=1: caller should keep in-process restart behavior (tests/dev)
26
+ * - otherwise: spawn detached child with current argv/execArgv, then caller exits
27
+ */
28
+ export function restartGatewayProcessWithFreshPid() {
29
+ if (isTruthy(process.env.POOLBOT_NO_RESPAWN)) {
30
+ return { mode: "disabled" };
31
+ }
32
+ if (isLikelySupervisedProcess(process.env)) {
33
+ return { mode: "supervised" };
34
+ }
35
+ try {
36
+ const args = [...process.execArgv, ...process.argv.slice(1)];
37
+ const child = spawn(process.execPath, args, {
38
+ env: process.env,
39
+ detached: true,
40
+ stdio: "inherit",
41
+ });
42
+ child.unref();
43
+ return { mode: "spawned", pid: child.pid ?? undefined };
44
+ }
45
+ catch (err) {
46
+ const detail = err instanceof Error ? err.message : String(err);
47
+ return { mode: "failed", detail };
48
+ }
49
+ }
@@ -0,0 +1,16 @@
1
+ export function formatRuntimeStatusWithDetails({ status, pid, state, details = [], }) {
2
+ const runtimeStatus = status ?? "unknown";
3
+ const fullDetails = [];
4
+ if (pid) {
5
+ fullDetails.push(`pid ${pid}`);
6
+ }
7
+ if (state && state.toLowerCase() !== runtimeStatus) {
8
+ fullDetails.push(`state ${state}`);
9
+ }
10
+ for (const detail of details) {
11
+ if (detail) {
12
+ fullDetails.push(detail);
13
+ }
14
+ }
15
+ return fullDetails.length > 0 ? `${runtimeStatus} (${fullDetails.join(", ")})` : runtimeStatus;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ import { resolveSessionAgentId } from "../agents/agent-scope.js";
2
+ import { isDeliverableMessageChannel, normalizeMessageChannel } from "../utils/message-channel.js";
3
+ import { resolveSessionDeliveryTarget } from "./outbound/targets.js";
4
+ import { enqueueSystemEvent } from "./system-events.js";
5
+ const warnedContexts = new Map();
6
+ function shouldSendWarning() {
7
+ return !process.env.VITEST && process.env.NODE_ENV !== "test";
8
+ }
9
+ function buildWarningContext(params) {
10
+ const { warning } = params;
11
+ return [
12
+ warning.activeSessionKey,
13
+ warning.pruneAfterMs,
14
+ warning.maxEntries,
15
+ warning.wouldPrune ? "prune" : "",
16
+ warning.wouldCap ? "cap" : "",
17
+ ]
18
+ .filter(Boolean)
19
+ .join("|");
20
+ }
21
+ function formatDuration(ms) {
22
+ if (ms >= 86_400_000) {
23
+ const days = Math.round(ms / 86_400_000);
24
+ return `${days} day${days === 1 ? "" : "s"}`;
25
+ }
26
+ if (ms >= 3_600_000) {
27
+ const hours = Math.round(ms / 3_600_000);
28
+ return `${hours} hour${hours === 1 ? "" : "s"}`;
29
+ }
30
+ if (ms >= 60_000) {
31
+ const mins = Math.round(ms / 60_000);
32
+ return `${mins} minute${mins === 1 ? "" : "s"}`;
33
+ }
34
+ const secs = Math.round(ms / 1000);
35
+ return `${secs} second${secs === 1 ? "" : "s"}`;
36
+ }
37
+ function buildWarningText(warning) {
38
+ const reasons = [];
39
+ if (warning.wouldPrune) {
40
+ reasons.push(`older than ${formatDuration(warning.pruneAfterMs)}`);
41
+ }
42
+ if (warning.wouldCap) {
43
+ reasons.push(`not in the most recent ${warning.maxEntries} sessions`);
44
+ }
45
+ const reasonText = reasons.length > 0 ? reasons.join(" and ") : "over maintenance limits";
46
+ return (`⚠️ Session maintenance warning: this active session would be evicted (${reasonText}). ` +
47
+ `Maintenance is set to warn-only, so nothing was reset. ` +
48
+ `To enforce cleanup, set \`session.maintenance.mode: "enforce"\` or increase the limits.`);
49
+ }
50
+ export async function deliverSessionMaintenanceWarning(params) {
51
+ if (!shouldSendWarning()) {
52
+ return;
53
+ }
54
+ const contextKey = buildWarningContext(params);
55
+ if (warnedContexts.get(params.sessionKey) === contextKey) {
56
+ return;
57
+ }
58
+ warnedContexts.set(params.sessionKey, contextKey);
59
+ const text = buildWarningText(params.warning);
60
+ const target = resolveSessionDeliveryTarget({
61
+ entry: params.entry,
62
+ requestedChannel: "last",
63
+ });
64
+ if (!target.channel || !target.to) {
65
+ enqueueSystemEvent(text, { sessionKey: params.sessionKey });
66
+ return;
67
+ }
68
+ const channel = normalizeMessageChannel(target.channel) ?? target.channel;
69
+ if (!isDeliverableMessageChannel(channel)) {
70
+ enqueueSystemEvent(text, { sessionKey: params.sessionKey });
71
+ return;
72
+ }
73
+ try {
74
+ const { deliverOutboundPayloads } = await import("./outbound/deliver.js");
75
+ await deliverOutboundPayloads({
76
+ cfg: params.cfg,
77
+ channel,
78
+ to: target.to,
79
+ accountId: target.accountId,
80
+ threadId: target.threadId,
81
+ payloads: [{ text }],
82
+ agentId: resolveSessionAgentId({ sessionKey: params.sessionKey, config: params.cfg }),
83
+ });
84
+ }
85
+ catch (err) {
86
+ console.warn(`Failed to deliver session maintenance warning: ${String(err)}`);
87
+ enqueueSystemEvent(text, { sessionKey: params.sessionKey });
88
+ }
89
+ }
@@ -0,0 +1,78 @@
1
+ import path from "node:path";
2
+ function basenameLower(token) {
3
+ const win = path.win32.basename(token);
4
+ const posix = path.posix.basename(token);
5
+ const base = win.length < posix.length ? win : posix;
6
+ return base.trim().toLowerCase();
7
+ }
8
+ export function formatExecCommand(argv) {
9
+ return argv
10
+ .map((arg) => {
11
+ const trimmed = arg.trim();
12
+ if (!trimmed) {
13
+ return '""';
14
+ }
15
+ const needsQuotes = /\s|"/.test(trimmed);
16
+ if (!needsQuotes) {
17
+ return trimmed;
18
+ }
19
+ return `"${trimmed.replace(/"/g, '\\"')}"`;
20
+ })
21
+ .join(" ");
22
+ }
23
+ export function extractShellCommandFromArgv(argv) {
24
+ const token0 = argv[0]?.trim();
25
+ if (!token0) {
26
+ return null;
27
+ }
28
+ const base0 = basenameLower(token0);
29
+ // POSIX-style shells: sh -lc "<cmd>"
30
+ if (base0 === "sh" ||
31
+ base0 === "bash" ||
32
+ base0 === "zsh" ||
33
+ base0 === "dash" ||
34
+ base0 === "ksh") {
35
+ const flag = argv[1]?.trim();
36
+ if (flag !== "-lc" && flag !== "-c") {
37
+ return null;
38
+ }
39
+ const cmd = argv[2];
40
+ return typeof cmd === "string" ? cmd : null;
41
+ }
42
+ // Windows cmd.exe: cmd.exe /d /s /c "<cmd>"
43
+ if (base0 === "cmd.exe" || base0 === "cmd") {
44
+ const idx = argv.findIndex((item) => String(item).trim().toLowerCase() === "/c");
45
+ if (idx === -1) {
46
+ return null;
47
+ }
48
+ const cmd = argv[idx + 1];
49
+ return typeof cmd === "string" ? cmd : null;
50
+ }
51
+ return null;
52
+ }
53
+ export function validateSystemRunCommandConsistency(params) {
54
+ const raw = typeof params.rawCommand === "string" && params.rawCommand.trim().length > 0
55
+ ? params.rawCommand.trim()
56
+ : null;
57
+ const shellCommand = extractShellCommandFromArgv(params.argv);
58
+ const inferred = shellCommand ? shellCommand.trim() : formatExecCommand(params.argv);
59
+ if (raw && raw !== inferred) {
60
+ return {
61
+ ok: false,
62
+ message: "INVALID_REQUEST: rawCommand does not match command",
63
+ details: {
64
+ code: "RAW_COMMAND_MISMATCH",
65
+ rawCommand: raw,
66
+ inferred,
67
+ },
68
+ };
69
+ }
70
+ return {
71
+ ok: true,
72
+ // Only treat this as a shell command when argv is a recognized shell wrapper.
73
+ // For direct argv execution, rawCommand is purely display/approval text and
74
+ // must match the formatted argv.
75
+ shellCommand: shellCommand ? (raw ?? shellCommand) : null,
76
+ cmdText: raw ?? shellCommand ?? inferred,
77
+ };
78
+ }