@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,12 +1,37 @@
1
- import { getOAuthApiKey } from "@mariozechner/pi-ai";
2
- import lockfile from "proper-lockfile";
3
- import { refreshChutesTokens } from "../chutes-oauth.js";
1
+ import { getOAuthApiKey, getOAuthProviders, } from "@mariozechner/pi-ai";
2
+ import { withFileLock } from "../../infra/file-lock.js";
4
3
  import { refreshQwenPortalCredentials } from "../../providers/qwen-portal-oauth.js";
4
+ import { refreshChutesTokens } from "../chutes-oauth.js";
5
5
  import { AUTH_STORE_LOCK_OPTIONS, log } from "./constants.js";
6
6
  import { formatAuthDoctorHint } from "./doctor.js";
7
7
  import { ensureAuthStoreFile, resolveAuthStorePath } from "./paths.js";
8
8
  import { suggestOAuthProfileIdForLegacyDefault } from "./repair.js";
9
9
  import { ensureAuthProfileStore, saveAuthProfileStore } from "./store.js";
10
+ const OAUTH_PROVIDER_IDS = new Set(getOAuthProviders().map((provider) => provider.id));
11
+ const isOAuthProvider = (provider) => OAUTH_PROVIDER_IDS.has(provider);
12
+ const resolveOAuthProvider = (provider) => isOAuthProvider(provider) ? provider : null;
13
+ /** Bearer-token auth modes that are interchangeable (oauth tokens and raw tokens). */
14
+ const BEARER_AUTH_MODES = new Set(["oauth", "token"]);
15
+ const isCompatibleModeType = (mode, type) => {
16
+ if (!mode || !type) {
17
+ return false;
18
+ }
19
+ if (mode === type) {
20
+ return true;
21
+ }
22
+ // Both token and oauth represent bearer-token auth paths — allow bidirectional compat.
23
+ return BEARER_AUTH_MODES.has(mode) && BEARER_AUTH_MODES.has(type);
24
+ };
25
+ function isProfileConfigCompatible(params) {
26
+ const profileConfig = params.cfg?.auth?.profiles?.[params.profileId];
27
+ if (profileConfig && profileConfig.provider !== params.provider) {
28
+ return false;
29
+ }
30
+ if (profileConfig && !isCompatibleModeType(profileConfig.mode, params.mode)) {
31
+ return false;
32
+ }
33
+ return true;
34
+ }
10
35
  function buildOAuthApiKey(provider, credentials) {
11
36
  const needsProjectId = provider === "google-gemini-cli" || provider === "google-antigravity";
12
37
  return needsProjectId
@@ -16,18 +41,62 @@ function buildOAuthApiKey(provider, credentials) {
16
41
  })
17
42
  : credentials.access;
18
43
  }
44
+ function buildApiKeyProfileResult(params) {
45
+ return {
46
+ apiKey: params.apiKey,
47
+ provider: params.provider,
48
+ email: params.email,
49
+ };
50
+ }
51
+ function buildOAuthProfileResult(params) {
52
+ return buildApiKeyProfileResult({
53
+ apiKey: buildOAuthApiKey(params.provider, params.credentials),
54
+ provider: params.provider,
55
+ email: params.email,
56
+ });
57
+ }
58
+ function isExpiredCredential(expires) {
59
+ return (typeof expires === "number" && Number.isFinite(expires) && expires > 0 && Date.now() >= expires);
60
+ }
61
+ function adoptNewerMainOAuthCredential(params) {
62
+ if (!params.agentDir) {
63
+ return null;
64
+ }
65
+ try {
66
+ const mainStore = ensureAuthProfileStore(undefined);
67
+ const mainCred = mainStore.profiles[params.profileId];
68
+ if (mainCred?.type === "oauth" &&
69
+ mainCred.provider === params.cred.provider &&
70
+ Number.isFinite(mainCred.expires) &&
71
+ (!Number.isFinite(params.cred.expires) || mainCred.expires > params.cred.expires)) {
72
+ params.store.profiles[params.profileId] = { ...mainCred };
73
+ saveAuthProfileStore(params.store, params.agentDir);
74
+ log.info("adopted newer OAuth credentials from main agent", {
75
+ profileId: params.profileId,
76
+ agentDir: params.agentDir,
77
+ expires: new Date(mainCred.expires).toISOString(),
78
+ });
79
+ return mainCred;
80
+ }
81
+ }
82
+ catch (err) {
83
+ // Best-effort: don't crash if main agent store is missing or unreadable.
84
+ log.debug("adoptNewerMainOAuthCredential failed", {
85
+ profileId: params.profileId,
86
+ error: err instanceof Error ? err.message : String(err),
87
+ });
88
+ }
89
+ return null;
90
+ }
19
91
  async function refreshOAuthTokenWithLock(params) {
20
92
  const authPath = resolveAuthStorePath(params.agentDir);
21
93
  ensureAuthStoreFile(authPath);
22
- let release;
23
- try {
24
- release = await lockfile.lock(authPath, {
25
- ...AUTH_STORE_LOCK_OPTIONS,
26
- });
94
+ return await withFileLock(authPath, AUTH_STORE_LOCK_OPTIONS, async () => {
27
95
  const store = ensureAuthProfileStore(params.agentDir);
28
96
  const cred = store.profiles[params.profileId];
29
- if (!cred || cred.type !== "oauth")
97
+ if (!cred || cred.type !== "oauth") {
30
98
  return null;
99
+ }
31
100
  if (Date.now() < cred.expires) {
32
101
  return {
33
102
  apiKey: buildOAuthApiKey(cred.provider, cred),
@@ -49,9 +118,16 @@ async function refreshOAuthTokenWithLock(params) {
49
118
  const newCredentials = await refreshQwenPortalCredentials(cred);
50
119
  return { apiKey: newCredentials.access, newCredentials };
51
120
  })()
52
- : await getOAuthApiKey(cred.provider, oauthCreds);
53
- if (!result)
121
+ : await (async () => {
122
+ const oauthProvider = resolveOAuthProvider(cred.provider);
123
+ if (!oauthProvider) {
124
+ return null;
125
+ }
126
+ return await getOAuthApiKey(oauthProvider, oauthCreds);
127
+ })();
128
+ if (!result) {
54
129
  return null;
130
+ }
55
131
  store.profiles[params.profileId] = {
56
132
  ...cred,
57
133
  ...result.newCredentials,
@@ -59,104 +135,111 @@ async function refreshOAuthTokenWithLock(params) {
59
135
  };
60
136
  saveAuthProfileStore(store, params.agentDir);
61
137
  return result;
62
- }
63
- finally {
64
- if (release) {
65
- try {
66
- await release();
67
- }
68
- catch {
69
- // ignore unlock errors
70
- }
71
- }
72
- }
138
+ });
73
139
  }
74
140
  async function tryResolveOAuthProfile(params) {
75
141
  const { cfg, store, profileId } = params;
76
142
  const cred = store.profiles[profileId];
77
- if (!cred || cred.type !== "oauth")
78
- return null;
79
- const profileConfig = cfg?.auth?.profiles?.[profileId];
80
- if (profileConfig && profileConfig.provider !== cred.provider)
143
+ if (!cred || cred.type !== "oauth") {
81
144
  return null;
82
- if (profileConfig && profileConfig.mode !== cred.type)
145
+ }
146
+ if (!isProfileConfigCompatible({
147
+ cfg,
148
+ profileId,
149
+ provider: cred.provider,
150
+ mode: cred.type,
151
+ })) {
83
152
  return null;
153
+ }
84
154
  if (Date.now() < cred.expires) {
85
- return {
86
- apiKey: buildOAuthApiKey(cred.provider, cred),
155
+ return buildOAuthProfileResult({
87
156
  provider: cred.provider,
157
+ credentials: cred,
88
158
  email: cred.email,
89
- };
159
+ });
90
160
  }
91
161
  const refreshed = await refreshOAuthTokenWithLock({
92
162
  profileId,
93
163
  agentDir: params.agentDir,
94
164
  });
95
- if (!refreshed)
165
+ if (!refreshed) {
96
166
  return null;
97
- return {
167
+ }
168
+ return buildApiKeyProfileResult({
98
169
  apiKey: refreshed.apiKey,
99
170
  provider: cred.provider,
100
171
  email: cred.email,
101
- };
172
+ });
102
173
  }
103
174
  export async function resolveApiKeyForProfile(params) {
104
175
  const { cfg, store, profileId } = params;
105
176
  const cred = store.profiles[profileId];
106
- if (!cred)
107
- return null;
108
- const profileConfig = cfg?.auth?.profiles?.[profileId];
109
- if (profileConfig && profileConfig.provider !== cred.provider)
177
+ if (!cred) {
110
178
  return null;
111
- if (profileConfig && profileConfig.mode !== cred.type) {
179
+ }
180
+ if (!isProfileConfigCompatible({
181
+ cfg,
182
+ profileId,
183
+ provider: cred.provider,
184
+ mode: cred.type,
112
185
  // Compatibility: treat "oauth" config as compatible with stored token profiles.
113
- if (!(profileConfig.mode === "oauth" && cred.type === "token"))
114
- return null;
186
+ allowOAuthTokenCompatibility: true,
187
+ })) {
188
+ return null;
115
189
  }
116
190
  if (cred.type === "api_key") {
117
- return { apiKey: cred.key, provider: cred.provider, email: cred.email };
191
+ const key = cred.key?.trim();
192
+ if (!key) {
193
+ return null;
194
+ }
195
+ return buildApiKeyProfileResult({ apiKey: key, provider: cred.provider, email: cred.email });
118
196
  }
119
197
  if (cred.type === "token") {
120
198
  const token = cred.token?.trim();
121
- if (!token)
199
+ if (!token) {
122
200
  return null;
123
- if (typeof cred.expires === "number" &&
124
- Number.isFinite(cred.expires) &&
125
- cred.expires > 0 &&
126
- Date.now() >= cred.expires) {
201
+ }
202
+ if (isExpiredCredential(cred.expires)) {
127
203
  return null;
128
204
  }
129
- return { apiKey: token, provider: cred.provider, email: cred.email };
205
+ return buildApiKeyProfileResult({ apiKey: token, provider: cred.provider, email: cred.email });
130
206
  }
131
- if (Date.now() < cred.expires) {
132
- return {
133
- apiKey: buildOAuthApiKey(cred.provider, cred),
134
- provider: cred.provider,
135
- email: cred.email,
136
- };
207
+ const oauthCred = adoptNewerMainOAuthCredential({
208
+ store,
209
+ profileId,
210
+ agentDir: params.agentDir,
211
+ cred,
212
+ }) ?? cred;
213
+ if (Date.now() < oauthCred.expires) {
214
+ return buildOAuthProfileResult({
215
+ provider: oauthCred.provider,
216
+ credentials: oauthCred,
217
+ email: oauthCred.email,
218
+ });
137
219
  }
138
220
  try {
139
221
  const result = await refreshOAuthTokenWithLock({
140
222
  profileId,
141
223
  agentDir: params.agentDir,
142
224
  });
143
- if (!result)
225
+ if (!result) {
144
226
  return null;
145
- return {
227
+ }
228
+ return buildApiKeyProfileResult({
146
229
  apiKey: result.apiKey,
147
230
  provider: cred.provider,
148
231
  email: cred.email,
149
- };
232
+ });
150
233
  }
151
234
  catch (error) {
152
235
  const refreshedStore = ensureAuthProfileStore(params.agentDir);
153
236
  const refreshed = refreshedStore.profiles[profileId];
154
237
  if (refreshed?.type === "oauth" && Date.now() < refreshed.expires) {
155
- return {
156
- apiKey: buildOAuthApiKey(refreshed.provider, refreshed),
238
+ return buildOAuthProfileResult({
157
239
  provider: refreshed.provider,
240
+ credentials: refreshed,
158
241
  email: refreshed.email ?? cred.email,
159
- };
242
+ });
160
243
  }
161
244
  const fallbackProfileId = suggestOAuthProfileIdForLegacyDefault({
162
245
  cfg,
@@ -172,8 +255,9 @@ export async function resolveApiKeyForProfile(params) {
172
255
  profileId: fallbackProfileId,
173
256
  agentDir: params.agentDir,
174
257
  });
175
- if (fallbackResolved)
258
+ if (fallbackResolved) {
176
259
  return fallbackResolved;
260
+ }
177
261
  }
178
262
  catch {
179
263
  // keep original error
@@ -193,11 +277,11 @@ export async function resolveApiKeyForProfile(params) {
193
277
  agentDir: params.agentDir,
194
278
  expires: new Date(mainCred.expires).toISOString(),
195
279
  });
196
- return {
197
- apiKey: buildOAuthApiKey(mainCred.provider, mainCred),
280
+ return buildOAuthProfileResult({
198
281
  provider: mainCred.provider,
282
+ credentials: mainCred,
199
283
  email: mainCred.email,
200
- };
284
+ });
201
285
  }
202
286
  }
203
287
  catch {
@@ -213,6 +297,6 @@ export async function resolveApiKeyForProfile(params) {
213
297
  });
214
298
  throw new Error(`OAuth token refresh failed for ${cred.provider}: ${message}. ` +
215
299
  "Please try again or re-authenticate." +
216
- (hint ? `\n\n${hint}` : ""));
300
+ (hint ? `\n\n${hint}` : ""), { cause: error });
217
301
  }
218
302
  }
@@ -1,10 +1,11 @@
1
1
  import { updateSessionStore } from "../../config/sessions.js";
2
- import { normalizeProviderId } from "../model-selection.js";
3
2
  import { ensureAuthProfileStore, isProfileInCooldown, resolveAuthProfileOrder, } from "../auth-profiles.js";
3
+ import { normalizeProviderId } from "../model-selection.js";
4
4
  function isProfileForProvider(params) {
5
5
  const entry = params.store.profiles[params.profileId];
6
- if (!entry?.provider)
6
+ if (!entry?.provider) {
7
7
  return false;
8
+ }
8
9
  return normalizeProviderId(entry.provider) === normalizeProviderId(params.provider);
9
10
  }
10
11
  export async function clearSessionAuthProfileOverride(params) {
@@ -22,8 +23,9 @@ export async function clearSessionAuthProfileOverride(params) {
22
23
  }
23
24
  export async function resolveSessionAuthProfileOverride(params) {
24
25
  const { cfg, provider, agentDir, sessionEntry, sessionStore, sessionKey, storePath, isNewSession, } = params;
25
- if (!sessionEntry || !sessionStore || !sessionKey)
26
+ if (!sessionEntry || !sessionStore || !sessionKey) {
26
27
  return sessionEntry?.authProfileOverride;
28
+ }
27
29
  const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
28
30
  const order = resolveAuthProfileOrder({ cfg, store, provider });
29
31
  let current = sessionEntry.authProfileOverride?.trim();
@@ -39,17 +41,20 @@ export async function resolveSessionAuthProfileOverride(params) {
39
41
  await clearSessionAuthProfileOverride({ sessionEntry, sessionStore, sessionKey, storePath });
40
42
  current = undefined;
41
43
  }
42
- if (order.length === 0)
44
+ if (order.length === 0) {
43
45
  return undefined;
46
+ }
44
47
  const pickFirstAvailable = () => order.find((profileId) => !isProfileInCooldown(store, profileId)) ?? order[0];
45
48
  const pickNextAvailable = (active) => {
46
49
  const startIndex = order.indexOf(active);
47
- if (startIndex < 0)
50
+ if (startIndex < 0) {
48
51
  return pickFirstAvailable();
52
+ }
49
53
  for (let offset = 1; offset <= order.length; offset += 1) {
50
54
  const candidate = order[(startIndex + offset) % order.length];
51
- if (!isProfileInCooldown(store, candidate))
55
+ if (!isProfileInCooldown(store, candidate)) {
52
56
  return candidate;
57
+ }
53
58
  }
54
59
  return order[startIndex] ?? order[0];
55
60
  };
@@ -76,8 +81,9 @@ export async function resolveSessionAuthProfileOverride(params) {
76
81
  else if (!current || isProfileInCooldown(store, current)) {
77
82
  next = pickFirstAvailable();
78
83
  }
79
- if (!next)
84
+ if (!next) {
80
85
  return current;
86
+ }
81
87
  const shouldPersist = next !== sessionEntry.authProfileOverride ||
82
88
  sessionEntry.authProfileOverrideSource !== "auto" ||
83
89
  sessionEntry.authProfileOverrideCompactionCount !== compactionCount;
@@ -0,0 +1,29 @@
1
+ export function createProcessSessionFixture(params) {
2
+ const session = {
3
+ id: params.id,
4
+ command: params.command ?? "test",
5
+ startedAt: params.startedAt ?? Date.now(),
6
+ cwd: params.cwd ?? "/tmp",
7
+ maxOutputChars: params.maxOutputChars ?? 10_000,
8
+ pendingMaxOutputChars: params.pendingMaxOutputChars ?? 30_000,
9
+ totalOutputChars: 0,
10
+ pendingStdout: [],
11
+ pendingStderr: [],
12
+ pendingStdoutChars: 0,
13
+ pendingStderrChars: 0,
14
+ aggregated: "",
15
+ tail: "",
16
+ exited: false,
17
+ exitCode: undefined,
18
+ exitSignal: undefined,
19
+ truncated: false,
20
+ backgrounded: params.backgrounded ?? false,
21
+ };
22
+ if (params.pid !== undefined) {
23
+ session.pid = params.pid;
24
+ }
25
+ if (params.child) {
26
+ session.child = params.child;
27
+ }
28
+ return session;
29
+ }
@@ -0,0 +1,20 @@
1
+ import { DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS, DEFAULT_APPROVAL_TIMEOUT_MS, } from "./bash-tools.exec-runtime.js";
2
+ import { callGatewayTool } from "./tools/gateway.js";
3
+ export async function requestExecApprovalDecision(params) {
4
+ const decisionResult = await callGatewayTool("exec.approval.request", { timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS }, {
5
+ id: params.id,
6
+ command: params.command,
7
+ cwd: params.cwd,
8
+ host: params.host,
9
+ security: params.security,
10
+ ask: params.ask,
11
+ agentId: params.agentId,
12
+ resolvedPath: params.resolvedPath,
13
+ sessionKey: params.sessionKey,
14
+ timeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS,
15
+ });
16
+ const decisionValue = decisionResult && typeof decisionResult === "object"
17
+ ? decisionResult.decision
18
+ : undefined;
19
+ return typeof decisionValue === "string" ? decisionValue : null;
20
+ }
@@ -0,0 +1,240 @@
1
+ import crypto from "node:crypto";
2
+ import { addAllowlistEntry, buildSafeBinsShellCommand, buildSafeShellCommand, evaluateShellAllowlist, maxAsk, minSecurity, recordAllowlistUse, requiresExecApproval, resolveAllowAlwaysPatterns, resolveExecApprovals, } from "../infra/exec-approvals.js";
3
+ import { markBackgrounded, tail } from "./bash-process-registry.js";
4
+ import { requestExecApprovalDecision } from "./bash-tools.exec-approval-request.js";
5
+ import { DEFAULT_APPROVAL_TIMEOUT_MS, DEFAULT_NOTIFY_TAIL_CHARS, createApprovalSlug, emitExecSystemEvent, normalizeNotifyOutput, runExecProcess, } from "./bash-tools.exec-runtime.js";
6
+ export async function processGatewayAllowlist(params) {
7
+ const approvals = resolveExecApprovals(params.agentId, {
8
+ security: params.security,
9
+ ask: params.ask,
10
+ });
11
+ const hostSecurity = minSecurity(params.security, approvals.agent.security);
12
+ const hostAsk = maxAsk(params.ask, approvals.agent.ask);
13
+ const askFallback = approvals.agent.askFallback;
14
+ if (hostSecurity === "deny") {
15
+ throw new Error("exec denied: host=gateway security=deny");
16
+ }
17
+ const allowlistEval = evaluateShellAllowlist({
18
+ command: params.command,
19
+ allowlist: approvals.allowlist,
20
+ safeBins: params.safeBins,
21
+ cwd: params.workdir,
22
+ env: params.env,
23
+ platform: process.platform,
24
+ trustedSafeBinDirs: params.trustedSafeBinDirs,
25
+ });
26
+ const allowlistMatches = allowlistEval.allowlistMatches;
27
+ const analysisOk = allowlistEval.analysisOk;
28
+ const allowlistSatisfied = hostSecurity === "allowlist" && analysisOk ? allowlistEval.allowlistSatisfied : false;
29
+ const hasHeredocSegment = allowlistEval.segments.some((segment) => segment.argv.some((token) => token.startsWith("<<")));
30
+ const requiresHeredocApproval = hostSecurity === "allowlist" && analysisOk && allowlistSatisfied && hasHeredocSegment;
31
+ const requiresAsk = requiresExecApproval({
32
+ ask: hostAsk,
33
+ security: hostSecurity,
34
+ analysisOk,
35
+ allowlistSatisfied,
36
+ }) || requiresHeredocApproval;
37
+ if (requiresHeredocApproval) {
38
+ params.warnings.push("Warning: heredoc execution requires explicit approval in allowlist mode.");
39
+ }
40
+ if (requiresAsk) {
41
+ const approvalId = crypto.randomUUID();
42
+ const approvalSlug = createApprovalSlug(approvalId);
43
+ const expiresAtMs = Date.now() + DEFAULT_APPROVAL_TIMEOUT_MS;
44
+ const contextKey = `exec:${approvalId}`;
45
+ const resolvedPath = allowlistEval.segments[0]?.resolution?.resolvedPath;
46
+ const noticeSeconds = Math.max(1, Math.round(params.approvalRunningNoticeMs / 1000));
47
+ const effectiveTimeout = typeof params.timeoutSec === "number" ? params.timeoutSec : params.defaultTimeoutSec;
48
+ const warningText = params.warnings.length ? `${params.warnings.join("\n")}\n\n` : "";
49
+ void (async () => {
50
+ let decision = null;
51
+ try {
52
+ decision = await requestExecApprovalDecision({
53
+ id: approvalId,
54
+ command: params.command,
55
+ cwd: params.workdir,
56
+ host: "gateway",
57
+ security: hostSecurity,
58
+ ask: hostAsk,
59
+ agentId: params.agentId,
60
+ resolvedPath,
61
+ sessionKey: params.sessionKey,
62
+ });
63
+ }
64
+ catch {
65
+ emitExecSystemEvent(`Exec denied (gateway id=${approvalId}, approval-request-failed): ${params.command}`, {
66
+ sessionKey: params.notifySessionKey,
67
+ contextKey,
68
+ });
69
+ return;
70
+ }
71
+ let approvedByAsk = false;
72
+ let deniedReason = null;
73
+ if (decision === "deny") {
74
+ deniedReason = "user-denied";
75
+ }
76
+ else if (!decision) {
77
+ if (askFallback === "full") {
78
+ approvedByAsk = true;
79
+ }
80
+ else if (askFallback === "allowlist") {
81
+ if (!analysisOk || !allowlistSatisfied) {
82
+ deniedReason = "approval-timeout (allowlist-miss)";
83
+ }
84
+ else {
85
+ approvedByAsk = true;
86
+ }
87
+ }
88
+ else {
89
+ deniedReason = "approval-timeout";
90
+ }
91
+ }
92
+ else if (decision === "allow-once") {
93
+ approvedByAsk = true;
94
+ }
95
+ else if (decision === "allow-always") {
96
+ approvedByAsk = true;
97
+ if (hostSecurity === "allowlist") {
98
+ const patterns = resolveAllowAlwaysPatterns({
99
+ segments: allowlistEval.segments,
100
+ cwd: params.workdir,
101
+ env: params.env,
102
+ platform: process.platform,
103
+ });
104
+ for (const pattern of patterns) {
105
+ if (pattern) {
106
+ addAllowlistEntry(approvals.file, params.agentId, pattern);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ if (hostSecurity === "allowlist" && (!analysisOk || !allowlistSatisfied) && !approvedByAsk) {
112
+ deniedReason = deniedReason ?? "allowlist-miss";
113
+ }
114
+ if (deniedReason) {
115
+ emitExecSystemEvent(`Exec denied (gateway id=${approvalId}, ${deniedReason}): ${params.command}`, {
116
+ sessionKey: params.notifySessionKey,
117
+ contextKey,
118
+ });
119
+ return;
120
+ }
121
+ if (allowlistMatches.length > 0) {
122
+ const seen = new Set();
123
+ for (const match of allowlistMatches) {
124
+ if (seen.has(match.pattern)) {
125
+ continue;
126
+ }
127
+ seen.add(match.pattern);
128
+ recordAllowlistUse(approvals.file, params.agentId, match, params.command, resolvedPath ?? undefined);
129
+ }
130
+ }
131
+ let run = null;
132
+ try {
133
+ run = await runExecProcess({
134
+ command: params.command,
135
+ workdir: params.workdir,
136
+ env: params.env,
137
+ sandbox: undefined,
138
+ containerWorkdir: null,
139
+ usePty: params.pty,
140
+ warnings: params.warnings,
141
+ maxOutput: params.maxOutput,
142
+ pendingMaxOutput: params.pendingMaxOutput,
143
+ notifyOnExit: false,
144
+ notifyOnExitEmptySuccess: false,
145
+ scopeKey: params.scopeKey,
146
+ sessionKey: params.notifySessionKey,
147
+ timeoutSec: effectiveTimeout,
148
+ });
149
+ }
150
+ catch {
151
+ emitExecSystemEvent(`Exec denied (gateway id=${approvalId}, spawn-failed): ${params.command}`, {
152
+ sessionKey: params.notifySessionKey,
153
+ contextKey,
154
+ });
155
+ return;
156
+ }
157
+ markBackgrounded(run.session);
158
+ let runningTimer = null;
159
+ if (params.approvalRunningNoticeMs > 0) {
160
+ runningTimer = setTimeout(() => {
161
+ emitExecSystemEvent(`Exec running (gateway id=${approvalId}, session=${run?.session.id}, >${noticeSeconds}s): ${params.command}`, { sessionKey: params.notifySessionKey, contextKey });
162
+ }, params.approvalRunningNoticeMs);
163
+ }
164
+ const outcome = await run.promise;
165
+ if (runningTimer) {
166
+ clearTimeout(runningTimer);
167
+ }
168
+ const output = normalizeNotifyOutput(tail(outcome.aggregated || "", DEFAULT_NOTIFY_TAIL_CHARS));
169
+ const exitLabel = outcome.timedOut ? "timeout" : `code ${outcome.exitCode ?? "?"}`;
170
+ const summary = output
171
+ ? `Exec finished (gateway id=${approvalId}, session=${run.session.id}, ${exitLabel})\n${output}`
172
+ : `Exec finished (gateway id=${approvalId}, session=${run.session.id}, ${exitLabel})`;
173
+ emitExecSystemEvent(summary, { sessionKey: params.notifySessionKey, contextKey });
174
+ })();
175
+ return {
176
+ pendingResult: {
177
+ content: [
178
+ {
179
+ type: "text",
180
+ text: `${warningText}Approval required (id ${approvalSlug}). ` +
181
+ "Approve to run; updates will arrive after completion.",
182
+ },
183
+ ],
184
+ details: {
185
+ status: "approval-pending",
186
+ approvalId,
187
+ approvalSlug,
188
+ expiresAtMs,
189
+ host: "gateway",
190
+ command: params.command,
191
+ cwd: params.workdir,
192
+ },
193
+ },
194
+ };
195
+ }
196
+ if (hostSecurity === "allowlist" && (!analysisOk || !allowlistSatisfied)) {
197
+ throw new Error("exec denied: allowlist miss");
198
+ }
199
+ let execCommandOverride;
200
+ // If allowlist uses safeBins, sanitize only those stdin-only segments:
201
+ // disable glob/var expansion by forcing argv tokens to be literal via single-quoting.
202
+ if (hostSecurity === "allowlist" &&
203
+ analysisOk &&
204
+ allowlistSatisfied &&
205
+ allowlistEval.segmentSatisfiedBy.some((by) => by === "safeBins")) {
206
+ const safe = buildSafeBinsShellCommand({
207
+ command: params.command,
208
+ segments: allowlistEval.segments,
209
+ segmentSatisfiedBy: allowlistEval.segmentSatisfiedBy,
210
+ platform: process.platform,
211
+ });
212
+ if (!safe.ok || !safe.command) {
213
+ // Fallback: quote everything (safe, but may change glob behavior).
214
+ const fallback = buildSafeShellCommand({
215
+ command: params.command,
216
+ platform: process.platform,
217
+ });
218
+ if (!fallback.ok || !fallback.command) {
219
+ throw new Error(`exec denied: safeBins sanitize failed (${safe.reason ?? "unknown"})`);
220
+ }
221
+ params.warnings.push("Warning: safeBins hardening used fallback quoting due to parser mismatch.");
222
+ execCommandOverride = fallback.command;
223
+ }
224
+ else {
225
+ params.warnings.push("Warning: safeBins hardening disabled glob/variable expansion for stdin-only segments.");
226
+ execCommandOverride = safe.command;
227
+ }
228
+ }
229
+ if (allowlistMatches.length > 0) {
230
+ const seen = new Set();
231
+ for (const match of allowlistMatches) {
232
+ if (seen.has(match.pattern)) {
233
+ continue;
234
+ }
235
+ seen.add(match.pattern);
236
+ recordAllowlistUse(approvals.file, params.agentId, match, params.command, allowlistEval.segments[0]?.resolution?.resolvedPath);
237
+ }
238
+ }
239
+ return { execCommandOverride };
240
+ }