mixdog 1.0.11 → 1.1.0

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 (471) hide show
  1. package/NOTICE.md +20 -0
  2. package/README.md +75 -181
  3. package/package.json +9 -4
  4. package/scripts/build-shipped-history.mjs +131 -0
  5. package/scripts/check-changelog-locales.mjs +203 -0
  6. package/scripts/computer-task-cost-report.mjs +0 -4
  7. package/scripts/lib/run-node-tests.mjs +235 -13
  8. package/scripts/lib/test-failure-records.mjs +5 -0
  9. package/scripts/lib/test-failure-summary.mjs +9 -3
  10. package/scripts/lib/test-spawn-ledger.mjs +19 -0
  11. package/scripts/prune-embedding-runtime.mjs +9 -5
  12. package/scripts/sync-client-version-floors.mjs +100 -0
  13. package/scripts/test-direct.mjs +16 -1
  14. package/src/agents/advisor/AGENT.md +38 -0
  15. package/src/agents/advisor/agent.json +6 -0
  16. package/src/agents/reviewer/AGENT.md +5 -2
  17. package/src/agents/reviewer/agent.json +1 -1
  18. package/src/defaults/shipped-history.json +381 -0
  19. package/src/defaults/skills/docx/SKILL.md +7 -5
  20. package/src/defaults/skills/docx/references/html.md +9 -8
  21. package/src/defaults/skills/docx/references/native-authoring.md +28 -18
  22. package/src/defaults/skills/goal-management/SKILL.md +11 -5
  23. package/src/defaults/skills/local-provider/SKILL.md +2 -1
  24. package/src/defaults/skills/pdf/SKILL.md +9 -6
  25. package/src/defaults/skills/pdf/references/html.md +17 -12
  26. package/src/defaults/skills/pptx/SKILL.md +8 -6
  27. package/src/defaults/skills/pptx/references/composition.md +4 -4
  28. package/src/defaults/skills/pptx/references/concepts.md +168 -0
  29. package/src/defaults/skills/pptx/references/direction.md +5 -4
  30. package/src/defaults/skills/pptx/references/html.md +6 -29
  31. package/src/defaults/skills/pptx/references/kit-index.md +11 -3
  32. package/src/defaults/skills/pptx/references/kit.md +27 -5
  33. package/src/defaults/skills/pptx/references/review.md +6 -5
  34. package/src/defaults/skills/setup/SKILL.md +5 -8
  35. package/src/defaults/skills/setup/references/actions.md +61 -31
  36. package/src/defaults/skills/setup/references/surfaces.md +12 -10
  37. package/src/defaults/skills/xlsx/SKILL.md +8 -6
  38. package/src/defaults/skills/xlsx/references/html.md +8 -4
  39. package/src/defaults/skills/xlsx/references/model-conventions.md +2 -0
  40. package/src/defaults/skills/xlsx/references/report-design.md +32 -16
  41. package/src/help.mjs +1 -1
  42. package/src/lib/rules-builder.cjs +1 -1
  43. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +3 -1
  44. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +4 -0
  45. package/src/runtime/agent/orchestrator/config-presets.d.mts +1 -0
  46. package/src/runtime/agent/orchestrator/config-presets.mjs +44 -0
  47. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +9 -1
  48. package/src/runtime/agent/orchestrator/config.mjs +102 -21
  49. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +3 -2
  50. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +90 -26
  51. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +44 -14
  52. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +4 -4
  53. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +5 -3
  54. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +79 -8
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -4
  56. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  57. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
  58. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +11 -2
  59. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +9 -5
  60. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +9 -1
  61. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +2 -0
  62. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -22
  63. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -0
  64. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +28 -10
  65. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +14 -72
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +19 -3
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +20 -10
  68. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-sink.mjs +36 -9
  69. package/src/runtime/agent/orchestrator/providers/cursor.mjs +11 -17
  70. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +388 -0
  71. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +92 -109
  72. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +107 -0
  73. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +138 -30
  74. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +32 -15
  75. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +2 -0
  76. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +39 -5
  77. package/src/runtime/agent/orchestrator/providers/gemini.mjs +9 -2
  78. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +3 -2
  79. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +6 -1
  80. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +10 -1
  81. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +3 -2
  82. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +5 -1
  83. package/src/runtime/agent/orchestrator/providers/lib/note-error-usage.mjs +7 -0
  84. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +57 -0
  85. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +12 -5
  86. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +20 -15
  87. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +14 -9
  88. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +56 -11
  89. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +2 -1
  90. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +28 -1
  91. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +27 -3
  92. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +7 -5
  93. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +12 -0
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -8
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +26 -6
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +7 -1
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +34 -15
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +12 -2
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +0 -6
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +0 -19
  102. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +12 -43
  103. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +6 -0
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +39 -9
  105. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +31 -9
  106. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +13 -38
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +5 -2
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +40 -9
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +7 -39
  110. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +28 -101
  111. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +8 -4
  112. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +3 -6
  113. package/src/runtime/agent/orchestrator/providers/openai-service-tier.mjs +19 -0
  114. package/src/runtime/agent/orchestrator/providers/openai-startup-prewarm.mjs +5 -195
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +9 -18
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +4 -66
  117. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +11 -5
  118. package/src/runtime/agent/orchestrator/providers/openai-ws-send/acquire-attempt.mjs +3 -15
  119. package/src/runtime/agent/orchestrator/providers/openai-ws-send/attempt-request.mjs +6 -56
  120. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +1 -19
  121. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +2 -2
  122. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +2 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +3 -0
  124. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure-stamps.mjs +0 -1
  125. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +3 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts.mjs +3 -5
  127. package/src/runtime/agent/orchestrator/providers/openai-ws-send-outcome.mjs +10 -89
  128. package/src/runtime/agent/orchestrator/providers/openai-ws-send-span.mjs +1 -1
  129. package/src/runtime/agent/orchestrator/providers/openai-ws-send-trace.mjs +0 -6
  130. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +34 -11
  131. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +0 -1
  132. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +3 -7
  133. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +44 -19
  134. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +40 -12
  135. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +70 -0
  136. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -3
  137. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +4 -0
  138. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +1 -0
  139. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +2 -0
  140. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +11 -0
  141. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +31 -41
  142. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +5 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +0 -17
  144. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +0 -3
  145. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +0 -1
  146. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +1 -1
  148. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -2
  149. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +18 -4
  150. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +8 -1
  151. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/runtime-core/session-route-policy.mjs +16 -0
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +2 -0
  154. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -2
  155. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +7 -7
  156. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +6 -0
  157. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +45 -2
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +5 -3
  159. package/src/runtime/agent/orchestrator/session/eager-dispatch/entry.mjs +5 -0
  160. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +6 -13
  161. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +6 -2
  162. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +114 -0
  163. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +2 -0
  164. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +5 -9
  165. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +51 -18
  166. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +7 -4
  167. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
  168. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +0 -2
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +6 -9
  170. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +63 -3
  171. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +10 -28
  172. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +4 -4
  173. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +13 -0
  174. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +10 -19
  175. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +7 -1
  176. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +1 -0
  177. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +1 -3
  178. package/src/runtime/agent/orchestrator/stall-policy.mjs +0 -1
  179. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +18 -8
  180. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +19 -20
  181. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +6 -11
  182. package/src/runtime/agent/orchestrator/tools/builtin/file-version-test-helpers.mjs +11 -0
  183. package/src/runtime/agent/orchestrator/tools/builtin/file-version.mjs +13 -0
  184. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-single-file-rescue.mjs +8 -5
  185. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +25 -12
  186. package/src/runtime/agent/orchestrator/tools/builtin/raw-content-publication.mjs +17 -0
  187. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +136 -76
  188. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +15 -17
  189. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +4 -2
  190. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +11 -10
  191. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +5 -3
  192. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +30 -16
  193. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +2 -2
  194. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +4 -11
  195. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +7 -3
  196. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-validation.mjs +16 -19
  197. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  198. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +4 -1
  199. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +14 -4
  200. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +58 -8
  201. package/src/runtime/agent/orchestrator/tools/patch/content-guard.mjs +47 -0
  202. package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +155 -0
  203. package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-proofs.mjs +6 -2
  204. package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-snapshots.mjs +6 -2
  205. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +19 -16
  206. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +13 -44
  207. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +2 -2
  208. package/src/runtime/agent/orchestrator/tools/patch/post-patch-excerpts.mjs +5 -2
  209. package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +47 -7
  210. package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +72 -8
  211. package/src/runtime/agent/orchestrator/tools/patch/section-coalesce.mjs +3 -2
  212. package/src/runtime/agent/orchestrator/tools/patch/sequence/run.mjs +9 -1
  213. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +9 -1
  214. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +6 -6
  215. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +16 -4
  216. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +35 -14
  217. package/src/runtime/agent/orchestrator/tools/patch/wave.mjs +42 -4
  218. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
  219. package/src/runtime/agent/orchestrator/tools/shell-codepage.mjs +296 -0
  220. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +75 -24
  221. package/src/runtime/browser-bridge/tool-defs.mjs +1 -0
  222. package/src/runtime/channels/lib/config.mjs +3 -8
  223. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +7 -3
  224. package/src/{tui → runtime/channels}/lib/voice-setup.mjs +38 -22
  225. package/src/runtime/channels/lib/webhook/request-handler.mjs +42 -8
  226. package/src/runtime/computer-bridge/actions.mjs +2 -0
  227. package/src/runtime/effort-judge/judge-client.mjs +125 -25
  228. package/src/runtime/effort-judge/judge-input.mjs +96 -0
  229. package/src/runtime/effort-judge/judge-worker.mjs +52 -20
  230. package/src/runtime/effort-judge/model-install.mjs +74 -0
  231. package/src/runtime/effort-judge/model-manifest.json +21 -0
  232. package/src/runtime/effort-judge/previous-human-request.mjs +162 -0
  233. package/src/runtime/effort-judge/verified-context-input.mjs +10 -0
  234. package/src/runtime/github/tool.mjs +214 -14
  235. package/src/runtime/local-provider/context-settings.mjs +15 -6
  236. package/src/runtime/local-provider/gguf-header.mjs +13 -5
  237. package/src/runtime/local-provider/hugging-face.mjs +27 -5
  238. package/src/runtime/local-provider/install-progress.mjs +7 -0
  239. package/src/runtime/local-provider/managed-runtime.mjs +2 -1
  240. package/src/runtime/local-provider/model-maintenance.mjs +15 -6
  241. package/src/runtime/local-provider/resumable-installations.mjs +40 -1
  242. package/src/runtime/local-provider/server.mjs +2 -0
  243. package/src/runtime/memory/lib/embedding-provider.mjs +12 -0
  244. package/src/runtime/memory/lib/http-router/session-routes.mjs +2 -1
  245. package/src/runtime/memory/lib/memory-config-flags.mjs +3 -2
  246. package/src/runtime/memory/lib/memory-embed.mjs +5 -0
  247. package/src/runtime/memory/lib/pg/process.mjs +57 -5
  248. package/src/runtime/office/README.md +13 -7
  249. package/src/runtime/office/authoring/docx-html-build.mjs +4 -4
  250. package/src/runtime/office/authoring/docx-html-measure.mjs +60 -0
  251. package/src/runtime/office/authoring/pdf-author-action.mjs +6 -1
  252. package/src/runtime/office/authoring/pptx-brief.mjs +40 -1
  253. package/src/runtime/office/authoring/pptx-html-build.mjs +1 -1
  254. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  255. package/src/runtime/office/bench/deck-bench.mjs +1 -1
  256. package/src/runtime/office/com/office-com-host.ps1 +8 -0
  257. package/src/runtime/office/core/office-actions-render.mjs +2 -0
  258. package/src/runtime/office/design/design-art-direction.mjs +10 -2
  259. package/src/runtime/office/design/design-discipline.mjs +4 -5
  260. package/src/runtime/office/design/design-tokens.mjs +20 -1
  261. package/src/runtime/office/design/docx/design-docx/front-matter.mjs +7 -4
  262. package/src/runtime/office/design/docx/design-docx/section.mjs +3 -1
  263. package/src/runtime/office/design/docx/design-docx/writer.mjs +1 -0
  264. package/src/runtime/office/design/docx/design-docx-components.mjs +19 -15
  265. package/src/runtime/office/design/docx/design-docx.mjs +5 -6
  266. package/src/runtime/office/design/docx/document-typography.mjs +20 -6
  267. package/src/runtime/office/design/xlsx/design-xlsx.mjs +9 -2
  268. package/src/runtime/office/pdf/document-preview.mjs +133 -12
  269. package/src/runtime/office/pdf/pdf-writer.mjs +56 -22
  270. package/src/runtime/office/portable/portable-snapshot-docx.mjs +46 -3
  271. package/src/runtime/office/portable/portable-snapshot-shared.mjs +27 -1
  272. package/src/runtime/office/quality/assurance-rendered.mjs +21 -5
  273. package/src/runtime/office/quality/assurance-structure-docx.mjs +41 -9
  274. package/src/runtime/office/quality/design-aesthetics.mjs +4 -2
  275. package/src/runtime/office/quality/design-deck-diversity.mjs +15 -3
  276. package/src/runtime/office/quality/design-review.mjs +13 -5
  277. package/src/runtime/office/quality/document-brief.mjs +8 -2
  278. package/src/runtime/office/quality/forced-break-pages.mjs +203 -0
  279. package/src/runtime/office/quality/pptx-deck-rubric.mjs +21 -3
  280. package/src/runtime/office/quality/quality-pipeline.mjs +14 -17
  281. package/src/runtime/session-search/session-search-db.mjs +183 -0
  282. package/src/runtime/session-search/session-search-ingest.mjs +106 -0
  283. package/src/runtime/shared/agent-route-config.mjs +50 -2
  284. package/src/runtime/shared/bounded-file-read.mjs +166 -0
  285. package/src/runtime/shared/builtin-grandfathering.mjs +37 -0
  286. package/src/runtime/shared/config.mjs +24 -4
  287. package/src/runtime/shared/defaults-separation.mjs +263 -0
  288. package/src/runtime/shared/error-presentation.mjs +8 -1
  289. package/src/runtime/shared/llm/anthropic-effort.mjs +4 -0
  290. package/src/runtime/shared/llm/cost.mjs +4 -2
  291. package/src/runtime/shared/llm/model-catalog-projection.mjs +1 -1
  292. package/src/runtime/shared/llm/model-catalog.mjs +25 -0
  293. package/src/runtime/shared/llm/reasoning-usage.mjs +1 -2
  294. package/src/runtime/shared/llm/usage-accounting.mjs +14 -4
  295. package/src/runtime/shared/llm/usage-context.mjs +11 -1
  296. package/src/runtime/shared/llm/usage-ledger-repair.mjs +3 -1
  297. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +105 -1
  298. package/src/runtime/shared/llm/usage-ledger-worker.mjs +2 -1
  299. package/src/runtime/shared/llm/usage-ledger.mjs +72 -5
  300. package/src/runtime/shared/onnx-runtime-support.mjs +6 -0
  301. package/src/runtime/shared/orchestration.mjs +14 -6
  302. package/src/runtime/shared/pristine-execution-contract.json +7 -2
  303. package/src/runtime/shared/projects.mjs +65 -48
  304. package/src/runtime/shared/provider-accounts.mjs +47 -6
  305. package/src/runtime/shared/quota-resume-store.mjs +255 -0
  306. package/src/runtime/shared/shipped-definitions.mjs +275 -0
  307. package/src/runtime/shared/tool-card-model/agent-surface.mjs +30 -9
  308. package/src/runtime/shared/tool-card-model/aggregate-card.mjs +7 -3
  309. package/src/runtime/shared/tool-card-model/background-task.mjs +17 -1
  310. package/src/runtime/shared/tool-card-model/card-detail.mjs +10 -4
  311. package/src/runtime/shared/tool-card-model/card-header.mjs +10 -4
  312. package/src/runtime/shared/tool-card-model/card-status.mjs +22 -5
  313. package/src/runtime/shared/tool-card-model/displayed-result.mjs +6 -1
  314. package/src/runtime/shared/tool-card-model/media-result.mjs +53 -0
  315. package/src/runtime/shared/tool-card-model/terminal-status.mjs +17 -1
  316. package/src/runtime/shared/tool-card-model.golden-cases.mjs +1 -1
  317. package/src/runtime/shared/tool-card-model.golden.json +75 -66
  318. package/src/runtime/shared/tool-card-model.mjs +1 -0
  319. package/src/runtime/shared/tool-output-limit.mjs +3 -0
  320. package/src/runtime/shared/tool-primitives.mjs +24 -18
  321. package/src/runtime/shared/tool-result-summary.mjs +128 -17
  322. package/src/runtime/shared/tool-status.mjs +20 -7
  323. package/src/runtime/shared/tool-surface.mjs +105 -28
  324. package/src/runtime/shared/tool-work-units.mjs +221 -18
  325. package/src/runtime/shared/transcript-metadata.mjs +2 -0
  326. package/src/runtime/shared/turn-review-reply.mjs +2 -0
  327. package/src/runtime/shared/turn-snapshot.mjs +65 -6
  328. package/src/runtime/shared/turn-worktree-snapshot.mjs +202 -22
  329. package/src/runtime/shared/worker-requests.mjs +14 -2
  330. package/src/runtime/terminal-bridge/client.mjs +311 -0
  331. package/src/runtime/terminal-bridge/tool-defs.mjs +36 -0
  332. package/src/runtime/web-search/lib/ssrf-guard.mjs +12 -56
  333. package/src/runtime/web-search/tool-defs.mjs +2 -0
  334. package/src/session-runtime/boot/apis.mjs +30 -5
  335. package/src/session-runtime/boot/config.mjs +4 -0
  336. package/src/session-runtime/boot/facade.mjs +4 -1
  337. package/src/session-runtime/boot/infrastructure.mjs +21 -2
  338. package/src/session-runtime/boot/session.mjs +5 -5
  339. package/src/session-runtime/boot/tools.mjs +2 -0
  340. package/src/session-runtime/builtin-features.d.mts +1 -0
  341. package/src/session-runtime/channel-config-api.mjs +5 -0
  342. package/src/session-runtime/config-lifecycle/config-writers.mjs +3 -0
  343. package/src/session-runtime/config-lifecycle.mjs +31 -6
  344. package/src/session-runtime/goal-facade-api.mjs +4 -0
  345. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +15 -3
  346. package/src/session-runtime/lifecycle/inheritance.mjs +28 -6
  347. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +3 -0
  348. package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -1
  349. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +9 -0
  350. package/src/session-runtime/lifecycle/teardown/session-close.mjs +14 -2
  351. package/src/session-runtime/lifecycle/teardown.mjs +5 -0
  352. package/src/session-runtime/local-provider-settings.mjs +10 -0
  353. package/src/session-runtime/media-api.mjs +32 -22
  354. package/src/session-runtime/model-recency.mjs +14 -0
  355. package/src/session-runtime/model-route/route-persist.mjs +17 -2
  356. package/src/session-runtime/model-route/route-tuning.mjs +16 -5
  357. package/src/session-runtime/model-route/set-route.mjs +55 -22
  358. package/src/session-runtime/model-route/web-search-route.mjs +2 -2
  359. package/src/session-runtime/model-route-api.mjs +2 -1
  360. package/src/session-runtime/notification-bus.mjs +31 -6
  361. package/src/session-runtime/provider-auth/login.mjs +6 -0
  362. package/src/session-runtime/provider-models/catalog-load.mjs +3 -1
  363. package/src/session-runtime/provider-models/row-hydration.mjs +36 -10
  364. package/src/session-runtime/quick-model-rows/model-meta.mjs +26 -0
  365. package/src/session-runtime/quick-model-rows/provider-rows.mjs +40 -14
  366. package/src/session-runtime/resource-api.mjs +8 -1
  367. package/src/session-runtime/route-state.mjs +9 -0
  368. package/src/session-runtime/runtime-core.mjs +4 -0
  369. package/src/session-runtime/runtime-facade.mjs +20 -1
  370. package/src/session-runtime/runtime-feature-gates.mjs +2 -0
  371. package/src/session-runtime/runtime-review-api.mjs +12 -1
  372. package/src/session-runtime/services/agent-tool/helpers.mjs +14 -1
  373. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +10 -15
  374. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +6 -1
  375. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +20 -2
  376. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +14 -6
  377. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +2 -0
  378. package/src/session-runtime/services/agent-tool/tag-registry.mjs +12 -1
  379. package/src/session-runtime/services/agent-tool/worker-index.mjs +17 -1
  380. package/src/session-runtime/services/agent-tool.mjs +1 -0
  381. package/src/session-runtime/services/channel-admin.mjs +87 -13
  382. package/src/session-runtime/services/provider-admin.mjs +306 -66
  383. package/src/session-runtime/services/seeds.mjs +73 -142
  384. package/src/session-runtime/services/usage-dashboard-model.mjs +29 -0
  385. package/src/session-runtime/services/usage-dashboard.mjs +7 -0
  386. package/src/session-runtime/session-address.mjs +125 -0
  387. package/src/session-runtime/session-create.mjs +57 -2
  388. package/src/session-runtime/settings-api.mjs +1 -0
  389. package/src/session-runtime/settings-builtin-tools-api.mjs +15 -10
  390. package/src/session-runtime/settings-compaction-api.mjs +13 -0
  391. package/src/session-runtime/setup-tool/executor.mjs +93 -40
  392. package/src/session-runtime/setup-tool/extended-actions.mjs +64 -5
  393. package/src/session-runtime/setup-tool/settings-contract.mjs +46 -3
  394. package/src/session-runtime/setup-tool/tool-defs.mjs +14 -6
  395. package/src/session-runtime/tool-surface.mjs +16 -9
  396. package/src/session-runtime/turn/session-ops.mjs +3 -0
  397. package/src/session-runtime/turn/share-ops.mjs +4 -1
  398. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +6 -0
  399. package/src/session-runtime/usage-stats-api.mjs +43 -3
  400. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +31 -5
  401. package/src/session-runtime/workflow-agents-api/agent-route.mjs +6 -2
  402. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +27 -7
  403. package/src/standalone/daemon-boot-coordinator.mjs +10 -0
  404. package/src/standalone/daemon-desktop-runtime.mjs +1 -0
  405. package/src/standalone/daemon-drain-policy.mjs +9 -0
  406. package/src/standalone/daemon-stored-session-views.mjs +7 -8
  407. package/src/standalone/daemon.mjs +36 -8
  408. package/src/standalone/local-session-runtime.mjs +11 -0
  409. package/src/standalone/session-client.mjs +52 -7
  410. package/src/standalone/session-protocol.mjs +9 -0
  411. package/src/standalone/session-service/agent-tree/agent-child.mjs +2 -0
  412. package/src/standalone/session-service/entries/lifecycle.mjs +2 -0
  413. package/src/standalone/session-service/entries/session-loads.mjs +9 -0
  414. package/src/standalone/session-service/projection/revisions.mjs +28 -4
  415. package/src/standalone/session-service/projection.mjs +1 -0
  416. package/src/standalone/session-service/quota-resume.mjs +140 -0
  417. package/src/standalone/session-service/session-calls/session-action.mjs +2 -2
  418. package/src/standalone/session-service/session-calls.mjs +10 -2
  419. package/src/standalone/session-service/stored-reader.mjs +26 -1
  420. package/src/standalone/session-service.mjs +21 -0
  421. package/src/standalone/session-transport/routes.mjs +2 -0
  422. package/src/tui/app/doctor.mjs +7 -11
  423. package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +3 -5
  424. package/src/tui/app/model-picker/model-footer.mjs +2 -2
  425. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +21 -2
  426. package/src/tui/app/model-picker/route-selection.mjs +6 -1
  427. package/src/tui/app/settings-picker/settings-rows.mjs +4 -6
  428. package/src/tui/app/settings-picker/settings-toggles/store-toggles.mjs +1 -1
  429. package/src/tui/app/slash-commands.mjs +1 -1
  430. package/src/tui/app/slash-dispatch/route-commands.mjs +5 -3
  431. package/src/tui/app/transcript-row-estimate.mjs +17 -5
  432. package/src/tui/components/ContextPanel.jsx +5 -1
  433. package/src/tui/components/Spinner.jsx +34 -319
  434. package/src/tui/components/SpinnerByline.jsx +256 -0
  435. package/src/tui/components/tool-execution/aggregate-card.jsx +4 -2
  436. package/src/tui/components/tool-execution/text-format.mjs +1 -0
  437. package/src/tui/components/use-spinner-progress.mjs +113 -0
  438. package/src/tui/dist/index.mjs +15896 -14452
  439. package/src/tui/session/agent-job-feed/execution-delivery.mjs +13 -1
  440. package/src/tui/session/agent-job-feed/notification-router.mjs +3 -0
  441. package/src/tui/session/agent-job-feed/pending-resume.mjs +14 -1
  442. package/src/tui/session/agent-job-feed.mjs +4 -0
  443. package/src/tui/session/context-state.mjs +13 -1
  444. package/src/tui/session/initial-state.mjs +6 -0
  445. package/src/tui/session/quota-resume.mjs +263 -0
  446. package/src/tui/session/session-api/intake/abort.mjs +39 -35
  447. package/src/tui/session/session-api/intake/submission.mjs +13 -21
  448. package/src/tui/session/session-api/intake.mjs +3 -3
  449. package/src/tui/session/session-api/integrations.mjs +5 -1
  450. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  451. package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -2
  452. package/src/tui/session/session-api/lifecycle/session-reset.mjs +4 -0
  453. package/src/tui/session/session-api/lifecycle.mjs +71 -2
  454. package/src/tui/session/session-api/media.mjs +2 -2
  455. package/src/tui/session/session-api/quota-resume.mjs +21 -0
  456. package/src/tui/session/session-api/routes.mjs +5 -2
  457. package/src/tui/session/session-api/settings.mjs +2 -0
  458. package/src/tui/session/session-api.mjs +2 -0
  459. package/src/tui/session/session-flow/auto-clear.mjs +14 -6
  460. package/src/tui/session/session-flow/drain.mjs +52 -5
  461. package/src/tui/session/session-flow/queue/take-entries.mjs +9 -4
  462. package/src/tui/session/session-flow/queue.mjs +4 -0
  463. package/src/tui/session/session-flow/steering.mjs +11 -0
  464. package/src/tui/session/session-flow.mjs +1 -0
  465. package/src/tui/session/tool-approval.mjs +7 -2
  466. package/src/tui/session/transcript-intake.mjs +1 -0
  467. package/src/tui/session/turn-tool-cards.mjs +4 -6
  468. package/src/tui/session/turn.mjs +40 -4
  469. package/src/vendor/statusline/bin/statusline-route.mjs +3 -2
  470. package/src/vendor/statusline/src/gateway/route-meta.mjs +1 -1
  471. package/src/runtime/agent/orchestrator/providers/openai-ws-warmup.mjs +0 -165
@@ -1,4 +1,8 @@
1
1
  // Context lifecycle settings: compaction budgets and the idle auto-clear.
2
+ import {
3
+ refreshLiveSessionsProviderCacheOpts,
4
+ refreshSessionProviderCacheOpts,
5
+ } from '../runtime/agent/orchestrator/session/manager/session-lifecycle.mjs';
2
6
 
3
7
  // Every spelling of the main-context buffer budget; a new representation
4
8
  // replaces the previous one.
@@ -46,6 +50,13 @@ export function createCompactionSettings({
46
50
  formatDurationMs,
47
51
  invalidateContextStatusCache,
48
52
  }) {
53
+ // The Lead messages-tail TTL derives from the auto-clear idle window.
54
+ const refreshLeadCacheOpts = () => {
55
+ const config = getConfig();
56
+ refreshSessionProviderCacheOpts(getSession(), config);
57
+ refreshLiveSessionsProviderCacheOpts(config);
58
+ };
59
+
49
60
  /** Apply a per-provider idle override (or its reset) and return the resolved view. */
50
61
  const saveProviderIdle = (config, next, providerKey, input) => {
51
62
  const providerIdleMs = { ...(next.providerIdleMs || {}) };
@@ -57,6 +68,7 @@ export function createCompactionSettings({
57
68
  providerIdleMs[providerKey] = Math.max(60_000, Math.round(idleMs));
58
69
  }
59
70
  saveConfigAndAdopt({ ...config, autoClear: { ...next, providerIdleMs } });
71
+ refreshLeadCacheOpts();
60
72
  };
61
73
 
62
74
  return {
@@ -157,6 +169,7 @@ export function createCompactionSettings({
157
169
  if (!hasOwn(input, 'enabled')) next.enabled = true;
158
170
  }
159
171
  saveConfigAndAdopt({ ...config, autoClear: next });
172
+ refreshLeadCacheOpts();
160
173
  }
161
174
  const resolved = this.getAutoClear();
162
175
  return { ...resolved, label: formatDurationMs(resolved.idleMs) };
@@ -5,8 +5,9 @@
5
5
  * registers the tool executor before it finishes assembling the API object. */
6
6
  import { builtinFeatureActive } from '../../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
7
7
  import { ORCHESTRATION_MODES } from '../../runtime/shared/orchestration.mjs';
8
+ import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
8
9
  import { SETUP_DESKTOP_DOMAINS, SETUP_HANDOFFS } from './settings-contract.mjs';
9
- import { executeExtendedSetupAction, publicAutomation, validateMcpInput } from './extended-actions.mjs';
10
+ import { executeExtendedSetupAction, publicAutomation, publicHookRule, validateMcpInput } from './extended-actions.mjs';
10
11
  import { SETUP_DESKTOP_UNCLAIMED, createSetupUiRequests } from './ui-requests.mjs';
11
12
  import {
12
13
  SETUP_ACTIONS,
@@ -33,6 +34,10 @@ const ACTION_APPLIES_TO = {
33
34
  delete_automation: 'future automation runs',
34
35
  set_automation_enabled: 'future automation runs',
35
36
  set_webhook_config: 'the webhook worker after configuration reload',
37
+ add_hook_rule: 'subsequent tool calls; no restart required',
38
+ set_hook_rule_enabled: 'subsequent tool calls; no restart required',
39
+ delete_hook_rule: 'subsequent tool calls; no restart required',
40
+ set_media_default: 'media generations that omit lane/model, and the Studio selection',
36
41
  };
37
42
 
38
43
  const OPEN_TARGET_HINTS = Object.freeze({
@@ -114,6 +119,7 @@ function publicProviderRows(setup) {
114
119
  api: (setup?.api || []).map((row) =>
115
120
  pick(row, {
116
121
  source: apiKeySource(row),
122
+ custom: row.custom === true,
117
123
  keyUrl: /^https:\/\//.test(String(row.url || '')) ? row.url : null,
118
124
  })
119
125
  ),
@@ -137,6 +143,7 @@ function publicAccounts(pool) {
137
143
  return {
138
144
  selectedId: pool.selectedId,
139
145
  auto: pool.auto,
146
+ useCredits: pool.useCredits === true,
140
147
  accounts: pool.accounts.map(({ id, label, authenticated, reauthRequired }) => ({
141
148
  id,
142
149
  label,
@@ -188,13 +195,49 @@ async function automationStatus(rt, { domain }) {
188
195
  };
189
196
  }
190
197
 
191
- function featureFlags(rt) {
192
- return Object.fromEntries(
193
- Object.entries(rt.getToolModuleSettings?.() || {}).map(([name, settings]) => [
194
- name,
195
- Object.fromEntries(Object.entries(settings).filter(([key]) => key === 'enabled' || key === 'installed')),
196
- ])
197
- );
198
+ // Summary keys per built-in; Auto Effort also reports machine support and
199
+ // judge-model readiness so a failed toggle or install is explainable.
200
+ const FEATURE_STATUS_KEYS = ['enabled', 'installed'];
201
+ const FEATURE_EXTRA_STATUS_KEYS = { autoEffort: ['supported', 'ready', 'installing'] };
202
+
203
+ async function featureStatus(rt, getConfig) {
204
+ const config = getConfig();
205
+ return {
206
+ ...Object.fromEntries(
207
+ Object.entries(rt.getToolModuleSettings?.() || {}).map(([name, settings]) => {
208
+ const keys = [...FEATURE_STATUS_KEYS, ...(FEATURE_EXTRA_STATUS_KEYS[name] || [])];
209
+ return [name, Object.fromEntries(Object.entries(settings).filter(([key]) => keys.includes(key)))];
210
+ })
211
+ ),
212
+ browser: { active: builtinFeatureActive(config, 'browser') },
213
+ computer: { active: builtinFeatureActive(config, 'computer') },
214
+ terminal: { active: builtinFeatureActive(config, 'terminal') },
215
+ voice: rt.getVoiceStatus ? voiceFeatureStatus(await rt.getVoiceStatus()) : null,
216
+ };
217
+ }
218
+
219
+ async function mediaDefaults(rt) {
220
+ const rows = await Promise.all(MEDIA_KINDS.map((kind) => rt.getMediaDefault(kind)));
221
+ return {
222
+ defaults: Object.fromEntries(
223
+ MEDIA_KINDS.map((kind, i) => [kind, rows[i] ? { lane: rows[i].lane, model: rows[i].model } : null])
224
+ ),
225
+ };
226
+ }
227
+
228
+ function hookStatus(rt) {
229
+ const status = rt.hooksStatus();
230
+ return {
231
+ enabled: status.enabled === true,
232
+ configMode: status.configMode,
233
+ rulesPath: status.rulesPath,
234
+ ruleCount: status.ruleCount,
235
+ rules: status.rules.map(publicHookRule),
236
+ configuredEvents: status.configuredEvents,
237
+ configSources: status.configSources,
238
+ errors: status.errors,
239
+ note: status.note,
240
+ };
198
241
  }
199
242
 
200
243
  // status readers per non-desktop domain: (rt, { domain, getConfig }) → the
@@ -206,23 +249,16 @@ const SETUP_STATUS_READERS = {
206
249
  desktopScope: 'desktop-host; requires this conversation open in the local Desktop window',
207
250
  handoffs: SETUP_HANDOFFS,
208
251
  }),
209
- summary: (rt, { getConfig }) => {
210
- const config = getConfig();
211
- return {
212
- route: mainRoute(rt),
213
- workflow: (rt.listWorkflows?.() || []).find((pack) => pack.active) || null,
214
- outputStyle: rt.getOutputStyle?.()?.configured || null,
215
- profile: (({ title, language, experienceLevel }) => ({ title, language, experienceLevel }))(
216
- rt.getProfile?.() || {}
217
- ),
218
- features: {
219
- ...featureFlags(rt),
220
- browser: { active: builtinFeatureActive(config, 'browser') },
221
- computer: { active: builtinFeatureActive(config, 'computer') },
222
- },
223
- onboarding: rt.getOnboardingStatus?.() || null,
224
- };
225
- },
252
+ summary: async (rt, { getConfig }) => ({
253
+ route: mainRoute(rt),
254
+ workflow: (rt.listWorkflows?.() || []).find((pack) => pack.active) || null,
255
+ outputStyle: rt.getOutputStyle?.()?.configured || null,
256
+ profile: (({ title, language, experienceLevel }) => ({ title, language, experienceLevel }))(
257
+ rt.getProfile?.() || {}
258
+ ),
259
+ features: await featureStatus(rt, getConfig),
260
+ onboarding: rt.getOnboardingStatus?.() || null,
261
+ }),
226
262
  model: (rt) => ({ route: mainRoute(rt), effortOptions: rt.effortOptions || [] }),
227
263
  agents: (rt) => ({
228
264
  agents: rt.listAgents?.() || [],
@@ -249,14 +285,7 @@ const SETUP_STATUS_READERS = {
249
285
  compaction: (rt) => rt.getCompactionSettings?.() || {},
250
286
  memory: (rt) => ({ ...(rt.getToolModuleSettings?.()?.memory || {}), recap: rt.getRecapSettings?.() || null }),
251
287
  'local-provider': (rt) => rt.getToolModuleSettings().localProvider,
252
- features: (rt, { getConfig }) => {
253
- const config = getConfig();
254
- return {
255
- ...featureFlags(rt),
256
- browser: { active: builtinFeatureActive(config, 'browser') },
257
- computer: { active: builtinFeatureActive(config, 'computer') },
258
- };
259
- },
288
+ features: (rt, { getConfig }) => featureStatus(rt, getConfig),
260
289
  shell: (rt) => rt.getSystemShell?.() || {},
261
290
  providers: async (rt) => {
262
291
  const rows = publicProviderRows(await rt.getProviderSetup?.({}));
@@ -273,6 +302,8 @@ const SETUP_STATUS_READERS = {
273
302
  onboarding: (rt) => rt.getOnboardingStatus?.() || {},
274
303
  schedules: automationStatus,
275
304
  webhooks: automationStatus,
305
+ hooks: hookStatus,
306
+ media: mediaDefaults,
276
307
  };
277
308
 
278
309
  // Shape validation shared by every action: the action enum, the JSON
@@ -294,8 +325,8 @@ function validateSetupInput(args) {
294
325
  if (action !== 'set_agent_route' && Object.hasOwn(args.route, 'disabled')) {
295
326
  throw new Error('route.disabled is only accepted by set_agent_route');
296
327
  }
297
- if (action !== 'set_route' && Object.hasOwn(args.route, 'contextPercent')) {
298
- throw new Error('route.contextPercent is only accepted by set_route');
328
+ if (action !== 'set_route' && action !== 'set_agent_route' && Object.hasOwn(args.route, 'contextPercent')) {
329
+ throw new Error('route.contextPercent is only accepted by set_route and set_agent_route');
299
330
  }
300
331
  }
301
332
  for (const field of ['desktop', 'appearance', 'webhook', 'compaction', 'providerAccount']) {
@@ -311,7 +342,27 @@ function mcpServerInput(args) {
311
342
  return server;
312
343
  }
313
344
 
314
- const DESKTOP_HOSTED_FEATURES = ['browser', 'computer', 'voice'];
345
+ const DESKTOP_HOSTED_FEATURES = ['browser', 'computer'];
346
+
347
+ const publicVoice = (status) => ({
348
+ enabled: status.enabled === true,
349
+ installed: status.installed === true,
350
+ components: status.components,
351
+ });
352
+ const voiceFeatureStatus = (status) => ({ ...publicVoice(status), installing: status.busy === true });
353
+
354
+ // Voice runs on the runtime toggle the Desktop Built-in card also uses:
355
+ // enabling installs any missing whisper/ffmpeg component first.
356
+ async function setVoice(rt, enabled) {
357
+ const { status, error } = await rt.setVoiceEnabled(enabled);
358
+ if (status.enabled !== enabled || (enabled && status.installed !== true)) {
359
+ throw new Error(
360
+ `Voice did not reach the requested ${enabled ? 'installed and enabled' : 'disabled'} state${error ? `: ${error}` : ''}`
361
+ );
362
+ }
363
+ return { voice: publicVoice(status), appliesTo: 'channel voice transcription and Desktop dictation now' };
364
+ }
365
+
315
366
  // Git and Office installs bring their system dependency (Git, LibreOffice) in
316
367
  // through the Desktop's guided installers, the same steps as the Built-in card.
317
368
  // A request no Desktop window takes keeps the runtime-only install.
@@ -322,6 +373,7 @@ const SETUP_INSTALLABLE_FEATURES = [
322
373
  'office',
323
374
  'tidy',
324
375
  'localProvider',
376
+ 'autoEffort',
325
377
  'browser',
326
378
  'computer',
327
379
  'voice',
@@ -399,11 +451,13 @@ const SETUP_ACTION_HANDLERS = {
399
451
  set_builtin_enabled: (rt, args, { requestDesktop }) => {
400
452
  const name = requireEnum(args.name, SETUP_BUILTIN_TOGGLE_FEATURES, 'name');
401
453
  if (DESKTOP_HOSTED_FEATURES.includes(name)) return requestDesktop(args);
454
+ if (name === 'voice') return setVoice(rt, requireBoolean(args.enabled));
402
455
  return rt.setBuiltinToolEnabled(name, requireBoolean(args.enabled));
403
456
  },
404
457
  install_builtin: async (rt, args, { requestDesktop }) => {
405
458
  const name = requireEnum(args.name, SETUP_INSTALLABLE_FEATURES, 'name');
406
459
  if (DESKTOP_HOSTED_FEATURES.includes(name)) return requestDesktop(args);
460
+ if (name === 'voice') return setVoice(rt, true);
407
461
  if (DESKTOP_PREPARED_FEATURES.includes(name)) {
408
462
  try {
409
463
  return await requestDesktop(args);
@@ -565,9 +619,8 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
565
619
  const command = requireEnum(target, SETUP_OPEN_TARGETS, 'target');
566
620
  const sessionId = clean(getSessionId?.());
567
621
  const hint = OPEN_TARGET_HINTS[command] || `TUI: /${command}`;
568
- const handled = sessionId
569
- ? notifySessionUi?.(sessionId, `Open /${command}`, { kind: 'ui-open', command }) === true
570
- : false;
622
+ const handled =
623
+ Boolean(sessionId) && notifySessionUi?.(sessionId, `Open /${command}`, { kind: 'ui-open', command }) === true;
571
624
  return {
572
625
  opened: handled,
573
626
  target: command,
@@ -577,7 +630,7 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
577
630
  };
578
631
  }
579
632
 
580
- async function execute(args = {}, { signal } = {}) {
633
+ async function execute(args, { signal }) {
581
634
  signal?.throwIfAborted();
582
635
  const requestDesktop = (request) => desktop.request(request, { signal });
583
636
  const action = validateSetupInput(args);
@@ -1,4 +1,5 @@
1
1
  import { SETUP_EXTENDED_PROPERTIES, SETUP_DESKTOP_ACTIONS } from './settings-contract.mjs';
2
+ import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
2
3
 
3
4
  const own = (value, key) => Object.hasOwn(value || {}, key);
4
5
  const pick = (value, keys) => Object.fromEntries(keys.filter((key) => own(value, key)).map((key) => [key, value[key]]));
@@ -135,9 +136,10 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
135
136
  set_local_context: (rt, args) => rt.setLocalProviderContext(args.modelId, args.localContextWindow),
136
137
  async list_models(rt, args) {
137
138
  const options = args.catalog || {};
139
+ const refresh = options.refresh === true;
138
140
  const models = options.webSearch
139
- ? await rt.listWebSearchModels({ refresh: options.refresh === true })
140
- : await rt.listProviderModels({ refresh: options.refresh === true });
141
+ ? await rt.listWebSearchModels({ refresh })
142
+ : await rt.listProviderModels({ refresh });
141
143
  return { models: options.provider ? models.filter((model) => model.provider === options.provider) : models };
142
144
  },
143
145
  set_orchestration_mode: (rt, args) => rt.setOrchestrationMode(args.mode),
@@ -166,7 +168,7 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
166
168
  }
167
169
  if (kind === 'schedule' && own(input, 'parser')) throw new Error('parser is a webhook-only field');
168
170
  let previous = {};
169
- if (input.overwrite === true) {
171
+ if (input.overwrite) {
170
172
  const status = await rt.getChannelSetup();
171
173
  previous = status[kind === 'schedule' ? 'schedules' : 'webhooks'].find((row) => row.name === input.name);
172
174
  if (!previous) throw new Error(`${kind} "${input.name}" does not exist`);
@@ -184,7 +186,11 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
184
186
  return {
185
187
  ...publicAutomation(result),
186
188
  ...(kind === 'webhook'
187
- ? { secretSet: true, credentialHandoff: 'Use the Webhooks UI to copy the signing secret.' }
189
+ ? {
190
+ secretSet: true,
191
+ credentialHandoff:
192
+ 'The signing secret is never returned here or shown again. Open the Webhooks panel, edit this webhook, press Regenerate secret, copy the new value, and save.',
193
+ }
188
194
  : {}),
189
195
  };
190
196
  },
@@ -206,7 +212,7 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
206
212
  .sections.flatMap((section) => section.options)
207
213
  .find((row) => row.id === args.name);
208
214
  if (!option) throw new Error(`Unknown developer option "${args.name}"; read status developer`);
209
- if (args.enabled && option.warning && args.riskAccepted !== true) {
215
+ if (args.enabled && option.warning && !args.riskAccepted) {
210
216
  throw new Error(
211
217
  `Enabling ${option.label} requires riskAccepted:true after the user explicitly accepts: ${option.warning}`
212
218
  );
@@ -218,8 +224,61 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
218
224
  const status = await rt.getChannelSetup();
219
225
  return { webhook: pick(status.webhook, ['enabled', 'port', 'domain']) };
220
226
  },
227
+ add_hook_rule: async (rt, args) => {
228
+ const rule = args.hookRule;
229
+ const rewrites = ['modify', 'rewrite'].includes(rule.action);
230
+ const edits = ['patch', 'args'].filter((key) => own(rule, key));
231
+ if (rewrites && edits.length !== 1)
232
+ throw new Error(`hookRule.${rule.action} requires exactly one of patch or args`);
233
+ if (!rewrites && edits.length) throw new Error(`hookRule.${edits[0]} applies only to modify or rewrite rules`);
234
+ return { rules: publicHookRules(await rt.addHookRule(rule)) };
235
+ },
236
+ async set_hook_rule_enabled(rt, args) {
237
+ hookRuleAt(rt, args.ruleIndex);
238
+ const rules = await rt.setHookRuleEnabled(args.ruleIndex, args.enabled);
239
+ // Toggles are debounced; settle the write so the receipt reflects disk.
240
+ rt.flushHookRules();
241
+ return { rules: publicHookRules(rules) };
242
+ },
243
+ async delete_hook_rule(rt, args) {
244
+ const deleted = hookRuleAt(rt, args.ruleIndex);
245
+ return {
246
+ deleted,
247
+ rules: publicHookRules(await rt.deleteHookRule(args.ruleIndex)),
248
+ recovery: 'The rule is removed from the hook rules file; re-adding it with add_hook_rule restores it.',
249
+ };
250
+ },
251
+ async set_media_default(rt, args) {
252
+ if (!MEDIA_KINDS.includes(args.kind)) throw new Error(`kind must be one of ${MEDIA_KINDS.join(', ')}`);
253
+ const lane = (await rt.listMediaLanes()).find((row) => row.id === args.lane);
254
+ if (!lane) throw new Error(`Unknown media lane "${args.lane}"; list lanes with the media tool`);
255
+ if (!lane.authenticated) throw new Error(`${lane.label} is not signed in; open providers first`);
256
+ const spec = lane[args.kind];
257
+ if (!spec) throw new Error(lane.catalogError || `${lane.id} offers no ${args.kind} models`);
258
+ if (own(args, 'model') && !spec.models.some((model) => model.id === args.model)) {
259
+ throw new Error(`model "${args.model}" is not available on ${lane.id}/${args.kind}`);
260
+ }
261
+ return { media: await rt.setMediaDefault(pick(args, ['kind', 'lane', 'model'])) };
262
+ },
221
263
  });
222
264
 
265
+ /** Rule metadata only. Argument edits (patch/args) may embed credentials, so
266
+ * setup reports their presence, never their contents. */
267
+ export function publicHookRule(row) {
268
+ return {
269
+ ...pick(row, ['index', 'enabled', 'tool', 'action', 'match', 'cwd', 'reason']),
270
+ hasArgumentEdit: row.patch != null,
271
+ };
272
+ }
273
+
274
+ const publicHookRules = (rules) => rules.map(publicHookRule);
275
+
276
+ function hookRuleAt(rt, index) {
277
+ const rule = rt.hooksStatus().rules.find((row) => row.index === index);
278
+ if (!rule) throw new Error(`hook rule ${index} not found; read status hooks`);
279
+ return publicHookRule(rule);
280
+ }
281
+
223
282
  export async function executeExtendedSetupAction(rt, args, requestDesktop) {
224
283
  if (SETUP_DESKTOP_ACTIONS.includes(args.action)) return requestDesktop(args);
225
284
  const handler = EXTENDED_SETUP_HANDLERS[args.action];
@@ -3,6 +3,7 @@ import { ORCHESTRATION_MODES } from '../../runtime/shared/orchestration.mjs';
3
3
  /** Additional settings surfaces. Keep this registry shared by the wire schema,
4
4
  * dispatch coverage tests and the model-visible capability inventory. */
5
5
  const text = { type: 'string' };
6
+ const nonBlank = { type: 'string', minLength: 1, pattern: '\\S' };
6
7
  const removableText = { type: ['string', 'null'] };
7
8
  const boolean = { type: 'boolean' };
8
9
  const strings = { type: 'array', items: text };
@@ -33,8 +34,15 @@ export const SETUP_EXTENDED_ACTION_FIELDS = Object.freeze({
33
34
  revoke_linked_device: 'name',
34
35
  set_activity_rail_pins: 'activityRailPins',
35
36
  set_developer_option: 'name enabled riskAccepted?',
37
+ add_hook_rule: 'hookRule',
38
+ set_hook_rule_enabled: 'ruleIndex enabled',
39
+ delete_hook_rule: 'ruleIndex',
40
+ set_media_default: 'kind lane model?',
36
41
  });
37
42
 
43
+ /** Mirrors RULE_ACTIONS in services/hook-bus/rule-store.mjs. */
44
+ export const SETUP_HOOK_RULE_ACTIONS = Object.freeze(['allow', 'deny', 'block', 'modify', 'rewrite', 'ask']);
45
+
38
46
  /** Mirrors ACTIVITY_RAIL_PIN_IDS in apps/desktop/src/shared/activity-rail-pins.ts. */
39
47
  export const SETUP_ACTIVITY_RAIL_PIN_IDS = Object.freeze([
40
48
  'sessions',
@@ -57,6 +65,8 @@ export const SETUP_EXTENDED_DOMAINS = Object.freeze([
57
65
  'connection',
58
66
  'schedules',
59
67
  'webhooks',
68
+ 'hooks',
69
+ 'media',
60
70
  ]);
61
71
 
62
72
  export const SETUP_DESKTOP_ACTIONS = Object.freeze([
@@ -108,9 +118,9 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
108
118
  }),
109
119
  localContextWindow: {
110
120
  type: ['integer', 'null'],
111
- minimum: 512,
121
+ minimum: 16384,
112
122
  description:
113
- 'Managed local model context tokens; null restores automatic allocation. Maximum comes from the model status.',
123
+ 'Managed local model context tokens (32768+ recommended for agent work); null restores automatic allocation. Maximum comes from the model status.',
114
124
  },
115
125
  mode: {
116
126
  type: 'string',
@@ -185,6 +195,12 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
185
195
  turnNotifications: boolean,
186
196
  usagePinned: boolean,
187
197
  computerObserveOnly: boolean,
198
+ notificationVolume: {
199
+ type: 'integer',
200
+ minimum: 0,
201
+ maximum: 400,
202
+ description: 'Windows only: notification sound volume percent.',
203
+ },
188
204
  }),
189
205
  appearance: object({
190
206
  theme: { type: 'string', enum: ['system', 'dark', 'white'] },
@@ -193,13 +209,40 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
193
209
  description: 'Desktop UI language id from status appearance; independent of profile language.',
194
210
  },
195
211
  sidePanels: { type: 'string', enum: ['close-left', 'close-right', 'close-both', 'keep-open'] },
212
+ markdownDefaultView: { type: 'string', enum: ['preview', 'rich', 'source'] },
213
+ linkPreview: boolean,
214
+ toolActivityExpansion: { type: 'string', enum: ['collapsed', 'commands', 'all'] },
196
215
  }),
216
+ hookRule: object(
217
+ {
218
+ tool: { ...nonBlank, description: 'Tool name, prefix* pattern, or * (default).' },
219
+ action: { type: 'string', enum: [...SETUP_HOOK_RULE_ACTIONS] },
220
+ match: { ...nonBlank, description: 'Substring the tool arguments or cwd must contain.' },
221
+ cwd: { ...nonBlank, description: 'Substring the working directory must contain.' },
222
+ reason: nonBlank,
223
+ patch: { type: 'object', description: 'modify/rewrite: fields merged into the tool arguments.' },
224
+ args: { type: 'object', description: 'modify/rewrite: arguments that replace the tool arguments.' },
225
+ enabled: boolean,
226
+ },
227
+ ['action']
228
+ ),
229
+ ruleIndex: {
230
+ type: 'integer',
231
+ minimum: 0,
232
+ description: 'set_hook_rule_enabled/delete_hook_rule: rule index from status hooks.',
233
+ },
234
+ lane: { ...nonBlank, description: 'set_media_default: lane id from the media catalog.' },
235
+ model: {
236
+ ...nonBlank,
237
+ description: 'set_media_default: model id offered by the lane for the kind; omitted = the lane default.',
238
+ },
197
239
  project: object({ path: text, alias: text }, ['path']),
198
240
  projectPath: { ...text, description: 'Exact registered Project root.' },
199
241
  activityRailPins: {
200
242
  type: 'array',
201
243
  items: { type: 'string', enum: [...SETUP_ACTIVITY_RAIL_PIN_IDS] },
202
- description: 'set_activity_rail_pins: complete ordered list of pinned activity rail items; it replaces the current list.',
244
+ description:
245
+ 'set_activity_rail_pins: complete ordered list of pinned activity rail items; it replaces the current list.',
203
246
  },
204
247
  riskAccepted: {
205
248
  ...boolean,
@@ -4,6 +4,7 @@ import {
4
4
  SETUP_EXTENDED_PROPERTIES,
5
5
  SETUP_MCP_SCHEMA,
6
6
  } from './settings-contract.mjs';
7
+ import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
7
8
 
8
9
  /** Built-in `setup` tool: the model's handle on a Mixdog user's persisted
9
10
  * configuration. The description is a contract only; how to use each action
@@ -115,6 +116,7 @@ export const SETUP_BUILTIN_TOGGLE_FEATURES = Object.freeze([
115
116
  'office',
116
117
  'tidy',
117
118
  'localProvider',
119
+ 'autoEffort',
118
120
  'browser',
119
121
  'computer',
120
122
  'voice',
@@ -172,7 +174,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
172
174
  route: {
173
175
  ...ROUTE_SCHEMA,
174
176
  description:
175
- 'Partial route update; omitted fields are preserved. Agent or Web Search provider "" restores Main inheritance. contextPercent is Main-only.',
177
+ 'Partial route update; omitted fields are preserved. Agent or Web Search provider "" restores Main inheritance. contextPercent applies to Main and agent routes only.',
176
178
  },
177
179
  agent: { type: 'string', description: 'set_agent_route: agent id.' },
178
180
  workflow: { type: 'string', description: 'set_workflow: pack id.' },
@@ -225,7 +227,12 @@ export const SETUP_TOOL_DEFS = Object.freeze([
225
227
  properties: {
226
228
  selectedId: { type: 'string', description: 'Account to use now.' },
227
229
  auto: { type: 'boolean', description: 'Automatic switching to another account when one is exhausted.' },
228
- order: { type: 'array', items: { type: 'string' }, description: 'Every connected account id exactly once.' },
230
+ useCredits: { type: 'boolean', description: 'Allow paid credits once plan limits are reached.' },
231
+ order: {
232
+ type: 'array',
233
+ items: { type: 'string' },
234
+ description: 'Every connected account id exactly once.',
235
+ },
229
236
  rename: {
230
237
  type: 'object',
231
238
  additionalProperties: false,
@@ -261,9 +268,9 @@ export const SETUP_TOOL_DEFS = Object.freeze([
261
268
  },
262
269
  contextWindow: {
263
270
  type: 'integer',
264
- minimum: 512,
271
+ minimum: 16384,
265
272
  maximum: 32768,
266
- description: 'inspect_hf_model: runtime context allocation, default 8192.',
273
+ description: 'inspect_hf_model: runtime context allocation; default 32768 when the GPU holds it, else 16384.',
267
274
  },
268
275
  previewId: { type: 'string', description: 'register_hf_model: unexpired read-only inspection receipt.' },
269
276
  licenseAccepted: {
@@ -296,8 +303,9 @@ export const SETUP_TOOL_DEFS = Object.freeze([
296
303
  source: { type: 'string', description: 'add_plugin: Git URL, owner/repo, or local path.' },
297
304
  kind: {
298
305
  type: 'string',
299
- enum: ['skills', 'mcp', 'plugins'],
300
- description: 'set_extension_scope: which extension list `name` belongs to.',
306
+ enum: ['skills', 'mcp', 'plugins', ...MEDIA_KINDS],
307
+ description:
308
+ 'set_extension_scope: which extension list `name` belongs to (skills|mcp|plugins). set_media_default: media kind.',
301
309
  },
302
310
  projects: {
303
311
  type: 'array',
@@ -1,12 +1,20 @@
1
1
  // Lead tool surface: which tools the model sees before a session exists, and
2
2
  // how that pre-session selection is replayed once one does. runtime-core keeps
3
3
  // the mutable session/route/mode it injects here.
4
- import { applyDeferredToolSurface, filterDisallowedTools, selectDeferredTools } from '../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
4
+ import {
5
+ applyDeferredToolSurface,
6
+ filterDisallowedTools,
7
+ selectDeferredTools,
8
+ } from '../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
5
9
  import { LEAD_DISALLOWED_TOOLS } from '../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
6
10
  import { deferredSurfaceModeForLead, toolSpecForMode } from '../runtime/agent/orchestrator/runtime-core/effort.mjs';
7
11
  import { loadSkillToolDependencies } from '../runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs';
8
- import { disallowedModelToolNamesForProfile, filterModelToolsForProfile } from '../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
9
- import { configuredOrchestrationMode, sessionOrchestrationMode } from '../runtime/shared/orchestration.mjs';
12
+ import {
13
+ disallowedModelToolNamesForProfile,
14
+ filterModelToolsForProfile,
15
+ } from '../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
16
+ import { workflowDisallowsAgentTool } from '../runtime/agent/orchestrator/runtime-core/workflow.mjs';
17
+ import { configuredOrchestrationMode } from '../runtime/shared/orchestration.mjs';
10
18
 
11
19
  export function createToolSurface({
12
20
  mgr,
@@ -26,16 +34,14 @@ export function createToolSurface({
26
34
  }) {
27
35
  let preSessionSurface = null;
28
36
 
29
- // A live session keeps its frozen mode; a new session uses current settings.
37
+ // A live session keeps its frozen capability; a new session uses current
38
+ // agents. Solo still offers the tool (deferred) for explicit user requests.
30
39
  function workflowAllowsAgents() {
31
40
  const session = getSession();
32
41
  if (session?.id || session?.workflow || session?.orchestrationMode) {
33
- return sessionOrchestrationMode(session) !== 'none' && session?.workflow?.delegatesAgents !== false;
42
+ return !workflowDisallowsAgentTool(session?.workflow);
34
43
  }
35
- return (
36
- configuredOrchestrationMode(getConfig()) !== 'none' &&
37
- (delegatableAgentIds?.(getConfig(), cfgMod.getPluginData?.() || dataDir).length ?? 1) > 0
38
- );
44
+ return (delegatableAgentIds?.(getConfig(), cfgMod.getPluginData?.() || dataDir).length ?? 1) > 0;
39
45
  }
40
46
 
41
47
  function modelStandaloneTools() {
@@ -80,6 +86,7 @@ export function createToolSurface({
80
86
  tools: Array.isArray(tools) ? tools.slice() : [],
81
87
  mcpScopeId: getMcpScopeId(),
82
88
  cwd: getCurrentCwd?.() || null,
89
+ orchestrationMode: configuredOrchestrationMode(getConfig()),
83
90
  };
84
91
  applyDeferredToolSurface(surface, deferredSurfaceModeForLead(mode), modelStandaloneTools(), {
85
92
  provider: getRoute().provider,
@@ -79,6 +79,9 @@ export function createSessionOps(deps) {
79
79
  } catch {
80
80
  /* best-effort: PostCompact hook must never break manual compact */
81
81
  }
82
+ // The awaited compaction may outlive its session (user resumed/started
83
+ // another one). Only touch the active session if it is still this id.
84
+ if (getSession()?.id !== session.id) return result;
82
85
  setSession(mgr.getSession(session.id) || session);
83
86
  // Manual /compact drops the Goal's tool results exactly like the
84
87
  // automatic path, so it marks the same one-shot state reminder.
@@ -3,13 +3,16 @@
3
3
  * the owner side: pending-spool intake, presence beacon, and the viewer's
4
4
  * owner-liveness probe.
5
5
  */
6
- export function createShareOps({ getSession, getActiveTurnCount, mgr }) {
6
+ export function createShareOps({ getSession, getActiveTurnCount, mgr, isSessionAdmissionOpen }) {
7
7
  // Owner-side injection intake: foreign user messages persisted into the
8
8
  // shared spool by an attached surface. Engine pollers call this while
9
9
  // idle and run each returned text through the normal submit queue.
10
10
  async function takeRemoteInjections() {
11
11
  const session = getSession();
12
12
  if (!session?.id || session.remoteAttached) return [];
13
+ // Pending-spool intake is an admission route: a fenced/closed owner leaves
14
+ // the spool untouched.
15
+ if (isSessionAdmissionOpen && !isSessionAdmissionOpen()) return [];
13
16
  if (getActiveTurnCount() > 0) return [];
14
17
  try {
15
18
  return (await mgr.drainForeignUserInjections?.(session.id)) || [];
@@ -20,6 +20,7 @@ export function createTurnPreparation({
20
20
  hookCommonPayload,
21
21
  agentTool,
22
22
  getConfig,
23
+ assertSessionAdmission,
23
24
  }) {
24
25
  const scopedMcpTools = (session) => scopedMcpToolsFor(session, getConfig());
25
26
 
@@ -84,12 +85,17 @@ export function createTurnPreparation({
84
85
  // provider/model metadata initializes in the background. Only the next
85
86
  // actual turn waits, guaranteeing that it cannot run on a stale route.
86
87
  async function prepareSession(turn, prompt) {
88
+ // A closing/closed addressed runtime admits no turn (checked again after
89
+ // every await that could have outlived a close).
90
+ assertSessionAdmission?.();
87
91
  await turn.awaitTurn(() => awaitRoutePreparation?.());
92
+ assertSessionAdmission?.();
88
93
  turn.timing.routeWaitMs = performance.now() - turn.routeStartedAt;
89
94
  if (!getSession()?.id) {
90
95
  await turn.awaitTurn(() => createCurrentSession('turn', { signal: turn.signal }));
91
96
  }
92
97
  throwIfAborted(turn.signal);
98
+ assertSessionAdmission?.();
93
99
  ensureSessionTranscriptWriter?.();
94
100
  transcript.appendUser(prompt);
95
101
  const session0 = getSession();