@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
package/src/usage/log.ts CHANGED
@@ -4,8 +4,9 @@ import { join } from "node:path";
4
4
  import { getConfigDir } from "../config";
5
5
  import { enforceAppOwnedMemoryBudget } from "../lib/app-owned-memory";
6
6
  import { recordOwnedConfigPath } from "../lib/config-ownership";
7
+ import { sanitizeLogMetadataString } from "../lib/redact";
7
8
  import { usageDisplayTotalTokens } from "./totals";
8
- import type { OcxUsage } from "../types";
9
+ import type { AttemptTierOutcome, OcxUsage } from "../types";
9
10
  import { normalizeRouteDecisionTrace, type RouteDecisionTraceV1 } from "../routing/trace";
10
11
  import { CODEX_ACCOUNT_LOG_LABEL_RE } from "../codex/account-label";
11
12
 
@@ -61,6 +62,8 @@ export interface PersistedUsageAttempt {
61
62
  effectiveEffort?: string;
62
63
  reasoningWireField?: string;
63
64
  reasoningWireValue?: string | number | boolean;
65
+ /** Adapter-produced tier fact for this physical attempt; absent on pre-B0 rows. */
66
+ tierOutcome?: AttemptTierOutcome;
64
67
  }
65
68
 
66
69
  export interface PersistedUsageEntry {
@@ -87,12 +90,16 @@ export interface PersistedUsageEntry {
87
90
  effectiveEffort?: string;
88
91
  reasoningWireField?: string;
89
92
  reasoningWireValue?: string | number | boolean;
93
+ /** Raw caller tier captured before routing, sanitized and bounded for durable logs. */
94
+ callerServiceTier?: string;
90
95
  requestedServiceTier?: string;
91
96
  requestedSpeedLabel?: string;
92
97
  configuredServiceTier?: string;
93
98
  configuredSpeedLabel?: string;
94
99
  modelSupportsServiceTier?: boolean;
95
100
  responseServiceTier?: string;
101
+ /** Summary of the final physical attempt for dashboard consumers. */
102
+ tierOutcome?: AttemptTierOutcome;
96
103
  status: number;
97
104
  durationMs: number;
98
105
  /** TTFT relative to the request start (WP4); unset for non-streaming/tool-only. */
@@ -218,6 +225,15 @@ const USAGE_STATUSES = new Set<UsageStatus>([
218
225
  "estimated",
219
226
  ]);
220
227
  const LAB_ROUTE_SUBJECT_ID_RE = /^[0-9a-f]{64}$/;
228
+ const FAST_OUTCOMES = new Set<AttemptTierOutcome["fastOutcome"]>([
229
+ "not-requested", "applied", "downgraded", "unknown",
230
+ ]);
231
+ const TIER_CONFIRMATIONS = new Set<AttemptTierOutcome["confirmation"]>([
232
+ "confirmed", "assumed", "downgraded", "unknown",
233
+ ]);
234
+ const FAST_DOWNGRADE_REASONS = new Set<NonNullable<AttemptTierOutcome["fastDowngradeReason"]>>([
235
+ "route-unsupported", "wire-unavailable", "response-declined",
236
+ ]);
221
237
 
222
238
  export function isLabRouteSubjectId(value: unknown): value is string {
223
239
  return typeof value === "string" && LAB_ROUTE_SUBJECT_ID_RE.test(value);
@@ -246,6 +262,53 @@ function normalizeAttemptUsage(raw: unknown): OcxUsage | null {
246
262
  return normalizeUsageValue(usage as unknown as OcxUsage) ?? null;
247
263
  }
248
264
 
265
+ function normalizeAttemptTierOutcome(raw: unknown): AttemptTierOutcome | null {
266
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
267
+ const outcome = raw as Record<string, unknown>;
268
+ if (typeof outcome.fastOutcome !== "string"
269
+ || !FAST_OUTCOMES.has(outcome.fastOutcome as AttemptTierOutcome["fastOutcome"])
270
+ || typeof outcome.confirmation !== "string"
271
+ || !TIER_CONFIRMATIONS.has(outcome.confirmation as AttemptTierOutcome["confirmation"])) {
272
+ return null;
273
+ }
274
+ if ("canonical" in outcome && outcome.canonical !== "priority") return null;
275
+ if ("wireKind" in outcome
276
+ && outcome.wireKind !== null
277
+ && outcome.wireKind !== "service-tier"
278
+ && outcome.wireKind !== "anthropic-speed") return null;
279
+ if ("wireValue" in outcome && outcome.wireValue !== null && typeof outcome.wireValue !== "string") return null;
280
+ if ("fastDowngradeReason" in outcome
281
+ && (typeof outcome.fastDowngradeReason !== "string"
282
+ || !FAST_DOWNGRADE_REASONS.has(outcome.fastDowngradeReason as NonNullable<AttemptTierOutcome["fastDowngradeReason"]>))) {
283
+ return null;
284
+ }
285
+ if ("callerTierDropped" in outcome && typeof outcome.callerTierDropped !== "boolean") return null;
286
+ if ("callerFastSuppressedByConfig" in outcome
287
+ && typeof outcome.callerFastSuppressedByConfig !== "boolean") return null;
288
+ if ("responseServiceTier" in outcome && typeof outcome.responseServiceTier !== "string") return null;
289
+ const wireValue = sanitizeLogMetadataString(outcome.wireValue);
290
+ const responseServiceTier = sanitizeLogMetadataString(outcome.responseServiceTier);
291
+ return {
292
+ ...(outcome.canonical === "priority" ? { canonical: "priority" as const } : {}),
293
+ ...(outcome.wireKind === null || outcome.wireKind === "service-tier" || outcome.wireKind === "anthropic-speed"
294
+ ? { wireKind: outcome.wireKind }
295
+ : {}),
296
+ ...(outcome.wireValue === null
297
+ ? { wireValue: null }
298
+ : wireValue ? { wireValue } : {}),
299
+ fastOutcome: outcome.fastOutcome as AttemptTierOutcome["fastOutcome"],
300
+ ...(typeof outcome.fastDowngradeReason === "string"
301
+ ? { fastDowngradeReason: outcome.fastDowngradeReason as NonNullable<AttemptTierOutcome["fastDowngradeReason"]> }
302
+ : {}),
303
+ ...(typeof outcome.callerTierDropped === "boolean" ? { callerTierDropped: outcome.callerTierDropped } : {}),
304
+ ...(typeof outcome.callerFastSuppressedByConfig === "boolean"
305
+ ? { callerFastSuppressedByConfig: outcome.callerFastSuppressedByConfig }
306
+ : {}),
307
+ confirmation: outcome.confirmation as AttemptTierOutcome["confirmation"],
308
+ ...(responseServiceTier ? { responseServiceTier } : {}),
309
+ };
310
+ }
311
+
249
312
  function normalizeUsageAttempt(raw: unknown): PersistedUsageAttempt | null {
250
313
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
251
314
  const attempt = raw as Record<string, unknown>;
@@ -272,6 +335,9 @@ function normalizeUsageAttempt(raw: unknown): PersistedUsageAttempt | null {
272
335
  && !isNonNegativeFiniteNumber(attempt.totalTokens)) return null;
273
336
  const usage = "usage" in attempt ? normalizeAttemptUsage(attempt.usage) : undefined;
274
337
  if ("usage" in attempt && usage === null) return null;
338
+ const tierOutcome = "tierOutcome" in attempt
339
+ ? normalizeAttemptTierOutcome(attempt.tierOutcome)
340
+ : undefined;
275
341
  const recoveryKinds = Array.isArray(attempt.recoveryKinds)
276
342
  ? [...new Set(attempt.recoveryKinds.filter(
277
343
  (value): value is AttemptRecoveryKind => typeof value === "string"
@@ -321,6 +387,7 @@ function normalizeUsageAttempt(raw: unknown): PersistedUsageAttempt | null {
321
387
  ? { reasoningWireValue: capMetadataString(attempt.reasoningWireValue) }
322
388
  : { reasoningWireValue: attempt.reasoningWireValue }
323
389
  : {}),
390
+ ...(tierOutcome ? { tierOutcome } : {}),
324
391
  };
325
392
  }
326
393
 
@@ -357,6 +424,9 @@ export function normalizeUsageEntryForTest(entry: PersistedUsageEntry): Persiste
357
424
 
358
425
  function normalizeUsageEntry(entry: PersistedUsageEntry): PersistedUsageEntry {
359
426
  const attempts = normalizedAttempts(entry.attempts);
427
+ const tierOutcome = entry.tierOutcome ? normalizeAttemptTierOutcome(entry.tierOutcome) : undefined;
428
+ const callerServiceTier = sanitizeLogMetadataString(entry.callerServiceTier);
429
+ const responseServiceTier = sanitizeLogMetadataString(entry.responseServiceTier);
360
430
  const routeDecision = entry.routeDecision
361
431
  ? normalizeRouteDecisionTrace(entry.routeDecision)
362
432
  : undefined;
@@ -397,6 +467,7 @@ function normalizeUsageEntry(entry: PersistedUsageEntry): PersistedUsageEntry {
397
467
  ? { reasoningWireValue: capMetadataString(entry.reasoningWireValue) }
398
468
  : { reasoningWireValue: entry.reasoningWireValue }
399
469
  : {}),
470
+ ...(callerServiceTier ? { callerServiceTier } : {}),
400
471
  ...(typeof entry.requestedServiceTier === "string" && entry.requestedServiceTier
401
472
  ? { requestedServiceTier: capMetadataString(entry.requestedServiceTier) }
402
473
  : {}),
@@ -412,9 +483,8 @@ function normalizeUsageEntry(entry: PersistedUsageEntry): PersistedUsageEntry {
412
483
  ...(typeof entry.modelSupportsServiceTier === "boolean"
413
484
  ? { modelSupportsServiceTier: entry.modelSupportsServiceTier }
414
485
  : {}),
415
- ...(typeof entry.responseServiceTier === "string" && entry.responseServiceTier
416
- ? { responseServiceTier: capMetadataString(entry.responseServiceTier) }
417
- : {}),
486
+ ...(responseServiceTier ? { responseServiceTier } : {}),
487
+ ...(tierOutcome ? { tierOutcome } : {}),
418
488
  status: entry.status,
419
489
  durationMs: entry.durationMs,
420
490
  ...(isNonNegativeFiniteNumber(entry.firstOutputMs)
@@ -3,7 +3,7 @@ import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fin
3
3
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
4
4
  import { sidecarEnter } from "../lib/sidecar-tracker";
5
5
  import { fetchWithResetRetry } from "../lib/upstream-retry";
6
- import { getValidAccessToken } from "../oauth";
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";
9
9
 
@@ -67,8 +67,8 @@ export async function parseAnthropicVisionSSE(res: Response): Promise<DescribeOu
67
67
  const delta = isRecord(data.delta) ? data.delta : {};
68
68
  if (delta.type === "text_delta" && typeof delta.text === "string") text += delta.text;
69
69
  } else if (data.type === "error") {
70
- const error = isRecord(data.error) ? data.error : {};
71
- terminalError = typeof error.message === "string" ? error.message : "anthropic vision sidecar stream error";
70
+ // Provider-authored stream errors can contain credentials, paths, or response bodies.
71
+ terminalError = "anthropic vision sidecar stream error";
72
72
  }
73
73
  };
74
74
 
@@ -116,7 +116,7 @@ export async function describeImageAnthropic(
116
116
  try {
117
117
  token = await getValidAccessToken(providerName);
118
118
  } catch (error) {
119
- return { text: "", error: `anthropic vision sidecar auth failed: ${error instanceof Error ? error.message : String(error)}` };
119
+ return { text: "", error: `anthropic vision sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(error)}` };
120
120
  }
121
121
 
122
122
  const headers: Record<string, string> = {
@@ -166,7 +166,11 @@ export async function describeImageAnthropic(
166
166
  if (!res.ok) {
167
167
  const responseText = await res.text().catch(() => "");
168
168
  console.warn(`[vision] anthropic sidecar HTTP ${res.status} (${Date.now() - startedAt}ms)`);
169
- return { text: "", error: `anthropic vision sidecar HTTP ${res.status}: ${responseText.slice(0, 200)}` };
169
+ if (res.status === 401) {
170
+ return { text: "", error: `anthropic vision sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(new Error(responseText))}` };
171
+ }
172
+ // Upstream bodies are untrusted and may contain credentials, paths, or provider diagnostics.
173
+ return { text: "", error: `anthropic vision sidecar HTTP ${res.status}` };
170
174
  }
171
175
  const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
172
176
  try {
@@ -177,7 +181,7 @@ export async function describeImageAnthropic(
177
181
  } catch (error) {
178
182
  const kind = error instanceof Error && error.name === "TimeoutError" ? "timeout" : "connect_error";
179
183
  console.warn(`[vision] anthropic sidecar ${kind} (${Date.now() - startedAt}ms)`);
180
- return { text: "", error: error instanceof Error ? error.message : String(error) };
184
+ return { text: "", error: `anthropic vision sidecar ${kind}` };
181
185
  } finally {
182
186
  sidecarExit();
183
187
  linkedSignal.cleanup();
@@ -1,9 +1,8 @@
1
1
  import type { OcxProviderConfig } from "../types";
2
- import { getValidAccessToken } from "../oauth";
2
+ import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
3
3
  import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/anthropic";
4
4
  import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
5
5
  import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
6
- import { redactSecretString } from "../lib/redact";
7
6
  import { sidecarEnter } from "../lib/sidecar-tracker";
8
7
  import { fetchWithResetRetry } from "../lib/upstream-retry";
9
8
  import type { WebSearchSource } from "./parse";
@@ -127,7 +126,7 @@ export async function runAnthropicWebSearch(
127
126
  try {
128
127
  token = await getValidAccessToken(providerName);
129
128
  } catch (e) {
130
- return { text: "", sources: [], error: `anthropic sidecar auth failed: ${e instanceof Error ? e.message : String(e)}` };
129
+ return { text: "", sources: [], error: `anthropic sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(e)}` };
131
130
  }
132
131
  const headers: Record<string, string> = {
133
132
  "Content-Type": "application/json",
@@ -174,8 +173,11 @@ export async function runAnthropicWebSearch(
174
173
  const t = await res.text().catch(() => "");
175
174
  detachBodyGuard();
176
175
  console.warn(`[web-search] anthropic sidecar HTTP ${res.status} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
177
- // Redact before surfacing: the body can echo auth headers/tokens (#398 review).
178
- return { text: "", sources: [], error: `sidecar HTTP ${res.status}: ${redactSecretString(t.slice(0, 200))}` };
176
+ if (res.status === 401) {
177
+ return { text: "", sources: [], error: `anthropic sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(new Error(t))}` };
178
+ }
179
+ // Upstream bodies are untrusted and may contain credentials, paths, or provider diagnostics.
180
+ return { text: "", sources: [], error: `sidecar HTTP ${res.status}` };
179
181
  }
180
182
  try {
181
183
  return await parseAnthropicSidecarSSE(res);
@@ -185,7 +187,7 @@ export async function runAnthropicWebSearch(
185
187
  } catch (e) {
186
188
  const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
187
189
  console.warn(`[web-search] anthropic sidecar ${kind} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
188
- return { text: "", sources: [], error: e instanceof Error ? e.message : String(e) };
190
+ return { text: "", sources: [], error: `anthropic sidecar ${kind}` };
189
191
  } finally {
190
192
  sidecarExit();
191
193
  linkedSignal.cleanup();