@bitkyc08/opencodex 2.35.0 → 2.36.0-preview.20260830

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 (155) hide show
  1. package/gui/dist/assets/index-Cy7Z_pl0.css +1 -0
  2. package/gui/dist/assets/index-DPl4nBMA.js +112 -0
  3. package/gui/dist/index.html +2 -2
  4. package/package.json +2 -1
  5. package/src/AGENTS.md +2 -1
  6. package/src/adapters/agentrouter.ts +50 -0
  7. package/src/adapters/anthropic.ts +1 -51
  8. package/src/adapters/cursor/call-id.ts +76 -8
  9. package/src/adapters/cursor/checkpoint-store.ts +6 -1
  10. package/src/adapters/cursor/cursor-errors.ts +44 -0
  11. package/src/adapters/cursor/native-exec.ts +13 -0
  12. package/src/adapters/cursor/protobuf-request.ts +651 -29
  13. package/src/adapters/cursor/tool-result-normalize.ts +3 -3
  14. package/src/adapters/cursor/transport-retry.ts +5 -1
  15. package/src/adapters/cursor.ts +15 -1
  16. package/src/adapters/empty-tool-output-annotation.ts +43 -0
  17. package/src/adapters/exec-tool-result-normalize.ts +70 -5
  18. package/src/adapters/google.ts +22 -2
  19. package/src/adapters/kiro.ts +26 -2
  20. package/src/adapters/ollama-native-url.ts +111 -0
  21. package/src/adapters/ollama-native.ts +1131 -0
  22. package/src/adapters/openai-chat.ts +30 -7
  23. package/src/adapters/openai-responses.ts +72 -4
  24. package/src/adapters/registry.ts +7 -0
  25. package/src/adapters/xai-web-search.ts +58 -0
  26. package/src/claude/desktop-3p.ts +21 -1
  27. package/src/claude/desktop-policy.ts +149 -0
  28. package/src/cli/account.ts +16 -2
  29. package/src/cli/claude-desktop.ts +13 -3
  30. package/src/cli/combo.ts +8 -5
  31. package/src/cli/doctor.ts +77 -11
  32. package/src/cli/help.ts +1 -1
  33. package/src/cli/index.ts +16 -0
  34. package/src/cli/models.ts +20 -3
  35. package/src/cli/registry.ts +2 -1
  36. package/src/cli/status.ts +140 -2
  37. package/src/cli/storage.ts +10 -1
  38. package/src/codex/account-runtime-state.ts +39 -5
  39. package/src/codex/account-store.ts +393 -13
  40. package/src/codex/account-usability.ts +11 -4
  41. package/src/codex/app-server-processes.ts +46 -5
  42. package/src/codex/auth-context.ts +160 -32
  43. package/src/codex/catalog/bundled.ts +7 -5
  44. package/src/codex/catalog/metadata.ts +1 -1
  45. package/src/codex/catalog/parsing.ts +57 -1
  46. package/src/codex/catalog/provider-fetch.ts +61 -4
  47. package/src/codex/catalog/sync.ts +4 -3
  48. package/src/codex/convergence.ts +3 -2
  49. package/src/codex/data/upstream-models.json +40 -8
  50. package/src/codex/inject-coordination.ts +111 -14
  51. package/src/codex/integration-record.ts +12 -2
  52. package/src/codex/main-account.ts +225 -1
  53. package/src/codex/model-entitlements.ts +339 -27
  54. package/src/codex/prompt-layers.ts +346 -7
  55. package/src/codex/prompt-text-probe.ts +272 -21
  56. package/src/codex/routing.ts +693 -132
  57. package/src/codex/runtime.ts +12 -0
  58. package/src/codex/subagent-model-fallback.ts +62 -24
  59. package/src/codex/user-identity.ts +33 -25
  60. package/src/combos/index.ts +1 -0
  61. package/src/combos/reset-window.ts +46 -0
  62. package/src/combos/resolve.ts +84 -2
  63. package/src/combos/types.ts +5 -2
  64. package/src/config/atomic-write.ts +104 -22
  65. package/src/config/provider-validation.ts +11 -0
  66. package/src/config.ts +75 -3
  67. package/src/generated/compatibility-version.json +207 -131
  68. package/src/generated/model-metadata.ts +1 -1
  69. package/src/grok/catalog.ts +71 -0
  70. package/src/grok/effort.ts +83 -0
  71. package/src/grok/inject.ts +952 -127
  72. package/src/grok/models.ts +56 -0
  73. package/src/grok/status.ts +21 -8
  74. package/src/grok/sync.ts +10 -18
  75. package/src/images/loop.ts +6 -3
  76. package/src/integrations/native/ownership-preflight.ts +4 -1
  77. package/src/lab/fabric/producer-isolate.ts +36 -3
  78. package/src/lib/destination-policy.ts +93 -7
  79. package/src/lib/redact.ts +6 -1
  80. package/src/lib/shadow-call.ts +38 -3
  81. package/src/lib/test-home-guard.ts +18 -3
  82. package/src/lib/upstream-retry.ts +43 -6
  83. package/src/lib/windows-secret-acl.ts +66 -0
  84. package/src/lib/windows-text.ts +28 -2
  85. package/src/lib/windows-user-principal.ts +35 -23
  86. package/src/oauth/account-quota-rank.ts +107 -0
  87. package/src/oauth/anthropic-routing.ts +125 -30
  88. package/src/oauth/chatgpt.ts +5 -1
  89. package/src/oauth/generic-account-failover.ts +114 -7
  90. package/src/oauth/index.ts +15 -8
  91. package/src/oauth/store.ts +16 -0
  92. package/src/providers/account-quota-disk.ts +79 -0
  93. package/src/providers/command-code-efforts.ts +24 -0
  94. package/src/providers/derive.ts +6 -0
  95. package/src/providers/key-failover.ts +33 -1
  96. package/src/providers/kiro-usage.ts +272 -0
  97. package/src/providers/ollama-show.ts +311 -0
  98. package/src/providers/openai-sidecar.ts +5 -0
  99. package/src/providers/quota-routing-cache.ts +32 -0
  100. package/src/providers/quota-types.ts +36 -0
  101. package/src/providers/quota-wire.ts +102 -0
  102. package/src/providers/quota.ts +208 -147
  103. package/src/providers/registry.ts +68 -8
  104. package/src/providers/slug-codec.ts +12 -4
  105. package/src/providers/vercel-gateway-routing.ts +108 -0
  106. package/src/router.ts +22 -12
  107. package/src/server/auth-cors.ts +26 -0
  108. package/src/server/catalog-download.ts +73 -0
  109. package/src/server/chat-native.ts +12 -2
  110. package/src/server/gui-static.ts +4 -1
  111. package/src/server/index.ts +132 -9
  112. package/src/server/management/agent-settings-routes.ts +38 -5
  113. package/src/server/management/codex-prompt-routes.ts +7 -1
  114. package/src/server/management/combo-routes.ts +10 -1
  115. package/src/server/management/config-routes.ts +9 -1
  116. package/src/server/management/context.ts +5 -0
  117. package/src/server/management/model-routes.ts +16 -6
  118. package/src/server/management/native-integration-routes.ts +12 -17
  119. package/src/server/management/oauth-account-routes.ts +13 -0
  120. package/src/server/management/provider-routes.ts +32 -5
  121. package/src/server/management/routing-profile-routes.ts +15 -0
  122. package/src/server/management/shadow-call-validation.ts +29 -0
  123. package/src/server/management-api.ts +7 -3
  124. package/src/server/request-log.ts +3 -5
  125. package/src/server/responses/agent-task-recovery-cache.ts +8 -0
  126. package/src/server/responses/agent-task-recovery.ts +52 -20
  127. package/src/server/responses/codex-auth-error.ts +26 -0
  128. package/src/server/responses/compact.ts +345 -10
  129. package/src/server/responses/core.ts +736 -108
  130. package/src/server/responses/empty-completion-guard.ts +16 -0
  131. package/src/server/responses/fetch-helpers.ts +42 -0
  132. package/src/server/responses/policy-fallback.ts +11 -6
  133. package/src/server/responses-undeclared-tool-guard.ts +16 -3
  134. package/src/server/startup-health-cache.ts +59 -13
  135. package/src/service-manager-probe.ts +115 -9
  136. package/src/service.ts +139 -40
  137. package/src/storage/cleanup.ts +10 -0
  138. package/src/storage/storage-mutation-coordinator.ts +14 -3
  139. package/src/tray/windows-tray.ps1 +10 -4
  140. package/src/tray/windows.ts +30 -2
  141. package/src/types/config.ts +27 -14
  142. package/src/types/provider.ts +54 -0
  143. package/src/types/tools.ts +13 -3
  144. package/src/types.ts +4 -0
  145. package/src/usage/summary.ts +421 -177
  146. package/src/vision/anthropic-describe.ts +3 -3
  147. package/src/vision/describe.ts +5 -3
  148. package/src/web-search/anthropic-executor.ts +9 -2
  149. package/src/web-search/exa-executor.ts +3 -3
  150. package/src/web-search/executor.ts +8 -3
  151. package/src/web-search/gemini-executor.ts +3 -3
  152. package/src/web-search/loop.ts +11 -3
  153. package/src/web-search/xai-executor.ts +3 -3
  154. package/gui/dist/assets/index-DNdRKXK9.js +0 -112
  155. package/gui/dist/assets/index-DQ-Ie18T.css +0 -1
@@ -2,7 +2,7 @@ import type { OcxProviderConfig } from "../types";
2
2
  import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
3
3
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
4
4
  import { sidecarEnter } from "../lib/sidecar-tracker";
5
- import { fetchWithResetRetry } from "../lib/upstream-retry";
5
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
6
6
  import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
7
7
  import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/anthropic";
8
8
  import type { DescribeOutcome, VisionSettings } from "./describe";
@@ -155,12 +155,12 @@ export async function describeImageAnthropic(
155
155
  const startedAt = Date.now();
156
156
  try {
157
157
  const res = await fetchWithResetRetry(
158
- () => fetch(`${base}/v1/messages`, {
158
+ recovery => fetch(`${base}/v1/messages`, applyUpstreamRecoveryInit({
159
159
  method: "POST",
160
160
  headers,
161
161
  body: JSON.stringify(body),
162
162
  signal: linkedSignal.signal,
163
- }),
163
+ }, recovery)),
164
164
  { abortSignal: linkedSignal.signal, label: "vision-sidecar-anthropic" },
165
165
  );
166
166
  if (!res.ok) {
@@ -4,7 +4,7 @@ import { FORWARD_HEADERS } from "../adapters/openai-responses";
4
4
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
5
5
  import { redactSecretString } from "../lib/redact";
6
6
  import { sidecarEnter } from "../lib/sidecar-tracker";
7
- import { fetchWithResetRetry } from "../lib/upstream-retry";
7
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
8
8
  import { parseSidecarSSE } from "../web-search/parse";
9
9
  import type { SidecarOutcomeRecorder } from "../web-search/executor";
10
10
 
@@ -90,7 +90,9 @@ export async function describeImage(
90
90
  const t0 = Date.now();
91
91
  try {
92
92
  const res = await fetchWithResetRetry(
93
- () => fetch(`${forwardProvider.baseUrl}/responses`, {
93
+ // The replay needs `keepalive: false` to abandon the half-closed pooled socket; Bun has
94
+ // ignored a bare `Connection: close` (oven-sh/bun#20492).
95
+ recovery => fetch(`${forwardProvider.baseUrl}/responses`, applyUpstreamRecoveryInit({
94
96
  method: "POST",
95
97
  headers,
96
98
  body: JSON.stringify(body),
@@ -99,7 +101,7 @@ export async function describeImage(
99
101
  // across origins but forwards nonstandard headers such as `chatgpt-account-id`,
100
102
  // `session_id`, and `x-codex-turn-metadata` to the redirect target.
101
103
  redirect: "manual",
102
- }),
104
+ }, recovery)),
103
105
  { abortSignal: linkedSignal.signal, label: "vision-sidecar" },
104
106
  );
105
107
  const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
@@ -4,7 +4,7 @@ import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/a
4
4
  import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
5
5
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
6
6
  import { sidecarEnter } from "../lib/sidecar-tracker";
7
- import { fetchWithResetRetry } from "../lib/upstream-retry";
7
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
8
8
  import type { WebSearchSource } from "./parse";
9
9
  import { BASE_INSTRUCTION, IMAGE_INSTRUCTION, type SidecarOutcome, type SidecarSettings } from "./executor";
10
10
 
@@ -162,7 +162,14 @@ export async function runAnthropicWebSearch(
162
162
  const t0 = Date.now();
163
163
  try {
164
164
  const res = await fetchWithResetRetry(
165
- () => fetch(url, { method: "POST", headers, body: JSON.stringify(body), signal: linkedSignal.signal }),
165
+ // The replay needs `keepalive: false` to leave the half-closed pooled socket; Bun has
166
+ // ignored a bare `Connection: close` (oven-sh/bun#20492).
167
+ recovery => fetch(url, applyUpstreamRecoveryInit({
168
+ method: "POST",
169
+ headers,
170
+ body: JSON.stringify(body),
171
+ signal: linkedSignal.signal,
172
+ }, recovery)),
166
173
  { abortSignal: linkedSignal.signal, label: "web-search-sidecar-anthropic" },
167
174
  );
168
175
  // Guard before any branch reads the body: the failure branch's `res.text()` ran ahead of
@@ -8,7 +8,7 @@
8
8
  * redirect: "manual" because Bun forwards custom headers across redirects.
9
9
  * Never throws; every error string passes redactSecretString.
10
10
  */
11
- import { fetchWithResetRetry } from "../lib/upstream-retry";
11
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
12
12
  import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
13
13
  import { readBoundedResponseBytes } from "../lib/bounded-body";
14
14
  import { sidecarEnter } from "../lib/sidecar-tracker";
@@ -39,13 +39,13 @@ export async function runExaWebSearch(
39
39
  const t0 = Date.now();
40
40
  try {
41
41
  const res = await fetchWithResetRetry(
42
- () => fetch(EXA_SEARCH_URL, {
42
+ recovery => fetch(EXA_SEARCH_URL, applyUpstreamRecoveryInit({
43
43
  method: "POST",
44
44
  headers: { "Content-Type": "application/json", "x-api-key": apiKey },
45
45
  body: JSON.stringify({ query, numResults: EXA_NUM_RESULTS, contents: { text: { maxCharacters: EXA_SNIPPET_CHARS } } }),
46
46
  signal: linkedSignal.signal,
47
47
  redirect: "manual",
48
- }),
48
+ }, recovery)),
49
49
  { abortSignal: linkedSignal.signal, label: "exa-web-search-sidecar" },
50
50
  );
51
51
  const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
@@ -3,7 +3,8 @@ import { FORWARD_HEADERS } from "../adapters/openai-responses";
3
3
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
4
4
  import { redactSecretString } from "../lib/redact";
5
5
  import { sidecarEnter } from "../lib/sidecar-tracker";
6
- import { fetchWithResetRetry } from "../lib/upstream-retry";
6
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
7
+ import { withUpstreamHttpVersion } from "../lib/upstream-http-version";
7
8
  import { parseSidecarSSE, type WebSearchResult } from "./parse";
8
9
  import type { CodexUpstreamOutcome } from "../codex/routing";
9
10
 
@@ -73,7 +74,11 @@ export async function runWebSearch(
73
74
  const t0 = Date.now();
74
75
  try {
75
76
  const res = await fetchWithResetRetry(
76
- () => fetch(url, {
77
+ // Recovery nests INSIDE the version helper: applyUpstreamRecoveryInit then always receives a
78
+ // defined init, and withUpstreamHttpVersion spreads the result, so `protocol` and the
79
+ // recovery fields (`connection: close` + Bun's transport-level `keepalive: false`) survive
80
+ // together. The reverse order needs a `?? init` fallback to type-check at all.
81
+ recovery => fetch(url, withUpstreamHttpVersion(url, applyUpstreamRecoveryInit({
77
82
  method: "POST",
78
83
  headers,
79
84
  body: JSON.stringify(body),
@@ -82,7 +87,7 @@ export async function runWebSearch(
82
87
  // across origins but forwards nonstandard headers such as `chatgpt-account-id`,
83
88
  // `session_id`, and `x-codex-turn-metadata` to the redirect target.
84
89
  redirect: "manual",
85
- }),
90
+ }, recovery), forwardProvider)),
86
91
  { abortSignal: linkedSignal.signal, label: "web-search-sidecar" },
87
92
  );
88
93
  // Attach the body guard before ANY branch reads it. The success path guarded itself below,
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import type { OcxProviderConfig } from "../types";
12
12
  import { getValidAccessTokenSnapshot, publicOAuthAuthenticationErrorMessage } from "../oauth";
13
- import { fetchWithResetRetry } from "../lib/upstream-retry";
13
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
14
14
  import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
15
15
  import { readBoundedResponseBytes } from "../lib/bounded-body";
16
16
  import { sidecarEnter } from "../lib/sidecar-tracker";
@@ -69,7 +69,7 @@ export async function runGeminiWebSearch(
69
69
  const t0 = Date.now();
70
70
  try {
71
71
  const res = await fetchWithResetRetry(
72
- () => fetch(`${base}/v1internal:generateContent`, {
72
+ recovery => fetch(`${base}/v1internal:generateContent`, applyUpstreamRecoveryInit({
73
73
  method: "POST",
74
74
  headers: {
75
75
  "Content-Type": "application/json",
@@ -79,7 +79,7 @@ export async function runGeminiWebSearch(
79
79
  body: JSON.stringify(envelope),
80
80
  signal: linkedSignal.signal,
81
81
  redirect: "manual",
82
- }),
82
+ }, recovery)),
83
83
  { abortSignal: linkedSignal.signal, label: "gemini-web-search-sidecar" },
84
84
  );
85
85
  const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
@@ -13,7 +13,7 @@ import type { WebSearchBackendId } from "./index";
13
13
  import { clearableDeadline } from "../lib/abort";
14
14
  import { redactSecretString } from "../lib/redact";
15
15
  import { readBoundedResponseBody } from "../lib/bounded-body";
16
- import { fetchWithResetRetry, prepareSameTarget429Wait } from "../lib/upstream-retry";
16
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry, prepareSameTarget429Wait } from "../lib/upstream-retry";
17
17
  import { rateLimitRetryDelayMs } from "../providers/key-failover";
18
18
  import {
19
19
  isTranslatorBudgetExceededError,
@@ -323,6 +323,7 @@ export interface WebSearchLoopDeps {
323
323
  */
324
324
  export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Response> {
325
325
  const translatorBudget = deps.incomingMeta.translatorBudget;
326
+ const routedProviderFetch = deps.incomingMeta.providerFetch ?? globalThis.fetch;
326
327
  const { parsed, selectedForwardHeaders, forwardProvider, hostedTool, settings, maxSearches, abortSignal, recordSidecarOutcome } = deps;
327
328
  const backend = deps.backend ?? "openai";
328
329
  const anthropicSidecar = deps.anthropicSidecar;
@@ -426,6 +427,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
426
427
  request = cachedRequest;
427
428
  } else {
428
429
  request = await requestAdapter.buildRequest(iterParsed, {
430
+ ...deps.incomingMeta,
429
431
  headers: selectedForwardHeaders,
430
432
  abortSignal: headerDeadline.signal,
431
433
  translatorBudget,
@@ -447,6 +449,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
447
449
  timeoutMs: connectTimeoutMs,
448
450
  returnRawErrors: true,
449
451
  stream: true,
452
+ executor: routedProviderFetch,
450
453
  });
451
454
  } else {
452
455
  response = await fetchWithResetRetry(
@@ -457,12 +460,17 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
457
460
  deps.onAttemptSend?.(retryRecovery ?? recovery);
458
461
  const h = new Headers(request.headers);
459
462
  if (!h.has("accept-encoding")) h.set("accept-encoding", "identity");
460
- return fetch(request.url, {
463
+ // A connection-reset replay must leave the half-closed pooled socket, not just
464
+ // ask politely: Bun has ignored a bare `Connection: close` (oven-sh/bun#20492),
465
+ // so the transport-level `keepalive: false` this helper adds is what actually
466
+ // opens a new connection. Spending `retryRecovery` on telemetry alone left every
467
+ // replay on this leg eligible for the same dead socket the reset came from.
468
+ return routedProviderFetch(request.url, applyUpstreamRecoveryInit({
461
469
  method: request.method,
462
470
  headers: h,
463
471
  body: request.body,
464
472
  signal: headerDeadline.signal,
465
- });
473
+ }, retryRecovery));
466
474
  },
467
475
  { abortSignal: headerDeadline.signal, label: "web-search-loop" },
468
476
  );
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import type { OcxProviderConfig } from "../types";
14
14
  import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
15
- import { fetchWithResetRetry } from "../lib/upstream-retry";
15
+ import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
16
16
  import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
17
17
  import { sidecarEnter } from "../lib/sidecar-tracker";
18
18
  import { redactSecretString } from "../lib/redact";
@@ -102,14 +102,14 @@ export async function runXaiWebSearch(
102
102
  const t0 = Date.now();
103
103
  try {
104
104
  const res = await fetchWithResetRetry(
105
- () => fetch(url, {
105
+ recovery => fetch(url, applyUpstreamRecoveryInit({
106
106
  method: "POST",
107
107
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
108
108
  body: JSON.stringify(body),
109
109
  signal: linkedSignal.signal,
110
110
  // Credential-bearing: never follow a redirect off the pinned origin.
111
111
  redirect: "manual",
112
- }),
112
+ }, recovery)),
113
113
  { abortSignal: linkedSignal.signal, label: "xai-web-search-sidecar" },
114
114
  );
115
115
  const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);