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
@@ -1,4 +1,4 @@
1
- import { GITHUB_ACTIONS } from './contract.mjs';
1
+ import { DEFAULT_GITHUB_HOSTNAME, GITHUB_ACTIONS } from './contract.mjs';
2
2
  import { executeGithubRequest } from './client.mjs';
3
3
  import { GITHUB_OUTPUT_MAX_BYTES } from '../shared/tool-output-limit.mjs';
4
4
  import { persistToolResultArtifactSync } from '../agent/orchestrator/session/tool-result-offload.mjs';
@@ -6,19 +6,19 @@ import { normalizeOutputPath } from '../agent/orchestrator/tools/builtin/path-ut
6
6
 
7
7
  // Model-facing reduction only; executeGithubRequest (also used by Desktop)
8
8
  // keeps the raw REST response, and the agent's copy is preserved as `raw`.
9
- const KEPT_URL_KEYS = new Set([
10
- 'html_url',
11
- 'browser_download_url',
12
- 'diff_url',
13
- 'patch_url',
14
- 'clone_url',
15
- 'ssh_url',
16
- 'tarball_url',
17
- 'zipball_url',
18
- 'target_url',
19
- 'details_url',
9
+ // html_url is the one page link the model can hand to a user; the asset,
10
+ // status and check links are the only other URLs not derivable from ids.
11
+ const KEPT_URL_KEYS = new Set(['html_url', 'browser_download_url', 'target_url', 'details_url']);
12
+ const DROPPED_KEYS = new Set([
13
+ 'url',
14
+ 'node_id',
15
+ '_links',
16
+ 'gravatar_id',
17
+ 'performed_via_github_app',
18
+ 'author_association',
19
+ 'sub_issues_summary',
20
+ 'issue_dependencies_summary',
20
21
  ]);
21
- const DROPPED_KEYS = new Set(['node_id', '_links', 'gravatar_id']);
22
22
  const USER_KEYS = new Set([
23
23
  'user',
24
24
  'owner',
@@ -55,12 +55,195 @@ function reduceGithubData(value, key, parentKey) {
55
55
  if (isNestedRepository(key, parentKey) && typeof value.full_name === 'string') return value.full_name;
56
56
  const reduced = {};
57
57
  for (const [name, item] of Object.entries(value)) {
58
- if (DROPPED_KEYS.has(name) || (name.endsWith('_url') && !KEPT_URL_KEYS.has(name))) continue;
58
+ if (DROPPED_KEYS.has(name) || name.endsWith('node_id') || (name.endsWith('_url') && !KEPT_URL_KEYS.has(name))) {
59
+ continue;
60
+ }
61
+ // Numbered objects (issues, PRs, milestones) are addressed by number; their id is noise.
62
+ if (name === 'id' && typeof value.number === 'number') continue;
63
+ if (name === 'reactions' && isEmptyReactions(item)) continue;
59
64
  reduced[name] = reduceGithubData(item, name, key);
60
65
  }
61
66
  return reduced;
62
67
  }
63
68
 
69
+ function isEmptyReactions(value) {
70
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
71
+ return Object.values(value).every((item) => typeof item !== 'number' || item === 0);
72
+ }
73
+
74
+ const EXCERPT_MAX = 140;
75
+ const day = (value) => (typeof value === 'string' ? value.slice(0, 10) : undefined);
76
+ const login = (value) => userLogin(value) ?? (typeof value === 'string' ? value : undefined);
77
+
78
+ function excerpt(body) {
79
+ if (typeof body !== 'string') return undefined;
80
+ const text = body.replace(/\s+/g, ' ').trim();
81
+ if (!text) return undefined;
82
+ return text.length > EXCERPT_MAX ? `${text.slice(0, EXCERPT_MAX - 1)}…` : text;
83
+ }
84
+
85
+ function labelNames(labels) {
86
+ const names = (Array.isArray(labels) ? labels : [])
87
+ .map((label) => (typeof label === 'string' ? label : label?.name))
88
+ .filter(Boolean);
89
+ return names.length ? names : undefined;
90
+ }
91
+
92
+ // Compact per-row projections for *.list actions: only what picks the next item
93
+ // to open. Undefined fields are dropped by JSON.stringify.
94
+ const LIST_PROJECTORS = {
95
+ 'issue.list': (item) => ({
96
+ number: item.number,
97
+ title: item.title,
98
+ state: item.state,
99
+ author: login(item.user),
100
+ updated: day(item.updated_at),
101
+ labels: labelNames(item.labels),
102
+ comments: item.comments || undefined,
103
+ excerpt: excerpt(item.body),
104
+ }),
105
+ 'pr.list': (item) => ({
106
+ number: item.number,
107
+ title: item.title,
108
+ state: item.merged_at ? 'merged' : item.state,
109
+ draft: item.draft || undefined,
110
+ author: login(item.user),
111
+ updated: day(item.updated_at),
112
+ head: item.head?.ref,
113
+ base: item.base?.ref,
114
+ labels: labelNames(item.labels),
115
+ excerpt: excerpt(item.body),
116
+ }),
117
+ 'repo.list': (item) => ({
118
+ name: item.full_name,
119
+ description: excerpt(item.description),
120
+ visibility: item.visibility || (item.private ? 'private' : 'public'),
121
+ language: item.language || undefined,
122
+ fork: item.fork || undefined,
123
+ archived: item.archived || undefined,
124
+ updated: day(item.pushed_at || item.updated_at),
125
+ }),
126
+ 'run.list': (item) => ({
127
+ id: item.id,
128
+ name: item.display_title || item.name,
129
+ workflow: item.name,
130
+ status: item.status,
131
+ conclusion: item.conclusion || undefined,
132
+ branch: item.head_branch,
133
+ event: item.event,
134
+ actor: login(item.actor),
135
+ updated: day(item.updated_at),
136
+ }),
137
+ 'release.list': (item) => ({
138
+ id: item.id,
139
+ tag: item.tag_name,
140
+ name: item.name || undefined,
141
+ draft: item.draft || undefined,
142
+ prerelease: item.prerelease || undefined,
143
+ author: login(item.author),
144
+ published: day(item.published_at || item.created_at),
145
+ }),
146
+ 'notification.list': (item) => ({
147
+ id: item.id,
148
+ unread: item.unread,
149
+ reason: item.reason,
150
+ type: item.subject?.type,
151
+ title: item.subject?.title,
152
+ number: Number(/\/(?:issues|pulls)\/(\d+)$/.exec(item.subject?.url || '')?.[1]) || undefined,
153
+ repo: typeof item.repository === 'string' ? item.repository : item.repository?.full_name,
154
+ updated: day(item.updated_at),
155
+ }),
156
+ 'workflow.list': (item) => ({ id: item.id, name: item.name, path: item.path, state: item.state }),
157
+ };
158
+
159
+ function projectList(action, data) {
160
+ const project = LIST_PROJECTORS[action];
161
+ return project && Array.isArray(data) ? data.map(project) : undefined;
162
+ }
163
+
164
+ const BODY_MAX = 1500;
165
+
166
+ function bodyText(body) {
167
+ if (typeof body !== 'string') return undefined;
168
+ const text = body.replace(/\r\n/g, '\n').trim();
169
+ if (!text) return undefined;
170
+ if (text.length <= BODY_MAX) return text;
171
+ const cut = /[\ud800-\udbff]/.test(text[BODY_MAX - 1]) ? BODY_MAX - 1 : BODY_MAX;
172
+ return `${text.slice(0, cut)}… ${text.length - cut} more chars in raw`;
173
+ }
174
+
175
+ function logins(list) {
176
+ const names = (Array.isArray(list) ? list : []).map(login).filter(Boolean);
177
+ return names.length ? names : undefined;
178
+ }
179
+
180
+ const stamp = (value) => (typeof value === 'string' ? value : undefined);
181
+ const repoName = (repo) => (typeof repo === 'string' ? repo : repo?.full_name);
182
+
183
+ // Single-item projections: the decision fields of one issue/PR. Nulls that
184
+ // mean "not yet" (open PR closed_at) are dropped; `mergeable`/`mergeable_state`
185
+ // stay as returned because null there means GitHub is still computing.
186
+ const VIEW_PROJECTORS = {
187
+ 'pr.view': (pr) => ({
188
+ number: pr.number,
189
+ title: pr.title,
190
+ state: pr.state,
191
+ draft: pr.draft,
192
+ merged: pr.merged,
193
+ mergeable: pr.mergeable,
194
+ mergeable_state: pr.mergeable_state,
195
+ user: login(pr.user),
196
+ labels: labelNames(pr.labels),
197
+ assignees: logins(pr.assignees),
198
+ requested_reviewers: logins(pr.requested_reviewers),
199
+ head: pr.head && { ref: pr.head.ref, sha: pr.head.sha, repo: repoName(pr.head.repo) },
200
+ base: pr.base && { ref: pr.base.ref, sha: pr.base.sha },
201
+ commits: pr.commits,
202
+ additions: pr.additions,
203
+ deletions: pr.deletions,
204
+ changed_files: pr.changed_files,
205
+ comments: pr.comments,
206
+ review_comments: pr.review_comments,
207
+ html_url: pr.html_url,
208
+ created_at: stamp(pr.created_at),
209
+ updated_at: stamp(pr.updated_at),
210
+ closed_at: stamp(pr.closed_at),
211
+ merged_at: stamp(pr.merged_at),
212
+ body: bodyText(pr.body),
213
+ }),
214
+ 'issue.view': (issue) => ({
215
+ number: issue.number,
216
+ title: issue.title,
217
+ state: issue.state,
218
+ state_reason: issue.state_reason || undefined,
219
+ user: login(issue.user),
220
+ labels: labelNames(issue.labels),
221
+ assignees: logins(issue.assignees),
222
+ milestone: issue.milestone?.title,
223
+ comments: issue.comments,
224
+ html_url: issue.html_url,
225
+ created_at: stamp(issue.created_at),
226
+ updated_at: stamp(issue.updated_at),
227
+ closed_at: stamp(issue.closed_at),
228
+ body: bodyText(issue.body),
229
+ }),
230
+ };
231
+
232
+ function projectView(action, data) {
233
+ const project = VIEW_PROJECTORS[action];
234
+ return project && data && typeof data === 'object' && !Array.isArray(data) ? project(data) : undefined;
235
+ }
236
+
237
+ // Rows whose excerpt/description was shortened ("…") need raw for the rest.
238
+ function rowsWereCut(rows) {
239
+ return rows.some(
240
+ (row) =>
241
+ row &&
242
+ typeof row === 'object' &&
243
+ Object.values(row).some((value) => typeof value === 'string' && value.endsWith('…'))
244
+ );
245
+ }
246
+
64
247
  const fits = (text) => Buffer.byteLength(text, 'utf8') <= GITHUB_OUTPUT_MAX_BYTES;
65
248
 
66
249
  function clampStrings(value, max) {
@@ -213,7 +396,7 @@ export const GITHUB_TOOL_DEF = {
213
396
  },
214
397
  trigger: 'GitHub repos, issues, PRs, Actions, releases; not local Git history, diffs or staging (git).',
215
398
  description:
216
- 'GitHub repositories, issues, PRs and reviews, Actions/logs, releases, and notifications through the signed-in GitHub CLI. Local Git history/diffs/staging belong to git. One action per call; writes are serialized and never retried. Obtain user approval before writes; workflow runs and published releases may deploy. repo is owner/name; omit to resolve the current Project. Lists use page/limit. Review/merge requires the current PR head sha. Install/connect in Extensions → Plugin → Git & GitHub. Results omit API-only URLs and node ids and name users/repos by login/full_name; `raw` is a readable file with the full response, and long results state what is shown.',
399
+ 'GitHub repositories, issues, PRs and reviews, Actions/logs, releases, and notifications through the signed-in GitHub CLI. Local Git history/diffs/staging belong to git. One action per call; writes are serialized and never retried. Obtain user approval before writes; workflow runs and published releases may deploy. repo is owner/name; omit to resolve the current Project. Lists use page/limit and return compact rows (issues/PRs: number, title, state, author, updated, labels, 140-char excerpt; other lists: ids and status fields); open a row with its *.view action for bodies and details. Review/merge requires the current PR head sha. Install/connect in Extensions → Plugin → Git & GitHub. Results omit API-only URLs and node ids and name users/repos by login/full_name; issue/PR views keep decision fields and cap the body; `raw`, present whenever rows, text or fields were cut or dropped, is a readable file with the full response, and long results state what is shown.',
217
400
  inputSchema: {
218
401
  type: 'object',
219
402
  properties: {
@@ -267,9 +450,17 @@ export const GITHUB_TOOL_DEF = {
267
450
  export async function executeGithubTool(args, cwd, options = {}) {
268
451
  try {
269
452
  const result = await executeGithubRequest(args, cwd, options);
270
- const reduced = { ...result, data: reduceGithubData(result.data) };
453
+ const data =
454
+ projectList(args.action, result.data) ?? projectView(args.action, result.data) ?? reduceGithubData(result.data);
455
+ const reduced = { ...result, data };
456
+ if (reduced.hostname === DEFAULT_GITHUB_HOSTNAME) delete reduced.hostname;
271
457
  const text = JSON.stringify(reduced);
272
- if (text === JSON.stringify(result) && fits(text)) return text;
458
+ // Lists point at raw only when a row or excerpt was cut; they are projected
459
+ // by design. Everything else needs raw whenever the reduction dropped data.
460
+ const lossy = GITHUB_ACTIONS[args.action]?.list
461
+ ? Array.isArray(data) && rowsWereCut(data)
462
+ : JSON.stringify(data) !== JSON.stringify(result.data);
463
+ if (!lossy && fits(text)) return text;
273
464
  const raw = persistToolResultArtifactSync({
274
465
  sessionId: options.sessionId,
275
466
  toolCallId: options.toolCallId,
@@ -1,17 +1,27 @@
1
1
  /**
2
2
  * ChatGPT OAuth image adapter (`openai-oauth` lane).
3
3
  *
4
- * Runs the hosted `image_generation` tool on the Codex responses backend — the
5
- * same endpoint/headers the chat provider uses, so the subscription session is
6
- * the only credential involved. The final image arrives as base64 on the
7
- * image_generation_call item; partial frames are kept as a fallback.
4
+ * Primary path: the subscription's Images endpoints on the Codex backend
5
+ * (`images/generations`, or `images/edits` when reference images are given),
6
+ * a plain JSON request answered with the finished image as base64.
7
+ *
8
+ * Fallback path, used only when those endpoints are not served (404/405/501,
9
+ * or the edge's HTML 403 for an unknown route): the hosted `image_generation`
10
+ * tool on the responses backend. Its final image arrives on the
11
+ * image_generation_call item; a stream that only produced partial preview
12
+ * frames fails instead of saving a draft as the result.
13
+ *
14
+ * Both paths use the chat provider's session, so the subscription login is the
15
+ * only credential involved. Usage-limit failures name the reset time, looked up
16
+ * from the account's usage summary when the failure itself omits it.
8
17
  */
9
18
  import { randomBytes } from 'node:crypto';
10
19
  import { resolveCodexAuth } from '../auth.mjs';
11
20
  import { timeoutSignal } from '../bounded-signal.mjs';
21
+ import { chatgptLimitResetAt } from '../chatgpt-usage.mjs';
12
22
  import { decodeBase64Media } from '../download.mjs';
13
23
  import { mediaError } from '../lanes.mjs';
14
- import { upstreamError } from '../upstream-error.mjs';
24
+ import { upstreamError, usageLimitError, usageLimitFromResponse, usageLimitInfo } from '../upstream-error.mjs';
15
25
  import { responsesUsage, withReportedUsage } from '../media-usage.mjs';
16
26
  import { CODEX_OAUTH_ORIGINATOR, CODEX_RESPONSES_URL } from '../../agent/orchestrator/providers/openai-oauth.mjs';
17
27
  import {
@@ -21,6 +31,13 @@ import {
21
31
  } from '../../agent/orchestrator/providers/codex-client-meta.mjs';
22
32
 
23
33
  const REQUEST_TIMEOUT_MS = 400_000;
34
+ const LABEL = 'ChatGPT image';
35
+ export const CODEX_IMAGE_MODEL = 'gpt-image-2';
36
+ export const CODEX_IMAGES_GENERATIONS_URL = new URL('images/generations', CODEX_RESPONSES_URL).href;
37
+ export const CODEX_IMAGES_EDITS_URL = new URL('images/edits', CODEX_RESPONSES_URL).href;
38
+ const BACKGROUNDS = new Set(['transparent', 'opaque', 'auto']);
39
+
40
+ const dataUrl = (ref) => `data:${ref.mime || 'image/png'};base64,${ref.base64}`;
24
41
 
25
42
  function imageTool(options = {}) {
26
43
  const tool = { type: 'image_generation' };
@@ -28,9 +45,91 @@ function imageTool(options = {}) {
28
45
  if (size && size !== 'auto') tool.size = size;
29
46
  const quality = String(options.quality || 'auto');
30
47
  if (quality && quality !== 'auto') tool.quality = quality;
48
+ if (options.background && options.background !== 'auto') tool.background = options.background;
31
49
  return tool;
32
50
  }
33
51
 
52
+ /** Images endpoint request: generation, or an edit when references are given. */
53
+ export function codexImagesRequest({ prompt, options = {}, references = [] }) {
54
+ const body = { prompt, model: CODEX_IMAGE_MODEL, size: 'auto', quality: 'auto' };
55
+ if (options.background) body.background = options.background;
56
+ if (!references.length) return { url: CODEX_IMAGES_GENERATIONS_URL, body };
57
+ return {
58
+ url: CODEX_IMAGES_EDITS_URL,
59
+ body: { images: references.map((ref) => ({ image_url: dataUrl(ref) })), ...body },
60
+ };
61
+ }
62
+
63
+ export function codexImagesRequestHeaders(auth) {
64
+ const headers = {
65
+ Authorization: `Bearer ${auth.access_token}`,
66
+ 'Content-Type': 'application/json',
67
+ Accept: 'application/json',
68
+ originator: CODEX_OAUTH_ORIGINATOR,
69
+ 'x-client-request-id': randomBytes(16).toString('hex'),
70
+ version: codexVersionHeader(),
71
+ 'User-Agent': codexUserAgent(),
72
+ };
73
+ if (auth.account_id) headers['ChatGPT-Account-ID'] = auth.account_id;
74
+ return headers;
75
+ }
76
+
77
+ // The endpoint is not served for this backend: a missing route or method, or
78
+ // the edge's HTML 403 page that unknown backend routes answer with. Auth,
79
+ // billing and limit failures come back as JSON and are reported, not retried.
80
+ function imagesEndpointUnavailable(res) {
81
+ if ([404, 405, 501].includes(res.status)) return true;
82
+ return res.status === 403 && !/json/i.test(res.headers.get('content-type') || '');
83
+ }
84
+
85
+ function imagesUsage(usage) {
86
+ const tokens = responsesUsage(usage);
87
+ const imageTokens = Math.trunc(Number(usage?.output_tokens_details?.image_tokens) || 0);
88
+ return imageTokens > 0 ? { ...tokens, outputImageTokens: imageTokens } : tokens;
89
+ }
90
+
91
+ async function limitError(limit, { auth, fetchFn, lookupReset, signal }) {
92
+ const resetsAt = limit.resetsAt || (await lookupReset({ auth, limitId: limit.limitId, fetchFn, signal }));
93
+ return usageLimitError(LABEL, { limitId: limit.limitId, resetsAt });
94
+ }
95
+
96
+ async function failedResponse(res, ctx) {
97
+ const text = await res.text().catch(() => '');
98
+ const limit = usageLimitFromResponse(res.status, text, res.headers);
99
+ if (limit) return await limitError(limit, ctx);
100
+ return upstreamError(LABEL, res.status, text);
101
+ }
102
+
103
+ /** Returns the image, or null when the Images endpoint is unavailable. */
104
+ async function generateViaImagesEndpoint({ prompt, options, references, signal }, ctx) {
105
+ const { url, body } = codexImagesRequest({ prompt, options, references });
106
+ const res = await ctx.fetchFn(url, {
107
+ method: 'POST',
108
+ headers: codexImagesRequestHeaders(ctx.auth),
109
+ body: JSON.stringify(body),
110
+ redirect: 'error',
111
+ signal: timeoutSignal(signal, REQUEST_TIMEOUT_MS),
112
+ });
113
+ if (imagesEndpointUnavailable(res)) {
114
+ await res.body?.cancel().catch(() => {});
115
+ return null;
116
+ }
117
+ if (!res.ok) throw await failedResponse(res, ctx);
118
+ const json = await res.json().catch(() => null);
119
+ const usage = imagesUsage(json?.usage);
120
+ const b64 = json?.data?.[0]?.b64_json;
121
+ if (typeof b64 !== 'string' || !b64) {
122
+ throw withReportedUsage(mediaError(`${LABEL}: returned no image data`, 'MEDIA_EMPTY_RESULT', 502), usage);
123
+ }
124
+ return {
125
+ bytes: decodeBase64Media(b64, LABEL),
126
+ mime: 'image/png',
127
+ revisedPrompt: null,
128
+ actualModel: CODEX_IMAGE_MODEL,
129
+ usage: usage || null,
130
+ };
131
+ }
132
+
34
133
  function collectImage(event, state) {
35
134
  const item = event?.item;
36
135
  // Terminal Responses events carry the orchestrator's token usage. It does
@@ -55,10 +154,7 @@ export function codexImageRequestBody({ model, prompt, options = {}, references
55
154
  // Reference images ride as input_image parts on the user turn — the same
56
155
  // shape the chat path uses for pasted images.
57
156
  const content = [
58
- ...references.map((ref) => ({
59
- type: 'input_image',
60
- image_url: `data:${ref.mime || 'image/png'};base64,${ref.base64}`,
61
- })),
157
+ ...references.map((ref) => ({ type: 'input_image', image_url: dataUrl(ref) })),
62
158
  { type: 'input_text', text: prompt },
63
159
  ];
64
160
  return {
@@ -91,7 +187,12 @@ export function codexImageRequestHeaders(auth) {
91
187
 
92
188
  export async function generateImage(
93
189
  { model, prompt, options = {}, references = [], signal },
94
- { fetchFn = fetch, resolveAuth = resolveCodexAuth, warmVersion = warmCodexClientVersion } = {}
190
+ {
191
+ fetchFn = fetch,
192
+ resolveAuth = resolveCodexAuth,
193
+ warmVersion = warmCodexClientVersion,
194
+ lookupReset = chatgptLimitResetAt,
195
+ } = {}
95
196
  ) {
96
197
  if (['size', 'quality', 'resolution', 'aspectRatio'].some((key) => options[key] && options[key] !== 'auto')) {
97
198
  throw mediaError(
@@ -99,19 +200,28 @@ export async function generateImage(
99
200
  'MEDIA_OPTION_UNSUPPORTED'
100
201
  );
101
202
  }
203
+ if (options.background && !BACKGROUNDS.has(options.background)) {
204
+ throw mediaError('background must be transparent, opaque or auto.', 'MEDIA_OPTION_UNSUPPORTED');
205
+ }
102
206
  const auth = await resolveAuth();
103
207
  // Discovery and generation must report the same client version; otherwise
104
208
  // a newly discovered model can still be rejected by the Codex version gate.
105
209
  await warmVersion();
210
+ const ctx = { auth, fetchFn, lookupReset, signal };
211
+ const image = await generateViaImagesEndpoint({ prompt, options, references, signal }, ctx);
212
+ return image || (await generateViaResponses({ model, prompt, options, references, signal }, ctx));
213
+ }
214
+
215
+ async function generateViaResponses({ model, prompt, options, references, signal }, ctx) {
106
216
  const body = codexImageRequestBody({ model, prompt, options, references });
107
- const res = await fetchFn(CODEX_RESPONSES_URL, {
217
+ const res = await ctx.fetchFn(CODEX_RESPONSES_URL, {
108
218
  method: 'POST',
109
- headers: codexImageRequestHeaders(auth),
219
+ headers: codexImageRequestHeaders(ctx.auth),
110
220
  body: JSON.stringify(body),
111
221
  redirect: 'error',
112
222
  signal: timeoutSignal(signal, REQUEST_TIMEOUT_MS),
113
223
  });
114
- if (!res.ok || !res.body) throw upstreamError('ChatGPT image', res.status, await res.text().catch(() => ''));
224
+ if (!res.ok || !res.body) throw await failedResponse(res, ctx);
115
225
 
116
226
  const reader = res.body.getReader();
117
227
  const decoder = new TextDecoder();
@@ -136,7 +246,8 @@ export async function generateImage(
136
246
  continue;
137
247
  }
138
248
  if (event?.type === 'response.failed' || event?.type === 'error') {
139
- failure = event?.response?.error?.message || event?.message || 'stream failed';
249
+ // A top-level `error` event carries code/type/resets_at on itself.
250
+ failure = event?.response?.error || event?.error || event;
140
251
  }
141
252
  collectImage(event, state);
142
253
  }
@@ -147,15 +258,23 @@ export async function generateImage(
147
258
  } catch {}
148
259
  }
149
260
 
150
- const b64 = state.final || state.partial;
151
- if (!b64) {
152
- throw withReportedUsage(
153
- mediaError(`ChatGPT returned no image data${failure ? `: ${failure}` : ''}`, 'MEDIA_EMPTY_RESULT', 502),
154
- state.usage
155
- );
261
+ if (!state.final) {
262
+ const limit = failure && usageLimitInfo(failure, res.headers);
263
+ if (limit) throw withReportedUsage(await limitError(limit, ctx), state.usage);
264
+ const reason = (typeof failure === 'string' ? failure : failure?.message) || 'stream failed';
265
+ // A partial frame is a low-fidelity preview of an unfinished render; it is
266
+ // never saved as the result.
267
+ const error = state.partial
268
+ ? mediaError(
269
+ `${LABEL}: generation stopped after a partial preview; no final image was produced${failure ? ` (${reason})` : ''}`,
270
+ 'MEDIA_PARTIAL_ONLY',
271
+ 502
272
+ )
273
+ : mediaError(`ChatGPT returned no image data${failure ? `: ${reason}` : ''}`, 'MEDIA_EMPTY_RESULT', 502);
274
+ throw withReportedUsage(error, state.usage);
156
275
  }
157
276
  return {
158
- bytes: decodeBase64Media(b64, 'ChatGPT image'),
277
+ bytes: decodeBase64Media(state.final, LABEL),
159
278
  mime: 'image/png',
160
279
  revisedPrompt: state.revisedPrompt,
161
280
  actualModel: state.actualModel || null,
@@ -145,12 +145,12 @@ export function projectMediaModels(lane, rows) {
145
145
  result.image = orchestrator
146
146
  ? [
147
147
  {
148
- id: 'chatgpt-image-auto',
149
- label: 'ChatGPT Image · Auto',
148
+ id: 'gpt-image-2',
149
+ label: 'GPT Image 2',
150
150
  description:
151
- 'ChatGPT selects the image engine. GPT Image 2.5 selection and output size/quality are not verified on this connection.',
151
+ 'ChatGPT image engine. Output size/quality are chosen by ChatGPT; background can be transparent.',
152
152
  requestModel: orchestrator.id,
153
- controls: { maxReferences: 5 },
153
+ controls: { maxReferences: 5, background: ['auto', 'transparent', 'opaque'] },
154
154
  },
155
155
  ]
156
156
  : [];
@@ -0,0 +1,55 @@
1
+ /**
2
+ * ChatGPT subscription usage lookup.
3
+ *
4
+ * A usage-limit failure does not always say when the window reopens. The
5
+ * account's usage summary does: each metered limit lists its windows with
6
+ * `used_percent` and an epoch `reset_at`.
7
+ */
8
+ import { timeoutSignal } from './bounded-signal.mjs';
9
+ import { codexUserAgent } from '../agent/orchestrator/providers/codex-client-meta.mjs';
10
+
11
+ export const CHATGPT_USAGE_URL = 'https://chatgpt.com/backend-api/wham/usage';
12
+ const LOOKUP_TIMEOUT_MS = 10_000;
13
+
14
+ function exhaustedResetAt(rateLimit) {
15
+ if (!rateLimit || typeof rateLimit !== 'object') return null;
16
+ const windows = [rateLimit.primary_window, rateLimit.secondary_window].filter((w) => Number(w?.reset_at) > 0);
17
+ const full = windows.filter((w) => Number(w.used_percent) >= 100);
18
+ const candidates = full.length ? full : rateLimit.limit_reached ? windows : [];
19
+ return candidates.length ? Math.max(...candidates.map((w) => Math.trunc(Number(w.reset_at)))) : null;
20
+ }
21
+
22
+ /**
23
+ * Reset time (epoch seconds) of the exhausted limit in a usage summary. The
24
+ * limit named `limitId` wins; an image limit is next; the account's main
25
+ * window is last.
26
+ */
27
+ export function limitResetFromUsage(payload, limitId = '') {
28
+ const extra = Array.isArray(payload?.additional_rate_limits) ? payload.additional_rate_limits : [];
29
+ const id = String(limitId).toLowerCase();
30
+ const names = (entry) => [entry?.metered_feature, entry?.limit_name].map((name) => String(name || '').toLowerCase());
31
+ const named =
32
+ (id && extra.find((entry) => names(entry).includes(id))) ||
33
+ extra.find((entry) => names(entry).some((name) => name.includes('image')));
34
+ return exhaustedResetAt(named ? named.rate_limit : payload?.rate_limit);
35
+ }
36
+
37
+ /**
38
+ * Look the reset time up for the signed-in account. A failed lookup yields
39
+ * null: the caller still reports the limit, just without a time.
40
+ */
41
+ export async function chatgptLimitResetAt({ auth, limitId = '', fetchFn = fetch, signal } = {}) {
42
+ try {
43
+ const headers = { Authorization: `Bearer ${auth.access_token}`, 'User-Agent': codexUserAgent() };
44
+ if (auth.account_id) headers['ChatGPT-Account-Id'] = auth.account_id;
45
+ const res = await fetchFn(CHATGPT_USAGE_URL, {
46
+ headers,
47
+ redirect: 'error',
48
+ signal: timeoutSignal(signal, LOOKUP_TIMEOUT_MS),
49
+ });
50
+ if (!res.ok) return null;
51
+ return limitResetFromUsage(await res.json(), limitId);
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
@@ -41,6 +41,43 @@ export function getMediaDefault(kind) {
41
41
  return lane ? { kind: key, lane, model: text(row?.model) } : null;
42
42
  }
43
43
 
44
+ // Settings → Built-in → Media generation. Unlike the remembered selection above
45
+ // (rewritten by every generation), a pin is only ever written by the user:
46
+ // `{ lane, model, account }` per kind, where an empty model is the lane default
47
+ // and an empty account follows that provider's currently selected account.
48
+ const PINNED = 'pinned';
49
+
50
+ function readPins() {
51
+ const pins = readAll()[PINNED];
52
+ return pins && typeof pins === 'object' && !Array.isArray(pins) ? pins : {};
53
+ }
54
+
55
+ /** `{ kind, lane, model, account }` for the kind, or null when it is on auto. */
56
+ export function getMediaPin(kind) {
57
+ const key = text(kind);
58
+ if (!MEDIA_KINDS.includes(key)) return null;
59
+ const row = readPins()[key];
60
+ const lane = text(row?.lane);
61
+ return lane ? { kind: key, lane, model: text(row?.model), account: text(row?.account) } : null;
62
+ }
63
+
64
+ export function getMediaPins() {
65
+ return Object.fromEntries(MEDIA_KINDS.map((kind) => [kind, getMediaPin(kind)]));
66
+ }
67
+
68
+ /** Pin one kind to a lane/model/account; an empty `lane` returns it to auto. */
69
+ export function setMediaPin({ kind, lane, model, account } = {}) {
70
+ const key = text(kind);
71
+ if (!MEDIA_KINDS.includes(key)) throw new TypeError(`kind must be one of ${MEDIA_KINDS.join(', ')}`);
72
+ const laneId = text(lane);
73
+ const { [key]: _previous, ...others } = readPins();
74
+ const pins = laneId ? { ...others, [key]: { lane: laneId, model: text(model), account: text(account) } } : others;
75
+ const path = defaultsPath();
76
+ mkdirSync(dirname(path), { recursive: true });
77
+ writeJsonAtomicSync(path, { ...readAll(), [PINNED]: pins });
78
+ return getMediaPin(key);
79
+ }
80
+
44
81
  /** Remember the lane (and model) for one kind. `model` may be empty: the lane default then applies. */
45
82
  export function setMediaDefault({ kind, lane, model } = {}) {
46
83
  const key = text(kind);
@@ -8,7 +8,8 @@
8
8
  */
9
9
  import { randomUUID } from 'node:crypto';
10
10
  import { MAX_GENERATED_MEDIA_BYTES } from './download.mjs';
11
- import { mediaError, resolveMediaRequest } from './lanes.mjs';
11
+ import { mediaError, mediaLaneAccountProvider, resolveMediaRequest } from './lanes.mjs';
12
+ import { withProviderAccount } from '../shared/provider-auth-binding.mjs';
12
13
  import { saveMediaAsset } from './store.mjs';
13
14
  import { setMediaDefault } from './defaults.mjs';
14
15
  import { recordMediaUsage } from './media-usage.mjs';
@@ -77,8 +78,17 @@ async function runAdapter({ lane, kind, model, requestModel, prompt, options, re
77
78
  /**
78
79
  * Validate + start one generation. Returns the initial snapshot immediately;
79
80
  * the caller polls getMediaJob for progress and the finished asset id.
81
+ * `account` runs the whole job (catalog check, credentials, adapter) as that
82
+ * connected account of the lane's provider, whatever the chat is using; an
83
+ * account that cannot serve the call fails it, never another account.
80
84
  */
81
- export async function startMediaJob({
85
+ export async function startMediaJob(input = {}) {
86
+ const account = String(input?.account || '').trim();
87
+ const provider = account ? mediaLaneAccountProvider(input.lane) : '';
88
+ return provider ? withProviderAccount(provider, account, () => beginMediaJob(input)) : beginMediaJob(input);
89
+ }
90
+
91
+ async function beginMediaJob({
82
92
  lane: laneId,
83
93
  kind,
84
94
  model,