@bitkyc08/opencodex 2.82.0 → 2.84.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 (266) hide show
  1. package/gui/dist/assets/App-CZtqiGcw.js +56 -0
  2. package/gui/dist/assets/Tray-C9TGtwad.js +1 -0
  3. package/gui/dist/assets/{index-BAbcj51J.css → index-BB6uK6tU.css} +1 -1
  4. package/gui/dist/assets/index-CTm4l-HQ.js +94 -0
  5. package/gui/dist/assets/{quota-summary-DTBC8n7-.js → quota-summary-BbEeRfPY.js} +1 -1
  6. package/gui/dist/index.html +2 -2
  7. package/package.json +2 -2
  8. package/src/adapters/coding-agent/protocol.ts +15 -8
  9. package/src/adapters/cursor/catalog.ts +2 -2
  10. package/src/adapters/cursor/effort-map.ts +1 -1
  11. package/src/adapters/devin/live-models.ts +2 -2
  12. package/src/adapters/google-truncation.ts +22 -0
  13. package/src/adapters/google.ts +7 -3
  14. package/src/adapters/ollama-native.ts +47 -15
  15. package/src/adapters/openai-chat/messages.ts +8 -4
  16. package/src/adapters/openai-responses/empty-assistant.ts +32 -0
  17. package/src/adapters/openai-responses/passthrough.ts +5 -0
  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/request-strips.ts +10 -2
  21. package/src/adapters/qoder/adapter.ts +16 -14
  22. package/src/bridge/errors.ts +26 -1
  23. package/src/bridge.ts +1 -1
  24. package/src/claude/context-windows.ts +57 -4
  25. package/src/claude/desktop-picker.ts +1 -1
  26. package/src/claude/intercept/connect-proxy.ts +10 -3
  27. package/src/claude/intercept/picker-ca-persistence.ts +3 -1
  28. package/src/claude/intercept/picker-listener.ts +49 -1
  29. package/src/claude/intercept/settings-no-proxy.ts +146 -0
  30. package/src/claude/intercept/settings.ts +101 -9
  31. package/src/cli/account-api.ts +65 -0
  32. package/src/cli/account-auth.ts +44 -12
  33. package/src/cli/account.ts +41 -5
  34. package/src/cli/capabilities-access-remote.ts +8 -0
  35. package/src/cli/capabilities-base.ts +13 -1
  36. package/src/cli/catalog-command-result.ts +2 -1
  37. package/src/cli/claude.ts +15 -6
  38. package/src/cli/config-command.ts +8 -2
  39. package/src/cli/debug.ts +8 -0
  40. package/src/cli/dispatch.ts +16 -3
  41. package/src/cli/export-command.ts +14 -1
  42. package/src/cli/hub-disable.ts +99 -0
  43. package/src/cli/hub.ts +4 -2
  44. package/src/cli/index.ts +13 -4
  45. package/src/cli/link-child.ts +104 -0
  46. package/src/cli/link-enrollment.ts +96 -0
  47. package/src/cli/link.ts +39 -24
  48. package/src/cli/observe-stream.ts +6 -1
  49. package/src/cli/observe.ts +10 -2
  50. package/src/cli/provider.ts +12 -0
  51. package/src/cli/registry.ts +5 -4
  52. package/src/cli/resolve.ts +1 -1
  53. package/src/cli/runtime-api.ts +27 -2
  54. package/src/cli/status.ts +104 -20
  55. package/src/client/connect.ts +39 -4
  56. package/src/client/hub-client.ts +14 -7
  57. package/src/client/hub-state.ts +25 -14
  58. package/src/client/link-home.ts +248 -0
  59. package/src/client/link-management-relay.ts +61 -0
  60. package/src/client/link-relay.ts +6 -1
  61. package/src/client/link-status.ts +14 -0
  62. package/src/client/machine-api.ts +14 -7
  63. package/src/client/machine-listener.ts +29 -4
  64. package/src/clients/config-export/model-metadata.ts +16 -0
  65. package/src/clients/config-export/zcode-store.ts +46 -11
  66. package/src/clients/config-export/zcode.ts +3 -5
  67. package/src/clients/config-export.ts +47 -17
  68. package/src/clients/omo-role-models.ts +6 -3
  69. package/src/codex/agent-role-models.ts +26 -8
  70. package/src/codex/auth-api/account-list.ts +17 -2
  71. package/src/codex/auth-api/account-selection.ts +17 -7
  72. package/src/codex/auth-api/pool-mode-gate.ts +4 -5
  73. package/src/codex/auth-api/routes.ts +5 -1
  74. package/src/codex/auth-context.ts +8 -3
  75. package/src/codex/autostart-health.ts +3 -1
  76. package/src/codex/catalog/bundled.ts +5 -1
  77. package/src/codex/catalog/effort.ts +2 -2
  78. package/src/codex/catalog/metadata.ts +4 -2
  79. package/src/codex/catalog/native-models.ts +17 -3
  80. package/src/codex/catalog/provider-models.ts +25 -0
  81. package/src/codex/desktop-app/darwin.ts +1 -1
  82. package/src/codex/desktop-app/handoff.ts +1 -1
  83. package/src/codex/desktop-app/linux.ts +1 -1
  84. package/src/codex/desktop-app/lock.ts +1 -1
  85. package/src/codex/desktop-app/types.ts +1 -1
  86. package/src/codex/desktop-app/windows.ts +1 -1
  87. package/src/codex/desktop-app-restart.ts +1 -1
  88. package/src/codex/main-account.ts +6 -7
  89. package/src/codex/native-profile-startup.ts +4 -1
  90. package/src/codex/prompt-journal.ts +20 -2
  91. package/src/codex/prompt-layers/encoding.ts +49 -0
  92. package/src/codex/prompt-layers/import-source.ts +30 -0
  93. package/src/codex/prompt-layers/toml-edit.ts +269 -37
  94. package/src/codex/prompt-layers/toml-read.ts +52 -4
  95. package/src/codex/prompt-layers.ts +383 -20
  96. package/src/codex/prompt-lock-claim.ts +13 -3
  97. package/src/codex/prompt-lock-evidence.ts +3 -3
  98. package/src/codex/prompt-lock-owner.ts +14 -6
  99. package/src/codex/prompt-text-probe.ts +34 -5
  100. package/src/codex/quota.ts +13 -6
  101. package/src/codex/role-auto-assign.ts +2 -5
  102. package/src/codex/routing/active-account.ts +21 -0
  103. package/src/codex/routing.ts +1 -1
  104. package/src/codex/runtime.ts +196 -8
  105. package/src/codex/shim-overlay.ts +8 -4
  106. package/src/codex/shim.ts +1 -1
  107. package/src/combos/failover.ts +3 -0
  108. package/src/config/api-key-reconcile.ts +34 -0
  109. package/src/config/diagnostics.ts +16 -0
  110. package/src/config/feature-flags.ts +5 -0
  111. package/src/config/live-reconcile.ts +43 -29
  112. package/src/config/live-topology.ts +29 -0
  113. package/src/config/load-degrade.ts +2 -1
  114. package/src/config/paths.ts +3 -0
  115. package/src/config/salvage.ts +3 -1
  116. package/src/config/schema/config-schema.ts +2 -0
  117. package/src/generated/compatibility-version.json +373 -217
  118. package/src/grok/grpc-web.ts +23 -1
  119. package/src/grok/inject.ts +245 -221
  120. package/src/grok/reset-coupon-ledger.ts +293 -57
  121. package/src/grok/reset-coupons.ts +15 -6
  122. package/src/integrations/cursor-detect.ts +1 -1
  123. package/src/integrations/mutation-plan.ts +13 -7
  124. package/src/integrations/registry.ts +45 -11
  125. package/src/integrations/state.ts +19 -7
  126. package/src/integrations/target.ts +42 -5
  127. package/src/integrations/writer.ts +14 -6
  128. package/src/lib/app-owned-memory-stores.ts +4 -0
  129. package/src/lib/app-owned-memory.ts +11 -0
  130. package/src/lib/errors.ts +25 -0
  131. package/src/lib/json-byte-size.ts +31 -0
  132. package/src/lib/optional-shutdown-hooks.ts +35 -0
  133. package/src/lib/outbound-credential-registry.ts +210 -0
  134. package/src/lib/passive-read.ts +35 -0
  135. package/src/lib/redact.ts +2 -2
  136. package/src/lib/shadow-call.ts +44 -5
  137. package/src/link/codex-settings.ts +155 -0
  138. package/src/link/management-routes.ts +89 -0
  139. package/src/link/remote-probe.ts +38 -0
  140. package/src/link/ssh-argv.ts +26 -5
  141. package/src/link/ssh-runner.ts +58 -27
  142. package/src/link/status-projection.ts +22 -4
  143. package/src/link/supervisor.ts +144 -49
  144. package/src/link/tunnel-state.ts +11 -4
  145. package/src/oauth/anthropic-continuity.ts +4 -3
  146. package/src/oauth/anthropic-identity.ts +13 -2
  147. package/src/oauth/anthropic-model-quota.ts +13 -1
  148. package/src/oauth/anthropic-routing.ts +230 -23
  149. package/src/oauth/anthropic.ts +18 -4
  150. package/src/oauth/google-antigravity.ts +24 -7
  151. package/src/oauth/index.ts +25 -16
  152. package/src/oauth/kiro-account-identity.ts +106 -0
  153. package/src/oauth/kiro.ts +48 -5
  154. package/src/oauth/meta-muse-device.ts +1 -1
  155. package/src/oauth/plan.ts +29 -0
  156. package/src/oauth/store.ts +40 -3
  157. package/src/oauth/types.ts +3 -1
  158. package/src/plugins/loader.ts +11 -0
  159. package/src/providers/anthropic-billing-ownership.ts +74 -0
  160. package/src/providers/anthropic-billing-recovery.ts +31 -0
  161. package/src/providers/anthropic-billing-refusal.ts +55 -0
  162. package/src/providers/anthropic-fast.ts +1 -1
  163. package/src/providers/anthropic-reset-admission.ts +62 -0
  164. package/src/providers/anthropic-reset-grant-ledger.ts +29 -7
  165. package/src/providers/api-key-resolve.ts +17 -2
  166. package/src/providers/devin-cli-authmode-migration.ts +1 -1
  167. package/src/providers/devin-provider-merge-migration.ts +1 -1
  168. package/src/providers/github-copilot-auto.ts +169 -0
  169. package/src/providers/key-failover.ts +52 -5
  170. package/src/providers/model-presets.ts +1 -1
  171. package/src/providers/model-rename-startup.ts +5 -3
  172. package/src/providers/muse-subscription-usage.ts +1 -1
  173. package/src/providers/quota/account-cache.ts +11 -0
  174. package/src/providers/quota/anthropic-account-quota.ts +4 -2
  175. package/src/providers/quota/report-cache.ts +14 -0
  176. package/src/providers/quota/vendor-probes-oauth.ts +3 -3
  177. package/src/providers/quota.ts +4 -1
  178. package/src/providers/registry/entries-core.ts +20 -20
  179. package/src/providers/registry/entries-extended.ts +4 -1
  180. package/src/providers/registry/model-seeds.ts +20 -3
  181. package/src/providers/request-pacing.ts +9 -0
  182. package/src/providers/stale-no-vision-seed-migration.ts +72 -0
  183. package/src/providers/xai-fast-model.ts +1 -1
  184. package/src/responses/compaction.ts +14 -0
  185. package/src/responses/parser.ts +7 -1
  186. package/src/server/auth-cors.ts +42 -0
  187. package/src/server/configured-credentials.ts +194 -0
  188. package/src/server/inbound-body-admission.ts +24 -7
  189. package/src/server/index/link-listener.ts +30 -17
  190. package/src/server/index/link-management.ts +58 -0
  191. package/src/server/index/optional-listeners.ts +5 -1
  192. package/src/server/index/serve-options.ts +21 -2
  193. package/src/server/index.ts +1 -1
  194. package/src/server/lifecycle.ts +33 -5
  195. package/src/server/management/agent-settings-routes.ts +28 -10
  196. package/src/server/management/anthropic-reset-grant-routes.ts +17 -1
  197. package/src/server/management/codex-agent-role-routes.ts +19 -6
  198. package/src/server/management/codex-prompt-routes.ts +136 -5
  199. package/src/server/management/codex-role-auto-assign.ts +1 -1
  200. package/src/server/management/grok-coupon-routes.ts +333 -57
  201. package/src/server/management/link-enrollment.ts +192 -0
  202. package/src/server/management/link-route-state.ts +185 -0
  203. package/src/server/management/link-routes.ts +92 -390
  204. package/src/server/management/model-rows.ts +3 -1
  205. package/src/server/management/provider-overwrite-carry.ts +10 -0
  206. package/src/server/management/provider-routes.ts +1 -0
  207. package/src/server/management/route-registry.ts +7 -5
  208. package/src/server/management/shared.ts +3 -0
  209. package/src/server/management-api.ts +3 -1
  210. package/src/server/messages-native.ts +68 -42
  211. package/src/server/relay-eager.ts +4 -0
  212. package/src/server/relay.ts +18 -7
  213. package/src/server/request-log-failure-attribution.ts +3 -0
  214. package/src/server/request-log-filter.ts +6 -1
  215. package/src/server/request-log-terminal-status.ts +243 -0
  216. package/src/server/request-log.ts +15 -118
  217. package/src/server/responses/adapter-continuation.ts +9 -1
  218. package/src/server/responses/adapter-dispatch.ts +293 -81
  219. package/src/server/responses/code-mode-collab-surface.ts +205 -0
  220. package/src/server/responses/codex-ws-exchange.ts +147 -6
  221. package/src/server/responses/codex-ws-wire.ts +203 -0
  222. package/src/server/responses/collaboration.ts +36 -7
  223. package/src/server/responses/compact.ts +129 -50
  224. package/src/server/responses/context-overflow.ts +13 -1
  225. package/src/server/responses/core-codex-account.ts +105 -1
  226. package/src/server/responses/core-combo-failure.ts +14 -0
  227. package/src/server/responses/core-combo.ts +7 -2
  228. package/src/server/responses/core-errors.ts +29 -1
  229. package/src/server/responses/core-opaque-recovery.ts +5 -5
  230. package/src/server/responses/core-options.ts +2 -0
  231. package/src/server/responses/core.ts +6 -6
  232. package/src/server/responses/deferred-collab-surface.ts +158 -0
  233. package/src/server/responses/deferred-send-reporter.ts +25 -0
  234. package/src/server/responses/empty-completion-guard.ts +18 -2
  235. package/src/server/responses/fetch-helpers.ts +12 -1
  236. package/src/server/responses/jev-model-invoke.ts +1 -1
  237. package/src/server/responses/passthrough-delivery.ts +4 -1
  238. package/src/server/responses/passthrough-dispatch.ts +130 -64
  239. package/src/server/responses/passthrough-execution.ts +3 -3
  240. package/src/server/responses/request-prepare.ts +6 -4
  241. package/src/server/responses/request-transport.ts +131 -13
  242. package/src/server/responses/run-turn-execution.ts +13 -5
  243. package/src/server/responses/sidecar-execution.ts +16 -2
  244. package/src/server/responses/spend-storage-error.ts +33 -0
  245. package/src/server/responses/ws-upstream.ts +9 -1
  246. package/src/server/startup-action-control.ts +22 -2
  247. package/src/server/startup-health-cache.ts +4 -0
  248. package/src/server/system-env-shell.ts +7 -2
  249. package/src/server/system-env.ts +11 -1
  250. package/src/service/cli.ts +5 -1
  251. package/src/service/desktop-startup.ts +147 -34
  252. package/src/service/desktop-supervision.d.mts +27 -1
  253. package/src/service/desktop-supervision.mjs +111 -5
  254. package/src/service/health-sentinel-launch.ts +176 -0
  255. package/src/service/health-sentinel-main.ts +447 -0
  256. package/src/service/health-sentinel-policy.ts +241 -0
  257. package/src/service/health-sentinel-probe.ts +54 -0
  258. package/src/service/health-sentinel-windows.ts +87 -0
  259. package/src/service/linux-linger.ts +20 -0
  260. package/src/types/config.ts +5 -0
  261. package/src/types/request.ts +5 -0
  262. package/src/usage/expected-prices.ts +5 -1
  263. package/src/usage/log.ts +19 -1
  264. package/gui/dist/assets/App-Ds_qL7o8.js +0 -54
  265. package/gui/dist/assets/Tray-BqHF5Trd.js +0 -1
  266. package/gui/dist/assets/index-D3FBCNiP.js +0 -94
@@ -4,6 +4,8 @@ import { stampApiKeyAccountLabel, usesApiKeyAccount } from "../providers/label";
4
4
  import { KEY_ACCOUNT_LOG_LABEL_RE } from "../codex/account-label";
5
5
  import { attemptAccountChanged, sealRequestAttemptIdentity } from "./request-log-account-rotation";
6
6
  export { sealRequestAttemptIdentity };
7
+ import { captureUpstreamTerminalDiagnostics, upstreamDiagnosticLogFields, type UpstreamErrorDiagnostics, type UpstreamErrorPayload } from "./request-log-terminal-status";
8
+ export { noteUpstreamRequestId } from "./request-log-terminal-status";
7
9
  import { readBoundedResponseBody } from "../lib/bounded-body";
8
10
  import type { ResponsesTerminalStatus } from "../bridge";
9
11
  import {
@@ -12,8 +14,6 @@ import {
12
14
  httpStatusFromTerminalError as httpStatusFromClassifiedTerminalError,
13
15
  isClientClosedMessage,
14
16
  isCyberPolicyCode,
15
- isCyberPolicyMessage,
16
- isRateLimitOrQuotaFailureMessage,
17
17
  isUpstreamResetReplayRefusedMessage,
18
18
  upstreamErrorMessageFromPayload,
19
19
  } from "../lib/errors";
@@ -104,7 +104,7 @@ function cacheDiagnosticHooks(): CacheDiagnosticHooks | undefined {
104
104
  return (globalThis as Record<symbol, CacheDiagnosticHooks | undefined>)[CACHE_DIAGNOSTIC_HOOK];
105
105
  }
106
106
 
107
- export interface RequestLogContext {
107
+ export interface RequestLogContext extends UpstreamErrorDiagnostics {
108
108
  model: string;
109
109
  provider: string;
110
110
  /** Optional process-lifetime aggregate sink, injected by the server composition owner. */
@@ -232,8 +232,6 @@ export interface RequestLogContext {
232
232
  * message) extracted from a `response.failed` SSE payload or non-streaming error body, so the
233
233
  * request log / GUI shows the actual upstream failure rather than only the HTTP-mapped code. */
234
234
  upstreamError?: string;
235
- upstreamErrorCode?: string;
236
- upstreamRequestId?: string;
237
235
  /** HTTP status derived from a terminal `response.failed` SSE payload (429/401/503/etc.). */
238
236
  terminalHttpStatus?: number;
239
237
  /** Recognized structured terminal code whose exact identity must survive status mapping. */
@@ -256,6 +254,8 @@ export interface RequestLogContext {
256
254
  conversationStateScrub?: "account-change";
257
255
  transportPhase?: "pre_headers" | "mid_stream" | "terminal_sse";
258
256
  terminalSource?: "upstream" | "synthetic";
257
+ /** Closed failure evidence supplied by the transport, never inferred from provider text. */
258
+ causeHint?: RequestFailureCause;
259
259
  /** Bounded route-decision trace (RI-01); never contains secrets. */
260
260
  routeDecision?: RouteDecisionTraceV1;
261
261
  /** Full eligible provider/model membership from a policy route; never logged. */
@@ -284,7 +284,7 @@ export function rebindCacheDiagnosticBody(
284
284
  cacheDiagnosticHooks()?.rebind(body, draft);
285
285
  }
286
286
 
287
- export interface RequestLogEntry {
287
+ export interface RequestLogEntry extends UpstreamErrorDiagnostics {
288
288
  requestId: string;
289
289
  /** The logical request this row belongs to (#4546); absent on rows written without a budget. */
290
290
  logicalRequestId?: string;
@@ -344,8 +344,6 @@ export interface RequestLogEntry {
344
344
  closeReason?: "terminal" | "client_cancel" | "non_stream" | "body_stall" | "body_overflow";
345
345
  /** Secret-redacted upstream error reason, surfaced in /api/logs and the GUI detail modal. */
346
346
  upstreamError?: string;
347
- upstreamErrorCode?: string;
348
- upstreamRequestId?: string;
349
347
  usageStatus: UsageStatus;
350
348
  usage?: OcxUsage;
351
349
  totalTokens?: number;
@@ -844,6 +842,7 @@ export function requestLogErrorCode(
844
842
  status: number,
845
843
  upstreamError?: string,
846
844
  terminalErrorCode?: string,
845
+ replayRefusal = false,
847
846
  ): string | undefined {
848
847
  if (status >= 200 && status < 400) return undefined;
849
848
  // A structured terminal code is authoritative even when the provider message is localized,
@@ -872,10 +871,8 @@ export function requestLogErrorCode(
872
871
  return "permission_denied";
873
872
  }
874
873
  if (status === 429) {
875
- // A refused ambiguous reset answers 429 by design (it must not invite a client
876
- // retry that could duplicate inference); classify it by its message so the log
877
- // distinguishes a proxy refusal from provider throttling.
878
- if (upstreamError?.trim() && isUpstreamResetReplayRefusedMessage(upstreamError)) {
874
+ // Prefer transport provenance; retain the legacy message fallback for older callers.
875
+ if (replayRefusal || (upstreamError?.trim() && isUpstreamResetReplayRefusedMessage(upstreamError))) {
879
876
  return UPSTREAM_RESET_REPLAY_REFUSED_CODE;
880
877
  }
881
878
  return "rate_limit_exceeded";
@@ -1099,24 +1096,6 @@ export function inspectResponseLogSsePayloadParsed(
1099
1096
  * a non-streaming JSON error body. We keep the FIRST non-empty reason (the original failure) and
1100
1097
  * run it through redactSecretString so secrets never reach /api/logs. Pure; safe on any text.
1101
1098
  */
1102
- const UPSTREAM_DIAGNOSTIC_TOKEN = /^[A-Za-z0-9_.:-]{1,128}$/;
1103
-
1104
- function noteBoundedDiagnostic(
1105
- logCtx: RequestLogContext,
1106
- field: "upstreamErrorCode" | "upstreamRequestId",
1107
- value: unknown,
1108
- ): void {
1109
- if (logCtx[field] !== undefined) return;
1110
- if (typeof value !== "string" || !UPSTREAM_DIAGNOSTIC_TOKEN.test(value)) return;
1111
- logCtx[field] = value;
1112
- const status = logCtx.terminalHttpStatus;
1113
- if (status === undefined || status >= 500) console.warn(`[opencodex] upstream failure${status ? ` status=${status}` : ""}${logCtx.upstreamErrorCode ? ` code=${logCtx.upstreamErrorCode}` : ""}${logCtx.upstreamRequestId ? ` request_id=${logCtx.upstreamRequestId}` : ""}`);
1114
- }
1115
-
1116
- export function noteUpstreamRequestId(logCtx: RequestLogContext, headers: Headers): void {
1117
- noteBoundedDiagnostic(logCtx, "upstreamRequestId", headers.get("openai-request-id") ?? headers.get("x-request-id"));
1118
- }
1119
-
1120
1099
  function captureUpstreamError(logCtx: RequestLogContext, text: string | null): void {
1121
1100
  if (!text) return;
1122
1101
  let parsed: unknown | undefined;
@@ -1134,21 +1113,8 @@ function captureUpstreamErrorParsed(
1134
1113
  parsed: unknown | undefined,
1135
1114
  ): void {
1136
1115
  if (parsed !== undefined && parsed !== null) {
1137
- const json = parsed as {
1138
- type?: unknown;
1139
- error?: { message?: unknown; code?: unknown };
1140
- last_error?: { message?: unknown; code?: unknown };
1141
- response?: {
1142
- error?: { type?: unknown; code?: unknown; message?: unknown };
1143
- incomplete_details?: { reason?: unknown; message?: unknown };
1144
- };
1145
- };
1146
- captureTerminalHttpStatus(logCtx, json);
1147
- noteBoundedDiagnostic(
1148
- logCtx,
1149
- "upstreamErrorCode",
1150
- json.error?.code ?? json.response?.error?.code ?? json.last_error?.code,
1151
- );
1116
+ const json = parsed as UpstreamErrorPayload;
1117
+ captureUpstreamTerminalDiagnostics(logCtx, json);
1152
1118
  const reason = json?.response?.incomplete_details?.reason;
1153
1119
  if (json.type === "response.incomplete"
1154
1120
  && logCtx.terminalIncompleteReason === undefined
@@ -1192,75 +1158,6 @@ function incompleteReasonLabel(reason: string): string {
1192
1158
  }
1193
1159
  }
1194
1160
 
1195
- function captureTerminalHttpStatus(
1196
- logCtx: RequestLogContext,
1197
- json: {
1198
- type?: unknown;
1199
- code?: unknown;
1200
- message?: unknown;
1201
- error?: { type?: unknown; code?: unknown; message?: unknown };
1202
- last_error?: { type?: unknown; code?: unknown; message?: unknown };
1203
- response?: {
1204
- error?: { type?: unknown; code?: unknown; message?: unknown };
1205
- incomplete_details?: { code?: unknown; message?: unknown; reason?: unknown };
1206
- };
1207
- },
1208
- ): void {
1209
- if (logCtx.terminalHttpStatus !== undefined) return;
1210
- const type = json.type;
1211
- if (type !== "response.failed" && type !== "response.incomplete" && type !== "error") return;
1212
- const responseError = json.response?.error;
1213
- const responseDetails = json.response?.incomplete_details;
1214
- const candidates: Array<{ type?: unknown; code?: unknown; message?: unknown } | undefined> = [
1215
- json.error, json.last_error, responseError, responseDetails, json,
1216
- ];
1217
- const policy = candidates.some(candidate => (
1218
- candidate?.code === null || typeof candidate?.code === "string"
1219
- ) && isCyberPolicyCode(candidate.code as string | null | undefined))
1220
- || candidates.some(candidate => (
1221
- typeof candidate?.message === "string"
1222
- && candidate.message.trim().length > 0
1223
- && isCyberPolicyMessage(candidate.message)
1224
- ));
1225
- if (policy) {
1226
- logCtx.terminalErrorCode = CYBER_POLICY_ERROR_CODE;
1227
- logCtx.terminalHttpStatus = 400;
1228
- return;
1229
- }
1230
- // A quota terminal can carry only a structured reason, without an error message.
1231
- // Keep this separate from normal output limits and from the policy precedence above.
1232
- const quotaTag = (value: unknown): boolean => value === "usage_limit_reached"
1233
- || value === "rate_limit_exceeded" || value === "insufficient_quota";
1234
- const structuredRefusal = candidates.some(candidate => [400, 401, 403, 499].includes(
1235
- httpStatusFromTerminalError({
1236
- type: typeof candidate?.type === "string" ? candidate.type : undefined,
1237
- code: typeof candidate?.code === "string" ? candidate.code : undefined,
1238
- }),
1239
- ));
1240
- const ordinaryIncompleteReason = typeof responseDetails?.reason === "string"
1241
- && ["max_output_tokens", "content_filter", "steered", "upstream_stall_timeout", "adapter_eof"].includes(responseDetails.reason);
1242
- if (type === "response.incomplete" && !structuredRefusal && (quotaTag(responseDetails?.reason) || candidates.some(candidate =>
1243
- quotaTag(candidate?.code)
1244
- || quotaTag(candidate?.type) || candidate?.type === "rate_limit_error"
1245
- || (!ordinaryIncompleteReason && typeof candidate?.message === "string" && isRateLimitOrQuotaFailureMessage(candidate.message))
1246
- ))) {
1247
- // The shared quota classifier also accepts a numeric HTTP status as its message.
1248
- // Preserve explicit payment-required evidence rather than relabeling it as 429.
1249
- logCtx.terminalHttpStatus = candidates.some(candidate => typeof candidate?.message === "string"
1250
- && Number(candidate.message.trim()) === 402) ? 402 : 429;
1251
- return;
1252
- }
1253
- if (type !== "response.failed" || !responseError || typeof responseError !== "object") return;
1254
- const responseCode = responseError.code === null || typeof responseError.code === "string"
1255
- ? responseError.code
1256
- : undefined;
1257
- logCtx.terminalHttpStatus = httpStatusFromTerminalError({
1258
- type: typeof responseError.type === "string" ? responseError.type : undefined,
1259
- code: responseCode,
1260
- message: typeof responseError.message === "string" ? responseError.message : undefined,
1261
- });
1262
- }
1263
-
1264
1161
  /** Map a terminal Responses error object to the HTTP status we record in /api/logs. */
1265
1162
  export function httpStatusFromTerminalError(error: {
1266
1163
  type?: string;
@@ -1467,12 +1364,12 @@ export function addFinalRequestLog(
1467
1364
  const effectiveStatus = status >= 500 && logCtx.upstreamError && isClientClosedMessage(logCtx.upstreamError)
1468
1365
  ? 499
1469
1366
  : status;
1470
- // A locally assigned code wins: it names a refusal this proxy made itself, which no
1471
- // status-plus-upstream-message classification can reconstruct.
1367
+ // Locally assigned codes name proxy refusals that status and upstream text cannot reconstruct.
1472
1368
  const errorCode = logCtx.errorCode ?? requestLogErrorCode(
1473
1369
  effectiveStatus,
1474
1370
  logCtx.upstreamError,
1475
1371
  logCtx.terminalErrorCode,
1372
+ logCtx.causeHint === "transport-ambiguous" && logCtx.terminalSource === "synthetic",
1476
1373
  );
1477
1374
  // A response.failed whose classified status is 499 is still a client cancel, not an upstream
1478
1375
  // terminal failure — keep /api/logs closeReason aligned with that.
@@ -1502,6 +1399,7 @@ export function addFinalRequestLog(
1502
1399
  ...(logCtx.transportPhase ? { transportPhase: logCtx.transportPhase } : {}),
1503
1400
  ...(logCtx.terminalSource ? { terminalSource: logCtx.terminalSource } : {}),
1504
1401
  outputObserved: logCtx.firstOutputMs !== undefined,
1402
+ ...(logCtx.causeHint ? { causeHint: logCtx.causeHint } : {}),
1505
1403
  locallyAnswered: logCtx.localTerminalReason !== undefined,
1506
1404
  ...(logCtx.activeAttempt ? { attempt: logCtx.activeAttempt } : {}),
1507
1405
  });
@@ -1620,8 +1518,7 @@ export function addFinalRequestLog(
1620
1518
  ...(meta?.terminalStatus ? { terminalStatus: meta.terminalStatus } : {}),
1621
1519
  ...(closeReason ? { closeReason } : {}),
1622
1520
  ...(logCtx.upstreamError ? { upstreamError: logCtx.upstreamError } : {}),
1623
- ...(logCtx.upstreamErrorCode ? { upstreamErrorCode: logCtx.upstreamErrorCode } : {}),
1624
- ...(logCtx.upstreamRequestId ? { upstreamRequestId: logCtx.upstreamRequestId } : {}),
1521
+ ...upstreamDiagnosticLogFields(logCtx),
1625
1522
  usageStatus,
1626
1523
  ...(loggedUsage ? { usage: loggedUsage } : {}),
1627
1524
  ...(totalTokens !== undefined ? { totalTokens } : {}),
@@ -83,6 +83,7 @@ export function createAdapterContinuations(
83
83
  | "oauthDispatch"
84
84
  | "invalidateSameTargetRequest"
85
85
  | "resolveSelectionAdapter"
86
+ | "resolveCopilotSelection"
86
87
  | "anthropicInstance"
87
88
  | "currentAnthropicRouteDecision"
88
89
  | "anthropicRouteDecision"
@@ -156,7 +157,8 @@ export function createAdapterContinuations(
156
157
  /**
157
158
  * One bounded internal re-ask for Anthropic end_turn-without-tool-call turns. Replays the
158
159
  * continuation on a 429 with the same-key retry budget (hoisted per request), then falls
159
- * back to key/account failover; a failure becomes an in-stream adapter error so the client
160
+ * back to key/account failover, rebuilding Copilot model, wire, and credential negotiation.
161
+ * A failure becomes an in-stream adapter error so the client
160
162
  * never sees a second hidden HTTP response or an unbounded retry loop.
161
163
  */
162
164
  const fetchTerminalGuardContinuation = async function* (
@@ -377,6 +379,12 @@ export function createAdapterContinuations(
377
379
  if (rotated) {
378
380
  try { void response.body?.cancel().catch(() => {}); } catch { /* already closed */ }
379
381
  route.provider = rotated;
382
+ try { await transportState.resolveCopilotSelection(nextParsed); }
383
+ catch (error) {
384
+ yield { type: "error", message: `Provider continuation failed: ${redactSecretString(error instanceof Error ? error.message : String(error))}`,
385
+ ...(options.abortSignal?.aborted || upstream.signal.aborted ? { status: 499 } : {}) };
386
+ return;
387
+ }
380
388
  invalidateSameTargetRequest();
381
389
  transportState.activeAdapter = resolveSelectionAdapter(
382
390
  resolveWireProtocolOverride(route.providerName, route.modelId, route.provider, inboundWire, route.staticPolicy),