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
@@ -79,6 +79,15 @@ export function createBuiltinToolSettings(
79
79
  invalidateContextStatusCache();
80
80
  return this.getRecapSettings();
81
81
  },
82
+ // Whether the model may title the session (session tool, action=rename).
83
+ // Absent config means on; only the opt-out is stored.
84
+ getSessionTitleSettings() {
85
+ return { aiSessionTitles: getConfig()?.aiSessionTitles !== false };
86
+ },
87
+ setAiSessionTitles(enabled) {
88
+ saveConfigAndAdopt({ ...getConfig(), aiSessionTitles: enabled !== false });
89
+ return this.getSessionTitleSettings();
90
+ },
82
91
  getToolModuleSettings() {
83
92
  const config = getConfig();
84
93
  const localProvider = getLocalProviderStatus?.() || {};
@@ -92,6 +92,7 @@ function routeInput(source) {
92
92
  if (clean(source.model)) next.model = clean(source.model);
93
93
  if (clean(source.effort)) next.effort = clean(source.effort);
94
94
  if (typeof source.fast === 'boolean') next.fast = source.fast;
95
+ if (typeof source.autoEffort === 'boolean') next.autoEffort = source.autoEffort;
95
96
  if (Object.hasOwn(source, 'modelParameters')) next.modelParameters = { ...source.modelParameters };
96
97
  if (Object.hasOwn(source, 'contextPercent')) next.contextPercent = source.contextPercent;
97
98
  if (Object.hasOwn(source, 'contextTokens')) next.contextTokens = source.contextTokens;
@@ -141,6 +142,34 @@ function publicProviderRows(setup) {
141
142
  };
142
143
  }
143
144
 
145
+ /** Minimal provider rows for the model: only providers with a credential (or
146
+ * one needing re-authentication), counts instead of account rosters. */
147
+ function configuredProviderRows(rows, accountCount) {
148
+ const providers = [];
149
+ let notConfigured = 0;
150
+ for (const [kind, list] of [
151
+ ['api', rows.api],
152
+ ['oauth', rows.oauth],
153
+ ['local', rows.local],
154
+ ]) {
155
+ for (const row of list) {
156
+ if (!row.authenticated && !row.reauthRequired) {
157
+ notConfigured += 1;
158
+ continue;
159
+ }
160
+ providers.push({
161
+ id: row.id,
162
+ kind,
163
+ authenticated: row.authenticated,
164
+ status: row.status,
165
+ ...(row.reauthRequired ? { reauthRequired: true } : {}),
166
+ ...(kind === 'oauth' ? { accounts: row.authenticated ? accountCount(row.id) : 0 } : {}),
167
+ });
168
+ }
169
+ }
170
+ return { ...(rows.pendingSecrets ? { pendingSecrets: true } : {}), providers, notConfigured };
171
+ }
172
+
144
173
  /** OAuth account roster without usage meters or provider-side identities. */
145
174
  function publicAccounts(pool) {
146
175
  return {
@@ -300,8 +329,9 @@ const SETUP_STATUS_READERS = {
300
329
  'local-provider': (rt) => rt.getToolModuleSettings().localProvider,
301
330
  features: (rt, { getConfig }) => featureStatus(rt, getConfig),
302
331
  shell: (rt) => rt.getSystemShell?.() || {},
303
- providers: async (rt) => {
332
+ providers: async (rt, { detail }) => {
304
333
  const rows = publicProviderRows(await rt.getProviderSetup?.({}));
334
+ if (!detail) return configuredProviderRows(rows, (id) => rt.getProviderAccounts(id).accounts.length);
305
335
  rows.oauth = rows.oauth.map((row) =>
306
336
  row.authenticated ? { ...row, accounts: publicAccounts(rt.getProviderAccounts(row.id)) } : row
307
337
  );
@@ -339,7 +369,7 @@ function validateSetupInput(args) {
339
369
  if (action !== 'set_agent_route' && Object.hasOwn(args.route, 'disabled')) {
340
370
  throw new Error('route.disabled is only accepted by set_agent_route');
341
371
  }
342
- for (const field of ['contextPercent', 'contextTokens']) {
372
+ for (const field of ['contextPercent', 'contextTokens', 'autoEffort']) {
343
373
  if (action !== 'set_route' && action !== 'set_agent_route' && Object.hasOwn(args.route, field)) {
344
374
  throw new Error(`route.${field} is only accepted by set_route and set_agent_route`);
345
375
  }
@@ -401,7 +431,7 @@ const SETUP_ACTION_HANDLERS = {
401
431
  status: async (_rt, args, { readStatus, requestDesktop }) => {
402
432
  const domain = clean(args.domain) || 'summary';
403
433
  requireEnum(domain, SETUP_STATUS_DOMAINS, 'domain');
404
- return { domain, ...(await readStatus(domain, requestDesktop)) };
434
+ return { domain, ...(await readStatus(domain, requestDesktop, args.detail === true)) };
405
435
  },
406
436
  open: (_rt, args, { openSurface }) => openSurface(args.target),
407
437
  set_route: async (rt, args) => {
@@ -631,11 +661,11 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
631
661
  return facade;
632
662
  };
633
663
 
634
- async function readStatus(domain, requestDesktop) {
664
+ async function readStatus(domain, requestDesktop, detail) {
635
665
  const rt = api();
636
666
  if (SETUP_DESKTOP_DOMAINS.includes(domain)) return requestDesktop({ action: 'status', domain });
637
667
  if (!Object.hasOwn(SETUP_STATUS_READERS, domain)) throw new Error(`setup: unknown status domain "${domain}"`);
638
- return SETUP_STATUS_READERS[domain](rt, { domain, getConfig: () => getConfig?.() || {} });
668
+ return SETUP_STATUS_READERS[domain](rt, { domain, detail, getConfig: () => getConfig?.() || {} });
639
669
  }
640
670
 
641
671
  function openSurface(target) {
@@ -669,7 +699,7 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
669
699
  dispose: desktop.dispose,
670
700
  async execute(args = {}, options = {}) {
671
701
  const result = await execute(args, options);
672
- if (READ_ONLY_SETUP_ACTIONS.has(args.action)) return JSON.stringify(result ?? {}, null, 2);
702
+ if (READ_ONLY_SETUP_ACTIONS.has(args.action)) return JSON.stringify(result ?? {});
673
703
  await flushSettings?.();
674
704
  // Attached surfaces re-read what changed instead of waiting for their
675
705
  // next open or cache expiry.
@@ -1,11 +1,81 @@
1
1
  import { SETUP_EXTENDED_PROPERTIES, SETUP_DESKTOP_ACTIONS } from './settings-contract.mjs';
2
2
  import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
3
+ import { OPENAI_COMPAT_PRESETS } from '../../runtime/agent/orchestrator/providers/openai-compat-presets.mjs';
3
4
 
4
5
  const own = (value, key) => Object.hasOwn(value || {}, key);
5
6
  const pick = (value, keys) => Object.fromEntries(keys.filter((key) => own(value, key)).map((key) => [key, value[key]]));
6
7
  const entryKeys = Object.keys(SETUP_EXTENDED_PROPERTIES.entry.properties);
7
8
  const definitionKeys = Object.keys(SETUP_EXTENDED_PROPERTIES.definition.properties);
8
9
 
10
+ const MODEL_PAGE_DEFAULT = 25;
11
+
12
+ function providerIndex(rows) {
13
+ const counts = new Map();
14
+ for (const row of rows) counts.set(row.provider, (counts.get(row.provider) || 0) + 1);
15
+ return [...counts].map(([provider, count]) => {
16
+ const defaultModel = OPENAI_COMPAT_PRESETS[provider]?.defaultModel;
17
+ return { provider, count, ...(defaultModel ? { defaultModel } : {}) };
18
+ });
19
+ }
20
+
21
+ function compactModelRow(row) {
22
+ const context = row.contextWindow || null;
23
+ const maxContext = Number(row.maxContextWindow) || 0;
24
+ return {
25
+ id: row.id,
26
+ display: row.display || row.id,
27
+ context,
28
+ ...(maxContext > (context || 0) ? { maxContext } : {}),
29
+ efforts: (row.effortOptions || []).map((option) => option.value),
30
+ ...(row.fastCapable === true ? { fast: true } : {}),
31
+ ...(row.supportsVision === true ? { vision: true } : {}),
32
+ };
33
+ }
34
+
35
+ const isPresent = (value) =>
36
+ value != null &&
37
+ value !== '' &&
38
+ value !== false &&
39
+ !(typeof value === 'object' && !Object.keys(value).length);
40
+
41
+ /** Everything set_route can use for one model; empty and false fields omitted. */
42
+ function modelDetail(row) {
43
+ const detail = {
44
+ provider: row.provider,
45
+ id: row.id,
46
+ display: row.display || row.id,
47
+ context: row.contextWindow,
48
+ maxContext: Number(row.maxContextWindow) > row.contextWindow ? row.maxContextWindow : null,
49
+ outputTokens: row.outputTokens,
50
+ vision: row.supportsVision,
51
+ webSearch: row.supportsWebSearch,
52
+ reasoning: row.supportsReasoning,
53
+ effortOptions: (row.effortOptions || []).map(({ value, label }) => ({ value, label })),
54
+ defaultEffort: row.defaultEffort,
55
+ fastCapable: row.fastCapable,
56
+ fastEfforts: row.fastEfforts,
57
+ defaultFast: row.defaultFast,
58
+ serviceTiers: row.serviceTiers,
59
+ defaultServiceTier: row.defaultServiceTier,
60
+ additionalSpeedTiers: row.additionalSpeedTiers,
61
+ modelParameterOptions: row.modelParameterOptions,
62
+ parameterVariants: row.parameterVariants,
63
+ defaultModelParameters: row.defaultModelParameters,
64
+ supportsMaxMode: row.supportsMaxMode,
65
+ };
66
+ return Object.fromEntries(Object.entries(detail).filter(([, value]) => isPresent(value)));
67
+ }
68
+
69
+ function findModel(rows, id, provider) {
70
+ const matches = rows.filter((row) => row.id === id && (!provider || row.provider === provider));
71
+ if (!matches.length) {
72
+ throw new Error(`model "${id}" not found${provider ? ` for provider "${provider}"` : ''}; list_models with catalog.provider returns its model ids`);
73
+ }
74
+ const providers = [...new Set(matches.map((row) => row.provider))];
75
+ if (providers.length > 1) throw new Error(`model "${id}" is offered by ${providers.join(', ')}; pass catalog.provider`);
76
+ return matches[0];
77
+ }
78
+
9
79
  export function publicAutomation(row) {
10
80
  const result = {
11
81
  ...pick(row, entryKeys),
@@ -136,12 +206,22 @@ async function saveDefinition(rt, args) {
136
206
  export const EXTENDED_SETUP_HANDLERS = Object.freeze({
137
207
  set_local_context: (rt, args) => rt.setLocalProviderContext(args.modelId, args.localContextWindow),
138
208
  async list_models(rt, args) {
139
- const options = args.catalog || {};
140
- const refresh = options.refresh === true;
141
- const models = options.webSearch
142
- ? await rt.listWebSearchModels({ refresh })
143
- : await rt.listProviderModels({ refresh });
144
- return { models: options.provider ? models.filter((model) => model.provider === options.provider) : models };
209
+ const { provider, model, page = 1, limit = MODEL_PAGE_DEFAULT, webSearch, refresh } = args.catalog || {};
210
+ const rows = webSearch
211
+ ? await rt.listWebSearchModels({ refresh: refresh === true })
212
+ : await rt.listProviderModels({ refresh: refresh === true });
213
+ if (model) return { model: modelDetail(findModel(rows, model, provider)) };
214
+ if (!provider) return { providers: providerIndex(rows) };
215
+ const own = rows.filter((row) => row.provider === provider);
216
+ const pages = Math.max(1, Math.ceil(own.length / limit));
217
+ return {
218
+ provider,
219
+ total: own.length,
220
+ page,
221
+ pages,
222
+ ...(page < pages ? { nextPage: page + 1 } : {}),
223
+ models: own.slice((page - 1) * limit, page * limit).map(compactModelRow),
224
+ };
145
225
  },
146
226
  set_orchestration_mode: (rt, args) => rt.setOrchestrationMode(args.mode),
147
227
  get_mcp_server: async (rt, args) => publicMcpConfig(await rt.getMcpServerConfig(args.name)),
@@ -114,9 +114,19 @@ export const SETUP_MCP_SCHEMA = object({
114
114
 
115
115
  export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
116
116
  catalog: object({
117
- provider: text,
118
- webSearch: boolean,
119
- refresh: boolean,
117
+ provider: {
118
+ ...text,
119
+ description: 'list_models: omit for the provider index; set for that provider\'s compact model rows.',
120
+ },
121
+ model: {
122
+ ...text,
123
+ description:
124
+ 'list_models: one model id; returns its full options (efforts, fast, service tiers, modelParameterOptions, parameterVariants) for set_route. Add provider when several offer the id.',
125
+ },
126
+ page: { type: 'integer', minimum: 1, description: 'list_models with provider: 1-based page; default 1.' },
127
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'list_models with provider: rows per page; default 25.' },
128
+ webSearch: { ...boolean, description: 'list_models: native-search capable models only.' },
129
+ refresh: { ...boolean, description: 'list_models: refresh the catalog first.' },
120
130
  }),
121
131
  localContextWindow: {
122
132
  type: ['integer', 'null'],
@@ -68,7 +68,7 @@ export const SETUP_OPEN_TARGETS = Object.freeze([
68
68
  // Runtime dispatch contract. A trailing ? denotes an optional field. Keep
69
69
  // this out of the wire schema: field descriptions already name their actions.
70
70
  export const SETUP_ACTION_FIELDS = Object.freeze({
71
- status: 'domain?',
71
+ status: 'domain? detail?',
72
72
  open: 'target',
73
73
  set_route: 'route',
74
74
  set_agent_route: 'agent route',
@@ -136,6 +136,10 @@ const ROUTE_SCHEMA = {
136
136
  model: { type: 'string' },
137
137
  effort: { type: 'string' },
138
138
  fast: { type: 'boolean' },
139
+ autoEffort: {
140
+ type: 'boolean',
141
+ description: 'Main and agent routes only: Auto reasoning for this route; omitted = preserved.',
142
+ },
139
143
  modelParameters: { type: 'object', additionalProperties: { type: 'string' } },
140
144
  // A typed enum is unrepresentable on Gemini; the bounds project everywhere
141
145
  // and the executor rejects values that are not a multiple of 10.
@@ -157,7 +161,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
157
161
  name: 'setup',
158
162
  title: 'Setup',
159
163
  description:
160
- "Read or change this Mixdog installation's settings through the runtime. Load the setup skill first (local-provider for managed local-model installation). status reads one domain; open navigates the attached app to a settings surface. Secrets (API keys, OAuth) are never accepted. Changes apply to new sessions unless the result says otherwise.",
164
+ "Read or change this Mixdog installation's settings through the runtime. Load the setup skill first (local-provider for managed local-model installation). status reads one domain; open navigates the attached app to a settings surface; list_models returns a provider index, then one provider's paged compact rows, then one model's full options (catalog.model). Results are compact JSON. Secrets (API keys, OAuth) are never accepted. Changes apply to new sessions unless the result says otherwise.",
161
165
  annotations: {
162
166
  title: 'Setup',
163
167
  readOnlyHint: false,
@@ -177,6 +181,11 @@ export const SETUP_TOOL_DEFS = Object.freeze([
177
181
  enum: [...SETUP_STATUS_DOMAINS],
178
182
  description: 'status: which domain to read; default summary.',
179
183
  },
184
+ detail: {
185
+ type: 'boolean',
186
+ description:
187
+ 'status providers: full rows for every provider (key URLs, expiry, account ids) instead of configured providers only.',
188
+ },
180
189
  target: {
181
190
  type: 'string',
182
191
  enum: [...SETUP_OPEN_TARGETS],
@@ -236,7 +245,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
236
245
  accountId: {
237
246
  type: 'string',
238
247
  description:
239
- 'forget_provider_auth: OAuth account id from status providers; required when the provider has several accounts.',
248
+ 'forget_provider_auth: OAuth account id from status providers with detail:true; required when the provider has several accounts.',
240
249
  },
241
250
  providerAccount: {
242
251
  type: 'object',
@@ -263,7 +272,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
263
272
  properties: { id: { type: 'string' }, label: { type: 'string', maxLength: 80 } },
264
273
  },
265
274
  },
266
- description: 'set_provider_account: OAuth account change; account ids from status providers.',
275
+ description: 'set_provider_account: OAuth account change; account ids from status providers with detail:true.',
267
276
  },
268
277
  modelId: {
269
278
  type: 'string',
@@ -46,18 +46,16 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
46
46
  }
47
47
  return { kind: 'user' };
48
48
  };
49
+ const enabledFlags = contextMod.skillEnabledFlags(skills);
49
50
  return {
50
51
  cwd,
51
52
  count: skills.length,
52
53
  tools: getTools().map(({ name }) => ({ name })),
53
- skills: skills.map((skill) => {
54
+ skills: skills.map((skill, index) => {
54
55
  const source = sourceForSkill(skill);
55
56
  return {
56
57
  name: skill.name,
57
- enabled: !(
58
- contextMod.isSkillDisabled?.(skill.name, null, skills) ||
59
- contextMod.skillMissingFeature?.(skill.name, null, skills)
60
- ),
58
+ enabled: enabledFlags[index],
61
59
  description: skill.description || '',
62
60
  whenToUse: skill.whenToUse || '',
63
61
  filePath: skill.filePath || null,
@@ -6,6 +6,7 @@ import {
6
6
  filterDisallowedTools,
7
7
  selectDeferredTools,
8
8
  } from '../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
9
+ import { AGENT_WORKER_DENIED_TOOLS } from '../runtime/agent/orchestrator/session/manager/tool-resolution.mjs';
9
10
  import { LEAD_DISALLOWED_TOOLS } from '../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
10
11
  import { deferredSurfaceModeForLead, toolSpecForMode } from '../runtime/agent/orchestrator/runtime-core/effort.mjs';
11
12
  import { loadSkillToolDependencies } from '../runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs';
@@ -52,8 +53,11 @@ export function createToolSurface({
52
53
  const workflowTools = hideAgentTool
53
54
  ? profileTools.filter((tool) => !agentToolNames.has(String(tool?.name || '')))
54
55
  : profileTools;
56
+ const visibleTools = agentOwned
57
+ ? workflowTools.filter((tool) => !AGENT_WORKER_DENIED_TOOLS.has(String(tool?.name || '').toLowerCase()))
58
+ : workflowTools;
55
59
  const denied = new Set(getFeatureDisallowedTools().map((name) => String(name || '')));
56
- return denied.size ? workflowTools.filter((tool) => !denied.has(String(tool?.name || ''))) : workflowTools;
60
+ return denied.size ? visibleTools.filter((tool) => !denied.has(String(tool?.name || ''))) : visibleTools;
57
61
  }
58
62
 
59
63
  function disallowedTools() {
@@ -0,0 +1,25 @@
1
+ /**
2
+ * src/session-runtime/turn/compaction-gate.mjs - serializes a model-scheduled
3
+ * compaction (session tool) with everything that follows its turn. The
4
+ * compaction is chained, never left dangling: `after(fn)` wraps a command so it
5
+ * waits for the compaction in flight, and the compaction itself only runs if
6
+ * the session it was scheduled for is still the live one.
7
+ */
8
+ export function createCompactionGate({ getSessionId, compact }) {
9
+ let tail = Promise.resolve();
10
+ const run = (sessionId) => {
11
+ tail = tail
12
+ .then(() => (getSessionId() === sessionId ? compact() : null))
13
+ .catch(() => {
14
+ /* best-effort: a scheduled compaction must never break teardown */
15
+ });
16
+ return tail;
17
+ };
18
+ const after =
19
+ (fn) =>
20
+ async (...args) => {
21
+ await tail;
22
+ return fn(...args);
23
+ };
24
+ return { run, after };
25
+ }
@@ -10,7 +10,6 @@ export function createSessionOps(deps) {
10
10
  const {
11
11
  getSession,
12
12
  setSession,
13
- getCurrentCwd,
14
13
  setMode,
15
14
  getActiveTurnCount,
16
15
  mgr,
@@ -18,7 +17,7 @@ export function createSessionOps(deps) {
18
17
  agentTool,
19
18
  invalidatePreSessionToolSurface,
20
19
  refreshEmptySessionToolPolicy,
21
- applyResolvedCwd,
20
+ switchProject,
22
21
  resolveCwdPath,
23
22
  agentStatusState,
24
23
  getReservedSessionId,
@@ -122,9 +121,12 @@ export function createSessionOps(deps) {
122
121
  return { messageCount: list.length, messages: list.slice(start) };
123
122
  }
124
123
 
125
- function setCwd(path) {
126
- applyResolvedCwd(resolveCwdPath(path), { persistProjectSelection: true });
127
- return getCurrentCwd();
124
+ // The desktop/remote Project switch: refused while a turn runs or the
125
+ // session works in a managed worktree (switchProject); resolves once the
126
+ // prompt refresh landed. Its target is a registered Project or the task
127
+ // workspace, classified by desktop membership.
128
+ async function setCwd(path) {
129
+ return switchProject(resolveCwdPath(path), { classifyByMembership: true });
128
130
  }
129
131
 
130
132
  return {
@@ -0,0 +1,22 @@
1
+ /**
2
+ * src/session-runtime/turn/side-question-ops.mjs - /btw side questions on the
3
+ * runtime's current session. They run beside an in-progress turn and touch no
4
+ * session state (see orchestrator/session/side-question.mjs).
5
+ */
6
+ import {
7
+ askSideQuestion,
8
+ cancelSideQuestion,
9
+ } from '../../runtime/agent/orchestrator/session/side-question.mjs';
10
+
11
+ export function createSideQuestionOps({ getSession, getReservedSessionId }) {
12
+ const sessionId = () => getSession()?.id || getReservedSessionId?.() || '';
13
+ return {
14
+ /** @returns {Promise<{ text: string }>} */
15
+ askSide: (question) => askSideQuestion(sessionId(), question),
16
+ /** Abort the side question of `targetSessionId` (the session it was
17
+ * asked in), or of the current session when omitted. */
18
+ cancelSide: (targetSessionId) => {
19
+ cancelSideQuestion(typeof targetSessionId === 'string' && targetSessionId ? targetSessionId : sessionId());
20
+ },
21
+ };
22
+ }
@@ -1,4 +1,5 @@
1
1
  import { isVisibleStreamProgress } from '../../../runtime/shared/stream-progress.mjs';
2
+ import { toolCallDisplayIdentity } from '../../../runtime/shared/tool-primitives.mjs';
2
3
 
3
4
  // The askSession callback bridge: caller callbacks pass through, with the
4
5
  // transcript, first-visible timing, title release and warmup arming folded in.
@@ -6,10 +7,13 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
6
7
  function plannedToolCalls(session0, options) {
7
8
  return async (iter, calls) => {
8
9
  for (const call of calls || []) {
10
+ // A bridged call reports the tool it runs; the transcript keeps the wire call.
11
+ const identity = toolCallDisplayIdentity(call?.name, call?.arguments);
9
12
  hooks.emit('tool:planned', {
10
13
  sessionId: session0.id,
11
- name: call?.name || 'tool',
14
+ name: identity.name || 'tool',
12
15
  callId: call?.id || null,
16
+ ...(identity.via ? { via: identity.via } : {}),
13
17
  });
14
18
  }
15
19
  if (typeof options.onToolCall === 'function') {
@@ -49,9 +49,9 @@ export function createTurnPreparation({
49
49
  // Slower servers remain available through the late-tool path; a reconnect
50
50
  // in flight gets the same short TTFT grace BEFORE folding the catalog so it
51
51
  // cannot hold the provider request. No reconnect in flight → no-op.
52
- const awaitGrace = async () => {
52
+ const awaitGrace = async (options) => {
53
53
  try {
54
- await turn.awaitTurn(() => turn.timing.awaitMcpGrace());
54
+ await turn.awaitTurn(() => turn.timing.awaitMcpGrace(options));
55
55
  } catch {
56
56
  /* gate must never break the turn */
57
57
  }
@@ -64,7 +64,12 @@ export function createTurnPreparation({
64
64
  // One-shot: cleared before the fold so a throw still never re-runs it,
65
65
  // and a resumed session (flag unset) skips straight to the late path.
66
66
  session0.deferredInitialRefreshPending = false;
67
- await awaitGrace();
67
+ // A spawned agent runtime owns a fresh MCP scope whose connect starts at
68
+ // its boot, so the 0 ms default grace would hide every MCP tool from the
69
+ // agent's first (often only) turn. Agents are not on the user's TTFT
70
+ // path: wait for the initial connect within the server startup budget.
71
+ const agentOwned = session0.owner === 'agent' || session0.visibility === 'agent-only';
72
+ await awaitGrace({ untilConnected: agentOwned });
68
73
  try {
69
74
  refreshInitialDeferredMcpSurface(session0, scopedMcpTools(session0));
70
75
  } catch {
@@ -28,6 +28,8 @@ export function createTurnSettlement({
28
28
  setFirstTurnCompleted,
29
29
  scheduleProviderWarmup,
30
30
  scheduleProviderModelWarmup,
31
+ takePendingCompact,
32
+ runPendingCompact,
31
33
  }) {
32
34
  async function completeTurn(turn, session0, result) {
33
35
  throwIfAborted(turn.signal);
@@ -99,6 +101,14 @@ export function createTurnSettlement({
99
101
  /* lead pool must never break turn teardown */
100
102
  }
101
103
  setActiveTurnCount(Math.max(0, getActiveTurnCount() - 1));
104
+ // A compaction the model scheduled (session tool) runs once the turn is over.
105
+ // Only while the settled session is still the live one; otherwise it stays
106
+ // pending for that session and never compacts another. The runner chains
107
+ // the compaction so the next turn waits on it.
108
+ const settledId = turn.session0?.id;
109
+ if (getActiveTurnCount() === 0 && settledId && getSession()?.id === settledId && takePendingCompact?.(settledId)) {
110
+ runPendingCompact?.(settledId);
111
+ }
102
112
  if (!isFirstTurnCompleted()) {
103
113
  setFirstTurnCompleted(true);
104
114
  scheduleProviderWarmup();
@@ -38,11 +38,12 @@ export function createTurnTimingFactory({ getSession, awaitInitialMcpConnect, mc
38
38
  /* timing telemetry must never affect a turn */
39
39
  }
40
40
  };
41
- // Give an in-flight MCP connect only a short TTFT grace.
42
- timing.awaitMcpGrace = async () => {
41
+ // Give an in-flight MCP connect only a short TTFT grace. untilConnected
42
+ // waits for the initial connect bounded only by the server startup budget.
43
+ timing.awaitMcpGrace = async ({ untilConnected = false } = {}) => {
43
44
  const graceStartedAt = performance.now();
44
45
  try {
45
- await awaitInitialMcpConnect?.(mcpTurnGraceMs);
46
+ await awaitInitialMcpConnect?.(untilConnected ? undefined : mcpTurnGraceMs);
46
47
  } finally {
47
48
  timing.mcpWaitMs += performance.now() - graceStartedAt;
48
49
  }
@@ -13,6 +13,7 @@ import { createSnapshotTrackerFactory } from './turn-run/snapshot-tracker.mjs';
13
13
  import { createTurnOpener } from './turn-run/turn-open.mjs';
14
14
  import { createTurnPreparation } from './turn-run/turn-prepare.mjs';
15
15
  import { createAskCallbacks } from './turn-run/ask-callbacks.mjs';
16
+ import { registerNativeWebSearchUsageSink } from '../native-web-search-usage.mjs';
16
17
  import { createTurnSettlement } from './turn-run/turn-settle.mjs';
17
18
 
18
19
  export function createTurnRunner(deps) {
@@ -94,15 +95,30 @@ export function createTurnRunner(deps) {
94
95
  try {
95
96
  const session0 = await prepareSession(turn, prompt, options);
96
97
  const turnContext = await dispatchPromptSubmit(turn, session0, prompt, options);
97
- const result = await mgr.askSession(
98
- session0.id,
99
- prompt,
100
- turnContext || null,
101
- plannedToolCalls(session0, options),
102
- getCurrentCwd(),
103
- options.prefetch || null,
104
- askCallbacks(turn, session0, options)
105
- );
98
+ const callbacks = askCallbacks(turn, session0, options);
99
+ // Register only once askSession's session lock is held: the first
100
+ // provider send of this turn. A turn queued behind another on the same
101
+ // session id therefore never receives the running turn's search usage.
102
+ let releaseWebSearchUsage = null;
103
+ const providerSendStarted = callbacks.onProviderSendStarted;
104
+ callbacks.onProviderSendStarted = (...args) => {
105
+ releaseWebSearchUsage ??= registerNativeWebSearchUsageSink(session0.id, options.onNativeWebSearchUsage);
106
+ return providerSendStarted(...args);
107
+ };
108
+ let result;
109
+ try {
110
+ result = await mgr.askSession(
111
+ session0.id,
112
+ prompt,
113
+ turnContext || null,
114
+ plannedToolCalls(session0, options),
115
+ getCurrentCwd(),
116
+ options.prefetch || null,
117
+ callbacks
118
+ );
119
+ } finally {
120
+ releaseWebSearchUsage?.();
121
+ }
106
122
  return await completeTurn(turn, session0, result);
107
123
  } catch (error) {
108
124
  reportTurnError(turn, error);
@@ -82,22 +82,43 @@ function accountsInUse(accountPool) {
82
82
  return inUse;
83
83
  }
84
84
 
85
- // Every id a session's spend was recorded under: its own, and the per-account
86
- // provider session each subscription account sent it under before account
87
- // sends recorded the visible session.
88
- function sessionUsageIds(sessionId, accountPool) {
89
- const ids = [sessionId];
85
+ // Each subscription provider's account ids, read once per request.
86
+ function accountScopes(accountPool) {
87
+ const scopes = [];
90
88
  for (const provider of ACCOUNT_PROVIDERS) {
91
89
  try {
92
- for (const account of accountPool(provider).accounts)
93
- ids.push(accountScopedSessionId(provider, account.id, sessionId));
90
+ scopes.push([provider, accountPool(provider).accounts.map((account) => account.id)]);
94
91
  } catch {
95
92
  /* an unreadable pool leaves that provider's older records out */
96
93
  }
97
94
  }
95
+ return scopes;
96
+ }
97
+
98
+ // Every id a session's spend was recorded under: its own, and the per-account
99
+ // provider session each subscription account sent it under before account
100
+ // sends recorded the visible session.
101
+ function sessionUsageIdsFor(scopes, sessionId) {
102
+ const ids = [sessionId];
103
+ for (const [provider, accounts] of scopes) {
104
+ for (const account of accounts) ids.push(accountScopedSessionId(provider, account, sessionId));
105
+ }
98
106
  return ids;
99
107
  }
100
108
 
109
+ // Other sessions a caller asks about beside its own (the composer island's
110
+ // agent sessions): bounded, distinct, never the caller's own id.
111
+ const MAX_SESSION_USAGE_IDS = 64;
112
+ function otherSessionIds(options, sessionId) {
113
+ const ids = Array.isArray(options?.sessionIds) ? options.sessionIds : [];
114
+ const unique = new Set();
115
+ for (const id of ids) {
116
+ if (typeof id === 'string' && id && id !== sessionId) unique.add(id);
117
+ if (unique.size >= MAX_SESSION_USAGE_IDS) break;
118
+ }
119
+ return [...unique];
120
+ }
121
+
101
122
  /** `null` = all time. `0` = today. Anything else is a trailing day count. */
102
123
  function normalizeDays(value) {
103
124
  if (value === null || value === undefined || value === 'all') return null;
@@ -213,15 +234,26 @@ export function createUsageStatsApi({
213
234
  return snapshot;
214
235
  },
215
236
 
216
- /** This runtime's session from its first request, compactions included; null before it has one. */
217
- async getSessionUsage() {
237
+ /**
238
+ * This runtime's session from its first request, compactions included; null before it has one.
239
+ * `sessionIds` adds the same totals for each named session (the agents it spawned) under
240
+ * `sessions`, each read by its own id only.
241
+ */
242
+ async getSessionUsage(options = {}) {
218
243
  const sessionId = getSessionId();
219
244
  if (!sessionId) return null;
220
245
  const store = ledger();
221
246
  if (!store) throw new Error('Usage ledger is unavailable');
222
247
  await store.settleWrites();
223
- const usage = await store.sessionUsageAsync(sessionUsageIds(sessionId, accountPool));
224
- return { sessionId, ...sessionUsageSnapshot(usage) };
248
+ const scopes = accountScopes(accountPool);
249
+ const usage = await store.sessionUsageAsync(sessionUsageIdsFor(scopes, sessionId));
250
+ const result = { sessionId, ...sessionUsageSnapshot(usage) };
251
+ const others = otherSessionIds(options, sessionId);
252
+ if (!others.length) return result;
253
+ const totals = await Promise.all(
254
+ others.map(async (id) => [id, sessionUsageSnapshot(await store.sessionUsageAsync(sessionUsageIdsFor(scopes, id)))])
255
+ );
256
+ return { ...result, sessions: Object.fromEntries(totals) };
225
257
  },
226
258
 
227
259
  /**