@bitkyc08/opencodex 2.25.0 → 2.26.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 (99) hide show
  1. package/bin/ocx.mjs +59 -7
  2. package/gui/dist/assets/index-RL6b1bTV.js +102 -0
  3. package/gui/dist/index.html +1 -1
  4. package/package.json +1 -1
  5. package/src/adapters/base.ts +18 -0
  6. package/src/adapters/client-fingerprint.ts +0 -2
  7. package/src/adapters/cursor/http1-bidi.ts +361 -0
  8. package/src/adapters/cursor/live-models.ts +117 -30
  9. package/src/adapters/cursor/live-transport.ts +137 -56
  10. package/src/adapters/cursor/native-exec-fs.ts +1 -1
  11. package/src/adapters/cursor/native-exec-network.ts +1 -1
  12. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  13. package/src/adapters/cursor/protobuf-request.ts +89 -21
  14. package/src/adapters/cursor/tool-definitions.ts +18 -7
  15. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  16. package/src/adapters/cursor/transport.ts +7 -0
  17. package/src/adapters/cursor.ts +2 -0
  18. package/src/adapters/google-http.ts +38 -10
  19. package/src/adapters/google.ts +23 -3
  20. package/src/adapters/openai-chat.ts +38 -13
  21. package/src/adapters/openai-responses.ts +129 -9
  22. package/src/adapters/registry.ts +30 -1
  23. package/src/bridge.ts +50 -12
  24. package/src/chat/inbound.ts +1 -0
  25. package/src/claude/agents-inject.ts +3 -2
  26. package/src/cli/dispatch.ts +19 -6
  27. package/src/cli/help.ts +2 -1
  28. package/src/cli/integrations.ts +35 -0
  29. package/src/cli/minimax.ts +8 -2
  30. package/src/cli/registry.ts +13 -2
  31. package/src/clients/config-export.ts +120 -1
  32. package/src/codex/account-store.ts +17 -1
  33. package/src/codex/auth-api.ts +51 -17
  34. package/src/codex/catalog/effort.ts +8 -5
  35. package/src/codex/catalog/provider-fetch.ts +39 -27
  36. package/src/codex/catalog/sync.ts +30 -8
  37. package/src/codex/inject.ts +39 -13
  38. package/src/codex/main-account.ts +29 -1
  39. package/src/codex/plan-from-token.ts +140 -0
  40. package/src/codex/plan.ts +25 -0
  41. package/src/codex/prompt-journal.ts +6 -2
  42. package/src/codex/quota-rejection.ts +21 -7
  43. package/src/codex/refresh.ts +4 -2
  44. package/src/codex/sync.ts +106 -3
  45. package/src/codex/warmup.ts +187 -81
  46. package/src/config.ts +85 -46
  47. package/src/generated/compatibility-version.json +127 -83
  48. package/src/grok/inject.ts +1 -1
  49. package/src/images/loop.ts +1 -0
  50. package/src/integrations/registry.ts +7 -0
  51. package/src/lab/automation/config-persistence.ts +2 -2
  52. package/src/lab/automation/persistence.ts +2 -2
  53. package/src/lab/ledger/purge.ts +2 -2
  54. package/src/lab/subject/behavior-fingerprint.ts +2 -2
  55. package/src/lib/config-ownership.ts +5 -2
  56. package/src/lib/destination-policy.ts +18 -1
  57. package/src/lib/provider-outbound.ts +7 -0
  58. package/src/lib/redact.ts +11 -0
  59. package/src/lib/tool-argument-integers.ts +50 -6
  60. package/src/lib/upstream-http-version.ts +57 -0
  61. package/src/lib/upstream-retry.ts +2 -1
  62. package/src/lib/windows-atomic-replace.ts +155 -0
  63. package/src/lib/windows-service-wrappers.ts +72 -0
  64. package/src/oauth/google-antigravity.ts +2 -2
  65. package/src/oauth/index.ts +60 -8
  66. package/src/providers/antigravity-models.ts +58 -4
  67. package/src/providers/command-code-efforts.ts +36 -9
  68. package/src/providers/context-cap.ts +9 -0
  69. package/src/providers/derive.ts +4 -0
  70. package/src/providers/fastwire.ts +453 -0
  71. package/src/providers/registry.ts +21 -1
  72. package/src/providers/service-tier.ts +173 -89
  73. package/src/responses/parser.ts +25 -16
  74. package/src/responses/reasoning-replay-cache.ts +30 -0
  75. package/src/responses/thought-signature-replay.ts +74 -4
  76. package/src/router.ts +6 -0
  77. package/src/routing/compatibility/behavior.ts +27 -16
  78. package/src/server/index.ts +10 -1
  79. package/src/server/management/oauth-account-routes.ts +10 -2
  80. package/src/server/management/shared.ts +1 -1
  81. package/src/server/management/system-routes.ts +15 -0
  82. package/src/server/request-log.ts +57 -3
  83. package/src/server/responses/agent-task-recovery.ts +6 -1
  84. package/src/server/responses/core.ts +209 -40
  85. package/src/server/responses/fetch-helpers.ts +15 -36
  86. package/src/server/responses/responses-field-backfill.ts +173 -0
  87. package/src/server/responses-reasoning-summary-rewrite.ts +171 -0
  88. package/src/service.ts +38 -36
  89. package/src/storage/cleanup.ts +2 -2
  90. package/src/tray/windows.ts +3 -2
  91. package/src/types.ts +101 -14
  92. package/src/update/job.ts +9 -18
  93. package/src/update/transactional-install.d.mts +22 -0
  94. package/src/update/transactional-install.mjs +259 -0
  95. package/src/usage/cost.ts +34 -5
  96. package/src/usage/log.ts +74 -4
  97. package/src/vision/anthropic-describe.ts +10 -6
  98. package/src/web-search/anthropic-executor.ts +8 -6
  99. package/gui/dist/assets/index-DxJ7kXj9.js +0 -102
@@ -0,0 +1,453 @@
1
+ import type {
2
+ AttemptTierOutcome,
3
+ FastWire,
4
+ OcxProviderConfig,
5
+ TierDecision,
6
+ TierObservationContext,
7
+ } from "../types";
8
+ import { MODEL_ADAPTER_OVERRIDE_ALLOWED } from "../types";
9
+ import { sanitizeLogMetadataString } from "../lib/redact";
10
+ import type { InboundWire, ModelWireDefault } from "./registry";
11
+
12
+ const SERVICE_TIER_ADAPTERS = new Set(["openai-chat", "openai-responses"]);
13
+ const FAST_WIRE_ADAPTERS: Readonly<Record<FastWire["kind"], ReadonlySet<string>>> = {
14
+ "service-tier": SERVICE_TIER_ADAPTERS,
15
+ // A1 deliberately has no adapter implementation for Anthropic speed.
16
+ "anthropic-speed": new Set(),
17
+ };
18
+
19
+ const DEFAULT_SERVICE_TIER_FAST_WIRE: FastWire = Object.freeze({
20
+ kind: "service-tier" as const,
21
+ canonicalToWire: Object.freeze({ priority: "priority" }),
22
+ foreignCallerTiers: "verbatim" as const,
23
+ });
24
+
25
+ export type FastPolicyAuthTransport =
26
+ | "oauth_bearer"
27
+ | "forwarded_authorization"
28
+ | "none"
29
+ | "x_api_key"
30
+ | "authorization_bearer";
31
+
32
+ export interface FastPolicyAuthority {
33
+ readonly providerAdapter: string;
34
+ readonly fastWireDeclaration: FastWire | null | undefined;
35
+ readonly modelWireOverrideAllowed: boolean;
36
+ readonly authTransport: FastPolicyAuthTransport;
37
+ readonly capability: {
38
+ readonly provider?: boolean;
39
+ readonly models: Readonly<Record<string, boolean>>;
40
+ readonly chatServiceTier?: boolean;
41
+ };
42
+ readonly modelAdapters: Readonly<Record<string, string>>;
43
+ readonly hardPins: Readonly<Record<string, string>>;
44
+ readonly registryWireDefaults: Readonly<Record<string, ModelWireDefault>>;
45
+ }
46
+
47
+ export interface ResolvedFastPolicy {
48
+ readonly capability: boolean | undefined;
49
+ readonly eligibility:
50
+ | "eligible"
51
+ | "capability-unsupported"
52
+ | "unclassified"
53
+ | "wire-unavailable"
54
+ | "pin-unavailable";
55
+ readonly adapter: string;
56
+ readonly fastWire: FastWire | null;
57
+ readonly forwardCallerTier: boolean;
58
+ }
59
+
60
+ /** Adapter-owned response observer paired with the exact body that adapter serialized. */
61
+ export interface AdapterTierMetadata {
62
+ readonly outcome: AttemptTierOutcome;
63
+ observeResponseServiceTier(value: unknown): void;
64
+ markResponseUnparseable(): void;
65
+ }
66
+
67
+ /** Detach a FastWire declaration from config or registry ownership. */
68
+ export function cloneFastWire(
69
+ value: FastWire | null | undefined,
70
+ options: { freeze?: boolean } = {},
71
+ ): FastWire | null | undefined {
72
+ if (value === null || value === undefined) return value;
73
+ const canonicalToWire = { ...value.canonicalToWire };
74
+ const betas = value.betas ? [...value.betas] : undefined;
75
+ if (options.freeze) {
76
+ Object.freeze(canonicalToWire);
77
+ if (betas) Object.freeze(betas);
78
+ }
79
+ const clone: FastWire = {
80
+ ...value,
81
+ canonicalToWire,
82
+ ...(betas ? { betas } : {}),
83
+ };
84
+ return options.freeze ? Object.freeze(clone) : clone;
85
+ }
86
+
87
+ function exactModelValue<T>(record: Readonly<Record<string, T>>, modelId: string): T | undefined {
88
+ if (Object.prototype.hasOwnProperty.call(record, modelId)) return record[modelId];
89
+ const folded = modelId.toLowerCase();
90
+ for (const [key, value] of Object.entries(record)) {
91
+ if (key.toLowerCase() === folded) return value;
92
+ }
93
+ return undefined;
94
+ }
95
+
96
+ export function resolveProviderAuthTransport(
97
+ adapter: string,
98
+ mode: NonNullable<OcxProviderConfig["authMode"]>,
99
+ apiKeyTransport?: OcxProviderConfig["apiKeyTransport"],
100
+ ): FastPolicyAuthTransport {
101
+ if (mode === "oauth") return "oauth_bearer";
102
+ if (mode === "forward") return "forwarded_authorization";
103
+ if (mode === "local") return "none";
104
+ if (adapter === "anthropic" && apiKeyTransport !== "bearer") return "x_api_key";
105
+ return "authorization_bearer";
106
+ }
107
+
108
+ /** Adapter-derived declaration. This runs only after the final model wire is known. */
109
+ export function defaultFastWireForAdapter(adapter: string): FastWire | null {
110
+ return SERVICE_TIER_ADAPTERS.has(adapter) ? DEFAULT_SERVICE_TIER_FAST_WIRE : null;
111
+ }
112
+
113
+ function registryDefaultForModel(
114
+ defaults: Readonly<Record<string, ModelWireDefault>>,
115
+ modelId: string,
116
+ inbound: InboundWire,
117
+ ): string | undefined {
118
+ const normalizedModelId = modelId.trim().toLowerCase();
119
+ if (!Object.hasOwn(defaults, normalizedModelId)) return undefined;
120
+ const declared = defaults[normalizedModelId];
121
+ if (declared === undefined) return undefined;
122
+ if (typeof declared !== "string" && !declared.inbound.includes(inbound)) return undefined;
123
+ const wire = typeof declared === "string" ? declared : declared.wire;
124
+ return MODEL_ADAPTER_OVERRIDE_ALLOWED.has(wire) ? wire : undefined;
125
+ }
126
+
127
+ function resolvePolicyAdapter(
128
+ authority: FastPolicyAuthority,
129
+ modelId: string,
130
+ inbound: InboundWire,
131
+ ): { adapter: string; hardPinned: boolean } {
132
+ // Hard pins and configured overrides deliberately use the same exact-key semantics as
133
+ // resolveWireProtocolOverride(). Registry defaults alone normalize ids at their boundary.
134
+ const hardPin = Object.hasOwn(authority.hardPins, modelId)
135
+ ? authority.hardPins[modelId]
136
+ : undefined;
137
+ if (typeof hardPin === "string") return { adapter: hardPin, hardPinned: true };
138
+ if (authority.modelWireOverrideAllowed) {
139
+ const configured = Object.hasOwn(authority.modelAdapters, modelId)
140
+ ? authority.modelAdapters[modelId]
141
+ : undefined;
142
+ if (typeof configured === "string" && MODEL_ADAPTER_OVERRIDE_ALLOWED.has(configured)) {
143
+ return { adapter: configured, hardPinned: false };
144
+ }
145
+ if (MODEL_ADAPTER_OVERRIDE_ALLOWED.has(authority.providerAdapter)) {
146
+ const registryDefault = registryDefaultForModel(authority.registryWireDefaults, modelId, inbound);
147
+ if (registryDefault !== undefined) return { adapter: registryDefault, hardPinned: false };
148
+ }
149
+ }
150
+ return { adapter: authority.providerAdapter, hardPinned: false };
151
+ }
152
+
153
+ export function resolveFastPolicy(
154
+ authority: FastPolicyAuthority,
155
+ modelId: string,
156
+ inbound: InboundWire = "responses",
157
+ ): ResolvedFastPolicy {
158
+ const { adapter, hardPinned } = resolvePolicyAdapter(authority, modelId, inbound);
159
+ const exactCapability = exactModelValue(authority.capability.models, modelId);
160
+ const capability = authority.capability.provider === false
161
+ ? false
162
+ : exactCapability ?? authority.capability.provider;
163
+ const fastWire = authority.fastWireDeclaration === undefined
164
+ ? defaultFastWireForAdapter(adapter)
165
+ : authority.fastWireDeclaration;
166
+ const wireAvailable = fastWire !== null && FAST_WIRE_ADAPTERS[fastWire.kind].has(adapter);
167
+ // Explicit null disables Fast injection, but the defensive true+null branch still preserves
168
+ // a caller tier on an existing OpenAI service-tier wire.
169
+ const callerWireAvailable = wireAvailable
170
+ || (fastWire === null && SERVICE_TIER_ADAPTERS.has(adapter));
171
+ // On classified routes this permission applies only to a caller's foreign tier: proxy-owned
172
+ // canonical Fast has already passed capability validation. On unclassified routes every caller
173
+ // tier still needs the final wire's forwarding permission.
174
+ const forwardCallerTier = capability !== false
175
+ && callerWireAvailable
176
+ && (adapter !== "openai-chat" || authority.capability.chatServiceTier === true);
177
+
178
+ let eligibility: ResolvedFastPolicy["eligibility"];
179
+ if (capability === false) eligibility = "capability-unsupported";
180
+ else if (!wireAvailable) {
181
+ eligibility = hardPinned && authority.fastWireDeclaration !== null
182
+ ? "pin-unavailable"
183
+ : "wire-unavailable";
184
+ }
185
+ else if (capability === undefined) eligibility = "unclassified";
186
+ else eligibility = "eligible";
187
+
188
+ return { capability, eligibility, adapter, fastWire, forwardCallerTier };
189
+ }
190
+
191
+ export function canonicalFastTierMarker(callerTier: string | undefined): "priority" | undefined {
192
+ const folded = callerTier?.trim().toLowerCase();
193
+ return folded === "priority" || folded === "fast" ? "priority" : undefined;
194
+ }
195
+
196
+ /** Capture Fast demand before the final A1 serialization action rewrites the parsed tier view. */
197
+ export function tierObservationContext(
198
+ policy: ResolvedFastPolicy,
199
+ fastMode: boolean | undefined,
200
+ callerTier: string | undefined,
201
+ ): TierObservationContext {
202
+ return {
203
+ capability: policy.capability,
204
+ eligibility: policy.eligibility,
205
+ fastWire: policy.fastWire,
206
+ demandDecision: fastMode === true ? "force-fast" : fastMode === false ? "force-default" : "inherit",
207
+ ...(callerTier !== undefined ? { callerTier } : {}),
208
+ };
209
+ }
210
+
211
+ function canonicalFromWire(
212
+ fastWire: FastWire | null,
213
+ wireValue: string,
214
+ ): string | undefined {
215
+ if (!fastWire) return undefined;
216
+ for (const [canonical, mapped] of Object.entries(fastWire.canonicalToWire)) {
217
+ if (mapped === wireValue) return canonical;
218
+ }
219
+ return undefined;
220
+ }
221
+
222
+ function downgradeReasonForUnavailable(
223
+ context: TierObservationContext,
224
+ ): AttemptTierOutcome["fastDowngradeReason"] {
225
+ if (context.capability === false || context.eligibility === "capability-unsupported") {
226
+ return "route-unsupported";
227
+ }
228
+ return "wire-unavailable";
229
+ }
230
+
231
+ /**
232
+ * Build the mutable observation record only after an adapter has completed serialization.
233
+ * `wireKind`/`wireValue` describe the field the adapter actually emitted, never a route guess.
234
+ */
235
+ export function createAdapterTierMetadata(
236
+ context: TierObservationContext | undefined,
237
+ decision: TierDecision | undefined,
238
+ wireKind: FastWire["kind"] | null,
239
+ wireValue: string | null,
240
+ ): AdapterTierMetadata | undefined {
241
+ if (!context || !decision) return undefined;
242
+
243
+ const callerCanonicalFast = canonicalFastTierMarker(context.callerTier) === "priority";
244
+ const callerTierDropped = context.callerTier !== undefined
245
+ && !callerCanonicalFast
246
+ && wireValue === null;
247
+ const callerFastSuppressedByConfig = context.capability !== undefined
248
+ && context.demandDecision === "force-default"
249
+ && callerCanonicalFast;
250
+ const loggedWireValue = wireValue === null ? null : sanitizeLogMetadataString(wireValue);
251
+ const outcome: AttemptTierOutcome = {
252
+ wireKind,
253
+ ...(wireValue === null
254
+ ? { wireValue: null }
255
+ : loggedWireValue ? { wireValue: loggedWireValue } : {}),
256
+ fastOutcome: "unknown",
257
+ confirmation: "unknown",
258
+ ...(callerTierDropped ? { callerTierDropped: true } : {}),
259
+ ...(callerFastSuppressedByConfig ? { callerFastSuppressedByConfig: true } : {}),
260
+ };
261
+
262
+ // A0/A1 deliberately make fastMode inert for unclassified routes. Preserve that uncertainty:
263
+ // do not infer demand, suppression, or a canonical tier from a verbatim caller passthrough.
264
+ if (context.capability === undefined || context.eligibility === "unclassified") {
265
+ delete outcome.callerFastSuppressedByConfig;
266
+ return {
267
+ outcome,
268
+ observeResponseServiceTier(value: unknown) {
269
+ const sanitized = sanitizeLogMetadataString(value);
270
+ if (sanitized) outcome.responseServiceTier = sanitized;
271
+ },
272
+ markResponseUnparseable() {},
273
+ };
274
+ }
275
+
276
+ const effectiveFastRequested = context.capability === true
277
+ && context.fastWire !== null
278
+ && (context.demandDecision === "force-fast"
279
+ || (context.demandDecision === "inherit" && callerCanonicalFast));
280
+ // Known-unsupported routes still need a downgrade when the caller/config expressed Fast intent,
281
+ // but they are deliberately outside the effective-demand calculation above.
282
+ const fastIntent = context.demandDecision === "force-fast"
283
+ || (context.demandDecision === "inherit" && callerCanonicalFast);
284
+
285
+ if (!fastIntent) {
286
+ outcome.fastOutcome = "not-requested";
287
+ } else if (!effectiveFastRequested || context.eligibility !== "eligible" || wireValue === null) {
288
+ outcome.fastOutcome = "downgraded";
289
+ outcome.fastDowngradeReason = downgradeReasonForUnavailable(context);
290
+ outcome.confirmation = "downgraded";
291
+ } else if (canonicalFromWire(context.fastWire, wireValue) === "priority") {
292
+ outcome.canonical = "priority";
293
+ outcome.fastOutcome = "applied";
294
+ outcome.confirmation = "assumed";
295
+ }
296
+
297
+ const responseCanConfirmFast = effectiveFastRequested
298
+ && context.eligibility === "eligible"
299
+ && wireValue !== null;
300
+ return {
301
+ outcome,
302
+ observeResponseServiceTier(value: unknown) {
303
+ if (typeof value !== "string" || !value.trim()) {
304
+ if (value !== undefined && responseCanConfirmFast) {
305
+ delete outcome.canonical;
306
+ delete outcome.fastDowngradeReason;
307
+ outcome.fastOutcome = "unknown";
308
+ outcome.confirmation = "unknown";
309
+ }
310
+ return;
311
+ }
312
+ const sanitized = sanitizeLogMetadataString(value);
313
+ if (sanitized) outcome.responseServiceTier = sanitized;
314
+ if (!responseCanConfirmFast) return;
315
+ if (canonicalFromWire(context.fastWire, value) === "priority") {
316
+ outcome.canonical = "priority";
317
+ delete outcome.fastDowngradeReason;
318
+ outcome.fastOutcome = "applied";
319
+ outcome.confirmation = "confirmed";
320
+ } else {
321
+ delete outcome.canonical;
322
+ outcome.fastOutcome = "downgraded";
323
+ outcome.fastDowngradeReason = "response-declined";
324
+ outcome.confirmation = "downgraded";
325
+ }
326
+ },
327
+ markResponseUnparseable() {
328
+ if (!responseCanConfirmFast) return;
329
+ delete outcome.canonical;
330
+ delete outcome.fastDowngradeReason;
331
+ delete outcome.responseServiceTier;
332
+ outcome.fastOutcome = "unknown";
333
+ outcome.confirmation = "unknown";
334
+ },
335
+ };
336
+ }
337
+
338
+ /** Pure tier state machine. B1 normalizes canonical Fast on classified inherit routes. */
339
+ export function decideTier(
340
+ policy: ResolvedFastPolicy,
341
+ fastMode: boolean | undefined,
342
+ callerTier: string | undefined,
343
+ ): TierDecision {
344
+ if (policy.capability === false) return { kind: "drop" };
345
+ if (policy.capability === undefined) {
346
+ return policy.forwardCallerTier ? { kind: "forward-caller" } : { kind: "drop" };
347
+ }
348
+ if (policy.fastWire === null) {
349
+ return policy.forwardCallerTier ? { kind: "forward-caller" } : { kind: "drop" };
350
+ }
351
+ if (policy.eligibility !== "eligible") return { kind: "drop" };
352
+ if (fastMode === true) {
353
+ const value = policy.fastWire.canonicalToWire.priority;
354
+ return typeof value === "string" && value.length > 0
355
+ ? { kind: "set", value }
356
+ : { kind: "drop" };
357
+ }
358
+ if (fastMode === false) return { kind: "drop" };
359
+ const callerCanonicalFast = canonicalFastTierMarker(callerTier);
360
+ if (callerCanonicalFast !== undefined) {
361
+ const value = policy.fastWire.canonicalToWire[callerCanonicalFast];
362
+ return typeof value === "string" && value.length > 0
363
+ ? { kind: "set", value }
364
+ : { kind: "drop" };
365
+ }
366
+ if (callerTier !== undefined && !policy.forwardCallerTier) return { kind: "drop" };
367
+ if (
368
+ callerTier !== undefined
369
+ && policy.fastWire.foreignCallerTiers === "drop"
370
+ ) {
371
+ return { kind: "drop" };
372
+ }
373
+ return { kind: "forward-caller" };
374
+ }
375
+
376
+ export function tierValueAfterDecision(
377
+ decision: TierDecision,
378
+ callerTier: string | undefined,
379
+ ): string | undefined {
380
+ if (decision.kind === "set") return decision.value;
381
+ if (decision.kind === "drop") return undefined;
382
+ return callerTier;
383
+ }
384
+
385
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
386
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
387
+ const prototype = Object.getPrototypeOf(value);
388
+ return prototype === Object.prototype || prototype === null;
389
+ }
390
+
391
+ export function hasFastWireCapabilityConflict(source: {
392
+ readonly fastWire?: unknown;
393
+ readonly supportsServiceTier?: unknown;
394
+ readonly modelSupportsServiceTier?: unknown;
395
+ }): boolean {
396
+ if (source.fastWire !== null) return false;
397
+ if (source.supportsServiceTier === false) return false;
398
+ if (source.supportsServiceTier === true) return true;
399
+ return isPlainRecord(source.modelSupportsServiceTier)
400
+ && Object.values(source.modelSupportsServiceTier).some(value => value === true);
401
+ }
402
+
403
+ /** Runtime registry validation; config uses the equivalent Zod shape at its boundary. */
404
+ export function fastWireDeclarationError(source: {
405
+ readonly fastWire?: unknown;
406
+ readonly supportsServiceTier?: unknown;
407
+ readonly modelSupportsServiceTier?: unknown;
408
+ }): string | null {
409
+ const value = source.fastWire;
410
+ if (value === undefined) return null;
411
+ if (hasFastWireCapabilityConflict(source)) {
412
+ return "fastWire=null conflicts with supportsServiceTier=true";
413
+ }
414
+ if (value === null) return null;
415
+ if (!isPlainRecord(value)) return "fastWire must be an object, null, or absent";
416
+ if (value.kind !== "service-tier" && value.kind !== "anthropic-speed") {
417
+ return "fastWire.kind must be service-tier or anthropic-speed";
418
+ }
419
+ if (value.foreignCallerTiers !== "verbatim" && value.foreignCallerTiers !== "drop") {
420
+ return "fastWire.foreignCallerTiers must be verbatim or drop";
421
+ }
422
+ if (!isPlainRecord(value.canonicalToWire)) return "fastWire.canonicalToWire must be an object";
423
+ if (!Object.prototype.hasOwnProperty.call(value.canonicalToWire, "priority")) {
424
+ return "fastWire.canonicalToWire must include priority";
425
+ }
426
+ const wireValues: string[] = [];
427
+ for (const [canonicalTier, wireValue] of Object.entries(value.canonicalToWire)) {
428
+ if (canonicalTier.trim().length === 0) {
429
+ return "fastWire.canonicalToWire keys must be nonblank strings";
430
+ }
431
+ if (typeof wireValue !== "string" || wireValue.trim().length === 0 || wireValue.trim().length > 64) {
432
+ return "fastWire.canonicalToWire values must be nonblank strings of at most 64 characters";
433
+ }
434
+ wireValues.push(wireValue.trim());
435
+ }
436
+ if (new Set(wireValues).size !== wireValues.length) {
437
+ return "fastWire.canonicalToWire values must be unique";
438
+ }
439
+ if (value.betas !== undefined) {
440
+ if (!Array.isArray(value.betas) || value.betas.length > 16) {
441
+ return "fastWire.betas must be an array of at most 16 values";
442
+ }
443
+ const betas: string[] = [];
444
+ for (const beta of value.betas) {
445
+ if (typeof beta !== "string" || beta.trim().length === 0) {
446
+ return "fastWire.betas values must be nonblank strings";
447
+ }
448
+ betas.push(beta.trim());
449
+ }
450
+ if (new Set(betas).size !== betas.length) return "fastWire.betas values must be unique";
451
+ }
452
+ return null;
453
+ }
@@ -1,4 +1,5 @@
1
- import type { CodexAccountMode, OcxProviderConfig } from "../types";
1
+ import type { CodexAccountMode, FastWire, OcxProviderConfig } from "../types";
2
+ import { fastWireDeclarationError } from "./fastwire";
2
3
  import { KIRO_MODELS, KIRO_MODEL_CONTEXT_WINDOWS, KIRO_MODEL_REASONING_EFFORTS } from "./kiro-models";
3
4
  import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, ANTIGRAVITY_MODEL_EFFORTS, ANTIGRAVITY_MODEL_INPUT_MODALITIES } from "./antigravity-models";
4
5
  import type { ProviderBaseUrlChoice } from "./base-url-choices";
@@ -165,6 +166,8 @@ export interface ProviderRegistryEntry {
165
166
  * of paying a translation hop.
166
167
  */
167
168
  modelWireDefaults?: Record<string, ModelWireDefault>;
169
+ /** Explicit Fast wire declaration; absence derives from the final model adapter. */
170
+ fastWire?: FastWire | null;
168
171
  /**
169
172
  * Registry-only per-model override for the upstream request shape used behind a
170
173
  * Codex Responses WebSocket turn. `false` keeps the client-facing WebSocket but
@@ -1735,6 +1738,12 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1735
1738
  apiKeyValidation: "unknown",
1736
1739
  // The public catalog reports ids/context windows only; no trustworthy reasoning contract.
1737
1740
  reasoningEfforts: [],
1741
+ // Official Command Code model-profile reasoning facts (shared with the OAuth
1742
+ // `command-code` entry). Without them the API-key preset never advertises a
1743
+ // reasoning picker, and the router's known-ids decode source misses the native
1744
+ // slash ids — so a Codex-facing slug like `commandcode/deepseek-deepseek-v4-pro`
1745
+ // is sent upstream verbatim and rejected with `unsupported_model`.
1746
+ modelReasoningEfforts: COMMAND_CODE_MODEL_REASONING_EFFORTS,
1738
1747
  modelDiscovery: {
1739
1748
  path: "models",
1740
1749
  maxResponseBytes: 256 * 1024,
@@ -2531,6 +2540,17 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
2531
2540
  { id: "gitlab-duo", label: "GitLab Duo", baseUrl: "https://cloud.gitlab.com/ai/v1/proxy/openai/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://gitlab.com/-/user_settings/personal_access_tokens" },
2532
2541
  ];
2533
2542
 
2543
+ export function providerRegistryFastWireError(
2544
+ entry: Pick<ProviderRegistryEntry, "fastWire" | "supportsServiceTier" | "modelSupportsServiceTier">,
2545
+ ): string | null {
2546
+ return fastWireDeclarationError(entry);
2547
+ }
2548
+
2549
+ for (const entry of PROVIDER_REGISTRY) {
2550
+ const error = providerRegistryFastWireError(entry);
2551
+ if (error) throw new TypeError(`Invalid provider registry entry ${entry.id}: ${error}`);
2552
+ }
2553
+
2534
2554
  export function getProviderRegistryEntry(id: string): ProviderRegistryEntry | undefined {
2535
2555
  return PROVIDER_REGISTRY.find(entry => entry.id === id);
2536
2556
  }