@bitkyc08/opencodex 2.84.0 → 2.87.0

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 (518) hide show
  1. package/README.md +0 -4
  2. package/bin/ocx.mjs +61 -3
  3. package/gui/dist/assets/App-ZfYbLHkB.js +58 -0
  4. package/gui/dist/assets/App-wT3mXqFz.css +1 -0
  5. package/gui/dist/assets/{Tray-C9TGtwad.js → Tray-DCd-A1az.js} +1 -1
  6. package/gui/dist/assets/index-CfYDMj34.js +94 -0
  7. package/gui/dist/assets/index-DPeB9HpV.css +1 -0
  8. package/gui/dist/assets/quota-summary-ChvmKGOk.js +1 -0
  9. package/gui/dist/index.html +2 -2
  10. package/package.json +1 -2
  11. package/src/adapters/anthropic/beta-allowlist.ts +91 -11
  12. package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
  13. package/src/adapters/anthropic/client-identity.ts +1 -1
  14. package/src/adapters/anthropic/passthrough.ts +16 -3
  15. package/src/adapters/anthropic-progress.ts +84 -0
  16. package/src/adapters/anthropic.ts +108 -21
  17. package/src/adapters/azure.ts +19 -1
  18. package/src/adapters/base.ts +2 -0
  19. package/src/adapters/claude-cli/adapter.ts +111 -23
  20. package/src/adapters/claude-cli/profiles.ts +2 -1
  21. package/src/adapters/claude-cli/stable-replay.ts +108 -0
  22. package/src/adapters/claude-cli/usage-admission.ts +230 -0
  23. package/src/adapters/client-fingerprint.ts +24 -0
  24. package/src/adapters/coding-agent/protocol.ts +1 -1
  25. package/src/adapters/coding-agent/turn.ts +40 -11
  26. package/src/adapters/cursor/arg-codec.ts +17 -5
  27. package/src/adapters/cursor/catalog.ts +8 -0
  28. package/src/adapters/cursor/effort-map.ts +3 -0
  29. package/src/adapters/cursor/freeform-args.ts +75 -0
  30. package/src/adapters/cursor/protobuf-events.ts +36 -23
  31. package/src/adapters/dsh-account.ts +97 -0
  32. package/src/adapters/google-antigravity-wire.ts +22 -1
  33. package/src/adapters/google.ts +37 -10
  34. package/src/adapters/openai-chat/messages.ts +4 -3
  35. package/src/adapters/openai-chat/passthrough.ts +8 -2
  36. package/src/adapters/openai-chat/reasoning-replay.ts +52 -0
  37. package/src/adapters/openai-chat/response-events.ts +59 -1
  38. package/src/adapters/openai-chat.ts +8 -5
  39. package/src/adapters/openai-responses/compaction-search-history.ts +14 -7
  40. package/src/adapters/openai-responses/passthrough.ts +57 -125
  41. package/src/adapters/openai-responses/request-strips.ts +25 -3
  42. package/src/adapters/openai-responses/transport.ts +81 -0
  43. package/src/adapters/qoder/adapter.ts +44 -3
  44. package/src/adapters/registry.ts +5 -0
  45. package/src/adapters/zed.ts +26 -1
  46. package/src/advisor/activity.ts +55 -0
  47. package/src/advisor/budget.ts +62 -0
  48. package/src/advisor/consult.ts +223 -0
  49. package/src/advisor/context.ts +238 -0
  50. package/src/advisor/disclosure.ts +20 -0
  51. package/src/advisor/evidence-tool.ts +21 -0
  52. package/src/advisor/evidence.ts +117 -0
  53. package/src/advisor/runtime.ts +353 -0
  54. package/src/advisor/settings.ts +144 -0
  55. package/src/advisor/state.ts +369 -0
  56. package/src/advisor/synthetic-tool.ts +33 -0
  57. package/src/bridge/errors.ts +24 -1
  58. package/src/bridge/internal.ts +3 -1
  59. package/src/bridge/response-json.ts +18 -3
  60. package/src/bridge/sse.ts +58 -8
  61. package/src/bridge/terminal-refusal.ts +59 -0
  62. package/src/chat/inbound.ts +30 -6
  63. package/src/chat/outbound.ts +5 -0
  64. package/src/claude/desktop-3p-library.ts +72 -7
  65. package/src/claude/desktop-3p.ts +75 -19
  66. package/src/claude/desktop-first-party.ts +1 -1
  67. package/src/claude/desktop-picker-platform.ts +4 -0
  68. package/src/claude/desktop-picker-profile.ts +11 -4
  69. package/src/claude/desktop-picker.ts +15 -8
  70. package/src/claude/desktop-profile.ts +10 -1
  71. package/src/claude/desktop-remote-store-io.ts +5 -3
  72. package/src/claude/desktop-system-proxy.ts +50 -4
  73. package/src/claude/inbound-content-options.ts +11 -0
  74. package/src/claude/inbound.ts +154 -50
  75. package/src/claude/intercept/local-ca.ts +8 -1
  76. package/src/claude/intercept/picker-ca-startup.ts +2 -1
  77. package/src/claude/intercept/picker-runtime.ts +6 -5
  78. package/src/claude/intercept/picker-trust-windows.ts +338 -0
  79. package/src/claude/intercept/picker-trust.ts +19 -0
  80. package/src/claude/intercept/port-policy.ts +30 -0
  81. package/src/claude/intercept/runtime.ts +97 -94
  82. package/src/claude/model-default-settings.ts +154 -0
  83. package/src/claude/model-info.ts +7 -7
  84. package/src/claude/outbound.ts +51 -19
  85. package/src/cli/account-api.ts +1 -0
  86. package/src/cli/account-policy-dto.ts +6 -0
  87. package/src/cli/account-policy.ts +34 -5
  88. package/src/cli/account-preservation.ts +44 -0
  89. package/src/cli/account.ts +8 -2
  90. package/src/cli/advisor.ts +165 -0
  91. package/src/cli/auxiliary-listener-preflight.ts +37 -0
  92. package/src/cli/capabilities-accounts.ts +20 -1
  93. package/src/cli/capabilities-agents-routing.ts +23 -2
  94. package/src/cli/capabilities-base.ts +39 -11
  95. package/src/cli/capabilities-observe-system.ts +63 -3
  96. package/src/cli/capabilities-provider-models.ts +11 -0
  97. package/src/cli/chatgpt-command.ts +35 -14
  98. package/src/cli/claude.ts +46 -6
  99. package/src/cli/codex-cli-update.ts +151 -41
  100. package/src/cli/codex-provider.ts +44 -0
  101. package/src/cli/combo-input.ts +10 -1
  102. package/src/cli/combo-result.ts +1 -1
  103. package/src/cli/combo.ts +2 -1
  104. package/src/cli/cross-home-owner.ts +17 -14
  105. package/src/cli/dispatch.ts +30 -5
  106. package/src/cli/doctor.ts +15 -1
  107. package/src/cli/ensure-desktop-cold-start.ts +382 -0
  108. package/src/cli/export-command.ts +1 -1
  109. package/src/cli/help.ts +4 -2
  110. package/src/cli/index.ts +14 -5
  111. package/src/cli/integration-plan-dto.ts +3 -0
  112. package/src/cli/log-history.ts +172 -0
  113. package/src/cli/models-runtime-subcommands.ts +1 -0
  114. package/src/cli/models-runtime.ts +72 -8
  115. package/src/cli/observe-stream.ts +2 -0
  116. package/src/cli/observe.ts +16 -4
  117. package/src/cli/provider.ts +27 -5
  118. package/src/cli/registry.ts +41 -9
  119. package/src/cli/restart-scope.ts +3 -1
  120. package/src/cli/runtime-api.ts +5 -3
  121. package/src/cli/system-command.ts +40 -8
  122. package/src/cli/uninstall-client-state.ts +32 -0
  123. package/src/cli/usage-compare.ts +309 -0
  124. package/src/cli/usage-model-search.ts +4 -4
  125. package/src/cli/usage-report.ts +2 -2
  126. package/src/cli/v2.ts +1 -1
  127. package/src/client/machine-listener.ts +1 -3
  128. package/src/client/runtime.ts +1 -0
  129. package/src/clients/client-path.ts +51 -0
  130. package/src/clients/config-export/contracts.ts +3 -1
  131. package/src/clients/config-export/model-metadata.ts +3 -2
  132. package/src/clients/config-export/qoder.ts +93 -0
  133. package/src/clients/config-export.ts +35 -48
  134. package/src/clients/gentle-shell-path.ts +87 -0
  135. package/src/codex/account-auto-switch.ts +2 -0
  136. package/src/codex/account-identity.ts +29 -0
  137. package/src/codex/account-label.ts +1 -1
  138. package/src/codex/account-lifecycle.ts +21 -5
  139. package/src/codex/account-preservation.ts +28 -0
  140. package/src/codex/account-use-remaining.ts +23 -0
  141. package/src/codex/app-server-processes.ts +97 -7
  142. package/src/codex/app-server-restart-service.ts +55 -4
  143. package/src/codex/auth-api/account-list.ts +4 -0
  144. package/src/codex/auth-api/account-pause-group.ts +6 -50
  145. package/src/codex/auth-api/account-preservation.ts +57 -0
  146. package/src/codex/auth-api/pool-mode-gate.ts +5 -2
  147. package/src/codex/auth-api/routes.ts +8 -0
  148. package/src/codex/auth-api/use-remaining-route.ts +36 -0
  149. package/src/codex/auth-api.ts +0 -1
  150. package/src/codex/auth-context.ts +81 -7
  151. package/src/codex/autostart-health.ts +4 -0
  152. package/src/codex/catalog/auto-review.ts +20 -3
  153. package/src/codex/catalog/build-entries.ts +19 -2
  154. package/src/codex/catalog/combo-member.ts +14 -5
  155. package/src/codex/catalog/configured-tiers.ts +50 -0
  156. package/src/codex/catalog/effort.ts +4 -1
  157. package/src/codex/catalog/gather-capture.ts +2 -0
  158. package/src/codex/catalog/metadata.ts +11 -9
  159. package/src/codex/catalog/model-hints.ts +42 -19
  160. package/src/codex/catalog/model-visibility.ts +3 -1
  161. package/src/codex/catalog/native-ultrafast.ts +106 -0
  162. package/src/codex/catalog/parsing.ts +35 -86
  163. package/src/codex/catalog/provider-models.ts +40 -34
  164. package/src/codex/catalog/retained-sync.ts +2 -0
  165. package/src/codex/catalog/routed-gather.ts +33 -16
  166. package/src/codex/catalog/vendor-context.ts +82 -0
  167. package/src/codex/cli-install-provenance.ts +105 -17
  168. package/src/codex/cli-update-plan.ts +545 -0
  169. package/src/codex/config-write-lock.ts +63 -4
  170. package/src/codex/convergence.ts +2 -0
  171. package/src/codex/desktop-app/picker-freshness.ts +96 -0
  172. package/src/codex/desktop-app/types.ts +2 -0
  173. package/src/codex/desktop-app/windows.ts +29 -16
  174. package/src/codex/desktop-app-restart.ts +25 -2
  175. package/src/codex/desktop-compatibility/certificate-service.ts +99 -0
  176. package/src/codex/desktop-compatibility/certificate-store.ts +193 -0
  177. package/src/codex/desktop-compatibility/connection-store.ts +87 -0
  178. package/src/codex/desktop-compatibility/installed-build.ts +73 -0
  179. package/src/codex/desktop-compatibility/json-body.ts +29 -0
  180. package/src/codex/desktop-compatibility/native-identity.ts +62 -0
  181. package/src/codex/desktop-compatibility/relay-listener.ts +93 -0
  182. package/src/codex/desktop-compatibility/routing-binding.ts +10 -0
  183. package/src/codex/desktop-compatibility/routing-preflight.ts +69 -0
  184. package/src/codex/desktop-compatibility/runtime-ownership.ts +28 -0
  185. package/src/codex/desktop-compatibility/runtime.ts +182 -0
  186. package/src/codex/desktop-compatibility/service.ts +30 -0
  187. package/src/codex/desktop-compatibility/startup-settings.ts +50 -0
  188. package/src/codex/desktop-compatibility/usage-activation.ts +86 -0
  189. package/src/codex/desktop-compatibility/usage-controlled-fetch.ts +59 -0
  190. package/src/codex/desktop-compatibility/usage-controller.ts +107 -0
  191. package/src/codex/desktop-compatibility/usage-policy.ts +59 -0
  192. package/src/codex/desktop-compatibility/usage-refresh.ts +33 -0
  193. package/src/codex/desktop-compatibility/usage-sse-controller.ts +86 -0
  194. package/src/codex/desktop-compatibility/windows-activation-source.ts +44 -0
  195. package/src/codex/desktop-compatibility/windows-certificate-trust.ts +81 -0
  196. package/src/codex/desktop-compatibility/windows-key-protection.ts +165 -0
  197. package/src/codex/desktop-compatibility/windows-package-command.ts +86 -0
  198. package/src/codex/desktop-compatibility/windows-package-launch.ts +28 -0
  199. package/src/codex/features.ts +85 -45
  200. package/src/codex/history-provider.ts +1 -1
  201. package/src/codex/inject/config-write-section.ts +4 -1
  202. package/src/codex/inject/history-failure.ts +27 -0
  203. package/src/codex/inject/remove.ts +18 -6
  204. package/src/codex/inject/restore.ts +24 -2
  205. package/src/codex/inject/routing-classify.ts +4 -3
  206. package/src/codex/inject.ts +18 -27
  207. package/src/codex/journal.ts +16 -1
  208. package/src/codex/main-account-hard-lock.ts +30 -1
  209. package/src/codex/main-account.ts +99 -15
  210. package/src/codex/native-main-refresh-mode.ts +217 -0
  211. package/src/codex/native-profile-startup.ts +1 -1
  212. package/src/codex/ocx-compaction-history.ts +12 -10
  213. package/src/codex/paths.ts +86 -1
  214. package/src/codex/provider-routing.ts +174 -0
  215. package/src/codex/refresh.ts +2 -2
  216. package/src/codex/routing/health-store.ts +2 -2
  217. package/src/codex/routing/pool-recovery.ts +79 -0
  218. package/src/codex/routing/selection.ts +4 -3
  219. package/src/codex/routing/thread-affinity.ts +1 -1
  220. package/src/codex/shim-diagnostics.ts +6 -0
  221. package/src/codex/shim-overlay.ts +7 -2
  222. package/src/codex/signed-in-identity.ts +43 -0
  223. package/src/codex/subagent-model-fallback.ts +1 -1
  224. package/src/codex/sync.ts +6 -1
  225. package/src/codex/user-identity.ts +16 -5
  226. package/src/codex/windows-local-appdata.ts +84 -0
  227. package/src/combos/failover.ts +6 -1
  228. package/src/combos/index.ts +1 -0
  229. package/src/combos/resolve.ts +46 -10
  230. package/src/combos/types.ts +15 -0
  231. package/src/config/diagnostics.ts +35 -7
  232. package/src/config/live-reconcile.ts +51 -2
  233. package/src/config/load-degrade.ts +23 -1
  234. package/src/config/opencode-wire-upgrade.ts +54 -0
  235. package/src/config/opencode-zen-upgrade.ts +52 -0
  236. package/src/config/owner-registry.ts +22 -17
  237. package/src/config/paths.ts +10 -3
  238. package/src/config/provider-validation.ts +45 -2
  239. package/src/config/schema/config-schema.ts +39 -0
  240. package/src/config/schema/desktop-compatibility.ts +9 -0
  241. package/src/config/schema/leaf-validators.ts +39 -9
  242. package/src/config/schema/main-account-hard-lock-fallback.ts +26 -0
  243. package/src/config/schema/native-reasoning-retention.ts +26 -0
  244. package/src/config.ts +2 -0
  245. package/src/generated/compatibility-version.json +962 -350
  246. package/src/generated/model-metadata.ts +1 -1
  247. package/src/grok/sync.ts +1 -1
  248. package/src/images/loop.ts +46 -8
  249. package/src/integrations/catalog-refresh.ts +1 -1
  250. package/src/integrations/config-io.ts +20 -2
  251. package/src/integrations/journal.ts +15 -1
  252. package/src/integrations/mutation-plan.ts +2 -0
  253. package/src/integrations/registry.ts +15 -0
  254. package/src/integrations/store.ts +3 -0
  255. package/src/integrations/writer.ts +10 -1
  256. package/src/lib/advisor-activation.ts +16 -0
  257. package/src/lib/background-work.ts +65 -0
  258. package/src/lib/bounded-file-read.ts +58 -0
  259. package/src/lib/bun-path-runtime.d.mts +10 -1
  260. package/src/lib/bun-path-runtime.mjs +62 -3
  261. package/src/lib/codex-restart-contract.ts +15 -0
  262. package/src/lib/desktop-proxy-route.ts +30 -0
  263. package/src/lib/desktop-upstream-tunnel.ts +72 -0
  264. package/src/lib/empty-tool-catalog.ts +62 -0
  265. package/src/lib/errors.ts +26 -3
  266. package/src/lib/gcp-adc.ts +96 -9
  267. package/src/lib/gcp-credential-input.ts +12 -0
  268. package/src/lib/lab-live-route-production.ts +5 -0
  269. package/src/lib/local-internal-call-capability.ts +55 -0
  270. package/src/lib/opaque-proxy-tunnel.ts +217 -0
  271. package/src/lib/package-tree-integrity.ts +2 -2
  272. package/src/lib/redact.ts +2 -2
  273. package/src/lib/socks5-fetch.ts +48 -71
  274. package/src/lib/socks5-handshake.ts +112 -0
  275. package/src/lib/translator-budget.ts +7 -1
  276. package/src/oauth/account-quota-rank.ts +69 -2
  277. package/src/oauth/anthropic-account-refusal.ts +20 -2
  278. package/src/oauth/anthropic-oauth-definitions.ts +3 -1
  279. package/src/oauth/anthropic-routing.ts +1 -21
  280. package/src/oauth/anthropic.ts +38 -7
  281. package/src/oauth/callback-server.ts +27 -1
  282. package/src/oauth/chatgpt-device.ts +1 -1
  283. package/src/oauth/chatgpt-shared.ts +83 -0
  284. package/src/oauth/chatgpt.ts +8 -72
  285. package/src/oauth/dsh.ts +203 -0
  286. package/src/oauth/generic-account-failover.ts +62 -12
  287. package/src/oauth/generic-session-affinity.ts +125 -0
  288. package/src/oauth/index.ts +188 -111
  289. package/src/oauth/kiro-device-login.ts +2 -1
  290. package/src/oauth/kiro.ts +7 -1
  291. package/src/oauth/local-token-detect.ts +21 -1
  292. package/src/oauth/login-cli-errors.ts +44 -0
  293. package/src/oauth/login-cli.ts +69 -7
  294. package/src/oauth/login-flow-state.ts +371 -23
  295. package/src/oauth/meta-muse-errors.ts +41 -0
  296. package/src/oauth/meta-muse-keychain.ts +52 -0
  297. package/src/oauth/meta-muse.ts +51 -84
  298. package/src/oauth/model-discovery-auth.ts +3 -0
  299. package/src/oauth/pool-settings-capability.ts +4 -2
  300. package/src/oauth/refresh-flight-retirement.ts +48 -0
  301. package/src/oauth/session-affinity-key.ts +23 -0
  302. package/src/oauth/store-anthropic-instance.ts +9 -2
  303. package/src/oauth/store.ts +12 -5
  304. package/src/protocols/codecs/chat-ir.ts +467 -0
  305. package/src/protocols/codecs/chat.ts +10 -1
  306. package/src/protocols/codecs/messages-ir.ts +500 -0
  307. package/src/protocols/encoders/adapter-events.ts +5 -4
  308. package/src/protocols/encoders/messages.ts +9 -6
  309. package/src/protocols/features.ts +10 -2
  310. package/src/protocols/path.ts +11 -1
  311. package/src/protocols/plan-snapshot.ts +39 -16
  312. package/src/protocols/plan.ts +9 -1
  313. package/src/protocols/provider-summary.ts +2 -1
  314. package/src/protocols/settings.ts +8 -0
  315. package/src/providers/antigravity-account-roster.ts +102 -0
  316. package/src/providers/antigravity-models.ts +85 -7
  317. package/src/providers/api-key-cooldowns.ts +49 -0
  318. package/src/providers/api-key-resolve.ts +11 -6
  319. package/src/providers/api-key-response-ownership.ts +57 -0
  320. package/src/providers/api-key-selection.ts +31 -6
  321. package/src/providers/api-keys.ts +214 -3
  322. package/src/providers/claude-cli-usage.ts +96 -0
  323. package/src/providers/dsh-account-destination.ts +31 -0
  324. package/src/providers/dsh-account-models.ts +41 -0
  325. package/src/providers/gcp-credential-cleanup.ts +59 -0
  326. package/src/providers/key-failover.ts +54 -50
  327. package/src/providers/key-store.ts +7 -2
  328. package/src/providers/model-rename-fields.ts +5 -0
  329. package/src/providers/model-rename-migration.ts +7 -5
  330. package/src/providers/openai-tiers-destination.ts +11 -2
  331. package/src/providers/openai-tiers.ts +5 -12
  332. package/src/providers/opencode-go-transport.ts +3 -1
  333. package/src/providers/quota/account-cache.ts +6 -5
  334. package/src/providers/quota/account-row.ts +34 -0
  335. package/src/providers/quota/antigravity.ts +28 -7
  336. package/src/providers/quota/dsh-account.ts +70 -0
  337. package/src/providers/quota/vendor-probes-oauth.ts +1 -93
  338. package/src/providers/quota-types.ts +2 -0
  339. package/src/providers/quota.ts +14 -20
  340. package/src/providers/registry/entries-core.ts +44 -14
  341. package/src/providers/registry/entries-extended.ts +19 -0
  342. package/src/providers/registry/types.ts +1 -1
  343. package/src/providers/request-pacing.ts +77 -19
  344. package/src/providers/routed-config.ts +339 -0
  345. package/src/providers/service-tier.ts +2 -1
  346. package/src/quota/window-mapping.ts +5 -2
  347. package/src/responses/anthropic-progress.ts +34 -0
  348. package/src/responses/assistant-replay.ts +35 -0
  349. package/src/responses/compaction-history-framing.ts +65 -0
  350. package/src/responses/compaction.ts +6 -1
  351. package/src/responses/incomplete-reason.ts +31 -0
  352. package/src/responses/parser.ts +78 -22
  353. package/src/responses/reasoning-envelope.ts +4 -0
  354. package/src/responses/reasoning-replay-cache.ts +24 -2
  355. package/src/responses/reasoning-retention.ts +173 -0
  356. package/src/responses/retained-compaction.ts +46 -0
  357. package/src/responses/schema.ts +23 -0
  358. package/src/responses/state.ts +32 -29
  359. package/src/router.ts +8 -321
  360. package/src/routing/health.ts +37 -22
  361. package/src/routing/history/build-file.ts +92 -0
  362. package/src/routing/history/indexer.ts +254 -221
  363. package/src/routing/history/ingest.ts +242 -0
  364. package/src/routing/history/rebuild-job.ts +111 -0
  365. package/src/routing/history/rebuild-protocol.ts +15 -0
  366. package/src/routing/history/rebuild-worker.ts +34 -0
  367. package/src/routing/profile.ts +1 -1
  368. package/src/server/admission-model-scope.ts +21 -1
  369. package/src/server/antigravity-direct-eligibility.ts +208 -0
  370. package/src/server/auth-cors.ts +15 -0
  371. package/src/server/chat-completions.ts +82 -10
  372. package/src/server/chat-native-reasoning.ts +123 -0
  373. package/src/server/chat-native-sse.ts +110 -7
  374. package/src/server/chat-native.ts +76 -17
  375. package/src/server/claude-messages.ts +164 -433
  376. package/src/server/effort-policy.ts +1 -1
  377. package/src/server/images.ts +15 -2
  378. package/src/server/index/desktop-compatibility-startup.ts +56 -0
  379. package/src/server/index/model-alias-id.ts +36 -0
  380. package/src/server/index/optional-listeners.ts +2 -0
  381. package/src/server/index/serve-options.ts +11 -3
  382. package/src/server/index/startup-warnings.ts +11 -0
  383. package/src/server/index/websocket-handler.ts +9 -0
  384. package/src/server/index.ts +14 -11
  385. package/src/server/inference/advisor-diagnostics.ts +31 -0
  386. package/src/server/inference/client-encoder-delivery.ts +6 -5
  387. package/src/server/login-shell-path.ts +146 -0
  388. package/src/server/management/advisor-routes.ts +202 -0
  389. package/src/server/management/agent-settings-routes.ts +22 -4
  390. package/src/server/management/claude-desktop-picker-routes.ts +1 -1
  391. package/src/server/management/combo-routes.ts +176 -50
  392. package/src/server/management/companion-routes.ts +4 -0
  393. package/src/server/management/config-routes.ts +77 -6
  394. package/src/server/management/context.ts +4 -0
  395. package/src/server/management/cursor-integration-routes.ts +1 -1
  396. package/src/server/management/desktop-compatibility-routes.ts +46 -0
  397. package/src/server/management/desktop-compatibility-runtime-routes.ts +46 -0
  398. package/src/server/management/desktop-compatibility-settings-routes.ts +27 -0
  399. package/src/server/management/model-routes.ts +13 -8
  400. package/src/server/management/model-rows.ts +14 -0
  401. package/src/server/management/native-integration-routes.ts +2 -7
  402. package/src/server/management/native-reasoning-retention-routes.ts +41 -0
  403. package/src/server/management/oauth-account-routes.ts +87 -14
  404. package/src/server/management/protocol-settings-patch.ts +1 -0
  405. package/src/server/management/provider-gcp-credential-routes.ts +29 -0
  406. package/src/server/management/provider-key-pacing-routes.ts +31 -0
  407. package/src/server/management/provider-overwrite-carry.ts +7 -0
  408. package/src/server/management/provider-routes.ts +25 -30
  409. package/src/server/management/route-registry.ts +21 -1
  410. package/src/server/management/sibling-guard.ts +1 -0
  411. package/src/server/management-api.ts +9 -1
  412. package/src/server/messages-antigravity-direct.ts +195 -0
  413. package/src/server/messages-native-tool-guard.ts +185 -0
  414. package/src/server/messages-native.ts +106 -22
  415. package/src/server/messages-shared.ts +431 -0
  416. package/src/server/relay.ts +1 -1
  417. package/src/server/request-log-terminal-status.ts +1 -1
  418. package/src/server/request-log.ts +13 -1
  419. package/src/server/responses/account-change-state.ts +8 -2
  420. package/src/server/responses/adapter-continuation.ts +48 -19
  421. package/src/server/responses/adapter-delivery.ts +43 -8
  422. package/src/server/responses/adapter-dispatch.ts +48 -4
  423. package/src/server/responses/advisor-plan-slot.ts +27 -0
  424. package/src/server/responses/advisor-retention.ts +117 -0
  425. package/src/server/responses/advisor-slot.ts +368 -0
  426. package/src/server/responses/code-mode-collab-surface.ts +116 -8
  427. package/src/server/responses/codex-ws-wire.ts +15 -8
  428. package/src/server/responses/compact.ts +303 -125
  429. package/src/server/responses/compaction-recovery.ts +18 -10
  430. package/src/server/responses/compaction-retention.ts +61 -0
  431. package/src/server/responses/context-overflow.ts +11 -6
  432. package/src/server/responses/core-auth.ts +6 -0
  433. package/src/server/responses/core-codex-account.ts +11 -1
  434. package/src/server/responses/core-combo-failure.ts +12 -1
  435. package/src/server/responses/core-combo.ts +141 -36
  436. package/src/server/responses/core-errors.ts +3 -3
  437. package/src/server/responses/core-lifetime.ts +7 -2
  438. package/src/server/responses/core-normalize.ts +11 -0
  439. package/src/server/responses/core-opaque-recovery.ts +35 -0
  440. package/src/server/responses/core-options.ts +51 -0
  441. package/src/server/responses/core-pipeline.ts +141 -0
  442. package/src/server/responses/core-replay.ts +25 -6
  443. package/src/server/responses/core.ts +3 -116
  444. package/src/server/responses/fetch-helpers.ts +73 -19
  445. package/src/server/responses/main-hard-lock-routing.ts +109 -0
  446. package/src/server/responses/native-response-control.ts +4 -2
  447. package/src/server/responses/passthrough-delivery.ts +19 -11
  448. package/src/server/responses/passthrough-dispatch.ts +29 -16
  449. package/src/server/responses/request-prepare.ts +144 -17
  450. package/src/server/responses/request-sidecar-auth.ts +2 -2
  451. package/src/server/responses/request-transport.ts +120 -27
  452. package/src/server/responses/response-effects.ts +1 -0
  453. package/src/server/responses/run-turn-execution.ts +166 -38
  454. package/src/server/responses/sidecar-execution.ts +98 -5
  455. package/src/server/responses/terminal-guard.ts +4 -17
  456. package/src/server/responses-undeclared-tool-guard.ts +30 -9
  457. package/src/server/startup-action-control.ts +16 -2
  458. package/src/server/startup-health-cache.ts +1 -0
  459. package/src/service/auth-preflight.ts +71 -0
  460. package/src/service/cli.ts +4 -2
  461. package/src/service/definition.ts +97 -0
  462. package/src/service/desktop-startup.ts +14 -0
  463. package/src/service/guards.ts +1 -61
  464. package/src/service/health-sentinel-linux.ts +112 -0
  465. package/src/service/health-sentinel-main.ts +99 -61
  466. package/src/service/health-sentinel-probe.ts +24 -7
  467. package/src/service/health.ts +5 -89
  468. package/src/service/launchd.ts +27 -7
  469. package/src/service/logging.ts +135 -0
  470. package/src/service/repair.ts +2 -1
  471. package/src/service/state.ts +7 -8
  472. package/src/service/systemd.ts +1 -1
  473. package/src/service/windows-guarded-manager.ts +2 -1
  474. package/src/service/windows-ops.ts +1 -1
  475. package/src/service/windows-scheduler.ts +2 -7
  476. package/src/service/windows-taskxml.ts +2 -2
  477. package/src/service/windows-wscript.ts +14 -0
  478. package/src/service.ts +4 -2
  479. package/src/sidecar/auth.ts +2 -0
  480. package/src/tray/windows-tray.ps1 +43 -24
  481. package/src/types/config.ts +124 -6
  482. package/src/types/opencode-go.ts +61 -0
  483. package/src/types/opencode-zen.ts +29 -0
  484. package/src/types/provider.ts +39 -6
  485. package/src/types/request.ts +38 -2
  486. package/src/types/tools.ts +2 -0
  487. package/src/types/wire.ts +29 -37
  488. package/src/types.ts +1 -0
  489. package/src/update/async-check.ts +1 -1
  490. package/src/update/badge.ts +2 -2
  491. package/src/update/index.ts +88 -15
  492. package/src/update/job-supervised-restart.ts +107 -0
  493. package/src/update/job.ts +32 -32
  494. package/src/update/notify.ts +1 -1
  495. package/src/update/npm-invocation.mjs +12 -2
  496. package/src/update/refresh-scheduler.ts +2 -2
  497. package/src/update/supervised-recovery.d.mts +27 -0
  498. package/src/update/supervised-recovery.mjs +157 -0
  499. package/src/usage/cache-diagnostic.ts +2 -0
  500. package/src/usage/cost.ts +48 -12
  501. package/src/usage/expected-prices.ts +15 -0
  502. package/src/usage/ledger-retention.ts +2 -1
  503. package/src/usage/ledger-scanner.ts +6 -5
  504. package/src/usage/log.ts +17 -8
  505. package/src/usage/summary.ts +22 -9
  506. package/src/usage/user-cost-overlays.ts +14 -19
  507. package/src/usage/user-cost-validation.ts +38 -0
  508. package/src/vision/eligibility.ts +13 -0
  509. package/src/web-search/gemini-executor.ts +2 -2
  510. package/src/web-search/loop.ts +55 -5
  511. package/src/web-search/progress-stream.ts +4 -1
  512. package/src/web-search/run-turn-loop.ts +9 -1
  513. package/assets/sponsors/packycode.png +0 -0
  514. package/gui/dist/assets/App-CSJvmjNs.css +0 -1
  515. package/gui/dist/assets/App-CZtqiGcw.js +0 -56
  516. package/gui/dist/assets/index-BB6uK6tU.css +0 -1
  517. package/gui/dist/assets/index-CTm4l-HQ.js +0 -94
  518. package/gui/dist/assets/quota-summary-BbEeRfPY.js +0 -1
@@ -0,0 +1,500 @@
1
+ /**
2
+ * Anthropic Messages -> IR, directly (the Antigravity direct lane).
3
+ *
4
+ * The bridge decodes a Messages conversation twice: `anthropicToResponsesTranslation`
5
+ * (`src/claude/inbound.ts`) projects it into Responses items, then `parseRequest`
6
+ * (`src/responses/parser.ts`) turns those items into the IR. This module walks the Messages body
7
+ * once and builds the IR conversation itself: the system prompt (including the
8
+ * `stabilizePromptCache` relocation), user turns with images and documents, tool calls and
9
+ * results (including `tool_reference` markers, tool errors and blocked-skill elision), thinking
10
+ * and redacted thinking with their ocxr1 envelopes, the native reasoning replay map, and the
11
+ * tool catalog. It is the Messages twin of `chat-ir.ts`.
12
+ *
13
+ * Contract: for every Messages body the bridge accepts, `messagesConversationToIr(body, cc,
14
+ * budget, model)` equals the `context` of `parseRequest(anthropicToResponsesTranslation(body,
15
+ * cc).body)` (reasoning item ids are random on both sides), and every body the bridge refuses in
16
+ * its conversation walk is refused here with the same `AnthropicRequestError` message.
17
+ * `tests/responses/protocol-messages-ir-parity.test.ts` holds both sides over a fixture corpus.
18
+ * Envelopes are encoded and charged against the request budget exactly as the translator does,
19
+ * then decoded exactly as the parser does, so the signature an adapter reads is the same string.
20
+ *
21
+ * Request settings (model resolution, sampling, tool choice, format, prompt-cache key, reasoning)
22
+ * are not decoded here: they travel through the Responses core on `anthropicSettingsTranslation`.
23
+ * A hosted web-search tool never reaches this decoder: the lane's eligibility rule keeps it on the
24
+ * bridge, where the sidecar reads it.
25
+ */
26
+ import {
27
+ anthropicDocumentData,
28
+ anthropicImageBlockUrl,
29
+ anthropicSystemLayout,
30
+ blockedSkillCallIds,
31
+ documentTitle,
32
+ effectiveBlockedSkillNames,
33
+ maybeElideSkillText,
34
+ skillElisionStub,
35
+ systemMessageText,
36
+ } from "../../claude/inbound";
37
+ import { toolsToResponses } from "../../claude/inbound-content-options";
38
+ import { AnthropicRequestError, isRec, type Rec } from "../../claude/inbound-records";
39
+ import { hasRoutedIdentity, nameRoutedIdentity } from "../../adapters/identity";
40
+ import type { TranslatorBudget } from "../../lib/translator-budget";
41
+ import { inlineDocumentFromDataUrl, inlineDocumentMarker } from "../../responses/inline-document";
42
+ import { functionCallArgumentsFromText } from "../../responses/parser";
43
+ import { decodeReasoningEnvelope, encodeReasoningEnvelope, OCX_REASONING_PREFIX } from "../../responses/reasoning-envelope";
44
+ import { normalizeVisualizationContext } from "../../responses/visualization-directives";
45
+ import type { PolicyRequestEvidence } from "../../routing/evaluator";
46
+ import { createToolChoiceResolver, namespacedToolName } from "../../types";
47
+ import type {
48
+ OcxAssistantMessage,
49
+ OcxClaudeCodeConfig,
50
+ OcxContentPart,
51
+ OcxContext,
52
+ OcxMessage,
53
+ OcxParsedRequest,
54
+ OcxTextContent,
55
+ OcxThinkingContent,
56
+ OcxTool,
57
+ } from "../../types";
58
+ import { normalizedParameters } from "./chat-ir";
59
+
60
+ /** The translator refuses an undecodable proxy envelope with this message; the ingress retries it. */
61
+ export const MALFORMED_REASONING_SIGNATURE = "malformed ocxr1 reasoning signature";
62
+
63
+ function nameDestination(text: string, modelId: string): string {
64
+ return hasRoutedIdentity(text) ? nameRoutedIdentity(text, modelId) : text;
65
+ }
66
+
67
+ function reasoningItemId(): string {
68
+ return `rs_${crypto.randomUUID().replace(/-/g, "")}`;
69
+ }
70
+
71
+ /** The parser collapses a lone text part to a plain string; images and documents stay structured. */
72
+ function collapsed(parts: OcxContentPart[]): string | OcxContentPart[] {
73
+ return parts.length === 1 && parts[0]!.type === "text" ? parts[0]!.text : parts;
74
+ }
75
+
76
+ /** One entry of a tool result as the translator lists it, before the parser reads it. */
77
+ type ToolResultEntry = { text: string } | { image: string };
78
+
79
+ /**
80
+ * A `tool_result` block's content as the IR carries it: the translator's `toolResultOutput`
81
+ * (error prefix, `tool_reference` markers, image references, document markers) read through the
82
+ * parser's `outputToToolResultContent` (text joined unless an image survives).
83
+ */
84
+ function toolResultContent(block: Rec): string | OcxContentPart[] {
85
+ const isError = block.is_error === true;
86
+ const content = block.content;
87
+ if (typeof content === "string") return isError ? `[tool error] ${content}` : content;
88
+ if (!Array.isArray(content)) return isError ? "[tool error]" : "";
89
+ const out: ToolResultEntry[] = [];
90
+ for (const item of content) {
91
+ if (!isRec(item)) continue;
92
+ if (item.type === "text" && typeof item.text === "string") {
93
+ out.push({ text: item.text });
94
+ } else if (item.type === "tool_reference" && typeof item.tool_name === "string" && item.tool_name.length > 0) {
95
+ const prev = out[out.length - 1];
96
+ const lead = prev !== undefined && "text" in prev && !prev.text.endsWith("\n") ? "\n" : "";
97
+ out.push({ text: `${lead}Tool loaded: ${item.tool_name}\n` });
98
+ } else if (item.type === "image") {
99
+ const url = anthropicImageBlockUrl(item);
100
+ if (url !== null) out.push({ image: url });
101
+ } else if (item.type === "document") {
102
+ out.push({ text: inlineDocumentMarker(documentTitle(item)) });
103
+ }
104
+ }
105
+ if (isError) out.unshift({ text: "[tool error]" });
106
+ if (out.length === 0) return isError ? "[tool error]" : "";
107
+ const parts: OcxContentPart[] = [];
108
+ let hasImage = false;
109
+ for (const entry of out) {
110
+ if ("text" in entry) parts.push({ type: "text", text: entry.text });
111
+ else if (entry.image.length > 0) {
112
+ parts.push({ type: "image", imageUrl: entry.image });
113
+ hasImage = true;
114
+ }
115
+ }
116
+ if (!hasImage) return parts.map(part => (part.type === "text" ? part.text : "")).join("");
117
+ return parts;
118
+ }
119
+
120
+ /**
121
+ * The tool catalog: the translator's function declarations (a hosted web-search tool and
122
+ * schema-less server tools are not function tools) read through the parser's `buildTools` and
123
+ * deduplicated by name as its catalog merge does.
124
+ */
125
+ function toolCatalog(raw: unknown): OcxTool[] {
126
+ if (!Array.isArray(raw)) return [];
127
+ const declared: OcxTool[] = [];
128
+ for (const entry of raw) {
129
+ if (!isRec(entry)) continue;
130
+ const type = typeof entry.type === "string" ? entry.type : "";
131
+ if (type.startsWith("web_search")) continue;
132
+ if (typeof entry.name !== "string" || entry.name.length === 0 || !isRec(entry.input_schema)) continue;
133
+ const tool: OcxTool = {
134
+ name: entry.name,
135
+ description: typeof entry.description === "string" ? entry.description : "",
136
+ parameters: normalizedParameters(entry.input_schema),
137
+ strict: typeof entry.strict === "boolean" ? entry.strict : false,
138
+ };
139
+ if (Array.isArray(entry.allowed_callers)) {
140
+ tool.allowedCallers = entry.allowed_callers.filter((caller): caller is string => typeof caller === "string");
141
+ }
142
+ declared.push(tool);
143
+ }
144
+ const seen = new Set<string>();
145
+ return declared.filter(tool => {
146
+ const key = namespacedToolName(tool.namespace, tool.name);
147
+ if (seen.has(key)) return false;
148
+ seen.add(key);
149
+ return true;
150
+ });
151
+ }
152
+
153
+ export interface MessagesIrConversation {
154
+ /** The resolved model the conversation was decoded for; identity naming and placeholders use it. */
155
+ modelId: string;
156
+ context: OcxContext;
157
+ /** The native reasoning blobs the translator would have recorded, keyed by blob. */
158
+ nativeReasoningReplay: ReadonlyMap<string, string>;
159
+ }
160
+
161
+ /**
162
+ * Decode a Messages body's conversation straight into the IR context. `modelId` is the resolved
163
+ * model the bridge body would carry. Throws `AnthropicRequestError` exactly where the translator's
164
+ * conversation walk would, and `TranslatorBudgetExceededError` where its envelope charges would.
165
+ */
166
+ export function messagesConversationToIr(
167
+ raw: unknown,
168
+ cc: OcxClaudeCodeConfig | undefined,
169
+ budget: TranslatorBudget,
170
+ modelId: string,
171
+ ): MessagesIrConversation {
172
+ if (!isRec(raw)) throw new AnthropicRequestError("request body must be a JSON object");
173
+ if (typeof raw.model !== "string" || raw.model.length === 0) throw new AnthropicRequestError("model is required");
174
+ if (!Array.isArray(raw.messages) || raw.messages.length === 0) {
175
+ throw new AnthropicRequestError("messages must be a non-empty array");
176
+ }
177
+ const requestedModel = raw.model;
178
+ const now = Date.now();
179
+ const messages: OcxMessage[] = [];
180
+ const nativeReasoningReplay = new Map<string, string>();
181
+ const blockedNames = effectiveBlockedSkillNames(cc);
182
+ const blockedCalls = blockedSkillCallIds(raw.messages, blockedNames);
183
+ // The parser's pending reasoning: it belongs to the next assistant turn, and turn boundaries
184
+ // clear it after keeping any signed or redacted replay.
185
+ const pending: Array<{ part: OcxThinkingContent; envelopeSigned: boolean }> = [];
186
+
187
+ const placeholder = (): OcxAssistantMessage => {
188
+ const last = messages[messages.length - 1];
189
+ if (last && last.role === "assistant") return last;
190
+ const holder: OcxAssistantMessage = { role: "assistant", content: [], model: modelId, timestamp: now };
191
+ messages.push(holder);
192
+ return holder;
193
+ };
194
+ const holderWithReasoning = (): OcxAssistantMessage => {
195
+ const holder = placeholder();
196
+ if (pending.length > 0) {
197
+ holder.content.push(...pending.map(entry => entry.part));
198
+ pending.length = 0;
199
+ }
200
+ return holder;
201
+ };
202
+ const preservePendingReplay = (): void => {
203
+ const replay = pending.filter(entry => entry.envelopeSigned || entry.part.redacted?.length);
204
+ if (replay.length > 0) placeholder().content.push(...replay.map(entry => entry.part));
205
+ };
206
+ const pushUser = (content: string | OcxContentPart[]): void => {
207
+ preservePendingReplay();
208
+ pending.length = 0;
209
+ messages.push({ role: "user", content, timestamp: now });
210
+ };
211
+ const pushDeveloper = (text: string): void => {
212
+ preservePendingReplay();
213
+ pending.length = 0;
214
+ messages.push({ role: "developer", content: nameDestination(text, modelId), timestamp: now });
215
+ };
216
+ const pushAssistantText = (parts: OcxTextContent[]): void => {
217
+ messages.push({
218
+ role: "assistant",
219
+ content: pending.length > 0 ? [...pending.map(entry => entry.part), ...parts] : parts,
220
+ model: modelId,
221
+ timestamp: now,
222
+ });
223
+ pending.length = 0;
224
+ };
225
+ const pushToolCall = (id: string, name: string, input: unknown): void => {
226
+ holderWithReasoning().content.push({
227
+ type: "toolCall",
228
+ id,
229
+ name,
230
+ arguments: functionCallArgumentsFromText(id, JSON.stringify(input ?? {})),
231
+ });
232
+ };
233
+ const pushToolResult = (callId: string, content: string | OcxContentPart[]): void => {
234
+ // Reasoning replayed after the call it belongs to joins that call's assistant turn (#950).
235
+ if (pending.length > 0) {
236
+ outer: for (let i = messages.length - 1; i >= 0; i--) {
237
+ const message = messages[i]!;
238
+ if (message.role !== "assistant") continue;
239
+ for (const part of message.content) {
240
+ if (part.type === "toolCall" && part.id === callId) {
241
+ message.content = [...pending.map(entry => entry.part), ...message.content];
242
+ break outer;
243
+ }
244
+ }
245
+ }
246
+ }
247
+ pending.length = 0;
248
+ let owner: { name: string; namespace?: string } = { name: "" };
249
+ search: for (let i = messages.length - 1; i >= 0; i--) {
250
+ const message = messages[i]!;
251
+ if (message.role !== "assistant") continue;
252
+ for (const part of message.content) {
253
+ if (part.type === "toolCall" && part.id === callId) {
254
+ owner = { name: part.name, namespace: part.namespace };
255
+ break search;
256
+ }
257
+ }
258
+ }
259
+ messages.push({
260
+ role: "toolResult", toolCallId: callId, toolName: owner.name, toolNamespace: owner.namespace,
261
+ content, isError: false, timestamp: now,
262
+ });
263
+ };
264
+ /**
265
+ * One translator reasoning item, read as the parser reads it. `encrypted` is the item's
266
+ * `encrypted_content`; the placeholder signature is the item's serialized form, spelled in the
267
+ * schema's key order.
268
+ */
269
+ const pushReasoning = (id: string, summaryText: string, encrypted: string | undefined): void => {
270
+ const item: Rec = {
271
+ type: "reasoning",
272
+ id,
273
+ summary: summaryText.length > 0 ? [{ type: "summary_text", text: summaryText }] : [],
274
+ ...(encrypted !== undefined ? { encrypted_content: encrypted } : {}),
275
+ };
276
+ const envelope = encrypted !== undefined ? decodeReasoningEnvelope(encrypted) : null;
277
+ const thinkingText = envelope?.txt ?? summaryText;
278
+ if (envelope?.krc && thinkingText.length === 0) {
279
+ const previous = messages[messages.length - 1];
280
+ if (previous?.role === "assistant") previous.kiroRedactedReasoning = envelope.krc;
281
+ return;
282
+ }
283
+ if (!(thinkingText.length > 0 || envelope?.sig || envelope?.red?.length)) return;
284
+ const part: OcxThinkingContent = {
285
+ type: "thinking",
286
+ thinking: thinkingText,
287
+ signature: envelope?.sig ?? JSON.stringify(item),
288
+ ...(envelope?.red ? { redacted: envelope.red } : {}),
289
+ itemId: id,
290
+ };
291
+ const envelopeSigned = typeof envelope?.sig === "string";
292
+ const previous = pending[pending.length - 1];
293
+ if (!envelopeSigned && !part.redacted && previous && !previous.envelopeSigned && !previous.part.redacted) {
294
+ previous.part = { ...part, thinking: `${previous.part.thinking}\n${part.thinking}` };
295
+ } else {
296
+ pending.push({ part, envelopeSigned });
297
+ }
298
+ };
299
+
300
+ const userContent = (content: unknown): void => {
301
+ if (typeof content === "string") {
302
+ if (content.length > 0) pushUser(content);
303
+ return;
304
+ }
305
+ if (!Array.isArray(content)) return;
306
+ // Contiguous text, image and document blocks form one user turn; a tool_result ends it.
307
+ let parts: OcxContentPart[] = [];
308
+ let blocks = 0;
309
+ const flush = (): void => {
310
+ if (blocks > 0) pushUser(collapsed(parts));
311
+ parts = [];
312
+ blocks = 0;
313
+ };
314
+ for (const block of content) {
315
+ if (!isRec(block)) continue;
316
+ switch (block.type) {
317
+ case "text":
318
+ if (typeof block.text === "string") {
319
+ blocks++;
320
+ parts.push({ type: "text", text: maybeElideSkillText(block.text, blockedNames) });
321
+ }
322
+ break;
323
+ case "image": {
324
+ const url = anthropicImageBlockUrl(block);
325
+ if (url !== null) {
326
+ blocks++;
327
+ // An empty reference is a block the parser drops.
328
+ if (url.length > 0) parts.push({ type: "image", imageUrl: url });
329
+ }
330
+ break;
331
+ }
332
+ case "tool_result": {
333
+ flush();
334
+ if (typeof block.tool_use_id !== "string" || block.tool_use_id.length === 0) {
335
+ throw new AnthropicRequestError("tool_result requires tool_use_id");
336
+ }
337
+ pushToolResult(
338
+ block.tool_use_id,
339
+ blockedCalls.has(block.tool_use_id) ? skillElisionStub(block.tool_use_id) : toolResultContent(block),
340
+ );
341
+ break;
342
+ }
343
+ case "document": {
344
+ blocks++;
345
+ const document = anthropicDocumentData(block);
346
+ parts.push(document
347
+ ? inlineDocumentFromDataUrl(document.fileData, document.title)
348
+ ?? { type: "text", text: document.title ? `[file: ${document.title}]` : "[file: inline data]" }
349
+ : { type: "text", text: inlineDocumentMarker(documentTitle(block)) });
350
+ break;
351
+ }
352
+ default:
353
+ break;
354
+ }
355
+ }
356
+ flush();
357
+ };
358
+
359
+ const assistantContent = (content: unknown): void => {
360
+ if (typeof content === "string") {
361
+ if (content.length > 0) pushAssistantText([{ type: "text", text: content }]);
362
+ return;
363
+ }
364
+ if (!Array.isArray(content)) return;
365
+ let text: OcxTextContent[] = [];
366
+ const flush = (): void => {
367
+ if (text.length > 0) pushAssistantText(text);
368
+ text = [];
369
+ };
370
+ for (const block of content) {
371
+ if (!isRec(block)) continue;
372
+ switch (block.type) {
373
+ case "text":
374
+ if (typeof block.text === "string") text.push({ type: "text", text: block.text });
375
+ break;
376
+ case "tool_use":
377
+ flush();
378
+ if (typeof block.id !== "string" || block.id.length === 0 || typeof block.name !== "string" || block.name.length === 0) {
379
+ throw new AnthropicRequestError("tool_use requires id and name");
380
+ }
381
+ pushToolCall(block.id, block.name, block.input);
382
+ break;
383
+ case "thinking": {
384
+ flush();
385
+ const thinking = typeof block.thinking === "string" ? block.thinking : "";
386
+ const signature = typeof block.signature === "string" ? block.signature : "";
387
+ if (signature.startsWith(OCX_REASONING_PREFIX)) {
388
+ const owned = decodeReasoningEnvelope(signature, budget);
389
+ if (!owned) throw new AnthropicRequestError(MALFORMED_REASONING_SIGNATURE);
390
+ if (Object.hasOwn(owned, "sig")) {
391
+ throw new AnthropicRequestError("OpenCodex reasoning continuity cannot be replayed as an Anthropic signature");
392
+ }
393
+ if (owned.nat) {
394
+ // The provider's own blob goes back only to the model that minted it.
395
+ const nat = owned.nat.model === requestedModel ? owned.nat : undefined;
396
+ if (nat) {
397
+ const previous = nativeReasoningReplay.get(nat.enc);
398
+ nativeReasoningReplay.set(nat.enc, previous === undefined || previous === nat.tag ? nat.tag : "");
399
+ budget.chargeRetained(2 * nat.enc.length, { kind: "reasoning" });
400
+ }
401
+ if (thinking.length === 0 && !nat) break;
402
+ pushReasoning(nat?.id ?? reasoningItemId(), thinking, nat?.enc);
403
+ break;
404
+ }
405
+ }
406
+ const encrypted = signature.length === 0
407
+ ? undefined
408
+ : signature.startsWith(OCX_REASONING_PREFIX) ? signature : encodeReasoningEnvelope({ sig: signature }, budget);
409
+ if (encrypted) budget.chargeRetained(2 * encrypted.length, { kind: "reasoning" });
410
+ if (thinking.length === 0 && !encrypted) break;
411
+ pushReasoning(reasoningItemId(), thinking, encrypted);
412
+ break;
413
+ }
414
+ case "redacted_thinking": {
415
+ flush();
416
+ const data = typeof block.data === "string" ? block.data : "";
417
+ if (data.length > 0) {
418
+ const encrypted = encodeReasoningEnvelope({ red: [data] }, budget);
419
+ budget.chargeRetained(2 * encrypted.length, { kind: "reasoning" });
420
+ pushReasoning(reasoningItemId(), "", encrypted);
421
+ }
422
+ break;
423
+ }
424
+ default:
425
+ break;
426
+ }
427
+ }
428
+ flush();
429
+ };
430
+
431
+ for (const message of raw.messages) {
432
+ if (!isRec(message)) throw new AnthropicRequestError("each message must be an object");
433
+ if (message.role === "user") userContent(message.content);
434
+ else if (message.role === "assistant") assistantContent(message.content);
435
+ else if (message.role === "system") {
436
+ const text = systemMessageText(message.content);
437
+ if (text.length > 0) pushDeveloper(text);
438
+ } else throw new AnthropicRequestError(`unsupported message role: ${String(message.role)}`);
439
+ }
440
+
441
+ const system = anthropicSystemLayout(raw.system, cc);
442
+ if (system.dynamicNotice !== undefined) pushUser(system.dynamicNotice);
443
+ preservePendingReplay();
444
+
445
+ const tools = toolCatalog(raw.tools);
446
+ const context: OcxContext = {
447
+ ...(system.instructions ? { systemPrompt: [nameDestination(system.instructions, modelId)] } : {}),
448
+ messages,
449
+ ...(tools.length > 0 ? { tools } : {}),
450
+ };
451
+ return { modelId, context: normalizeVisualizationContext(context), nativeReasoningReplay };
452
+ }
453
+
454
+ /**
455
+ * Put a directly decoded conversation onto the request the core parsed from the settings-only
456
+ * body, re-decoding if the core settled a different model id than the one decoded for. The tool
457
+ * choice is checked against the decoded catalog, which the settings-only parse could not see.
458
+ */
459
+ export function withDirectMessagesConversation(
460
+ base: OcxParsedRequest,
461
+ decoded: MessagesIrConversation,
462
+ decodeFor: (modelId: string) => MessagesIrConversation,
463
+ ): OcxParsedRequest {
464
+ const conversation = decoded.modelId === base.modelId ? decoded : decodeFor(base.modelId);
465
+ const choice = base.options.toolChoice;
466
+ if (choice && typeof choice === "object") {
467
+ const selectors = "allowedTools" in choice ? choice.allowedTools : [choice.name];
468
+ const resolver = createToolChoiceResolver(conversation.context.tools ?? []);
469
+ for (const selector of selectors) {
470
+ if (resolver.candidateCount(selector) > 1) throw new Error(`ambiguous tool_choice name: ${selector}`);
471
+ }
472
+ }
473
+ return { ...base, context: conversation.context };
474
+ }
475
+
476
+ /**
477
+ * The policy-routing evidence the core reads from the bridge body (`evidenceFromBody`): a
478
+ * non-empty translated tool catalog, and an image block in a user turn. Images inside a
479
+ * tool_result sit under `output` on the bridge body, which that scan does not read.
480
+ */
481
+ export function messagesRouteEvidence(raw: unknown): PolicyRequestEvidence {
482
+ if (!isRec(raw)) return {};
483
+ const tools = toolsToResponses(raw.tools) !== undefined;
484
+ const image = Array.isArray(raw.messages) && raw.messages.some(message => isRec(message)
485
+ && message.role === "user" && Array.isArray(message.content)
486
+ && message.content.some(block => isRec(block) && block.type === "image" && imageReference(block)));
487
+ return {
488
+ ...(tools ? { toolsRequired: true } : {}),
489
+ ...(image ? { imageInputRequired: true } : {}),
490
+ };
491
+ }
492
+
493
+ function imageReference(block: Rec): boolean {
494
+ try {
495
+ return anthropicImageBlockUrl(block) !== null;
496
+ } catch {
497
+ return false;
498
+ }
499
+ }
500
+
@@ -61,6 +61,7 @@ export interface ClientWebSearch {
61
61
  status: "completed" | "failed";
62
62
  queries: string[];
63
63
  sources: { url: string; title?: string }[];
64
+ fetch?: { url: string; result: unknown };
64
65
  }
65
66
 
66
67
  /**
@@ -411,9 +412,9 @@ export function encodeAdapterEventStream(
411
412
  budget.closeCall(call.callId);
412
413
  currentToolCall = null;
413
414
  };
414
- const closeCurrentWebSearch = (status: "completed" | "failed", queries: string[], sources?: { url: string; title?: string }[]) => {
415
+ const closeCurrentWebSearch = (status: "completed" | "failed", queries: string[], sources?: { url: string; title?: string }[], fetch?: ClientWebSearch["fetch"]) => {
415
416
  if (!currentWebSearch) return;
416
- writer.webSearchDone({ itemId: currentWebSearch.itemId, status, queries, sources: sources ?? [] });
417
+ writer.webSearchDone({ itemId: currentWebSearch.itemId, status, queries, sources: sources ?? [], ...(fetch ? { fetch } : {}) });
417
418
  currentWebSearch = null;
418
419
  };
419
420
  const appendToolArgs = (call: OpenToolCall, fragment: string) => {
@@ -688,7 +689,7 @@ export function encodeAdapterEventStream(
688
689
  if (currentWebSearch) closeCurrentWebSearch("completed", []);
689
690
  currentWebSearch = { itemId: `ws_${uuid()}`, eventId: event.id };
690
691
  }
691
- closeCurrentWebSearch(event.status ?? "completed", event.queries, safeWebSearchSources(event.sources));
692
+ closeCurrentWebSearch(event.status ?? "completed", event.queries, safeWebSearchSources(event.sources), event.fetch);
692
693
  break;
693
694
  }
694
695
  case "done": {
@@ -729,7 +730,7 @@ export function encodeAdapterEventStream(
729
730
  terminal = {
730
731
  status: "incomplete",
731
732
  incomplete: {
732
- reason: event.reason,
733
+ reason: truncationReasonFor(event.reason) ?? event.reason,
733
734
  ...(event.message ? { message: event.message } : {}),
734
735
  ...(event.retryable !== undefined ? { retryable: event.retryable } : {}),
735
736
  },
@@ -16,6 +16,7 @@ import {
16
16
  type TranslatorBudget,
17
17
  } from "../../lib/translator-budget";
18
18
  import { isTransientUpstreamStatus } from "../../lib/upstream-retry";
19
+ import { UNDECLARED_TOOL_CALL_ERROR_CODE } from "../../lib/errors";
19
20
  import { encodeReasoningEnvelope } from "../../responses/reasoning-envelope";
20
21
  import { responsesUsage, webSearchAction } from "../../bridge/internal";
21
22
  import {
@@ -344,13 +345,14 @@ function createAnthropicMessageWriter(
344
345
  type: "web_search_call",
345
346
  id: search.itemId,
346
347
  status: search.status,
347
- action: webSearchAction(search.queries),
348
+ action: webSearchAction(search.queries, search.fetch),
348
349
  ...(search.sources.length > 0 ? { sources: search.sources } : {}),
350
+ ...(search.fetch ? { fetch_result: search.fetch.result } : {}),
349
351
  });
350
352
  const toolIndex = blockIndex++;
351
353
  emit("content_block_start", {
352
354
  type: "content_block_start", index: toolIndex,
353
- content_block: { type: "server_tool_use", id: pair.id, name: "web_search" },
355
+ content_block: { type: "server_tool_use", id: pair.id, name: pair.name },
354
356
  }, { sideEffect: true });
355
357
  emit("content_block_delta", {
356
358
  type: "content_block_delta", index: toolIndex,
@@ -360,10 +362,10 @@ function createAnthropicMessageWriter(
360
362
  const resultIndex = blockIndex++;
361
363
  emit("content_block_start", {
362
364
  type: "content_block_start", index: resultIndex,
363
- content_block: { type: "web_search_tool_result", tool_use_id: pair.id, content: pair.resultContent },
365
+ content_block: { type: pair.resultType, tool_use_id: pair.id, content: pair.resultContent },
364
366
  });
365
367
  emit("content_block_stop", { type: "content_block_stop", index: resultIndex });
366
- if (pair.completed) webSearchRequests++;
368
+ if (pair.completed && pair.name === "web_search") webSearchRequests++;
367
369
  },
368
370
  terminal(terminal) {
369
371
  if (terminal.status === "completed") {
@@ -386,8 +388,9 @@ function createAnthropicMessageWriter(
386
388
  return;
387
389
  }
388
390
  const message = typeof error.message === "string" ? error.message : "upstream request failed";
389
- fail(anthropicFailedStatus(error, message), message, true,
390
- error.code === "context_length_exceeded" ? error.code : undefined);
391
+ const deterministic = error.code === UNDECLARED_TOOL_CALL_ERROR_CODE;
392
+ fail(anthropicFailedStatus(error, message), message, !deterministic,
393
+ deterministic || error.code === "context_length_exceeded" ? error.code as string : undefined);
391
394
  },
392
395
  overflow() {
393
396
  fail(413, "upstream translation buffer exceeded the safe limit", false, "translation_buffer_limit");
@@ -152,6 +152,12 @@ export function featureEffectsForPath(
152
152
  present: Iterable<ProtocolFeature>,
153
153
  ): PathFeatureEffects {
154
154
  const nodes = protocolNodes(path);
155
+ // A Chat or Messages body decoded straight into the IR (the direct lane, `[inbound, ir, other]`)
156
+ // keeps exactly what its Responses projection keeps: the direct codecs are held to
157
+ // `parseRequest(projection)` by parity tests. The decode hop therefore reads the
158
+ // `<inbound>>responses` row, and the hop from the IR into `other` stays unknown as before.
159
+ const directIrDecode = inbound !== "responses" && path.length === 3
160
+ && path[0] === inbound && path[1] === "ir" && path[2] === "other";
155
161
  const effects: FeatureEffect[] = [];
156
162
  const unknown: ProtocolFeature[] = [];
157
163
  const seen = new Set<ProtocolFeature>();
@@ -160,8 +166,10 @@ export function featureEffectsForPath(
160
166
  seen.add(feature);
161
167
  let worst: FeatureDisposition = "passthrough";
162
168
  let unknownHop = false;
163
- for (let i = 1; i < nodes.length; i++) {
164
- const hop = featureHopDisposition(feature, nodes[i - 1]!, nodes[i]!);
169
+ const hops = directIrDecode
170
+ ? [featureHopDisposition(feature, inbound, "responses"), undefined]
171
+ : nodes.slice(1).map((node, i) => featureHopDisposition(feature, nodes[i]!, node));
172
+ for (const hop of hops) {
165
173
  if (hop === undefined) unknownHop = true;
166
174
  else if (RANK[hop] > RANK[worst]) worst = hop;
167
175
  }
@@ -10,14 +10,23 @@ import { deliveryModeForPath, type DeliveryMode, type Protocol, type ProtocolHop
10
10
  /**
11
11
  * `native`: the ingress sent its own wire to a same-wire upstream.
12
12
  * `bridge`: the ingress projected the request into the Responses pipeline.
13
+ * `direct`: the ingress decoded its own wire straight into the IR the final adapter compiles
14
+ * from, with no internal Responses body in between (the Antigravity direct lane). Only a Chat or
15
+ * Messages ingress toward a non-protocol (`other`) upstream takes it; anything else falls back
16
+ * to the bridge rule so an inconsistent mark cannot claim a path that does not exist.
13
17
  */
14
- export type ProtocolLane = "native" | "bridge";
18
+ export type ProtocolLane = "native" | "bridge" | "direct";
19
+
20
+ function directApplies(inbound: Protocol, lane: ProtocolLane, upstream: UpstreamWire): boolean {
21
+ return lane === "direct" && inbound !== "responses" && upstream === "other";
22
+ }
15
23
 
16
24
  export function requestPathForLane(inbound: Protocol, lane: ProtocolLane, upstream: UpstreamWire): ProtocolHop[] {
17
25
  if (inbound === "responses") {
18
26
  return upstream === "responses" ? ["responses", "responses"] : ["responses", "ir", upstream];
19
27
  }
20
28
  if (lane === "native") return [inbound, inbound];
29
+ if (directApplies(inbound, lane, upstream)) return [inbound, "ir", upstream];
21
30
  if (upstream === "responses") return [inbound, "responses"];
22
31
  return [inbound, "responses-internal", "ir", upstream];
23
32
  }
@@ -26,6 +35,7 @@ export function requestPathForLane(inbound: Protocol, lane: ProtocolLane, upstre
26
35
  export function responsePathForLane(inbound: Protocol, lane: ProtocolLane, upstream: UpstreamWire): ProtocolHop[] {
27
36
  if (inbound === "responses") return upstream === "responses" ? ["responses", "responses"] : [upstream, "ir", "responses"];
28
37
  if (lane === "native") return [inbound, inbound];
38
+ if (directApplies(inbound, lane, upstream)) return [upstream, "ir", inbound];
29
39
  if (upstream === "responses") return ["responses", inbound];
30
40
  return [upstream, "ir", "responses-internal", inbound];
31
41
  }