mixdog 1.2.2 → 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 (415) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/provider-pingpong-live.mjs +509 -0
  4. package/src/agents/advisor/AGENT.md +1 -1
  5. package/src/agents/advisor/agent.json +1 -1
  6. package/src/defaults/shipped-history.json +5 -0
  7. package/src/defaults/skills/setup/SKILL.md +6 -1
  8. package/src/defaults/skills/setup/references/actions.md +44 -22
  9. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  10. package/src/headless-exec.mjs +15 -8
  11. package/src/lib/keychain-cjs.cjs +7 -4
  12. package/src/output-styles/common.md +11 -10
  13. package/src/rules/agent/AGENT.md +5 -5
  14. package/src/rules/lead/LEAD.md +5 -5
  15. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  16. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  17. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  18. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  19. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  20. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  21. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  22. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  23. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
  24. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  25. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
  26. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
  28. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  30. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  31. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  32. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  35. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  36. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  37. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
  38. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
  39. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  40. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
  41. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
  42. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
  43. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
  45. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  46. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
  47. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
  49. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
  50. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
  51. package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
  52. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
  53. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
  54. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  55. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  56. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  57. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
  58. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  59. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
  60. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
  61. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  62. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
  63. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
  64. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  65. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
  66. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
  67. package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
  68. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  71. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  72. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
  73. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  74. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  75. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
  76. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  77. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  78. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  79. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  80. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
  81. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
  82. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  83. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  84. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  85. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
  86. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  88. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
  89. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  90. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  91. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
  92. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  93. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
  103. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  104. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  108. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
  109. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  110. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  111. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
  112. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  113. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  114. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  115. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  117. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  119. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  121. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
  122. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  123. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
  124. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
  125. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  126. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
  127. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  129. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  130. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
  131. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
  132. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
  133. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
  134. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
  135. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
  136. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
  137. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  138. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  139. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
  140. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
  141. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  142. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  147. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  148. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  150. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  151. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  152. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
  154. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  155. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
  156. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  157. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
  158. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  159. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
  160. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  161. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  162. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
  163. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  164. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
  165. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  167. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  168. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
  169. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
  170. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
  171. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
  172. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
  173. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
  174. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  175. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
  179. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
  180. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
  181. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  184. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  187. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
  188. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
  189. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
  190. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
  192. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  193. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  194. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
  195. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  196. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
  197. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  198. package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
  199. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
  200. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  201. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
  203. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  204. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
  205. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
  206. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  207. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  208. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  209. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  210. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
  211. package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
  212. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
  213. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  215. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  216. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  217. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
  218. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  221. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
  223. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  224. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  225. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  226. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  227. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  228. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  229. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  230. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  231. package/src/runtime/computer-bridge/action-schema.mjs +44 -21
  232. package/src/runtime/github/tool.mjs +92 -2
  233. package/src/runtime/memory/index.mjs +1 -0
  234. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  235. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  236. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  237. package/src/runtime/memory/lib/pg/process.mjs +31 -26
  238. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  239. package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
  240. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  241. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  242. package/src/runtime/office/README.md +1 -1
  243. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  244. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  245. package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
  246. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  247. package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
  248. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  249. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  250. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  251. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  252. package/src/runtime/office/core/office-sessions.mjs +5 -0
  253. package/src/runtime/office/core/office-transactions.mjs +3 -0
  254. package/src/runtime/office/core/office-write-ledger.mjs +98 -0
  255. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  256. package/src/runtime/office/index.mjs +30 -0
  257. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  258. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  259. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  260. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  261. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  262. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  263. package/src/runtime/shared/bounded-line-diff.mjs +182 -0
  264. package/src/runtime/shared/buffered-appender.mjs +18 -0
  265. package/src/runtime/shared/config.mjs +78 -18
  266. package/src/runtime/shared/err-text.mjs +6 -0
  267. package/src/runtime/shared/file-permissions.d.mts +6 -1
  268. package/src/runtime/shared/file-permissions.mjs +54 -6
  269. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  270. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  271. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  272. package/src/runtime/shared/loopback-listener.mjs +9 -0
  273. package/src/runtime/shared/provider-api-key.mjs +2 -0
  274. package/src/runtime/shared/review-diff.mjs +52 -0
  275. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  276. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  277. package/src/runtime/shared/slow-span.mjs +114 -0
  278. package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
  279. package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
  280. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  281. package/src/runtime/shared/tool-card-model.mjs +5 -2
  282. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  283. package/src/runtime/shared/tool-primitives.mjs +13 -0
  284. package/src/runtime/shared/tool-result-summary.mjs +8 -1
  285. package/src/runtime/shared/tool-surface.mjs +18 -3
  286. package/src/runtime/shared/tool-work-units.mjs +40 -4
  287. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  288. package/src/runtime/shared/transcript-writer.mjs +10 -2
  289. package/src/runtime/shared/turn-changes.mjs +268 -100
  290. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  291. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  292. package/src/runtime/shared/turn-snapshot.mjs +857 -683
  293. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  294. package/src/runtime/shared/user-data-guard.mjs +262 -49
  295. package/src/runtime/shared/worktrees/carry.mjs +531 -0
  296. package/src/runtime/shared/worktrees/contract.mjs +34 -0
  297. package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
  298. package/src/runtime/shared/worktrees/git-head.mjs +205 -0
  299. package/src/runtime/shared/worktrees/git.mjs +8 -3
  300. package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
  301. package/src/runtime/shared/worktrees/manager.mjs +156 -8
  302. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  303. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  304. package/src/runtime/terminal-bridge/client.mjs +44 -11
  305. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  306. package/src/runtime/tidy/apply.mjs +47 -2
  307. package/src/runtime/tidy/run-engines.mjs +11 -5
  308. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  309. package/src/session-runtime/boot/apis.mjs +13 -5
  310. package/src/session-runtime/boot/facade.mjs +1 -0
  311. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  312. package/src/session-runtime/boot/session.mjs +0 -1
  313. package/src/session-runtime/boot/tools.mjs +4 -1
  314. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  315. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
  316. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  317. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
  318. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
  319. package/src/session-runtime/internal-tool-executor.mjs +6 -2
  320. package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
  321. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  322. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
  323. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  324. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
  325. package/src/session-runtime/lifecycle/teardown.mjs +72 -7
  326. package/src/session-runtime/lifecycle-api.mjs +1 -0
  327. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  328. package/src/session-runtime/model-route/set-route.mjs +2 -2
  329. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  330. package/src/session-runtime/native-web-search.mjs +10 -1
  331. package/src/session-runtime/new-session-config.mjs +4 -2
  332. package/src/session-runtime/provider-auth/login.mjs +4 -0
  333. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  334. package/src/session-runtime/runtime-review-api.mjs +8 -2
  335. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  336. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  337. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  338. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
  339. package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
  340. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  341. package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
  342. package/src/session-runtime/services/agent-tool.mjs +3 -0
  343. package/src/session-runtime/services/channel-admin.mjs +19 -3
  344. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  345. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  346. package/src/session-runtime/services/provider-admin.mjs +81 -15
  347. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  348. package/src/session-runtime/session-turn-api.mjs +14 -5
  349. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
  350. package/src/session-runtime/setup-tool/executor.mjs +36 -6
  351. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  352. package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
  353. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
  354. package/src/session-runtime/skills-api.mjs +3 -5
  355. package/src/session-runtime/tool-surface.mjs +5 -1
  356. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  357. package/src/session-runtime/turn/session-ops.mjs +7 -5
  358. package/src/session-runtime/turn/side-question-ops.mjs +22 -0
  359. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
  360. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
  361. package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
  362. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  363. package/src/session-runtime/turn/turn-run.mjs +25 -9
  364. package/src/session-runtime/usage-stats-api.mjs +43 -11
  365. package/src/session-runtime/workspace/project-branches.mjs +7 -5
  366. package/src/session-runtime/workspace/transition-steps.mjs +129 -31
  367. package/src/session-runtime/workspace/transitions.mjs +190 -15
  368. package/src/standalone/daemon-agent-control.mjs +9 -1
  369. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  370. package/src/standalone/daemon-owner.mjs +17 -4
  371. package/src/standalone/daemon-pg-stop.mjs +51 -0
  372. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  373. package/src/standalone/daemon-stop-budget.mjs +18 -0
  374. package/src/standalone/daemon-stored-session-views.mjs +2 -0
  375. package/src/standalone/daemon-telemetry.mjs +19 -0
  376. package/src/standalone/daemon.mjs +61 -1
  377. package/src/standalone/desktop-service-registry.mjs +5 -0
  378. package/src/standalone/local-session-runtime.mjs +70 -19
  379. package/src/standalone/session-client.mjs +42 -0
  380. package/src/standalone/session-protocol.mjs +7 -0
  381. package/src/standalone/session-proxy/projection.mjs +41 -4
  382. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  383. package/src/standalone/session-runtime-inline-host.mjs +1 -0
  384. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  385. package/src/standalone/session-service-api.mjs +6 -1
  386. package/src/standalone/session-state-patch.d.mts +2 -1
  387. package/src/standalone/session-state-patch.mjs +41 -1
  388. package/src/tui/App.jsx +25 -0
  389. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  390. package/src/tui/app/btw-controller.mjs +118 -0
  391. package/src/tui/app/create-app-pickers.mjs +2 -0
  392. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  393. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  394. package/src/tui/app/slash-commands.mjs +13 -3
  395. package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
  396. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  397. package/src/tui/app/use-global-key-input.mjs +5 -12
  398. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  399. package/src/tui/components/BtwPanel.jsx +53 -0
  400. package/src/tui/components/QuestionPanel.jsx +275 -0
  401. package/src/tui/components/question-panel-model.mjs +156 -0
  402. package/src/tui/dist/index.mjs +2413 -1465
  403. package/src/tui/session/context-state.mjs +4 -2
  404. package/src/tui/session/session-api/commands.mjs +10 -0
  405. package/src/tui/session/session-api/controls.mjs +2 -2
  406. package/src/tui/session/session-api/integrations.mjs +9 -2
  407. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  408. package/src/tui/session/session-api/lifecycle.mjs +2 -1
  409. package/src/tui/session/session-api/settings.mjs +6 -0
  410. package/src/tui/session/session-api.mjs +1 -0
  411. package/src/tui/session/tool-approval.mjs +10 -7
  412. package/src/tui/session/transcript-spill.mjs +14 -7
  413. package/src/tui/session/turn-stream.mjs +174 -31
  414. package/src/tui/session/turn.mjs +12 -5
  415. package/src/workflows/default/WORKFLOW.md +3 -1
@@ -35,13 +35,19 @@ function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts
35
35
  });
36
36
  }
37
37
 
38
- function dispatchInternal(name, args, { cwd, callerSessionId, sessionRef, executeOpts, notifyFn, toolApprovalHook }) {
38
+ function dispatchInternal(
39
+ name,
40
+ args,
41
+ { cwd, callerSessionId, sessionRef, executeOpts, notifyFn, toolApprovalHook, elevationApproved }
42
+ ) {
39
43
  // callerSessionId propagates into server.mjs dispatchTool so that
40
44
  // dispatchAiWrapped can detect and reject recursive calls from a
41
45
  // hidden-role session (recall/search → self).
42
46
  return executeInternalTool(name, args, {
43
47
  scopeId: sessionRef?.mcpScopeId || null,
44
48
  callerSessionId,
49
+ // The calling session itself: bridge tools answer within its scope.
50
+ callerSession: sessionRef || null,
45
51
  callerCwd: cwd,
46
52
  setCallerCwd: async (nextCwd) => {
47
53
  const applyForCaller = sessionRef?._applyResolvedCwdForCaller;
@@ -58,6 +64,8 @@ function dispatchInternal(name, args, { cwd, callerSessionId, sessionRef, execut
58
64
  notifyFn,
59
65
  toolApprovalHook,
60
66
  toolCallId: executeOpts.toolCallId || null,
67
+ // Runtime-granted for this call only (terminal run); never from model args.
68
+ elevationApproved: elevationApproved === true,
61
69
  invocationSource: 'model-tool',
62
70
  });
63
71
  }
@@ -90,9 +98,12 @@ export function dispatchToolCall({ name, args }, ctx) {
90
98
  // variants) adapt to a native execution inside executeBuiltinTool's default
91
99
  // case; on a shape mismatch it falls back to the redirect guidance message.
92
100
  if (name === 'shell' || isBuiltinTool(name) || isExternalAdapterTool(name)) {
93
- const builtinOpts = executeOpts.suppressReadUnchangedStub
94
- ? { ...completionToolOpts, suppressReadUnchangedStub: true }
95
- : completionToolOpts;
101
+ const builtinOpts = {
102
+ ...completionToolOpts,
103
+ ...(executeOpts.suppressReadUnchangedStub ? { suppressReadUnchangedStub: true } : {}),
104
+ // Runtime-granted only; any value inherited from executeOpts is overridden.
105
+ elevationApproved: ctx.elevationApproved === true,
106
+ };
96
107
  return executeBuiltinTool(name, args, cwd, builtinOpts);
97
108
  }
98
109
  return formatUnknownBuiltinToolMessage(name, args, 'tool');
@@ -8,12 +8,13 @@
8
8
  import { isMcpTool } from '../../mcp/client.mjs';
9
9
  import { prepareDeferredToolCallThrough } from './deferred-call-through.mjs';
10
10
  import { refreshDeferredMcpToolCatalog } from '../../runtime-core/tool-catalog.mjs';
11
+ import { bridgeTargetUnavailable } from '../../runtime-core/tool-bridge.mjs';
11
12
  import { preDispatchDenyForSession, routeWebFetchCall } from './pre-dispatch-deny.mjs';
12
13
  import { runWithToolExecutionOwner } from '../../../../shared/tool-execution-owner.mjs';
13
14
  import { runWithLocalSearchTelemetry } from '../../tools/builtin/local-search-telemetry.mjs';
14
15
  import { throwIfAborted } from '../../../../shared/abort-race.mjs';
15
16
  import { prepareToolCall } from './tool-exec/call-prep.mjs';
16
- import { applyBeforeToolHook } from './tool-exec/before-hook.mjs';
17
+ import { applyBeforeToolHook, applyShellElevationGate } from './tool-exec/before-hook.mjs';
17
18
  import { dispatchToolCall } from './tool-exec/dispatch.mjs';
18
19
  import { applyAfterToolHook } from './tool-exec/after-hook.mjs';
19
20
  import { runReadOnlyIoWithDeadline } from './tool-exec/read-only-deadline.mjs';
@@ -65,6 +66,18 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
65
66
  if (isMcpTool(call.name)) refreshDeferredMcpToolCatalog(sessionRef);
66
67
  const deferredPrep = prepareDeferredToolCallThrough(sessionRef, call.name);
67
68
  if (deferredPrep?.deny) return deferredPrep.deny;
69
+ // A bridged target was resolved when its call_tool was projected; it must
70
+ // still be available in this session's scope (also after a hook rewrite).
71
+ // The authorized identity is the public tool name, not its transport
72
+ // (web_fetch routed to local_fetch/image_fetch stays web_fetch here).
73
+ if (executeOpts.bridgeWireCall) {
74
+ const unavailable = bridgeTargetUnavailable(sessionRef, finalCall.schemaName || finalCall.name);
75
+ if (unavailable) return unavailable;
76
+ }
77
+ // Elevated launches ask the user first; denied / no approval UI refuses the call.
78
+ const elevation = await applyShellElevationGate(call, { callerSessionId, executeOpts, toolApprovalHook });
79
+ if (elevation.denial) return elevation.denial;
80
+ throwIfAborted(executeOpts.signal);
68
81
  const result = await runReadOnlyIoWithDeadline(call.name, executeOpts.signal || null, async (deadlineSignal) => {
69
82
  let callOpts = executeOpts;
70
83
  if (deadlineSignal !== executeOpts.signal) {
@@ -80,6 +93,7 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
80
93
  completionToolOpts,
81
94
  notifyFn,
82
95
  toolApprovalHook,
96
+ elevationApproved: elevation.elevationApproved === true,
83
97
  });
84
98
  });
85
99
  return applyAfterToolHook(result, hookFrom(executeOpts, sessionRef, 'afterToolHook'), {
@@ -0,0 +1,150 @@
1
+ // Tool-exposure migration (native ↔ bridge-v1, and pre-versioned fixed
2
+ // surfaces → bridge-v1). The surface itself is rebuilt by
3
+ // applyDeferredToolSurface; this module adds what a changed request prefix
4
+ // invalidates: provider state, the prefix guard, the context baseline and the
5
+ // cache-break tag. Historical tool calls are never rewritten.
6
+ import {
7
+ applyDeferredToolSurface,
8
+ rebuildDeferredToolSurfaceForProvider,
9
+ } from '../../runtime-core/tool-catalog.mjs';
10
+ import {
11
+ bridgeSurfaceOutdated,
12
+ sessionToolExposure,
13
+ TOOL_EXPOSURE_BRIDGE,
14
+ TOOL_SURFACE_MIGRATION_INTENT,
15
+ toolExposureMigrationNeeded,
16
+ toolExposureModeForProvider,
17
+ } from '../../runtime-core/tool-exposure.mjs';
18
+ import { applyInitialDeferredToolManifestToBp2 } from '../../context/collect.mjs';
19
+ import { isAgentOwner } from '../../agent-owner.mjs';
20
+ import { honoredSchemaAllowlist } from '../manager/session-tool-surface.mjs';
21
+ import { syncSystemPrefix } from '../manager/prompt-utils.mjs';
22
+ import { invalidateProviderContextBaseline } from './compact-policy.mjs';
23
+
24
+ /** Drop everything measured against the previous tool surface. */
25
+ function invalidateForToolSurfaceMigration(session) {
26
+ delete session.providerState;
27
+ delete session._providerPrefixGuardState;
28
+ invalidateProviderContextBaseline(session);
29
+ session.updatedAt = Date.now();
30
+ }
31
+
32
+ /**
33
+ * After a surface re-apply outside a request (resume, provider switch)
34
+ * migrated the exposure: the first send of the next turn carries the tag.
35
+ */
36
+ export function markToolSurfaceMigrated(session) {
37
+ invalidateForToolSurfaceMigration(session);
38
+ session.pendingCacheBreakIntent = TOOL_SURFACE_MIGRATION_INTENT;
39
+ }
40
+
41
+ /** Provider switch: rebuild the surface for `provider`, migrating bridge ↔ native. */
42
+ export function rebuildToolSurfaceForProviderWithMigration(session, provider) {
43
+ if (!session) return false;
44
+ const migrating = toolExposureMigrationNeeded(session, provider);
45
+ rebuildDeferredToolSurfaceForProvider(session, provider);
46
+ if (migrating) markToolSurfaceMigrated(session);
47
+ return migrating;
48
+ }
49
+
50
+ // The latest assistant tool turn still waits for a result: not a safe boundary.
51
+ function hasUnansweredToolCalls(messages) {
52
+ const list = Array.isArray(messages) ? messages : [];
53
+ const index = list.findLastIndex((message) => message?.role === 'assistant' && message.toolCalls?.length);
54
+ if (index < 0) return false;
55
+ const answered = new Set(
56
+ list.slice(index + 1).flatMap((message) => (message?.role === 'tool' ? [message.toolCallId] : []))
57
+ );
58
+ return list[index].toolCalls.some((call) => call?.id && !answered.has(call.id));
59
+ }
60
+
61
+ /**
62
+ * Request-boundary migration of a live session whose persisted exposure
63
+ * differs from its provider's. `messages` is the transcript the request is
64
+ * built from; the fixed-guidance rewrite lands there (and on the session).
65
+ * Returns true when the surface changed; the caller drops its frozen tool
66
+ * snapshot and provider state and tags the send.
67
+ */
68
+ export function migrateToolExposureAtBoundary(session, messages) {
69
+ if (!session || !toolExposureMigrationNeeded(session) || hasUnansweredToolCalls(messages)) return false;
70
+ const stored = session.messages;
71
+ const working = Array.isArray(messages) ? messages : stored;
72
+ if (Array.isArray(working)) session.messages = working;
73
+ try {
74
+ applyDeferredToolSurface(session, session.deferredSurfaceMode || 'lead', [], {
75
+ provider: session.provider,
76
+ model: session.model,
77
+ });
78
+ } finally {
79
+ if (Array.isArray(working) && session.messages !== working) {
80
+ // The rewrite may drop an emptied system message: keep the request
81
+ // transcript array identity the loop holds.
82
+ working.splice(0, working.length, ...session.messages);
83
+ }
84
+ session.messages = stored;
85
+ }
86
+ // The rewritten prompt messages are fresh objects; the canonical transcript
87
+ // the save path persists takes them too, so the next save writes the new
88
+ // prompt together with the new exposure.
89
+ if (Array.isArray(stored) && Array.isArray(working) && stored !== working) syncSystemPrefix(stored, working);
90
+ invalidateForToolSurfaceMigration(session);
91
+ return true;
92
+ }
93
+
94
+ // Bridge state an agent surface carries; dropped when it returns to the full array.
95
+ const AGENT_BRIDGE_FIELDS = [
96
+ 'toolExposureMode',
97
+ 'deferredProviderMode',
98
+ 'deferredNativeTools',
99
+ 'deferredSurfaceMode',
100
+ 'deferredToolUsage',
101
+ 'deferredDefaultTools',
102
+ 'deferredSelectedTools',
103
+ 'deferredDiscoveredTools',
104
+ 'deferredCallableTools',
105
+ 'deferredAnnouncedTools',
106
+ 'deferredToolDeltaRevision',
107
+ 'nativeDeferredDiscovery',
108
+ 'mcpServerInstructions',
109
+ ];
110
+
111
+ /**
112
+ * Agent (worker) sessions. Call right after their tools were resolved
113
+ * (create, resume, route change): on a bridge provider the eager surface
114
+ * becomes the full-mode core plus the bridge, built only from those
115
+ * role/policy-filtered tools; a native provider keeps the full array. A
116
+ * session honouring its own schema allowlist (a hidden specialist role) is
117
+ * already a small explicit surface and keeps it. `existing`: the session had
118
+ * a surface before, so a changed exposure is a migration.
119
+ */
120
+ export function applyAgentToolExposure(session, { existing = false } = {}) {
121
+ if (!session || !Array.isArray(session.tools) || !isAgentOwner(session)) return false;
122
+ const before = sessionToolExposure(session);
123
+ const allowlisted = honoredSchemaAllowlist(session.schemaAllowedTools, { ownerIsAgent: true, agent: session.agent });
124
+ const bridge =
125
+ !allowlisted && toolExposureModeForProvider(session.provider, session.wireRoute) === TOOL_EXPOSURE_BRIDGE;
126
+ if (!bridge && before === null) return false;
127
+ // A surface an earlier bridge revision built is rebuilt now.
128
+ const outdated = bridgeSurfaceOutdated(session);
129
+ // The tools just resolved are the whole authority: no earlier catalog, MCP
130
+ // availability snapshot or pending MCP delta survives. (A bridge surface
131
+ // re-takes the snapshot at its next request boundary; a native agent has no
132
+ // refresh, so a stale snapshot would hide a connected server's tools.)
133
+ delete session.deferredToolCatalog;
134
+ delete session.deferredLateToolCatalog;
135
+ delete session.deferredMcpToolNames;
136
+ delete session.pendingDeferredToolDelta;
137
+ if (bridge) {
138
+ // The resolved list may be shared (prepared-resume cache): rebuild a copy.
139
+ session.tools = session.tools.slice();
140
+ applyDeferredToolSurface(session, 'full', [], { provider: session.provider, model: session.model });
141
+ } else {
142
+ for (const field of AGENT_BRIDGE_FIELDS) delete session[field];
143
+ // Without bridge state the fixed slot composes empty: the guidance goes.
144
+ if (Array.isArray(session.messages)) applyInitialDeferredToolManifestToBp2(session, [], { rebuild: true });
145
+ delete session.deferredToolBp2Applied;
146
+ }
147
+ const changed = before !== sessionToolExposure(session) || outdated;
148
+ if (existing && changed) markToolSurfaceMigrated(session);
149
+ return changed;
150
+ }
@@ -8,6 +8,7 @@ import { traceLoopPhaseTiming } from './diagnostics.mjs';
8
8
  import { processToolBatch } from '../tool-batch.mjs';
9
9
  import { CROSS_TURN_CAP, REPEAT_FAIL_LIMIT } from './loop-state.mjs';
10
10
  import { markStepEffort } from './step-auto-effort.mjs';
11
+ import { resolveExecutionToolCalls } from './tool-call-resolution.mjs';
11
12
 
12
13
  function isSleepLikeToolCall(call) {
13
14
  const name = String(call?.name || call?.toolName || call?.function?.name || '').toLowerCase();
@@ -34,7 +35,9 @@ export async function runToolPhase(state, round, sent, onToolCall) {
34
35
  }
35
36
  // Per-turn batch shape — one row per assistant turn so trace consumers can
36
37
  // derive the multi-tool adoption ratio without scanning message bodies.
37
- const toolBatchId = recordToolBatch(sessionId, calls, state.iterations);
38
+ // Audit records what runs: a bridged call_tool is recorded as its target.
39
+ // The wire calls stay the transcript identity (assistant turn below).
40
+ const toolBatchId = recordToolBatch(sessionId, resolveExecutionToolCalls(calls, sessionRef), state.iterations);
38
41
  await Promise.resolve(onToolCall?.(state.iterations, calls));
39
42
  const assistantTurnMsg = buildToolCallAssistantMessage(response, { calls, suppressMidTurnText, opts });
40
43
  commitAssistantMessage(messages, assistantTurnMsg, opts);
@@ -15,7 +15,7 @@ import {
15
15
  resolveAutoEffort,
16
16
  } from '../../providers/auto-effort.mjs';
17
17
  import { builtinFeatureActive } from '../../runtime-core/builtin-features.mjs';
18
- import { effortOptionsFor } from '../../runtime-core/effort.mjs';
18
+ import { effortOptionsFor, warnEmptyAutoEffortLadder } from '../../runtime-core/effort.mjs';
19
19
  import { effortJudgeSupportsSteps, judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-client.mjs';
20
20
  import { promptContentText } from './prompt-utils.mjs';
21
21
 
@@ -98,6 +98,7 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
98
98
  // the judge is not asked (in observe mode too: nothing would be logged).
99
99
  if (!autoEffortApplicable({ base, options })) {
100
100
  recordEffortDecision({ ...record, skipped: 'default-outside-auto-range' });
101
+ warnEmptyAutoEffortLadder(session.provider, session.model, base);
101
102
  return null;
102
103
  }
103
104
  // The previous user request shows the work a short follow-up continues.
@@ -120,22 +120,44 @@ function recordAgentRuntimeCall(session, result) {
120
120
  export async function recordAskUsage({ session, result, askStartedAt, turnSignal }) {
121
121
  const prefixHashForLog = recordAgentRuntimeCall(session, result);
122
122
  if (!result.usage) return;
123
- const inputTokens = result.usage.inputTokens || 0;
124
- const outputTokens = result.usage.outputTokens || 0;
125
- const cacheReadTokens = result.usage.cachedTokens || 0;
126
- const cacheWriteTokens = result.usage.cacheWriteTokens || 0;
123
+ await logSessionLlmUsage({
124
+ session,
125
+ usage: result.usage,
126
+ startedAt: askStartedAt,
127
+ signal: turnSignal,
128
+ prefixHash: prefixHashForLog,
129
+ transportTiming: result.transportTiming || null,
130
+ });
131
+ recordStandaloneStatusTelemetry(session, result, Date.now() - askStartedAt);
132
+ }
133
+
134
+ /** The usage-ledger row of one provider call billed to `session`. `mode`
135
+ * labels a call made outside the turn loop (a /btw side question). */
136
+ export async function logSessionLlmUsage({
137
+ session,
138
+ usage,
139
+ startedAt,
140
+ signal = null,
141
+ prefixHash = null,
142
+ transportTiming = null,
143
+ mode = null,
144
+ }) {
145
+ const inputTokens = usage.inputTokens || 0;
146
+ const outputTokens = usage.outputTokens || 0;
147
+ const cacheReadTokens = usage.cachedTokens || 0;
148
+ const cacheWriteTokens = usage.cacheWriteTokens || 0;
127
149
  // Unified total-prompt field. Anthropic = input+cache_read+cache_write
128
150
  // (additive); OpenAI OAuth/API/Gemini = input_tokens already includes the
129
151
  // cached portion (inclusive), so the fallback must not double-count.
130
152
  const { isInclusiveProvider, computeCostUsd } = await runAbortable(
131
- turnSignal,
153
+ signal,
132
154
  () => import('../../../../shared/llm/cost.mjs')
133
155
  );
134
156
  const inclusive = isInclusiveProvider(session.provider);
135
157
  let promptTokens = inputTokens + cacheReadTokens + cacheWriteTokens;
136
- if (typeof result.usage.promptTokens === 'number') promptTokens = result.usage.promptTokens;
158
+ if (typeof usage.promptTokens === 'number') promptTokens = usage.promptTokens;
137
159
  else if (inclusive) promptTokens = Math.max(inputTokens, cacheReadTokens + cacheWriteTokens);
138
- let costUsd = result.usage.costUsd || 0;
160
+ let costUsd = usage.costUsd || 0;
139
161
  if (!costUsd) {
140
162
  try {
141
163
  costUsd = computeCostUsd({
@@ -145,7 +167,7 @@ export async function recordAskUsage({ session, result, askStartedAt, turnSignal
145
167
  outputTokens,
146
168
  cacheReadTokens,
147
169
  cacheWriteTokens,
148
- cacheWrite1hTokens: result.usage.cacheWrite1hTokens || 0,
170
+ cacheWrite1hTokens: usage.cacheWrite1hTokens || 0,
149
171
  });
150
172
  } catch {
151
173
  /* best-effort */
@@ -158,7 +180,8 @@ export async function recordAskUsage({ session, result, askStartedAt, turnSignal
158
180
  preset: session.presetName || null,
159
181
  model: session.model,
160
182
  provider: session.provider,
161
- duration: Date.now() - askStartedAt,
183
+ ...(mode ? { mode } : {}),
184
+ duration: Date.now() - startedAt,
162
185
  profileId: session.profileId || null,
163
186
  sessionId: session.id,
164
187
  inputTokens,
@@ -166,11 +189,10 @@ export async function recordAskUsage({ session, result, askStartedAt, turnSignal
166
189
  cacheReadTokens,
167
190
  cacheWriteTokens,
168
191
  promptTokens,
169
- prefixHash: prefixHashForLog,
192
+ prefixHash,
170
193
  costUsd,
171
- transportTiming: result.transportTiming || null,
194
+ transportTiming,
172
195
  });
173
- recordStandaloneStatusTelemetry(session, result, Date.now() - askStartedAt);
174
196
  }
175
197
 
176
198
  /** Persist opaque providerState for stateful providers. The update bit
@@ -5,6 +5,7 @@
5
5
  // (runAskAgentLoop). Provider-not-available and trim failures throw here so
6
6
  // the caller marks the session errored instead of leaving stage='connecting'.
7
7
  import { getProvider } from '../../providers/registry.mjs';
8
+ import { pinSessionWireRoute } from '../../providers/wire-route.mjs';
8
9
  import { notifySkillsApplied, prepareExplicitSkills, recordAppliedSkills } from '../explicit-skills.mjs';
9
10
  import { prepareTurnEffortConfiguration } from '../../providers/effort-configuration.mjs';
10
11
  import { resolveTurnAutoEffort, turnStepAutoEffort } from './ask-turn-auto-effort.mjs';
@@ -17,6 +18,7 @@ import { applyTurnContextMeta, buildUserTurn, startProviderPrewarm, traceTurnCon
17
18
  import { rewindUnansweredPrompt } from './failed-turn-rewind.mjs';
18
19
  import { buildAgentLoopOptions, trackedToolCallHook } from './ask-turn-loop-options.mjs';
19
20
  import { _api_call_with_interrupt } from './ask-call-interrupt.mjs';
21
+ import { backfillFallbackSessionTitle } from './session-fallback-title.mjs';
20
22
 
21
23
  /** Resolves the provider, builds the user turn and pre-commits it; returns
22
24
  * what the loop and the commit need from this preparation. */
@@ -27,6 +29,10 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
27
29
  // Register the live session object for synchronous close snapshots.
28
30
  runtime.session = session;
29
31
  if (!provider) throw new Error(`Provider "${session.provider}" not available`);
32
+ // The session's wire is pinned before its first request (an existing
33
+ // session keeps the wire it started on); read from the history as the turn
34
+ // found it, awaited with the user turn below.
35
+ const wireRoutePending = pinSessionWireRoute(session, provider);
30
36
  // The turn-level judgment runs while the rest of the turn is prepared; it
31
37
  // reads the session as the turn found it (synchronously, on this call).
32
38
  // The first request still carries its decision: it is awaited below,
@@ -65,6 +71,7 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
65
71
  turnPromptSource: input.promptSource,
66
72
  effortConfiguration: null,
67
73
  }),
74
+ wireRoutePending,
68
75
  ]);
69
76
  const turnEffort = autoEffort?.applied ? autoEffort.effort : session.effort || null;
70
77
  const effortConfiguration = prepareTurnEffortConfiguration(
@@ -107,6 +114,14 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
107
114
  // user turn is introduced.
108
115
  session.messages = filterModelVisibleSessionMessages(outgoing);
109
116
  session.liveTurnMessages = outgoing;
117
+ // Name a titleless session from its first human prompt before the first
118
+ // save, so the title outlives any later compaction of the transcript. The
119
+ // earliest human turn already in the history wins; this turn's prompt is the
120
+ // fallback (runtime-injected turns carrying a promptSource never name it).
121
+ backfillFallbackSessionTitle(session, [
122
+ ...historyMessages,
123
+ ...(input.promptSource ? [] : [{ role: 'user', content: input.prompt }]),
124
+ ]);
110
125
  session.activeTurnCheckpoint = {
111
126
  version: 1,
112
127
  turnToken,
@@ -147,6 +162,7 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
147
162
  beforeCount: historyMessages.length + 1,
148
163
  deferredToolDelta: userTurn.deferredToolDelta,
149
164
  goalReminder: userTurn.goalReminder,
165
+ workspaceNotice: userTurn.workspaceNotice,
150
166
  };
151
167
  }
152
168
 
@@ -18,6 +18,53 @@ const relay = (fn, ...args) => {
18
18
  }
19
19
  };
20
20
 
21
+ /**
22
+ * The callback-free send options that shape a turn's provider request (effort,
23
+ * model parameters, cache routing, continuation state, Codex wire identity and
24
+ * the session's provider cache settings). agentLoop's options spread them, and
25
+ * a /btw request built before any turn has run uses them as they are.
26
+ */
27
+ export function buildRequestSendOptions({
28
+ sessionId,
29
+ session,
30
+ turnEffort,
31
+ effortConfiguration,
32
+ stepAutoEffort,
33
+ codexTurnId,
34
+ startedAtMs,
35
+ signal,
36
+ }) {
37
+ return {
38
+ effort: turnEffort,
39
+ effortConfiguration,
40
+ // { request, base } when each tool-result step is judged (step-auto-effort.mjs).
41
+ stepAutoEffort: stepAutoEffort || null,
42
+ fast: session.fast === true,
43
+ modelParameters: session.modelParameters || {},
44
+ selectedContextWindow: session.selectedContextWindow || session.contextWindow || null,
45
+ sessionId,
46
+ // Same projection compaction uses, so a session presents one identity on
47
+ // every request it makes.
48
+ ...(codexWireSendOpts(session, { turnId: codexTurnId, startedAtMs }) || {}),
49
+ promptCacheKey: session.promptCacheKey || sessionId,
50
+ // Provider-scoped cache key (mixdog-codex, mixdog-claude…). Distinct
51
+ // from sessionId — providers that pool sockets per-session (openai-oauth
52
+ // WS) use sessionId as the pool bucket and providerCacheKey as the
53
+ // server-side prompt-cache shard so parallel callers don't collide on a
54
+ // mid-turn socket while still sharing prefix cache.
55
+ providerCacheKey: session.promptCacheKey || null,
56
+ signal,
57
+ providerState: session.providerState ?? undefined,
58
+ // The wire this session is pinned to (wire-route.mjs).
59
+ wireRoute: session.wireRoute ?? undefined,
60
+ session,
61
+ // Agent Runtime cache settings — merged last so session overrides don't
62
+ // get overridden by defaults. When session has no profile,
63
+ // providerCacheOpts is null and this spread is a no-op.
64
+ ...(session.providerCacheOpts || {}),
65
+ };
66
+ }
67
+
21
68
  /**
22
69
  * @param {object} input
23
70
  * @param {string} input.sessionId
@@ -49,14 +96,6 @@ export function buildAgentLoopOptions({
49
96
  // (ask-turn-steering-drain.mjs).
50
97
  const drainSteering = createAskSteeringDrain({ sessionId, turn, askOpts });
51
98
  return {
52
- effort: turnEffort,
53
- effortConfiguration,
54
- // { request, base } when each tool-result step is judged (step-auto-effort.mjs).
55
- stepAutoEffort: stepAutoEffort || null,
56
- fast: session.fast === true,
57
- modelParameters: session.modelParameters || {},
58
- selectedContextWindow: session.selectedContextWindow || session.contextWindow || null,
59
- sessionId,
60
99
  onTextDelta: (chunk) => {
61
100
  interruption.recordTextDelta(chunk);
62
101
  checkpoint.schedule();
@@ -157,23 +196,16 @@ export function buildAgentLoopOptions({
157
196
  relay(askOpts?.onSkillsApplied, names, detail);
158
197
  },
159
198
  notifyFn: optionalFn(askOpts?.notifyFn),
160
- // Same projection compaction uses, so a session presents one identity on
161
- // every request it makes.
162
- ...(codexWireSendOpts(session, { turnId: codexTurnId, startedAtMs }) || {}),
163
- promptCacheKey: session.promptCacheKey || sessionId,
164
- // Provider-scoped cache key (mixdog-codex, mixdog-claude…). Distinct
165
- // from sessionId — providers that pool sockets per-session (openai-oauth
166
- // WS) use sessionId as the pool bucket and providerCacheKey as the
167
- // server-side prompt-cache shard so parallel callers don't collide on a
168
- // mid-turn socket while still sharing prefix cache.
169
- providerCacheKey: session.promptCacheKey || null,
170
- signal,
171
- providerState: session.providerState ?? undefined,
172
- session,
173
- // Agent Runtime cache settings — merged last so session overrides don't
174
- // get overridden by defaults. When session has no profile,
175
- // providerCacheOpts is null and this spread is a no-op.
176
- ...(session.providerCacheOpts || {}),
199
+ ...buildRequestSendOptions({
200
+ sessionId,
201
+ session,
202
+ turnEffort,
203
+ effortConfiguration,
204
+ stepAutoEffort,
205
+ codexTurnId,
206
+ startedAtMs,
207
+ signal,
208
+ }),
177
209
  onStageChange: (stage, detail) => {
178
210
  updateSessionStage(sessionId, stage);
179
211
  relay(askOpts?.onStageChange, stage, detail);
@@ -16,6 +16,7 @@ import {
16
16
  prefixUserTurnContent,
17
17
  suffixUserTurnReminders,
18
18
  buildCurrentTimeBlock,
19
+ snapshotPendingWorkspaceNotice,
19
20
  } from './prompt-utils.mjs';
20
21
  import { codexWireSendOpts } from './session-id.mjs';
21
22
  import { _tryBridgeExplicitPrefetch } from './prefetch-bridge.mjs';
@@ -173,7 +174,11 @@ export async function buildUserTurn({
173
174
  // input intake: either can precede the previous turn's pause.
174
175
  // This supplies context only; it never resumes the Goal.
175
176
  const goalReminder = snapshotPendingGoalReminder(session, { includePaused: true });
177
+ // A mid-conversation working-folder change: the system prompt keeps its
178
+ // old root (cache intact) and the new folder's facts ride this turn.
179
+ const workspaceNotice = snapshotPendingWorkspaceNotice(session);
176
180
  const reminderBlock = [
181
+ workspaceNotice?.content || '',
177
182
  currentTimeBlock ? `<system-reminder>\n# Current Time\n${currentTimeBlock}\n</system-reminder>` : '',
178
183
  deferredToolDelta?.content || '',
179
184
  goalReminder?.content || '',
@@ -200,6 +205,7 @@ export async function buildUserTurn({
200
205
  historyMessages,
201
206
  deferredToolDelta,
202
207
  goalReminder,
208
+ workspaceNotice,
203
209
  userTurnMessage,
204
210
  outgoing: [...historyMessages, userTurnMessage],
205
211
  };
@@ -8,6 +8,7 @@ import { ingestSessionTurn } from '../../../../session-search/session-search-ing
8
8
  import { persistedAssistantTranscriptMetadata } from '../../../../shared/transcript-metadata.mjs';
9
9
  import { acknowledgePendingDeferredToolDelta } from '../../runtime-core/deferred-tool-delta.mjs';
10
10
  import { acknowledgePendingGoalReminder } from '../../runtime-core/goal-reminder.mjs';
11
+ import { acknowledgePendingWorkspaceNotice } from './prompt-utils.mjs';
11
12
  import {
12
13
  finalizePendingMessageDelivery,
13
14
  drainPendingMessages,
@@ -121,6 +122,9 @@ export async function commitAskTurn({ sessionId, opened, prepared, result, rawTr
121
122
  if (prepared.goalReminder) {
122
123
  acknowledgePendingGoalReminder(session, prepared.goalReminder.revision);
123
124
  }
125
+ if (prepared.workspaceNotice) {
126
+ acknowledgePendingWorkspaceNotice(session, prepared.workspaceNotice.revision);
127
+ }
124
128
  return {
125
129
  ...result,
126
130
  trimmed: messagesDropped > 0,
@@ -21,7 +21,9 @@ import { uncachedInputTokensForProvider } from './usage-metrics.mjs';
21
21
  import { pruneOffloadSession } from '../tool-result-offload.mjs';
22
22
  import { _getPendingMessagesForSession } from './pending-messages.mjs';
23
23
  import { isSessionCompactionBlocked } from './runtime-liveness.mjs';
24
+ import { backfillFallbackSessionTitle } from './session-fallback-title.mjs';
24
25
  import { resetReadStateAfterCompaction } from '../read-dedup.mjs';
26
+ import { applyPendingWorkspaceReroot } from './prompt-utils.mjs';
25
27
  import {
26
28
  compactTargetBudget as compactTargetBudgetForPolicy,
27
29
  compactDisplayBeforeTokens,
@@ -629,7 +631,13 @@ async function commitSessionCompaction(plan, run, compactStartedAt) {
629
631
  let unchangedReason = null;
630
632
  if (!changed) unchangedReason = force ? 'nothing to compact' : 'below threshold';
631
633
  const now = Date.now();
634
+ // Older titleless sessions: keep a name before the transcript that carries
635
+ // the first prompt is replaced.
636
+ if (changed) backfillFallbackSessionTitle(session, messages);
632
637
  session.messages = transcript;
638
+ // The compacted transcript breaks the cache anyway: a staged working-folder
639
+ // change re-roots the system prompt now and needs no notice any more.
640
+ if (changed) applyPendingWorkspaceReroot(session);
633
641
  if (changed) resetReadStateAfterCompaction(resolvedSessionId);
634
642
  await pruneCompactedOffloads(session, resolvedSessionId);
635
643
  if (changed) session.providerState = undefined;