@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,34 @@
1
+ import {
2
+ adapterFailureFromMessage,
3
+ classifyError,
4
+ cyberPolicyErrorType,
5
+ CYBER_POLICY_ERROR_CODE,
6
+ isCyberPolicyCode,
7
+ type OcxErrorPayload,
8
+ } from "../lib/errors";
9
+
10
+ export function formatErrorResponse(
11
+ status: number,
12
+ type: string,
13
+ message: string,
14
+ options?: { code?: string | null; retryAfter?: string | null },
15
+ ): Response {
16
+ const error = classifyError(status, type, message);
17
+ if (isCyberPolicyCode(options?.code)) {
18
+ error.code = CYBER_POLICY_ERROR_CODE;
19
+ error.type = cyberPolicyErrorType(type);
20
+ }
21
+ const finalStatus = error.code === CYBER_POLICY_ERROR_CODE ? 400 : status;
22
+ const headers = new Headers({ "Content-Type": "application/json" });
23
+ const retryAfter = options?.retryAfter?.trim();
24
+ if (error.code !== CYBER_POLICY_ERROR_CODE
25
+ && retryAfter
26
+ && retryAfter.length > 0
27
+ && retryAfter.length <= 128) {
28
+ headers.set("Retry-After", retryAfter);
29
+ }
30
+ return new Response(JSON.stringify({ error }), {
31
+ status: finalStatus,
32
+ headers,
33
+ });
34
+ }
@@ -0,0 +1,174 @@
1
+ import type {
2
+ AdapterEvent,
3
+ OcxMessagePhase,
4
+ OcxProviderContinuationState,
5
+ OcxProviderOpaqueToolCallMetadata,
6
+ OcxReasoningReplayScopeRef,
7
+ OcxUsage,
8
+ } from "../types";
9
+ import {
10
+ adapterFailureFromMessage,
11
+ classifyError,
12
+ cyberPolicyErrorType,
13
+ CYBER_POLICY_ERROR_CODE,
14
+ isCyberPolicyCode,
15
+ type OcxErrorPayload,
16
+ } from "../lib/errors";
17
+ import { redactSecretString } from "../lib/redact";
18
+ import { usageDisplayTotalTokens } from "../usage/totals";
19
+
20
+ export function uuid(): string {
21
+ return crypto.randomUUID().replace(/-/g, "");
22
+ }
23
+
24
+ /** Test-only: bound the abandoned-owned-budget watchdog delay (null restores). */
25
+ export let ownedBudgetAbandonedMs = 10 * 60 * 1000;
26
+ const OWNED_BUDGET_ABANDONED_DEFAULT_MS = ownedBudgetAbandonedMs;
27
+ export function setOwnedBudgetAbandonedMsForTests(ms: number | null): void {
28
+ ownedBudgetAbandonedMs = ms ?? OWNED_BUDGET_ABANDONED_DEFAULT_MS;
29
+ }
30
+
31
+ function isRecord(value: unknown): value is Record<string, unknown> {
32
+ return value !== null && typeof value === "object" && !Array.isArray(value);
33
+ }
34
+
35
+ export function responsesUsage(usage: OcxUsage | undefined): Record<string, unknown> {
36
+ // input_tokens_details / output_tokens_details are ALWAYS emitted (zero defaults):
37
+ // strict Responses clients deserialize them as required fields — grok-build's pinned
38
+ // async-openai fork (rev 95b52ebd, response_usage.rs) has non-Option InputTokenDetails/
39
+ // OutputTokenDetails, so omitting them turns a successful turn into a hard exit after
40
+ // response.completed ("missing field `input_tokens_details`", verified live 2026-07-23).
41
+ if (!usage) {
42
+ return {
43
+ input_tokens: 0,
44
+ output_tokens: 0,
45
+ total_tokens: 0,
46
+ input_tokens_details: { cached_tokens: 0 },
47
+ output_tokens_details: { reasoning_tokens: 0 },
48
+ };
49
+ }
50
+ // inputTokens is already inclusive of cache read/write (types.ts convention). Stateful
51
+ // providers may report an absolute active-context checkpoint separately from their
52
+ // per-attempt usage. Split that checkpoint into input + output without adding output twice.
53
+ const inputTokens = usage.contextTotalTokens !== undefined
54
+ ? Math.max(0, usage.contextTotalTokens - usage.outputTokens)
55
+ : usage.inputTokens;
56
+ // openai/codex#41980 parity: unknown upstream usage fields (subscription metadata, future
57
+ // counters) pass through the rebuild. Normalized values stay authoritative for the known
58
+ // keys (they are derived from the same raw values, so this never disagrees with upstream).
59
+ const raw: Record<string, unknown> = usage.rawUsage ?? {};
60
+ // cache_write_tokens is a KNOWN key: it is emitted only from the validated normalized
61
+ // value below, never copied through raw (an unknown-shaped value must not leak into the
62
+ // normalized contract).
63
+ const rawInputDetails = isRecord(raw.input_tokens_details)
64
+ ? Object.fromEntries(Object.entries(raw.input_tokens_details as Record<string, unknown>)
65
+ .filter(([key]) => key !== "cache_write_tokens"))
66
+ : {} as Record<string, unknown>;
67
+ const rawOutputDetails = isRecord(raw.output_tokens_details)
68
+ ? raw.output_tokens_details as Record<string, unknown>
69
+ : {} as Record<string, unknown>;
70
+ const out: Record<string, unknown> = {
71
+ ...Object.fromEntries(Object.entries(raw).filter(([key]) =>
72
+ key !== "input_tokens" && key !== "output_tokens" && key !== "total_tokens"
73
+ && key !== "input_tokens_details" && key !== "output_tokens_details")),
74
+ input_tokens: inputTokens,
75
+ output_tokens: usage.outputTokens,
76
+ total_tokens: usage.contextTotalTokens !== undefined
77
+ ? usage.contextTotalTokens
78
+ : usageDisplayTotalTokens(usage) ?? inputTokens + usage.outputTokens,
79
+ };
80
+ // cached_tokens carries cache READS only, matching OpenAI semantics, and is always present
81
+ // (zero default) for strict clients. Clamp to inputTokens so a provider's absolute
82
+ // checkpoint can never report more cache reads than input.
83
+ const inputDetails: Record<string, unknown> = {
84
+ ...rawInputDetails,
85
+ cached_tokens: Math.min(usage.cachedInputTokens ?? 0, inputTokens),
86
+ };
87
+ if (usage.cacheCreationInputTokens !== undefined) {
88
+ const cacheRead = typeof inputDetails.cached_tokens === "number" ? inputDetails.cached_tokens : 0;
89
+ inputDetails.cache_write_tokens = Math.min(
90
+ usage.cacheCreationInputTokens,
91
+ Math.max(0, inputTokens - cacheRead),
92
+ );
93
+ }
94
+ out.input_tokens_details = inputDetails;
95
+ out.output_tokens_details = { ...rawOutputDetails, reasoning_tokens: usage.reasoningOutputTokens ?? 0 };
96
+ return out;
97
+ }
98
+
99
+ /**
100
+ * Whether assembled function-call arguments are usable JSON.
101
+ * An empty buffer is valid (no-arg tools send no deltas). Non-empty must parse —
102
+ * once fragments have been streamed to the client they cannot be repaired the way
103
+ * non-stream adapters degrade a bad payload to `{}`.
104
+ */
105
+ export function toolCallArgumentsUsable(args: string): boolean {
106
+ if (args.length === 0) return true;
107
+ const trimmed = args.trim();
108
+ if (!trimmed) return false;
109
+ try {
110
+ JSON.parse(args);
111
+ return true;
112
+ } catch {
113
+ return false;
114
+ }
115
+ }
116
+
117
+ export function adapterFailureFromEvent(event: Extract<AdapterEvent, { type: "error" }>): { httpStatus: number; error: OcxErrorPayload } {
118
+ const message = redactSecretString(event.message);
119
+ if (event.status === undefined && event.errorType === undefined && event.code === undefined) {
120
+ return adapterFailureFromMessage(message);
121
+ }
122
+ const fallback = adapterFailureFromMessage(message);
123
+ let httpStatus = event.status ?? fallback.httpStatus;
124
+ const error = classifyError(httpStatus, event.errorType ?? fallback.error.type, message);
125
+ if (event.errorType !== undefined) error.type = event.errorType;
126
+ if (event.code !== undefined) error.code = event.code;
127
+ // Codex maps cyber_policy on HTTP 400 (body) or mid-stream code; never leave it as 502.
128
+ if (isCyberPolicyCode(error.code) || isCyberPolicyCode(event.code)) {
129
+ error.code = CYBER_POLICY_ERROR_CODE;
130
+ error.type = cyberPolicyErrorType(event.errorType);
131
+ httpStatus = 400;
132
+ }
133
+ return { httpStatus, error };
134
+ }
135
+
136
+ /**
137
+ * Build the native `WebSearchAction::Search` payload from the queries that ran.
138
+ *
139
+ * Every action carries BOTH keys: `{ query, queries }`, where `query` is the first
140
+ * member. Empty → `{ query: "", queries: [""] }`.
141
+ *
142
+ * Carrying both is load-bearing in both directions. DeepSeek's native Responses parser
143
+ * makes `queries` a required field, and Console Go's upstream validator makes `query` a
144
+ * required field — so a replayed `web_search_call` carried in the history of every
145
+ * subsequent turn fails deserialization with `missing field 'queries'` (#930) or 400s
146
+ * with `missing required field 'query'` unless both keys are present. Carrying both keys
147
+ * in every case satisfies both strict parsers; the trade-off is that a multi-query batch
148
+ * loses the "<first> ..." ellipsis in codex-rs and shows the first query as the label.
149
+ *
150
+ * That trade is deliberate: a cosmetic label against a conversation that 400s on every
151
+ * subsequent turn. Do not restore the old batch-omits-`query` shape to win the ellipsis
152
+ * back — it reopens #3071.
153
+ *
154
+ * This fixes items created from here on. History recorded before it is repaired at the
155
+ * replay boundary by `backfillWebSearchQueries()` in the Responses adapter.
156
+ */
157
+ export function webSearchAction(queries: string[]): Record<string, unknown> {
158
+ const first = queries[0] ?? "";
159
+ return { type: "search", query: first, queries: queries.length > 0 ? queries : [first] };
160
+ }
161
+
162
+ export interface OutputItem {
163
+ type: string;
164
+ id: string;
165
+ [key: string]: unknown;
166
+ }
167
+
168
+ /** Accumulates string fragments and their total byte length without concatenating. */
169
+ export interface StringChunks {
170
+ chunks: string[];
171
+ bytes: number;
172
+ }
173
+ export const emptyChunks = (): StringChunks => ({ chunks: [], bytes: 0 });
174
+ export const joinChunks = (sc: StringChunks): string => sc.chunks.join("");