@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
@@ -1,5 +1,5 @@
1
- import { listPairingChannels, notifyPairingApproved } from "../channels/plugins/pairing.js";
2
1
  import { normalizeChannelId } from "../channels/plugins/index.js";
2
+ import { listPairingChannels, notifyPairingApproved } from "../channels/plugins/pairing.js";
3
3
  import { loadConfig } from "../config/config.js";
4
4
  import { resolvePairingIdLabel } from "../pairing/pairing-labels.js";
5
5
  import { approveChannelPairingCode, listChannelPairingRequests, } from "../pairing/pairing-store.js";
@@ -17,8 +17,9 @@ function parseChannel(raw, channels) {
17
17
  : "")
18
18
  .trim()
19
19
  .toLowerCase();
20
- if (!value)
20
+ if (!value) {
21
21
  throw new Error("Channel required");
22
+ }
22
23
  const normalized = normalizeChannelId(value);
23
24
  if (normalized) {
24
25
  if (!channels.includes(normalized)) {
@@ -27,8 +28,9 @@ function parseChannel(raw, channels) {
27
28
  return normalized;
28
29
  }
29
30
  // Allow extension channels: validate format but don't require registry
30
- if (/^[a-z][a-z0-9_-]{0,63}$/.test(value))
31
+ if (/^[a-z][a-z0-9_-]{0,63}$/.test(value)) {
31
32
  return value;
33
+ }
32
34
  throw new Error(`Invalid channel: ${value}`);
33
35
  }
34
36
  async function notifyApproved(channel, id) {
@@ -40,20 +42,24 @@ export function registerPairingCli(program) {
40
42
  const pairing = program
41
43
  .command("pairing")
42
44
  .description("Secure DM pairing (approve inbound requests)")
43
- .addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/pairing", "docs.molt.bot/cli/pairing")}\n`);
45
+ .addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/pairing", "docs.poolbot.ai/cli/pairing")}\n`);
44
46
  pairing
45
47
  .command("list")
46
48
  .description("List pending pairing requests")
47
49
  .option("--channel <channel>", `Channel (${channels.join(", ")})`)
50
+ .option("--account <accountId>", "Account id (for multi-account channels)")
48
51
  .argument("[channel]", `Channel (${channels.join(", ")})`)
49
52
  .option("--json", "Print JSON", false)
50
53
  .action(async (channelArg, opts) => {
51
- const channelRaw = opts.channel ?? channelArg;
54
+ const channelRaw = opts.channel ?? channelArg ?? (channels.length === 1 ? channels[0] : "");
52
55
  if (!channelRaw) {
53
56
  throw new Error(`Channel required. Use --channel <channel> or pass it as the first argument (expected one of: ${channels.join(", ")})`);
54
57
  }
55
58
  const channel = parseChannel(channelRaw, channels);
56
- const requests = await listChannelPairingRequests(channel);
59
+ const accountId = String(opts.account ?? "").trim();
60
+ const requests = accountId
61
+ ? await listChannelPairingRequests(channel, process.env, accountId)
62
+ : await listChannelPairingRequests(channel);
57
63
  if (opts.json) {
58
64
  defaultRuntime.log(JSON.stringify({ channel, requests }, null, 2));
59
65
  return;
@@ -85,29 +91,49 @@ export function registerPairingCli(program) {
85
91
  .command("approve")
86
92
  .description("Approve a pairing code and allow that sender")
87
93
  .option("--channel <channel>", `Channel (${channels.join(", ")})`)
94
+ .option("--account <accountId>", "Account id (for multi-account channels)")
88
95
  .argument("<codeOrChannel>", "Pairing code (or channel when using 2 args)")
89
96
  .argument("[code]", "Pairing code (when channel is passed as the 1st arg)")
90
97
  .option("--notify", "Notify the requester on the same channel", false)
91
98
  .action(async (codeOrChannel, code, opts) => {
92
- const channelRaw = opts.channel ?? codeOrChannel;
93
- const resolvedCode = opts.channel ? codeOrChannel : code;
94
- if (!opts.channel && !code) {
99
+ const defaultChannel = channels.length === 1 ? channels[0] : "";
100
+ const usingExplicitChannel = Boolean(opts.channel);
101
+ const hasPositionalCode = code != null;
102
+ const channelRaw = usingExplicitChannel
103
+ ? opts.channel
104
+ : hasPositionalCode
105
+ ? codeOrChannel
106
+ : defaultChannel;
107
+ const resolvedCode = usingExplicitChannel
108
+ ? codeOrChannel
109
+ : hasPositionalCode
110
+ ? code
111
+ : codeOrChannel;
112
+ if (!channelRaw || !resolvedCode) {
95
113
  throw new Error(`Usage: ${formatCliCommand("poolbot pairing approve <channel> <code>")} (or: ${formatCliCommand("poolbot pairing approve --channel <channel> <code>")})`);
96
114
  }
97
115
  if (opts.channel && code != null) {
98
116
  throw new Error(`Too many arguments. Use: ${formatCliCommand("poolbot pairing approve --channel <channel> <code>")}`);
99
117
  }
100
118
  const channel = parseChannel(channelRaw, channels);
101
- const approved = await approveChannelPairingCode({
102
- channel,
103
- code: String(resolvedCode),
104
- });
119
+ const accountId = String(opts.account ?? "").trim();
120
+ const approved = accountId
121
+ ? await approveChannelPairingCode({
122
+ channel,
123
+ code: String(resolvedCode),
124
+ accountId,
125
+ })
126
+ : await approveChannelPairingCode({
127
+ channel,
128
+ code: String(resolvedCode),
129
+ });
105
130
  if (!approved) {
106
131
  throw new Error(`No pending pairing request found for code: ${String(resolvedCode)}`);
107
132
  }
108
133
  defaultRuntime.log(`${theme.success("Approved")} ${theme.muted(channel)} sender ${theme.command(approved.id)}.`);
109
- if (!opts.notify)
134
+ if (!opts.notify) {
110
135
  return;
136
+ }
111
137
  await notifyApproved(channel, approved.id).catch((err) => {
112
138
  defaultRuntime.log(theme.warn(`Failed to notify requester: ${String(err)}`));
113
139
  });
@@ -1,17 +1,49 @@
1
1
  import fs from "node:fs";
2
+ import os from "node:os";
2
3
  import path from "node:path";
3
4
  import { loadConfig, writeConfigFile } from "../config/config.js";
5
+ import { resolveStateDir } from "../config/paths.js";
4
6
  import { resolveArchiveKind } from "../infra/archive.js";
7
+ import { enablePluginInConfig } from "../plugins/enable.js";
5
8
  import { installPluginFromNpmSpec, installPluginFromPath } from "../plugins/install.js";
6
9
  import { recordPluginInstall } from "../plugins/installs.js";
10
+ import { clearPluginManifestRegistryCache } from "../plugins/manifest-registry.js";
7
11
  import { applyExclusiveSlotSelection } from "../plugins/slots.js";
12
+ import { resolvePluginSourceRoots, formatPluginSourceForTable } from "../plugins/source-display.js";
8
13
  import { buildPluginStatusReport } from "../plugins/status.js";
14
+ import { resolveUninstallDirectoryTarget, uninstallPlugin } from "../plugins/uninstall.js";
9
15
  import { updateNpmInstalledPlugins } from "../plugins/update.js";
10
16
  import { defaultRuntime } from "../runtime.js";
11
17
  import { formatDocsLink } from "../terminal/links.js";
12
18
  import { renderTable } from "../terminal/table.js";
13
19
  import { theme } from "../terminal/theme.js";
14
20
  import { resolveUserPath, shortenHomeInString, shortenHomePath } from "../utils.js";
21
+ import { promptYesNo } from "./prompt.js";
22
+ function resolveFileNpmSpecToLocalPath(raw) {
23
+ const trimmed = raw.trim();
24
+ if (!trimmed.toLowerCase().startsWith("file:")) {
25
+ return null;
26
+ }
27
+ const rest = trimmed.slice("file:".length);
28
+ if (!rest) {
29
+ return { ok: false, error: "unsupported file: spec: missing path" };
30
+ }
31
+ if (rest.startsWith("///")) {
32
+ // file:///abs/path -> /abs/path
33
+ return { ok: true, path: rest.slice(2) };
34
+ }
35
+ if (rest.startsWith("//localhost/")) {
36
+ // file://localhost/abs/path -> /abs/path
37
+ return { ok: true, path: rest.slice("//localhost".length) };
38
+ }
39
+ if (rest.startsWith("//")) {
40
+ return {
41
+ ok: false,
42
+ error: 'unsupported file: URL host (expected "file:<path>" or "file:///abs/path")',
43
+ };
44
+ }
45
+ return { ok: true, path: rest };
46
+ }
15
47
  function formatPluginLine(plugin, verbose = false) {
16
48
  const status = plugin.status === "loaded"
17
49
  ? theme.success("loaded")
@@ -33,13 +65,15 @@ function formatPluginLine(plugin, verbose = false) {
33
65
  ` source: ${theme.muted(shortenHomeInString(plugin.source))}`,
34
66
  ` origin: ${plugin.origin}`,
35
67
  ];
36
- if (plugin.version)
68
+ if (plugin.version) {
37
69
  parts.push(` version: ${plugin.version}`);
70
+ }
38
71
  if (plugin.providerIds.length > 0) {
39
72
  parts.push(` providers: ${plugin.providerIds.join(", ")}`);
40
73
  }
41
- if (plugin.error)
74
+ if (plugin.error) {
42
75
  parts.push(theme.error(` error: ${plugin.error}`));
76
+ }
43
77
  return parts.join("\n");
44
78
  }
45
79
  function applySlotSelectionForPlugin(config, pluginId) {
@@ -56,9 +90,16 @@ function applySlotSelectionForPlugin(config, pluginId) {
56
90
  });
57
91
  return { config: result.config, warnings: result.warnings };
58
92
  }
93
+ function createPluginInstallLogger() {
94
+ return {
95
+ info: (msg) => defaultRuntime.log(msg),
96
+ warn: (msg) => defaultRuntime.log(theme.warn(msg)),
97
+ };
98
+ }
59
99
  function logSlotWarnings(warnings) {
60
- if (warnings.length === 0)
100
+ if (warnings.length === 0) {
61
101
  return;
102
+ }
62
103
  for (const warning of warnings) {
63
104
  defaultRuntime.log(theme.warn(warning));
64
105
  }
@@ -66,7 +107,7 @@ function logSlotWarnings(warnings) {
66
107
  export function registerPluginsCli(program) {
67
108
  const plugins = program
68
109
  .command("plugins")
69
- .description("Manage Poolbot plugins/extensions")
110
+ .description("Manage Pool Bot plugins and extensions")
70
111
  .addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/plugins", "docs.molt.bot/cli/plugins")}\n`);
71
112
  plugins
72
113
  .command("list")
@@ -96,9 +137,17 @@ export function registerPluginsCli(program) {
96
137
  defaultRuntime.log(`${theme.heading("Plugins")} ${theme.muted(`(${loaded}/${list.length} loaded)`)}`);
97
138
  if (!opts.verbose) {
98
139
  const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1);
140
+ const sourceRoots = resolvePluginSourceRoots({
141
+ workspaceDir: report.workspaceDir,
142
+ });
143
+ const usedRoots = new Set();
99
144
  const rows = list.map((plugin) => {
100
145
  const desc = plugin.description ? theme.muted(plugin.description) : "";
101
- const sourceLine = desc ? `${plugin.source}\n${desc}` : plugin.source;
146
+ const formattedSource = formatPluginSourceForTable(plugin, sourceRoots);
147
+ if (formattedSource.rootKey) {
148
+ usedRoots.add(formattedSource.rootKey);
149
+ }
150
+ const sourceLine = desc ? `${formattedSource.value}\n${desc}` : formattedSource.value;
102
151
  return {
103
152
  Name: plugin.name || plugin.id,
104
153
  ID: plugin.name && plugin.name !== plugin.id ? plugin.id : "",
@@ -111,6 +160,20 @@ export function registerPluginsCli(program) {
111
160
  Version: plugin.version ?? "",
112
161
  };
113
162
  });
163
+ if (usedRoots.size > 0) {
164
+ defaultRuntime.log(theme.muted("Source roots:"));
165
+ for (const key of ["stock", "workspace", "global"]) {
166
+ if (!usedRoots.has(key)) {
167
+ continue;
168
+ }
169
+ const dir = sourceRoots[key];
170
+ if (!dir) {
171
+ continue;
172
+ }
173
+ defaultRuntime.log(` ${theme.command(`${key}:`)} ${theme.muted(dir)}`);
174
+ }
175
+ defaultRuntime.log("");
176
+ }
114
177
  defaultRuntime.log(renderTable({
115
178
  width: tableWidth,
116
179
  columns: [
@@ -154,14 +217,16 @@ export function registerPluginsCli(program) {
154
217
  if (plugin.name && plugin.name !== plugin.id) {
155
218
  lines.push(theme.muted(`id: ${plugin.id}`));
156
219
  }
157
- if (plugin.description)
220
+ if (plugin.description) {
158
221
  lines.push(plugin.description);
222
+ }
159
223
  lines.push("");
160
224
  lines.push(`${theme.muted("Status:")} ${plugin.status}`);
161
225
  lines.push(`${theme.muted("Source:")} ${shortenHomeInString(plugin.source)}`);
162
226
  lines.push(`${theme.muted("Origin:")} ${plugin.origin}`);
163
- if (plugin.version)
227
+ if (plugin.version) {
164
228
  lines.push(`${theme.muted("Version:")} ${plugin.version}`);
229
+ }
165
230
  if (plugin.toolNames.length > 0) {
166
231
  lines.push(`${theme.muted("Tools:")} ${plugin.toolNames.join(", ")}`);
167
232
  }
@@ -180,21 +245,27 @@ export function registerPluginsCli(program) {
180
245
  if (plugin.services.length > 0) {
181
246
  lines.push(`${theme.muted("Services:")} ${plugin.services.join(", ")}`);
182
247
  }
183
- if (plugin.error)
248
+ if (plugin.error) {
184
249
  lines.push(`${theme.error("Error:")} ${plugin.error}`);
250
+ }
185
251
  if (install) {
186
252
  lines.push("");
187
253
  lines.push(`${theme.muted("Install:")} ${install.source}`);
188
- if (install.spec)
254
+ if (install.spec) {
189
255
  lines.push(`${theme.muted("Spec:")} ${install.spec}`);
190
- if (install.sourcePath)
256
+ }
257
+ if (install.sourcePath) {
191
258
  lines.push(`${theme.muted("Source path:")} ${shortenHomePath(install.sourcePath)}`);
192
- if (install.installPath)
259
+ }
260
+ if (install.installPath) {
193
261
  lines.push(`${theme.muted("Install path:")} ${shortenHomePath(install.installPath)}`);
194
- if (install.version)
262
+ }
263
+ if (install.version) {
195
264
  lines.push(`${theme.muted("Recorded version:")} ${install.version}`);
196
- if (install.installedAt)
265
+ }
266
+ if (install.installedAt) {
197
267
  lines.push(`${theme.muted("Installed at:")} ${install.installedAt}`);
268
+ }
198
269
  }
199
270
  defaultRuntime.log(lines.join("\n"));
200
271
  });
@@ -204,24 +275,17 @@ export function registerPluginsCli(program) {
204
275
  .argument("<id>", "Plugin id")
205
276
  .action(async (id) => {
206
277
  const cfg = loadConfig();
207
- let next = {
208
- ...cfg,
209
- plugins: {
210
- ...cfg.plugins,
211
- entries: {
212
- ...cfg.plugins?.entries,
213
- [id]: {
214
- ...cfg.plugins?.entries?.[id],
215
- enabled: true,
216
- },
217
- },
218
- },
219
- };
278
+ const enableResult = enablePluginInConfig(cfg, id);
279
+ let next = enableResult.config;
220
280
  const slotResult = applySlotSelectionForPlugin(next, id);
221
281
  next = slotResult.config;
222
282
  await writeConfigFile(next);
223
283
  logSlotWarnings(slotResult.warnings);
224
- defaultRuntime.log(`Enabled plugin "${id}". Restart the gateway to apply.`);
284
+ if (enableResult.enabled) {
285
+ defaultRuntime.log(`Enabled plugin "${id}". Restart the gateway to apply.`);
286
+ return;
287
+ }
288
+ defaultRuntime.log(theme.warn(`Plugin "${id}" could not be enabled (${enableResult.reason ?? "unknown reason"}).`));
225
289
  });
226
290
  plugins
227
291
  .command("disable")
@@ -245,13 +309,133 @@ export function registerPluginsCli(program) {
245
309
  await writeConfigFile(next);
246
310
  defaultRuntime.log(`Disabled plugin "${id}". Restart the gateway to apply.`);
247
311
  });
312
+ plugins
313
+ .command("uninstall")
314
+ .description("Uninstall a plugin")
315
+ .argument("<id>", "Plugin id")
316
+ .option("--keep-files", "Keep installed files on disk", false)
317
+ .option("--keep-config", "Deprecated alias for --keep-files", false)
318
+ .option("--force", "Skip confirmation prompt", false)
319
+ .option("--dry-run", "Show what would be removed without making changes", false)
320
+ .action(async (id, opts) => {
321
+ const cfg = loadConfig();
322
+ const report = buildPluginStatusReport({ config: cfg });
323
+ const extensionsDir = path.join(resolveStateDir(process.env, os.homedir), "extensions");
324
+ const keepFiles = Boolean(opts.keepFiles || opts.keepConfig);
325
+ if (opts.keepConfig) {
326
+ defaultRuntime.log(theme.warn("`--keep-config` is deprecated, use `--keep-files`."));
327
+ }
328
+ // Find plugin by id or name
329
+ const plugin = report.plugins.find((p) => p.id === id || p.name === id);
330
+ const pluginId = plugin?.id ?? id;
331
+ // Check if plugin exists in config
332
+ const hasEntry = pluginId in (cfg.plugins?.entries ?? {});
333
+ const hasInstall = pluginId in (cfg.plugins?.installs ?? {});
334
+ if (!hasEntry && !hasInstall) {
335
+ if (plugin) {
336
+ defaultRuntime.error(`Plugin "${pluginId}" is not managed by plugins config/install records and cannot be uninstalled.`);
337
+ }
338
+ else {
339
+ defaultRuntime.error(`Plugin not found: ${id}`);
340
+ }
341
+ process.exit(1);
342
+ }
343
+ const install = cfg.plugins?.installs?.[pluginId];
344
+ const isLinked = install?.source === "path";
345
+ // Build preview of what will be removed
346
+ const preview = [];
347
+ if (hasEntry) {
348
+ preview.push("config entry");
349
+ }
350
+ if (hasInstall) {
351
+ preview.push("install record");
352
+ }
353
+ if (cfg.plugins?.allow?.includes(pluginId)) {
354
+ preview.push("allowlist entry");
355
+ }
356
+ if (isLinked &&
357
+ install?.sourcePath &&
358
+ cfg.plugins?.load?.paths?.includes(install.sourcePath)) {
359
+ preview.push("load path");
360
+ }
361
+ if (cfg.plugins?.slots?.memory === pluginId) {
362
+ preview.push(`memory slot (will reset to "memory-core")`);
363
+ }
364
+ const deleteTarget = !keepFiles
365
+ ? resolveUninstallDirectoryTarget({
366
+ pluginId,
367
+ hasInstall,
368
+ installRecord: install,
369
+ extensionsDir,
370
+ })
371
+ : null;
372
+ if (deleteTarget) {
373
+ preview.push(`directory: ${shortenHomePath(deleteTarget)}`);
374
+ }
375
+ const pluginName = plugin?.name || pluginId;
376
+ defaultRuntime.log(`Plugin: ${theme.command(pluginName)}${pluginName !== pluginId ? theme.muted(` (${pluginId})`) : ""}`);
377
+ defaultRuntime.log(`Will remove: ${preview.length > 0 ? preview.join(", ") : "(nothing)"}`);
378
+ if (opts.dryRun) {
379
+ defaultRuntime.log(theme.muted("Dry run, no changes made."));
380
+ return;
381
+ }
382
+ if (!opts.force) {
383
+ const confirmed = await promptYesNo(`Uninstall plugin "${pluginId}"?`);
384
+ if (!confirmed) {
385
+ defaultRuntime.log("Cancelled.");
386
+ return;
387
+ }
388
+ }
389
+ const result = await uninstallPlugin({
390
+ config: cfg,
391
+ pluginId,
392
+ deleteFiles: !keepFiles,
393
+ extensionsDir,
394
+ });
395
+ if (!result.ok) {
396
+ defaultRuntime.error(result.error);
397
+ process.exit(1);
398
+ }
399
+ for (const warning of result.warnings) {
400
+ defaultRuntime.log(theme.warn(warning));
401
+ }
402
+ await writeConfigFile(result.config);
403
+ const removed = [];
404
+ if (result.actions.entry) {
405
+ removed.push("config entry");
406
+ }
407
+ if (result.actions.install) {
408
+ removed.push("install record");
409
+ }
410
+ if (result.actions.allowlist) {
411
+ removed.push("allowlist");
412
+ }
413
+ if (result.actions.loadPath) {
414
+ removed.push("load path");
415
+ }
416
+ if (result.actions.memorySlot) {
417
+ removed.push("memory slot");
418
+ }
419
+ if (result.actions.directory) {
420
+ removed.push("directory");
421
+ }
422
+ defaultRuntime.log(`Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`);
423
+ defaultRuntime.log("Restart the gateway to apply changes.");
424
+ });
248
425
  plugins
249
426
  .command("install")
250
427
  .description("Install a plugin (path, archive, or npm spec)")
251
428
  .argument("<path-or-spec>", "Path (.ts/.js/.zip/.tgz/.tar.gz) or an npm package spec")
252
429
  .option("-l, --link", "Link a local path instead of copying", false)
430
+ .option("--pin", "Record npm installs as exact resolved <name>@<version>", false)
253
431
  .action(async (raw, opts) => {
254
- const resolved = resolveUserPath(raw);
432
+ const fileSpec = resolveFileNpmSpecToLocalPath(raw);
433
+ if (fileSpec && !fileSpec.ok) {
434
+ defaultRuntime.error(fileSpec.error);
435
+ process.exit(1);
436
+ }
437
+ const normalized = fileSpec && fileSpec.ok ? fileSpec.path : raw;
438
+ const resolved = resolveUserPath(normalized);
255
439
  const cfg = loadConfig();
256
440
  if (fs.existsSync(resolved)) {
257
441
  if (opts.link) {
@@ -262,7 +446,7 @@ export function registerPluginsCli(program) {
262
446
  defaultRuntime.error(probe.error);
263
447
  process.exit(1);
264
448
  }
265
- let next = {
449
+ let next = enablePluginInConfig({
266
450
  ...cfg,
267
451
  plugins: {
268
452
  ...cfg.plugins,
@@ -270,15 +454,8 @@ export function registerPluginsCli(program) {
270
454
  ...cfg.plugins?.load,
271
455
  paths: merged,
272
456
  },
273
- entries: {
274
- ...cfg.plugins?.entries,
275
- [probe.pluginId]: {
276
- ...cfg.plugins?.entries?.[probe.pluginId],
277
- enabled: true,
278
- },
279
- },
280
457
  },
281
- };
458
+ }, probe.pluginId).config;
282
459
  next = recordPluginInstall(next, {
283
460
  pluginId: probe.pluginId,
284
461
  source: "path",
@@ -296,28 +473,16 @@ export function registerPluginsCli(program) {
296
473
  }
297
474
  const result = await installPluginFromPath({
298
475
  path: resolved,
299
- logger: {
300
- info: (msg) => defaultRuntime.log(msg),
301
- warn: (msg) => defaultRuntime.log(theme.warn(msg)),
302
- },
476
+ logger: createPluginInstallLogger(),
303
477
  });
304
478
  if (!result.ok) {
305
479
  defaultRuntime.error(result.error);
306
480
  process.exit(1);
307
481
  }
308
- let next = {
309
- ...cfg,
310
- plugins: {
311
- ...cfg.plugins,
312
- entries: {
313
- ...cfg.plugins?.entries,
314
- [result.pluginId]: {
315
- ...cfg.plugins?.entries?.[result.pluginId],
316
- enabled: true,
317
- },
318
- },
319
- },
320
- };
482
+ // Plugin CLI registrars may have warmed the manifest registry cache before install;
483
+ // force a rescan so config validation sees the freshly installed plugin.
484
+ clearPluginManifestRegistryCache();
485
+ let next = enablePluginInConfig(cfg, result.pluginId).config;
321
486
  const source = resolveArchiveKind(resolved) ? "archive" : "path";
322
487
  next = recordPluginInstall(next, {
323
488
  pluginId: result.pluginId,
@@ -355,34 +520,35 @@ export function registerPluginsCli(program) {
355
520
  }
356
521
  const result = await installPluginFromNpmSpec({
357
522
  spec: raw,
358
- logger: {
359
- info: (msg) => defaultRuntime.log(msg),
360
- warn: (msg) => defaultRuntime.log(theme.warn(msg)),
361
- },
523
+ logger: createPluginInstallLogger(),
362
524
  });
363
525
  if (!result.ok) {
364
526
  defaultRuntime.error(result.error);
365
527
  process.exit(1);
366
528
  }
367
- let next = {
368
- ...cfg,
369
- plugins: {
370
- ...cfg.plugins,
371
- entries: {
372
- ...cfg.plugins?.entries,
373
- [result.pluginId]: {
374
- ...cfg.plugins?.entries?.[result.pluginId],
375
- enabled: true,
376
- },
377
- },
378
- },
379
- };
529
+ // Ensure config validation sees newly installed plugin(s) even if the cache was warmed at startup.
530
+ clearPluginManifestRegistryCache();
531
+ let next = enablePluginInConfig(cfg, result.pluginId).config;
532
+ const resolvedSpec = result.npmResolution?.resolvedSpec;
533
+ const recordSpec = opts.pin && resolvedSpec ? resolvedSpec : raw;
534
+ if (opts.pin && !resolvedSpec) {
535
+ defaultRuntime.log(theme.warn("Could not resolve exact npm version for --pin; storing original npm spec."));
536
+ }
537
+ if (opts.pin && resolvedSpec) {
538
+ defaultRuntime.log(`Pinned npm install record to ${resolvedSpec}.`);
539
+ }
380
540
  next = recordPluginInstall(next, {
381
541
  pluginId: result.pluginId,
382
542
  source: "npm",
383
- spec: raw,
543
+ spec: recordSpec,
384
544
  installPath: result.targetDir,
385
545
  version: result.version,
546
+ resolvedName: result.npmResolution?.name,
547
+ resolvedVersion: result.npmResolution?.version,
548
+ resolvedSpec: result.npmResolution?.resolvedSpec,
549
+ integrity: result.npmResolution?.integrity,
550
+ shasum: result.npmResolution?.shasum,
551
+ resolvedAt: result.npmResolution?.resolvedAt,
386
552
  });
387
553
  const slotResult = applySlotSelectionForPlugin(next, result.pluginId);
388
554
  next = slotResult.config;
@@ -417,6 +583,16 @@ export function registerPluginsCli(program) {
417
583
  info: (msg) => defaultRuntime.log(msg),
418
584
  warn: (msg) => defaultRuntime.log(theme.warn(msg)),
419
585
  },
586
+ onIntegrityDrift: async (drift) => {
587
+ const specLabel = drift.resolvedSpec ?? drift.spec;
588
+ defaultRuntime.log(theme.warn(`Integrity drift detected for "${drift.pluginId}" (${specLabel})` +
589
+ `\nExpected: ${drift.expectedIntegrity}` +
590
+ `\nActual: ${drift.actualIntegrity}`));
591
+ if (drift.dryRun) {
592
+ return true;
593
+ }
594
+ return await promptYesNo(`Continue updating "${drift.pluginId}" with this artifact?`);
595
+ },
420
596
  });
421
597
  for (const outcome of result.outcomes) {
422
598
  if (outcome.status === "error") {
@@ -453,8 +629,9 @@ export function registerPluginsCli(program) {
453
629
  }
454
630
  }
455
631
  if (diags.length > 0) {
456
- if (lines.length > 0)
632
+ if (lines.length > 0) {
457
633
  lines.push("");
634
+ }
458
635
  lines.push(theme.warn("Diagnostics:"));
459
636
  for (const diag of diags) {
460
637
  const target = diag.pluginId ? `${diag.pluginId}: ` : "";
package/dist/cli/ports.js CHANGED
@@ -1,24 +1,24 @@
1
1
  import { execFileSync } from "node:child_process";
2
2
  import { resolveLsofCommandSync } from "../infra/ports-lsof.js";
3
- function sleep(ms) {
4
- return new Promise((resolve) => setTimeout(resolve, ms));
5
- }
3
+ import { sleep } from "../utils.js";
6
4
  export function parseLsofOutput(output) {
7
5
  const lines = output.split(/\r?\n/).filter(Boolean);
8
6
  const results = [];
9
7
  let current = {};
10
8
  for (const line of lines) {
11
9
  if (line.startsWith("p")) {
12
- if (current.pid)
10
+ if (current.pid) {
13
11
  results.push(current);
12
+ }
14
13
  current = { pid: Number.parseInt(line.slice(1), 10) };
15
14
  }
16
15
  else if (line.startsWith("c")) {
17
16
  current.command = line.slice(1);
18
17
  }
19
18
  }
20
- if (current.pid)
19
+ if (current.pid) {
21
20
  results.push(current);
21
+ }
22
22
  return results;
23
23
  }
24
24
  export function listPortListeners(port) {
@@ -33,10 +33,11 @@ export function listPortListeners(port) {
33
33
  const status = err.status;
34
34
  const code = err.code;
35
35
  if (code === "ENOENT") {
36
- throw new Error("lsof not found; required for --force");
36
+ throw new Error("lsof not found; required for --force", { cause: err });
37
37
  }
38
- if (status === 1)
39
- return []; // no listeners
38
+ if (status === 1) {
39
+ return [];
40
+ } // no listeners
40
41
  throw err instanceof Error ? err : new Error(String(err));
41
42
  }
42
43
  }
@@ -47,7 +48,7 @@ export function forceFreePort(port) {
47
48
  process.kill(proc.pid, "SIGTERM");
48
49
  }
49
50
  catch (err) {
50
- throw new Error(`failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`);
51
+ throw new Error(`failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`, { cause: err });
51
52
  }
52
53
  }
53
54
  return listeners;
@@ -58,7 +59,7 @@ function killPids(listeners, signal) {
58
59
  process.kill(proc.pid, signal);
59
60
  }
60
61
  catch (err) {
61
- throw new Error(`failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`);
62
+ throw new Error(`failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`, { cause: err });
62
63
  }
63
64
  }
64
65
  }