@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
@@ -1201,6 +1201,7 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
1201
1201
  ...admissionFields(admission),
1202
1202
  inboundProtocol: "responses",
1203
1203
  };
1204
+ if (req.headers.get("x-opencodex-grok") === "1") logCtx.surface = "grok";
1204
1205
  let logged = false;
1205
1206
  const finalizeNativePassthroughLog = (
1206
1207
  status: number,
@@ -1728,7 +1729,15 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
1728
1729
  && isCanonicalOpenAiForwardProvider(openAiProvider)
1729
1730
  && providerCodexAccountMode("openai", openAiProvider) === "pool"
1730
1731
  ) {
1731
- import("../codex/auth-api")
1732
+ import("../codex/plan-from-token")
1733
+ .then(({ reconcileCodexPlansFromTokens }) => {
1734
+ try {
1735
+ reconcileCodexPlansFromTokens(config);
1736
+ } catch {
1737
+ // Derived plan metadata must not block WHAM priming.
1738
+ }
1739
+ return import("../codex/auth-api");
1740
+ })
1732
1741
  .then(({ primeCodexPoolQuotas }) => primeCodexPoolQuotas(config, "startup"))
1733
1742
  .catch(() => {});
1734
1743
  }
@@ -19,6 +19,7 @@ import {
19
19
  getLoginStatus,
20
20
  isPublicOAuthProvider,
21
21
  listOAuthProviders,
22
+ publicOAuthAuthenticationErrorMessage,
22
23
  startLoginFlow,
23
24
  submitManualLoginCode,
24
25
  } from "../../oauth";
@@ -175,7 +176,13 @@ export async function handleOauthAccountRoutes(ctx: ManagementContext): Promise<
175
176
  return jsonResponse({ url: authUrl, instructions, deviceCode });
176
177
  } catch (err) {
177
178
  if (err instanceof OAuthMutationBusyError) throw err;
178
- return jsonResponse({ error: err instanceof Error ? err.message : String(err) }, 409);
179
+ const message = err instanceof Error ? err.message : String(err);
180
+ const duplicateLoginMessage = `A login for ${provider} is already in progress`;
181
+ return jsonResponse({
182
+ error: message === duplicateLoginMessage
183
+ ? duplicateLoginMessage
184
+ : publicOAuthAuthenticationErrorMessage(err),
185
+ }, 409);
179
186
  }
180
187
  }
181
188
 
@@ -208,7 +215,8 @@ export async function handleOauthAccountRoutes(ctx: ManagementContext): Promise<
208
215
  if (url.pathname === "/api/oauth/status" && req.method === "GET") {
209
216
  const provider = (url.searchParams.get("provider") ?? "").trim().toLowerCase();
210
217
  if (!isPublicOAuthProvider(provider)) return jsonResponse({ error: "unknown oauth provider" }, 400);
211
- return jsonResponse(getLoginStatus(provider));
218
+ const status = getLoginStatus(provider);
219
+ return jsonResponse(status);
212
220
  }
213
221
 
214
222
  if (url.pathname === "/api/oauth/logout" && req.method === "POST") {
@@ -92,7 +92,7 @@ export type CostResult =
92
92
  | { kind: "value"; estimate: NonNullable<ReturnType<typeof estimateRequestCost>>; estimateReasons: CostEstimateReason[] }
93
93
  | { kind: "unavailable"; reason: MetricUnavailableReason };
94
94
 
95
- export type MetricSource = Pick<RequestLogEntry, "provider" | "model" | "durationMs" | "usageStatus" | "usage" | "requestedServiceTier" | "configuredServiceTier" | "responseServiceTier"> & {
95
+ export type MetricSource = Pick<RequestLogEntry, "provider" | "model" | "durationMs" | "usageStatus" | "usage" | "requestedServiceTier" | "configuredServiceTier" | "responseServiceTier" | "tierOutcome"> & {
96
96
  attempts?: readonly PersistedUsageAttempt[];
97
97
  };
98
98
 
@@ -27,6 +27,7 @@ import { getActiveTurnCount, isDraining } from "../lifecycle";
27
27
  import { getActiveMemoryWatchdog, observedMemoryCounter } from "../memory-watchdog";
28
28
  import { responseStateMetrics } from "../../responses/state";
29
29
  import { appOwnedBytesSnapshot } from "../../lib/app-owned-memory";
30
+ import { readWindowsReplaceRetryCounters } from "../../lib/windows-atomic-replace";
30
31
  import {
31
32
  SYSTEM_RESTART_EXPECTED_PID_HEADER,
32
33
  parseExpectedSystemRestartPid,
@@ -115,6 +116,20 @@ export async function handleSystemRoutes(ctx: ManagementContext): Promise<Respon
115
116
  });
116
117
  }
117
118
 
119
+ /**
120
+ * Windows atomic-replace retry counters.
121
+ *
122
+ * A sibling route rather than a field on /api/system/memory: that payload is
123
+ * memory-shaped, and appending unrelated filesystem counters to it makes both
124
+ * harder to consume.
125
+ *
126
+ * Keys are `publisher:CODE` where publisher is a closed union
127
+ * (ReplacePublisher) and never a path — a path could carry a username. The
128
+ * type is what enforces that; a text scan cannot see a runtime value.
129
+ */
130
+ if (url.pathname === "/api/system/windows-replace-retries" && req.method === "GET") {
131
+ return jsonResponse({ counters: readWindowsReplaceRetryCounters() });
132
+ }
118
133
  if (url.pathname === "/api/system/restart" && req.method === "POST") {
119
134
  const expectedPid = parseExpectedSystemRestartPid(
120
135
  req.headers.get(SYSTEM_RESTART_EXPECTED_PID_HEADER),
@@ -9,10 +9,11 @@ import {
9
9
  } from "../lib/errors";
10
10
  import { CODEX_CONFIG_PATH, readRootTomlString } from "../codex/paths";
11
11
  import { readCodexCatalogPath } from "../codex/catalog";
12
- import type { OcxUsage } from "../types";
12
+ import type { AttemptTierOutcome, OcxUsage } from "../types";
13
13
  import { normalizeRouteDecisionTrace, type RouteDecisionTraceV1 } from "../routing/trace";
14
14
  import type { AdapterRequest } from "../adapters/base";
15
- import { redactSecretString } from "../lib/redact";
15
+ import type { AdapterTierMetadata } from "../providers/fastwire";
16
+ import { redactSecretString, sanitizeLogMetadataString } from "../lib/redact";
16
17
  import {
17
18
  appendUsageEntry,
18
19
  isKnownAdmissionKind,
@@ -70,12 +71,15 @@ export interface RequestLogContext {
70
71
  effectiveEffort?: string;
71
72
  reasoningWireField?: string;
72
73
  reasoningWireValue?: string | number | boolean;
74
+ callerServiceTier?: string;
73
75
  requestedServiceTier?: string;
74
76
  requestedSpeedLabel?: string;
75
77
  configuredServiceTier?: string;
76
78
  configuredSpeedLabel?: string;
77
79
  modelSupportsServiceTier?: boolean;
78
80
  responseServiceTier?: string;
81
+ /** Final-attempt tier summary; attempt rows remain the accounting source of truth. */
82
+ tierOutcome?: AttemptTierOutcome;
79
83
  resolvedModel?: string;
80
84
  /** Internal: client-facing response metadata must not replace the physical routed model. */
81
85
  preserveResolvedModelFromRoute?: boolean;
@@ -86,6 +90,8 @@ export interface RequestLogContext {
86
90
  activeAttempt?: PersistedUsageAttempt;
87
91
  /** Internal wall-clock origin for the committed final attempt; never persisted. */
88
92
  activeAttemptStartedAt?: number;
93
+ /** Internal adapter response observer paired with activeAttempt.tierOutcome. */
94
+ activeTierMetadata?: AdapterTierMetadata;
89
95
  usageDebugBodyKind?: UsageDebugBodyKind;
90
96
  usageDebugBodySample?: string;
91
97
  usageDebugContentType?: string;
@@ -140,12 +146,14 @@ export interface RequestLogEntry {
140
146
  effectiveEffort?: string;
141
147
  reasoningWireField?: string;
142
148
  reasoningWireValue?: string | number | boolean;
149
+ callerServiceTier?: string;
143
150
  requestedServiceTier?: string;
144
151
  requestedSpeedLabel?: string;
145
152
  configuredServiceTier?: string;
146
153
  configuredSpeedLabel?: string;
147
154
  modelSupportsServiceTier?: boolean;
148
155
  responseServiceTier?: string;
156
+ tierOutcome?: AttemptTierOutcome;
149
157
  resolvedModel?: string;
150
158
  status: number;
151
159
  durationMs: number;
@@ -251,6 +259,7 @@ export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): R
251
259
  ...(entry.effectiveEffort ? { effectiveEffort: entry.effectiveEffort } : {}),
252
260
  ...(entry.reasoningWireField ? { reasoningWireField: entry.reasoningWireField } : {}),
253
261
  ...(entry.reasoningWireValue !== undefined ? { reasoningWireValue: entry.reasoningWireValue } : {}),
262
+ ...(entry.callerServiceTier ? { callerServiceTier: entry.callerServiceTier } : {}),
254
263
  ...(entry.requestedServiceTier ? { requestedServiceTier: entry.requestedServiceTier } : {}),
255
264
  ...(entry.requestedSpeedLabel ? { requestedSpeedLabel: entry.requestedSpeedLabel } : {}),
256
265
  ...(entry.configuredServiceTier ? { configuredServiceTier: entry.configuredServiceTier } : {}),
@@ -259,6 +268,7 @@ export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): R
259
268
  ? { modelSupportsServiceTier: entry.modelSupportsServiceTier }
260
269
  : {}),
261
270
  ...(entry.responseServiceTier ? { responseServiceTier: entry.responseServiceTier } : {}),
271
+ ...(entry.tierOutcome ? { tierOutcome: entry.tierOutcome } : {}),
262
272
  ...(entry.resolvedModel ? { resolvedModel: entry.resolvedModel } : {}),
263
273
  status: entry.status,
264
274
  durationMs: entry.durationMs,
@@ -352,6 +362,7 @@ export function addRequestLog(entry: RequestLogEntry) {
352
362
  ...(entry.effectiveEffort ? { effectiveEffort: entry.effectiveEffort } : {}),
353
363
  ...(entry.reasoningWireField ? { reasoningWireField: entry.reasoningWireField } : {}),
354
364
  ...(entry.reasoningWireValue !== undefined ? { reasoningWireValue: entry.reasoningWireValue } : {}),
365
+ ...(entry.callerServiceTier ? { callerServiceTier: entry.callerServiceTier } : {}),
355
366
  ...(entry.requestedServiceTier ? { requestedServiceTier: entry.requestedServiceTier } : {}),
356
367
  ...(entry.requestedSpeedLabel ? { requestedSpeedLabel: entry.requestedSpeedLabel } : {}),
357
368
  ...(entry.configuredServiceTier ? { configuredServiceTier: entry.configuredServiceTier } : {}),
@@ -360,6 +371,7 @@ export function addRequestLog(entry: RequestLogEntry) {
360
371
  ? { modelSupportsServiceTier: entry.modelSupportsServiceTier }
361
372
  : {}),
362
373
  ...(entry.responseServiceTier ? { responseServiceTier: entry.responseServiceTier } : {}),
374
+ ...(entry.tierOutcome ? { tierOutcome: entry.tierOutcome } : {}),
363
375
  status: entry.status,
364
376
  durationMs: entry.durationMs,
365
377
  ...(entry.firstOutputMs !== undefined ? { firstOutputMs: entry.firstOutputMs } : {}),
@@ -464,6 +476,35 @@ export function recordAdapterReasoning(
464
476
  }
465
477
  }
466
478
 
479
+ /** Attach the serializing adapter's tier observation to the active durable attempt. */
480
+ export function recordAdapterTier(
481
+ logCtx: RequestLogContext,
482
+ request: AdapterRequest,
483
+ ): void {
484
+ recordAdapterTierMetadata(logCtx, request.tierLog);
485
+ }
486
+
487
+ /** Attach adapter-owned metadata for transports that expose no AdapterRequest (runTurn). */
488
+ export function recordAdapterTierMetadata(
489
+ logCtx: RequestLogContext,
490
+ metadata: AdapterTierMetadata | undefined,
491
+ ): void {
492
+ delete logCtx.tierOutcome;
493
+ delete logCtx.activeTierMetadata;
494
+ const attempt = logCtx.activeAttempt;
495
+ if (attempt) delete attempt.tierOutcome;
496
+
497
+ try {
498
+ const outcome = metadata?.outcome;
499
+ if (!metadata || !outcome) return;
500
+ logCtx.tierOutcome = outcome;
501
+ logCtx.activeTierMetadata = metadata;
502
+ if (attempt) attempt.tierOutcome = outcome;
503
+ } catch {
504
+ // Request logging is best-effort and must not affect request delivery.
505
+ }
506
+ }
507
+
467
508
  export function requestLogErrorCode(
468
509
  status: number,
469
510
  upstreamError?: string,
@@ -552,7 +593,13 @@ export function applyResponseLogMetadata(logCtx: RequestLogContext, payload: unk
552
593
  && model.trim()
553
594
  ) logCtx.resolvedModel = model;
554
595
  const serviceTier = (source as { service_tier?: unknown }).service_tier;
555
- if (typeof serviceTier === "string" && serviceTier.trim()) logCtx.responseServiceTier = serviceTier;
596
+ if (typeof serviceTier === "string" && serviceTier.trim()) {
597
+ const sanitized = sanitizeLogMetadataString(serviceTier);
598
+ if (sanitized) logCtx.responseServiceTier = sanitized;
599
+ logCtx.activeTierMetadata?.observeResponseServiceTier(serviceTier);
600
+ } else if (Object.prototype.hasOwnProperty.call(source, "service_tier")) {
601
+ logCtx.activeTierMetadata?.observeResponseServiceTier(serviceTier);
602
+ }
556
603
  const usage = usageFromResponsesPayload((source as { usage?: unknown }).usage);
557
604
  if (usage && !logCtx.usageFromBridge) {
558
605
  logCtx.usage = usage;
@@ -618,6 +665,7 @@ export function inspectResponseLogJson(logCtx: RequestLogContext, text: string):
618
665
  try {
619
666
  applyResponseLogMetadata(logCtx, JSON.parse(text));
620
667
  } catch {
668
+ logCtx.activeTierMetadata?.markResponseUnparseable();
621
669
  /* body may not be JSON; request log metadata is best-effort only */
622
670
  }
623
671
  captureUpstreamError(logCtx, text);
@@ -648,6 +696,7 @@ export function inspectResponseLogSsePayloadParsed(
648
696
  const debugEnabled = isUsageDebugEnabled();
649
697
  const sseAlreadyMarked = logCtx.usageDebugBodyKind === "sse";
650
698
  if (parsed !== undefined) applyResponseLogMetadata(logCtx, parsed);
699
+ else logCtx.activeTierMetadata?.markResponseUnparseable();
651
700
  captureUpstreamErrorParsed(logCtx, payload, parsed);
652
701
  if (debugEnabled) {
653
702
  if (!sseAlreadyMarked) {
@@ -849,6 +898,7 @@ export function addFinalRequestLog(
849
898
  ...attempt,
850
899
  recoveryKinds: [...attempt.recoveryKinds],
851
900
  ...(attempt.usage ? { usage: { ...attempt.usage } } : {}),
901
+ ...(attempt.tierOutcome ? { tierOutcome: { ...attempt.tierOutcome } } : {}),
852
902
  }));
853
903
  const isCombo = logCtx.comboId !== undefined && (attempts?.length ?? 0) > 0;
854
904
  const aggregate = isCombo ? aggregateAttemptUsage(attempts ?? []) : null;
@@ -873,12 +923,16 @@ export function addFinalRequestLog(
873
923
  ...(logCtx.effectiveEffort ? { effectiveEffort: logCtx.effectiveEffort } : {}),
874
924
  ...(logCtx.reasoningWireField ? { reasoningWireField: logCtx.reasoningWireField } : {}),
875
925
  ...(logCtx.reasoningWireValue !== undefined ? { reasoningWireValue: logCtx.reasoningWireValue } : {}),
926
+ ...(logCtx.callerServiceTier ? { callerServiceTier: logCtx.callerServiceTier } : {}),
876
927
  ...(logCtx.requestedServiceTier ? { requestedServiceTier: logCtx.requestedServiceTier } : {}),
877
928
  ...(logCtx.requestedSpeedLabel ? { requestedSpeedLabel: logCtx.requestedSpeedLabel } : {}),
878
929
  ...(logCtx.configuredServiceTier ? { configuredServiceTier: logCtx.configuredServiceTier } : {}),
879
930
  ...(logCtx.configuredSpeedLabel ? { configuredSpeedLabel: logCtx.configuredSpeedLabel } : {}),
880
931
  ...(logCtx.modelSupportsServiceTier !== undefined ? { modelSupportsServiceTier: logCtx.modelSupportsServiceTier } : {}),
881
932
  ...(logCtx.responseServiceTier ? { responseServiceTier: logCtx.responseServiceTier } : {}),
933
+ ...((attempts?.at(-1)?.tierOutcome ?? logCtx.tierOutcome)
934
+ ? { tierOutcome: attempts?.at(-1)?.tierOutcome ?? { ...logCtx.tierOutcome! } }
935
+ : {}),
882
936
  ...(logCtx.resolvedModel ? { resolvedModel: logCtx.resolvedModel } : {}),
883
937
  status: effectiveStatus,
884
938
  durationMs: Date.now() - start,
@@ -17,7 +17,12 @@ const RECOVERY_PROMPT =
17
17
  "Read the received agent message and call capture_assignment exactly once with only the complete "
18
18
  + "plaintext payload after Payload:. Preserve every byte of the payload; do not summarize, execute, "
19
19
  + "explain, or include the routing header.";
20
- const CODEX_ORIGINATORS = new Set(["codex_cli_rs", "Codex Desktop", "codex_app"]);
20
+ const CODEX_ORIGINATORS = new Set([
21
+ "codex_cli_rs",
22
+ "Codex Desktop",
23
+ "codex_app",
24
+ "codex_work_desktop",
25
+ ]);
21
26
  const CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
22
27
  const OPENAI_TOKEN_ISSUERS = new Set(["https://auth.openai.com", "https://auth.openai.com/"]);
23
28
  const OPENAI_TOKEN_AUDIENCE = "https://api.openai.com/v1";