@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
@@ -24,6 +24,7 @@ import { clientEncoderForDelivery, deliverClientEncodedResponse } from "../infer
24
24
  import { noteKiroServedSuccess } from "../../providers/kiro-usage";
25
25
  import { persistKiroAccountState } from "../../providers/kiro-account-state-disk";
26
26
  import { isCanonicalOpenAiForwardProvider } from "../../providers/openai-tiers";
27
+ import { guardEmptyToolCatalogEvents, guardEmptyToolCatalogStream } from "../../lib/empty-tool-catalog";
27
28
 
28
29
  /** One responsibility of the Responses request pipeline; state owners are explicit. */
29
30
  export async function deliverAdapterResponse(
@@ -34,6 +35,7 @@ export async function deliverAdapterResponse(
34
35
  | "route"
35
36
  | "translatorBudget"
36
37
  | "toolBridgeMaps"
38
+ | "clientToolCatalogRestriction"
37
39
  | "rememberKiroDeliveredFinalAnswer"
38
40
  | "responseStateOptions"
39
41
  >,
@@ -75,6 +77,10 @@ export async function deliverAdapterResponse(
75
77
  const { routedCompaction } = sidecarState;
76
78
  const bodyInactivityMs = resolveStallTimeoutMs(config.stallTimeoutSec, { localUpstream });
77
79
  const upstreamRequestsStream = parsed.stream || isCanonicalOpenAiForwardProvider(route.provider);
80
+ const clientToolCatalog = requestState.clientToolCatalogRestriction && route.provider.authMode !== "forward"
81
+ ? requestState.clientToolCatalogRestriction : undefined;
82
+ const deliveryToolBridgeMaps = clientToolCatalog
83
+ ? { ...toolBridgeMaps, ...clientToolCatalog } : toolBridgeMaps;
78
84
 
79
85
 
80
86
  if (parsed.stream) {
@@ -113,17 +119,31 @@ export async function deliverAdapterResponse(
113
119
  continuation: next => fetchTerminalGuardContinuation(next, undefined, !parsed.stream),
114
120
  })
115
121
  : initialEventStream;
122
+ // Optional advisor guard (registered per request by the sidecar planner; absent unless the
123
+ // user enabled the advisor): holds synthetic `advisor` tool calls, consults the configured
124
+ // expert model, and re-dispatches the worker. Sits inside the empty-completion guard so an
125
+ // advisor-only turn never reads as an empty completion, and outside the bridge so the
126
+ // synthetic call never reaches the client.
127
+ const advisorStream = parsed._advisorGuard
128
+ ? parsed._advisorGuard({
129
+ parsed,
130
+ translatorBudget,
131
+ firstEvents: eventStream,
132
+ continuation: fetchTerminalGuardContinuation,
133
+ })
134
+ : eventStream;
116
135
  // The empty-completion guard sits OUTSIDE the terminal guard: a completed
117
136
  // turn with no text and no tool call is retried with the IDENTICAL request
118
137
  // (fetchTerminalGuardContinuation(parsed) replays the cached byte-identical
119
138
  // request — same body, same headers, same signal).
120
- const guardedEventStream = emptyCompletionGuardEnabled
139
+ const completionGuardedEventStream = emptyCompletionGuardEnabled
121
140
  ? guardEmptyCompletionEventStream({
122
- firstEvents: eventStream,
141
+ firstEvents: advisorStream,
123
142
  continuation: fetchGuardedEmptyCompletionRetry,
124
143
  })
125
- : eventStream;
126
- const { toolNsMap, declaredToolNames, toolParameterSchemas, freeformToolNames, bareCustomToolNames, toolSearchToolNames } = toolBridgeMaps;
144
+ : advisorStream;
145
+ const guardedEventStream = guardEmptyToolCatalogStream(completionGuardedEventStream, clientToolCatalog, translatorBudget);
146
+ const { toolNsMap, declaredToolNames, toolParameterSchemas, freeformToolNames, bareCustomToolNames, toolSearchToolNames } = deliveryToolBridgeMaps;
127
147
  // One completion owner for both deliveries: the bridge calls it from its terminal, the
128
148
  // direct client encoder from the fold of the same events.
129
149
  const onCompletedResponse = (response: Record<string, unknown>, providerState?: OcxProviderContinuationState) => {
@@ -145,7 +165,9 @@ export async function deliverAdapterResponse(
145
165
  }
146
166
  notifyResponseComplete(response);
147
167
  };
148
- const clientEncoder = clientEncoderForDelivery(options, logCtx, !!routedCompaction, transportState.activeAdapter.name);
168
+ // The Responses bridge owns code-mode helper compilation; the direct encoder only renames.
169
+ const clientEncoder = clientToolCatalog?.bareCustomToolNames.has("exec") ? undefined
170
+ : clientEncoderForDelivery(options, logCtx, !!routedCompaction, transportState.activeAdapter.name);
149
171
  if (clientEncoder) {
150
172
  return deliverClientEncodedResponse({
151
173
  encoder: clientEncoder,
@@ -184,9 +206,10 @@ export async function deliverAdapterResponse(
184
206
  declaredToolNames,
185
207
  bareCustomToolNames,
186
208
  enforceDeclaredToolNames: options.inboundWire !== "chat" && options.inboundWire !== "anthropic",
209
+ terminalRefusalAsFailed: options.inboundWire !== "chat" && options.inboundWire !== "anthropic",
187
210
  toolParameterSchemas,
188
211
  ...(options.onFirstOutput ? { onFirstOutput: options.onFirstOutput } : {}),
189
- ...(routedCompaction ? { compaction: true } : {}),
212
+ ...(routedCompaction ? { compaction: true, compactionRetention: parsed._compactionRetention } : {}),
190
213
  // Same grok-surface split as the runTurn branch above.
191
214
  ...(logCtx.surface === "grok" ? { heartbeatStyle: "comment" as const } : {}),
192
215
  onUsage: usage => {
@@ -240,6 +263,17 @@ export async function deliverAdapterResponse(
240
263
  } else {
241
264
  guardedEvents = initialEvents;
242
265
  }
266
+ // Optional advisor guard — same semantics as the streaming branch above.
267
+ if (parsed._advisorGuard) {
268
+ const advisorEvents: AdapterEvent[] = [];
269
+ for await (const event of parsed._advisorGuard({
270
+ parsed,
271
+ translatorBudget,
272
+ firstEvents: (async function* () { yield* guardedEvents; })(),
273
+ continuation: fetchTerminalGuardContinuation,
274
+ })) advisorEvents.push(event);
275
+ guardedEvents = advisorEvents;
276
+ }
243
277
  if (emptyCompletionGuardEnabled) {
244
278
  events = [];
245
279
  for await (const event of guardEmptyCompletionEventStream({
@@ -257,8 +291,9 @@ export async function deliverAdapterResponse(
257
291
  } finally {
258
292
  cleanupUpstreamAbort();
259
293
  }
260
- const { toolNsMap, declaredToolNames, toolParameterSchemas, freeformToolNames, bareCustomToolNames, toolSearchToolNames } = toolBridgeMaps;
294
+ const { toolNsMap, declaredToolNames, toolParameterSchemas, freeformToolNames, bareCustomToolNames, toolSearchToolNames } = deliveryToolBridgeMaps;
261
295
  let providerState: OcxProviderContinuationState | undefined;
296
+ events = guardEmptyToolCatalogEvents(events, clientToolCatalog, translatorBudget);
262
297
  const json = buildResponseJSON(events, parsed._responseModelId ?? parsed.modelId, {
263
298
  translatorBudget,
264
299
  replayCacheScope: parsed._reasoningReplayScope,
@@ -271,7 +306,7 @@ export async function deliverAdapterResponse(
271
306
  toolParameterSchemas,
272
307
  freeformToolNames,
273
308
  toolSearchToolNames,
274
- ...(routedCompaction ? { compaction: true } : {}),
309
+ ...(routedCompaction ? { compaction: true, compactionRetention: parsed._compactionRetention } : {}),
275
310
  onProviderState: state => { providerState = state; },
276
311
  onUsage: usage => {
277
312
  transportState.bindKeyUsageFromBridge(usage);
@@ -54,7 +54,7 @@ import { describeUpstreamConnectFailure } from "./upstream-error";
54
54
  import type { OpaqueBlobRecoveryGuard } from "./core-opaque-recovery";
55
55
  import type { AttemptRecoveryKind } from "../../usage/log";
56
56
  import type { OAuthAccessSnapshot } from "../../oauth";
57
- import { OAuthAccountPausedError, OAuthLoginRequiredError, publicOAuthAuthenticationErrorMessage } from "../../oauth";
57
+ import { OAuthAccountPausedError, OAuthLoginRequiredError, OAuthTokenRefreshBusyError, publicOAuthAuthenticationErrorMessage } from "../../oauth";
58
58
  import { getAccountSet, markAccountNeedsReauthIfGeneration } from "../../oauth/store";
59
59
  import { tryKiroAlternateAfterTerminalRefresh } from "../../oauth/kiro-terminal-failover";
60
60
  import { classifyKiroRefusal } from "../../adapters/kiro-refusal";
@@ -112,6 +112,7 @@ import { mapCodexAuthContextErrorToResponse } from "./codex-auth-error";
112
112
  import { chargeWorkflowSends } from "../../lib/workflow-budget";
113
113
  import { isAntigravityValidationRefusal } from "./antigravity-validation-refusal";
114
114
  import { unboundPoolSpendRefusalResponse } from "../workflow-refusal";
115
+ import { AdmissionModelDeniedError, admissionModelDeniedResponse } from "../admission-model-scope";
115
116
 
116
117
  /** One responsibility of the Responses request pipeline; state owners are explicit. */
117
118
  export async function prepareAdapterExchange(
@@ -225,8 +226,13 @@ export async function prepareAdapterExchange(
225
226
 
226
227
 
227
228
  let selfContainedJudgment: boolean | undefined;
229
+ // On the Antigravity direct lane the raw body carries only settings; judge the body the bridge
230
+ // would have sent, built only if an ambiguous reset actually asks.
231
+ const directRequest = options.directRequest;
228
232
  const requestIsSelfContained = (): boolean =>
229
- selfContainedJudgment ??= selfContainedResponsesBody(parsed._rawBody);
233
+ selfContainedJudgment ??= selfContainedResponsesBody(directRequest
234
+ ? { ...(parsed._rawBody as Record<string, unknown>), ...directRequest.bridgeConversation() }
235
+ : parsed._rawBody);
230
236
  const claimPreHeaderResend = (): boolean => authorizeResendForRecovery(
231
237
  "pre-header", "connection-reset",
232
238
  ambiguousResendAllowanceFor(route.provider, requestIsSelfContained, claimAmbiguousResend),
@@ -541,6 +547,10 @@ export async function prepareAdapterExchange(
541
547
  return storageRefusal;
542
548
  }
543
549
  const refusal = err instanceof UpstreamRetryEvidenceError ? err.cause : err;
550
+ if (refusal instanceof AdmissionModelDeniedError) {
551
+ releaseCodexAuthContextProbeLease(admissionState.authCtx);
552
+ return admissionModelDeniedResponse(refusal);
553
+ }
544
554
  const codexRefusal = mapCodexAuthContextErrorToResponse(unwrapUpstreamRetryEvidenceError(err), {
545
555
  now: Date.now(), accountSelector: route.codexAccountNamespace,
546
556
  });
@@ -810,6 +820,13 @@ export async function prepareAdapterExchange(
810
820
  releaseCodexAuthContextProbeLease(admissionState.authCtx);
811
821
  return { failed: storageRefusal };
812
822
  }
823
+ const scopeRefusal = unwrapUpstreamRetryEvidenceError(err);
824
+ if (!options.abortSignal?.aborted && scopeRefusal instanceof AdmissionModelDeniedError) {
825
+ cleanupUpstreamAbort();
826
+ upstream.abort();
827
+ releaseCodexAuthContextProbeLease(admissionState.authCtx);
828
+ return { failed: admissionModelDeniedResponse(scopeRefusal) };
829
+ }
813
830
  const codexRefusal = !options.abortSignal?.aborted && mapCodexAuthContextErrorToResponse(unwrapUpstreamRetryEvidenceError(err), {
814
831
  now: Date.now(), accountSelector: route.codexAccountNamespace,
815
832
  });
@@ -915,6 +932,15 @@ export async function prepareAdapterExchange(
915
932
  try {
916
933
  refreshed = await refreshResolvedOAuthSelection(transportState.sentOAuthSnapshot);
917
934
  } catch (err) {
935
+ const cancelled = options.abortSignal?.aborted || req.signal.aborted;
936
+ if (cancelled || err instanceof OAuthTokenRefreshBusyError) {
937
+ cleanupUpstreamAbort();
938
+ upstream.abort();
939
+ try { void upstreamResponse.body?.cancel().catch(() => {}); } catch { /* already closed */ }
940
+ releaseCodexAuthContextProbeLease(admissionState.authCtx);
941
+ return cancelled ? clientCancelledResponse()
942
+ : formatErrorResponse(503, "server_error", publicOAuthAuthenticationErrorMessage(err), { retryAfter: "1" });
943
+ }
918
944
  const failed = transportState.sentOAuthSnapshot;
919
945
  if (route.providerName === "google-antigravity" && !antigravityAuthRotationAttempted
920
946
  && err instanceof OAuthLoginRequiredError && failed
@@ -1320,9 +1346,17 @@ export async function prepareAdapterExchange(
1320
1346
  resolveWireProtocolOverride(route.providerName, route.modelId, route.provider, inboundWire, route.staticPolicy),
1321
1347
  config.cacheRetention,
1322
1348
  );
1349
+ bindRouteReasoningReplayScope({
1350
+ parsed,
1351
+ providerName: route.providerName,
1352
+ provider: route.provider,
1353
+ adapterName: transportState.activeAdapter.name,
1354
+ oauthCredentialSnapshot: transportState.replayOAuthCredentialSnapshot,
1355
+ });
1323
1356
  sealRequestAttemptIdentity(logCtx.activeAttempt, logCtx.provider, transportState.activeAdapter.name, logCtx.accountLogLabel);
1324
1357
  recordAttemptCredentialSource(logCtx.activeAttempt, route.providerName, route.provider, transportState.activeAdapter.name);
1325
- const result = await rebuildAndRefetch(upstreamResponse.status === 401 ? "oauth-401" : "anthropic-oauth-429");
1358
+ const result = await rebuildAndRefetch(upstreamResponse.status === 401 ? "oauth-401"
1359
+ : upstreamResponse.status === 403 ? "oauth-account-403" : "anthropic-oauth-429");
1326
1360
  if ("failed" in result) return result.failed;
1327
1361
  upstreamResponse = result;
1328
1362
  if (isNonReplayableResponse(upstreamResponse)) continue recovery;
@@ -1539,7 +1573,17 @@ export async function prepareAdapterExchange(
1539
1573
  // The hop's permit is already settled by the dispatch boundary above; continuing
1540
1574
  // only skips the remaining arms, it does not abandon a reservation.
1541
1575
  if (isNonReplayableResponse(upstreamResponse)) continue recovery;
1542
- } catch {
1576
+ } catch (err) {
1577
+ // A local admission denial is terminal for the whole request: rotating to another
1578
+ // account cannot re-scope the key, so the refusal answers in place of the 429.
1579
+ const scopeRefusal = unwrapUpstreamRetryEvidenceError(err);
1580
+ if (!options.abortSignal?.aborted && scopeRefusal instanceof AdmissionModelDeniedError) {
1581
+ hop.permit?.release();
1582
+ cleanupUpstreamAbort();
1583
+ upstream.abort();
1584
+ releaseCodexAuthContextProbeLease(admissionState.authCtx);
1585
+ return admissionModelDeniedResponse(scopeRefusal);
1586
+ }
1543
1587
  // A throw before the send — snapshot fetch, credential application, adapter
1544
1588
  // resolution — must hand the reservation back. Without this the ladder charges the
1545
1589
  // request for a send it never made, and a later recovery in the same request is
@@ -0,0 +1,27 @@
1
+ /** Core-owned, config-scoped registration. An inactive install has no Advisor factory. */
2
+ import type { OcxConfig, OcxParsedRequest, OcxTool } from "../../types";
3
+
4
+ export interface AdvisorPlanInput {
5
+ config: OcxConfig;
6
+ workerIdentity: string;
7
+ workerModelId: string;
8
+ abortSignal?: AbortSignal;
9
+ }
10
+
11
+ export interface RegisteredAdvisorPlan {
12
+ tool: OcxTool;
13
+ preflightInject(parsed: OcxParsedRequest): Promise<boolean>;
14
+ attachGuard(parsed: OcxParsedRequest): void;
15
+ }
16
+
17
+ type AdvisorPlanFactory = (input: AdvisorPlanInput) => Promise<RegisteredAdvisorPlan | null>;
18
+ const factories = new WeakMap<OcxConfig, AdvisorPlanFactory>();
19
+
20
+ export function setAdvisorPlanFactory(config: OcxConfig, factory: AdvisorPlanFactory | null): void {
21
+ if (factory) factories.set(config, factory);
22
+ else factories.delete(config);
23
+ }
24
+
25
+ export function createRegisteredAdvisorPlan(input: AdvisorPlanInput): Promise<RegisteredAdvisorPlan | null> | null {
26
+ return factories.get(input.config)?.(input) ?? null;
27
+ }
@@ -0,0 +1,117 @@
1
+ import { jsonUtf8Bytes } from "../../lib/json-byte-size";
2
+ import {
3
+ TRANSLATOR_MAX_TURN_BYTES,
4
+ TranslatorBudgetExceededError,
5
+ type TranslatorBudget,
6
+ } from "../../lib/translator-budget";
7
+ import type { AdapterEvent, OcxMessage, OcxUsage } from "../../types";
8
+ import { mergeUsage } from "./terminal-guard";
9
+
10
+ export const MAX_ADVISOR_RETAINED_EVENTS = 4_096;
11
+ export const MAX_ADVISOR_RETAINED_CALLS = 1_024;
12
+
13
+ /** Independent ownership: never borrow the bridge's event or tool-call leases. */
14
+ export class AdvisorRetention {
15
+ private legBytes = 0;
16
+ private historyBytes = 0;
17
+ private copyBytes = 0;
18
+ private usageBytes = 0;
19
+ private events = 0;
20
+ private calls = 0;
21
+
22
+ constructor(private readonly shared?: TranslatorBudget) {}
23
+
24
+ private charge(bytes: number, kind: "retained_collectors" | "request_copies"): void {
25
+ if (bytes > TRANSLATOR_MAX_TURN_BYTES - this.legBytes - this.historyBytes - this.copyBytes - this.usageBytes) {
26
+ throw new TranslatorBudgetExceededError(kind, TRANSLATOR_MAX_TURN_BYTES);
27
+ }
28
+ this.shared?.chargeRetained(bytes, { kind });
29
+ }
30
+
31
+ /** Usage can alias a terminal payload. Keep its own owner after the raw leg ends. */
32
+ usage(first: OcxUsage | undefined, second: OcxUsage | undefined): OcxUsage | undefined {
33
+ if (!second) return first;
34
+ // Two-input merge materializes a new object. Reserve before merging, including
35
+ // a conservative bound for concatenation if a provider supplied malformed scalars.
36
+ const bytes = first
37
+ ? (jsonUtf8Bytes(first) + jsonUtf8Bytes(second)) * 2 + 256
38
+ : jsonUtf8Bytes(second) + 1;
39
+ this.charge(bytes, "request_copies");
40
+ this.copyBytes += bytes;
41
+ let retained = 0;
42
+ try {
43
+ const merged = mergeUsage(first, second);
44
+ const measured = jsonUtf8Bytes(merged, bytes) + 1;
45
+ if (measured > bytes) throw new TranslatorBudgetExceededError("request_copies", TRANSLATOR_MAX_TURN_BYTES);
46
+ retained = measured;
47
+ const previous = this.usageBytes;
48
+ this.usageBytes = retained;
49
+ this.shared?.releaseRetained(previous, { kind: "request_copies" });
50
+ return merged;
51
+ } finally {
52
+ this.copyBytes -= bytes;
53
+ this.shared?.releaseRetained(bytes - retained, { kind: "request_copies" });
54
+ }
55
+ }
56
+
57
+ /**
58
+ * `counted: false` is only for non-empty text/thinking deltas: the leg's 16 KiB character
59
+ * caps already bound how many of those can be held, and an ordinary long answer streams
60
+ * thousands of them. They still consume bytes.
61
+ */
62
+ retain(event: AdapterEvent, call = false, counted = true): void {
63
+ if ((counted && this.events >= MAX_ADVISOR_RETAINED_EVENTS) || (call && this.calls >= MAX_ADVISOR_RETAINED_CALLS)) {
64
+ throw new TranslatorBudgetExceededError("retained_collectors", TRANSLATOR_MAX_TURN_BYTES);
65
+ }
66
+ const bytes = jsonUtf8Bytes(event) + 1;
67
+ this.charge(bytes, "retained_collectors");
68
+ this.legBytes += bytes;
69
+ if (counted) this.events++;
70
+ if (call) this.calls++;
71
+ }
72
+
73
+ /** Hold a bounded materialization while its raw sources are still retained. */
74
+ copy<T>(bytes: number, build: () => T): T {
75
+ this.charge(bytes, "request_copies");
76
+ this.copyBytes += bytes;
77
+ try { return build(); }
78
+ finally {
79
+ this.copyBytes -= bytes;
80
+ this.shared?.releaseRetained(bytes, { kind: "request_copies" });
81
+ }
82
+ }
83
+
84
+ /** Reserve before constructing replay JSON; transfer the reservation to history. */
85
+ history<T extends OcxMessage | undefined>(bytes: number, build: () => T): T {
86
+ this.charge(bytes, "request_copies");
87
+ this.copyBytes += bytes;
88
+ let retained = 0;
89
+ try {
90
+ const message = build();
91
+ const measured = message ? jsonUtf8Bytes(message, bytes) + 1 : 0;
92
+ if (measured > bytes) throw new TranslatorBudgetExceededError("request_copies", TRANSLATOR_MAX_TURN_BYTES);
93
+ retained = measured;
94
+ this.historyBytes += retained;
95
+ return message;
96
+ } finally {
97
+ this.copyBytes -= bytes;
98
+ this.shared?.releaseRetained(bytes - retained, { kind: "request_copies" });
99
+ }
100
+ }
101
+
102
+ /** Event envelopes dominate the replay content; allow new message/call framing too. */
103
+ replayReservation(): number { return this.legBytes + (this.calls + 1) * 256; }
104
+
105
+ releaseLeg(): void {
106
+ this.shared?.releaseRetained(this.legBytes, { kind: "retained_collectors" });
107
+ this.legBytes = this.events = this.calls = 0;
108
+ }
109
+
110
+ release(): void {
111
+ this.releaseLeg();
112
+ this.shared?.releaseRetained(this.historyBytes, { kind: "request_copies" });
113
+ this.historyBytes = 0;
114
+ this.shared?.releaseRetained(this.usageBytes, { kind: "request_copies" });
115
+ this.usageBytes = 0;
116
+ }
117
+ }