mixdog 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/provider-pingpong-live.mjs +509 -0
  4. package/src/agents/advisor/AGENT.md +1 -1
  5. package/src/agents/advisor/agent.json +1 -1
  6. package/src/defaults/shipped-history.json +5 -0
  7. package/src/defaults/skills/setup/SKILL.md +6 -1
  8. package/src/defaults/skills/setup/references/actions.md +44 -22
  9. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  10. package/src/headless-exec.mjs +15 -8
  11. package/src/lib/keychain-cjs.cjs +7 -4
  12. package/src/output-styles/common.md +11 -10
  13. package/src/rules/agent/AGENT.md +5 -5
  14. package/src/rules/lead/LEAD.md +5 -5
  15. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  16. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  17. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  18. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  19. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  20. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  21. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  22. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  23. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
  24. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  25. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
  26. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
  28. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  30. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  31. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  32. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  35. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  36. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  37. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
  38. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
  39. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  40. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
  41. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
  42. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
  43. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
  45. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  46. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
  47. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
  49. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
  50. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
  51. package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
  52. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
  53. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
  54. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  55. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  56. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  57. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
  58. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  59. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
  60. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
  61. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  62. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
  63. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
  64. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  65. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
  66. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
  67. package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
  68. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  71. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  72. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
  73. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  74. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  75. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
  76. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  77. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  78. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  79. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  80. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
  81. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
  82. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  83. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  84. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  85. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
  86. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  88. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
  89. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  90. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  91. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
  92. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  93. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
  103. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  104. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  108. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
  109. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  110. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  111. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
  112. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  113. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  114. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  115. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  117. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  119. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  121. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
  122. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  123. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
  124. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
  125. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  126. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
  127. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  129. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  130. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
  131. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
  132. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
  133. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
  134. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
  135. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
  136. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
  137. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  138. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  139. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
  140. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
  141. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  142. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  147. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  148. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  150. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  151. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  152. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
  154. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  155. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
  156. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  157. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
  158. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  159. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
  160. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  161. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  162. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
  163. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  164. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
  165. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  167. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  168. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
  169. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
  170. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
  171. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
  172. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
  173. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
  174. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  175. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
  179. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
  180. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
  181. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  184. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  187. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
  188. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
  189. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
  190. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
  192. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  193. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  194. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
  195. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  196. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
  197. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  198. package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
  199. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
  200. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  201. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
  203. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  204. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
  205. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
  206. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  207. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  208. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  209. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  210. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
  211. package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
  212. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
  213. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  215. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  216. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  217. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
  218. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  221. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
  223. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  224. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  225. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  226. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  227. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  228. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  229. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  230. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  231. package/src/runtime/computer-bridge/action-schema.mjs +44 -21
  232. package/src/runtime/github/tool.mjs +92 -2
  233. package/src/runtime/memory/index.mjs +1 -0
  234. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  235. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  236. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  237. package/src/runtime/memory/lib/pg/process.mjs +31 -26
  238. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  239. package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
  240. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  241. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  242. package/src/runtime/office/README.md +1 -1
  243. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  244. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  245. package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
  246. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  247. package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
  248. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  249. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  250. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  251. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  252. package/src/runtime/office/core/office-sessions.mjs +5 -0
  253. package/src/runtime/office/core/office-transactions.mjs +3 -0
  254. package/src/runtime/office/core/office-write-ledger.mjs +98 -0
  255. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  256. package/src/runtime/office/index.mjs +30 -0
  257. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  258. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  259. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  260. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  261. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  262. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  263. package/src/runtime/shared/bounded-line-diff.mjs +182 -0
  264. package/src/runtime/shared/buffered-appender.mjs +18 -0
  265. package/src/runtime/shared/config.mjs +78 -18
  266. package/src/runtime/shared/err-text.mjs +6 -0
  267. package/src/runtime/shared/file-permissions.d.mts +6 -1
  268. package/src/runtime/shared/file-permissions.mjs +54 -6
  269. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  270. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  271. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  272. package/src/runtime/shared/loopback-listener.mjs +9 -0
  273. package/src/runtime/shared/provider-api-key.mjs +2 -0
  274. package/src/runtime/shared/review-diff.mjs +52 -0
  275. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  276. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  277. package/src/runtime/shared/slow-span.mjs +114 -0
  278. package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
  279. package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
  280. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  281. package/src/runtime/shared/tool-card-model.mjs +5 -2
  282. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  283. package/src/runtime/shared/tool-primitives.mjs +13 -0
  284. package/src/runtime/shared/tool-result-summary.mjs +8 -1
  285. package/src/runtime/shared/tool-surface.mjs +18 -3
  286. package/src/runtime/shared/tool-work-units.mjs +40 -4
  287. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  288. package/src/runtime/shared/transcript-writer.mjs +10 -2
  289. package/src/runtime/shared/turn-changes.mjs +268 -100
  290. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  291. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  292. package/src/runtime/shared/turn-snapshot.mjs +857 -683
  293. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  294. package/src/runtime/shared/user-data-guard.mjs +262 -49
  295. package/src/runtime/shared/worktrees/carry.mjs +531 -0
  296. package/src/runtime/shared/worktrees/contract.mjs +34 -0
  297. package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
  298. package/src/runtime/shared/worktrees/git-head.mjs +205 -0
  299. package/src/runtime/shared/worktrees/git.mjs +8 -3
  300. package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
  301. package/src/runtime/shared/worktrees/manager.mjs +156 -8
  302. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  303. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  304. package/src/runtime/terminal-bridge/client.mjs +44 -11
  305. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  306. package/src/runtime/tidy/apply.mjs +47 -2
  307. package/src/runtime/tidy/run-engines.mjs +11 -5
  308. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  309. package/src/session-runtime/boot/apis.mjs +13 -5
  310. package/src/session-runtime/boot/facade.mjs +1 -0
  311. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  312. package/src/session-runtime/boot/session.mjs +0 -1
  313. package/src/session-runtime/boot/tools.mjs +4 -1
  314. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  315. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
  316. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  317. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
  318. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
  319. package/src/session-runtime/internal-tool-executor.mjs +6 -2
  320. package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
  321. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  322. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
  323. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  324. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
  325. package/src/session-runtime/lifecycle/teardown.mjs +72 -7
  326. package/src/session-runtime/lifecycle-api.mjs +1 -0
  327. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  328. package/src/session-runtime/model-route/set-route.mjs +2 -2
  329. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  330. package/src/session-runtime/native-web-search.mjs +10 -1
  331. package/src/session-runtime/new-session-config.mjs +4 -2
  332. package/src/session-runtime/provider-auth/login.mjs +4 -0
  333. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  334. package/src/session-runtime/runtime-review-api.mjs +8 -2
  335. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  336. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  337. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  338. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
  339. package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
  340. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  341. package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
  342. package/src/session-runtime/services/agent-tool.mjs +3 -0
  343. package/src/session-runtime/services/channel-admin.mjs +19 -3
  344. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  345. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  346. package/src/session-runtime/services/provider-admin.mjs +81 -15
  347. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  348. package/src/session-runtime/session-turn-api.mjs +14 -5
  349. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
  350. package/src/session-runtime/setup-tool/executor.mjs +36 -6
  351. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  352. package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
  353. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
  354. package/src/session-runtime/skills-api.mjs +3 -5
  355. package/src/session-runtime/tool-surface.mjs +5 -1
  356. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  357. package/src/session-runtime/turn/session-ops.mjs +7 -5
  358. package/src/session-runtime/turn/side-question-ops.mjs +22 -0
  359. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
  360. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
  361. package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
  362. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  363. package/src/session-runtime/turn/turn-run.mjs +25 -9
  364. package/src/session-runtime/usage-stats-api.mjs +43 -11
  365. package/src/session-runtime/workspace/project-branches.mjs +7 -5
  366. package/src/session-runtime/workspace/transition-steps.mjs +129 -31
  367. package/src/session-runtime/workspace/transitions.mjs +190 -15
  368. package/src/standalone/daemon-agent-control.mjs +9 -1
  369. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  370. package/src/standalone/daemon-owner.mjs +17 -4
  371. package/src/standalone/daemon-pg-stop.mjs +51 -0
  372. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  373. package/src/standalone/daemon-stop-budget.mjs +18 -0
  374. package/src/standalone/daemon-stored-session-views.mjs +2 -0
  375. package/src/standalone/daemon-telemetry.mjs +19 -0
  376. package/src/standalone/daemon.mjs +61 -1
  377. package/src/standalone/desktop-service-registry.mjs +5 -0
  378. package/src/standalone/local-session-runtime.mjs +70 -19
  379. package/src/standalone/session-client.mjs +42 -0
  380. package/src/standalone/session-protocol.mjs +7 -0
  381. package/src/standalone/session-proxy/projection.mjs +41 -4
  382. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  383. package/src/standalone/session-runtime-inline-host.mjs +1 -0
  384. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  385. package/src/standalone/session-service-api.mjs +6 -1
  386. package/src/standalone/session-state-patch.d.mts +2 -1
  387. package/src/standalone/session-state-patch.mjs +41 -1
  388. package/src/tui/App.jsx +25 -0
  389. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  390. package/src/tui/app/btw-controller.mjs +118 -0
  391. package/src/tui/app/create-app-pickers.mjs +2 -0
  392. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  393. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  394. package/src/tui/app/slash-commands.mjs +13 -3
  395. package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
  396. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  397. package/src/tui/app/use-global-key-input.mjs +5 -12
  398. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  399. package/src/tui/components/BtwPanel.jsx +53 -0
  400. package/src/tui/components/QuestionPanel.jsx +275 -0
  401. package/src/tui/components/question-panel-model.mjs +156 -0
  402. package/src/tui/dist/index.mjs +2413 -1465
  403. package/src/tui/session/context-state.mjs +4 -2
  404. package/src/tui/session/session-api/commands.mjs +10 -0
  405. package/src/tui/session/session-api/controls.mjs +2 -2
  406. package/src/tui/session/session-api/integrations.mjs +9 -2
  407. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  408. package/src/tui/session/session-api/lifecycle.mjs +2 -1
  409. package/src/tui/session/session-api/settings.mjs +6 -0
  410. package/src/tui/session/session-api.mjs +1 -0
  411. package/src/tui/session/tool-approval.mjs +10 -7
  412. package/src/tui/session/transcript-spill.mjs +14 -7
  413. package/src/tui/session/turn-stream.mjs +174 -31
  414. package/src/tui/session/turn.mjs +12 -5
  415. package/src/workflows/default/WORKFLOW.md +3 -1
@@ -1,28 +1,20 @@
1
- import { getModelMetadataSync } from '../../../shared/llm/model-catalog.mjs';
1
+ import {
2
+ openAiCatalogMeta,
3
+ openAiSupportsExtendedRetention,
4
+ openAiUsesPromptCacheOptions,
5
+ } from './openai-model-capabilities.mjs';
2
6
 
3
- // Public Responses contracts are independent of the OAuth backend. Every
4
- // capability here comes from the model catalog (the service-tier price columns
5
- // and the cache-write rate), so a model the catalog lists works without an
6
- // edit. Only a model no catalog describes (cold install) falls back to the
7
- // documented ids known before the catalogs carried these columns.
8
- const SNAPSHOT_SUFFIX = /-\d{4}-\d{2}-\d{2}$/;
7
+ // Public Responses contracts are independent of the OAuth backend. Service
8
+ // tiers come from the model catalog (the service-tier price columns), so a
9
+ // model the catalog lists works without an edit. Only a model no catalog
10
+ // describes (cold install) falls back to the documented ids known before the
11
+ // catalogs carried these columns.
9
12
  const PRE_CATALOG_GPT_56_PLUS =
10
13
  /^(?:gpt-6-(?:astra|sol|luna)|gpt-6\.1-sol|gpt-5\.6-(?:sol|terra|luna))(?:-\d{4}-\d{2}-\d{2})?$/;
11
14
  const PRE_CATALOG_EARLIER_FAST = /^gpt-5\.(?:5|4|4-mini)(?:-\d{4}|$)/;
12
15
  const PRE_CATALOG_ULTRAFAST = /^(?:gpt-6-astra|gpt-6\.1-sol)(?:-\d{4}-\d{2}-\d{2})?$/;
13
16
  const modelId = (model) => String(model?.id || model || '').trim();
14
17
 
15
- // The catalog metadata of one model. A dated snapshot reads as its undated
16
- // alias when only the alias is listed.
17
- function openAiCatalogMeta(model) {
18
- const id = String(model?.id || model || '').trim();
19
- for (const candidate of new Set([id, id.replace(SNAPSHOT_SUFFIX, '')])) {
20
- const meta = candidate ? getModelMetadataSync(candidate, 'openai') : null;
21
- if (meta) return meta;
22
- }
23
- return null;
24
- }
25
-
26
18
  export function openAiDirectSupportsFast(model) {
27
19
  const meta = openAiCatalogMeta(model);
28
20
  // The catalog's declaration (true or false) decides; a published Priority
@@ -40,13 +32,13 @@ export function openAiDirectSupportsUltrafast(model) {
40
32
  return PRE_CATALOG_ULTRAFAST.test(modelId(model));
41
33
  }
42
34
 
43
- // OpenAI bills prompt-cache writes from GPT-5.6 on, and exactly those models
44
- // take prompt_cache_options in place of prompt_cache_retention, so a published
45
- // cache-write rate selects the new form.
46
35
  // https://developers.openai.com/api/docs/guides/prompt-caching
36
+ // GPT-5.6 and later: prompt_cache_options.ttl. Earlier models: 24h
37
+ // prompt_cache_retention only on the documented extended-retention list;
38
+ // every other model gets no lifetime field (never inferred from pricing).
47
39
  function promptCacheForm(model) {
48
- const writeRate = openAiCatalogMeta(model)?.cacheWriteCostPerM > 0;
49
- return writeRate || PRE_CATALOG_GPT_56_PLUS.test(modelId(model)) ? 'options' : 'retention';
40
+ if (openAiUsesPromptCacheOptions(model) || PRE_CATALOG_GPT_56_PLUS.test(modelId(model))) return 'options';
41
+ return openAiSupportsExtendedRetention(model) ? 'retention' : null;
50
42
  }
51
43
 
52
44
  export function applyOpenAIDirectCachePolicy(body, model, storeResponses) {
@@ -6,6 +6,8 @@
6
6
  */
7
7
  import { recomputeToolInFlight } from '../response-state.mjs';
8
8
  import { parseJsonObject } from '../response-items.mjs';
9
+ import { withToolCallNamespace } from '../../custom-tool-wire.mjs';
10
+ import { isIncompleteToolItem } from '../../lib/responses-terminal-fields.mjs';
9
11
 
10
12
  function outputItemKind(item) {
11
13
  if (item.type === 'reasoning') return 'reasoning';
@@ -19,10 +21,10 @@ export function createOutputItemEvents({ state, items, meaningful }) {
19
21
  const onOutputItemAdded = (item) => {
20
22
  if (item?.type === 'function_call') {
21
23
  toolTracker.mark(item);
22
- state.pendingCalls.set(item.id || '', {
23
- name: item.name || '',
24
- callId: item.call_id || '',
25
- });
24
+ state.pendingCalls.set(
25
+ item.id || '',
26
+ withToolCallNamespace({ name: item.name || '', callId: item.call_id || '' }, item)
27
+ );
26
28
  state.toolInFlight = true;
27
29
  } else if (item?.type === 'tool_search_call') {
28
30
  // Mark tool_search as in-flight the moment the item is added,
@@ -66,12 +68,15 @@ export function createOutputItemEvents({ state, items, meaningful }) {
66
68
  meaningful('tool');
67
69
  return;
68
70
  }
69
- const call = {
70
- id: pending?.callId || event.call_id || '',
71
- name: pending?.name || event.name || '',
72
- arguments: parseJsonObject(event.arguments),
73
- _pendingItemId: itemId,
74
- };
71
+ const call = withToolCallNamespace(
72
+ {
73
+ id: pending?.callId || event.call_id || '',
74
+ name: pending?.name || event.name || '',
75
+ arguments: parseJsonObject(event.arguments),
76
+ _pendingItemId: itemId,
77
+ },
78
+ pending
79
+ );
75
80
  state.toolCalls.push(call);
76
81
  if (call.id && call.name) {
77
82
  delete call._pendingItemId;
@@ -81,9 +86,17 @@ export function createOutputItemEvents({ state, items, meaningful }) {
81
86
  };
82
87
 
83
88
  const onOutputItemDone = (item) => {
89
+ if (isIncompleteToolItem(item)) {
90
+ // Server-truncated call: stays in flight, never collected or replayed.
91
+ toolTracker.mark(item);
92
+ state.toolInFlight = true;
93
+ meaningful('tool');
94
+ return;
95
+ }
84
96
  items.pushResponseItem(item);
85
97
  items.pushReasoningItem(item);
86
98
  items.pushWebSearchCall(item);
99
+ state.refusals.absorbMessage(item);
87
100
  if (item.type === 'function_call') {
88
101
  const tc = state.toolCalls.find((t) => t._pendingItemId === (item.id || ''));
89
102
  if (tc) items.completePendingCall(tc, item);
@@ -8,6 +8,7 @@ import { typedStatusFrom } from '../../retry-classifier.mjs';
8
8
  import {
9
9
  endTurnFromEvent,
10
10
  incompleteReasonFromEvent,
11
+ isIncompleteToolItem,
11
12
  isMaxOutputIncompleteReason,
12
13
  } from '../../lib/responses-terminal-fields.mjs';
13
14
  import { applyErrorContract, markContentFilter } from '../../openai-error-contract.mjs';
@@ -36,6 +37,13 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
36
37
  const absorbCompletedOutput = (output) => {
37
38
  let reported = false;
38
39
  for (const item of output) {
40
+ if (isIncompleteToolItem(item)) {
41
+ state.toolTracker.mark(item);
42
+ state.toolInFlight = true;
43
+ meaningful('tool');
44
+ reported = true;
45
+ continue;
46
+ }
39
47
  items.pushResponseItem(item);
40
48
  if (item.type === 'message') {
41
49
  if (text.absorbCompletedMessage(item)) reported = true;
@@ -101,26 +109,39 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
101
109
  }
102
110
  throw err;
103
111
  }
112
+ for (const item of event.response?.output || []) {
113
+ if (isIncompleteToolItem(item)) {
114
+ state.toolTracker.mark(item);
115
+ state.toolInFlight = true;
116
+ }
117
+ }
104
118
  if (toolInputPending(state)) {
119
+ // Same carried state as the WS path: text (leak-guard tail flushed),
120
+ // the calls already complete and dispatched, model and billed usage.
121
+ text.flushLeak();
105
122
  const err = outcome.stampToolSafety(new Error(`${state.label} ${frame} (max_output_tokens) with tool call in flight`));
123
+ outcome.attachStreamPartial(err);
106
124
  err.streamStalled = true;
107
125
  err.pendingToolUse = true;
108
- err.partialContent = state.content;
109
- err.partialModel = state.model || undefined;
126
+ err.incompleteReason = reason;
110
127
  if (state.usage) err.partialUsage = state.usage;
111
128
  throw err;
112
129
  }
113
130
  state.completed = true;
114
131
  state.stopReason = 'length';
132
+ state.incompleteReason = reason;
115
133
  };
116
134
 
117
135
  const onDone = (event) => {
118
- if (!event.response || event.response.status === 'completed') {
119
- if (event.response) absorbTerminalResponse(event.response);
136
+ if (!event.response) {
120
137
  state.completed = true;
121
138
  // Terminal success frame for streams that never emit a separate
122
139
  // response.completed — same optional end_turn.
123
140
  setEndTurn(event);
141
+ } else if (event.response.status === 'completed') {
142
+ // Same terminal as response.completed: usage, end_turn and the output
143
+ // bundle reconciled through the same deduplicated collectors.
144
+ onCompleted(event);
124
145
  } else if (event.response.status === 'failed') {
125
146
  const msg = event.response?.error?.message || 'response.done failed';
126
147
  const err = new Error(`${state.label} response.done failed: ${msg}`);
@@ -42,6 +42,16 @@ export function createResponseEvents({ state, items, text, outcome, meaningful,
42
42
  case 'response.function_call_arguments.done':
43
43
  output.onFunctionCallArgumentsDone(event);
44
44
  break;
45
+ // Refusal text is collected for the typed refusal result, never relayed
46
+ // as visible answer text.
47
+ case 'response.refusal.delta':
48
+ state.refusals.delta(event);
49
+ meaningful('semantic');
50
+ break;
51
+ case 'response.refusal.done':
52
+ state.refusals.done(event);
53
+ meaningful('semantic');
54
+ break;
45
55
  case 'response.output_item.done':
46
56
  output.onOutputItemDone(event.item || {});
47
57
  break;
@@ -5,7 +5,12 @@
5
5
  * pending function_call completion.
6
6
  */
7
7
  import { makeInvalidToolArgsMarker } from '../lib/openai-tool-args.mjs';
8
- import { customToolCallFromResponseItem, nativeToolSearchCallFromArguments } from '../custom-tool-wire.mjs';
8
+ import {
9
+ customToolCallFromResponseItem,
10
+ nativeToolSearchCallFromArguments,
11
+ qualifiedToolCallName,
12
+ withToolCallNamespace,
13
+ } from '../custom-tool-wire.mjs';
9
14
 
10
15
  // Completed function_call.arguments parse for the OpenAI Responses stream.
11
16
  // A function_call item arrives only on a completion/done signal, so a
@@ -37,7 +42,7 @@ export function createResponseItems({ state, onToolCall }) {
37
42
  if (!call?.id) return;
38
43
  if (state.emittedToolCallIds.has(call.id)) return;
39
44
  state.emittedToolCallIds.add(call.id);
40
- if (!state.toolDedupe.shouldDispatch(call.name, call.arguments, call.id)) return;
45
+ if (!state.toolDedupe.shouldDispatch(qualifiedToolCallName(call), call.arguments, call.id)) return;
41
46
  state.emittedToolCall = true;
42
47
  try {
43
48
  onToolCall?.(call);
@@ -77,6 +82,8 @@ export function createResponseItems({ state, onToolCall }) {
77
82
  };
78
83
  const pushToolSearchCall = (item) => {
79
84
  if (item?.type !== 'tool_search_call') return;
85
+ // Server-executed search already ran inside the response; replay-only.
86
+ if (item.execution === 'server') return;
80
87
  const callId = item.call_id || item.id || '';
81
88
  if (!callId || state.toolCalls.some((t) => t.id === callId)) return;
82
89
  let args = {};
@@ -104,6 +111,7 @@ export function createResponseItems({ state, onToolCall }) {
104
111
  const completePendingCall = (tc, item) => {
105
112
  if (!tc.id && item.call_id) tc.id = item.call_id;
106
113
  if (!tc.name && item.name) tc.name = item.name;
114
+ withToolCallNamespace(tc, item);
107
115
  if (tc.id && tc.name) {
108
116
  delete tc._pendingItemId;
109
117
  emitToolCall(tc);
@@ -119,11 +127,14 @@ export function createResponseItems({ state, onToolCall }) {
119
127
  if (tc) {
120
128
  completePendingCall(tc, item);
121
129
  } else if (item.call_id && item.name) {
122
- const call = {
123
- id: item.call_id,
124
- name: item.name,
125
- arguments: parseJsonObject(item.arguments),
126
- };
130
+ const call = withToolCallNamespace(
131
+ {
132
+ id: item.call_id,
133
+ name: item.name,
134
+ arguments: parseJsonObject(item.arguments),
135
+ },
136
+ item
137
+ );
127
138
  state.toolCalls.push(call);
128
139
  emitToolCall(call);
129
140
  }
@@ -9,6 +9,7 @@ import { dedupeToolCallList } from '../lib/leaked-toolcall.mjs';
9
9
  import { _displayCodexModel } from '../openai-codex-model.mjs';
10
10
  import { createProviderReplay } from '../lib/provider-replay.mjs';
11
11
  import { createResponseStamps } from './response-stamps.mjs';
12
+ import { refusalResultFields } from '../openai-ws-response-state/refusals.mjs';
12
13
 
13
14
  export function createResponseOutcome({ state }) {
14
15
  const { stampToolSafety, stampOutcome, stallPartial, stampStreamError, attachStreamPartial, endedEarlyError } =
@@ -74,6 +75,7 @@ export function createResponseOutcome({ state }) {
74
75
  webSearchCalls: state.webSearchCalls.length ? state.webSearchCalls : undefined,
75
76
  usage: state.usage || undefined,
76
77
  stopReason: state.stopReason || undefined,
78
+ incompleteReason: state.incompleteReason || undefined,
77
79
  // Only present when the terminal frame carried the wire field.
78
80
  ...(typeof state.endTurn === 'boolean' ? { endTurn: state.endTurn } : {}),
79
81
  // Text-only max-output cutoff (status:'incomplete'/reason=max_output_tokens
@@ -83,6 +85,8 @@ export function createResponseOutcome({ state }) {
83
85
  ...(state.stopReason === 'length' && state.content.length > 0 ? { truncated: true } : {}),
84
86
  responseId: state.responseId || undefined,
85
87
  serviceTier: state.serviceTier || undefined,
88
+ // A refused turn: typed stop reason and the refusal text.
89
+ ...refusalResultFields(state.refusals, state.content),
86
90
  };
87
91
  };
88
92
 
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import { createActiveToolItemTracker } from '../tool-stream-state.mjs';
9
9
  import { createToolCallDedupe } from '../lib/leaked-toolcall.mjs';
10
+ import { createRefusals } from '../openai-ws-response-state/refusals.mjs';
10
11
 
11
12
  export function createResponseState(label) {
12
13
  return {
@@ -31,8 +32,12 @@ export function createResponseState(label) {
31
32
  citationKeys: new Set(),
32
33
  webSearchCalls: [],
33
34
  webSearchCallKeys: new Set(),
35
+ // Refusal parts (streamed and final), folded into one typed refusal.
36
+ refusals: createRefusals(),
34
37
  completed: false,
35
38
  stopReason: null,
39
+ // Why a max-output cutoff completed the turn (response.incomplete_details).
40
+ incompleteReason: null,
36
41
  // Normalized wire `end_turn` from the terminal frame; undefined unless the
37
42
  // server actually supplied a boolean.
38
43
  endTurn: undefined,
@@ -97,10 +97,18 @@ export function createTextRelay({ state, body, onTextDelta, meaningful, emitTool
97
97
  };
98
98
  const absorbCompletedMessage = (item) => {
99
99
  let reported = false;
100
+ // Decided once per message item (as the WS completed-item fold does), so
101
+ // every content part of an item with no streamed text is absorbed rather
102
+ // than only the first one that fills `state.content`.
103
+ const absorbText = !state.content;
100
104
  for (const part of item.content || []) {
101
- if (!state.content && part.type === 'output_text' && absorbCompletedText(part)) reported = true;
105
+ if (absorbText && part.type === 'output_text' && absorbCompletedText(part)) reported = true;
102
106
  if (part.type === 'output_text') pushOutputTextAnnotations(part, state.citations, state.citationKeys);
103
107
  }
108
+ if (state.refusals.absorbMessage(item)) {
109
+ meaningful('semantic');
110
+ reported = true;
111
+ }
104
112
  return reported;
105
113
  };
106
114
 
@@ -0,0 +1,80 @@
1
+ // Public OpenAI API model capabilities for Responses request construction.
2
+ // Catalog metadata decides where it declares a capability; otherwise the
3
+ // documented model-family rules below apply. The Codex (openai-oauth) route is
4
+ // separate: its backend serves only current GPT-5.x models and keeps its own
5
+ // defaults, so none of these gates apply to it.
6
+ // reasoning: https://developers.openai.com/api/docs/guides/reasoning/
7
+ // tool_search: https://developers.openai.com/api/docs/guides/tools-tool-search/ (gpt-5.4 and later)
8
+ // cache: https://developers.openai.com/api/docs/guides/prompt-caching/
9
+ import { getModelMetadataSync } from '../../../shared/llm/model-catalog.mjs';
10
+
11
+ const SNAPSHOT_SUFFIX = /-\d{4}-\d{2}-\d{2}$/;
12
+ const modelId = (model) => String(model?.id || model || '').trim();
13
+
14
+ // The catalog metadata of one model. A dated snapshot reads as its undated
15
+ // alias when only the alias is listed.
16
+ export function openAiCatalogMeta(model) {
17
+ const id = modelId(model);
18
+ for (const candidate of new Set([id, id.replace(SNAPSHOT_SUFFIX, '')])) {
19
+ const meta = candidate ? getModelMetadataSync(candidate, 'openai') : null;
20
+ if (meta) return meta;
21
+ }
22
+ return null;
23
+ }
24
+
25
+ // gpt-5.4 -> [5, 4]; gpt-6-astra -> [6, 0]; non-GPT ids -> null.
26
+ // A bare multi-digit major with no minor or family suffix (gpt-60) is not a
27
+ // generation id.
28
+ function gptVersion(id) {
29
+ const m = /^gpt-(\d+)(?:\.(\d+))?(?=-|$)/.exec(id);
30
+ if (!m || (m[1].length > 1 && m[2] === undefined && m[0] === id)) return null;
31
+ return [Number(m[1]), Number(m[2] || 0)];
32
+ }
33
+ const atLeast = (version, major, minor) =>
34
+ Boolean(version) && (version[0] > major || (version[0] === major && version[1] >= minor));
35
+
36
+ // Reasoning models: the o-series and GPT-5 and later (gpt-5-chat-latest is the
37
+ // non-reasoning chat snapshot).
38
+ export function openAiPublicSupportsReasoning(model) {
39
+ const flag = openAiCatalogMeta(model)?.supportsReasoning;
40
+ if (typeof flag === 'boolean') return flag;
41
+ const id = modelId(model);
42
+ if (/^gpt-5-chat/.test(id)) return false;
43
+ return /^o\d/.test(id) || atLeast(gptVersion(id), 5, 0);
44
+ }
45
+
46
+ // text.verbosity is documented for GPT-5 and later.
47
+ export function openAiPublicSupportsVerbosity(model) {
48
+ return atLeast(gptVersion(modelId(model)), 5, 0);
49
+ }
50
+
51
+ // Native tool_search: Responses API gpt-5.4 and later.
52
+ export function openAiPublicSupportsToolSearch(model) {
53
+ return atLeast(gptVersion(modelId(model)), 5, 4);
54
+ }
55
+
56
+ // GPT-5.6 and later take prompt_cache_options.ttl instead of prompt_cache_retention.
57
+ export function openAiUsesPromptCacheOptions(model) {
58
+ return atLeast(gptVersion(modelId(model)), 5, 6);
59
+ }
60
+
61
+ // Documented extended (24h) prompt_cache_retention list; dated snapshots read
62
+ // as their alias.
63
+ const EXTENDED_RETENTION = new Set([
64
+ 'gpt-5.5',
65
+ 'gpt-5.5-pro',
66
+ 'gpt-5.4',
67
+ 'gpt-5.2',
68
+ 'gpt-5.1-codex-max',
69
+ 'gpt-5.1',
70
+ 'gpt-5.1-codex',
71
+ 'gpt-5.1-codex-mini',
72
+ 'gpt-5.1-chat-latest',
73
+ 'gpt-5',
74
+ 'gpt-5-codex',
75
+ 'gpt-4.1',
76
+ ]);
77
+ export function openAiSupportsExtendedRetention(model) {
78
+ const id = modelId(model);
79
+ return EXTENDED_RETENTION.has(id) || EXTENDED_RETENTION.has(id.replace(SNAPSHOT_SUFFIX, ''));
80
+ }
@@ -102,7 +102,9 @@ export function createOpenAiOAuthDispatch({
102
102
  for (const [key, expiresAt] of provider._httpFallbackUntilByPoolKey) {
103
103
  if (!(expiresAt > now)) provider._httpFallbackUntilByPoolKey.delete(key);
104
104
  }
105
- return (provider._httpFallbackUntilByPoolKey.get(poolKey) || 0) > now;
105
+ // A forked transport scope follows its session's switch; it records its own.
106
+ const sessionUntil = opts.sessionId ? provider._httpFallbackUntilByPoolKey.get(opts.sessionId) || 0 : 0;
107
+ return Math.max(provider._httpFallbackUntilByPoolKey.get(poolKey) || 0, sessionUntil) > now;
106
108
  };
107
109
  const markStickyHttpFallback = () => {
108
110
  if (!poolKey) return;
@@ -20,6 +20,8 @@ import { httpLabel } from './openai-error-contract.mjs';
20
20
  import { openHttpSseResponse } from './openai-http-sse-request.mjs';
21
21
  import { createHttpSseWatchdogs } from './openai-http-sse-watchdogs.mjs';
22
22
  import { createHttpSseResponseState } from './openai-http-sse-response-state.mjs';
23
+ import { codexUserAgent, codexVersionHeader } from './codex-client-meta.mjs';
24
+ import { _codexBetaFeatures } from './openai-ws-headers.mjs';
23
25
  export { _envFlag };
24
26
 
25
27
  function _sseEventsFromBuffer(buffer) {
@@ -73,6 +75,11 @@ export function _buildOpenAIHttpFallbackHeaders({
73
75
  originator: CODEX_OAUTH_ORIGINATOR,
74
76
  'chatgpt-account-id': auth.account_id || '',
75
77
  'x-client-request-id': randomBytes(16).toString('hex'),
78
+ // Codex identity shared with the WS handshake (build_responses_headers);
79
+ // WS-only OpenAI-Beta value stays HTTP-specific above.
80
+ 'User-Agent': codexUserAgent(),
81
+ version: codexVersionHeader(),
82
+ 'x-codex-beta-features': _codexBetaFeatures(),
76
83
  };
77
84
  if (cacheKey && !statelessConversation) {
78
85
  const sid = String(cacheKey);
@@ -152,6 +152,11 @@ export class OpenAIOAuthProvider {
152
152
  return this.tokens;
153
153
  }
154
154
 
155
+ /** Drop a disposed transport scope's sticky transport record. */
156
+ releaseTransportScope(scope) {
157
+ this._httpFallbackUntilByPoolKey.delete(scope);
158
+ }
159
+
155
160
  send(messages, model, tools, sendOpts) {
156
161
  return withEffortConfigurationFallback('openai-oauth', model, sendOpts || {}, (opts) =>
157
162
  this._sendOnce(messages, model, tools, opts)
@@ -207,7 +212,8 @@ export class OpenAIOAuthProvider {
207
212
  // session. cacheKey is body.prompt_cache_key and affects prompt-cache
208
213
  // routing only; Codex handshake identity comes from sendOpts and remains
209
214
  // independent so a future cache-lane policy cannot merge conversations.
210
- const poolKey = opts.sessionId || null;
215
+ // A forked request runs in its own transport scope (transport-scope.mjs).
216
+ const poolKey = opts.transportScope || opts.sessionId || null;
211
217
  const cacheKey = body.prompt_cache_key || resolveProviderCacheKey(opts, 'openai-oauth');
212
218
  const iteration = Number.isFinite(Number(opts.iteration)) ? Number(opts.iteration) : null;
213
219
  const sendWs = typeof opts._sendViaWebSocketFn === 'function' ? opts._sendViaWebSocketFn : sendViaWebSocket;