mixdog 1.2.1 → 1.2.3

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 (557) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +19 -3
  4. package/scripts/model-catalog-audit.mjs +1 -15
  5. package/scripts/provider-pingpong-live.mjs +509 -0
  6. package/src/agents/advisor/AGENT.md +1 -1
  7. package/src/agents/advisor/agent.json +1 -1
  8. package/src/agents/reviewer/AGENT.md +3 -3
  9. package/src/agents/reviewer/agent.json +1 -1
  10. package/src/defaults/shipped-history.json +6 -0
  11. package/src/defaults/skills/setup/SKILL.md +6 -1
  12. package/src/defaults/skills/setup/references/actions.md +44 -22
  13. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  14. package/src/headless-exec.mjs +15 -8
  15. package/src/lib/keychain-cjs.cjs +7 -4
  16. package/src/output-styles/common.md +11 -10
  17. package/src/repl/slash-commands.mjs +16 -1
  18. package/src/rules/agent/AGENT.md +5 -5
  19. package/src/rules/lead/LEAD.md +5 -5
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
  21. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
  22. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  23. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  24. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  25. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  26. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  28. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  29. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
  30. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
  31. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
  32. package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
  33. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
  34. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
  35. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
  36. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
  37. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
  38. package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
  39. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
  40. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
  41. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
  42. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
  43. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  44. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
  45. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
  46. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
  47. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
  48. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
  49. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
  50. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
  51. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
  52. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  53. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
  54. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
  56. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
  58. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
  59. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
  60. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  62. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  63. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  65. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  66. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
  70. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
  71. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
  72. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
  73. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
  74. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
  75. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
  76. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
  77. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  79. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  80. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
  81. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  82. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
  83. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
  84. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
  85. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
  86. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
  87. package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
  88. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
  89. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
  90. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  91. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  92. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  93. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
  94. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  95. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
  96. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
  97. package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
  98. package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
  99. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  100. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
  102. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
  103. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
  104. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
  105. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
  106. package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
  107. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  109. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
  110. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
  113. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  114. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  115. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
  116. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  117. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  118. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  119. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  120. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
  121. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
  122. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  123. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
  124. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
  125. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  126. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  127. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
  128. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
  129. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
  138. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  140. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  141. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
  142. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
  143. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
  144. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  145. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
  147. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
  148. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
  150. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
  151. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
  153. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
  154. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
  155. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
  156. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
  157. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
  158. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
  159. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  160. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
  161. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  162. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  163. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
  164. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
  165. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
  166. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  167. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
  168. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
  169. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  170. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
  171. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
  172. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
  173. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
  174. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
  175. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  176. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
  177. package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
  178. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
  179. package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
  180. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  181. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
  182. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  183. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
  184. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
  185. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  186. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  187. package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
  188. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
  189. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
  190. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
  191. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
  192. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
  193. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
  194. package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
  195. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
  196. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
  197. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
  198. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
  199. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  200. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  201. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
  202. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
  203. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  204. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
  205. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
  206. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
  207. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
  208. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
  210. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
  211. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
  212. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
  213. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  214. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  215. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
  216. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  217. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  218. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  219. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
  220. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
  221. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  222. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
  223. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  224. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
  225. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  226. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
  227. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  228. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  229. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
  230. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  231. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
  232. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  233. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  234. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  235. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
  236. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
  237. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
  238. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
  239. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  240. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
  241. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  242. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  243. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
  244. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  245. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
  246. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
  248. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
  249. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
  250. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  251. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
  252. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  253. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  254. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  255. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  256. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
  257. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
  258. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
  259. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
  260. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  261. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
  262. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  263. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  264. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
  265. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
  266. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  267. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
  268. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  269. package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
  270. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
  271. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  272. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
  273. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
  274. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
  275. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  276. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
  277. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
  278. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
  279. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
  280. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  281. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
  282. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
  283. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
  284. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
  285. package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
  286. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
  287. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
  288. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  289. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  290. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  291. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
  292. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
  293. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  294. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  295. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  296. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
  297. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  298. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
  299. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
  300. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
  301. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  302. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  303. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  304. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  305. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  306. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  307. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  308. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  309. package/src/runtime/computer-bridge/action-schema.mjs +44 -21
  310. package/src/runtime/github/tool.mjs +92 -2
  311. package/src/runtime/memory/index.mjs +1 -0
  312. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  313. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  314. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  315. package/src/runtime/memory/lib/pg/process.mjs +65 -50
  316. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  317. package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
  318. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  319. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  320. package/src/runtime/office/README.md +2 -2
  321. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  322. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  323. package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
  324. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  325. package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
  326. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  327. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  328. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  329. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  330. package/src/runtime/office/core/office-sessions.mjs +5 -0
  331. package/src/runtime/office/core/office-transactions.mjs +3 -0
  332. package/src/runtime/office/core/office-write-ledger.mjs +98 -0
  333. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  334. package/src/runtime/office/index.mjs +30 -0
  335. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  336. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  337. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  338. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  339. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  340. package/src/runtime/office/shared/values.mjs +0 -5
  341. package/src/runtime/shared/background-tasks.mjs +92 -14
  342. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  343. package/src/runtime/shared/bounded-line-diff.mjs +182 -0
  344. package/src/runtime/shared/buffered-appender.mjs +18 -0
  345. package/src/runtime/shared/config.mjs +78 -18
  346. package/src/runtime/shared/err-text.mjs +31 -0
  347. package/src/runtime/shared/error-presentation.mjs +159 -19
  348. package/src/runtime/shared/file-permissions.d.mts +6 -1
  349. package/src/runtime/shared/file-permissions.mjs +54 -6
  350. package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
  351. package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
  352. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
  353. package/src/runtime/shared/llm/model-catalog.mjs +53 -40
  354. package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
  355. package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
  356. package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
  357. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  358. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  359. package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
  360. package/src/runtime/shared/loopback-listener.mjs +9 -0
  361. package/src/runtime/shared/model-display.mjs +13 -0
  362. package/src/runtime/shared/provider-api-key.mjs +2 -0
  363. package/src/runtime/shared/quota-resume-store.mjs +11 -0
  364. package/src/runtime/shared/review-diff.mjs +52 -0
  365. package/src/runtime/shared/session-baseline-store.mjs +960 -0
  366. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  367. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  368. package/src/runtime/shared/slow-span.mjs +114 -0
  369. package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
  370. package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
  371. package/src/runtime/shared/task-notification-envelope.mjs +2 -2
  372. package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
  373. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  374. package/src/runtime/shared/tool-card-model.mjs +5 -2
  375. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  376. package/src/runtime/shared/tool-primitives.mjs +13 -0
  377. package/src/runtime/shared/tool-result-summary.mjs +8 -1
  378. package/src/runtime/shared/tool-surface.mjs +18 -3
  379. package/src/runtime/shared/tool-work-units.mjs +40 -4
  380. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  381. package/src/runtime/shared/transcript-writer.mjs +10 -2
  382. package/src/runtime/shared/turn-changes.mjs +670 -274
  383. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  384. package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
  385. package/src/runtime/shared/turn-snapshot.mjs +986 -690
  386. package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
  387. package/src/runtime/shared/user-data-guard.mjs +262 -49
  388. package/src/runtime/shared/worktrees/carry.mjs +531 -0
  389. package/src/runtime/shared/worktrees/contract.mjs +34 -24
  390. package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
  391. package/src/runtime/shared/worktrees/git-head.mjs +205 -0
  392. package/src/runtime/shared/worktrees/git.mjs +8 -3
  393. package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
  394. package/src/runtime/shared/worktrees/manager.mjs +156 -8
  395. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  396. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  397. package/src/runtime/shared/worktrees/test-support.mjs +19 -4
  398. package/src/runtime/terminal-bridge/client.mjs +44 -11
  399. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  400. package/src/runtime/tidy/apply.mjs +47 -2
  401. package/src/runtime/tidy/run-engines.mjs +11 -5
  402. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  403. package/src/session-runtime/boot/apis.mjs +19 -5
  404. package/src/session-runtime/boot/facade.mjs +1 -0
  405. package/src/session-runtime/boot/infrastructure.mjs +12 -1
  406. package/src/session-runtime/boot/session.mjs +0 -1
  407. package/src/session-runtime/boot/tools.mjs +4 -1
  408. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  409. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
  410. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  411. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
  412. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
  413. package/src/session-runtime/internal-tool-executor.mjs +6 -2
  414. package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
  415. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  416. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
  417. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  418. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
  419. package/src/session-runtime/lifecycle/teardown.mjs +73 -8
  420. package/src/session-runtime/lifecycle-api.mjs +1 -0
  421. package/src/session-runtime/mcp-glue/connect.mjs +46 -14
  422. package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
  423. package/src/session-runtime/mcp-glue.mjs +3 -0
  424. package/src/session-runtime/mcp-oauth-login.mjs +174 -0
  425. package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
  426. package/src/session-runtime/model-route/set-route.mjs +85 -17
  427. package/src/session-runtime/model-route/web-search-route.mjs +1 -1
  428. package/src/session-runtime/native-web-search/routes.mjs +22 -3
  429. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  430. package/src/session-runtime/native-web-search.mjs +10 -1
  431. package/src/session-runtime/new-session-config.mjs +4 -2
  432. package/src/session-runtime/provider-auth/login.mjs +4 -0
  433. package/src/session-runtime/provider-models/model-meta.mjs +12 -3
  434. package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
  435. package/src/session-runtime/quick-web-search-models.mjs +13 -38
  436. package/src/session-runtime/resource-extension-sync.mjs +4 -0
  437. package/src/session-runtime/resource-mcp-api.mjs +98 -2
  438. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  439. package/src/session-runtime/runtime-review-api.mjs +21 -2
  440. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  441. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
  442. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
  443. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  444. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  445. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
  446. package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
  447. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
  448. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
  449. package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
  450. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
  451. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
  452. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  453. package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
  454. package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
  455. package/src/session-runtime/services/agent-tool.mjs +3 -0
  456. package/src/session-runtime/services/channel-admin.mjs +19 -3
  457. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  458. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  459. package/src/session-runtime/services/provider-admin.mjs +81 -15
  460. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  461. package/src/session-runtime/session-turn-api.mjs +14 -5
  462. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
  463. package/src/session-runtime/settings-compaction-api.mjs +1 -0
  464. package/src/session-runtime/setup-tool/executor.mjs +36 -6
  465. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  466. package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
  467. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
  468. package/src/session-runtime/skills-api.mjs +3 -5
  469. package/src/session-runtime/tool-surface.mjs +5 -1
  470. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  471. package/src/session-runtime/turn/session-ops.mjs +7 -5
  472. package/src/session-runtime/turn/side-question-ops.mjs +22 -0
  473. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
  474. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
  475. package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
  476. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  477. package/src/session-runtime/turn/turn-run.mjs +25 -9
  478. package/src/session-runtime/usage-stats-api.mjs +43 -11
  479. package/src/session-runtime/workspace/project-branches.mjs +7 -5
  480. package/src/session-runtime/workspace/transition-steps.mjs +129 -31
  481. package/src/session-runtime/workspace/transitions.mjs +190 -15
  482. package/src/standalone/daemon-agent-control.mjs +9 -1
  483. package/src/standalone/daemon-drain-policy.mjs +8 -0
  484. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  485. package/src/standalone/daemon-owner.mjs +17 -4
  486. package/src/standalone/daemon-pg-stop.mjs +51 -0
  487. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  488. package/src/standalone/daemon-stop-budget.mjs +18 -0
  489. package/src/standalone/daemon-stored-session-views.mjs +2 -0
  490. package/src/standalone/daemon-telemetry.mjs +74 -0
  491. package/src/standalone/daemon.mjs +64 -8
  492. package/src/standalone/desktop-service-registry.mjs +5 -0
  493. package/src/standalone/local-session-runtime.mjs +70 -19
  494. package/src/standalone/session-client.mjs +42 -0
  495. package/src/standalone/session-protocol.mjs +14 -0
  496. package/src/standalone/session-proxy/projection.mjs +41 -4
  497. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  498. package/src/standalone/session-runtime-inline-host.mjs +1 -0
  499. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
  500. package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
  501. package/src/standalone/session-service/agent-tree.mjs +12 -0
  502. package/src/standalone/session-service/quota-resume.mjs +8 -0
  503. package/src/standalone/session-service/retention/busy.mjs +15 -1
  504. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  505. package/src/standalone/session-service-api.mjs +11 -1
  506. package/src/standalone/session-service.mjs +1 -0
  507. package/src/standalone/session-state-patch.d.mts +2 -1
  508. package/src/standalone/session-state-patch.mjs +41 -1
  509. package/src/tui/App.jsx +25 -0
  510. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  511. package/src/tui/app/app-view.jsx +1 -0
  512. package/src/tui/app/btw-controller.mjs +118 -0
  513. package/src/tui/app/create-app-pickers.mjs +6 -0
  514. package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
  515. package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
  516. package/src/tui/app/extension-pickers.mjs +2 -1
  517. package/src/tui/app/model-options.mjs +11 -16
  518. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  519. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  520. package/src/tui/app/slash-commands.mjs +20 -5
  521. package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
  522. package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
  523. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  524. package/src/tui/app/use-global-key-input.mjs +5 -12
  525. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  526. package/src/tui/components/BtwPanel.jsx +53 -0
  527. package/src/tui/components/QuestionPanel.jsx +275 -0
  528. package/src/tui/components/StatusLine.jsx +2 -0
  529. package/src/tui/components/question-panel-model.mjs +156 -0
  530. package/src/tui/components/status-line/local-line.mjs +5 -2
  531. package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
  532. package/src/tui/dist/index.mjs +3221 -1500
  533. package/src/tui/session/context-state.mjs +4 -2
  534. package/src/tui/session/quota-resume.mjs +46 -14
  535. package/src/tui/session/session-api/commands.mjs +43 -24
  536. package/src/tui/session/session-api/controls.mjs +2 -2
  537. package/src/tui/session/session-api/extensions.mjs +22 -0
  538. package/src/tui/session/session-api/integrations.mjs +16 -2
  539. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  540. package/src/tui/session/session-api/lifecycle.mjs +7 -2
  541. package/src/tui/session/session-api/routes.mjs +71 -7
  542. package/src/tui/session/session-api/settings.mjs +11 -14
  543. package/src/tui/session/session-api.mjs +1 -0
  544. package/src/tui/session/session-flow/drain.mjs +7 -1
  545. package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
  546. package/src/tui/session/tool-approval.mjs +10 -7
  547. package/src/tui/session/transcript-spill.mjs +14 -7
  548. package/src/tui/session/turn-stream.mjs +174 -31
  549. package/src/tui/session/turn.mjs +46 -16
  550. package/src/tui/statusline-ansi-bridge.mjs +1 -1
  551. package/src/ui/statusline-agents.mjs +15 -4
  552. package/src/ui/statusline.mjs +7 -3
  553. package/src/ui/streaming-markdown-heal.mjs +34 -3
  554. package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
  555. package/src/workflows/default/WORKFLOW.md +3 -1
  556. package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
  557. package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
@@ -7,6 +7,7 @@ import {
7
7
  providerNativeToolPrefixCount,
8
8
  } from './provider-request-tools.mjs';
9
9
  import { MEASURED_TOOL_USAGE, ROUTE_TOOL_ORDER } from './tool-catalog-data.mjs';
10
+ import { nativeDeferredFamilyForRoute } from '../providers/wire-route.mjs';
10
11
 
11
12
  const toolSchemaBreakdownMemo = new WeakMap();
12
13
 
@@ -78,7 +79,7 @@ export function toolSchemaBucket(tool) {
78
79
  if (['shell', 'edit', 'apply_patch'].includes(name)) return 'mutation';
79
80
  if (name === 'agent' || name === 'delegate') return 'agents';
80
81
  if (name.includes('channel') || name.includes('webhook')) return 'channels';
81
- if (name.includes('provider') || name === 'load_tool' || name === 'tool_search' || name === 'cwd') return 'setup';
82
+ if (name.includes('provider') || name === 'load_tool' || name === 'tool_search' || name === 'session') return 'setup';
82
83
  if (kind === 'control') return 'control';
83
84
  return 'other';
84
85
  }
@@ -171,23 +172,25 @@ export function immutableToolForSurface(tool) {
171
172
  return frozen;
172
173
  }
173
174
 
174
- export function deferredProviderMode(provider) {
175
+ // `route` is the session's pinned wire route (session.wireRoute). The
176
+ // first-party Anthropic and OpenAI providers are native by name; a gateway or
177
+ // custom provider is native only on a route pinned with verified support
178
+ // (wire-route.mjs nativeDeferredFamilyForRoute), which is OFF everywhere today.
179
+ export function deferredProviderMode(provider, route = null) {
175
180
  const p = clean(provider).toLowerCase();
176
181
  if (p === 'gemini') return 'manifest';
177
- if (p === 'anthropic' || p === 'anthropic-oauth' || p === 'openai' || p === 'openai-oauth') {
178
- return 'native';
179
- }
182
+ if (nativeProviderFamily(p, route)) return 'native';
180
183
  // xAI/Grok and every other OpenAI-compatible backend have no native
181
184
  // tool_search/tool_search_output contract. Give them one complete canonical
182
185
  // function array instead of a load-driven array whose bytes churn.
183
186
  return 'canonical';
184
187
  }
185
188
 
186
- export function nativeProviderFamily(provider) {
189
+ export function nativeProviderFamily(provider, route = null) {
187
190
  const p = clean(provider).toLowerCase();
188
191
  if (p === 'openai' || p === 'openai-oauth') return 'openai';
189
192
  if (p === 'anthropic' || p === 'anthropic-oauth') return 'anthropic';
190
- return '';
193
+ return nativeDeferredFamilyForRoute(p, route);
191
194
  }
192
195
 
193
196
  export const ANTHROPIC_NATIVE_PROVIDERS = new Set(['anthropic', 'anthropic-oauth']);
@@ -3,10 +3,11 @@
3
3
  // application/selection logic. Pure module (session objects passed in).
4
4
  import { clean } from './session-text.mjs';
5
5
  import { mergePendingDeferredToolDelta } from './deferred-tool-delta.mjs';
6
- import { applyInitialDeferredToolManifestToBp2, stripDeferredToolManifestBlock } from '../context/collect.mjs';
6
+ import { applyInitialDeferredToolManifestToBp2 } from '../context/collect.mjs';
7
7
  import { getMcpServerInstructionsMap, getMcpTools, getMcpToolGeneration } from '../mcp/client.mjs';
8
8
  import { filterMcpToolsForSession } from './extension-scopes.mjs';
9
- import { isDeferredToolAvailable } from './deferred-tool-availability.mjs';
9
+ import { isDeferredToolAvailable, isToolPermittedBySessionPolicy } from './deferred-tool-availability.mjs';
10
+ import { routeToolExclusionReason } from '../session/loop/provider-tool-exclusions.mjs';
10
11
  import { isResponsesFreeformTool, toResponsesCustomTool } from '../providers/custom-tool-wire.mjs';
11
12
  import {
12
13
  DEFERRED_DEFAULT_FULL_TOOLS,
@@ -28,6 +29,17 @@ import {
28
29
  nativeProviderFamily,
29
30
  } from './tool-catalog-schema.mjs';
30
31
  import { filterModelEditTools } from '../../../shared/edit-tool-dialect.mjs';
32
+ import { describeBridgeTools, formatBridgeResult, isBridgeReadonlySession } from './tool-bridge.mjs';
33
+ import {
34
+ bridgeSurfaceOutdated,
35
+ isBridgeToolDefinition,
36
+ isToolBridgeEnabled,
37
+ sessionToolExposure,
38
+ TOOL_EXPOSURE_BRIDGE,
39
+ TOOL_EXPOSURE_NATIVE,
40
+ toolExposureModeForProvider,
41
+ } from './tool-exposure.mjs';
42
+ import { TOOL_BRIDGE_TOOLS } from './tool-defs.mjs';
31
43
  export {
32
44
  toolKind,
33
45
  toolSchemaBucket,
@@ -44,9 +56,30 @@ export {
44
56
  MEASURED_TOOL_USAGE,
45
57
  } from './tool-catalog-data.mjs';
46
58
 
47
- // Provider modes whose whole catalog is the active surface (no deferred pool).
59
+ // Provider modes without native tool search. Their bridge-v1 sessions
60
+ // (tool-exposure.mjs) get the native roster and late delta notices; only a
61
+ // surface not yet migrated to the bridge keeps the fixed full array, with no
62
+ // deferred-pool manifest and no late announcements.
48
63
  const FIXED_SURFACE_MODES = new Set(['full', 'manifest', 'canonical']);
49
64
 
65
+ function fixedSurfaceSession(session) {
66
+ return FIXED_SURFACE_MODES.has(session?.deferredProviderMode) && !isToolBridgeEnabled(session);
67
+ }
68
+
69
+ // Whether a bridge session's roster and delta notices may name `tool`: only
70
+ // what its own policy (allowlist, denied tools, read-only mode) lets it run.
71
+ // Native rosters are unchanged.
72
+ function rosterPermits(session, tool) {
73
+ if (!isToolBridgeEnabled(session)) return true;
74
+ if (!isToolPermittedBySessionPolicy(session, clean(tool?.name))) return false;
75
+ return !(isBridgeReadonlySession(session) && !isReadonlySelectable(tool));
76
+ }
77
+
78
+ // The bridge definitions every bridge session serializes: one frozen copy, so
79
+ // their bytes never vary across search, describe, call, skill loading or MCP
80
+ // connect/reconnect.
81
+ const BRIDGE_SURFACE_TOOLS = TOOL_BRIDGE_TOOLS.map((tool) => immutableToolForSurface(tool));
82
+
50
83
  function isMcpToolName(name) {
51
84
  return typeof name === 'string' && name.startsWith('mcp__');
52
85
  }
@@ -73,6 +106,30 @@ export function filterDisallowedTools(tools, disallowed = []) {
73
106
  return (tools || []).filter((tool) => !deny.has(clean(tool?.name)));
74
107
  }
75
108
 
109
+ /**
110
+ * Discovery's view of `tools` for one session: what its own policy (schema
111
+ * allowlist + denied tools) lets it execute. Nothing outside it is selected,
112
+ * registered as discovered, described or named in a result.
113
+ */
114
+ export function filterSessionToolPolicy(tools, session) {
115
+ return filterDisallowedTools(tools, session?.disallowedTools).filter((tool) =>
116
+ isToolPermittedBySessionPolicy(session, clean(tool?.name))
117
+ );
118
+ }
119
+
120
+ // Predicate over tool names: false for a tool the session's route leaves out
121
+ // of every request (see routeToolExclusionReason).
122
+ function sentOnRoute(session, catalog) {
123
+ const byName = new Map();
124
+ for (const tool of [...(catalog || []), ...(Array.isArray(session?.tools) ? session.tools : [])]) {
125
+ byName.set(clean(tool?.name), tool);
126
+ }
127
+ return (name) => !routeToolExclusionReason(session, byName.get(name));
128
+ }
129
+
130
+ const permittedNames = (session, names) =>
131
+ (names || []).filter((name) => isToolPermittedBySessionPolicy(session, name));
132
+
76
133
  export function sortedNamesByMeasuredUsage(names) {
77
134
  // Canonical route order first; measured usage orders the unrouted tail.
78
135
  return [...(names || [])].sort((a, b) => {
@@ -236,7 +293,7 @@ function setDeferredToolState(session, names) {
236
293
  }
237
294
 
238
295
  function deferredPoolToolNames(session) {
239
- if (!session || FIXED_SURFACE_MODES.has(session.deferredProviderMode)) return [];
296
+ if (!session || fixedSurfaceSession(session)) return [];
240
297
  const catalog = Array.isArray(session.deferredToolCatalog) ? session.deferredToolCatalog : [];
241
298
  const active = new Set([
242
299
  ...(session.tools || []).map((tool) => clean(tool?.name)).filter(Boolean),
@@ -245,7 +302,7 @@ function deferredPoolToolNames(session) {
245
302
  const out = [];
246
303
  for (const tool of catalog) {
247
304
  const name = clean(tool?.name);
248
- if (name && !active.has(name)) out.push(name);
305
+ if (name && !active.has(name) && rosterPermits(session, tool)) out.push(name);
249
306
  }
250
307
  return sortedNamesByMeasuredUsage(out);
251
308
  }
@@ -288,13 +345,37 @@ export function isReadonlySelectable(tool) {
288
345
 
289
346
  export function applyDeferredToolSurface(session, mode, extraTools = [], options = {}) {
290
347
  if (!session || !Array.isArray(session.tools)) return session;
291
- const providerMode = deferredProviderMode(options.provider || session.provider);
348
+ const provider = options.provider || session.provider;
349
+ // The pinned wire route decides a gateway's mode (it names its own
350
+ // provider, so a surface built for another provider ignores it).
351
+ const providerMode = deferredProviderMode(provider, session.wireRoute);
352
+ const exposure = toolExposureModeForProvider(provider, session.wireRoute);
353
+ const bridge = exposure === TOOL_EXPOSURE_BRIDGE;
354
+ // An existing surface built for another exposure is migrated, not merely
355
+ // re-selected: its fixed prompt guidance changes with it.
356
+ const previousExposure = sessionToolExposure(session);
357
+ // A surface an earlier bridge revision built (guidance-only prompt,
358
+ // search_tools) is rebuilt once, the same rewrite an exposure change makes.
359
+ const exposureChanged =
360
+ previousExposure !== null && (previousExposure !== exposure || (bridge && bridgeSurfaceOutdated(session)));
361
+ // The one native ↔ bridge transition, whoever triggers it (provider switch,
362
+ // resume, request boundary): leaving native keeps its discoveries aside,
363
+ // and the way back to native restores them below.
364
+ if (previousExposure === TOOL_EXPOSURE_NATIVE && bridge) {
365
+ session.nativeDeferredDiscovery = canonicalDeferredToolNames(
366
+ deferredCatalogUnion(session),
367
+ session.deferredDiscoveredTools || []
368
+ );
369
+ }
292
370
  const byName = new Map();
293
371
  // Rebuild from the full catalog, not just its eager projection. Current
294
- // definitions still take precedence over retained definitions.
372
+ // definitions still take precedence over retained definitions. Bridge
373
+ // definitions belong to the exposure, never to the catalog.
295
374
  const candidates = filterDisallowedTools(
296
375
  filterModelEditTools(
297
- [...session.tools, ...(extraTools || []), ...deferredCatalogUnion(session)],
376
+ [...session.tools, ...(extraTools || []), ...deferredCatalogUnion(session)].filter(
377
+ (tool) => !isBridgeToolDefinition(tool)
378
+ ),
298
379
  options.model || session.model
299
380
  ),
300
381
  [...(session.disallowedTools || []), ...(options.disallowed || [])]
@@ -308,15 +389,12 @@ export function applyDeferredToolSurface(session, mode, extraTools = [], options
308
389
  const defaultNames = defaultDeferredToolNames(catalog, mode);
309
390
  // Solo keeps `agent` in the deferred pool: loadable on request, never eager.
310
391
  if (session.orchestrationMode === 'none') defaultNames.delete('agent');
311
- const storedNames = providerMode === 'native' ? [] : storedDeferredToolNames(session);
312
- const fixedSurface = FIXED_SURFACE_MODES.has(providerMode);
313
- let selectedNames = fixedSurface
314
- ? sortedNamesByMeasuredUsage(catalog.map((tool) => clean(tool?.name)).filter(Boolean))
315
- : [];
316
- if (!fixedSurface) {
317
- selectedNames = storedNames.length ? canonicalDeferredToolNames(catalog, storedNames) : [];
318
- if (!selectedNames.length || providerMode === 'native') selectedNames = sortedNamesByMeasuredUsage(defaultNames);
319
- }
392
+ // Bridge sessions expose the mode's core only: a stored (legacy all-selected)
393
+ // selection never widens the wire surface, and load_tool is the bridge's own.
394
+ const storedNames = providerMode === 'native' || bridge ? [] : storedDeferredToolNames(session);
395
+ let selectedNames = storedNames.length ? canonicalDeferredToolNames(catalog, storedNames) : [];
396
+ if (!selectedNames.length || providerMode === 'native') selectedNames = sortedNamesByMeasuredUsage(defaultNames);
397
+ if (bridge) selectedNames = selectedNames.filter((name) => name !== 'load_tool');
320
398
  const selected = new Set(selectedNames);
321
399
  session.deferredToolCatalog = catalog;
322
400
  session.deferredToolUsage = MEASURED_TOOL_USAGE;
@@ -332,14 +410,29 @@ export function applyDeferredToolSurface(session, mode, extraTools = [], options
332
410
  session.tools.push(tool);
333
411
  active.push(clean(tool?.name));
334
412
  }
413
+ // Every other definition stays in the scoped catalog, reached through the
414
+ // bridge. A tool-free session (empty catalog) stays tool-free.
415
+ if (bridge && catalog.length) session.tools.push(...BRIDGE_SURFACE_TOOLS);
416
+ if (bridge) session.toolExposureMode = TOOL_EXPOSURE_BRIDGE;
417
+ else delete session.toolExposureMode;
335
418
  session.deferredCallableTools = sortedNamesByMeasuredUsage(active);
336
419
  if (providerMode === 'native') {
337
- const discovered = canonicalDeferredToolNames(catalog, session.deferredDiscoveredTools || []);
420
+ const restored = previousExposure === TOOL_EXPOSURE_BRIDGE ? session.nativeDeferredDiscovery || [] : [];
421
+ delete session.nativeDeferredDiscovery;
422
+ const discovered = canonicalDeferredToolNames(catalog, [...(session.deferredDiscoveredTools || []), ...restored]);
338
423
  session.deferredSelectedTools = active;
339
424
  session.deferredDiscoveredTools = discovered.filter((name) => !selected.has(name));
340
425
  } else {
341
426
  setDeferredToolState(session, active);
342
427
  }
428
+ if (exposureChanged && session.messages?.some((m) => m?.role === 'system')) {
429
+ // Replace the previous exposure's fixed block once: the native deferred
430
+ // manifest, or the bridge roster + guidance. History stays as is.
431
+ session.mcpServerInstructions = getMcpServerInstructionsMap(session.mcpScopeId);
432
+ applyInitialDeferredToolManifestToBp2(session, deferredPoolToolNames(session), { rebuild: true });
433
+ const rendered = renderedDeferredManifest(session);
434
+ session.deferredAnnouncedTools = deferredPoolToolNames(session).filter((name) => rendered.includes(name));
435
+ }
343
436
  if (!session.deferredToolBp2Applied && session.messages?.some((m) => m?.role === 'system')) {
344
437
  if (!session.mcpServerInstructions || typeof session.mcpServerInstructions !== 'object') {
345
438
  session.mcpServerInstructions = getMcpServerInstructionsMap(session.mcpScopeId);
@@ -358,41 +451,33 @@ export function applyDeferredToolSurface(session, mode, extraTools = [], options
358
451
 
359
452
  export function rebuildDeferredToolSurfaceForProvider(session, provider) {
360
453
  if (!session || !Array.isArray(session.tools)) return session;
361
- const previousMode = session.deferredProviderMode;
362
- const previousFamily = nativeProviderFamily(session.provider);
363
- const nextFamily = nativeProviderFamily(provider);
454
+ const previousFamily = nativeProviderFamily(session.provider, session.wireRoute);
455
+ const nextFamily = nativeProviderFamily(provider, session.wireRoute);
364
456
  const preserveNativeState = previousFamily && previousFamily === nextFamily;
365
457
  const discovered = preserveNativeState
366
458
  ? canonicalDeferredToolNames(deferredCatalogUnion(session), session.deferredDiscoveredTools || [])
367
459
  : [];
368
460
  const catalog = deferredCatalogUnion(session).slice();
369
- session.deferredDiscoveredTools = discovered;
461
+ const fromBridge = isToolBridgeEnabled(session);
462
+ // Another native family starts without this family's discoveries. Leaving
463
+ // native for the bridge keeps them: applyDeferredToolSurface sets them aside.
464
+ if (nextFamily) session.deferredDiscoveredTools = discovered;
465
+ // applyDeferredToolSurface replaces the fixed guidance when the exposure
466
+ // (native ↔ bridge) changes.
370
467
  applyDeferredToolSurface(session, session.deferredSurfaceMode || 'lead', catalog, { provider });
371
- if (session.deferredProviderMode === 'native' && discovered.length) {
372
- session.deferredDiscoveredTools = discovered;
468
+ // Back from the bridge: the discoveries applyDeferredToolSurface restored
469
+ // become callable again. Otherwise exactly the native family's own.
470
+ const eager = new Set(session.tools.map((tool) => clean(tool?.name)));
471
+ const kept = fromBridge
472
+ ? sortedNamesByMeasuredUsage((session.deferredDiscoveredTools || []).filter((name) => !eager.has(name)))
473
+ : discovered;
474
+ if (session.deferredProviderMode === 'native' && kept.length) {
475
+ session.deferredDiscoveredTools = kept;
373
476
  session.deferredCallableTools = sortedNamesByMeasuredUsage(
374
- new Set([...(session.deferredCallableTools || []), ...discovered])
477
+ new Set([...(session.deferredCallableTools || []), ...kept])
375
478
  );
376
479
  session.deferredSelectedTools = session.deferredCallableTools.slice();
377
480
  }
378
- if (previousMode && previousMode !== session.deferredProviderMode) {
379
- if (session.deferredProviderMode === 'native') {
380
- session.mcpServerInstructions = getMcpServerInstructionsMap(session.mcpScopeId);
381
- applyInitialDeferredToolManifestToBp2(session, deferredPoolToolNames(session), { rebuild: true });
382
- const rendered = renderedDeferredManifest(session);
383
- session.deferredAnnouncedTools = deferredPoolToolNames(session).filter((name) => rendered.includes(name));
384
- } else if (previousMode === 'native') {
385
- for (const system of session.messages?.filter((message) => message?.role === 'system') || []) {
386
- if (typeof system.content === 'string') system.content = stripDeferredToolManifestBlock(system.content);
387
- }
388
- session.messages = session.messages.filter(
389
- (message) => message?.role !== 'system' || String(message.content || '').trim()
390
- );
391
- session.deferredAnnouncedTools = [];
392
- session.deferredToolBp2Applied = true;
393
- delete session.deferredToolBp1Applied;
394
- }
395
- }
396
481
  return session;
397
482
  }
398
483
 
@@ -400,9 +485,9 @@ export function rebuildDeferredToolSurfaceForProvider(session, provider) {
400
485
  // An MCP server may finish its handshake BETWEEN session-create and the first
401
486
  // user send. Fold those LIVE MCP tools into the boot deferred catalog + the
402
487
  // provider-visible first-turn surface. Native providers rebuild the initial BP2
403
- // <available-deferred-tools> manifest IN PLACE and pre-mark names announced.
404
- // Manifest/canonical providers update their active fixed surface directly; the
405
- // canonical path never emits a deferred manifest or late reminder. Fully sync
488
+ // <available-deferred-tools> manifest IN PLACE and pre-mark names announced;
489
+ // bridge-v1 sessions do the same (roster + bridge guidance). Only a fixed
490
+ // surface not yet on the bridge updates its scoped catalog alone. Fully sync
406
491
  // and idempotent: no genuinely-new MCP name => no-op / no mutation.
407
492
  export function refreshInitialDeferredMcpSurface(session, liveMcpTools) {
408
493
  if (!session || !Array.isArray(session.messages)) return false;
@@ -422,15 +507,7 @@ export function refreshInitialDeferredMcpSurface(session, liveMcpTools) {
422
507
  }
423
508
  if (!added) return false;
424
509
  session.deferredToolCatalog = sortedCatalogByMeasuredUsage([...byName.values()]);
425
- if (session.deferredProviderMode === 'manifest' || session.deferredProviderMode === 'canonical') {
426
- const next = session.deferredToolCatalog.filter(
427
- (tool) => session.deferredSurfaceMode !== 'readonly' || isReadonlySelectable(tool)
428
- );
429
- session.tools.splice(0, session.tools.length, ...next);
430
- session.deferredCallableTools = next.map((tool) => clean(tool?.name)).filter(Boolean);
431
- if (session.deferredProviderMode === 'canonical') {
432
- setDeferredToolState(session, session.deferredCallableTools);
433
- }
510
+ if (fixedSurfaceSession(session)) {
434
511
  session.updatedAt = Date.now();
435
512
  return true;
436
513
  }
@@ -497,6 +574,7 @@ function reconcileStateOf(session, liveMcpTools) {
497
574
  cwd: clean(session.cwd),
498
575
  mode: clean(session.deferredSurfaceMode),
499
576
  providerMode: clean(session.deferredProviderMode),
577
+ exposure: clean(session.toolExposureMode),
500
578
  provider: clean(session.provider),
501
579
  model: clean(session.model),
502
580
  disallowed: JSON.stringify(session.disallowedTools || []),
@@ -525,7 +603,7 @@ function reconcileDeferredMcpToolCatalogUncached(session, liveMcpTools) {
525
603
  .filter(isMcpToolName)
526
604
  );
527
605
  session.deferredMcpToolNames = [...new Set(live.map((tool) => clean(tool?.name)).filter(isMcpToolName))];
528
- if (FIXED_SURFACE_MODES.has(session.deferredProviderMode)) {
606
+ if (fixedSurfaceSession(session)) {
529
607
  const byName = new Map();
530
608
  for (const tool of Array.isArray(session.deferredToolCatalog) ? session.deferredToolCatalog : []) {
531
609
  const name = clean(tool?.name);
@@ -535,17 +613,23 @@ function reconcileDeferredMcpToolCatalogUncached(session, liveMcpTools) {
535
613
  const name = clean(tool?.name);
536
614
  if (name && isMcpToolName(name)) byName.set(name, liveToolClone(tool));
537
615
  }
616
+ // A fixed surface not yet on the bridge: connect, reconnect and removal
617
+ // update the scoped catalog only (availability follows
618
+ // deferredMcpToolNames); nothing is announced.
538
619
  const catalog = sortedCatalogByMeasuredUsage([...byName.values()]);
539
- const next = catalog.filter((tool) => session.deferredSurfaceMode !== 'readonly' || isReadonlySelectable(tool));
540
- const before = JSON.stringify((session.tools || []).map((tool) => activeToolForSurface(tool)));
541
- const after = JSON.stringify(next);
620
+ const previous = Array.isArray(session.deferredToolCatalog) ? session.deferredToolCatalog : [];
542
621
  session.deferredToolCatalog = catalog;
543
- session.tools.splice(0, session.tools.length, ...next);
544
- session.deferredCallableTools = next.map((tool) => clean(tool?.name)).filter(Boolean);
545
- if (before !== after) session.updatedAt = Date.now();
546
- return before === after ? null : session.deferredCallableTools;
622
+ if (previous.length !== catalog.length || previous.some((tool, index) => tool !== catalog[index])) {
623
+ session.updatedAt = Date.now();
624
+ }
625
+ return null;
547
626
  }
548
627
  const lateCatalog = Array.isArray(session.deferredLateToolCatalog) ? session.deferredLateToolCatalog : [];
628
+ // A bridge session judges a removal by the definition it had before this
629
+ // reconciliation (a disconnected late tool leaves the late pool below).
630
+ const knownBefore = isToolBridgeEnabled(session)
631
+ ? new Map(deferredCatalogUnion(session).map((tool) => [clean(tool?.name), tool]))
632
+ : null;
549
633
  const active = new Set([
550
634
  ...(session.tools || []).map((tool) => clean(tool?.name)).filter(Boolean),
551
635
  ...parseToolSelection(session.deferredCallableTools),
@@ -594,11 +678,13 @@ function reconcileDeferredMcpToolCatalogUncached(session, liveMcpTools) {
594
678
  const name = clean(tool?.name);
595
679
  if (!name || !isMcpToolName(name)) continue;
596
680
  if (previousNames.has(name) || (!hadSnapshot && (active.has(name) || startupNames.has(name)))) continue;
681
+ if (!rosterPermits(session, tool)) continue;
597
682
  added.push({ name, description: lateAnnouncementDescription(tool?.description) });
598
683
  }
599
684
  const removed = [];
600
685
  for (const name of previousNames) {
601
686
  if (nextNames.has(name)) continue;
687
+ if (knownBefore && !rosterPermits(session, knownBefore.get(name) || { name })) continue;
602
688
  removed.push(name);
603
689
  }
604
690
  if (!added.length && !removed.length) return null;
@@ -625,6 +711,9 @@ export function selectDeferredTools(session, names, mode, { exact = false } = {}
625
711
  const active = new Set([...surfaceActive, ...parseToolSelection(session?.deferredCallableTools)]);
626
712
  const native = session?.deferredProviderMode === 'native' || session?.deferredNativeTools === true;
627
713
  const discovered = new Set(Array.isArray(session?.deferredDiscoveredTools) ? session.deferredDiscoveredTools : []);
714
+ // Bridge sessions keep a fixed surface: deferred tools are described and
715
+ // run through the bridge, never appended to session.tools.
716
+ const bridge = isToolBridgeEnabled(session);
628
717
  const activateOnSurface = !native;
629
718
  const byName = new Map();
630
719
  for (const tool of catalog) {
@@ -645,11 +734,18 @@ export function selectDeferredTools(session, names, mode, { exact = false } = {}
645
734
  missing.push(requestedName);
646
735
  continue;
647
736
  }
737
+ // A tool this route never sends (schema rejected) is not loaded and not
738
+ // listed as active; the reason says why.
739
+ const routeExclusion = bridge ? null : routeToolExclusionReason(session, tool);
740
+ if (routeExclusion) {
741
+ blocked.push({ name, reason: routeExclusion });
742
+ continue;
743
+ }
648
744
  if (mode === 'readonly' && !isReadonlySelectable(tool)) {
649
745
  blocked.push({ name, reason: 'readonly mode' });
650
746
  continue;
651
747
  }
652
- if (active.has(name) || (!activateOnSurface && discovered.has(name))) {
748
+ if (bridge || active.has(name) || (!activateOnSurface && discovered.has(name))) {
653
749
  already.push(name);
654
750
  continue;
655
751
  }
@@ -663,6 +759,7 @@ export function selectDeferredTools(session, names, mode, { exact = false } = {}
663
759
  }
664
760
  added.push(name);
665
761
  }
762
+ if (bridge) return { added, already, blocked, missing, native };
666
763
  if (native) {
667
764
  session.deferredCallableTools = sortedNamesByMeasuredUsage(active);
668
765
  session.deferredDiscoveredTools = sortedNamesByMeasuredUsage([...discovered]);
@@ -697,11 +794,13 @@ function pendingAndFailedMcpServers(mcpStatus) {
697
794
  return { pending: [...new Set(pending)].sort(), failed: [...new Set(failed)].sort() };
698
795
  }
699
796
 
700
- /** The deferred catalog union, or the session's own allowed tools when nothing is deferred. */
797
+ /**
798
+ * The deferred catalog union, or the session's own tools when nothing is
799
+ * deferred — either way only what the session's policy lets it execute.
800
+ */
701
801
  function resolvableCatalog(session) {
702
802
  const union = deferredCatalogUnion(session);
703
- if (union.length) return union;
704
- return filterDisallowedTools(Array.isArray(session?.tools) ? session.tools : [], session?.disallowedTools);
803
+ return filterSessionToolPolicy(union.length ? union : Array.isArray(session?.tools) ? session.tools : [], session);
705
804
  }
706
805
 
707
806
  // Pure loader. Input is exact deferred-tool names/aliases; output reports
@@ -709,6 +808,8 @@ function resolvableCatalog(session) {
709
808
  // servers. No listing, no ranking, no substring filter. `options.mcpStatus` is
710
809
  // the runtime getter for per-server status.
711
810
  export function renderToolSearch(args = {}, session, mode = 'full', options = {}) {
811
+ // Bridge mode: load_tool describes (bounded, paged) and never loads.
812
+ if (isToolBridgeEnabled(session)) return formatBridgeResult(describeBridgeTools(session, args, { mode }));
712
813
  const catalog = resolvableCatalog(session);
713
814
  const requestedNames = parseToolSelection(args.names);
714
815
  const { pending: pendingMcpServers, failed: failedMcpServers } = pendingAndFailedMcpServers(options?.mcpStatus);
@@ -729,9 +830,11 @@ export function renderToolSearch(args = {}, session, mode = 'full', options = {}
729
830
  missing: [],
730
831
  ...mcpFields,
731
832
  activeTools: sortedNamesByMeasuredUsage(
732
- (session?.tools || []).map((tool) => clean(tool?.name)).filter(Boolean)
833
+ permittedNames(session, (session?.tools || []).map((tool) => clean(tool?.name)).filter(Boolean)).filter(
834
+ sentOnRoute(session, catalog)
835
+ )
733
836
  ),
734
- discoveredTools: sortedNamesByMeasuredUsage(session?.deferredDiscoveredTools || []),
837
+ discoveredTools: sortedNamesByMeasuredUsage(permittedNames(session, session?.deferredDiscoveredTools)),
735
838
  },
736
839
  null,
737
840
  2
@@ -789,9 +892,11 @@ export function renderToolSearch(args = {}, session, mode = 'full', options = {}
789
892
  ...(blocked.length ? { blocked } : {}),
790
893
  ...mcpFields,
791
894
  activeTools: sortedNamesByMeasuredUsage(
792
- [...nextActiveNames].filter((name) => isDeferredToolAvailable(session, name))
895
+ permittedNames(session, [...nextActiveNames])
896
+ .filter((name) => isDeferredToolAvailable(session, name))
897
+ .filter(sentOnRoute(session, catalog))
793
898
  ),
794
- discoveredTools: sortedNamesByMeasuredUsage(session?.deferredDiscoveredTools || []),
899
+ discoveredTools: sortedNamesByMeasuredUsage(permittedNames(session, session?.deferredDiscoveredTools)),
795
900
  ...(notes.length ? { note: notes.join(' ') } : {}),
796
901
  },
797
902
  null,
@@ -2,6 +2,10 @@
2
2
  // Pure, self-contained schemas + the agent-hidden default helper; no runtime
3
3
  // closure dependencies.
4
4
 
5
+ // One load_tool for every session, native and bridge, byte for byte: native
6
+ // sessions register the named tools; bridge sessions (see tool-bridge.mjs)
7
+ // get their definitions back and run them through call_tool. Native request
8
+ // bytes must never change, so the bridge adds nothing to this definition.
5
9
  export const TOOL_SEARCH_TOOL = {
6
10
  name: 'load_tool',
7
11
  title: 'load_tool',
@@ -27,34 +31,80 @@ export const TOOL_SEARCH_TOOL = {
27
31
  },
28
32
  };
29
33
 
30
- export const CWD_TOOL = {
31
- name: 'cwd',
32
- title: 'Project',
34
+ // Fixed tool bridge for non-native providers (see tool-bridge.mjs). The
35
+ // description is static so the definition stays byte-stable: it never carries
36
+ // catalog names, counts or listings.
37
+ export const CALL_TOOL_TOOL = {
38
+ name: 'call_tool',
39
+ title: 'call_tool',
33
40
  annotations: {
34
- title: 'Project',
41
+ title: 'call_tool',
42
+ readOnlyHint: false,
43
+ destructiveHint: true,
44
+ idempotentHint: false,
45
+ openWorldHint: true,
46
+ agentHidden: true,
47
+ },
48
+ description:
49
+ 'Run one tool that is available in this session but not directly exposed, with the arguments its schema requires. The call has the same permissions, approvals and result as calling that tool directly.',
50
+ inputSchema: {
51
+ type: 'object',
52
+ properties: {
53
+ name: { type: 'string', minLength: 1, maxLength: 256, description: 'Exact tool name.' },
54
+ arguments: { type: 'object', description: 'Arguments for that tool.' },
55
+ },
56
+ required: ['name', 'arguments'],
57
+ additionalProperties: false,
58
+ },
59
+ };
60
+
61
+ // The fixed bridge for non-native providers: the shared load_tool plus call_tool.
62
+ export const TOOL_BRIDGE_TOOLS = Object.freeze([TOOL_SEARCH_TOOL, CALL_TOOL_TOOL]);
63
+
64
+ export const SESSION_TOOL = {
65
+ name: 'session',
66
+ title: 'Session',
67
+ annotations: {
68
+ title: 'Session',
35
69
  readOnlyHint: false,
36
70
  destructiveHint: false,
37
71
  idempotentHint: false,
38
72
  openWorldHint: false,
39
73
  agentHidden: true,
40
74
  },
41
- trigger: 'Show or switch the active Project; not a shell-local cd.',
75
+ trigger: 'Session status, rename the title, compact, fork into a new session, switch Project, worktrees.',
42
76
  description:
43
- 'Show or switch the active Project. list returns the registered projects (name, path); a project name instead of a path → list first, then set the matching path, ask only if several match. path must be an existing directory. A shell-local cd does not change the Project. merge-worktree / remove-worktree act on this session’s git worktree only when the user explicitly asks.',
77
+ 'Manage the current session. status shows session id, title, Project and model; rename sets the session title; compact runs after this turn ends; fork copies this conversation into a new session. set-project switches the active Project; list-projects returns the registered projects (name, path); a project name instead of a path → list-projects first, then set-project with the matching path, ask only if several match. path must be an existing directory. A shell-local cd does not change the Project. Worktree actions act on this session’s git worktree only when the user explicitly asks.',
44
78
  inputSchema: {
45
79
  type: 'object',
46
80
  properties: {
47
81
  action: {
48
82
  type: 'string',
49
- enum: ['get', 'set', 'list', 'merge-worktree', 'remove-worktree', 'list-worktrees', 'prune-worktrees'],
83
+ enum: [
84
+ 'status',
85
+ 'rename',
86
+ 'compact',
87
+ 'fork',
88
+ 'set-project',
89
+ 'list-projects',
90
+ 'favorite',
91
+ 'archive',
92
+ 'merge-worktree',
93
+ 'remove-worktree',
94
+ 'list-worktrees',
95
+ 'prune-worktrees',
96
+ ],
50
97
  description:
51
- 'get shows the active Project (default without path), set switches to path, list returns registered projects; merge-worktree merges this session’s worktree into the project folder’s checked-out branch, remove-worktree deletes it (returning to the project folder; call again if it reports WORKTREE_REMOVAL_INCOMPLETE); list-worktrees lists every managed worktree and who retains it; prune-worktrees removes clean, merged ones no session retains.',
98
+ 'status (default without path) shows the session; rename sets title; compact schedules a compaction right after this turn; fork creates a new session copying this conversation (returns its sessionId; this session stays current); set-project switches to path; list-projects returns registered projects; favorite/archive set this session’s sidebar flag to value; merge-worktree merges this session’s worktree into the project folder’s checked-out branch, remove-worktree deletes it (returning to the project folder; call again if it reports WORKTREE_REMOVAL_INCOMPLETE); list-worktrees lists every managed worktree and who retains it; prune-worktrees removes clean, merged ones no session retains.',
52
99
  },
53
- path: { type: 'string', description: 'Existing directory to switch to (implies action=set).' },
100
+ title: { type: 'string', description: 'rename: the new session title.' },
101
+ path: { type: 'string', description: 'Existing directory to switch to (implies action=set-project).' },
102
+ compact: { type: 'boolean', description: 'fork: compact the copied conversation.' },
54
103
  force: {
55
104
  type: 'boolean',
56
105
  description: 'remove-worktree: delete even with uncommitted or unmerged work (only when the user says so).',
57
106
  },
107
+ value: { type: 'boolean', description: 'favorite/archive: on or off.' },
58
108
  },
59
109
  additionalProperties: false,
60
110
  },
@@ -121,6 +171,7 @@ export function collectStandaloneToolDefs({
121
171
  tidyToolDefs = [],
122
172
  visualizeToolDefs = [],
123
173
  setupToolDefs = [],
174
+ askUserToolDefs = [],
124
175
  goalTools = [],
125
176
  agentTools = [],
126
177
  skillToolEnabled = true,
@@ -129,7 +180,7 @@ export function collectStandaloneToolDefs({
129
180
  const standaloneTools = [
130
181
  TOOL_SEARCH_TOOL,
131
182
  ...(skillToolEnabled ? [SKILL_TOOL] : []),
132
- CWD_TOOL,
183
+ SESSION_TOOL,
133
184
  ...webSearchRuntimeTools.filter((tool) => tool?.public !== false),
134
185
  ...admitted(memoryToolDefs?.TOOL_DEFS, MEMORY_RUNTIME_TOOLS),
135
186
  ...admitted(codeGraphToolDefs?.CODE_GRAPH_TOOL_DEFS, CODE_GRAPH_RUNTIME_TOOLS),
@@ -141,6 +192,7 @@ export function collectStandaloneToolDefs({
141
192
  ...admitted(tidyToolDefs, TIDY_RUNTIME_TOOLS),
142
193
  ...admitted(visualizeToolDefs, VISUALIZE_RUNTIME_TOOLS),
143
194
  ...setupToolDefs,
195
+ ...askUserToolDefs,
144
196
  ...goalTools,
145
197
  ...agentTools,
146
198
  ];