@poolzin/pool-bot 2026.2.25 → 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 (506) hide show
  1. package/dist/acp/event-mapper.js +87 -22
  2. package/dist/acp/meta.js +12 -6
  3. package/dist/agents/agent-paths.js +8 -9
  4. package/dist/agents/agent-scope.js +7 -5
  5. package/dist/agents/auth-profiles/oauth.js +148 -64
  6. package/dist/agents/auth-profiles/session-override.js +13 -7
  7. package/dist/agents/bash-tools.exec-host-gateway.js +14 -4
  8. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  9. package/dist/agents/bedrock-discovery.js +3 -1
  10. package/dist/agents/byteplus-models.js +97 -0
  11. package/dist/agents/chutes-oauth.js +1 -0
  12. package/dist/agents/cli-runner/helpers.js +4 -0
  13. package/dist/agents/compaction.js +41 -14
  14. package/dist/agents/doubao-models.js +121 -0
  15. package/dist/agents/failover-error.js +2 -0
  16. package/dist/agents/huggingface-models.js +5 -3
  17. package/dist/agents/live-model-filter.js +5 -0
  18. package/dist/agents/minimax-vlm.js +10 -8
  19. package/dist/agents/model-auth.js +6 -0
  20. package/dist/agents/model-catalog.js +3 -1
  21. package/dist/agents/model-selection.js +7 -1
  22. package/dist/agents/models-config.providers.js +93 -11
  23. package/dist/agents/ollama-stream.js +117 -4
  24. package/dist/agents/opencode-zen-models.js +22 -11
  25. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  26. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  27. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  28. package/dist/agents/pi-embedded-helpers.js +1 -1
  29. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  30. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  31. package/dist/agents/pi-embedded-runner/google.js +20 -8
  32. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  33. package/dist/agents/pi-embedded-runner/run.js +71 -12
  34. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  35. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  36. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  37. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  38. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  39. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  40. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  41. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  42. package/dist/agents/pi-embedded-subscribe.js +9 -4
  43. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  44. package/dist/agents/pi-embedded-utils.js +3 -0
  45. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  46. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  47. package/dist/agents/pi-settings.js +40 -0
  48. package/dist/agents/pi-tools.policy.js +2 -1
  49. package/dist/agents/provider/config-loader.js +1 -1
  50. package/dist/agents/sandbox/browser.js +170 -33
  51. package/dist/agents/sandbox/config-hash.js +14 -27
  52. package/dist/agents/sandbox/config.js +21 -2
  53. package/dist/agents/sandbox/constants.js +2 -0
  54. package/dist/agents/sandbox/docker.js +16 -2
  55. package/dist/agents/sandbox/novnc-auth.js +62 -0
  56. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  57. package/dist/agents/sandbox/shared.js +10 -6
  58. package/dist/agents/sandbox-paths.js +24 -11
  59. package/dist/agents/schema/clean-for-gemini.js +132 -85
  60. package/dist/agents/session-slug.js +10 -5
  61. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  62. package/dist/agents/session-tool-result-guard.js +3 -1
  63. package/dist/agents/session-transcript-repair.js +40 -6
  64. package/dist/agents/skills/bundled-dir.js +19 -5
  65. package/dist/agents/skills/env-overrides.js +124 -43
  66. package/dist/agents/skills/frontmatter.js +6 -6
  67. package/dist/agents/skills/plugin-skills.js +14 -7
  68. package/dist/agents/skills/workspace.js +1 -0
  69. package/dist/agents/subagent-announce.js +251 -49
  70. package/dist/agents/subagent-lifecycle-events.js +19 -0
  71. package/dist/agents/subagent-registry-cleanup.js +31 -0
  72. package/dist/agents/subagent-registry-completion.js +68 -0
  73. package/dist/agents/subagent-registry-queries.js +117 -0
  74. package/dist/agents/subagent-registry-state.js +46 -0
  75. package/dist/agents/subagent-registry.js +252 -221
  76. package/dist/agents/subagent-registry.store.js +1 -0
  77. package/dist/agents/subagent-registry.types.js +1 -0
  78. package/dist/agents/subagent-spawn.js +195 -7
  79. package/dist/agents/system-prompt.js +22 -6
  80. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  81. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  82. package/dist/agents/timeout.js +18 -6
  83. package/dist/agents/tool-call-id.js +1 -1
  84. package/dist/agents/tool-display-common.js +162 -29
  85. package/dist/agents/tool-images.js +82 -9
  86. package/dist/agents/tool-policy.js +51 -26
  87. package/dist/agents/tools/browser-tool.js +2 -2
  88. package/dist/agents/tools/canvas-tool.js +27 -1
  89. package/dist/agents/tools/common.js +45 -0
  90. package/dist/agents/tools/discord-actions-guild.js +4 -1
  91. package/dist/agents/tools/gateway-tool.js +3 -1
  92. package/dist/agents/tools/nodes-utils.js +1 -10
  93. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  94. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  95. package/dist/agents/tools/subagents-tool.js +2 -1
  96. package/dist/agents/tools/whatsapp-actions.js +10 -2
  97. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  98. package/dist/agents/transcript-policy.js +22 -8
  99. package/dist/agents/venice-models.js +11 -3
  100. package/dist/auto-reply/commands-registry.data.js +51 -0
  101. package/dist/auto-reply/commands-registry.js +4 -3
  102. package/dist/auto-reply/group-activation.js +10 -5
  103. package/dist/auto-reply/inbound-debounce.js +10 -5
  104. package/dist/auto-reply/reply/abort.js +1 -1
  105. package/dist/auto-reply/reply/agent-runner-execution.js +4 -1
  106. package/dist/auto-reply/reply/bash-command.js +41 -39
  107. package/dist/auto-reply/reply/command-gates.js +25 -0
  108. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  109. package/dist/auto-reply/reply/commands-bash.js +6 -5
  110. package/dist/auto-reply/reply/commands-config.js +30 -28
  111. package/dist/auto-reply/reply/commands-core.js +2 -1
  112. package/dist/auto-reply/reply/commands-info.js +1 -0
  113. package/dist/auto-reply/reply/commands-models.js +65 -14
  114. package/dist/auto-reply/reply/commands-session.js +237 -82
  115. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  116. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  117. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  118. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  119. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  120. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  121. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  122. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  123. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  124. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  125. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  126. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  127. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  128. package/dist/auto-reply/reply/commands-tts.js +10 -5
  129. package/dist/auto-reply/reply/config-value.js +10 -5
  130. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  131. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  132. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  133. package/dist/auto-reply/reply/followup-runner.js +1 -0
  134. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  135. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  136. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  137. package/dist/auto-reply/reply/get-reply.js +71 -12
  138. package/dist/auto-reply/reply/model-selection.js +80 -39
  139. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  140. package/dist/auto-reply/reply/queue/state.js +13 -12
  141. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  142. package/dist/auto-reply/reply/reply-reference.js +9 -8
  143. package/dist/auto-reply/reply/route-reply.js +15 -8
  144. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  145. package/dist/auto-reply/reply/session.js +22 -6
  146. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  147. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  148. package/dist/auto-reply/reply/typing.js +46 -21
  149. package/dist/auto-reply/send-policy.js +14 -7
  150. package/dist/auto-reply/status.js +140 -16
  151. package/dist/auto-reply/templating.js +10 -5
  152. package/dist/auto-reply/thinking.js +7 -16
  153. package/dist/auto-reply/tokens.js +21 -5
  154. package/dist/browser/bridge-server.js +36 -20
  155. package/dist/browser/cdp.helpers.js +7 -14
  156. package/dist/browser/cdp.js +35 -15
  157. package/dist/browser/chrome.profile-decoration.js +7 -4
  158. package/dist/browser/config.js +4 -0
  159. package/dist/browser/extension-relay-auth.js +55 -0
  160. package/dist/browser/extension-relay.js +74 -29
  161. package/dist/browser/navigation-guard.js +9 -1
  162. package/dist/browser/paths.js +77 -0
  163. package/dist/browser/profiles.js +13 -8
  164. package/dist/browser/pw-ai-module.js +10 -5
  165. package/dist/browser/pw-session.js +76 -39
  166. package/dist/browser/pw-tools-core.interactions.js +14 -7
  167. package/dist/browser/pw-tools-core.state.js +12 -6
  168. package/dist/browser/routes/agent.act.js +2 -2
  169. package/dist/browser/server-context.js +7 -0
  170. package/dist/build-info.json +3 -3
  171. package/dist/channels/allow-from.js +2 -1
  172. package/dist/channels/allowlists/resolve-utils.js +43 -19
  173. package/dist/channels/channel-config.js +14 -7
  174. package/dist/channels/draft-stream-loop.js +7 -0
  175. package/dist/channels/model-overrides.js +82 -0
  176. package/dist/channels/plugins/normalize/imessage.js +14 -7
  177. package/dist/channels/plugins/normalize/slack.js +10 -5
  178. package/dist/channels/plugins/normalize/telegram.js +14 -7
  179. package/dist/channels/plugins/outbound/discord.js +80 -8
  180. package/dist/channels/plugins/outbound/signal.js +11 -11
  181. package/dist/channels/plugins/setup-helpers.js +10 -5
  182. package/dist/channels/sender-label.js +14 -7
  183. package/dist/channels/session.js +4 -2
  184. package/dist/channels/status-reactions.js +297 -0
  185. package/dist/cli/banner.js +1 -1
  186. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  187. package/dist/cli/cli-name.js +11 -11
  188. package/dist/cli/cli-utils.js +13 -3
  189. package/dist/cli/command-format.js +1 -1
  190. package/dist/cli/config-cli.js +1 -1
  191. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  192. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  193. package/dist/cli/daemon-cli/restart-health.js +126 -0
  194. package/dist/cli/daemon-cli/status.gather.js +9 -13
  195. package/dist/cli/daemon-cli/status.print.js +2 -10
  196. package/dist/cli/deps.js +27 -22
  197. package/dist/cli/gateway-cli/run-loop.js +23 -5
  198. package/dist/cli/node-cli/register.js +14 -5
  199. package/dist/cli/nodes-media-utils.js +7 -2
  200. package/dist/cli/outbound-send-deps.js +2 -9
  201. package/dist/cli/outbound-send-mapping.js +11 -0
  202. package/dist/cli/pairing-cli.js +40 -14
  203. package/dist/cli/plugins-cli.js +34 -41
  204. package/dist/cli/ports.js +11 -10
  205. package/dist/cli/program/command-registry.js +2 -11
  206. package/dist/cli/program/command-tree.js +16 -0
  207. package/dist/cli/program/preaction.js +13 -9
  208. package/dist/cli/program/register.configure.js +3 -18
  209. package/dist/cli/program/register.maintenance.js +2 -2
  210. package/dist/cli/program/register.onboard.js +2 -0
  211. package/dist/cli/program/register.status-health-sessions.js +16 -17
  212. package/dist/cli/program/register.subclis.js +93 -52
  213. package/dist/cli/route.js +11 -7
  214. package/dist/cli/system-cli.js +36 -46
  215. package/dist/cli/update-cli/shared.js +22 -9
  216. package/dist/cli/update-cli/update-command.js +89 -14
  217. package/dist/cli/update-cli/wizard.js +6 -12
  218. package/dist/commands/agent/run-context.js +18 -5
  219. package/dist/commands/agent/session-store.js +17 -4
  220. package/dist/commands/agent.js +22 -2
  221. package/dist/commands/agents.bindings.js +14 -7
  222. package/dist/commands/agents.commands.add.js +13 -9
  223. package/dist/commands/agents.commands.identity.js +12 -6
  224. package/dist/commands/agents.commands.list.js +11 -6
  225. package/dist/commands/agents.config.js +8 -10
  226. package/dist/commands/agents.providers.js +12 -6
  227. package/dist/commands/auth-choice-options.js +103 -75
  228. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  229. package/dist/commands/auth-choice.apply.js +4 -0
  230. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  231. package/dist/commands/auth-choice.apply.openai.js +3 -1
  232. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  233. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  234. package/dist/commands/channels/remove.js +13 -6
  235. package/dist/commands/channels/shared.js +4 -14
  236. package/dist/commands/configure.commands.js +14 -0
  237. package/dist/commands/configure.gateway.js +2 -4
  238. package/dist/commands/configure.js +1 -1
  239. package/dist/commands/configure.shared.js +11 -0
  240. package/dist/commands/daemon-install-helpers.js +2 -2
  241. package/dist/commands/dashboard.js +12 -10
  242. package/dist/commands/docs.js +14 -8
  243. package/dist/commands/doctor-config-flow.js +11 -9
  244. package/dist/commands/doctor-legacy-config.js +281 -0
  245. package/dist/commands/doctor-state-integrity.js +99 -23
  246. package/dist/commands/doctor-update.js +12 -9
  247. package/dist/commands/models/list.list-command.js +7 -5
  248. package/dist/commands/models/set-image.js +2 -21
  249. package/dist/commands/node-daemon-install-helpers.js +10 -8
  250. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  251. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  252. package/dist/commands/onboard-auth.credentials.js +90 -13
  253. package/dist/commands/onboard-auth.js +1 -1
  254. package/dist/commands/onboard-auth.models.js +6 -5
  255. package/dist/commands/onboard-hooks.js +1 -1
  256. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  257. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  258. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  259. package/dist/commands/onboard-remote.js +14 -7
  260. package/dist/commands/onboard.js +11 -13
  261. package/dist/commands/sandbox-display.js +6 -5
  262. package/dist/commands/status-all/diagnosis.js +14 -10
  263. package/dist/commands/status-all/format.js +1 -0
  264. package/dist/commands/status.gateway-probe.js +1 -16
  265. package/dist/commands/systemd-linger.js +12 -6
  266. package/dist/config/agent-limits.js +2 -0
  267. package/dist/config/commands.js +30 -16
  268. package/dist/config/config-paths.js +9 -11
  269. package/dist/config/defaults.js +22 -2
  270. package/dist/config/discord-preview-streaming.js +104 -0
  271. package/dist/config/env-vars.js +37 -8
  272. package/dist/config/includes.js +4 -0
  273. package/dist/config/io.js +97 -12
  274. package/dist/config/legacy.migrations.part-1.js +189 -78
  275. package/dist/config/legacy.shared.js +3 -1
  276. package/dist/config/merge-patch.js +4 -0
  277. package/dist/config/prototype-keys.js +4 -0
  278. package/dist/config/schema.help.js +44 -7
  279. package/dist/config/schema.labels.js +38 -6
  280. package/dist/config/sessions/delivery-info.js +10 -3
  281. package/dist/config/sessions/main-session.js +10 -5
  282. package/dist/config/sessions/session-file.js +33 -0
  283. package/dist/config/sessions/session-key.js +10 -5
  284. package/dist/config/sessions/store.js +1 -1
  285. package/dist/config/sessions.js +1 -0
  286. package/dist/config/zod-schema.agent-runtime.js +11 -0
  287. package/dist/config/zod-schema.js +148 -13
  288. package/dist/config/zod-schema.providers-core.js +78 -4
  289. package/dist/config/zod-schema.providers.js +6 -1
  290. package/dist/config/zod-schema.session.js +41 -2
  291. package/dist/cron/run-log.js +3 -0
  292. package/dist/cron/schedule.js +21 -10
  293. package/dist/cron/service/ops.js +35 -21
  294. package/dist/cron/service/timer.js +116 -16
  295. package/dist/cron/stagger.js +3 -1
  296. package/dist/discord/api.js +12 -6
  297. package/dist/discord/draft-chunking.js +22 -0
  298. package/dist/discord/draft-stream.js +124 -0
  299. package/dist/discord/monitor/agent-components.js +1 -1
  300. package/dist/discord/monitor/commands.js +5 -0
  301. package/dist/discord/monitor/gateway-plugin.js +2 -1
  302. package/dist/discord/monitor/listeners.js +37 -27
  303. package/dist/discord/monitor/message-handler.js +4 -1
  304. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  305. package/dist/discord/monitor/message-handler.process.js +246 -217
  306. package/dist/discord/monitor/message-utils.js +143 -6
  307. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  308. package/dist/discord/monitor/model-picker.js +651 -0
  309. package/dist/discord/monitor/native-command.js +573 -16
  310. package/dist/discord/monitor/provider.allowlist.js +223 -0
  311. package/dist/discord/monitor/provider.js +275 -347
  312. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  313. package/dist/discord/monitor/reply-delivery.js +123 -16
  314. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  315. package/dist/discord/monitor/thread-bindings.js +4 -0
  316. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  317. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  318. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  319. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  320. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  321. package/dist/discord/resolve-users.js +33 -21
  322. package/dist/discord/send.channels.js +15 -0
  323. package/dist/discord/send.js +3 -2
  324. package/dist/discord/send.outbound.js +82 -26
  325. package/dist/discord/send.permissions.js +83 -30
  326. package/dist/discord/send.reactions.js +8 -4
  327. package/dist/discord/token.js +10 -5
  328. package/dist/discord/voice/command.js +263 -0
  329. package/dist/discord/voice/manager.js +531 -0
  330. package/dist/gateway/auth.js +34 -10
  331. package/dist/gateway/call.js +4 -16
  332. package/dist/gateway/client.js +28 -4
  333. package/dist/gateway/config-reload.js +3 -4
  334. package/dist/gateway/control-ui.js +219 -96
  335. package/dist/gateway/hooks-mapping.js +88 -38
  336. package/dist/gateway/http-auth-helpers.js +3 -2
  337. package/dist/gateway/http-endpoint-helpers.js +1 -0
  338. package/dist/gateway/net.js +54 -12
  339. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  340. package/dist/gateway/node-registry.js +10 -5
  341. package/dist/gateway/openai-http.js +1 -0
  342. package/dist/gateway/openresponses-http.js +1 -0
  343. package/dist/gateway/origin-check.js +1 -18
  344. package/dist/gateway/protocol/index.js +4 -3
  345. package/dist/gateway/protocol/schema/cron.js +1 -0
  346. package/dist/gateway/protocol/schema/devices.js +1 -0
  347. package/dist/gateway/protocol/schema/protocol-schemas.js +2 -1
  348. package/dist/gateway/protocol/schema/sessions.js +6 -0
  349. package/dist/gateway/role-policy.js +17 -0
  350. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  351. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  352. package/dist/gateway/server-chat.js +83 -25
  353. package/dist/gateway/server-constants.js +10 -9
  354. package/dist/gateway/server-cron.js +1 -0
  355. package/dist/gateway/server-http.js +16 -7
  356. package/dist/gateway/server-maintenance.js +20 -5
  357. package/dist/gateway/server-methods/chat.js +10 -6
  358. package/dist/gateway/server-methods/config.js +12 -14
  359. package/dist/gateway/server-methods/devices.js +17 -3
  360. package/dist/gateway/server-methods/models.js +11 -1
  361. package/dist/gateway/server-methods/sessions.js +64 -8
  362. package/dist/gateway/server-methods/usage.js +162 -75
  363. package/dist/gateway/server-node-events.js +29 -0
  364. package/dist/gateway/server-runtime-config.js +34 -13
  365. package/dist/gateway/server-startup-memory.js +17 -11
  366. package/dist/gateway/session-utils.fs.js +32 -34
  367. package/dist/gateway/sessions-resolve.js +17 -5
  368. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  369. package/dist/gateway/tools-invoke-http.js +21 -10
  370. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  371. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  372. package/dist/hooks/bundled/session-memory/handler.js +6 -5
  373. package/dist/hooks/frontmatter.js +6 -6
  374. package/dist/hooks/gmail-watcher.js +11 -6
  375. package/dist/hooks/internal-hooks.js +11 -1
  376. package/dist/hooks/llm-slug-generator.js +4 -1
  377. package/dist/hooks/workspace.js +47 -17
  378. package/dist/imessage/accounts.js +9 -20
  379. package/dist/imessage/monitor/inbound-processing.js +2 -1
  380. package/dist/infra/archive.js +174 -73
  381. package/dist/infra/control-ui-assets.js +14 -6
  382. package/dist/infra/device-pairing.js +108 -29
  383. package/dist/infra/env.js +10 -5
  384. package/dist/infra/exec-approvals-allowlist.js +122 -0
  385. package/dist/infra/exec-approvals-analysis.js +34 -3
  386. package/dist/infra/exec-approvals.js +5 -17
  387. package/dist/infra/exec-safe-bin-policy.js +53 -45
  388. package/dist/infra/fs-safe.js +71 -39
  389. package/dist/infra/gateway-lock.js +6 -2
  390. package/dist/infra/heartbeat-wake.js +6 -12
  391. package/dist/infra/host-env-security-policy.json +19 -0
  392. package/dist/infra/host-env-security.js +66 -0
  393. package/dist/infra/net/ssrf.js +131 -38
  394. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  395. package/dist/infra/outbound/channel-selection.js +12 -6
  396. package/dist/infra/outbound/envelope.js +1 -1
  397. package/dist/infra/outbound/format.js +12 -6
  398. package/dist/infra/outbound/payloads.js +14 -7
  399. package/dist/infra/outbound/session-binding-service.js +123 -0
  400. package/dist/infra/path-guards.js +25 -0
  401. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  402. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  403. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  404. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  405. package/dist/infra/retry-policy.js +4 -2
  406. package/dist/infra/retry.js +9 -5
  407. package/dist/infra/session-cost-usage.js +107 -59
  408. package/dist/infra/session-maintenance-warning.js +3 -1
  409. package/dist/infra/shell-env.js +98 -34
  410. package/dist/infra/ssh-config.js +12 -6
  411. package/dist/infra/system-run-command.js +49 -4
  412. package/dist/infra/update-channels.js +10 -5
  413. package/dist/line/accounts.js +5 -7
  414. package/dist/line/bot-access.js +8 -20
  415. package/dist/line/bot-handlers.js +3 -1
  416. package/dist/link-understanding/detect.js +15 -7
  417. package/dist/media/constants.js +15 -6
  418. package/dist/media/image-ops.js +7 -0
  419. package/dist/media/local-roots.js +3 -2
  420. package/dist/media-understanding/apply.js +4 -1
  421. package/dist/media-understanding/concurrency.js +8 -20
  422. package/dist/memory/backend-config.js +45 -6
  423. package/dist/memory/embeddings.js +10 -4
  424. package/dist/memory/fs-utils.js +23 -0
  425. package/dist/memory/manager-search.js +12 -6
  426. package/dist/memory/manager-sync-ops.js +12 -2
  427. package/dist/memory/qmd-manager.js +466 -53
  428. package/dist/memory/query-expansion.js +167 -3
  429. package/dist/memory/status-format.js +10 -5
  430. package/dist/memory/sync-memory-files.js +1 -1
  431. package/dist/node-host/invoke-system-run.js +281 -0
  432. package/dist/node-host/invoke.js +55 -337
  433. package/dist/pairing/pairing-store.js +22 -0
  434. package/dist/plugin-sdk/allow-from.js +1 -1
  435. package/dist/plugin-sdk/command-auth.js +3 -1
  436. package/dist/plugin-sdk/index.js +6 -3
  437. package/dist/plugin-sdk/webhook-targets.js +32 -0
  438. package/dist/plugins/bundled-dir.js +9 -6
  439. package/dist/plugins/hooks.js +50 -0
  440. package/dist/plugins/install.js +28 -16
  441. package/dist/plugins/runtime.js +3 -17
  442. package/dist/plugins/update.js +78 -12
  443. package/dist/process/spawn-utils.js +14 -7
  444. package/dist/providers/github-copilot-token.js +11 -6
  445. package/dist/providers/qwen-portal-oauth.js +14 -6
  446. package/dist/routing/account-id.js +30 -0
  447. package/dist/routing/resolve-route.js +3 -7
  448. package/dist/routing/session-key.js +2 -16
  449. package/dist/security/audit-channel.js +93 -2
  450. package/dist/security/audit-extra.async.js +159 -5
  451. package/dist/security/audit-extra.js +1 -1
  452. package/dist/security/audit-extra.sync.js +85 -6
  453. package/dist/security/audit.js +40 -4
  454. package/dist/security/dm-policy-shared.js +44 -0
  455. package/dist/security/external-content.js +26 -6
  456. package/dist/shared/entry-status.js +6 -0
  457. package/dist/shared/frontmatter.js +5 -5
  458. package/dist/shared/node-match.js +11 -4
  459. package/dist/shared/operator-scope-compat.js +8 -3
  460. package/dist/signal/accounts.js +7 -20
  461. package/dist/signal/monitor/event-handler.js +3 -1
  462. package/dist/slack/accounts.js +6 -19
  463. package/dist/slack/actions.js +11 -3
  464. package/dist/slack/monitor/auth.js +1 -1
  465. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  466. package/dist/slack/monitor/replies.js +15 -7
  467. package/dist/slack/monitor/slash.js +22 -13
  468. package/dist/slack/resolve-channels.js +10 -5
  469. package/dist/slack/send.js +102 -12
  470. package/dist/slack/stream-mode.js +10 -0
  471. package/dist/slack/streaming.js +4 -2
  472. package/dist/telegram/accounts.js +19 -14
  473. package/dist/telegram/bot/helpers.js +3 -5
  474. package/dist/telegram/bot-access.js +35 -36
  475. package/dist/telegram/bot-handlers.js +120 -148
  476. package/dist/telegram/bot-message-context.js +68 -9
  477. package/dist/telegram/bot-message-dispatch.js +155 -90
  478. package/dist/telegram/bot-native-commands.js +16 -0
  479. package/dist/telegram/draft-stream.js +14 -1
  480. package/dist/telegram/inline-buttons.js +5 -15
  481. package/dist/telegram/monitor.js +11 -7
  482. package/dist/telegram/network-config.js +19 -7
  483. package/dist/telegram/send.js +3 -2
  484. package/dist/telegram/sent-message-cache.js +5 -6
  485. package/dist/telegram/status-reaction-variants.js +208 -0
  486. package/dist/telegram/sticker-cache.js +11 -9
  487. package/dist/terminal/theme.js +12 -12
  488. package/dist/tts/tts.js +80 -567
  489. package/dist/tui/components/chat-log.js +41 -8
  490. package/dist/tui/theme/theme.js +10 -12
  491. package/dist/tui/tui-local-shell.js +16 -6
  492. package/dist/tui/tui.js +58 -6
  493. package/dist/utils/account-id.js +2 -4
  494. package/dist/utils/boolean.js +10 -5
  495. package/dist/utils/directive-tags.js +11 -0
  496. package/dist/utils/queue-helpers.js +67 -12
  497. package/dist/web/auto-reply/deliver-reply.js +8 -4
  498. package/dist/web/auto-reply/mentions.js +10 -5
  499. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  500. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  501. package/dist/web/inbound/access-control.js +5 -2
  502. package/dist/web/login-qr.js +12 -6
  503. package/dist/web/media.js +123 -16
  504. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  505. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  506. package/package.json +1 -1
@@ -29,6 +29,24 @@ export function createHookRunner(registry, options = {}) {
29
29
  ? `${acc.prependContext}\n\n${next.prependContext}`
30
30
  : (next.prependContext ?? acc?.prependContext),
31
31
  });
32
+ const mergeSubagentSpawningResult = (acc, next) => {
33
+ if (acc?.status === "error") {
34
+ return acc;
35
+ }
36
+ if (next.status === "error") {
37
+ return next;
38
+ }
39
+ return {
40
+ status: "ok",
41
+ threadBindingReady: Boolean(acc?.threadBindingReady || next.threadBindingReady),
42
+ };
43
+ };
44
+ const mergeSubagentDeliveryTargetResult = (acc, next) => {
45
+ if (acc?.origin) {
46
+ return acc;
47
+ }
48
+ return next;
49
+ };
32
50
  /**
33
51
  * Run a hook that doesn't return a value (fire-and-forget style).
34
52
  * All handlers are executed in parallel for performance.
@@ -338,6 +356,34 @@ export function createHookRunner(registry, options = {}) {
338
356
  async function runSessionEnd(event, ctx) {
339
357
  return runVoidHook("session_end", event, ctx);
340
358
  }
359
+ /**
360
+ * Run subagent_spawning hook.
361
+ * Runs sequentially so channel plugins can deterministically provision session bindings.
362
+ */
363
+ async function runSubagentSpawning(event, ctx) {
364
+ return runModifyingHook("subagent_spawning", event, ctx, mergeSubagentSpawningResult);
365
+ }
366
+ /**
367
+ * Run subagent_delivery_target hook.
368
+ * Runs sequentially so channel plugins can deterministically resolve routing.
369
+ */
370
+ async function runSubagentDeliveryTarget(event, ctx) {
371
+ return runModifyingHook("subagent_delivery_target", event, ctx, mergeSubagentDeliveryTargetResult);
372
+ }
373
+ /**
374
+ * Run subagent_spawned hook.
375
+ * Runs in parallel (fire-and-forget).
376
+ */
377
+ async function runSubagentSpawned(event, ctx) {
378
+ return runVoidHook("subagent_spawned", event, ctx);
379
+ }
380
+ /**
381
+ * Run subagent_ended hook.
382
+ * Runs in parallel (fire-and-forget).
383
+ */
384
+ async function runSubagentEnded(event, ctx) {
385
+ return runVoidHook("subagent_ended", event, ctx);
386
+ }
341
387
  // =========================================================================
342
388
  // Gateway Hooks
343
389
  // =========================================================================
@@ -394,6 +440,10 @@ export function createHookRunner(registry, options = {}) {
394
440
  // Session hooks
395
441
  runSessionStart,
396
442
  runSessionEnd,
443
+ runSubagentSpawning,
444
+ runSubagentDeliveryTarget,
445
+ runSubagentSpawned,
446
+ runSubagentEnded,
397
447
  // Gateway hooks
398
448
  runGatewayStart,
399
449
  runGatewayStop,
@@ -4,7 +4,8 @@ import { MANIFEST_KEY } from "../compat/legacy-names.js";
4
4
  import { extractArchive, fileExists, readJsonFile, resolveArchiveKind, resolvePackedRootDir, } from "../infra/archive.js";
5
5
  import { installPackageDir } from "../infra/install-package-dir.js";
6
6
  import { resolveSafeInstallDir, safeDirName, unscopedPackageName, } from "../infra/install-safe-path.js";
7
- import { packNpmSpecToArchive, resolveArchiveSourcePath, withTempDir, } from "../infra/install-source-utils.js";
7
+ import { resolveArchiveSourcePath, withTempDir, } from "../infra/install-source-utils.js";
8
+ import { installFromNpmSpecArchive } from "../infra/npm-pack-install.js";
8
9
  import { validateRegistryNpmSpec } from "../infra/npm-registry-spec.js";
9
10
  import { extensionUsesSkippedScannerPath, isPathInside } from "../security/scan-paths.js";
10
11
  import * as skillScanner from "../security/skill-scanner.js";
@@ -25,7 +26,7 @@ function validatePluginId(pluginId) {
25
26
  }
26
27
  return null;
27
28
  }
28
- async function ensurePoolbotExtensions(manifest) {
29
+ async function ensurePoolBotExtensions(manifest) {
29
30
  const extensions = manifest[MANIFEST_KEY]?.extensions;
30
31
  if (!Array.isArray(extensions)) {
31
32
  throw new Error("package.json missing poolbot.extensions");
@@ -92,7 +93,7 @@ async function installPluginFromPackageDir(params) {
92
93
  }
93
94
  let extensions;
94
95
  try {
95
- extensions = await ensurePoolbotExtensions(manifest);
96
+ extensions = await ensurePoolBotExtensions(manifest);
96
97
  }
97
98
  catch (err) {
98
99
  return { ok: false, error: String(err) };
@@ -302,26 +303,37 @@ export async function installPluginFromNpmSpec(params) {
302
303
  if (specError) {
303
304
  return { ok: false, error: specError };
304
305
  }
305
- return await withTempDir("poolbot-npm-pack-", async (tmpDir) => {
306
- logger.info?.(`Downloading ${spec}…`);
307
- const packedResult = await packNpmSpecToArchive({
308
- spec,
309
- timeoutMs,
310
- cwd: tmpDir,
311
- });
312
- if (!packedResult.ok) {
313
- return packedResult;
314
- }
315
- return await installPluginFromArchive({
316
- archivePath: packedResult.archivePath,
306
+ logger.info?.(`Downloading ${spec}…`);
307
+ const flowResult = await installFromNpmSpecArchive({
308
+ tempDirPrefix: "poolbot-npm-pack-",
309
+ spec,
310
+ timeoutMs,
311
+ expectedIntegrity: params.expectedIntegrity,
312
+ onIntegrityDrift: params.onIntegrityDrift,
313
+ warn: (message) => {
314
+ logger.warn?.(message);
315
+ },
316
+ installFromArchive: async ({ archivePath }) => await installPluginFromArchive({
317
+ archivePath,
317
318
  extensionsDir: params.extensionsDir,
318
319
  timeoutMs,
319
320
  logger,
320
321
  mode,
321
322
  dryRun,
322
323
  expectedPluginId,
323
- });
324
+ }),
324
325
  });
326
+ if (!flowResult.ok) {
327
+ return flowResult;
328
+ }
329
+ if (!flowResult.installResult.ok) {
330
+ return flowResult.installResult;
331
+ }
332
+ return {
333
+ ...flowResult.installResult,
334
+ npmResolution: flowResult.npmResolution,
335
+ integrityDrift: flowResult.integrityDrift,
336
+ };
325
337
  }
326
338
  export async function installPluginFromPath(params) {
327
339
  const resolved = resolveUserPath(params.path);
@@ -1,24 +1,10 @@
1
- const createEmptyRegistry = () => ({
2
- plugins: [],
3
- tools: [],
4
- hooks: [],
5
- typedHooks: [],
6
- channels: [],
7
- providers: [],
8
- gatewayHandlers: {},
9
- httpHandlers: [],
10
- httpRoutes: [],
11
- cliRegistrars: [],
12
- services: [],
13
- commands: [],
14
- diagnostics: [],
15
- });
1
+ import { createEmptyPluginRegistry } from "./registry.js";
16
2
  const REGISTRY_STATE = Symbol.for("poolbot.pluginRegistryState");
17
3
  const state = (() => {
18
4
  const globalState = globalThis;
19
5
  if (!globalState[REGISTRY_STATE]) {
20
6
  globalState[REGISTRY_STATE] = {
21
- registry: createEmptyRegistry(),
7
+ registry: createEmptyPluginRegistry(),
22
8
  key: null,
23
9
  };
24
10
  }
@@ -33,7 +19,7 @@ export function getActivePluginRegistry() {
33
19
  }
34
20
  export function requireActivePluginRegistry() {
35
21
  if (!state.registry) {
36
- state.registry = createEmptyRegistry();
22
+ state.registry = createEmptyPluginRegistry();
37
23
  }
38
24
  return state.registry;
39
25
  }
@@ -18,14 +18,17 @@ function resolveBundledPluginSources(params) {
18
18
  const discovery = discoverPoolBotPlugins({ workspaceDir: params.workspaceDir });
19
19
  const bundled = new Map();
20
20
  for (const candidate of discovery.candidates) {
21
- if (candidate.origin !== "bundled")
21
+ if (candidate.origin !== "bundled") {
22
22
  continue;
23
+ }
23
24
  const manifest = loadPluginManifest(candidate.rootDir);
24
- if (!manifest.ok)
25
+ if (!manifest.ok) {
25
26
  continue;
27
+ }
26
28
  const pluginId = manifest.manifest.id;
27
- if (bundled.has(pluginId))
29
+ if (bundled.has(pluginId)) {
28
30
  continue;
31
+ }
29
32
  const npmSpec = candidate.packagePoolbot?.install?.npmSpec?.trim() ||
30
33
  candidate.packageName?.trim() ||
31
34
  undefined;
@@ -38,8 +41,9 @@ function resolveBundledPluginSources(params) {
38
41
  return bundled;
39
42
  }
40
43
  function pathsEqual(left, right) {
41
- if (!left || !right)
44
+ if (!left || !right) {
42
45
  return false;
46
+ }
43
47
  return resolveUserPath(left) === resolveUserPath(right);
44
48
  }
45
49
  function buildLoadPathHelpers(existing) {
@@ -49,16 +53,18 @@ function buildLoadPathHelpers(existing) {
49
53
  let changed = false;
50
54
  const addPath = (value) => {
51
55
  const normalized = resolveUserPath(value);
52
- if (resolved.has(normalized))
56
+ if (resolved.has(normalized)) {
53
57
  return;
58
+ }
54
59
  paths.push(value);
55
60
  resolved.add(normalized);
56
61
  changed = true;
57
62
  };
58
63
  const removePath = (value) => {
59
64
  const normalized = resolveUserPath(value);
60
- if (!resolved.has(normalized))
65
+ if (!resolved.has(normalized)) {
61
66
  return;
67
+ }
62
68
  paths = paths.filter((entry) => resolveUserPath(entry) !== normalized);
63
69
  resolved = resolveSet();
64
70
  changed = true;
@@ -74,6 +80,24 @@ function buildLoadPathHelpers(existing) {
74
80
  },
75
81
  };
76
82
  }
83
+ function createPluginUpdateIntegrityDriftHandler(params) {
84
+ return async (drift) => {
85
+ const payload = {
86
+ pluginId: params.pluginId,
87
+ spec: drift.spec,
88
+ expectedIntegrity: drift.expectedIntegrity,
89
+ actualIntegrity: drift.actualIntegrity,
90
+ resolvedSpec: drift.resolution.resolvedSpec,
91
+ resolvedVersion: drift.resolution.version,
92
+ dryRun: params.dryRun,
93
+ };
94
+ if (params.onIntegrityDrift) {
95
+ return await params.onIntegrityDrift(payload);
96
+ }
97
+ params.logger.warn?.(`Integrity drift for "${params.pluginId}" (${payload.resolvedSpec ?? payload.spec}): expected ${payload.expectedIntegrity}, got ${payload.actualIntegrity}`);
98
+ return true;
99
+ };
100
+ }
77
101
  export async function updateNpmInstalledPlugins(params) {
78
102
  const logger = params.logger ?? {};
79
103
  const installs = params.config.plugins?.installs ?? {};
@@ -115,7 +139,18 @@ export async function updateNpmInstalledPlugins(params) {
115
139
  });
116
140
  continue;
117
141
  }
118
- const installPath = record.installPath ?? resolvePluginInstallDir(pluginId);
142
+ let installPath;
143
+ try {
144
+ installPath = record.installPath ?? resolvePluginInstallDir(pluginId);
145
+ }
146
+ catch (err) {
147
+ outcomes.push({
148
+ pluginId,
149
+ status: "error",
150
+ message: `Invalid install path for "${pluginId}": ${String(err)}`,
151
+ });
152
+ continue;
153
+ }
119
154
  const currentVersion = await readInstalledPackageVersion(installPath);
120
155
  if (params.dryRun) {
121
156
  let probe;
@@ -125,6 +160,13 @@ export async function updateNpmInstalledPlugins(params) {
125
160
  mode: "update",
126
161
  dryRun: true,
127
162
  expectedPluginId: pluginId,
163
+ expectedIntegrity: record.integrity,
164
+ onIntegrityDrift: createPluginUpdateIntegrityDriftHandler({
165
+ pluginId,
166
+ dryRun: true,
167
+ logger,
168
+ onIntegrityDrift: params.onIntegrityDrift,
169
+ }),
128
170
  logger,
129
171
  });
130
172
  }
@@ -172,6 +214,13 @@ export async function updateNpmInstalledPlugins(params) {
172
214
  spec: record.spec,
173
215
  mode: "update",
174
216
  expectedPluginId: pluginId,
217
+ expectedIntegrity: record.integrity,
218
+ onIntegrityDrift: createPluginUpdateIntegrityDriftHandler({
219
+ pluginId,
220
+ dryRun: false,
221
+ logger,
222
+ onIntegrityDrift: params.onIntegrityDrift,
223
+ }),
175
224
  logger,
176
225
  });
177
226
  }
@@ -198,6 +247,12 @@ export async function updateNpmInstalledPlugins(params) {
198
247
  spec: record.spec,
199
248
  installPath: result.targetDir,
200
249
  version: nextVersion,
250
+ resolvedName: result.npmResolution?.name,
251
+ resolvedVersion: result.npmResolution?.version,
252
+ resolvedSpec: result.npmResolution?.resolvedSpec,
253
+ integrity: result.npmResolution?.integrity,
254
+ shasum: result.npmResolution?.shasum,
255
+ resolvedAt: result.npmResolution?.resolvedAt,
201
256
  });
202
257
  changed = true;
203
258
  const currentLabel = currentVersion ?? "unknown";
@@ -241,12 +296,14 @@ export async function syncPluginsForUpdateChannel(params) {
241
296
  if (params.channel === "dev") {
242
297
  for (const [pluginId, record] of Object.entries(installs)) {
243
298
  const bundledInfo = bundled.get(pluginId);
244
- if (!bundledInfo)
299
+ if (!bundledInfo) {
245
300
  continue;
301
+ }
246
302
  loadHelpers.addPath(bundledInfo.localPath);
247
303
  const alreadyBundled = record.source === "path" && pathsEqual(record.sourcePath, bundledInfo.localPath);
248
- if (alreadyBundled)
304
+ if (alreadyBundled) {
249
305
  continue;
306
+ }
250
307
  next = recordPluginInstall(next, {
251
308
  pluginId,
252
309
  source: "path",
@@ -262,16 +319,19 @@ export async function syncPluginsForUpdateChannel(params) {
262
319
  else {
263
320
  for (const [pluginId, record] of Object.entries(installs)) {
264
321
  const bundledInfo = bundled.get(pluginId);
265
- if (!bundledInfo)
322
+ if (!bundledInfo) {
266
323
  continue;
324
+ }
267
325
  if (record.source === "npm") {
268
326
  loadHelpers.removePath(bundledInfo.localPath);
269
327
  continue;
270
328
  }
271
- if (record.source !== "path")
329
+ if (record.source !== "path") {
272
330
  continue;
273
- if (!pathsEqual(record.sourcePath, bundledInfo.localPath))
331
+ }
332
+ if (!pathsEqual(record.sourcePath, bundledInfo.localPath)) {
274
333
  continue;
334
+ }
275
335
  const spec = record.spec ?? bundledInfo.npmSpec;
276
336
  if (!spec) {
277
337
  summary.warnings.push(`Missing npm spec for ${pluginId}; keeping local path.`);
@@ -300,6 +360,12 @@ export async function syncPluginsForUpdateChannel(params) {
300
360
  spec,
301
361
  installPath: result.targetDir,
302
362
  version: result.version,
363
+ resolvedName: result.npmResolution?.name,
364
+ resolvedVersion: result.npmResolution?.version,
365
+ resolvedSpec: result.npmResolution?.resolvedSpec,
366
+ integrity: result.npmResolution?.integrity,
367
+ shasum: result.npmResolution?.shasum,
368
+ resolvedAt: result.npmResolution?.resolvedAt,
303
369
  sourcePath: undefined,
304
370
  });
305
371
  summary.switchedToNpm.push(pluginId);
@@ -5,19 +5,24 @@ export function resolveCommandStdio(params) {
5
5
  return [stdin, "pipe", "pipe"];
6
6
  }
7
7
  export function formatSpawnError(err) {
8
- if (!(err instanceof Error))
8
+ if (!(err instanceof Error)) {
9
9
  return String(err);
10
+ }
10
11
  const details = err;
11
12
  const parts = [];
12
13
  const message = err.message?.trim();
13
- if (message)
14
+ if (message) {
14
15
  parts.push(message);
15
- if (details.code && !message?.includes(details.code))
16
+ }
17
+ if (details.code && !message?.includes(details.code)) {
16
18
  parts.push(details.code);
17
- if (details.syscall)
19
+ }
20
+ if (details.syscall) {
18
21
  parts.push(`syscall=${details.syscall}`);
19
- if (typeof details.errno === "number")
22
+ }
23
+ if (typeof details.errno === "number") {
20
24
  parts.push(`errno=${details.errno}`);
25
+ }
21
26
  return parts.join(" ");
22
27
  }
23
28
  function shouldRetry(err, codes) {
@@ -33,15 +38,17 @@ async function spawnAndWaitForSpawn(spawnImpl, argv, options) {
33
38
  child.removeListener("spawn", onSpawn);
34
39
  };
35
40
  const finishResolve = () => {
36
- if (settled)
41
+ if (settled) {
37
42
  return;
43
+ }
38
44
  settled = true;
39
45
  cleanup();
40
46
  resolve(child);
41
47
  };
42
48
  const onError = (err) => {
43
- if (settled)
49
+ if (settled) {
44
50
  return;
51
+ }
45
52
  settled = true;
46
53
  cleanup();
47
54
  reject(err);
@@ -39,25 +39,30 @@ function parseCopilotTokenResponse(value) {
39
39
  export const DEFAULT_COPILOT_API_BASE_URL = "https://api.individual.githubcopilot.com";
40
40
  export function deriveCopilotApiBaseUrlFromToken(token) {
41
41
  const trimmed = token.trim();
42
- if (!trimmed)
42
+ if (!trimmed) {
43
43
  return null;
44
+ }
44
45
  // The token returned from the Copilot token endpoint is a semicolon-delimited
45
46
  // set of key/value pairs. One of them is `proxy-ep=...`.
46
47
  const match = trimmed.match(/(?:^|;)\s*proxy-ep=([^;\s]+)/i);
47
48
  const proxyEp = match?.[1]?.trim();
48
- if (!proxyEp)
49
+ if (!proxyEp) {
49
50
  return null;
51
+ }
50
52
  // pi-ai expects converting proxy.* -> api.*
51
53
  // (see upstream getGitHubCopilotBaseUrl).
52
54
  const host = proxyEp.replace(/^https?:\/\//, "").replace(/^proxy\./i, "api.");
53
- if (!host)
55
+ if (!host) {
54
56
  return null;
57
+ }
55
58
  return `https://${host}`;
56
59
  }
57
60
  export async function resolveCopilotApiToken(params) {
58
61
  const env = params.env ?? process.env;
59
- const cachePath = resolveCopilotTokenCachePath(env);
60
- const cached = loadJsonFile(cachePath);
62
+ const cachePath = params.cachePath?.trim() || resolveCopilotTokenCachePath(env);
63
+ const loadJsonFileFn = params.loadJsonFileImpl ?? loadJsonFile;
64
+ const saveJsonFileFn = params.saveJsonFileImpl ?? saveJsonFile;
65
+ const cached = loadJsonFileFn(cachePath);
61
66
  if (cached && typeof cached.token === "string" && typeof cached.expiresAt === "number") {
62
67
  if (isTokenUsable(cached)) {
63
68
  return {
@@ -85,7 +90,7 @@ export async function resolveCopilotApiToken(params) {
85
90
  expiresAt: json.expiresAt,
86
91
  updatedAt: Date.now(),
87
92
  };
88
- saveJsonFile(cachePath, payload);
93
+ saveJsonFileFn(cachePath, payload);
89
94
  return {
90
95
  token: payload.token,
91
96
  expiresAt: payload.expiresAt,
@@ -3,7 +3,8 @@ const QWEN_OAUTH_BASE_URL = "https://chat.qwen.ai";
3
3
  const QWEN_OAUTH_TOKEN_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/token`;
4
4
  const QWEN_OAUTH_CLIENT_ID = "f0304373b74a44d2b584a3fb70ca9e56";
5
5
  export async function refreshQwenPortalCredentials(credentials) {
6
- if (!credentials.refresh?.trim()) {
6
+ const refreshToken = credentials.refresh?.trim();
7
+ if (!refreshToken) {
7
8
  throw new Error("Qwen OAuth refresh token missing; re-authenticate.");
8
9
  }
9
10
  const response = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
@@ -14,7 +15,7 @@ export async function refreshQwenPortalCredentials(credentials) {
14
15
  },
15
16
  body: new URLSearchParams({
16
17
  grant_type: "refresh_token",
17
- refresh_token: credentials.refresh,
18
+ refresh_token: refreshToken,
18
19
  client_id: QWEN_OAUTH_CLIENT_ID,
19
20
  }),
20
21
  });
@@ -26,13 +27,20 @@ export async function refreshQwenPortalCredentials(credentials) {
26
27
  throw new Error(`Qwen OAuth refresh failed: ${text || response.statusText}`);
27
28
  }
28
29
  const payload = (await response.json());
29
- if (!payload.access_token || !payload.expires_in) {
30
+ const accessToken = payload.access_token?.trim();
31
+ const newRefreshToken = payload.refresh_token?.trim();
32
+ const expiresIn = payload.expires_in;
33
+ if (!accessToken) {
30
34
  throw new Error("Qwen OAuth refresh response missing access token.");
31
35
  }
36
+ if (typeof expiresIn !== "number" || !Number.isFinite(expiresIn) || expiresIn <= 0) {
37
+ throw new Error("Qwen OAuth refresh response missing or invalid expires_in.");
38
+ }
32
39
  return {
33
40
  ...credentials,
34
- access: payload.access_token,
35
- refresh: payload.refresh_token || credentials.refresh,
36
- expires: Date.now() + payload.expires_in * 1000,
41
+ access: accessToken,
42
+ // RFC 6749 section 6: new refresh token is optional; if present, replace old.
43
+ refresh: newRefreshToken || refreshToken,
44
+ expires: Date.now() + expiresIn * 1000,
37
45
  };
38
46
  }
@@ -0,0 +1,30 @@
1
+ export const DEFAULT_ACCOUNT_ID = "default";
2
+ const VALID_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
3
+ const INVALID_CHARS_RE = /[^a-z0-9_-]+/g;
4
+ const LEADING_DASH_RE = /^-+/;
5
+ const TRAILING_DASH_RE = /-+$/;
6
+ function canonicalizeAccountId(value) {
7
+ if (VALID_ID_RE.test(value)) {
8
+ return value.toLowerCase();
9
+ }
10
+ return value
11
+ .toLowerCase()
12
+ .replace(INVALID_CHARS_RE, "-")
13
+ .replace(LEADING_DASH_RE, "")
14
+ .replace(TRAILING_DASH_RE, "")
15
+ .slice(0, 64);
16
+ }
17
+ export function normalizeAccountId(value) {
18
+ const trimmed = (value ?? "").trim();
19
+ if (!trimmed) {
20
+ return DEFAULT_ACCOUNT_ID;
21
+ }
22
+ return canonicalizeAccountId(trimmed) || DEFAULT_ACCOUNT_ID;
23
+ }
24
+ export function normalizeOptionalAccountId(value) {
25
+ const trimmed = (value ?? "").trim();
26
+ if (!trimmed) {
27
+ return undefined;
28
+ }
29
+ return canonicalizeAccountId(trimmed) || undefined;
30
+ }
@@ -3,7 +3,7 @@ import { normalizeChatType } from "../channels/chat-type.js";
3
3
  import { shouldLogVerbose } from "../globals.js";
4
4
  import { logDebug } from "../logger.js";
5
5
  import { listBindings } from "./bindings.js";
6
- import { buildAgentMainSessionKey, buildAgentPeerSessionKey, DEFAULT_ACCOUNT_ID, DEFAULT_MAIN_KEY, normalizeAgentId, sanitizeAgentId, } from "./session-key.js";
6
+ import { buildAgentMainSessionKey, buildAgentPeerSessionKey, DEFAULT_ACCOUNT_ID, DEFAULT_MAIN_KEY, normalizeAccountId as normalizeAccountIdShared, normalizeAgentId, sanitizeAgentId, } from "./session-key.js";
7
7
  export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID } from "./session-key.js";
8
8
  function normalizeToken(value) {
9
9
  return (value ?? "").trim().toLowerCase();
@@ -17,10 +17,6 @@ function normalizeId(value) {
17
17
  }
18
18
  return "";
19
19
  }
20
- function normalizeAccountId(value) {
21
- const trimmed = (value ?? "").trim();
22
- return trimmed ? trimmed : DEFAULT_ACCOUNT_ID;
23
- }
24
20
  function matchesAccountId(match, actual) {
25
21
  const trimmed = (match ?? "").trim();
26
22
  if (!trimmed) {
@@ -29,7 +25,7 @@ function matchesAccountId(match, actual) {
29
25
  if (trimmed === "*") {
30
26
  return true;
31
27
  }
32
- return trimmed === actual;
28
+ return normalizeAccountIdShared(trimmed) === actual;
33
29
  }
34
30
  export function buildAgentSessionKey(params) {
35
31
  const channel = normalizeToken(params.channel) || "unknown";
@@ -164,7 +160,7 @@ function matchesBindingScope(match, scope) {
164
160
  }
165
161
  export function resolveAgentRoute(input) {
166
162
  const channel = normalizeToken(input.channel);
167
- const accountId = normalizeAccountId(input.accountId);
163
+ const accountId = normalizeAccountIdShared(input.accountId);
168
164
  const peer = input.peer ? { kind: input.peer.kind, id: normalizeId(input.peer.id) } : null;
169
165
  const guildId = normalizeId(input.guildId);
170
166
  const teamId = normalizeId(input.teamId);
@@ -1,8 +1,9 @@
1
1
  import { parseAgentSessionKey } from "../sessions/session-key-utils.js";
2
+ import { normalizeAccountId } from "./account-id.js";
2
3
  export { getSubagentDepth, isCronSessionKey, isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, } from "../sessions/session-key-utils.js";
4
+ export { DEFAULT_ACCOUNT_ID, normalizeAccountId, normalizeOptionalAccountId, } from "./account-id.js";
3
5
  export const DEFAULT_AGENT_ID = "main";
4
6
  export const DEFAULT_MAIN_KEY = "main";
5
- export const DEFAULT_ACCOUNT_ID = "default";
6
7
  // Pre-compiled regex
7
8
  const VALID_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
8
9
  const INVALID_CHARS_RE = /[^a-z0-9_-]+/g;
@@ -82,21 +83,6 @@ export function sanitizeAgentId(value) {
82
83
  .replace(TRAILING_DASH_RE, "")
83
84
  .slice(0, 64) || DEFAULT_AGENT_ID);
84
85
  }
85
- export function normalizeAccountId(value) {
86
- const trimmed = (value ?? "").trim();
87
- if (!trimmed) {
88
- return DEFAULT_ACCOUNT_ID;
89
- }
90
- if (VALID_ID_RE.test(trimmed)) {
91
- return trimmed.toLowerCase();
92
- }
93
- return (trimmed
94
- .toLowerCase()
95
- .replace(INVALID_CHARS_RE, "-")
96
- .replace(LEADING_DASH_RE, "")
97
- .replace(TRAILING_DASH_RE, "")
98
- .slice(0, 64) || DEFAULT_ACCOUNT_ID);
99
- }
100
86
  export function buildAgentMainSessionKey(params) {
101
87
  const agentId = normalizeAgentId(params.agentId);
102
88
  const mainKey = normalizeMainKey(params.mainKey);