mixdog 1.2.2 → 1.2.4

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 (692) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +6 -4
  4. package/scripts/lib/gate-scheduler.mjs +29 -11
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +599 -0
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/advisor/AGENT.md +1 -1
  9. package/src/agents/advisor/agent.json +1 -1
  10. package/src/agents/maintainer/AGENT.md +1 -1
  11. package/src/agents/maintainer/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +2 -4
  13. package/src/agents/security/AGENT.md +1 -2
  14. package/src/agents/writer/AGENT.md +2 -3
  15. package/src/defaults/shipped-history.json +11 -1
  16. package/src/defaults/skills/image/SKILL.md +21 -23
  17. package/src/defaults/skills/setup/SKILL.md +6 -1
  18. package/src/defaults/skills/setup/references/actions.md +44 -22
  19. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  20. package/src/headless-exec.mjs +15 -8
  21. package/src/lib/keychain-cjs.cjs +20 -15
  22. package/src/output-styles/common.md +11 -10
  23. package/src/rules/agent/AGENT.md +6 -4
  24. package/src/rules/lead/LEAD.md +7 -9
  25. package/src/rules/shared/45-destructive.md +4 -0
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  28. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  29. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  30. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  31. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  32. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  33. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  35. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  36. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
  41. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  42. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
  43. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  45. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
  46. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  48. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  49. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  50. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  51. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  52. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  53. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
  56. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  58. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
  59. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  60. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
  61. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
  63. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  65. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +39 -5
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
  76. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
  77. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -6
  78. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  79. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  80. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  81. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +29 -5
  82. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  83. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
  84. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
  85. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  86. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  88. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
  89. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
  90. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
  92. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
  93. package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
  94. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  96. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  97. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  98. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +253 -42
  99. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  100. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  101. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +392 -0
  102. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  103. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  104. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  105. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  106. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  107. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +50 -22
  108. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
  109. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  110. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  112. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  113. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +92 -16
  114. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
  115. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
  117. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  118. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -7
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +155 -0
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
  128. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  129. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +183 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  138. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  140. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  141. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  142. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +28 -5
  143. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  144. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  145. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  147. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  148. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  150. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  151. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
  153. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  154. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
  155. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
  156. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  157. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -36
  158. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  159. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  160. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  161. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -9
  162. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
  163. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
  164. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
  165. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
  166. package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
  167. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
  168. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  169. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  170. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +164 -0
  171. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -0
  172. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  173. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +195 -0
  174. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
  175. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  176. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
  177. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  178. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  179. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  180. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  181. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  182. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  183. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +16 -3
  184. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  186. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  187. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  188. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +178 -71
  189. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
  190. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  191. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  192. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  193. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  194. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  195. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  196. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
  197. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  198. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  199. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
  200. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  201. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  202. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
  203. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  204. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  205. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  206. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  207. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  208. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
  209. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  210. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  211. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  212. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -1
  213. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  215. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  216. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -27
  217. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  219. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  220. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
  221. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
  222. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
  223. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  224. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  225. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
  226. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  227. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  228. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  229. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +29 -5
  230. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  231. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
  232. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
  233. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  234. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  235. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
  236. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  237. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
  238. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  239. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  240. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +11 -0
  241. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
  242. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  243. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  244. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  245. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  246. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  247. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
  248. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  249. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  250. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
  251. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
  252. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  253. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
  254. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  255. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
  256. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  257. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  258. package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
  259. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  260. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  261. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
  262. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  263. package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
  264. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
  265. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  266. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  267. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  269. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  270. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  271. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  272. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
  273. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  274. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  275. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  276. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  277. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
  278. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  279. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  280. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  281. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
  282. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  283. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  284. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  285. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
  286. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  287. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  288. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  289. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  290. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
  291. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  292. package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
  293. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
  294. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
  295. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  296. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  297. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  298. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  299. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +79 -0
  300. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  301. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  302. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  303. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  304. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  305. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  306. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  307. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  308. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
  309. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  310. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  311. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  312. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  313. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  314. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  315. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  316. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
  317. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  318. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  319. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  320. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  321. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  322. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  323. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  324. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  325. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  326. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  327. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  328. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  329. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  330. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  331. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  332. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  333. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  334. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  335. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  336. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  337. package/src/runtime/attachments/store.d.mts +9 -0
  338. package/src/runtime/attachments/store.mjs +80 -9
  339. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  340. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  341. package/src/runtime/computer-bridge/action-schema.mjs +219 -196
  342. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  343. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  344. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  345. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  346. package/src/runtime/github/tool.mjs +208 -17
  347. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  348. package/src/runtime/media/catalog.mjs +4 -4
  349. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  350. package/src/runtime/media/defaults.mjs +37 -0
  351. package/src/runtime/media/jobs.mjs +12 -2
  352. package/src/runtime/media/lanes.mjs +12 -0
  353. package/src/runtime/media/tool-defs.mjs +15 -4
  354. package/src/runtime/media/tool.mjs +41 -12
  355. package/src/runtime/media/upstream-error.mjs +72 -6
  356. package/src/runtime/memory/index.mjs +1 -0
  357. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  358. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  359. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  360. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  361. package/src/runtime/memory/lib/pg/process.mjs +36 -33
  362. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  363. package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
  364. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  365. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  366. package/src/runtime/office/README.md +1 -1
  367. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  368. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  369. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  370. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  371. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  372. package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
  373. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  374. package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
  375. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  376. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  377. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  378. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  379. package/src/runtime/office/core/office-sessions.mjs +5 -0
  380. package/src/runtime/office/core/office-transactions.mjs +3 -0
  381. package/src/runtime/office/core/office-write-ledger.mjs +94 -0
  382. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  383. package/src/runtime/office/index.mjs +29 -0
  384. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  385. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  386. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  387. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  388. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  389. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  390. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  391. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  392. package/src/runtime/shared/atomic-file.d.mts +1 -1
  393. package/src/runtime/shared/background-tasks.mjs +6 -1
  394. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  395. package/src/runtime/shared/bounded-line-diff.mjs +191 -0
  396. package/src/runtime/shared/browser-launch.mjs +15 -0
  397. package/src/runtime/shared/buffered-appender.mjs +18 -0
  398. package/src/runtime/shared/config.mjs +78 -18
  399. package/src/runtime/shared/err-text.mjs +48 -4
  400. package/src/runtime/shared/file-lock.mjs +6 -5
  401. package/src/runtime/shared/file-permissions.d.mts +6 -1
  402. package/src/runtime/shared/file-permissions.mjs +54 -6
  403. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  404. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  405. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  406. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  407. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  408. package/src/runtime/shared/loopback-listener.mjs +9 -0
  409. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  410. package/src/runtime/shared/model-route-chain.mjs +48 -0
  411. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  412. package/src/runtime/shared/pid-liveness.mjs +12 -0
  413. package/src/runtime/shared/provider-api-key.mjs +8 -0
  414. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  415. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  416. package/src/runtime/shared/quiet-progress.mjs +101 -0
  417. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  418. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  419. package/src/runtime/shared/remote-intent.mjs +2 -42
  420. package/src/runtime/shared/review-diff.mjs +52 -0
  421. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  422. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  423. package/src/runtime/shared/slow-span.mjs +121 -0
  424. package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
  425. package/src/runtime/shared/tool-card-model/card-header.mjs +7 -1
  426. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  427. package/src/runtime/shared/tool-card-model.mjs +5 -2
  428. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  429. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  430. package/src/runtime/shared/tool-primitives.mjs +13 -0
  431. package/src/runtime/shared/tool-result-summary.mjs +22 -1
  432. package/src/runtime/shared/tool-status.mjs +3 -2
  433. package/src/runtime/shared/tool-surface.mjs +20 -6
  434. package/src/runtime/shared/tool-work-units.mjs +54 -11
  435. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  436. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  437. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  438. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  439. package/src/runtime/shared/transcript-writer.mjs +24 -6
  440. package/src/runtime/shared/turn-changes.mjs +269 -100
  441. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  442. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  443. package/src/runtime/shared/turn-snapshot.mjs +865 -683
  444. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  445. package/src/runtime/shared/user-data-guard.mjs +262 -49
  446. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  447. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  448. package/src/runtime/shared/worktrees/carry.mjs +533 -0
  449. package/src/runtime/shared/worktrees/contract.mjs +60 -0
  450. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  451. package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
  452. package/src/runtime/shared/worktrees/git-head.mjs +214 -0
  453. package/src/runtime/shared/worktrees/git.mjs +8 -3
  454. package/src/runtime/shared/worktrees/include.mjs +125 -7
  455. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  456. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  457. package/src/runtime/shared/worktrees/manager.mjs +525 -31
  458. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  459. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  460. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  461. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  462. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  463. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  464. package/src/runtime/terminal-bridge/client.mjs +57 -20
  465. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  466. package/src/runtime/tidy/apply.mjs +47 -2
  467. package/src/runtime/tidy/run-engines.mjs +11 -5
  468. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  469. package/src/session-runtime/boot/apis.mjs +20 -6
  470. package/src/session-runtime/boot/config.mjs +2 -0
  471. package/src/session-runtime/boot/facade.mjs +4 -0
  472. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  473. package/src/session-runtime/boot/session.mjs +3 -3
  474. package/src/session-runtime/boot/tools.mjs +7 -1
  475. package/src/session-runtime/conversation-import/service.mjs +1 -1
  476. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  477. package/src/session-runtime/goal-facade-api.mjs +2 -2
  478. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
  479. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  480. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
  481. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
  482. package/src/session-runtime/internal-tool-executor.mjs +8 -2
  483. package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
  484. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  485. package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
  486. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  487. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
  488. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  489. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  490. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  491. package/src/session-runtime/lifecycle/teardown.mjs +70 -14
  492. package/src/session-runtime/lifecycle-api.mjs +1 -0
  493. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  494. package/src/session-runtime/media-api.mjs +8 -0
  495. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  496. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  497. package/src/session-runtime/model-route/set-route.mjs +116 -36
  498. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  499. package/src/session-runtime/model-route-api.mjs +4 -2
  500. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  501. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  502. package/src/session-runtime/native-web-search.mjs +19 -9
  503. package/src/session-runtime/new-session-config.mjs +4 -2
  504. package/src/session-runtime/provider-auth/login.mjs +4 -0
  505. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  506. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  507. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  508. package/src/session-runtime/provider-models.mjs +1 -0
  509. package/src/session-runtime/provider-usage.mjs +4 -0
  510. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  511. package/src/session-runtime/route-resolution.mjs +3 -1
  512. package/src/session-runtime/runtime-core.mjs +4 -0
  513. package/src/session-runtime/runtime-facade.mjs +6 -0
  514. package/src/session-runtime/runtime-review-api.mjs +8 -2
  515. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  516. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  517. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  518. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  519. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  520. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  521. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  522. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  523. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  524. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  525. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  526. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  527. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  528. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  529. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  530. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
  531. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  532. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  533. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  534. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  535. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  536. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  537. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  538. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  539. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  540. package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
  541. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  542. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  543. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  544. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  545. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  546. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  547. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  548. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  549. package/src/session-runtime/services/agent-tool/worker-index.mjs +74 -15
  550. package/src/session-runtime/services/agent-tool.mjs +7 -0
  551. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  552. package/src/session-runtime/services/channel-admin.mjs +19 -3
  553. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  554. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  555. package/src/session-runtime/services/provider-admin.mjs +158 -15
  556. package/src/session-runtime/session-create/session-options.mjs +7 -5
  557. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  558. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  559. package/src/session-runtime/session-transcript.mjs +4 -5
  560. package/src/session-runtime/session-turn-api.mjs +17 -14
  561. package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
  562. package/src/session-runtime/setup-tool/executor.mjs +57 -9
  563. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  564. package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
  565. package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
  566. package/src/session-runtime/skills-api.mjs +3 -5
  567. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  568. package/src/session-runtime/tool-surface.mjs +5 -1
  569. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  570. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  571. package/src/session-runtime/turn/session-ops.mjs +7 -5
  572. package/src/session-runtime/turn/side-question-ops.mjs +19 -0
  573. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
  574. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
  575. package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
  576. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  577. package/src/session-runtime/turn/turn-run.mjs +26 -45
  578. package/src/session-runtime/usage-stats-api.mjs +46 -11
  579. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  580. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  581. package/src/session-runtime/workspace/project-branches.mjs +35 -41
  582. package/src/session-runtime/workspace/transition-steps.mjs +215 -116
  583. package/src/session-runtime/workspace/transitions.mjs +428 -73
  584. package/src/standalone/channel-transport.mjs +3 -4
  585. package/src/standalone/daemon-agent-control.mjs +9 -1
  586. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  587. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  588. package/src/standalone/daemon-owner.mjs +17 -4
  589. package/src/standalone/daemon-pg-stop.mjs +49 -0
  590. package/src/standalone/daemon-session-control.mjs +88 -0
  591. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  592. package/src/standalone/daemon-stop-budget.mjs +18 -0
  593. package/src/standalone/daemon-stored-session-views.mjs +25 -3
  594. package/src/standalone/daemon-telemetry.mjs +19 -0
  595. package/src/standalone/daemon.mjs +63 -1
  596. package/src/standalone/desktop-service-registry.mjs +5 -0
  597. package/src/standalone/local-session-runtime.mjs +80 -30
  598. package/src/standalone/session-client.mjs +42 -0
  599. package/src/standalone/session-protocol.mjs +14 -0
  600. package/src/standalone/session-proxy/projection.mjs +41 -4
  601. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  602. package/src/standalone/session-runtime-inline-host.mjs +3 -0
  603. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  604. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  605. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  606. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  607. package/src/standalone/session-service/agent-tree.mjs +28 -2
  608. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  609. package/src/standalone/session-service/entries.mjs +1 -0
  610. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  611. package/src/standalone/session-service/quota-resume.mjs +28 -13
  612. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  613. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  614. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  615. package/src/standalone/session-service-api.mjs +6 -1
  616. package/src/standalone/session-state-patch.d.mts +2 -1
  617. package/src/standalone/session-state-patch.mjs +41 -1
  618. package/src/standalone/session-tool-output.mjs +82 -0
  619. package/src/tui/App.jsx +25 -0
  620. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  621. package/src/tui/app/app-view.jsx +2 -1
  622. package/src/tui/app/btw-controller.mjs +118 -0
  623. package/src/tui/app/create-app-pickers.mjs +2 -0
  624. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  625. package/src/tui/app/provider-setup-picker.mjs +15 -3
  626. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  627. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  628. package/src/tui/app/slash-commands.mjs +19 -3
  629. package/src/tui/app/slash-dispatch/session-commands.mjs +68 -6
  630. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  631. package/src/tui/app/use-global-key-input.mjs +5 -12
  632. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  633. package/src/tui/components/BtwPanel.jsx +53 -0
  634. package/src/tui/components/QuestionPanel.jsx +275 -0
  635. package/src/tui/components/Spinner.jsx +4 -0
  636. package/src/tui/components/SpinnerByline.jsx +21 -2
  637. package/src/tui/components/question-panel-model.mjs +156 -0
  638. package/src/tui/components/status-line/local-line.mjs +10 -2
  639. package/src/tui/dist/index.mjs +2897 -1722
  640. package/src/tui/session/active-tool-summary.mjs +1 -1
  641. package/src/tui/session/context-state.mjs +4 -5
  642. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  643. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  644. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  645. package/src/tui/session/quota-resume.mjs +140 -61
  646. package/src/tui/session/session-api/commands.mjs +14 -10
  647. package/src/tui/session/session-api/controls.mjs +14 -2
  648. package/src/tui/session/session-api/integrations.mjs +9 -2
  649. package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
  650. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  651. package/src/tui/session/session-api/lifecycle.mjs +14 -11
  652. package/src/tui/session/session-api/media.mjs +2 -0
  653. package/src/tui/session/session-api/routes.mjs +81 -57
  654. package/src/tui/session/session-api/settings.mjs +9 -3
  655. package/src/tui/session/session-api/worktree.mjs +3 -2
  656. package/src/tui/session/session-api.mjs +1 -0
  657. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  658. package/src/tui/session/session-flow/drain.mjs +6 -4
  659. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  660. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  661. package/src/tui/session/session-flow/queue.mjs +1 -1
  662. package/src/tui/session/tool-approval.mjs +20 -8
  663. package/src/tui/session/transcript-spill.mjs +14 -7
  664. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  665. package/src/tui/session/tui-steering-persist.mjs +3 -5
  666. package/src/tui/session/turn-quiet.mjs +53 -0
  667. package/src/tui/session/turn-stream.mjs +179 -32
  668. package/src/tui/session/turn.mjs +50 -36
  669. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  670. package/src/tui/spinner-meta.mjs +10 -0
  671. package/src/tui/spinner-verbs.mjs +3 -0
  672. package/src/ui/statusline.mjs +13 -3
  673. package/src/workflows/default/WORKFLOW.md +3 -1
  674. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  675. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  676. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  677. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
  678. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  679. package/src/session-runtime/turn/share-ops.mjs +0 -77
  680. package/src/tui/session/cross-surface-share.mjs +0 -406
  681. package/src/tui/session/live-share/delta.mjs +0 -153
  682. package/src/tui/session/live-share/mirror.mjs +0 -106
  683. package/src/tui/session/live-share/owner.mjs +0 -254
  684. package/src/tui/session/live-share/retry.mjs +0 -54
  685. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  686. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  687. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  688. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  689. package/src/tui/session/live-share/viewer.mjs +0 -99
  690. package/src/tui/session/live-share/wire.mjs +0 -44
  691. package/src/tui/session/live-share.mjs +0 -154
  692. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -6,7 +6,11 @@
6
6
  */
7
7
  import { stampStreamOutcome, STREAM_TRANSPORTS } from '../lib/stream-outcome.mjs';
8
8
  import { createLeakGuard, createToolCallDedupe } from '../lib/leaked-toolcall.mjs';
9
- import { emitCompatToolCallOnce, synthLeakedOpenAICall } from '../openai-compat-stream-common.mjs';
9
+ import {
10
+ emitCompatToolCallOnce,
11
+ failingFinishReasonError,
12
+ synthLeakedOpenAICall,
13
+ } from '../openai-compat-stream-common.mjs';
10
14
  import { chatCompletionUsage } from '../openai-compat-response-normalization.mjs';
11
15
  import { noteAbandonedUsage } from '../../../../shared/llm/usage-context.mjs';
12
16
  import { createToolCallAccumulator } from './tool-call-acc.mjs';
@@ -31,6 +35,8 @@ export function createCompatStreamState({
31
35
  content: '',
32
36
  reasoningContent: '',
33
37
  sawReasoningContent: false,
38
+ // Where the last reasoning text came from: a delta field name or 'content_chunks'.
39
+ reasoningSource: null,
34
40
  reasoningDetails: [],
35
41
  // Both text and reasoning exposure prohibit resampling the request.
36
42
  emittedText: false,
@@ -43,6 +49,7 @@ export function createCompatStreamState({
43
49
  streamEmitState: { emittedToolCallKeys: new Set(), emittedToolCall: false, _toolDedupe: toolDedupe },
44
50
  leakGuard: createLeakGuard({ knownToolNames, harmony: true }),
45
51
  leakedCalls: [],
52
+ pendingLeakedCalls: [],
46
53
  };
47
54
  }
48
55
 
@@ -71,16 +78,41 @@ export function appendText(state, text) {
71
78
  }
72
79
  }
73
80
 
74
- function dispatchLeakedCall(state, recovered) {
81
+ /** A length-truncated or content-filtered turn is a partial result:
82
+ * normalizeCompatChatResponse rejects it, so no tool call of it may execute. */
83
+ export function isIncompleteFinishReason(finishReason) {
84
+ return finishReason === 'length' || finishReason === 'content_filter';
85
+ }
86
+
87
+ /** Whether `finish_reason` confirms a normal end of the turn: present, not an
88
+ * incomplete outcome and not a gateway-reported failure (network_error/error). */
89
+ export function isNormalFinishReason(finishReason) {
90
+ return (
91
+ Boolean(finishReason) && !isIncompleteFinishReason(finishReason) && !failingFinishReasonError(finishReason, '')
92
+ );
93
+ }
94
+
95
+ /** Dispatch held leaked calls once a normal finish_reason confirms the turn
96
+ * ended. Otherwise they stay on `leakedCalls` (partial tool calls) and never
97
+ * reach the executor. */
98
+ export function drainLeakedCalls(state) {
99
+ if (!isNormalFinishReason(state.stopReason)) return;
100
+ for (const call of state.pendingLeakedCalls.splice(0)) {
101
+ emitCompatToolCallOnce(state.streamEmitState, call, state.onToolCall);
102
+ }
103
+ }
104
+
105
+ function recordLeakedCall(state, recovered) {
75
106
  const call = synthLeakedOpenAICall(recovered);
76
- emitCompatToolCallOnce(state.streamEmitState, call, state.onToolCall);
107
+ state.pendingLeakedCalls.push(call);
77
108
  reportProgress(state, 'tool');
78
109
  return call;
79
110
  }
80
111
 
81
112
  function relayGuarded(state, { text, calls }) {
82
113
  if (text) appendText(state, text);
83
- for (const c of calls) state.leakedCalls.push(dispatchLeakedCall(state, c));
114
+ for (const c of calls) state.leakedCalls.push(recordLeakedCall(state, c));
115
+ drainLeakedCalls(state);
84
116
  }
85
117
 
86
118
  /** Route a text delta through the leak guard, dispatching rescued calls. */
@@ -113,9 +145,9 @@ export function noteReportedUsage(state) {
113
145
  }
114
146
 
115
147
  /** Keep the partial output on the error for upstream salvage: the text, the
116
- * recovered leaked calls already dispatched (native calls only dispatch once
117
- * the stream finishes) and whether a native call's arguments were still
118
- * streaming. */
148
+ * recovered leaked calls (none dispatched unless a normal finish_reason
149
+ * arrived; native calls only dispatch once the stream finishes) and whether a
150
+ * native call's arguments were still streaming. */
119
151
  export function attachPartial(state, err) {
120
152
  try {
121
153
  err.partialContent = state.content;
@@ -35,15 +35,8 @@ export function mergeToolCallDelta(acc, deltaCalls) {
35
35
  if (tc.id) prev.id = tc.id;
36
36
  if (tc.type) prev.type = tc.type;
37
37
  if (tc.function?.name && !prev.function.name) prev.function.name = tc.function.name;
38
- if (tc.function?.arguments) {
39
- const delta = tc.function.arguments;
40
- // Preserve support for providers that repeat cumulative arguments.
41
- if (prev.function.arguments && delta.startsWith(prev.function.arguments)) {
42
- prev.function.arguments = delta;
43
- } else {
44
- prev.function.arguments += delta;
45
- }
46
- }
38
+ // Argument fragments are deltas: always append, never infer snapshots.
39
+ if (tc.function?.arguments) prev.function.arguments += tc.function.arguments;
47
40
  }
48
41
  }
49
42
 
@@ -11,6 +11,7 @@ import {
11
11
  PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS,
12
12
  createTimeoutSignal,
13
13
  } from '../stall-policy.mjs';
14
+ import { TIMEOUT_PHASE } from '../../../shared/provider-timeout-phase.mjs';
14
15
  import {
15
16
  closeCompatStream,
16
17
  markErrorLiveTextEmitted,
@@ -86,6 +87,10 @@ export async function consumeCompatChatCompletionStream(
86
87
  }
87
88
  if (state.leakGuard.enabled) flushLeak(state);
88
89
  } catch (err) {
90
+ // The first-byte window (not a caller cancellation) ended the wait for the first chunk.
91
+ if (!signal?.aborted && err && typeof err === 'object' && err === firstByteTimeout.signal.reason) {
92
+ err.timeoutPhase = TIMEOUT_PHASE.FIRST_CHUNK;
93
+ }
89
94
  // Keep exposed partial text without permitting the request to replay;
90
95
  // every mid-flight failure carries what the stream completed (a
91
96
  // cancellation keeps the caller's own reason untouched).
@@ -14,7 +14,7 @@ function resetAtFrom(wire, now) {
14
14
  if (wire?.resets_in_seconds != null && Number.isFinite(inSeconds) && inSeconds >= 0) {
15
15
  return now + Math.ceil(inSeconds * 1000);
16
16
  }
17
- const raw = wire?.resets_at ?? wire?.reset_at;
17
+ const raw = wire?.resets_at ?? wire?.reset_at ?? wire?.metadata?.resets_at;
18
18
  if (raw == null || raw === '') return null;
19
19
  const numeric = Number(raw);
20
20
  if (Number.isFinite(numeric) && numeric > 0) return numeric < 1e12 ? Math.round(numeric * 1000) : Math.round(numeric);
@@ -2,12 +2,51 @@ import { resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
2
2
  import { enrichModels } from './model-catalog.mjs';
3
3
  import { sanitizeModelList } from './model-list-sanitize.mjs';
4
4
  import { PROVIDER_GENERATE_TOTAL_TIMEOUT_MS, createTimeoutSignal, resolveTimeoutMs } from '../stall-policy.mjs';
5
+ import { CUSTOM_EFFORT_LEVELS, normalizeCustomEffort } from './custom-reasoning.mjs';
5
6
 
6
7
  const MODEL_LIST_TIMEOUT_MS = resolveTimeoutMs('MIXDOG_COMPAT_MODEL_LIST_TIMEOUT_MS', 10_000, {
7
8
  minMs: 1_000,
8
9
  maxMs: PROVIDER_GENERATE_TOTAL_TIMEOUT_MS,
9
10
  });
10
11
 
12
+ /** Preserve endpoint-declared effort levels without inventing a default ladder. */
13
+ export function extractCompatReasoningEffort(model) {
14
+ if (!model || typeof model !== 'object') return null;
15
+ const rawLevels = [
16
+ model.reasoning_efforts,
17
+ model.reasoning_levels,
18
+ model.reasoningLevels,
19
+ model.capabilities?.reasoning_efforts,
20
+ model.capabilities?.reasoning_effort,
21
+ ].find(Array.isArray);
22
+ if (rawLevels) {
23
+ const declared = new Set(
24
+ rawLevels
25
+ .map((level) => (typeof level === 'string' ? level : level?.value))
26
+ .filter((level) => typeof level === 'string')
27
+ .map(normalizeCustomEffort)
28
+ .filter(Boolean)
29
+ );
30
+ const levels = CUSTOM_EFFORT_LEVELS.filter((level) => declared.has(level));
31
+ if (levels.length > 0) {
32
+ return {
33
+ supportsReasoning: levels.some((level) => level !== 'none'),
34
+ reasoningLevels: levels,
35
+ reasoningOptions: [{ type: 'effort', values: [...levels] }],
36
+ };
37
+ }
38
+ return null;
39
+ }
40
+ if (
41
+ model.supports_reasoning_effort === true ||
42
+ model.capabilities?.reasoning_effort === true ||
43
+ model.capabilities?.reasoning_efforts === true
44
+ ) {
45
+ return { supportsReasoning: true };
46
+ }
47
+ return null;
48
+ }
49
+
11
50
  // `keyless` omits the Authorization header entirely (keyless endpoints);
12
51
  // `signal` aborts the request together with the list timeout.
13
52
  export async function fetchCompatModelItems(provider, { signal = null, keyless = false } = {}) {
@@ -34,6 +73,25 @@ export async function fetchCompatModelItems(provider, { signal = null, keyless =
34
73
  }
35
74
  }
36
75
 
76
+ // Provider-native chat-ness: Together `type`, Mistral `capabilities`. Returns a
77
+ // sanitize-compatible mode, or null when the listing says nothing.
78
+ function nativeMode(m) {
79
+ const type = typeof m?.type === 'string' ? m.type.trim().toLowerCase() : '';
80
+ if (type === 'chat') return 'chat';
81
+ if (type === 'language' || type === 'code') return 'completion';
82
+ if (['embedding', 'embeddings', 'image', 'audio', 'rerank', 'moderation', 'video', 'transcribe'].includes(type)) {
83
+ return type;
84
+ }
85
+ // OpenRouter: a model that cannot emit text (image/audio generation) is no chat model.
86
+ const outputs = m?.architecture?.output_modalities;
87
+ if (Array.isArray(outputs) && outputs.length && !outputs.includes('text')) return 'non_chat';
88
+ const caps = m?.capabilities;
89
+ if (caps && typeof caps === 'object' && typeof caps.completion_chat === 'boolean') {
90
+ return caps.completion_chat ? 'chat' : 'non_chat';
91
+ }
92
+ return null;
93
+ }
94
+
37
95
  export async function listCompatModels(provider, { throwOnError = false, signal = null } = {}) {
38
96
  try {
39
97
  const list = await provider._fetchModelItems({ signal });
@@ -45,10 +103,20 @@ export async function listCompatModels(provider, { throwOnError = false, signal
45
103
  m?.max_input_tokens ??
46
104
  m?.max_model_len ??
47
105
  m?.context_length ??
106
+ m?.max_context_length ??
107
+ m?.top_provider?.context_length ??
48
108
  m?.contextWindow ??
49
109
  0
50
110
  );
51
- const outputTokens = Number(m?.max_output_tokens ?? m?.output_tokens ?? m?.maxOutputTokens ?? 0);
111
+ const outputTokens = Number(
112
+ m?.max_output_tokens ?? m?.output_tokens ?? m?.maxOutputTokens ?? m?.top_provider?.max_completion_tokens ?? 0
113
+ );
114
+ const mode = nativeMode(m);
115
+ // A catalog alias (OpenRouter `~anthropic/claude-opus-latest`) keeps its
116
+ // own slug for routing; the slug it currently points at is retained for
117
+ // capability lookup only.
118
+ const aliasTarget = typeof m?.alias_target === 'string' ? m.alias_target : m?.alias_target?.slug;
119
+ const effortInfo = extractCompatReasoningEffort(m);
52
120
  models.push({
53
121
  id: m?.id,
54
122
  name: m?.id,
@@ -56,10 +124,24 @@ export async function listCompatModels(provider, { throwOnError = false, signal
56
124
  contextWindow: Number.isFinite(contextWindow) && contextWindow > 0 ? contextWindow : 0,
57
125
  outputTokens: Number.isFinite(outputTokens) && outputTokens > 0 ? outputTokens : null,
58
126
  created: typeof m?.created === 'number' ? m.created : null,
127
+ ...(mode ? { mode } : {}),
128
+ ...(typeof aliasTarget === 'string' && aliasTarget ? { aliasTarget } : {}),
129
+ ...(effortInfo || {}),
59
130
  });
60
131
  }
61
132
  const filtered = models.filter((m) => m.id);
62
- const enriched = sanitizeModelList(await enrichModels(filtered), { provider: provider.name });
133
+ // The catalog fills gaps only: native limits and chat-ness are restored
134
+ // over whatever enrichment derived.
135
+ const enrichedRows = (await enrichModels(filtered)).map((row, i) => {
136
+ const native = filtered[i];
137
+ return {
138
+ ...row,
139
+ ...(native.contextWindow ? { contextWindow: native.contextWindow } : {}),
140
+ ...(native.outputTokens ? { outputTokens: native.outputTokens } : {}),
141
+ ...(native.mode ? { mode: native.mode } : {}),
142
+ };
143
+ });
144
+ const enriched = sanitizeModelList(enrichedRows, { provider: provider.name });
63
145
  provider._enrichedModels = enriched;
64
146
  return enriched;
65
147
  } catch (error) {
@@ -12,6 +12,41 @@ function normalizeReasoningEffort(value, allowed) {
12
12
  return allowed.includes(effort) ? effort : null;
13
13
  }
14
14
 
15
+ /**
16
+ * OpenRouter's unified `reasoning` field, shared by its Chat and Responses
17
+ * wires: `openRouterReasoningEffort`, else the turn effort, else the configured
18
+ * effort; `none` disables reasoning. Null when no effort applies.
19
+ */
20
+ export function openRouterReasoning(opts = {}, config = {}) {
21
+ const effort = normalizeReasoningEffort(opts.openRouterReasoningEffort ?? opts.effort ?? config?.reasoningEffort, [
22
+ 'none',
23
+ 'minimal',
24
+ 'low',
25
+ 'medium',
26
+ 'high',
27
+ 'xhigh',
28
+ 'max',
29
+ ]);
30
+ if (effort === 'none') return { enabled: false };
31
+ return effort ? { enabled: true, effort } : null;
32
+ }
33
+
34
+ function deepseekRawEffort(opts, config) {
35
+ return opts.deepseekReasoningEffort ?? opts.effort ?? config?.reasoningEffort;
36
+ }
37
+
38
+ /** 'enabled' | 'disabled' as the DeepSeek request will carry it, or null when nothing sets it. */
39
+ export function deepseekThinkingMode(opts = {}, config = {}) {
40
+ const rawThinking = opts.deepseekThinking ?? opts.thinking ?? config?.thinking;
41
+ const rawEffort = deepseekRawEffort(opts, config);
42
+ if (rawThinking === undefined && rawEffort === undefined) return null;
43
+ const thinkingMode = String(rawThinking?.type ?? rawThinking ?? rawEffort)
44
+ .trim()
45
+ .toLowerCase();
46
+ const disabled = rawThinking === false || thinkingMode === 'disabled' || thinkingMode === 'none';
47
+ return disabled ? 'disabled' : 'enabled';
48
+ }
49
+
15
50
  // Keep provider extensions isolated: fields accepted by one OpenAI-compatible
16
51
  // backend are frequently rejected by another even when the core Chat schema
17
52
  // is shared.
@@ -23,22 +58,14 @@ export function applyCompatProviderChatOptions(params, providerName, opts = {},
23
58
  protocol: 'openai-chat',
24
59
  model: modelInfo,
25
60
  effort: opts.effort ?? config?.reasoningEffort,
61
+ baseURL: config?.baseURL,
26
62
  });
27
63
  Object.assign(params, fields);
28
64
  return params;
29
65
  }
30
66
  if (providerName === 'openrouter') {
31
- const effort = normalizeReasoningEffort(opts.openRouterReasoningEffort ?? opts.effort ?? config?.reasoningEffort, [
32
- 'none',
33
- 'minimal',
34
- 'low',
35
- 'medium',
36
- 'high',
37
- 'xhigh',
38
- 'max',
39
- ]);
40
- if (effort === 'none') params.reasoning = { enabled: false };
41
- else if (effort) params.reasoning = { enabled: true, effort };
67
+ const reasoning = openRouterReasoning(opts, config);
68
+ if (reasoning) params.reasoning = reasoning;
42
69
  return params;
43
70
  }
44
71
  if (providerName === 'xai') {
@@ -53,22 +80,17 @@ export function applyCompatProviderChatOptions(params, providerName, opts = {},
53
80
  return params;
54
81
  }
55
82
  if (providerName === 'deepseek') {
56
- const rawThinking = opts.deepseekThinking ?? opts.thinking ?? config?.thinking;
57
- const rawEffort = opts.deepseekReasoningEffort ?? opts.effort ?? config?.reasoningEffort;
58
- if (rawThinking !== undefined || rawEffort !== undefined) {
59
- const thinkingMode = String(rawThinking?.type ?? rawThinking ?? rawEffort)
60
- .trim()
61
- .toLowerCase();
62
- const disabled = rawThinking === false || thinkingMode === 'disabled' || thinkingMode === 'none';
63
- params.thinking = { type: disabled ? 'disabled' : 'enabled' };
64
- if (!disabled) {
65
- const effort = String(rawEffort ?? '')
83
+ const mode = deepseekThinkingMode(opts, config);
84
+ if (mode) {
85
+ params.thinking = { type: mode };
86
+ if (mode === 'enabled') {
87
+ const effort = String(deepseekRawEffort(opts, config) ?? '')
66
88
  .trim()
67
89
  .toLowerCase();
68
- if (effort === 'max') params.reasoning_effort = 'max';
69
- // DeepSeek documents low/high/max; `medium` is its own alias for
70
- // high, and `low` is a real level that must not be promoted.
71
- else if (effort === 'low') params.reasoning_effort = 'low';
90
+ // DeepSeek documents low/high/max; `ultra` is its alias for max,
91
+ // `minimal` for low, `medium`/`xhigh` for high; `low` must not be promoted.
92
+ if (effort === 'max' || effort === 'ultra') params.reasoning_effort = 'max';
93
+ else if (effort === 'low' || effort === 'minimal') params.reasoning_effort = 'low';
72
94
  else if (['medium', 'high', 'xhigh'].includes(effort)) params.reasoning_effort = 'high';
73
95
  }
74
96
  }
@@ -11,12 +11,16 @@ export const OPENAI_COMPAT_PRESETS = {
11
11
  },
12
12
  // OpenCode Go - low-cost coding-model subscription gateway.
13
13
  'opencode-go': {
14
- baseURL: 'https://opencode.ai/zen/go/v1',
14
+ baseURL: 'https://opencode.ai/inference/go/v1',
15
15
  defaultModel: 'glm-5.2',
16
+ // The gateway expects an application User-Agent (not the SDK default).
17
+ extraHeaders: { 'User-Agent': 'mixdog' },
16
18
  },
17
19
  openrouter: {
18
20
  baseURL: 'https://openrouter.ai/api/v1',
19
21
  defaultModel: 'openrouter/auto',
22
+ // OpenRouter documents cache_control on Chat content blocks.
23
+ chatCacheControl: true,
20
24
  extraHeaders: {
21
25
  'HTTP-Referer': 'https://github.com/tribgames/mixdog',
22
26
  'X-OpenRouter-Title': 'mixdog',
@@ -0,0 +1,155 @@
1
+ /**
2
+ * openai-compat-reasoning-field.mjs — provider-specific reasoning shapes on the
3
+ * Chat Completions wire that the plain `reasoning_content` string path misses.
4
+ *
5
+ * Together AI (docs.together.ai/docs/inference/chat/reasoning): the chain of
6
+ * thought arrives on `reasoning` OR `reasoning_content` (model dependent), on
7
+ * the message and on each streaming delta, and must be passed back "under the
8
+ * same key" on prior assistant turns. vLLM reports it on `reasoning` (formerly
9
+ * `reasoning_content`), Groq on `message.reasoning` (reasoning_format parsed).
10
+ * OpenRouter reports plain text on `reasoning` next to `reasoning_details`.
11
+ *
12
+ * Mistral (docs.mistral.ai/studio/conversations/reasoning): with reasoning on,
13
+ * `message.content` / `delta.content` is a list of typed chunks —
14
+ * `{type:'thinking', thinking:[{type:'text', text}]}` and `{type:'text', text}`
15
+ * — and the full assistant message, thinking chunk included, goes back in the
16
+ * history. Receiving is by the response shape (an array), never by model name.
17
+ */
18
+
19
+ /** `message.providerMetadata[key].reasoningField`: the key a reply's reasoning arrived on. */
20
+ export const COMPAT_REASONING_METADATA_KEY = 'openaiCompat';
21
+
22
+ const TOGETHER_HOSTS = ['together.xyz', 'together.ai'];
23
+ const GROQ_HOSTS = ['groq.com'];
24
+ const MISTRAL_HOSTS = ['mistral.ai'];
25
+
26
+ function hostMatches(baseURL, domains) {
27
+ let host;
28
+ try {
29
+ host = new URL(String(baseURL || '')).hostname.toLowerCase();
30
+ } catch {
31
+ return false;
32
+ }
33
+ return domains.some((domain) => host === domain || host.endsWith(`.${domain}`));
34
+ }
35
+
36
+ export function isTogetherBaseURL(baseURL) {
37
+ return hostMatches(baseURL, TOGETHER_HOSTS);
38
+ }
39
+
40
+ /**
41
+ * Where an endpoint family reports reasoning and how a prior turn's reasoning
42
+ * goes back. `readsReasoningAlias`: the `reasoning` key is a reasoning field
43
+ * (otherwise only `reasoning_content` is). `resend`:
44
+ * same_key — back under the key it arrived on (Together, vLLM)
45
+ * reasoning — plain text as `reasoning`; reasoning_details win (OpenRouter)
46
+ * content_chunks — as a `thinking` chunk in the assistant content (Mistral)
47
+ * none — never echoed; the docs do not ask for it (Groq)
48
+ */
49
+ const SHAPES = Object.freeze({
50
+ together: Object.freeze({ id: 'together', readsReasoningAlias: true, resend: 'same_key' }),
51
+ vllm: Object.freeze({ id: 'vllm', readsReasoningAlias: true, resend: 'same_key' }),
52
+ groq: Object.freeze({ id: 'groq', readsReasoningAlias: true, resend: 'none' }),
53
+ mistral: Object.freeze({ id: 'mistral', readsReasoningAlias: false, resend: 'content_chunks' }),
54
+ openrouter: Object.freeze({ id: 'openrouter', readsReasoningAlias: true, resend: 'reasoning' }),
55
+ });
56
+
57
+ /**
58
+ * The reasoning shape of a provider, or null for the plain `reasoning_content`
59
+ * path. OpenRouter is by provider name, Together/Groq/Mistral by the provider's
60
+ * own base URL, vLLM (no fixed host) by the model row's `vllm` wire format.
61
+ */
62
+ export function compatReasoningShape({ providerName, baseURL, wireFormat } = {}) {
63
+ if (providerName === 'openrouter') return SHAPES.openrouter;
64
+ if (wireFormat === 'together' || isTogetherBaseURL(baseURL)) return SHAPES.together;
65
+ if (wireFormat === 'vllm') return SHAPES.vllm;
66
+ if (hostMatches(baseURL, GROQ_HOSTS)) return SHAPES.groq;
67
+ if (hostMatches(baseURL, MISTRAL_HOSTS)) return SHAPES.mistral;
68
+ return null;
69
+ }
70
+
71
+ /**
72
+ * The receive field worth recording for replay: `reasoning` (non-default key)
73
+ * or `content_chunks` (Mistral), per shape; `reasoning_content` is the default
74
+ * and needs no record. Null when nothing needs remembering.
75
+ */
76
+ export function replayReasoningField(shape, source) {
77
+ if (!shape) return null;
78
+ if (shape.resend === 'same_key' && source === 'reasoning') return 'reasoning';
79
+ if (shape.resend === 'content_chunks' && source === 'content_chunks') return 'content_chunks';
80
+ return null;
81
+ }
82
+
83
+ /** Whether a reply's reasoning source is captured under this shape. */
84
+ export function capturesShapeReasoning(shape, source) {
85
+ if (!shape) return source === 'content_chunks';
86
+ if (source === 'content_chunks') return true;
87
+ return source === 'reasoning_content' || (shape.readsReasoningAlias && source === 'reasoning');
88
+ }
89
+
90
+ /** Assistant content with the prior reasoning replayed as a leading `thinking` chunk. */
91
+ export function contentWithThinkingChunk(content, reasoning) {
92
+ const thinking = { type: 'thinking', thinking: [{ type: 'text', text: reasoning }] };
93
+ if (Array.isArray(content)) return [thinking, ...content];
94
+ return typeof content === 'string' && content ? [thinking, { type: 'text', text: content }] : [thinking];
95
+ }
96
+
97
+ function thinkingText(thinking) {
98
+ if (typeof thinking === 'string') return thinking;
99
+ if (!Array.isArray(thinking)) return '';
100
+ return thinking
101
+ .map((inner) => {
102
+ if (typeof inner === 'string') return inner;
103
+ return typeof inner?.text === 'string' ? inner.text : '';
104
+ })
105
+ .join('');
106
+ }
107
+
108
+ /**
109
+ * Ordered `{kind:'reasoning'|'text', text}` parts of an array-shaped `content`,
110
+ * or null when `content` is not an array (the plain string/absent shape).
111
+ */
112
+ export function chatContentParts(content) {
113
+ if (!Array.isArray(content)) return null;
114
+ const parts = [];
115
+ for (const chunk of content) {
116
+ if (typeof chunk === 'string') {
117
+ parts.push({ kind: 'text', text: chunk });
118
+ } else if (chunk?.type === 'thinking') {
119
+ parts.push({ kind: 'reasoning', text: thinkingText(chunk.thinking) });
120
+ } else if (chunk?.type === 'text' && typeof chunk.text === 'string') {
121
+ parts.push({ kind: 'text', text: chunk.text });
122
+ }
123
+ }
124
+ return parts;
125
+ }
126
+
127
+ /**
128
+ * Content text, reasoning and reasoning source of one non-streaming message.
129
+ * `reasoning_content` keeps priority; the `reasoning` alias is read only under
130
+ * a shape that reports reasoning there; thinking chunks fill in when no field
131
+ * carried reasoning.
132
+ */
133
+ export function readChatMessage(message, { shape = null } = {}) {
134
+ const parts = chatContentParts(message?.content);
135
+ let content;
136
+ if (parts) {
137
+ content = parts
138
+ .filter((part) => part.kind === 'text')
139
+ .map((part) => part.text)
140
+ .join('');
141
+ } else {
142
+ content = typeof message?.content === 'string' ? message.content : '';
143
+ }
144
+ if (typeof message?.reasoning_content === 'string') {
145
+ return { content, reasoningContent: message.reasoning_content, reasoningSource: 'reasoning_content' };
146
+ }
147
+ if (shape?.readsReasoningAlias && typeof message?.reasoning === 'string') {
148
+ return { content, reasoningContent: message.reasoning, reasoningSource: 'reasoning' };
149
+ }
150
+ const thinking = parts?.filter((part) => part.kind === 'reasoning');
151
+ if (thinking?.length) {
152
+ return { content, reasoningContent: thinking.map((part) => part.text).join(''), reasoningSource: 'content_chunks' };
153
+ }
154
+ return { content, reasoningContent: null, reasoningSource: null };
155
+ }
@@ -7,20 +7,20 @@ import {
7
7
  writeXaiResponsesCacheTrace,
8
8
  } from './openai-compat-xai.mjs';
9
9
  import { createProviderReplay } from './lib/provider-replay.mjs';
10
+ import { reportedCostUsd } from './lib/usage-primitives.mjs';
10
11
  import { stampStreamOutcome, STREAM_TRANSPORTS } from './lib/stream-outcome.mjs';
11
12
  import { failingFinishReasonError } from './openai-compat-stream-common.mjs';
12
-
13
- const reportedNumber = (value) =>
14
- value == null || (typeof value === 'string' && value.trim() === '') ? Number.NaN : Number(value);
13
+ import {
14
+ COMPAT_REASONING_METADATA_KEY,
15
+ capturesShapeReasoning,
16
+ replayReasoningField,
17
+ } from './openai-compat-reasoning-field.mjs';
15
18
 
16
19
  export function compatReportedCostUsd(providerName, usage) {
17
- if (providerName === 'openrouter') {
18
- const cost = reportedNumber(usage?.cost);
19
- return Number.isFinite(cost) && cost >= 0 ? cost : undefined;
20
- }
20
+ if (providerName === 'openrouter') return reportedCostUsd(usage?.cost);
21
21
  if (providerName === 'xai') {
22
- const ticks = reportedNumber(usage?.cost_in_usd_ticks);
23
- return Number.isFinite(ticks) && ticks >= 0 ? Number((ticks * 1e-10).toFixed(8)) : undefined;
22
+ const ticks = reportedCostUsd(usage?.cost_in_usd_ticks);
23
+ return ticks === undefined ? undefined : Number((ticks * 1e-10).toFixed(8));
24
24
  }
25
25
  return undefined;
26
26
  }
@@ -79,12 +79,11 @@ export function traceCompatResponseUsage({
79
79
  });
80
80
  }
81
81
 
82
- // Responses-wire reported cost: a gateway `cost` (decimal USD) when present,
83
- // else xAI ticks. null/empty/negative is "not reported", never a reported $0.
82
+ // Responses-wire reported cost: xAI `cost_in_usd_ticks` when present, else a
83
+ // gateway `cost` (decimal USD). null/empty/negative is "not reported", never a
84
+ // reported $0.
84
85
  export function responsesReportedCostUsd(usage) {
85
- const cost = reportedNumber(usage?.cost);
86
- if (Number.isFinite(cost) && cost >= 0) return cost;
87
- return costUsdFromTicks(usage?.cost_in_usd_ticks);
86
+ return costUsdFromTicks(usage?.cost_in_usd_ticks) ?? reportedCostUsd(usage?.cost);
88
87
  }
89
88
 
90
89
  export function chatCompletionUsage(providerName, usage) {
@@ -138,6 +137,7 @@ export function normalizeCompatChatResponse({
138
137
  cacheRoutingKey,
139
138
  cacheRouting,
140
139
  replaysReasoningContent,
140
+ reasoningShape = null,
141
141
  }) {
142
142
  const response = assembled.response;
143
143
  const choice = response.choices[0];
@@ -146,7 +146,7 @@ export function normalizeCompatChatResponse({
146
146
  const failingFinish = failingFinishReasonError(stopReason, providerName);
147
147
  if (failingFinish) {
148
148
  const err = failingFinish;
149
- const partialContent = choice?.message?.content || '';
149
+ const partialContent = assembled.content || '';
150
150
  Object.assign(err, {
151
151
  partialContent,
152
152
  partialToolCalls: Array.isArray(toolCalls) && toolCalls.length ? toolCalls : undefined,
@@ -173,7 +173,7 @@ export function normalizeCompatChatResponse({
173
173
  code: 'PROVIDER_INCOMPLETE',
174
174
  providerIncomplete: true,
175
175
  finishReason: stopReason,
176
- partialContent: choice?.message?.content || '',
176
+ partialContent: assembled.content || '',
177
177
  partialToolCalls: toolCalls,
178
178
  model: response.model || useModel,
179
179
  responseId: response.id || null,
@@ -205,14 +205,28 @@ export function normalizeCompatChatResponse({
205
205
  cachedTokens: extractCompatCachedTokens(response.usage),
206
206
  });
207
207
  }
208
+ // Together/vLLM/Groq/OpenRouter report reasoning on `reasoning` or
209
+ // `reasoning_content`; Mistral reports it as thinking chunks inside
210
+ // `content`. Both are captured by the provider's own shape / the response
211
+ // shape, whatever the replay flag says.
212
+ const reasoningField = replayReasoningField(reasoningShape, assembled.reasoningSource);
208
213
  const capturesReasoningContent =
209
- providerName === 'deepseek' || providerName === 'xai' || providerName === 'mixdog-local' || replaysReasoningContent;
214
+ providerName === 'deepseek' ||
215
+ providerName === 'xai' ||
216
+ providerName === 'mixdog-local' ||
217
+ replaysReasoningContent ||
218
+ capturesShapeReasoning(reasoningShape, assembled.reasoningSource);
210
219
  const reasoningContent =
211
220
  capturesReasoningContent && typeof assembled.reasoningContent === 'string' ? assembled.reasoningContent : null;
212
221
  const reasoningDetails =
213
222
  providerName === 'openrouter' && Array.isArray(choice?.message?.reasoning_details)
214
223
  ? choice.message.reasoning_details
215
224
  : null;
225
+ // Replay sends reasoning back under the field it arrived on.
226
+ const providerMetadata = {
227
+ ...(reasoningDetails?.length ? { openrouter: { reasoning_details: reasoningDetails } } : {}),
228
+ ...(reasoningContent !== null && reasoningField ? { [COMPAT_REASONING_METADATA_KEY]: { reasoningField } } : {}),
229
+ };
216
230
  return {
217
231
  content: assembled.content || '',
218
232
  // Streamed chunks can omit `model`; fall back to the requested
@@ -228,11 +242,7 @@ export function normalizeCompatChatResponse({
228
242
  // instead of silently treating a truncated answer as complete.
229
243
  ...(stopReason === 'length' && (assembled.content || '').length > 0 ? { truncated: true } : {}),
230
244
  ...(reasoningContent !== null ? { reasoningContent } : {}),
231
- ...(reasoningDetails?.length
232
- ? {
233
- providerMetadata: { openrouter: { reasoning_details: reasoningDetails } },
234
- }
235
- : {}),
245
+ ...(Object.keys(providerMetadata).length ? { providerMetadata } : {}),
236
246
  usage: response.usage ? chatCompletionUsage(providerName, response.usage) : undefined,
237
247
  };
238
248
  }
@@ -332,8 +342,14 @@ export function normalizeXaiResponsesWebSocket({
332
342
  cacheLane,
333
343
  }) {
334
344
  const responseId = result.responseId || previousResponseId || null;
335
- const encryptedReasoningItems = encryptedXaiReasoningItems(result.responseItems);
336
- const providerReplay = createProviderReplay('xai-responses', result.responseItems);
345
+ // The WS send result drops the collector's `responseItems`; its own
346
+ // owner-tagged `providerReplay` (traceProvider 'xai') still carries every
347
+ // output item in order: encrypted reasoning and server-executed tool_search
348
+ // call/output pairs. Always taken, so they survive to the next turn as xAI
349
+ // requires.
350
+ const responseItems = result.responseItems ?? result.providerReplay?.items;
351
+ const encryptedReasoningItems = encryptedXaiReasoningItems(responseItems);
352
+ const providerReplay = createProviderReplay('xai-responses', responseItems);
337
353
  const encryptedReasoningHistory = xaiEncryptedReasoningHistory(opts, messages, encryptedReasoningItems);
338
354
  const rawUsage = result.usage?.raw || result.usage || null;
339
355
  const response = {