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
@@ -8,6 +8,7 @@
8
8
  * an unauthenticated lane fails closed.
9
9
  */
10
10
  import { hasAgentApiKey } from '../shared/provider-api-key.mjs';
11
+ import { ACCOUNT_PROVIDERS } from '../shared/provider-accounts.mjs';
11
12
  // Credential probes are file-level checks: the catalog must not drag the whole
12
13
  // provider graph in just to render lane availability.
13
14
  import {
@@ -64,6 +65,7 @@ const LANES = Object.freeze([
64
65
  image: Object.freeze({
65
66
  controls: Object.freeze({
66
67
  maxReferences: 5,
68
+ background: Object.freeze(['auto', 'transparent', 'opaque']),
67
69
  }),
68
70
  }),
69
71
  }),
@@ -100,6 +102,13 @@ const LANES = Object.freeze([
100
102
 
101
103
  const LANE_BY_ID = new Map(LANES.map((lane) => [lane.id, lane]));
102
104
 
105
+ /** The provider whose connected accounts a lane can generate through, or ''
106
+ * for a lane that authenticates with a single API key. */
107
+ export function mediaLaneAccountProvider(laneId) {
108
+ const provider = LANE_BY_ID.get(String(laneId || '').trim())?.auth.provider;
109
+ return ACCOUNT_PROVIDERS.includes(provider) ? provider : '';
110
+ }
111
+
103
112
  const OAUTH_PROBES = Object.freeze({
104
113
  'grok-oauth': hasGrokOAuthCredentials,
105
114
  'openai-oauth': hasOpenAIOAuthCredentials,
@@ -143,6 +152,9 @@ export function createMediaLaneCatalog({ loadModels = loadMediaModels, authentic
143
152
  authType: lane.auth.type,
144
153
  authProvider: lane.auth.provider,
145
154
  authenticated: signedIn,
155
+ // What the lane can generate once signed in; `kinds` lists only what its
156
+ // live catalog offers right now.
157
+ supportedKinds: MEDIA_KINDS.filter((kind) => lane[kind]),
146
158
  kinds: [],
147
159
  image: null,
148
160
  video: null,
@@ -31,7 +31,7 @@ export const TOOL_DEFS = [
31
31
  lane: {
32
32
  type: 'string',
33
33
  description:
34
- 'Lane id from list; omitted = the lane the user last chose for the kind (Studio selection or last generation), else the first signed-in lane.',
34
+ 'Lane id from list; pass it when the user names a source. Omitted = the lane the user last chose for the kind, else the default signed-in lane.',
35
35
  },
36
36
  model: {
37
37
  type: 'string',
@@ -44,10 +44,21 @@ export const TOOL_DEFS = [
44
44
  description:
45
45
  'generate: output file (png/jpg/mp4); relative to the project. status: copy a finished asset here.',
46
46
  },
47
- aspect: { type: 'string', description: 'Aspect ratio, e.g. 16:9, 9:16, 1:1; must be one the model lists.' },
48
- resolution: { type: 'string', description: 'Model resolution token from list (1k, 2k, 720p, 1080p).' },
47
+ aspect: {
48
+ type: 'string',
49
+ description: 'Aspect ratio, e.g. 16:9, 9:16, 1:1; only when the model lists aspectRatio, else omit.',
50
+ },
51
+ resolution: {
52
+ type: 'string',
53
+ description: 'Resolution token (1k, 2k, 720p, 1080p); only when the model lists it, else omit.',
54
+ },
49
55
  duration: { type: 'number', description: "video: seconds, within the model's listed durations." },
50
- quality: { type: 'string', description: 'Quality token when the model lists one.' },
56
+ quality: { type: 'string', description: 'Quality token; only when the model lists one, else omit.' },
57
+ background: {
58
+ type: 'string',
59
+ enum: ['auto', 'transparent', 'opaque'],
60
+ description: 'image: transparent for real alpha; only when the model lists background, else omit.',
61
+ },
51
62
  references: {
52
63
  type: 'array',
53
64
  items: { type: 'string' },
@@ -8,6 +8,7 @@ import { MEDIA_ACTIONS, MEDIA_KINDS } from './tool-defs.mjs';
8
8
  import { clean } from '../shared/clean.mjs';
9
9
 
10
10
  const POLL_MS = 750;
11
+ const DEFAULT_LANE = 'openai-oauth';
11
12
  const TIMEOUT_MS = Object.freeze({ image: 180_000, video: 900_000 });
12
13
  // OpenAI's image lane takes pixel sizes, not ratios; the placement still speaks in ratios.
13
14
  const OPENAI_SIZE = Object.freeze({
@@ -36,6 +37,7 @@ async function mediaGraph(deps) {
36
37
  jobs: await import('./jobs.mjs'),
37
38
  store: await import('./store.mjs'),
38
39
  defaults: await import('./defaults.mjs'),
40
+ accounts: await import('../shared/provider-auth-binding.mjs'),
39
41
  };
40
42
  return graph;
41
43
  }
@@ -130,8 +132,9 @@ export function listMediaCatalog(lanes, { kind = '', model = '' } = {}, remember
130
132
 
131
133
  /**
132
134
  * Lane for a generate: the requested one, else the lane the user last chose
133
- * for this kind (Studio selection or last generation), else the first
134
- * signed-in lane. `laneSource` tells the caller which of the three applied.
135
+ * for this kind (Studio selection or last generation), else the signed-in
136
+ * ChatGPT-subscription lane, else the first signed-in lane. `laneSource` is
137
+ * `first` for either default.
135
138
  */
136
139
  function pickLane(lanes, kind, requested, remembered = null) {
137
140
  const available = lanes.filter((lane) => lane.authenticated && lane.kinds.includes(kind));
@@ -153,9 +156,8 @@ function pickLane(lanes, kind, requested, remembered = null) {
153
156
  );
154
157
  }
155
158
  const rememberedLane = remembered?.lane ? available.find((entry) => entry.id === remembered.lane) : null;
156
- return rememberedLane
157
- ? { lane: rememberedLane, laneSource: 'remembered' }
158
- : { lane: available[0], laneSource: 'first' };
159
+ if (rememberedLane) return { lane: rememberedLane, laneSource: 'remembered' };
160
+ return { lane: available.find((entry) => entry.id === DEFAULT_LANE) || available[0], laneSource: 'first' };
159
161
  }
160
162
 
161
163
  function readRemembered(defaults, kind) {
@@ -166,6 +168,14 @@ function readRemembered(defaults, kind) {
166
168
  }
167
169
  }
168
170
 
171
+ function readPin(defaults, kind) {
172
+ try {
173
+ return defaults?.getMediaPin?.(kind) || null;
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+
169
179
  function allowed(controls, key) {
170
180
  const list = controls?.[key];
171
181
  return Array.isArray(list) && list.length ? list : null;
@@ -185,9 +195,13 @@ export function buildOptions(
185
195
  lane,
186
196
  kind,
187
197
  controls,
188
- { aspect = '', resolution = '', duration = null, quality = '' } = {}
198
+ { aspect = '', resolution = '', duration = null, quality = '', background = '' } = {}
189
199
  ) {
190
200
  const options = {};
201
+ if (background) {
202
+ validateChoice(controls, 'background', background, 'background');
203
+ if (background !== 'auto') options.background = background;
204
+ }
191
205
  if (lane.id === 'openai-oauth') {
192
206
  if (!allowed(controls, 'size')) {
193
207
  if ([aspect, resolution, quality].some((value) => value && value !== 'auto')) {
@@ -291,9 +305,21 @@ async function generate(args, { cwd, signal, deps, sessionId, sourceType }) {
291
305
  const requestedPath = clean(args.path);
292
306
  if (!requestedPath) throw new MediaToolError('generate requires path: where to write the file');
293
307
  const target = fullPath(requestedPath, cwd);
294
- const { lanes, jobs, store, defaults } = await mediaGraph(deps);
295
- const remembered = readRemembered(defaults, kind);
296
- const { lane, laneSource } = pickLane(await lanes.listMediaLanes(), kind, clean(args.lane), remembered);
308
+ const { lanes, jobs, store, defaults, accounts } = await mediaGraph(deps);
309
+ // A generator the chat names (lane or model) wins for this call; otherwise
310
+ // the pinned default for the kind applies, and with none the remembered
311
+ // choice / ordered default. A pin never falls back: its lane, model and
312
+ // account errors surface as they are.
313
+ const pin = clean(args.lane) || clean(args.model) ? null : readPin(defaults, kind);
314
+ const remembered = pin ? null : readRemembered(defaults, kind);
315
+ const accountProvider = pin?.account ? lanes.mediaLaneAccountProvider?.(pin.lane) || '' : '';
316
+ const listLanes = () =>
317
+ accountProvider
318
+ ? accounts.withProviderAccount(accountProvider, pin.account, () => lanes.listMediaLanes())
319
+ : lanes.listMediaLanes();
320
+ const picked = pickLane(await listLanes(), kind, pin ? pin.lane : clean(args.lane), remembered);
321
+ const { lane } = picked;
322
+ const laneSource = pin ? 'pinned' : picked.laneSource;
297
323
  const spec = lane[kind];
298
324
  // The remembered model only applies on the remembered lane and only while
299
325
  // that lane still lists it; otherwise the lane default is the safe choice.
@@ -301,7 +327,7 @@ async function generate(args, { cwd, signal, deps, sessionId, sourceType }) {
301
327
  laneSource === 'remembered' && remembered.model && spec.models.some((entry) => entry.id === remembered.model)
302
328
  ? remembered.model
303
329
  : '';
304
- const modelId = clean(args.model) || rememberedModel || spec.defaultModel;
330
+ const modelId = clean(args.model) || pin?.model || rememberedModel || spec.defaultModel;
305
331
  const model = modelControls(lane, kind, modelId);
306
332
  if (!model)
307
333
  throw new MediaToolError(`model "${modelId}" is not available on ${lane.id} for ${kind}`, {
@@ -312,6 +338,7 @@ async function generate(args, { cwd, signal, deps, sessionId, sourceType }) {
312
338
  resolution: clean(args.resolution),
313
339
  duration: args.duration ?? null,
314
340
  quality: clean(args.quality),
341
+ background: clean(args.background),
315
342
  });
316
343
  const references = await readReferences(args.references, cwd, model.controls);
317
344
  const started = await jobs.startMediaJob({
@@ -323,6 +350,7 @@ async function generate(args, { cwd, signal, deps, sessionId, sourceType }) {
323
350
  references,
324
351
  sessionId,
325
352
  sourceType,
353
+ ...(accountProvider ? { account: pin.account } : {}),
326
354
  });
327
355
  const base = { lane: lane.id, model: modelId, laneSource, options, referenceCount: references.length, prompt };
328
356
  if (args.wait === false) {
@@ -396,11 +424,12 @@ export async function executeMediaTool(
396
424
  ...listMediaCatalog(
397
425
  await lanes.listMediaLanes(),
398
426
  { kind, model: clean(args.model) },
399
- readRemembered(defaults, kind)
427
+ readPin(defaults, kind) || readRemembered(defaults, kind)
400
428
  ),
401
429
  });
402
430
  }
403
- if (action === 'generate') return mediaToolResult(await generate(args, { cwd, signal, deps, sessionId, sourceType }));
431
+ if (action === 'generate')
432
+ return mediaToolResult(await generate(args, { cwd, signal, deps, sessionId, sourceType }));
404
433
  if (action === 'status') return mediaToolResult(await status(args, { cwd, deps }));
405
434
  return mediaToolResult(await cancel(args, { deps }));
406
435
  } catch (error) {
@@ -9,20 +9,34 @@
9
9
  import { mediaError } from './lanes.mjs';
10
10
 
11
11
  const CREDIT_HINTS = /credit|spending limit|billing|quota|insufficient|payment/i;
12
+ // Subscription usage caps (ChatGPT plan windows), as opposed to short-lived
13
+ // rate limiting: retrying in a moment does not help until the window resets.
14
+ const USAGE_LIMIT = /usage_?limit/i;
12
15
 
13
- function reason(text) {
16
+ function parseJson(text) {
14
17
  try {
15
- const parsed = JSON.parse(text);
16
- const message = parsed?.error?.message || parsed?.error || parsed?.message;
17
- return typeof message === 'string' ? message : '';
18
+ return JSON.parse(text);
18
19
  } catch {
19
- return '';
20
+ return null;
20
21
  }
21
22
  }
22
23
 
24
+ function reason(text) {
25
+ const parsed = parseJson(text);
26
+ const message = parsed?.error?.message || parsed?.error || parsed?.message;
27
+ return typeof message === 'string' ? message : '';
28
+ }
29
+
30
+ // Raw bodies are only echoed when they are short plain text; HTML error pages
31
+ // and other markup never reach the Studio.
32
+ function rawDetail(text) {
33
+ const raw = String(text || '').trim();
34
+ return raw && !raw.startsWith('<') ? raw.slice(0, 300) : '';
35
+ }
36
+
23
37
  /** Build the error a lane throws for a non-OK upstream response. */
24
38
  export function upstreamError(label, status, text) {
25
- const detail = reason(text) || String(text || '').slice(0, 300);
39
+ const detail = reason(text) || rawDetail(text);
26
40
  if (status === 401 || status === 403) {
27
41
  if (CREDIT_HINTS.test(detail)) {
28
42
  return mediaError(`${label}: account has no usable balance — ${detail}`, 'MEDIA_BILLING_BLOCKED', status);
@@ -41,3 +55,55 @@ export function upstreamError(label, status, text) {
41
55
  }
42
56
  return mediaError(`${label} failed (${status})${detail ? `: ${detail}` : ''}`, 'MEDIA_UPSTREAM_FAILED', status);
43
57
  }
58
+
59
+ const header = (headers, name) => String(headers?.get?.(name) || '').trim();
60
+ const epochSeconds = (value) => (Number.isFinite(Number(value)) && Number(value) > 0 ? Math.trunc(Number(value)) : 0);
61
+
62
+ // Latest reset among the exhausted windows advertised in the rate-limit
63
+ // headers. The family is named after the active limit, with the plain codex
64
+ // family as the fallback the backend also sends.
65
+ function headerResetAt(headers, limitId) {
66
+ const families = new Set([limitId && `x-${limitId.toLowerCase().replace(/_/g, '-')}`, 'x-codex'].filter(Boolean));
67
+ let latest = 0;
68
+ for (const family of families) {
69
+ for (const window of ['primary', 'secondary']) {
70
+ const used = Number(header(headers, `${family}-${window}-used-percent`));
71
+ const resetAt = epochSeconds(header(headers, `${family}-${window}-reset-at`));
72
+ if (used >= 100 && resetAt > latest) latest = resetAt;
73
+ }
74
+ }
75
+ return latest || null;
76
+ }
77
+
78
+ /**
79
+ * Recognize a subscription usage-limit failure. `error` is the upstream error
80
+ * object (`{ type, code, resets_at }`), from an HTTP body or a stream event.
81
+ * Returns `{ limitId, resetsAt }` (epoch seconds or null), or null when the
82
+ * failure is something else.
83
+ */
84
+ export function usageLimitInfo(error, headers) {
85
+ const kinds = [error?.type, error?.code, header(headers, 'x-codex-rate-limit-reached-type')];
86
+ if (!kinds.some((kind) => typeof kind === 'string' && USAGE_LIMIT.test(kind))) return null;
87
+ const limitId = header(headers, 'x-codex-active-limit') || String(error?.limit_id || error?.metered_feature || '');
88
+ return { limitId, resetsAt: epochSeconds(error?.resets_at) || headerResetAt(headers, limitId) };
89
+ }
90
+
91
+ /** usageLimitInfo for a non-OK HTTP response; only 429s are usage limits. */
92
+ export function usageLimitFromResponse(status, text, headers) {
93
+ if (status !== 429) return null;
94
+ const parsed = parseJson(text);
95
+ return usageLimitInfo(parsed?.error && typeof parsed.error === 'object' ? parsed.error : parsed, headers);
96
+ }
97
+
98
+ function formatResetAt(seconds) {
99
+ return `${new Date(seconds * 1000).toISOString().slice(0, 16).replace('T', ' ')} UTC`;
100
+ }
101
+
102
+ /** The error a lane throws when the subscription's usage window is exhausted. */
103
+ export function usageLimitError(label, { limitId = '', resetsAt = null } = {}) {
104
+ const what = /image/i.test(limitId) ? 'image generation usage limit reached' : 'usage limit reached';
105
+ const when = resetsAt ? `resets ${formatResetAt(resetsAt)}` : 'try again after the usage window resets';
106
+ const err = mediaError(`${label}: ${what} — ${when}`, 'MEDIA_USAGE_LIMIT', 429);
107
+ if (resetsAt) err.resetsAt = new Date(resetsAt * 1000).toISOString();
108
+ return err;
109
+ }
@@ -532,6 +532,7 @@ const _httpRouter = createHttpRouter({
532
532
  _traceDb = v;
533
533
  },
534
534
  ingestTranscriptFile,
535
+ forgetTranscripts: _transcriptIngest.forgetTranscripts,
535
536
  getTranscriptOffset: (fp) => _transcriptIngest.getOffset(fp),
536
537
  parseTsToMs,
537
538
  refreshCoreMemoryFile: refreshCoreMemorySnapshot,
@@ -15,7 +15,14 @@ const INSERT_ENTRY = `
15
15
  RETURNING id
16
16
  `;
17
17
 
18
- export function createIngestHandler({ getDb, log, ingestTranscriptFile, getTranscriptOffset, parseTsToMs }) {
18
+ export function createIngestHandler({
19
+ getDb,
20
+ log,
21
+ ingestTranscriptFile,
22
+ forgetTranscripts,
23
+ getTranscriptOffset,
24
+ parseTsToMs,
25
+ }) {
19
26
  const entry = async (body, res) => {
20
27
  const db = getDb();
21
28
  const role = String(body.role ?? 'user');
@@ -89,9 +96,23 @@ export function createIngestHandler({ getDb, log, ingestTranscriptFile, getTrans
89
96
  }
90
97
  };
91
98
 
99
+ const forgetTranscript = async (body, res) => {
100
+ const filePaths = body.filePaths;
101
+ if (!Array.isArray(filePaths) || filePaths.some((filePath) => typeof filePath !== 'string' || !filePath)) {
102
+ sendJson(res, { error: 'filePaths required' }, 400);
103
+ return;
104
+ }
105
+ try {
106
+ sendJson(res, { ok: true, removed: await forgetTranscripts(filePaths) });
107
+ } catch (e) {
108
+ sendJson(res, { error: e.message }, 500);
109
+ }
110
+ };
111
+
92
112
  const routes = {
93
113
  '/entry': entry,
94
114
  '/ingest-transcript': ingestTranscript,
115
+ '/transcript/forget': forgetTranscript,
95
116
  '/transcript/ingest-sync': ingestSync,
96
117
  };
97
118
 
@@ -47,6 +47,8 @@ export function createTranscriptOffsets({ loadMeta, persistMeta, log }) {
47
47
  set: (transcriptPath, position) => {
48
48
  offsets.set(transcriptPath, position);
49
49
  },
50
+ /** Drop one file's read position; true when an entry existed. */
51
+ forget: (transcriptPath) => offsets.delete(transcriptPath),
50
52
  reset: () => {
51
53
  offsets = new Map();
52
54
  },
@@ -69,6 +69,7 @@ export function cwdFromTranscriptPath(fp) {
69
69
  * prefix envelopes, drops synthetic reference-files/compaction/ack/
70
70
  * internal-notification rows). */
71
71
  export function transcriptRowFromLine(parsed) {
72
+ if (parsed.memoryEligible === false) return null;
72
73
  const role =
73
74
  parsed.message?.role ?? (parsed.type === 'user' || parsed.type === 'assistant' ? parsed.type : undefined);
74
75
  if (role !== 'user' && role !== 'assistant') return null;
@@ -90,7 +90,9 @@ function installPoolErrorHandler(pool, label, { onConnectionLoss } = {}) {
90
90
  // db.transaction(async tx => …) → auto BEGIN/COMMIT, ROLLBACK on throw
91
91
 
92
92
  import { resolve } from 'node:path';
93
- import { ensurePgInstance as supervisorEnsure } from './supervisor.mjs';
93
+ import { ensurePgInstance as supervisorEnsure, stopOwnedPgForShutdown } from './supervisor.mjs';
94
+
95
+ export { installOwnedPgExitStop, pgClusterExists } from './supervisor.mjs';
94
96
 
95
97
  // ---------------------------------------------------------------------------
96
98
  // One-shot bootstrap guard — keyed by resolved dataDir (cluster-level, not schema)
@@ -164,6 +166,52 @@ export async function checkedConnect(pgPool, schema) {
164
166
  return client;
165
167
  }
166
168
 
169
+ // ---------------------------------------------------------------------------
170
+ // Durable-operation tracking — a shutdown lets these settle before PG stops
171
+ // ---------------------------------------------------------------------------
172
+
173
+ /** Schemas holding only data rebuilt from another source of truth: the
174
+ * session-search copy (re-ingested from the session files by its backfill)
175
+ * and trace diagnostics. Every other schema (scheduler, webhooks, memory)
176
+ * holds the only copy, so its in-flight operations are drained first. */
177
+ const DERIVED_SCHEMAS = new Set(['session_search', 'trace']);
178
+ const _durableInFlight = new Set();
179
+
180
+ function trackDurable(schema, run) {
181
+ if (DERIVED_SCHEMAS.has(schema)) return run();
182
+ const op = run();
183
+ _durableInFlight.add(op);
184
+ const settle = () => _durableInFlight.delete(op);
185
+ op.then(settle, settle);
186
+ return op;
187
+ }
188
+
189
+ /** In-flight operations on durable schemas right now. */
190
+ export function pendingDurablePgOps() {
191
+ return _durableInFlight.size;
192
+ }
193
+
194
+ /**
195
+ * Wait, bounded, until no durable-schema operation is in flight (including
196
+ * ones issued while waiting). Resolves true when drained, false at the bound.
197
+ */
198
+ export async function drainDurablePgOps({ timeoutMs = 0 } = {}) {
199
+ const deadline = Date.now() + Math.max(0, Number(timeoutMs) || 0);
200
+ while (_durableInFlight.size > 0) {
201
+ const remaining = deadline - Date.now();
202
+ if (remaining <= 0) return false;
203
+ let timer = null;
204
+ await Promise.race([
205
+ Promise.allSettled([..._durableInFlight]),
206
+ new Promise((resolveBound) => {
207
+ timer = setTimeout(resolveBound, remaining);
208
+ }),
209
+ ]);
210
+ clearTimeout(timer);
211
+ }
212
+ return true;
213
+ }
214
+
167
215
  // ---------------------------------------------------------------------------
168
216
  // native PG db shim
169
217
  // ---------------------------------------------------------------------------
@@ -253,6 +301,12 @@ function makeCompatDb(pgPool, schema, dataDir) {
253
301
  return currentPool();
254
302
  },
255
303
  };
304
+ // Every statement entry point is tracked, so a shutdown can let durable
305
+ // writes settle before it stops the cluster.
306
+ const { query, exec, transaction } = db;
307
+ db.query = (sql, params) => trackDurable(schema, () => query(sql, params));
308
+ db.exec = (sql) => trackDurable(schema, () => exec(sql));
309
+ db.transaction = (fn) => trackDurable(schema, () => transaction(fn));
256
310
  return db;
257
311
  }
258
312
 
@@ -522,3 +576,46 @@ export async function closePgInstance(dataDir, opts = {}) {
522
576
  } catch {}
523
577
  instances.delete(key);
524
578
  }
579
+
580
+ // ---------------------------------------------------------------------------
581
+ // shutdownOwnedPg — process exit: every pool, then the cluster this process owns
582
+ // ---------------------------------------------------------------------------
583
+
584
+ export const POOL_CLOSE_BOUND_MS = 500;
585
+
586
+ /**
587
+ * For a host whose stores start PostgreSQL (the daemon's schedules/webhooks/
588
+ * session-search): stop the cluster it ensured (supervisor
589
+ * stopOwnedPgForShutdown, `pg_ctl stop -m fast`) while every pool this process
590
+ * opened ends alongside — a pool waiting on a checked-out client never holds
591
+ * the stop back. The stop latches the supervisor first (synchronously), so a
592
+ * pooled client that sees fast shutdown terminate its backend cannot restart
593
+ * PG through connection-loss recovery; the pools are dropped from the cache,
594
+ * and their close is waited on only for a short bound after the stop.
595
+ */
596
+ export async function shutdownOwnedPg({ timeoutMs, drainMs = 0 } = {}) {
597
+ // Durable writes still in flight (schedule/webhook state) commit first,
598
+ // bounded by `drainMs`; derived writes (session search, trace) are not
599
+ // waited on — their sources rebuild them.
600
+ if (!(await drainDurablePgOps({ timeoutMs: drainMs }))) {
601
+ __mixdogMemoryLog(
602
+ `[pg-adapter] stopping PG with ${_durableInFlight.size} durable operation(s) still in flight after ${drainMs}ms\n`
603
+ );
604
+ }
605
+ const pools = [...instances.values()].map((inst) => inst.pool);
606
+ instances.clear();
607
+ const stopping = stopOwnedPgForShutdown({ timeoutMs });
608
+ const closing = Promise.allSettled(pools.map((pool) => pool.end()));
609
+ try {
610
+ return await stopping;
611
+ } finally {
612
+ let timer = null;
613
+ await Promise.race([
614
+ closing,
615
+ new Promise((resolveBound) => {
616
+ timer = setTimeout(resolveBound, POOL_CLOSE_BOUND_MS);
617
+ }),
618
+ ]);
619
+ clearTimeout(timer);
620
+ }
621
+ }
@@ -5,8 +5,11 @@ import { sleep as delay } from '../../../shared/sleep.mjs';
5
5
  //
6
6
  // Public API:
7
7
  // startPg({ runtimeDir, pgdataDir, port?, logPath? }) → { pid, port }
8
- // stopPg({ runtimeDir, pgdataDir }) → void
8
+ // stopPg({ runtimeDir, pgdataDir, timeoutMs? }) → void
9
9
  // healthcheckPg({ port, host? }) → boolean
10
+ //
11
+ // Every child on the start/stop path (initdb, pg_ctl start/reload/status/stop)
12
+ // runs async; only stopPgSync — a process 'exit' hook — may block.
10
13
 
11
14
  import {
12
15
  existsSync,
@@ -24,6 +27,7 @@ import { join } from 'node:path';
24
27
  import { execFile, spawn, spawnSync } from 'node:child_process';
25
28
  import { createConnection, createServer } from 'node:net';
26
29
  import { isPidAlive } from '../../../shared/pid-liveness.mjs';
30
+ import { runChild } from './run-child.mjs';
27
31
 
28
32
  // ---------------------------------------------------------------------------
29
33
  // Helpers
@@ -201,14 +205,12 @@ function ensureConfV2(pgdataDir) {
201
205
  // callers route through this rather than re-implementing the conf/reload pair.
202
206
  // Reload-compatible settings apply immediately; postmaster settings such as
203
207
  // max_connections apply on the next normal PG start (never restart live work).
204
- export function reconcileConfV2(runtimeDir, pgdataDir) {
208
+ export async function reconcileConfV2(runtimeDir, pgdataDir) {
205
209
  const applied = ensureConfV2(pgdataDir);
206
210
  if (!applied) return { applied: false, reloaded: false };
207
- const reload = spawnSync(pgBin(runtimeDir, 'pg_ctl'), ['reload', '-D', pgdataDir], {
211
+ const reload = await runChild(pgBin(runtimeDir, 'pg_ctl'), ['reload', '-D', pgdataDir], {
208
212
  env: libEnv(runtimeDir),
209
- stdio: 'pipe',
210
- timeout: 5_000,
211
- windowsHide: true,
213
+ timeoutMs: 5_000,
212
214
  });
213
215
  const reloaded = reload.status === 0;
214
216
  if (reloaded) {
@@ -238,7 +240,7 @@ async function attachExistingPostmaster({ runtimeDir, pgdataDir, existingWaitMs,
238
240
  __mixdogMemoryLog(`[pg-process] attaching to existing PG pid=${existing.pid} port=${existing.port}\n`);
239
241
  // Route through the single reconcile entry point so v1 → v2 conf
240
242
  // upgrades land on already-running instances without restart.
241
- if (v2Applied) reconcileConfV2(runtimeDir, pgdataDir);
243
+ if (v2Applied) await reconcileConfV2(runtimeDir, pgdataDir);
242
244
  return { pid: existing.pid, port: existing.port, attached: true };
243
245
  }
244
246
  if (existing.state === 'alive-not-ready') {
@@ -259,6 +261,10 @@ async function attachExistingPostmaster({ runtimeDir, pgdataDir, existingWaitMs,
259
261
  // default_transaction_isolation: native PG default is read committed.
260
262
  // Native PG does not default to serializable; set isolation level explicitly
261
263
  // so behaviour is unambiguous across PG major versions.
264
+ // Carries every versioned block ensureConfV2 checks for, so a fresh cluster
265
+ // already holds what later boots expect: none of them rewrites the conf and
266
+ // pg_ctl-reloads it (a postmaster-only setting such as shared_buffers cannot
267
+ // change by reload, and every such reload logged an error).
262
268
  function freshClusterConfAppend() {
263
269
  return (
264
270
  [
@@ -279,7 +285,8 @@ function freshClusterConfAppend() {
279
285
  ].join('\n') +
280
286
  '\n' +
281
287
  buildV2Block() +
282
- buildV3Block()
288
+ buildV3Block() +
289
+ buildV4Block()
283
290
  );
284
291
  }
285
292
 
@@ -290,14 +297,14 @@ function freshClusterConfAppend() {
290
297
  * user profile). Such a share dir is passed through an ASCII junction under
291
298
  * %ProgramData% that is removed afterwards.
292
299
  */
293
- export function withInitdbShareDir(runtimeDir, run) {
300
+ export async function withInitdbShareDir(runtimeDir, run) {
294
301
  const shareDir = join(runtimeDir, 'share');
295
302
  if (process.platform !== 'win32' || /^[\x20-\x7e]*$/.test(shareDir)) return run(null);
296
303
  const linkRoot = mkdtempSync(join(process.env.ProgramData, 'mixdog-initdb-'));
297
304
  const link = join(linkRoot, 'share');
298
305
  try {
299
306
  symlinkSync(shareDir, link, 'junction');
300
- return run(link);
307
+ return await run(link);
301
308
  } finally {
302
309
  // Cleanup must not replace initdb's own result or error. Both removals are
303
310
  // non-recursive, so the junction target (the runtime share) is never touched.
@@ -312,11 +319,11 @@ export function withInitdbShareDir(runtimeDir, run) {
312
319
  }
313
320
 
314
321
  /** initdb if pgdata is not yet initialised (no PG_VERSION file). */
315
- function initClusterIfNeeded({ runtimeDir, pgdataDir, env }) {
322
+ async function initClusterIfNeeded({ runtimeDir, pgdataDir, env }) {
316
323
  if (existsSync(join(pgdataDir, 'PG_VERSION'))) return;
317
324
  __mixdogMemoryLog(`[pg-process] initdb → ${pgdataDir}\n`);
318
- const r = withInitdbShareDir(runtimeDir, (shareDir) =>
319
- spawnSync(
325
+ const r = await withInitdbShareDir(runtimeDir, (shareDir) =>
326
+ runChild(
320
327
  pgBin(runtimeDir, 'initdb'),
321
328
  [
322
329
  '-D',
@@ -329,7 +336,7 @@ function initClusterIfNeeded({ runtimeDir, pgdataDir, env }) {
329
336
  '-U',
330
337
  'postgres',
331
338
  ],
332
- { env, stdio: 'pipe', windowsHide: true }
339
+ { env }
333
340
  )
334
341
  );
335
342
  if (r.status !== 0) {
@@ -435,12 +442,7 @@ async function startAndWaitReady({ pgctl, startArgs, env, pgdataDir, port }) {
435
442
  */
436
443
  async function attachRaceWinner({ pgdataDir, pgctl, env, existingWaitMs }) {
437
444
  __mixdogMemoryLog(`[pg-process] pg_ctl start: "another server might be running" — probing status\n`);
438
- const statusR = spawnSync(pgctl, ['status', '-D', pgdataDir], {
439
- env,
440
- stdio: 'pipe',
441
- timeout: 3_000,
442
- windowsHide: true,
443
- });
445
+ const statusR = await runChild(pgctl, ['status', '-D', pgdataDir], { env, timeoutMs: 3_000 });
444
446
  __mixdogMemoryLog(
445
447
  `[pg-process] pg_ctl status: ${statusR.stdout?.toString() || statusR.stderr?.toString() || 'no output'}\n`
446
448
  );
@@ -480,7 +482,7 @@ export async function startPg({
480
482
  if (attached) return attached;
481
483
 
482
484
  const pgctl = pgBin(runtimeDir, 'pg_ctl');
483
- initClusterIfNeeded({ runtimeDir, pgdataDir, env });
485
+ await initClusterIfNeeded({ runtimeDir, pgdataDir, env });
484
486
  // PostgreSQL requires a completely empty target on first init. Creating the
485
487
  // Spotlight marker before initdb makes every fresh macOS cluster fail with
486
488
  // "directory exists but is not empty"; add it only after initialization.
@@ -511,15 +513,18 @@ export async function startPg({
511
513
  // stopPg
512
514
  // ---------------------------------------------------------------------------
513
515
 
514
- export async function stopPg({ runtimeDir, pgdataDir }) {
516
+ // Bounded graceful stop. `-m fast` rolls back open transactions and
517
+ // disconnects clients; pg_ctl's own wait (-t, whole seconds) and the child
518
+ // timeout share `timeoutMs`, so a wedged stop rejects instead of holding a
519
+ // shutdown sequence open.
520
+ export async function stopPg({ runtimeDir, pgdataDir, timeoutMs = 15_000 }) {
515
521
  const pgctl = pgBin(runtimeDir, 'pg_ctl');
516
522
  const env = libEnv(runtimeDir);
523
+ const waitSeconds = Math.max(1, Math.ceil(timeoutMs / 1000));
517
524
 
518
- const r = spawnSync(pgctl, ['stop', '-m', 'fast', '-w', '-D', pgdataDir], {
525
+ const r = await runChild(pgctl, ['stop', '-m', 'fast', '-w', '-t', String(waitSeconds), '-D', pgdataDir], {
519
526
  env,
520
- stdio: 'pipe',
521
- timeout: 15_000,
522
- windowsHide: true,
527
+ timeoutMs: waitSeconds * 1000 + 1_000,
523
528
  });
524
529
 
525
530
  if (r.status !== 0) {
@@ -662,13 +667,11 @@ async function listPostmasterRows() {
662
667
  }
663
668
  const stdout = await execFileText('ps', ['-eo', 'pid=,etimes=,args='], { timeout: 15_000 });
664
669
  if (stdout === null) return [];
665
- return stdout
666
- .split(/\r?\n/)
667
- .flatMap((line) => {
668
- const match = line.match(/^\s*(\d+)\s+(\d+)\s+(.*postgres.*)$/);
669
- if (!match) return [];
670
- return [{ pid: Number(match[1]), uptimeSec: Number(match[2]), args: match[3] }];
671
- });
670
+ return stdout.split(/\r?\n/).flatMap((line) => {
671
+ const match = line.match(/^\s*(\d+)\s+(\d+)\s+(.*postgres.*)$/);
672
+ if (!match) return [];
673
+ return [{ pid: Number(match[1]), uptimeSec: Number(match[2]), args: match[3] }];
674
+ });
672
675
  }
673
676
 
674
677
  const PRISTINE_ROOT_PREFIX = 'mixdog-headless-pristine-';