@bitkyc08/opencodex 2.55.0 → 2.56.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 (167) hide show
  1. package/gui/dist/assets/{index-VuoiWj9J.js → index-D4zuyIxQ.js} +1 -1
  2. package/gui/dist/index.html +1 -1
  3. package/package.json +2 -1
  4. package/src/adapters/base.ts +21 -0
  5. package/src/adapters/cursor/transport-retry.ts +46 -1
  6. package/src/adapters/cursor.ts +4 -0
  7. package/src/adapters/kiro/adapter.ts +42 -1
  8. package/src/adapters/kiro-retry.ts +23 -4
  9. package/src/adapters/openai-chat/errors.ts +116 -0
  10. package/src/adapters/openai-chat/messages.ts +346 -0
  11. package/src/adapters/openai-chat/passthrough.ts +146 -0
  12. package/src/adapters/openai-chat/response-events.ts +117 -0
  13. package/src/adapters/openai-chat/tool-call-validation.ts +200 -0
  14. package/src/adapters/openai-chat/tool-schema.ts +477 -0
  15. package/src/adapters/openai-chat/wire.ts +50 -0
  16. package/src/adapters/openai-chat.ts +33 -1445
  17. package/src/adapters/openai-responses/canonical-forward.ts +202 -0
  18. package/src/adapters/openai-responses/image-gen.ts +406 -0
  19. package/src/adapters/openai-responses/internal.ts +3 -0
  20. package/src/adapters/openai-responses/passthrough.ts +611 -0
  21. package/src/adapters/openai-responses/prompt-cache.ts +83 -0
  22. package/src/adapters/openai-responses/reasoning.ts +220 -0
  23. package/src/adapters/openai-responses/request-strips.ts +185 -0
  24. package/src/adapters/openai-responses/tool-output-recovery.ts +509 -0
  25. package/src/adapters/openai-responses/tool-schema.ts +293 -0
  26. package/src/adapters/openai-responses/web-search.ts +156 -0
  27. package/src/adapters/openai-responses.ts +4 -2625
  28. package/src/bridge/errors.ts +34 -0
  29. package/src/bridge/internal.ts +174 -0
  30. package/src/bridge/response-json.ts +624 -0
  31. package/src/bridge/sse.ts +1444 -0
  32. package/src/bridge.ts +5 -2204
  33. package/src/chat/inbound.ts +12 -1
  34. package/src/codex/account-lifecycle.ts +3 -0
  35. package/src/codex/account-store.ts +71 -9
  36. package/src/codex/auth-api/account-list.ts +507 -0
  37. package/src/codex/auth-api/http.ts +32 -0
  38. package/src/codex/auth-api/login-flow.ts +554 -0
  39. package/src/codex/auth-api/login-state.ts +64 -0
  40. package/src/codex/auth-api/main-account-probe.ts +331 -0
  41. package/src/codex/auth-api/pool-mode-gate.ts +274 -0
  42. package/src/codex/auth-api/pool-quota-probe.ts +512 -0
  43. package/src/codex/auth-api/reset-credit-service.ts +422 -0
  44. package/src/codex/auth-api/routes.ts +425 -0
  45. package/src/codex/auth-api/runtime-config.ts +48 -0
  46. package/src/codex/auth-api.ts +27 -3118
  47. package/src/codex/auth-context.ts +95 -28
  48. package/src/codex/catalog/auto-review.ts +507 -0
  49. package/src/codex/catalog/build-entries.ts +981 -0
  50. package/src/codex/catalog/combo-member.ts +375 -0
  51. package/src/codex/catalog/derive-entry.ts +229 -0
  52. package/src/codex/catalog/effort.ts +0 -1
  53. package/src/codex/catalog/gated-native-warn.ts +63 -0
  54. package/src/codex/catalog/gather-capture.ts +533 -0
  55. package/src/codex/catalog/model-hints.ts +691 -0
  56. package/src/codex/catalog/model-visibility.ts +304 -0
  57. package/src/codex/catalog/provider-fetch.ts +52 -2942
  58. package/src/codex/catalog/provider-models.ts +685 -0
  59. package/src/codex/catalog/restore.ts +132 -0
  60. package/src/codex/catalog/retained-sync.ts +706 -0
  61. package/src/codex/catalog/routed-gather.ts +858 -0
  62. package/src/codex/catalog/subagent-roster.ts +176 -0
  63. package/src/codex/catalog/sync.ts +52 -2698
  64. package/src/codex/inject/config-toml.ts +563 -0
  65. package/src/codex/inject/remove.ts +192 -0
  66. package/src/codex/inject/restore.ts +540 -0
  67. package/src/codex/inject/routing-classify.ts +109 -0
  68. package/src/codex/inject/routing-target.ts +125 -0
  69. package/src/codex/inject.ts +81 -1436
  70. package/src/codex/lineage.ts +458 -0
  71. package/src/codex/pool-refresh-backoff.ts +152 -0
  72. package/src/codex/routing/active-account.ts +194 -0
  73. package/src/codex/routing/cooldown-math.ts +275 -0
  74. package/src/codex/routing/health-store.ts +402 -0
  75. package/src/codex/routing/probe-lease.ts +358 -0
  76. package/src/codex/routing/selection.ts +703 -0
  77. package/src/codex/routing/thread-affinity.ts +538 -0
  78. package/src/codex/routing.ts +353 -2234
  79. package/src/codex/shim-fingerprint.ts +223 -0
  80. package/src/codex/shim-inspect.ts +175 -0
  81. package/src/codex/shim-probe.ts +367 -0
  82. package/src/codex/shim-restore-lock.ts +169 -0
  83. package/src/codex/shim-state-file.ts +151 -0
  84. package/src/codex/shim-templates.ts +265 -0
  85. package/src/codex/shim.ts +48 -1268
  86. package/src/config/diagnostics.ts +705 -0
  87. package/src/config/feature-flags.ts +55 -0
  88. package/src/config/live-reconcile.ts +403 -0
  89. package/src/config/load-degrade.ts +880 -0
  90. package/src/config/mutation-lock.ts +244 -0
  91. package/src/config/openai-tier-backup.ts +268 -0
  92. package/src/config/persist-unlocked.ts +92 -0
  93. package/src/config/proxy-env.ts +188 -0
  94. package/src/config/salvage.ts +244 -0
  95. package/src/config/schema/config-schema.ts +640 -0
  96. package/src/config/schema/leaf-validators.ts +855 -0
  97. package/src/config/warn-memo.ts +28 -0
  98. package/src/config.ts +234 -4481
  99. package/src/generated/compatibility-version.json +539 -39
  100. package/src/lib/request-execution-budget.ts +69 -20
  101. package/src/lib/spend-reservation-ledger.ts +940 -0
  102. package/src/lib/upstream-retry.ts +55 -11
  103. package/src/lib/workflow-budget.ts +553 -30
  104. package/src/providers/quota/account-cache.ts +441 -0
  105. package/src/providers/quota/antigravity.ts +295 -0
  106. package/src/providers/quota/report-cache.ts +320 -0
  107. package/src/providers/quota/vendor-probes-key.ts +1243 -0
  108. package/src/providers/quota/vendor-probes-oauth.ts +590 -0
  109. package/src/providers/quota.ts +324 -3079
  110. package/src/providers/registry/entries-core.ts +1221 -0
  111. package/src/providers/registry/entries-extended.ts +1204 -0
  112. package/src/providers/registry/model-seeds.ts +908 -0
  113. package/src/providers/registry/types.ts +352 -0
  114. package/src/providers/registry.ts +24 -3536
  115. package/src/responses/continuation-ownership.ts +29 -0
  116. package/src/responses/state/replay-fingerprint.ts +80 -0
  117. package/src/responses/state/snapshot-codec.ts +104 -0
  118. package/src/responses/state/spill-failure.ts +118 -0
  119. package/src/responses/state/spill-queue.ts +665 -0
  120. package/src/responses/state/temp-recovery.ts +257 -0
  121. package/src/responses/state.ts +82 -1143
  122. package/src/routing/identity-domains.ts +449 -0
  123. package/src/routing/probe-lease.ts +511 -0
  124. package/src/server/index/bounded-request.ts +88 -0
  125. package/src/server/index/live-sideband.ts +565 -0
  126. package/src/server/index/serve-options.ts +1766 -0
  127. package/src/server/index/startup-warnings.ts +213 -0
  128. package/src/server/index/websocket-handler.ts +335 -0
  129. package/src/server/index.ts +40 -2547
  130. package/src/server/management/route-registry.ts +26 -23
  131. package/src/server/management/shared.ts +8 -5
  132. package/src/server/management/workflow-budget-routes.ts +133 -0
  133. package/src/server/management-api.ts +12 -0
  134. package/src/server/request-log-conversation.ts +9 -7
  135. package/src/server/request-log.ts +245 -1
  136. package/src/server/responses/account-change-state.ts +233 -0
  137. package/src/server/responses/adapter-continuation.ts +514 -0
  138. package/src/server/responses/adapter-delivery.ts +214 -0
  139. package/src/server/responses/adapter-dispatch.ts +971 -0
  140. package/src/server/responses/compact.ts +59 -4
  141. package/src/server/responses/completion-policy.ts +33 -0
  142. package/src/server/responses/core-auth.ts +527 -0
  143. package/src/server/responses/core-codex-account.ts +859 -0
  144. package/src/server/responses/core-combo-failure.ts +210 -0
  145. package/src/server/responses/core-combo.ts +707 -0
  146. package/src/server/responses/core-errors.ts +152 -0
  147. package/src/server/responses/core-lifetime.ts +95 -0
  148. package/src/server/responses/core-normalize.ts +350 -0
  149. package/src/server/responses/core-opaque-recovery.ts +380 -0
  150. package/src/server/responses/core-options.ts +159 -0
  151. package/src/server/responses/core-replay.ts +225 -0
  152. package/src/server/responses/core.ts +192 -8893
  153. package/src/server/responses/passthrough-delivery.ts +856 -0
  154. package/src/server/responses/passthrough-dispatch.ts +1476 -0
  155. package/src/server/responses/passthrough-execution.ts +54 -0
  156. package/src/server/responses/request-prepare.ts +970 -0
  157. package/src/server/responses/request-send-budget.ts +164 -0
  158. package/src/server/responses/request-sidecar-auth.ts +149 -0
  159. package/src/server/responses/request-transport.ts +744 -0
  160. package/src/server/responses/response-effects.ts +157 -0
  161. package/src/server/responses/run-turn-execution.ts +448 -0
  162. package/src/server/responses/sidecar-execution.ts +469 -0
  163. package/src/server/responses-image-gen-repair.ts +1 -1
  164. package/src/server/workflow-refusal.ts +84 -0
  165. package/src/types/config.ts +30 -0
  166. package/src/usage/log.ts +146 -0
  167. package/src/usage/summary.ts +171 -21
@@ -0,0 +1,225 @@
1
+ import type {
2
+ OcxProviderContinuationOwner,
3
+ OcxProviderContinuationState,
4
+ OcxParsedRequest,
5
+ OcxProviderConfig,
6
+ OcxReasoningReplayIdentity,
7
+ AdapterEvent,
8
+ } from "../../types";
9
+ import {
10
+ isValidProviderContinuationOwner,
11
+ sameProviderContinuationOwner,
12
+ providerContinuationOwnerFromReplayIdentity,
13
+ providerContinuationRouteScope,
14
+ } from "../../responses/provider-continuation";
15
+ import {
16
+ reasoningReplayDestinationIdentity,
17
+ reasoningReplayOAuthCredentialIdentity,
18
+ durableReplayCredentialIdentity,
19
+ reasoningReplayCodexCredentialIdentity,
20
+ reasoningReplayKeyCredentialIdentity,
21
+ durableReplayDestinationIdentity,
22
+ bindReasoningReplayScope,
23
+ reasoningReplayServingIdentityChanged,
24
+ reasoningReplayOpaqueBlobRejectionMemoized,
25
+ } from "../../responses/reasoning-replay-cache";
26
+ import type { OAuthAccessSnapshot } from "../../oauth";
27
+ import type { CodexAuthContext } from "../../codex/auth-context";
28
+ import { thoughtSignatureReplaySalt } from "../../responses/thought-signature-replay";
29
+ import { randomUUID } from "node:crypto";
30
+
31
+ /**
32
+ * Adapters whose continuation state must survive Codex's store:false requests.
33
+ */
34
+ export function adapterNeedsForcedContinuation(name: string): boolean {
35
+ return name === "kiro" || name === "cursor";
36
+ }
37
+
38
+
39
+ export type ContinuationOwnerRead =
40
+ | { kind: "missing" }
41
+ | { kind: "invalid" }
42
+ | { kind: "valid"; owner: OcxProviderContinuationOwner };
43
+
44
+
45
+ export function readProviderContinuationOwner(
46
+ state: OcxProviderContinuationState | undefined,
47
+ ): ContinuationOwnerRead {
48
+ if (!state || state.__ocxOwner === undefined) return { kind: "missing" };
49
+ const owner = state.__ocxOwner;
50
+ if (!isValidProviderContinuationOwner(owner)) return { kind: "invalid" };
51
+ return { kind: "valid", owner: { ...owner } };
52
+ }
53
+
54
+
55
+ export function providerContinuationPayload(
56
+ state: OcxProviderContinuationState | undefined,
57
+ ): OcxProviderContinuationState | undefined {
58
+ if (!state) return undefined;
59
+ const cloned = structuredClone(state);
60
+ delete cloned.__ocxOwner;
61
+ return Object.keys(cloned).length > 0 ? cloned : undefined;
62
+ }
63
+
64
+
65
+ export function bindProviderContinuationForRoute(
66
+ parsed: OcxParsedRequest,
67
+ currentOwner: OcxProviderContinuationOwner | undefined,
68
+ ): void {
69
+ const candidate = parsed._providerContinuationCandidate;
70
+ const storedOwner = readProviderContinuationOwner(candidate);
71
+ const mayRestore = storedOwner.kind === "valid"
72
+ && !!currentOwner
73
+ && sameProviderContinuationOwner(storedOwner.owner, currentOwner);
74
+ const restored = mayRestore ? providerContinuationPayload(candidate) : undefined;
75
+ if (restored) parsed._providerContinuation = restored;
76
+ else delete parsed._providerContinuation;
77
+ const cursorConversationId = restored?.cursor?.conversationId;
78
+ if (cursorConversationId) parsed._cursorConversationId = cursorConversationId;
79
+ else delete parsed._cursorConversationId;
80
+ if (currentOwner) parsed._providerContinuationOwner = { ...currentOwner };
81
+ else delete parsed._providerContinuationOwner;
82
+ }
83
+
84
+
85
+ export function providerContinuationDestinationIdentity(
86
+ parsed: OcxParsedRequest,
87
+ provider: OcxProviderConfig,
88
+ ): string | undefined {
89
+ const kiroContext = parsed._kiroAuthContext;
90
+ return reasoningReplayDestinationIdentity(JSON.stringify([
91
+ provider.baseUrl.trim().replace(/\/+$/, ""),
92
+ provider.responsesPath ?? "",
93
+ kiroContext?.profileArn ?? "",
94
+ kiroContext?.apiRegion ?? "",
95
+ kiroContext?.ssoRegion ?? "",
96
+ ]));
97
+ }
98
+
99
+
100
+ export function bindRouteReasoningReplayScope(args: {
101
+ parsed: OcxParsedRequest;
102
+ providerName: string;
103
+ provider: OcxProviderConfig;
104
+ adapterName: string;
105
+ oauthCredentialSnapshot?: Pick<OAuthAccessSnapshot, "accountId" | "generation">;
106
+ codexAuthContext?: CodexAuthContext;
107
+ forwardHeaders?: Headers;
108
+ }): void {
109
+ const { parsed, providerName, provider, adapterName } = args;
110
+ let credentialIdentity: string | undefined;
111
+ let credentialDurableIdentity: string | undefined;
112
+ const durableSalt = thoughtSignatureReplaySalt();
113
+ if (provider.authMode === "oauth") {
114
+ credentialIdentity = reasoningReplayOAuthCredentialIdentity(
115
+ args.oauthCredentialSnapshot,
116
+ provider.headers,
117
+ );
118
+ // The persisted account-slot id survives token refresh and restarts; the rotating
119
+ // generation deliberately does NOT participate (#1926 design: rotation-safe).
120
+ credentialDurableIdentity = durableReplayCredentialIdentity(
121
+ "oauth",
122
+ args.oauthCredentialSnapshot?.accountId,
123
+ provider.headers,
124
+ durableSalt,
125
+ );
126
+ } else if (provider.authMode === "forward") {
127
+ const poolContext = args.codexAuthContext?.kind === "pool"
128
+ || args.codexAuthContext?.kind === "main-pool"
129
+ ? args.codexAuthContext
130
+ : undefined;
131
+ credentialIdentity = reasoningReplayCodexCredentialIdentity({
132
+ authorization: poolContext
133
+ ? `Bearer ${poolContext.accessToken}`
134
+ : args.forwardHeaders?.get("authorization"),
135
+ chatgptAccountId: poolContext?.chatgptAccountId
136
+ ?? args.forwardHeaders?.get("chatgpt-account-id"),
137
+ accountId: poolContext?.accountId,
138
+ credentialGeneration: poolContext?.kind === "pool"
139
+ ? poolContext.generation
140
+ : undefined,
141
+ writerGeneration: poolContext?.writerGeneration,
142
+ headers: provider.headers,
143
+ });
144
+ // Durable identity requires a STABLE, TRUSTED account handle. Pool context comes from
145
+ // our own account store; a client-supplied chatgpt-account-id header is attacker
146
+ // -influenceable bucket selection and a bearer alone is rotating material — both are
147
+ // refused, so direct-forward turns get no durable scope (fail closed; the in-process
148
+ // cache still covers same-process replay).
149
+ const codexDurableHandle = poolContext?.accountId
150
+ ?? poolContext?.chatgptAccountId
151
+ ?? undefined;
152
+ credentialDurableIdentity = durableReplayCredentialIdentity(
153
+ "codex",
154
+ codexDurableHandle ?? undefined,
155
+ provider.headers,
156
+ durableSalt,
157
+ );
158
+ } else if (provider.authMode !== "local") {
159
+ credentialIdentity = reasoningReplayKeyCredentialIdentity(provider);
160
+ credentialDurableIdentity = durableReplayCredentialIdentity(
161
+ "key",
162
+ nonEmptyProviderApiKey(provider),
163
+ provider.headers,
164
+ durableSalt,
165
+ );
166
+ }
167
+ const providerDestinationIdentity = reasoningReplayDestinationIdentity(provider.baseUrl);
168
+ const replayIdentity: OcxReasoningReplayIdentity | undefined = credentialIdentity && providerDestinationIdentity
169
+ ? {
170
+ providerName,
171
+ providerDestinationIdentity,
172
+ providerDestinationDurableIdentity: durableReplayDestinationIdentity(provider.baseUrl),
173
+ adapterName,
174
+ modelId: parsed.modelId,
175
+ credentialIdentity,
176
+ ...(credentialDurableIdentity ? { credentialDurableIdentity } : {}),
177
+ }
178
+ : undefined;
179
+ const continuationDestinationIdentity = providerContinuationDestinationIdentity(parsed, provider);
180
+ const continuationOwner = providerContinuationOwnerFromReplayIdentity(
181
+ replayIdentity && continuationDestinationIdentity
182
+ ? { ...replayIdentity, providerDestinationIdentity: continuationDestinationIdentity }
183
+ : undefined,
184
+ );
185
+ if (adapterName === "cursor") {
186
+ // The final route owner is authoritative for Cursor and supersedes the account-derived
187
+ // seed assigned before route binding. A Cursor conversation must be scoped to the exact
188
+ // provider/destination/adapter/model/credential that serves it.
189
+ if (continuationOwner) parsed._cursorIdentityScope = providerContinuationRouteScope(continuationOwner);
190
+ else if (!parsed._cursorIdentityScope?.startsWith("cursor-unowned:")) {
191
+ // Prevent the adapter's token-only fallback from recreating a provider-private id after the
192
+ // route owner failed closed. The sentinel is per parsed request and contains no credential.
193
+ parsed._cursorIdentityScope = `cursor-unowned:${randomUUID()}`;
194
+ }
195
+ }
196
+ bindReasoningReplayScope(
197
+ parsed._reasoningReplayScope,
198
+ replayIdentity,
199
+ );
200
+ // Keep this sticky for the whole outbound request: a later auth/key rebind may compare equal
201
+ // after the first mismatch, but it cannot make history minted by the prior route decodable.
202
+ if (reasoningReplayServingIdentityChanged(parsed._reasoningReplayScope)) {
203
+ parsed._stripReasoningEncryptedContent = true;
204
+ }
205
+ if (reasoningReplayOpaqueBlobRejectionMemoized(parsed._reasoningReplayScope)) {
206
+ parsed._stripReasoningEncryptedContent = true;
207
+ }
208
+ bindProviderContinuationForRoute(parsed, continuationOwner);
209
+ }
210
+
211
+
212
+ export function adapterResponseReachedServingTerminal(
213
+ events: readonly AdapterEvent[],
214
+ response: Readonly<Record<string, unknown>>,
215
+ ): boolean {
216
+ return (response.status === "completed" || response.status === "incomplete")
217
+ && events.some(event => event.type === "done" || event.type === "incomplete");
218
+ }
219
+
220
+
221
+ export function nonEmptyProviderApiKey(provider: OcxProviderConfig): string | undefined {
222
+ return typeof provider.apiKey === "string" && provider.apiKey.trim().length > 0
223
+ ? provider.apiKey
224
+ : undefined;
225
+ }