@bitkyc08/opencodex 2.81.0 → 2.83.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 (272) hide show
  1. package/bin/ocx.mjs +166 -73
  2. package/gui/dist/assets/App-Ba8uG696.js +54 -0
  3. package/gui/dist/assets/{Tray-EwAOsP0S.js → Tray-IImbNPRy.js} +1 -1
  4. package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
  5. package/gui/dist/assets/{index-RsoaAxXY.js → index-BHRZdJuv.js} +13 -13
  6. package/gui/dist/assets/{quota-summary-D2lN8tDm.js → quota-summary-DiJO6sYY.js} +1 -1
  7. package/gui/dist/index.html +2 -2
  8. package/package.json +1 -1
  9. package/src/adapters/anthropic.ts +1 -1
  10. package/src/adapters/cursor/catalog.ts +2 -2
  11. package/src/adapters/cursor/effort-map.ts +1 -1
  12. package/src/adapters/devin/live-models.ts +2 -2
  13. package/src/adapters/google-truncation.ts +22 -0
  14. package/src/adapters/google.ts +7 -3
  15. package/src/adapters/ollama-native.ts +18 -14
  16. package/src/adapters/openai-responses/compaction-search-history.ts +109 -0
  17. package/src/adapters/openai-responses/passthrough.ts +11 -4
  18. package/src/adapters/openai-responses/plaintext-reasoning-notice.ts +85 -0
  19. package/src/adapters/openai-responses/reasoning.ts +11 -1
  20. package/src/adapters/openai-responses/tool-output-recovery.ts +20 -0
  21. package/src/bridge/errors.ts +7 -1
  22. package/src/claude/agents-inject.ts +14 -3
  23. package/src/claude/context-windows.ts +22 -20
  24. package/src/claude/desktop-3p.ts +88 -12
  25. package/src/claude/desktop-picker.ts +1 -1
  26. package/src/claude/desktop-profile.ts +2 -1
  27. package/src/claude/gateway-cache.ts +18 -1
  28. package/src/claude/inbound.ts +77 -3
  29. package/src/claude/intercept/cli-catalog.ts +3 -0
  30. package/src/claude/intercept/picker-ca-persistence.ts +7 -6
  31. package/src/claude/intercept/picker-models.ts +14 -6
  32. package/src/claude/intercept/settings.ts +3 -0
  33. package/src/claude/long-context.ts +66 -0
  34. package/src/claude/model-info.ts +19 -16
  35. package/src/claude/outbound.ts +94 -9
  36. package/src/claude/subagent-model.ts +40 -11
  37. package/src/cli/account-auth.ts +20 -12
  38. package/src/cli/agent.ts +9 -5
  39. package/src/cli/aside-profile-recovery.ts +33 -0
  40. package/src/cli/capabilities-base.ts +5 -5
  41. package/src/cli/capabilities-integrations.ts +2 -2
  42. package/src/cli/cli-path-diagnostics.ts +132 -0
  43. package/src/cli/desktop-runtime-guidance.ts +65 -0
  44. package/src/cli/dispatch.ts +5 -0
  45. package/src/cli/doctor.ts +16 -3
  46. package/src/cli/index.ts +14 -9
  47. package/src/cli/integration-aside-sync.ts +2 -1
  48. package/src/cli/integrations.ts +16 -3
  49. package/src/cli/resolve.ts +26 -3
  50. package/src/cli/root.ts +4 -2
  51. package/src/cli/status.ts +64 -12
  52. package/src/cli/update-restart-child.ts +4 -2
  53. package/src/cli/update-restart-home.ts +28 -10
  54. package/src/cli/update-restart-service-record.ts +116 -0
  55. package/src/cli/update-restart-supervision.ts +96 -0
  56. package/src/cli/update-restart.ts +59 -13
  57. package/src/cli/v2.ts +27 -20
  58. package/src/cli/version-skew-notice.ts +77 -0
  59. package/src/clients/config-export/model-metadata.ts +16 -0
  60. package/src/clients/config-export/zcode-store.ts +46 -11
  61. package/src/clients/config-export/zcode.ts +3 -5
  62. package/src/clients/config-export.ts +1 -1
  63. package/src/clients/lazycodex.ts +1 -1
  64. package/src/clients/omo-role-models.ts +32 -7
  65. package/src/codex/auth-api/account-selection.ts +107 -0
  66. package/src/codex/auth-api/pool-mode-gate.ts +4 -5
  67. package/src/codex/auth-api/routes.ts +10 -49
  68. package/src/codex/auth-context.ts +28 -4
  69. package/src/codex/autostart-health.ts +12 -3
  70. package/src/codex/catalog/build-entries.ts +18 -0
  71. package/src/codex/catalog/bundled.ts +155 -26
  72. package/src/codex/catalog/combo-member.ts +3 -2
  73. package/src/codex/catalog/effort.ts +26 -5
  74. package/src/codex/catalog/gather-capture.ts +5 -0
  75. package/src/codex/catalog/model-hints.ts +15 -8
  76. package/src/codex/catalog/model-visibility.ts +3 -1
  77. package/src/codex/catalog/native-models.ts +1 -1
  78. package/src/codex/catalog/operator-tiers.ts +38 -0
  79. package/src/codex/catalog/provider-models.ts +68 -35
  80. package/src/codex/catalog/retained-sync.ts +7 -5
  81. package/src/codex/catalog/routed-gather.ts +15 -1
  82. package/src/codex/catalog-auto-refresh-sources.ts +3 -4
  83. package/src/codex/catalog-auto-refresh.ts +19 -0
  84. package/src/codex/catalog.ts +1 -1
  85. package/src/codex/codex-home-owner.ts +3 -0
  86. package/src/codex/config-write-lock.ts +333 -0
  87. package/src/codex/convergence.ts +2 -1
  88. package/src/codex/desktop-app/darwin.ts +1 -1
  89. package/src/codex/desktop-app/handoff.ts +1 -1
  90. package/src/codex/desktop-app/linux.ts +1 -1
  91. package/src/codex/desktop-app/lock.ts +1 -1
  92. package/src/codex/desktop-app/types.ts +1 -1
  93. package/src/codex/desktop-app/windows.ts +1 -1
  94. package/src/codex/desktop-app-restart.ts +1 -1
  95. package/src/codex/features.ts +257 -200
  96. package/src/codex/inject/config-write-section.ts +34 -0
  97. package/src/codex/inject/multi-agent-v2.ts +14 -6
  98. package/src/codex/inject/remove.ts +36 -11
  99. package/src/codex/inject/restore.ts +85 -20
  100. package/src/codex/inject-coordination.ts +15 -6
  101. package/src/codex/inject.ts +62 -20
  102. package/src/codex/journal.ts +62 -17
  103. package/src/codex/main-account-cache.ts +43 -0
  104. package/src/codex/main-account.ts +6 -7
  105. package/src/codex/paths.ts +2 -0
  106. package/src/codex/prepared-home.ts +18 -0
  107. package/src/codex/prompt-journal.ts +25 -12
  108. package/src/codex/prompt-layers.ts +49 -26
  109. package/src/codex/prompt-lock-claim.ts +134 -0
  110. package/src/codex/prompt-lock-evidence.ts +26 -0
  111. package/src/codex/prompt-lock-io.ts +16 -0
  112. package/src/codex/prompt-lock-owner.ts +130 -0
  113. package/src/codex/prompt-lock.ts +84 -53
  114. package/src/codex/routing/failure-window.ts +146 -0
  115. package/src/codex/routing/selection.ts +4 -1
  116. package/src/codex/routing.ts +13 -17
  117. package/src/codex/runtime.ts +106 -18
  118. package/src/codex/shim.ts +45 -19
  119. package/src/combos/jev-service-exchange.ts +281 -0
  120. package/src/combos/jev.ts +34 -220
  121. package/src/config/atomic-write.ts +1 -1
  122. package/src/config/codex-ws-reuse-setting.ts +10 -0
  123. package/src/config/live-reconcile.ts +17 -0
  124. package/src/config/load-degrade.ts +8 -0
  125. package/src/config/rebase-provenance.ts +11 -0
  126. package/src/config/schema/config-schema.ts +4 -0
  127. package/src/generated/compatibility-version.json +375 -227
  128. package/src/generated/model-metadata.ts +2 -2
  129. package/src/grok/inject.ts +276 -206
  130. package/src/grok/reset-coupon-ledger.ts +223 -57
  131. package/src/grok/reset-coupons.ts +13 -6
  132. package/src/grok/sync.ts +2 -1
  133. package/src/images/loop.ts +29 -11
  134. package/src/integrations/aside-profiles.ts +10 -3
  135. package/src/integrations/catalog-refresh.ts +18 -2
  136. package/src/integrations/cursor-detect.ts +1 -1
  137. package/src/integrations/writer.ts +9 -3
  138. package/src/lib/bun-path-runtime.d.mts +32 -0
  139. package/src/lib/bun-path-runtime.mjs +95 -0
  140. package/src/lib/bun-runtime-preflight.ts +140 -0
  141. package/src/lib/desktop-cli-handoff.d.mts +20 -0
  142. package/src/lib/desktop-cli-handoff.mjs +92 -0
  143. package/src/lib/desktop-cli-record.d.mts +29 -0
  144. package/src/lib/desktop-cli-record.mjs +102 -0
  145. package/src/lib/errors.ts +25 -0
  146. package/src/lib/redact.ts +2 -2
  147. package/src/lib/request-execution-budget.ts +8 -0
  148. package/src/lib/synced-state-location.ts +46 -6
  149. package/src/lib/test-home-guard.ts +87 -1
  150. package/src/lib/translator-budget.ts +17 -4
  151. package/src/lib/windows-atomic-replace.ts +38 -16
  152. package/src/lib/windows-elevation.ts +6 -0
  153. package/src/lib/windows-secret-acl.ts +92 -25
  154. package/src/lib/winsw.ts +2 -3
  155. package/src/oauth/anthropic-account-refusal.ts +39 -1
  156. package/src/oauth/anthropic-routing.ts +1 -1
  157. package/src/oauth/anthropic-send-ownership.ts +3 -3
  158. package/src/oauth/chatgpt.ts +113 -41
  159. package/src/oauth/index.ts +7 -3
  160. package/src/oauth/meta-muse-device.ts +1 -1
  161. package/src/oauth/store.ts +1 -1
  162. package/src/oauth/types.ts +1 -1
  163. package/src/providers/anthropic-fast.ts +1 -1
  164. package/src/providers/anthropic-reset-grant-ledger.ts +1 -1
  165. package/src/providers/azure-model-metadata.ts +115 -0
  166. package/src/providers/derive.ts +21 -0
  167. package/src/providers/devin-cli-authmode-migration.ts +1 -1
  168. package/src/providers/devin-provider-merge-migration.ts +1 -1
  169. package/src/providers/github-copilot-auto.ts +169 -0
  170. package/src/providers/model-presets.ts +1 -1
  171. package/src/providers/muse-subscription-usage.ts +1 -1
  172. package/src/providers/quota/vendor-probes-key.ts +127 -17
  173. package/src/providers/quota.ts +1 -1
  174. package/src/providers/registry/entries-core.ts +6 -6
  175. package/src/providers/registry/entries-extended.ts +4 -0
  176. package/src/providers/registry/model-seeds.ts +3 -3
  177. package/src/providers/xai-fast-model.ts +1 -1
  178. package/src/responses/reasoning-envelope.ts +29 -1
  179. package/src/responses/reasoning-replay-cache.ts +17 -1
  180. package/src/responses/spill-store.ts +15 -2
  181. package/src/responses/state/metrics.ts +8 -0
  182. package/src/responses/state/spill-failure.ts +12 -0
  183. package/src/responses/state/spill-queue.ts +12 -5
  184. package/src/responses/state.ts +18 -10
  185. package/src/responses/task-input.ts +17 -0
  186. package/src/server/background-lifecycle.ts +27 -0
  187. package/src/server/chat-completions.ts +1 -0
  188. package/src/server/chat-native.ts +28 -12
  189. package/src/server/claude-messages.ts +43 -6
  190. package/src/server/inbound-body-admission.ts +25 -7
  191. package/src/server/index/claude-intercept-lifecycle.ts +3 -1
  192. package/src/server/index/link-listener.ts +30 -17
  193. package/src/server/index/serve-options.ts +18 -4
  194. package/src/server/index/spend-ledger-lifecycle.ts +2 -1
  195. package/src/server/index/startup-warnings.ts +19 -0
  196. package/src/server/index.ts +2 -1
  197. package/src/server/lifecycle.ts +31 -4
  198. package/src/server/management/agent-settings-routes.ts +93 -32
  199. package/src/server/management/codex-agent-role-routes.ts +4 -2
  200. package/src/server/management/codex-prompt-routes.ts +1 -0
  201. package/src/server/management/codex-role-auto-assign.ts +13 -2
  202. package/src/server/management/config-routes.ts +59 -8
  203. package/src/server/management/context.ts +2 -2
  204. package/src/server/management/grok-coupon-routes.ts +277 -52
  205. package/src/server/management/link-routes.ts +42 -20
  206. package/src/server/management/route-registry.ts +2 -2
  207. package/src/server/management/shared.ts +3 -3
  208. package/src/server/messages-native-oauth.ts +9 -8
  209. package/src/server/messages-native.ts +49 -13
  210. package/src/server/messages-response-headers.ts +14 -0
  211. package/src/server/relay-eager.ts +2 -0
  212. package/src/server/relay.ts +18 -7
  213. package/src/server/request-log-conversation.ts +48 -5
  214. package/src/server/request-log-failure-attribution.ts +3 -0
  215. package/src/server/request-log-terminal-status.ts +186 -0
  216. package/src/server/request-log.ts +15 -89
  217. package/src/server/responses/adapter-continuation.ts +11 -3
  218. package/src/server/responses/adapter-dispatch.ts +99 -19
  219. package/src/server/responses/codex-ws-exchange.ts +17 -2
  220. package/src/server/responses/codex-ws-pool.ts +100 -13
  221. package/src/server/responses/codex-ws-wire.ts +9 -0
  222. package/src/server/responses/combo-requested-effort.ts +3 -1
  223. package/src/server/responses/compact.ts +3 -2
  224. package/src/server/responses/core-codex-account.ts +22 -1
  225. package/src/server/responses/core-combo-native.ts +20 -3
  226. package/src/server/responses/core-combo.ts +22 -14
  227. package/src/server/responses/core-lifetime.ts +3 -36
  228. package/src/server/responses/core-opaque-recovery.ts +5 -5
  229. package/src/server/responses/core-options.ts +5 -0
  230. package/src/server/responses/core-replay.ts +73 -0
  231. package/src/server/responses/core.ts +9 -9
  232. package/src/server/responses/empty-completion-guard.ts +18 -2
  233. package/src/server/responses/fetch-helpers.ts +26 -3
  234. package/src/server/responses/jev-model-invoke.ts +1 -1
  235. package/src/server/responses/passthrough-delivery.ts +24 -2
  236. package/src/server/responses/passthrough-dispatch.ts +134 -62
  237. package/src/server/responses/passthrough-execution.ts +3 -3
  238. package/src/server/responses/request-prepare.ts +4 -0
  239. package/src/server/responses/request-send-budget.ts +112 -49
  240. package/src/server/responses/request-transport.ts +125 -5
  241. package/src/server/responses/response-effects.ts +1 -0
  242. package/src/server/responses/run-turn-execution.ts +15 -5
  243. package/src/server/responses/sidecar-execution.ts +30 -16
  244. package/src/server/responses/sidecar-send-budget.ts +58 -0
  245. package/src/server/responses/spend-storage-error.ts +33 -0
  246. package/src/server/responses/ws-upstream.ts +19 -6
  247. package/src/server/startup-health-cache.ts +2 -1
  248. package/src/server/workflow-refusal.ts +3 -0
  249. package/src/service/cli.ts +20 -4
  250. package/src/service/desktop-command-guard.ts +32 -0
  251. package/src/service/desktop-startup.ts +66 -40
  252. package/src/service/desktop-supervision.d.mts +26 -0
  253. package/src/service/desktop-supervision.mjs +140 -0
  254. package/src/service/managing-cli.ts +1 -0
  255. package/src/service/orchestration.ts +46 -20
  256. package/src/service/repair.ts +25 -9
  257. package/src/service/state.ts +4 -3
  258. package/src/service/systemd.ts +17 -8
  259. package/src/service/windows-ops.ts +61 -22
  260. package/src/storage/policy-job.ts +5 -1
  261. package/src/storage/policy-worker.ts +3 -1
  262. package/src/storage/policy.ts +9 -0
  263. package/src/types/config.ts +21 -0
  264. package/src/types/request.ts +10 -0
  265. package/src/types/wire.ts +1 -0
  266. package/src/update/index.ts +57 -9
  267. package/src/update/restart-ownership.ts +10 -3
  268. package/src/update/runtime-ownership.d.mts +6 -0
  269. package/src/update/runtime-ownership.mjs +23 -7
  270. package/src/usage/expected-prices.ts +1 -1
  271. package/src/web-search/loop.ts +5 -2
  272. package/gui/dist/assets/App-7yhoys8a.js +0 -54
@@ -65,6 +65,8 @@ export interface PolicyJobTestHooks {
65
65
  * policy load, so concurrent PUTs can race completion metadata writes.
66
66
  */
67
67
  blockMs?: number;
68
+ /** Test-only shared barrier after the Worker has loaded its initial policy. */
69
+ workerLoadGate?: Int32Array;
68
70
  /**
69
71
  * When true, run on the main thread via `queueMicrotask` + optional sleep.
70
72
  * Used only for unit tests that cannot spawn workers; responsiveness tests
@@ -304,7 +306,7 @@ function applyMutationBusy(): void {
304
306
  };
305
307
  }
306
308
 
307
- function runInWorker(opts: RequestPolicyRunOptions & { blockMs?: number }): Promise<PolicyRunResult> {
309
+ function runInWorker(opts: RequestPolicyRunOptions & { blockMs?: number; workerLoadGate?: Int32Array }): Promise<PolicyRunResult> {
308
310
  const reservation = tryReserveStorageWorker();
309
311
  if (!reservation) return Promise.reject(new StorageWorkerAdmissionBusyError());
310
312
  return withStorageWorkerSpawnGate(() => new Promise<PolicyRunResult>((resolve, reject) => {
@@ -369,6 +371,7 @@ function runInWorker(opts: RequestPolicyRunOptions & { blockMs?: number }): Prom
369
371
  ...(opts.codexHome ? { codexHome: opts.codexHome } : {}),
370
372
  ...(opts.busyTimeoutMs !== undefined ? { busyTimeoutMs: opts.busyTimeoutMs } : {}),
371
373
  ...(opts.blockMs !== undefined ? { blockMs: opts.blockMs } : {}),
374
+ ...(opts.workerLoadGate ? { workerLoadGate: opts.workerLoadGate } : {}),
372
375
  env: {
373
376
  ...(process.env.CODEX_HOME ? { CODEX_HOME: process.env.CODEX_HOME } : {}),
374
377
  ...(process.env.OPENCODEX_HOME ? { OPENCODEX_HOME: process.env.OPENCODEX_HOME } : {}),
@@ -410,6 +413,7 @@ async function executeJob(opts: RequestPolicyRunOptions): Promise<void> {
410
413
  ...opts,
411
414
  codexHome,
412
415
  ...(typeof blockMs === "number" && blockMs > 0 ? { blockMs } : {}),
416
+ ...(testHooks?.workerLoadGate ? { workerLoadGate: testHooks.workerLoadGate } : {}),
413
417
  });
414
418
  }
415
419
 
@@ -13,6 +13,7 @@ interface RunMessage {
13
13
  busyTimeoutMs?: number;
14
14
  /** Test-only: block after loading the start-of-job policy (see holdAfterLoadMs). */
15
15
  blockMs?: number;
16
+ workerLoadGate?: Int32Array;
16
17
  /** Env snapshot — Workers may not see parent mutations on all platforms. */
17
18
  env?: { CODEX_HOME?: string; OPENCODEX_HOME?: string };
18
19
  }
@@ -29,7 +30,7 @@ declare const self: Worker;
29
30
 
30
31
  self.onmessage = (event: MessageEvent<unknown>) => {
31
32
  if (!isRunMessage(event.data)) return;
32
- const { requestId, reason, force, codexHome, busyTimeoutMs, blockMs, env } = event.data;
33
+ const { requestId, reason, force, codexHome, busyTimeoutMs, blockMs, workerLoadGate, env } = event.data;
33
34
  try {
34
35
  if (env?.CODEX_HOME) process.env.CODEX_HOME = env.CODEX_HOME;
35
36
  if (env?.OPENCODEX_HOME) process.env.OPENCODEX_HOME = env.OPENCODEX_HOME;
@@ -38,6 +39,7 @@ self.onmessage = (event: MessageEvent<unknown>) => {
38
39
  force: force === true,
39
40
  ...(codexHome ? { codexHome } : {}),
40
41
  ...(busyTimeoutMs !== undefined ? { busyTimeoutMs } : {}),
42
+ ...(workerLoadGate ? { holdAfterLoadGate: workerLoadGate } : {}),
41
43
  ...(typeof blockMs === "number" && Number.isFinite(blockMs) && blockMs > 0
42
44
  ? { holdAfterLoadMs: Math.floor(blockMs) }
43
45
  : {}),
@@ -74,6 +74,8 @@ export interface PolicyRunDeps {
74
74
  * land before completion merges run metadata.
75
75
  */
76
76
  holdAfterLoadMs?: number;
77
+ /** Test-only Worker barrier: 0=pending, 1=policy loaded, 2=released. */
78
+ holdAfterLoadGate?: Int32Array;
77
79
  }
78
80
 
79
81
  /** Canonical defaults — enabled is always false. */
@@ -500,6 +502,13 @@ export function runStorageCleanupPolicy(deps: PolicyRunDeps): PolicyRunResult {
500
502
  })
501
503
  : (patch: PolicyRunMetadataPatch) => commitPolicyRunMetadataToConfig(patch, policy);
502
504
 
505
+ if (deps.holdAfterLoadGate) {
506
+ Atomics.compareExchange(deps.holdAfterLoadGate, 0, 0, 1);
507
+ Atomics.notify(deps.holdAfterLoadGate, 0);
508
+ if (Atomics.wait(deps.holdAfterLoadGate, 0, 1, 10_000) === "timed-out") {
509
+ throw new Error("policy_test_load_gate_timeout");
510
+ }
511
+ }
503
512
  if (typeof deps.holdAfterLoadMs === "number" && Number.isFinite(deps.holdAfterLoadMs) && deps.holdAfterLoadMs > 0) {
504
513
  Bun.sleepSync(Math.floor(deps.holdAfterLoadMs));
505
514
  }
@@ -174,6 +174,15 @@ export interface OcxClaudeCodeConfig {
174
174
  autoContext?: boolean;
175
175
  /** Compact-window tokens for auto-context. Default 829_800 (AUTO_COMPACT_WINDOW_DEFAULT). */
176
176
  autoCompactWindow?: number;
177
+ /**
178
+ * Context accounting on Claude surfaces (devlog/_plan/261009_claude_1m_default/030). Absent
179
+ * (the default) = "1m": long-window models are offered at 1M wherever opencodex picks the
180
+ * default (launch env slots, Desktop pickers, Desktop 3P prefer1m, generated subagents).
181
+ * "200k" is the opt-in: nothing is marked [1m] automatically and no compact window is injected;
182
+ * a selector the user marks [1m] keeps it, and discovery and Desktop 3P keep offering 1M as a
183
+ * choice. The only stored value; "1m" deletes the key.
184
+ */
185
+ contextAccounting?: "200k";
177
186
  /**
178
187
  * Local CONNECT proxy + TLS listener that intercepts Claude Code's own `api.anthropic.com`
179
188
  * traffic without any `ANTHROPIC_BASE_URL` rewrite (src/claude/intercept). Claude Code reaches
@@ -1174,6 +1183,18 @@ export interface OcxConfig {
1174
1183
  accountPoolStickyLimit?: number;
1175
1184
  /** Consecutive non-2xx upstream responses before switching future new threads. Default 3. 0 = disabled. */
1176
1185
  upstreamFailoverThreshold?: number;
1186
+ /**
1187
+ * Sliding 60s transient-failure ratio for Codex pool placement. Default on.
1188
+ * Set false to steer new threads from the consecutive counter only.
1189
+ */
1190
+ codexFailureWindow?: boolean;
1191
+ /**
1192
+ * What a manual pin does while its failure window is degraded.
1193
+ * `hold` keeps using it and logs a warning. `detour-new-threads` places only new threads elsewhere.
1194
+ */
1195
+ codexPinnedTransientPolicy?: "hold" | "detour-new-threads";
1196
+ /** Opt-in: retain one Codex WebSocket per account and thread across turns. Default off. */
1197
+ codexWsReuseAcrossTurns?: boolean;
1177
1198
  /**
1178
1199
  * Opt-in provider-origin circuit threshold for proven pre-connection reachability failures.
1179
1200
  * Default 0 (disabled); range 0..20. The circuit never counts timeouts or HTTP responses.
@@ -1,4 +1,5 @@
1
1
  import type { KiroOAuthMetadata } from "../oauth/types";
2
+ import type { NativeReasoningOwner } from "../responses/reasoning-replay-cache";
2
3
  import type { OcxTool, OcxToolChoice } from "./tools";
3
4
  import type { TierDecision, TierObservationContext } from "./provider";
4
5
 
@@ -57,6 +58,10 @@ export interface OcxParsedRequest {
57
58
  stream: boolean;
58
59
  options: OcxRequestOptions;
59
60
  _rawBody?: unknown;
61
+ /** Claude replay tags, retained only until each route binding verifies them. */
62
+ _nativeReasoningReplay?: ReadonlyMap<string, string>;
63
+ _nativeReasoningBoundOwner?: NativeReasoningOwner;
64
+ _nativeReasoningMint?: { owner?: NativeReasoningOwner };
60
65
  /**
61
66
  * Boundary between replayed history and this turn's newly appended input. Usually the
62
67
  * items the proxy restored from local previous_response_id state; also set when the
@@ -437,6 +442,11 @@ export type AdapterEvent =
437
442
  errorType?: string;
438
443
  code?: string;
439
444
  retryable?: boolean;
445
+ /**
446
+ * Proxy-internal, never serialized: the upstream failed the turn before producing text or a
447
+ * tool call, so the opt-in empty-completion guard may replay the identical request once.
448
+ */
449
+ replaySafeBeforeOutput?: boolean;
440
450
  };
441
451
 
442
452
  /**
package/src/types/wire.ts CHANGED
@@ -47,6 +47,7 @@ export const MODEL_ADAPTER_OVERRIDE_ALLOWED: ReadonlySet<string> = new Set([
47
47
  */
48
48
  const ANTHROPIC_WIRE_MODELS: Record<string, ReadonlySet<string>> = {
49
49
  "opencode-go": new Set([
50
+ "claude-haiku-5-5",
50
51
  "minimax-m2.5",
51
52
  "minimax-m2.7",
52
53
  "minimax-m3",
@@ -1,4 +1,5 @@
1
1
  import { spawn, spawnSync } from "node:child_process";
2
+ import { createSupervisionLatch, inspectDesktopSupervision } from "../service/desktop-supervision.mjs";
2
3
  import { manualUpdateFailureGuidance } from "./update-failure-guidance.mjs";
3
4
  import { STOP_HISTORY_INCOMPLETE_EXIT_CODE } from "./stop-contract.mjs";
4
5
  import { proxyIdentityAt } from "../server/proxy-liveness";
@@ -484,14 +485,17 @@ export async function runUpdate(): Promise<void> {
484
485
  } catch { /* best-effort */ }
485
486
  // What this update may do to the runtime. A desktop takeover vetoes both the stop and the
486
487
  // service refresh below; see `planUpdateRuntimeHandling` for why each half is wrong.
488
+ const supervisionLatch = createSupervisionLatch();
489
+ const observeSupervision = () => supervisionLatch.observe(inspectDesktopSupervision());
487
490
  const initialOwnership = await resolvedRuntimeOwnership();
488
491
  const runtimePlan = planUpdateRuntimeHandling({
489
492
  ...initialOwnership,
490
493
  serviceInstalled: serviceWasInstalled,
494
+ supervision: observeSupervision(),
491
495
  });
492
496
  if (runtimePlan.notice) console.log(runtimePlan.notice);
493
497
  if (!runtimePlan.mayReplacePackage) {
494
- console.error("⚠️ Update stopped before tray handoff, runtime stop, or package replacement because runtime ownership is unknown.");
498
+ console.error("⚠️ Update stopped before tray handoff, runtime stop, or package replacement because runtime authority does not permit it.");
495
499
  return 1;
496
500
  }
497
501
  let trayWasInstalled = false;
@@ -548,6 +552,15 @@ export async function runUpdate(): Promise<void> {
548
552
  && before?.consentGeneration === after?.consentGeneration;
549
553
  };
550
554
  const startProxyDirectly = async (): Promise<boolean> => {
555
+ const ownership = await resolvedRuntimeOwnership();
556
+ const supervision = observeSupervision();
557
+ const plan = planUpdateRuntimeHandling({ ...ownership, serviceInstalled: false, supervision });
558
+ if (!plan.mayStopRuntime) {
559
+ console.warn(supervision
560
+ ? "OpenCodex Desktop supervises the proxy; no CLI runtime was restored."
561
+ : plan.notice);
562
+ return false;
563
+ }
551
564
  if (!postUpdateLauncherUsable || !existsSync(postUpdateLauncher)) return false;
552
565
  // An ordinary owner: a stray sibling marker would otherwise mark it before any probe.
553
566
  const env = mutation.controlEnvironment(withoutSiblingMarker(process.env));
@@ -574,7 +587,7 @@ export async function runUpdate(): Promise<void> {
574
587
  const planRecovery = async () => {
575
588
  const current = await resolvedRuntimeOwnership();
576
589
  return planStoppedRuntimeRecovery({
577
- stopAttempted, ...current, sameOwner: sameOwner(current),
590
+ stopAttempted, ...current, sameOwner: sameOwner(current), supervision: observeSupervision(),
578
591
  liveness: currentPackageRuntimeLiveness(), serviceInstalled: serviceWasInstalled,
579
592
  launcherUsable: postUpdateLauncherUsable && existsSync(postUpdateLauncher), hadRuntimeState,
580
593
  });
@@ -588,10 +601,17 @@ export async function runUpdate(): Promise<void> {
588
601
  mutation.release();
589
602
  recovery = await planRecovery();
590
603
  }
591
- if (recovery.action === "manual") {
604
+ if (recovery.reason === "desktop-supervised") {
605
+ console.log("OpenCodex Desktop supervises the proxy; no CLI runtime was restored.");
606
+ } else if (recovery.action === "manual") {
592
607
  console.warn(`⚠️ ${reason}; runtime recovery requires manual review (${recovery.reason}).`);
593
608
  } else if (recovery.action === "service") {
594
609
  const { serviceReinstallArgs, isServiceViable } = await import("../service");
610
+ recovery = await planRecovery();
611
+ if (recovery.action !== "service") {
612
+ console.warn("Runtime authority changed before service recovery; no CLI runtime was restored.");
613
+ return;
614
+ }
595
615
  const service = spawnSync(process.execPath, [postUpdateLauncher, ...serviceReinstallArgs()], {
596
616
  stdio: updateChildStdio(), windowsHide: true,
597
617
  env: mutation.controlEnvironment({ ...process.env, OCX_BAKE_PORT: String(capturedListen.port) }),
@@ -602,7 +622,7 @@ export async function runUpdate(): Promise<void> {
602
622
  mutation.reacquire();
603
623
  const nowOwned = await resolvedRuntimeOwnership();
604
624
  const fallback = planStoppedRuntimeRecovery({
605
- stopAttempted, ...nowOwned, sameOwner: sameOwner(nowOwned),
625
+ stopAttempted, ...nowOwned, sameOwner: sameOwner(nowOwned), supervision: observeSupervision(),
606
626
  liveness: currentPackageRuntimeLiveness(), serviceInstalled: false,
607
627
  launcherUsable: postUpdateLauncherUsable && existsSync(postUpdateLauncher), hadRuntimeState,
608
628
  });
@@ -632,6 +652,15 @@ export async function runUpdate(): Promise<void> {
632
652
  // Full `ocx stop` semantics (drain, service stop, restore).
633
653
 
634
654
  if (runtimePlan.mayStopRuntime && (serviceWasInstalled || readPid() || readRuntimePort() || pendingTeardownOutstanding())) {
655
+ const preStopPlan = planUpdateRuntimeHandling({
656
+ ...(await resolvedRuntimeOwnership()),
657
+ serviceInstalled: serviceWasInstalled,
658
+ supervision: supervisionLatch.observe(inspectDesktopSupervision({ targetPid: runtimeTrusted ? livePid : undefined })),
659
+ });
660
+ if (!preStopPlan.mayStopRuntime) {
661
+ console.error(preStopPlan.notice);
662
+ return 1;
663
+ }
635
664
  stopAttempted = true;
636
665
  console.log("⏹ Stopping the running proxy before updating...");
637
666
  const stopStdio = updateChildStdio();
@@ -701,13 +730,14 @@ export async function runUpdate(): Promise<void> {
701
730
  stderr?: string | Buffer | null;
702
731
  } | null = null;
703
732
  let replacementRefusal: string | null = null;
704
- // Ownership can change while registry work is in flight. Unknown at this exact
705
- // boundary blocks replacement; a confirmed desktop claim still permits updating the idle
706
- // npm installation while leaving the bundled sidecar alone.
733
+ // Re-read durable ownership and live supervision before package replacement.
734
+ // Desktop supervision and foreign/unknown ownership veto replacement.
735
+ // Plain unknown supervision preserves the existing ownership/liveness decision.
707
736
  const replacementOwnership = await resolvedRuntimeOwnership();
708
737
  const replacementPlan = planUpdateRuntimeHandling({
709
738
  ...replacementOwnership,
710
739
  serviceInstalled: serviceWasInstalled,
740
+ supervision: observeSupervision(),
711
741
  });
712
742
  const replacementLiveness = currentPackageRuntimeLiveness();
713
743
  if (replacementOwnership.subjectToken !== initialOwnership.subjectToken
@@ -786,9 +816,11 @@ export async function runUpdate(): Promise<void> {
786
816
  const postInstallPlan = planUpdateRuntimeHandling({
787
817
  ...(await resolvedRuntimeOwnership()),
788
818
  serviceInstalled: serviceWasInstalled,
819
+ supervision: observeSupervision(),
789
820
  });
790
821
  if (r.status === 0) {
791
822
  console.log(`\n✅ Updated${latest ? ` to v${latest}` : ""}.`);
823
+ if (!postInstallPlan.mayStopRuntime) console.warn("Runtime authority does not permit CLI recovery; no service was refreshed or proxy started.");
792
824
  // Re-enter through the verified active package launcher. This keeps the Codex
793
825
  // shim, tray, service and proxy recovery paths on the same package/group that
794
826
  // pnpm selected, including when the update changed the global link target.
@@ -819,6 +851,16 @@ export async function runUpdate(): Promise<void> {
819
851
  // (spawn the fresh cli.ts so updated code writes the baked paths) so a
820
852
  // launchd/schtasks/systemd user isn't left with the background proxy down.
821
853
  if (postInstallPlan.mayRestoreService) {
854
+ const mayRefresh = async () => {
855
+ const ownership = await resolvedRuntimeOwnership();
856
+ const supervision = observeSupervision();
857
+ const plan = planUpdateRuntimeHandling({ ...ownership, serviceInstalled: true, supervision });
858
+ if (!plan.mayRestoreService) console.warn(supervision
859
+ ? "OpenCodex Desktop supervises the proxy; CLI recovery was skipped. Use the app's updater (tray → Check for Updates)."
860
+ : plan.notice);
861
+ return plan.mayRestoreService;
862
+ };
863
+ if (!await mayRefresh()) return;
822
864
  console.log("🔁 Refreshing the background service with the updated files...");
823
865
  const { serviceReinstallArgs } = await import("../service");
824
866
  const { reclaimListenPort } = await import("../server/port-reclaim");
@@ -840,6 +882,7 @@ export async function runUpdate(): Promise<void> {
840
882
  const prevBake = process.env.OCX_BAKE_PORT;
841
883
  process.env.OCX_BAKE_PORT = String(capturedListen.port);
842
884
  try {
885
+ if (!await mayRefresh()) return;
843
886
  const svcStdio = updateChildStdio();
844
887
  const svc = spawnSync(process.execPath, [postUpdateLauncher, ...serviceReinstallArgs()], {
845
888
  env: mutation.controlEnvironment(),
@@ -889,12 +932,17 @@ export async function runUpdate(): Promise<void> {
889
932
  console.warn(` Run 'ocx service repair', then 'ocx start --port ${capturedListen.port}'.`);
890
933
  return 1;
891
934
  }
935
+ const fallbackOwnership = await resolvedRuntimeOwnership();
936
+ const supervision = observeSupervision();
892
937
  const nowOwned = planUpdateRuntimeHandling({
893
- ...(await resolvedRuntimeOwnership()),
938
+ ...fallbackOwnership,
894
939
  serviceInstalled: true,
940
+ supervision,
895
941
  });
896
942
  if (!nowOwned.mayStopRuntime) {
897
- console.warn(nowOwned.notice ?? "⚠️ The background runtime is owned elsewhere; not starting a second proxy.");
943
+ console.warn(supervision
944
+ ? "OpenCodex Desktop supervises the proxy; CLI recovery was skipped. Use the app's updater (tray → Check for Updates)."
945
+ : nowOwned.notice ?? "⚠️ The background runtime is owned elsewhere; not starting a second proxy.");
898
946
  return;
899
947
  }
900
948
  console.warn(
@@ -6,6 +6,8 @@ import {
6
6
  OWNERSHIP_MUTATION_LEASE_TOKEN_ENV,
7
7
  } from "../service/ownership-mutation-lease.mjs";
8
8
  import { planUpdateRuntimeHandling } from "./runtime-ownership.mjs";
9
+ import { createSupervisionLatch, inspectDesktopSupervision } from "../service/desktop-supervision.mjs";
10
+ type SupervisionInspector = typeof inspectDesktopSupervision;
9
11
 
10
12
  export type { ServiceOwnershipResolution };
11
13
 
@@ -24,6 +26,8 @@ export type { ServiceOwnershipResolution };
24
26
  */
25
27
  export function updateRestartVeto(
26
28
  resolve: () => ServiceOwnershipResolution = resolveServiceOwnership,
29
+ inspect: SupervisionInspector = inspectDesktopSupervision,
30
+ latch = createSupervisionLatch(),
27
31
  ): string | null {
28
32
  const owner = resolve();
29
33
  const plan = planUpdateRuntimeHandling({
@@ -31,6 +35,7 @@ export function updateRestartVeto(
31
35
  ownershipUnknown: owner.kind === "unknown",
32
36
  // The restart decision does not refresh the service; only the stop veto is read here.
33
37
  serviceInstalled: false,
38
+ supervision: latch.observe(inspect()),
34
39
  });
35
40
  if (plan.mayStopRuntime) return null;
36
41
  return plan.notice ?? "The background runtime is owned elsewhere; it was left running.";
@@ -78,7 +83,9 @@ const REACQUIRE_WAIT_MS = 10_000;
78
83
  export async function runUpdateRestartWithOwnershipLease<T>(
79
84
  resolve: (() => ServiceOwnershipResolution) | undefined,
80
85
  restart: (lease: UpdateRestartLeaseControl) => Promise<T>,
86
+ inspect: SupervisionInspector = inspectDesktopSupervision,
81
87
  ): Promise<{ readonly kind: "veto"; readonly notice: string } | { readonly kind: "ran"; readonly value: T }> {
88
+ const latch = createSupervisionLatch();
82
89
  let lease = acquireOwnershipMutationLease(serviceStatePaths());
83
90
  const previous = process.env[OWNERSHIP_MUTATION_LEASE_TOKEN_ENV];
84
91
  process.env[OWNERSHIP_MUTATION_LEASE_TOKEN_ENV] = lease.token;
@@ -107,11 +114,11 @@ export async function runUpdateRestartWithOwnershipLease<T>(
107
114
  heldNow = true;
108
115
  process.env[OWNERSHIP_MUTATION_LEASE_TOKEN_ENV] = lease.token;
109
116
  }
110
- const veto = updateRestartVeto(resolve);
117
+ const veto = updateRestartVeto(resolve, inspect, latch);
111
118
  return veto ? { notice: veto, failed: false } : null;
112
119
  };
113
120
  try {
114
- const veto = updateRestartVeto(resolve);
121
+ const veto = updateRestartVeto(resolve, inspect, latch);
115
122
  return veto
116
123
  ? { kind: "veto", notice: veto }
117
124
  : {
@@ -119,7 +126,7 @@ export async function runUpdateRestartWithOwnershipLease<T>(
119
126
  value: await restart({
120
127
  releaseForServiceManager: release,
121
128
  reacquireForDirectStart,
122
- vetoAgain: () => updateRestartVeto(resolve),
129
+ vetoAgain: () => updateRestartVeto(resolve, inspect, latch),
123
130
  }),
124
131
  };
125
132
  } finally {
@@ -1,6 +1,10 @@
1
+ import type { SupervisionEvidence } from "../service/desktop-supervision.mjs";
2
+
1
3
  export declare function planUpdateRuntimeHandling(input: {
2
4
  ownership: { owner: string; installId: string; consentGeneration: number } | null;
3
5
  ownershipUnknown?: boolean;
6
+ /** Fresh evidence or the operation's supervision latch verdict. */
7
+ supervision?: SupervisionEvidence | boolean;
4
8
  serviceInstalled: boolean;
5
9
  }): {
6
10
  mayReplacePackage: boolean;
@@ -13,6 +17,8 @@ export declare function planStoppedRuntimeRecovery(input: {
13
17
  stopAttempted: boolean;
14
18
  ownership: { owner: string; installId: string; consentGeneration: number } | null;
15
19
  ownershipUnknown?: boolean;
20
+ /** Fresh evidence or the operation's supervision latch verdict. */
21
+ supervision?: SupervisionEvidence | boolean;
16
22
  sameOwner: boolean;
17
23
  liveness: "live" | "dead" | "unknown";
18
24
  serviceInstalled: boolean;
@@ -7,6 +7,11 @@
7
7
  * situation separately is how a fix ships on one side only.
8
8
  */
9
9
 
10
+ function desktopSupervisionBlocked(supervision) {
11
+ return supervision === true || supervision?.kind === "desktop"
12
+ || (supervision?.kind === "unknown" && supervision.desktopSeen);
13
+ }
14
+
10
15
  /**
11
16
  * Decide how an update treats a runtime it may not own.
12
17
  *
@@ -21,11 +26,11 @@
21
26
  * The service registration itself is untouched in every case. It is kept by decision, not by
22
27
  * accident, so a user who later runs `ocx service install` gets their npm service back.
23
28
  *
24
- * THE COST OF A STALE MARKER. This reads the recorded claim, not liveness. An app deleted
25
- * without releasing ownership leaves a marker behind, and an update then declines to stop or
26
- * refresh a runtime no app is managing any more. That is the orphan-recovery cost the
27
- * two-record ownership design accepted; `ocx service install` clears the marker and restores
28
- * the ordinary path.
29
+ * Durable ownership and live supervision are separate. Desktop supervision denies package
30
+ * replacement, stop and restoration even without a claim. A latch retains that veto through
31
+ * inconclusive probes until a positive none. Plain unknown supervision alone keeps existing
32
+ * behavior; unknown durable ownership still vetoes. Explicit service install recovers a stale
33
+ * durable claim after Desktop has quit.
29
34
  *
30
35
  * The three returned flags are separate authorities, not commands. In particular, leaving
31
36
  * a runtime running is not permission to replace the package it may be executing from.
@@ -34,10 +39,19 @@
34
39
  * carries installation identity, it therefore blocks package replacement as well as stop and
35
40
  * restoration; the notice tells a stale-marker user how to take ownership back explicitly.
36
41
  *
37
- * @param {{ ownership: { owner: string, installId: string, consentGeneration: number } | null, ownershipUnknown?: boolean, serviceInstalled: boolean }} input
42
+ * @param {{ ownership: { owner: string, installId: string, consentGeneration: number } | null, ownershipUnknown?: boolean, serviceInstalled: boolean, supervision?: boolean | ReturnType<typeof import('../service/desktop-supervision.mjs').inspectDesktopSupervision> }} input
38
43
  * @returns {{ mayReplacePackage: boolean, mayStopRuntime: boolean, mayRestoreService: boolean, notice: string | null }}
39
44
  */
40
- export function planUpdateRuntimeHandling({ ownership, ownershipUnknown = false, serviceInstalled }) {
45
+ export function planUpdateRuntimeHandling({ ownership, ownershipUnknown = false, serviceInstalled, supervision }) {
46
+ if (desktopSupervisionBlocked(supervision)) {
47
+ return {
48
+ mayReplacePackage: false,
49
+ mayStopRuntime: false,
50
+ mayRestoreService: false,
51
+ notice: "OpenCodex Desktop runs this proxy from its own bundle; use the app's updater (tray → Check for Updates). "
52
+ + "This npm/Bun install was left unchanged; quit OpenCodex first to update it.",
53
+ };
54
+ }
41
55
  // Unreadable, malformed or contradictory is not "nobody owns it". Reading it that way is
42
56
  // how a permissions error reactivates the npm launcher over a consented takeover.
43
57
  if (ownershipUnknown) {
@@ -77,6 +91,7 @@ export function planUpdateRuntimeHandling({ ownership, ownershipUnknown = false,
77
91
  /** Decide recovery after this updater already stopped the prior CLI-owned runtime. */
78
92
  export function planStoppedRuntimeRecovery({
79
93
  stopAttempted,
94
+ supervision,
80
95
  ownership,
81
96
  ownershipUnknown = false,
82
97
  sameOwner,
@@ -86,6 +101,7 @@ export function planStoppedRuntimeRecovery({
86
101
  hadRuntimeState,
87
102
  }) {
88
103
  if (!stopAttempted) return { action: "none", reason: "not-stopped" };
104
+ if (desktopSupervisionBlocked(supervision)) return { action: "none", reason: "desktop-supervised" };
89
105
  if (ownershipUnknown) return { action: "manual", reason: "ownership-unknown" };
90
106
  if (!sameOwner || (ownership && ownership.owner !== "cli")) {
91
107
  return { action: "none", reason: "ownership-transferred" };
@@ -835,7 +835,7 @@ export const CONTEXT_TIERS: readonly ContextTier[] = [
835
835
  {
836
836
  // xAI documents the same whole-request >=200k band for grok-4.7;
837
837
  // priority stacking remains a lower bound. See
838
- // devlog/_plan/260923_grok47_parity/010_probe-evidence.md.
838
+ // devlog/_fin/260923_grok47_parity/010_probe-evidence.md.
839
839
  provider: "xai",
840
840
  modelId: "grok-4.7",
841
841
  thresholdInputTokens: 200_000,
@@ -323,7 +323,7 @@ export interface WebSearchLoopDeps {
323
323
  /** Observe the exact adapter request selected for each routed-model iteration. */
324
324
  onRequestBuilt?: (request: AdapterRequest) => void;
325
325
  /** Request-scoped executor retains the core's selection binding across loop retries. */
326
- fetchForRequest?: (request: AdapterRequest, parsed: OcxParsedRequest) => typeof globalThis.fetch;
326
+ fetchForRequest?: (request: AdapterRequest, parsed: OcxParsedRequest, adapter: ProviderAdapter) => typeof globalThis.fetch;
327
327
  /** Called before each routed-model dispatch in the loop, for attempt telemetry. Same-target 429 replays pass the `rate-limit-429` recovery kind. */
328
328
  onAttemptSend?: (recovery?: AttemptRecoveryKind) => void;
329
329
  /**
@@ -494,7 +494,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
494
494
  cachedRequest = request;
495
495
  cachedAdapter = requestAdapter;
496
496
  }
497
- const requestFetch = headerDeadline.pacedFetch(deps.fetchForRequest?.(request, iterParsed) ?? routedProviderFetch);
497
+ const requestFetch = headerDeadline.pacedFetch(deps.fetchForRequest?.(request, iterParsed, requestAdapter) ?? routedProviderFetch);
498
498
  let response: Response;
499
499
  try {
500
500
  if (requestAdapter.fetchResponse) {
@@ -507,6 +507,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
507
507
  sendBudget: deps.incomingMeta.sendBudget,
508
508
  onPhysicalSend: deps.incomingMeta.onPhysicalSend,
509
509
  executor: requestFetch,
510
+ onRecoveryWithheld: deps.incomingMeta.onRecoveryWithheld,
510
511
  });
511
512
  } else {
512
513
  response = await fetchWithResetRetry(
@@ -576,6 +577,8 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
576
577
  // 429 key-failover parity with the normal routed path: rotate pool keys until one responds
577
578
  // or the pool is exhausted (deps.on429 returns null — cooldown map guarantees termination).
578
579
  while ((prepared.response.status === 429
580
+ || (prepared.response.status === 401 && isAnthropicInstanceId(deps.incomingMeta?.providerName)
581
+ && !accountRefusalOutputStarted)
579
582
  || (prepared.response.status === 403
580
583
  && (isAnthropicInstanceId(deps.incomingMeta?.providerName) || deps.incomingMeta?.providerName === "google-antigravity")
581
584
  && !accountRefusalOutputStarted)