@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,31 +1,6 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
1
  import { DEFAULT_SAFE_BINS, analyzeShellCommand, isWindowsPlatform, matchAllowlist, resolveAllowlistCandidatePath, splitCommandChain, } from "./exec-approvals-analysis.js";
2
+ import { SAFE_BIN_GENERIC_PROFILE, SAFE_BIN_PROFILES, validateSafeBinArgv, } from "./exec-safe-bin-policy.js";
4
3
  import { isTrustedSafeBinPath } from "./exec-safe-bin-trust.js";
5
- function isPathLikeToken(value) {
6
- const trimmed = value.trim();
7
- if (!trimmed) {
8
- return false;
9
- }
10
- if (trimmed === "-") {
11
- return false;
12
- }
13
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("~")) {
14
- return true;
15
- }
16
- if (trimmed.startsWith("/")) {
17
- return true;
18
- }
19
- return /^[A-Za-z]:[\\/]/.test(trimmed);
20
- }
21
- function defaultFileExists(filePath) {
22
- try {
23
- return fs.existsSync(filePath);
24
- }
25
- catch {
26
- return false;
27
- }
28
- }
29
4
  export function normalizeSafeBins(entries) {
30
5
  if (!Array.isArray(entries)) {
31
6
  return new Set();
@@ -41,15 +16,10 @@ export function resolveSafeBins(entries) {
41
16
  }
42
17
  return normalizeSafeBins(entries ?? []);
43
18
  }
44
- function hasGlobToken(value) {
45
- // Safe bins are stdin-only; globbing is both surprising and a historical bypass vector.
46
- // Note: we still harden execution-time expansion separately.
47
- return /[*?[\]]/.test(value);
48
- }
49
19
  export function isSafeBinUsage(params) {
50
20
  // Windows host exec uses PowerShell, which has different parsing/expansion rules.
51
21
  // Keep safeBins conservative there (require explicit allowlist entries).
52
- if (isWindowsPlatform(process.platform)) {
22
+ if (isWindowsPlatform(params.platform ?? process.platform)) {
53
23
  return false;
54
24
  }
55
25
  if (params.safeBins.size === 0) {
@@ -60,55 +30,25 @@ export function isSafeBinUsage(params) {
60
30
  if (!execName) {
61
31
  return false;
62
32
  }
63
- const matchesSafeBin = params.safeBins.has(execName) ||
64
- (process.platform === "win32" && params.safeBins.has(path.parse(execName).name));
33
+ const matchesSafeBin = params.safeBins.has(execName);
65
34
  if (!matchesSafeBin) {
66
35
  return false;
67
36
  }
68
37
  if (!resolution?.resolvedPath) {
69
38
  return false;
70
39
  }
71
- if (!isTrustedSafeBinPath({
40
+ const isTrustedPath = params.isTrustedSafeBinPathFn ?? isTrustedSafeBinPath;
41
+ if (!isTrustedPath({
72
42
  resolvedPath: resolution.resolvedPath,
73
43
  trustedDirs: params.trustedSafeBinDirs,
74
44
  })) {
75
45
  return false;
76
46
  }
77
- const cwd = params.cwd ?? process.cwd();
78
- const exists = params.fileExists ?? defaultFileExists;
79
47
  const argv = params.argv.slice(1);
80
- for (let i = 0; i < argv.length; i += 1) {
81
- const token = argv[i];
82
- if (!token) {
83
- continue;
84
- }
85
- if (token === "-") {
86
- continue;
87
- }
88
- if (token.startsWith("-")) {
89
- const eqIndex = token.indexOf("=");
90
- if (eqIndex > 0) {
91
- const value = token.slice(eqIndex + 1);
92
- if (value && hasGlobToken(value)) {
93
- return false;
94
- }
95
- if (value && (isPathLikeToken(value) || exists(path.resolve(cwd, value)))) {
96
- return false;
97
- }
98
- }
99
- continue;
100
- }
101
- if (hasGlobToken(token)) {
102
- return false;
103
- }
104
- if (isPathLikeToken(token)) {
105
- return false;
106
- }
107
- if (exists(path.resolve(cwd, token))) {
108
- return false;
109
- }
110
- }
111
- return true;
48
+ const safeBinProfiles = params.safeBinProfiles ?? SAFE_BIN_PROFILES;
49
+ const genericSafeBinProfile = params.safeBinGenericProfile ?? SAFE_BIN_GENERIC_PROFILE;
50
+ const profile = safeBinProfiles[execName] ?? genericSafeBinProfile;
51
+ return validateSafeBinArgv(argv, profile);
112
52
  }
113
53
  function evaluateSegments(segments, params) {
114
54
  const matches = [];
@@ -127,7 +67,8 @@ function evaluateSegments(segments, params) {
127
67
  argv: segment.argv,
128
68
  resolution: segment.resolution,
129
69
  safeBins: params.safeBins,
130
- cwd: params.cwd,
70
+ platform: params.platform,
71
+ trustedSafeBinDirs: params.trustedSafeBinDirs,
131
72
  });
132
73
  const skillAllow = allowSkills && segment.resolution?.executableName
133
74
  ? params.skillBins?.has(segment.resolution.executableName)
@@ -157,6 +98,8 @@ export function evaluateExecAllowlist(params) {
157
98
  allowlist: params.allowlist,
158
99
  safeBins: params.safeBins,
159
100
  cwd: params.cwd,
101
+ platform: params.platform,
102
+ trustedSafeBinDirs: params.trustedSafeBinDirs,
160
103
  skillBins: params.skillBins,
161
104
  autoAllowSkills: params.autoAllowSkills,
162
105
  });
@@ -173,6 +116,8 @@ export function evaluateExecAllowlist(params) {
173
116
  allowlist: params.allowlist,
174
117
  safeBins: params.safeBins,
175
118
  cwd: params.cwd,
119
+ platform: params.platform,
120
+ trustedSafeBinDirs: params.trustedSafeBinDirs,
176
121
  skillBins: params.skillBins,
177
122
  autoAllowSkills: params.autoAllowSkills,
178
123
  });
@@ -182,6 +127,128 @@ export function evaluateExecAllowlist(params) {
182
127
  segmentSatisfiedBy: result.segmentSatisfiedBy,
183
128
  };
184
129
  }
130
+ const SHELL_WRAPPER_EXECUTABLES = new Set([
131
+ "ash",
132
+ "bash",
133
+ "cmd",
134
+ "cmd.exe",
135
+ "dash",
136
+ "fish",
137
+ "ksh",
138
+ "powershell",
139
+ "powershell.exe",
140
+ "pwsh",
141
+ "pwsh.exe",
142
+ "sh",
143
+ "zsh",
144
+ ]);
145
+ function normalizeExecutableName(name) {
146
+ return (name ?? "").trim().toLowerCase();
147
+ }
148
+ function isShellWrapperSegment(segment) {
149
+ const candidates = [
150
+ normalizeExecutableName(segment.resolution?.executableName),
151
+ normalizeExecutableName(segment.resolution?.rawExecutable),
152
+ ];
153
+ for (const candidate of candidates) {
154
+ if (!candidate) {
155
+ continue;
156
+ }
157
+ if (SHELL_WRAPPER_EXECUTABLES.has(candidate)) {
158
+ return true;
159
+ }
160
+ const base = candidate.split(/[\\/]/).pop();
161
+ if (base && SHELL_WRAPPER_EXECUTABLES.has(base)) {
162
+ return true;
163
+ }
164
+ }
165
+ return false;
166
+ }
167
+ function extractShellInlineCommand(argv) {
168
+ for (let i = 1; i < argv.length; i += 1) {
169
+ const token = argv[i];
170
+ if (!token) {
171
+ continue;
172
+ }
173
+ const lower = token.toLowerCase();
174
+ if (lower === "--") {
175
+ break;
176
+ }
177
+ if (lower === "-c" ||
178
+ lower === "--command" ||
179
+ lower === "-command" ||
180
+ lower === "/c" ||
181
+ lower === "/k") {
182
+ const next = argv[i + 1]?.trim();
183
+ return next ? next : null;
184
+ }
185
+ if (/^-[^-]*c[^-]*$/i.test(token)) {
186
+ const commandIndex = lower.indexOf("c");
187
+ const inline = token.slice(commandIndex + 1).trim();
188
+ if (inline) {
189
+ return inline;
190
+ }
191
+ const next = argv[i + 1]?.trim();
192
+ return next ? next : null;
193
+ }
194
+ }
195
+ return null;
196
+ }
197
+ function collectAllowAlwaysPatterns(params) {
198
+ const candidatePath = resolveAllowlistCandidatePath(params.segment.resolution, params.cwd);
199
+ if (!candidatePath) {
200
+ return;
201
+ }
202
+ if (!isShellWrapperSegment(params.segment)) {
203
+ params.out.add(candidatePath);
204
+ return;
205
+ }
206
+ if (params.depth >= 3) {
207
+ return;
208
+ }
209
+ const inlineCommand = extractShellInlineCommand(params.segment.argv);
210
+ if (!inlineCommand) {
211
+ return;
212
+ }
213
+ const nested = analyzeShellCommand({
214
+ command: inlineCommand,
215
+ cwd: params.cwd,
216
+ env: params.env,
217
+ platform: params.platform,
218
+ });
219
+ if (!nested.ok) {
220
+ return;
221
+ }
222
+ for (const nestedSegment of nested.segments) {
223
+ collectAllowAlwaysPatterns({
224
+ segment: nestedSegment,
225
+ cwd: params.cwd,
226
+ env: params.env,
227
+ platform: params.platform,
228
+ depth: params.depth + 1,
229
+ out: params.out,
230
+ });
231
+ }
232
+ }
233
+ /**
234
+ * Derive persisted allowlist patterns for an "allow always" decision.
235
+ * When a command is wrapped in a shell (for example `zsh -lc "<cmd>"`),
236
+ * persist the inner executable(s) rather than the shell binary.
237
+ */
238
+ export function resolveAllowAlwaysPatterns(params) {
239
+ const patterns = new Set();
240
+ for (const segment of params.segments) {
241
+ collectAllowAlwaysPatterns({
242
+ segment,
243
+ cwd: params.cwd,
244
+ env: params.env,
245
+ platform: params.platform,
246
+ depth: 0,
247
+ out: patterns,
248
+ });
249
+ }
250
+ return Array.from(patterns);
251
+ }
185
252
  /**
186
253
  * Evaluates allowlist for shell commands (including &&, ||, ;) and returns analysis metadata.
187
254
  */
@@ -209,6 +276,8 @@ export function evaluateShellAllowlist(params) {
209
276
  allowlist: params.allowlist,
210
277
  safeBins: params.safeBins,
211
278
  cwd: params.cwd,
279
+ platform: params.platform,
280
+ trustedSafeBinDirs: params.trustedSafeBinDirs,
212
281
  skillBins: params.skillBins,
213
282
  autoAllowSkills: params.autoAllowSkills,
214
283
  });
@@ -239,6 +308,8 @@ export function evaluateShellAllowlist(params) {
239
308
  allowlist: params.allowlist,
240
309
  safeBins: params.safeBins,
241
310
  cwd: params.cwd,
311
+ platform: params.platform,
312
+ trustedSafeBinDirs: params.trustedSafeBinDirs,
242
313
  skillBins: params.skillBins,
243
314
  autoAllowSkills: params.autoAllowSkills,
244
315
  });
@@ -1,20 +1,8 @@
1
1
  import fs from "node:fs";
2
- import os from "node:os";
3
2
  import path from "node:path";
4
3
  import { splitShellArgs } from "../utils/shell-argv.js";
5
- export const DEFAULT_SAFE_BINS = ["jq", "grep", "cut", "sort", "uniq", "head", "tail", "tr", "wc"];
6
- function expandHome(value) {
7
- if (!value) {
8
- return value;
9
- }
10
- if (value === "~") {
11
- return os.homedir();
12
- }
13
- if (value.startsWith("~/")) {
14
- return path.join(os.homedir(), value.slice(2));
15
- }
16
- return value;
17
- }
4
+ import { expandHomePrefix } from "./home-dir.js";
5
+ export const DEFAULT_SAFE_BINS = ["jq", "cut", "uniq", "head", "tail", "tr", "wc"];
18
6
  function isExecutableFile(filePath) {
19
7
  try {
20
8
  const stat = fs.statSync(filePath);
@@ -47,7 +35,7 @@ function parseFirstToken(command) {
47
35
  return match ? match[0] : null;
48
36
  }
49
37
  function resolveExecutablePath(rawExecutable, cwd, env) {
50
- const expanded = rawExecutable.startsWith("~") ? expandHome(rawExecutable) : rawExecutable;
38
+ const expanded = rawExecutable.startsWith("~") ? expandHomePrefix(rawExecutable) : rawExecutable;
51
39
  if (expanded.includes("/") || expanded.includes("\\")) {
52
40
  if (path.isAbsolute(expanded)) {
53
41
  return isExecutableFile(expanded) ? expanded : undefined;
@@ -145,7 +133,7 @@ function matchesPattern(pattern, target) {
145
133
  if (!trimmed) {
146
134
  return false;
147
135
  }
148
- const expanded = trimmed.startsWith("~") ? expandHome(trimmed) : trimmed;
136
+ const expanded = trimmed.startsWith("~") ? expandHomePrefix(trimmed) : trimmed;
149
137
  const hasWildcard = /[*?]/.test(expanded);
150
138
  let normalizedPattern = expanded;
151
139
  let normalizedTarget = target;
@@ -169,7 +157,7 @@ export function resolveAllowlistCandidatePath(resolution, cwd) {
169
157
  if (!raw) {
170
158
  return undefined;
171
159
  }
172
- const expanded = raw.startsWith("~") ? expandHome(raw) : raw;
160
+ const expanded = raw.startsWith("~") ? expandHomePrefix(raw) : raw;
173
161
  if (!expanded.includes("/") && !expanded.includes("\\")) {
174
162
  return undefined;
175
163
  }
@@ -199,6 +187,45 @@ export function matchAllowlist(entries, resolution) {
199
187
  }
200
188
  return null;
201
189
  }
190
+ /**
191
+ * Tokenizes a single argv entry into a normalized option/positional model.
192
+ * Consumers can share this model to keep argv parsing behavior consistent.
193
+ */
194
+ export function parseExecArgvToken(raw) {
195
+ if (!raw) {
196
+ return { kind: "empty", raw };
197
+ }
198
+ if (raw === "--") {
199
+ return { kind: "terminator", raw };
200
+ }
201
+ if (raw === "-") {
202
+ return { kind: "stdin", raw };
203
+ }
204
+ if (!raw.startsWith("-")) {
205
+ return { kind: "positional", raw };
206
+ }
207
+ if (raw.startsWith("--")) {
208
+ const eqIndex = raw.indexOf("=");
209
+ if (eqIndex > 0) {
210
+ return {
211
+ kind: "option",
212
+ raw,
213
+ style: "long",
214
+ flag: raw.slice(0, eqIndex),
215
+ inlineValue: raw.slice(eqIndex + 1),
216
+ };
217
+ }
218
+ return { kind: "option", raw, style: "long", flag: raw };
219
+ }
220
+ const cluster = raw.slice(1);
221
+ return {
222
+ kind: "option",
223
+ raw,
224
+ style: "short-cluster",
225
+ cluster,
226
+ flags: cluster.split("").map((entry) => `-${entry}`),
227
+ };
228
+ }
202
229
  const DISALLOWED_PIPELINE_TOKENS = new Set([">", "<", "`", "\n", "\r", "(", ")"]);
203
230
  const DOUBLE_QUOTE_ESCAPES = new Set(["\\", '"', "$", "`", "\n", "\r"]);
204
231
  const WINDOWS_UNSUPPORTED_TOKENS = new Set([
@@ -242,7 +269,7 @@ function splitShellPipeline(command) {
242
269
  continue;
243
270
  }
244
271
  if (ch === quote) {
245
- return { delimiter, end: i + 1 };
272
+ return { delimiter, end: i + 1, quoted: true };
246
273
  }
247
274
  delimiter += ch;
248
275
  i += 1;
@@ -261,7 +288,7 @@ function splitShellPipeline(command) {
261
288
  if (!delimiter) {
262
289
  return null;
263
290
  }
264
- return { delimiter, end: i };
291
+ return { delimiter, end: i, quoted: false };
265
292
  };
266
293
  const segments = [];
267
294
  let buf = "";
@@ -279,6 +306,28 @@ function splitShellPipeline(command) {
279
306
  }
280
307
  buf = "";
281
308
  };
309
+ const isEscapedInHeredocLine = (line, index) => {
310
+ let slashes = 0;
311
+ for (let i = index - 1; i >= 0 && line[i] === "\\"; i -= 1) {
312
+ slashes += 1;
313
+ }
314
+ return slashes % 2 === 1;
315
+ };
316
+ const hasUnquotedHeredocExpansionToken = (line) => {
317
+ for (let i = 0; i < line.length; i += 1) {
318
+ const ch = line[i];
319
+ if (ch === "`" && !isEscapedInHeredocLine(line, i)) {
320
+ return true;
321
+ }
322
+ if (ch === "$" && !isEscapedInHeredocLine(line, i)) {
323
+ const next = line[i + 1];
324
+ if (next === "(" || next === "{") {
325
+ return true;
326
+ }
327
+ }
328
+ }
329
+ return false;
330
+ };
282
331
  for (let i = 0; i < command.length; i += 1) {
283
332
  const ch = command[i];
284
333
  const next = command[i + 1];
@@ -290,6 +339,9 @@ function splitShellPipeline(command) {
290
339
  if (line === current.delimiter) {
291
340
  pendingHeredocs.shift();
292
341
  }
342
+ else if (!current.quoted && hasUnquotedHeredocExpansionToken(heredocLine)) {
343
+ return { ok: false, reason: "command substitution in unquoted heredoc", segments: [] };
344
+ }
293
345
  }
294
346
  heredocLine = "";
295
347
  if (pendingHeredocs.length === 0) {
@@ -395,7 +447,7 @@ function splitShellPipeline(command) {
395
447
  }
396
448
  const parsed = parseHeredocDelimiter(command, scanIndex);
397
449
  if (parsed) {
398
- pendingHeredocs.push({ delimiter: parsed.delimiter, stripTabs });
450
+ pendingHeredocs.push({ delimiter: parsed.delimiter, stripTabs, quoted: parsed.quoted });
399
451
  buf += command.slice(scanIndex, parsed.end);
400
452
  i = parsed.end - 1;
401
453
  }
@@ -415,8 +467,14 @@ function splitShellPipeline(command) {
415
467
  const line = current.stripTabs ? heredocLine.replace(/^\t+/, "") : heredocLine;
416
468
  if (line === current.delimiter) {
417
469
  pendingHeredocs.shift();
470
+ if (pendingHeredocs.length === 0) {
471
+ inHeredocBody = false;
472
+ }
418
473
  }
419
474
  }
475
+ if (pendingHeredocs.length > 0 || inHeredocBody) {
476
+ return { ok: false, reason: "unterminated heredoc", segments: [] };
477
+ }
420
478
  if (escaped || inSingle || inDouble) {
421
479
  return { ok: false, reason: "unterminated shell quote/escape", segments: [] };
422
480
  }
@@ -1,8 +1,8 @@
1
1
  import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
- import os from "node:os";
4
3
  import path from "node:path";
5
4
  import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
5
+ import { expandHomePrefix } from "./home-dir.js";
6
6
  import { requestJsonlSocket } from "./jsonl-socket.js";
7
7
  export * from "./exec-approvals-analysis.js";
8
8
  export * from "./exec-approvals-allowlist.js";
@@ -20,23 +20,11 @@ function hashExecApprovalsRaw(raw) {
20
20
  .update(raw ?? "")
21
21
  .digest("hex");
22
22
  }
23
- function expandHome(value) {
24
- if (!value) {
25
- return value;
26
- }
27
- if (value === "~") {
28
- return os.homedir();
29
- }
30
- if (value.startsWith("~/")) {
31
- return path.join(os.homedir(), value.slice(2));
32
- }
33
- return value;
34
- }
35
23
  export function resolveExecApprovalsPath() {
36
- return expandHome(DEFAULT_FILE);
24
+ return expandHomePrefix(DEFAULT_FILE);
37
25
  }
38
26
  export function resolveExecApprovalsSocketPath() {
39
- return expandHome(DEFAULT_SOCKET);
27
+ return expandHomePrefix(DEFAULT_SOCKET);
40
28
  }
41
29
  function normalizeAllowlistPattern(value) {
42
30
  const trimmed = value?.trim() ?? "";
@@ -261,7 +249,7 @@ export function resolveExecApprovals(agentId, overrides) {
261
249
  agentId,
262
250
  overrides,
263
251
  path: resolveExecApprovalsPath(),
264
- socketPath: expandHome(file.socket?.path ?? resolveExecApprovalsSocketPath()),
252
+ socketPath: expandHomePrefix(file.socket?.path ?? resolveExecApprovalsSocketPath()),
265
253
  token: file.socket?.token ?? "",
266
254
  });
267
255
  }
@@ -293,7 +281,7 @@ export function resolveExecApprovalsFromFile(params) {
293
281
  ];
294
282
  return {
295
283
  path: params.path ?? resolveExecApprovalsPath(),
296
- socketPath: expandHome(params.socketPath ?? file.socket?.path ?? resolveExecApprovalsSocketPath()),
284
+ socketPath: expandHomePrefix(params.socketPath ?? file.socket?.path ?? resolveExecApprovalsSocketPath()),
297
285
  token: params.token ?? file.socket?.token ?? "",
298
286
  defaults: resolvedDefaults,
299
287
  agent: resolvedAgent,