@yansigit/opencodex 2.32.0 → 2.33.1
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.
- package/README.md +2 -2
- package/gui/dist/assets/index-CIDo4y4k.js +102 -0
- package/gui/dist/assets/index-DrSQdTRd.css +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +8 -5
- package/src/adapters/anthropic.ts +20 -6
- package/src/adapters/azure.ts +20 -4
- package/src/adapters/base.ts +3 -1
- package/src/adapters/command-code.ts +131 -17
- package/src/adapters/cursor/envelope-echo.ts +162 -0
- package/src/adapters/cursor/live-transport.ts +4 -2
- package/src/adapters/cursor/native-exec-fs.ts +13 -12
- package/src/adapters/cursor/native-exec-network.ts +3 -5
- package/src/adapters/cursor/native-exec-policy.ts +47 -0
- package/src/adapters/cursor/native-exec-shell.ts +13 -25
- package/src/adapters/cursor/native-exec.ts +18 -10
- package/src/adapters/cursor/protobuf-events.ts +186 -9
- package/src/adapters/cursor/protobuf-request.ts +53 -18
- package/src/adapters/cursor/request-builder.ts +11 -3
- package/src/adapters/cursor/tool-definitions.ts +49 -2
- package/src/adapters/cursor/tool-result-normalize.ts +21 -8
- package/src/adapters/cursor/types.ts +11 -3
- package/src/adapters/cursor.ts +123 -0
- package/src/adapters/google-aistudio-parser.ts +49 -0
- package/src/adapters/google-antigravity-replay.ts +2 -2
- package/src/adapters/google-antigravity-wire.ts +7 -0
- package/src/adapters/google-errors.ts +6 -2
- package/src/adapters/google-http.ts +30 -7
- package/src/adapters/google-truncation.ts +5 -0
- package/src/adapters/google-wire-compiler.ts +38 -6
- package/src/adapters/google.ts +242 -28
- package/src/adapters/kiro-tools.ts +20 -9
- package/src/adapters/openai-chat.ts +9 -0
- package/src/adapters/openai-responses.ts +2 -1
- package/src/bridge.ts +112 -9
- package/src/chat/inbound.ts +15 -0
- package/src/claude/context-windows.ts +16 -9
- package/src/cli/doctor.ts +2 -2
- package/src/cli/index.ts +10 -3
- package/src/cli/provider.ts +6 -0
- package/src/cli/status.ts +23 -0
- package/src/codex/auth-api.ts +4 -2
- package/src/codex/autostart-health.ts +16 -0
- package/src/codex/catalog/aggregation.ts +12 -12
- package/src/codex/catalog/effort.ts +18 -3
- package/src/codex/catalog/metadata.ts +27 -1
- package/src/codex/catalog/model-metadata.ts +39 -12
- package/src/codex/catalog/parsing.ts +38 -27
- package/src/codex/catalog/provider-fetch.ts +232 -133
- package/src/codex/catalog/sync.ts +1 -1
- package/src/codex/convergence.ts +5 -0
- package/src/codex/shim.ts +56 -3
- package/src/config/provider-validation.ts +37 -0
- package/src/config.ts +78 -2
- package/src/generated/compatibility-version.json +187 -119
- package/src/generated/model-metadata.ts +3 -0
- package/src/images/loop.ts +37 -6
- package/src/lib/azure-identity.ts +154 -0
- package/src/lib/debug.ts +42 -0
- package/src/lib/errors.ts +14 -0
- package/src/lib/provider-outbound.ts +45 -33
- package/src/lib/provider-tls-profile.ts +309 -0
- package/src/lib/proxy-env.ts +49 -0
- package/src/lib/redact.ts +10 -1
- package/src/oauth/aistudio-native-daemon.ts +62 -0
- package/src/oauth/aistudio-session-sync.ts +95 -0
- package/src/oauth/antigravity-routing.ts +282 -236
- package/src/oauth/callback-server.ts +22 -2
- package/src/oauth/command-code.ts +5 -16
- package/src/oauth/google-aistudio-auth.ts +98 -0
- package/src/oauth/google-antigravity.ts +42 -5
- package/src/oauth/index.ts +15 -3
- package/src/oauth/key-providers.ts +8 -0
- package/src/oauth/kimi.ts +9 -1
- package/src/oauth/login-cli.ts +66 -1
- package/src/oauth/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +6 -0
- package/src/providers/antigravity-quota.ts +3 -1
- package/src/providers/api-keys.ts +2 -1
- package/src/providers/auto-compact-budget.ts +65 -0
- package/src/providers/derive.ts +5 -1
- package/src/providers/key-failover.ts +5 -1
- package/src/providers/openai-tiers.ts +5 -0
- package/src/providers/provider-id-rewrite.ts +1 -0
- package/src/providers/quota.ts +148 -50
- package/src/providers/registry.ts +27 -4
- package/src/providers/request-pacing.ts +33 -6
- package/src/providers/xai-transport.ts +21 -0
- package/src/responses/google-provider-options.ts +36 -0
- package/src/responses/namespace-tool-compat.ts +84 -4
- package/src/responses/parser.ts +11 -0
- package/src/responses/provider-opaque-metadata.ts +3 -3
- package/src/responses/schema.ts +37 -0
- package/src/responses/state.ts +94 -4
- package/src/router.ts +11 -2
- package/src/routing/account-pool/cooldown.ts +8 -0
- package/src/routing/account-pool/index.ts +1 -0
- package/src/server/aistudio-ws-hub.ts +295 -0
- package/src/server/auth-cors.ts +29 -0
- package/src/server/chat-completions.ts +2 -0
- package/src/server/images.ts +19 -35
- package/src/server/index.ts +94 -0
- package/src/server/management/agent-settings-routes.ts +205 -15
- package/src/server/management/combo-routes.ts +6 -0
- package/src/server/management/config-routes.ts +31 -5
- package/src/server/management/logs-usage-routes.ts +11 -5
- package/src/server/management/model-rows.ts +4 -0
- package/src/server/management/oauth-account-routes.ts +38 -7
- package/src/server/management/provider-routes.ts +113 -15
- package/src/server/management/routing-profile-routes.ts +3 -0
- package/src/server/port-reclaim.ts +19 -1
- package/src/server/request-log-conversation.ts +12 -0
- package/src/server/request-log.ts +23 -1
- package/src/server/responses/agent-task-recovery.ts +1 -1
- package/src/server/responses/compact.ts +30 -1
- package/src/server/responses/core.ts +363 -156
- package/src/server/responses/empty-completion-guard.ts +35 -6
- package/src/server/responses/fetch-helpers.ts +18 -5
- package/src/server/responses/policy-fallback.ts +1 -1
- package/src/server/responses/v2-native-parent-override.ts +59 -0
- package/src/server/responses/ws-upstream.ts +75 -2
- package/src/server/responses-undeclared-tool-guard.ts +90 -8
- package/src/server/ws-bridge.ts +2 -1
- package/src/service.ts +1 -1
- package/src/smoke/fingerprint-cache.ts +133 -0
- package/src/smoke/live-scenarios.ts +33 -0
- package/src/smoke/runner.ts +119 -0
- package/src/types/config.ts +16 -1
- package/src/types/provider.ts +18 -1
- package/src/types/request.ts +30 -0
- package/src/types/tools.ts +51 -0
- package/src/types.ts +6 -0
- package/src/usage/command-code-manifest.ts +116 -0
- package/src/usage/cost.ts +2 -2
- package/src/usage/expected-prices.ts +83 -0
- package/src/usage/log.ts +2 -2
- package/src/usage/summary.ts +34 -12
- package/src/web-search/gemini-executor.ts +6 -4
- package/src/web-search/index.ts +16 -8
- package/src/web-search/loop.ts +42 -6
- package/gui/dist/assets/index-BG43zwVe.js +0 -102
- package/gui/dist/assets/index-CiSI-jrP.css +0 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { loadConfig, resolveEnvValue } from "../config";
|
|
2
|
+
import { getCredential } from "../oauth/store";
|
|
3
|
+
import type { OAuthCredentials } from "../oauth/types";
|
|
4
|
+
import type { OcxProviderConfig } from "../types";
|
|
5
|
+
import { computeProviderSourceFingerprint, loadSmokeCache, recordSmokeResult, shouldRunSmokeForProvider } from "./fingerprint-cache";
|
|
6
|
+
import { buildSmokeScenarioRequest } from "./live-scenarios";
|
|
7
|
+
|
|
8
|
+
export interface ProviderSmokeResult {
|
|
9
|
+
provider: string;
|
|
10
|
+
modelId: string;
|
|
11
|
+
status: "passed" | "skipped" | "failed";
|
|
12
|
+
reason?: string;
|
|
13
|
+
level1Passed: boolean;
|
|
14
|
+
level2Passed: boolean;
|
|
15
|
+
level3Passed: boolean;
|
|
16
|
+
durationMs: number;
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function result(provider: string, modelId: string, started: number, extra: Partial<ProviderSmokeResult>): ProviderSmokeResult {
|
|
21
|
+
return { provider, modelId, status: "failed", level1Passed: false, level2Passed: false, level3Passed: false, durationMs: Date.now() - started, ...extra };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function providerHasSmokeCredential(
|
|
25
|
+
provider: Partial<Pick<OcxProviderConfig, "apiKey" | "authMode" | "headers">>,
|
|
26
|
+
credential?: OAuthCredentials | null,
|
|
27
|
+
): boolean {
|
|
28
|
+
if (resolveEnvValue(provider.apiKey)?.trim()) return true;
|
|
29
|
+
if (Object.entries(provider.headers ?? {}).some(([name, value]) => /authorization|cookie|api[-_]?key/i.test(name) && typeof value === "string" && value.trim().length > 0)) return true;
|
|
30
|
+
if (provider.authMode === "forward") return true;
|
|
31
|
+
return provider.authMode === "oauth" && Boolean(credential?.access?.trim() || credential?.refresh?.trim());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function classifyHttp(status: number, body: string): "not_authenticated" | "quota_exhausted" | undefined {
|
|
35
|
+
if (status === 401 || status === 403) return "not_authenticated";
|
|
36
|
+
if (status === 429 || /credit|quota|insufficient.?balance|billing/i.test(body)) return "quota_exhausted";
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function runProviderSmoke(options: { provider: string; modelId?: string; proxyUrl?: string; force?: boolean; cachePath?: string }): Promise<ProviderSmokeResult> {
|
|
41
|
+
const started = Date.now();
|
|
42
|
+
const config = loadConfig();
|
|
43
|
+
const providerConfig = config.providers[options.provider];
|
|
44
|
+
const modelId = options.modelId ?? config.subagentModels?.[0] ?? "gpt-5";
|
|
45
|
+
if (!providerConfig || providerConfig.disabled === true) return result(options.provider, modelId, started, { status: "skipped", reason: "not_authenticated" });
|
|
46
|
+
const credential = providerConfig.authMode === "oauth" ? getCredential(options.provider) : null;
|
|
47
|
+
if (!providerHasSmokeCredential(providerConfig, credential)) return result(options.provider, modelId, started, { status: "skipped", reason: "not_authenticated" });
|
|
48
|
+
const fingerprint = await computeProviderSourceFingerprint(options.provider);
|
|
49
|
+
const cache = await loadSmokeCache(options.cachePath);
|
|
50
|
+
if (!shouldRunSmokeForProvider(options.provider, fingerprint, { force: options.force, cache })) return result(options.provider, modelId, started, { status: "skipped", reason: "cached_pass" });
|
|
51
|
+
|
|
52
|
+
const baseUrl = options.proxyUrl ?? "http://127.0.0.1:10100/v1/responses";
|
|
53
|
+
let level1Passed = false, level2Passed = false, level3Passed = false;
|
|
54
|
+
let previousResponseId: string | undefined;
|
|
55
|
+
let emittedToolCallId: string | undefined;
|
|
56
|
+
try {
|
|
57
|
+
for (const level of [1, 2, 3] as const) {
|
|
58
|
+
const reqBody = buildSmokeScenarioRequest(level, modelId, {
|
|
59
|
+
previousResponseId,
|
|
60
|
+
toolCallId: emittedToolCallId,
|
|
61
|
+
toolResult: "smoke_test_123",
|
|
62
|
+
});
|
|
63
|
+
const response = await fetch(baseUrl, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "content-type": "application/json" },
|
|
66
|
+
body: JSON.stringify(reqBody),
|
|
67
|
+
signal: AbortSignal.timeout(30000),
|
|
68
|
+
});
|
|
69
|
+
const body = await response.text();
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const reason = classifyHttp(response.status, body);
|
|
72
|
+
if (reason) {
|
|
73
|
+
const skipped = result(options.provider, modelId, started, { status: "skipped", reason, level1Passed, level2Passed, level3Passed });
|
|
74
|
+
await recordSmokeResult(options.provider, { fingerprint, timestamp: Date.now(), status: "skipped", reason, modelsTested: [modelId] }, options.cachePath);
|
|
75
|
+
return skipped;
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`HTTP ${response.status}: ${body.slice(0, 200)}`);
|
|
78
|
+
}
|
|
79
|
+
const events = body.split(/\r?\n/).filter(line => line.startsWith("data: ")).flatMap(line => { try { return [JSON.parse(line.slice(6)) as Record<string, unknown>]; } catch { return []; } });
|
|
80
|
+
let jsonPayload: Record<string, unknown> | undefined;
|
|
81
|
+
try {
|
|
82
|
+
jsonPayload = JSON.parse(body) as Record<string, unknown>;
|
|
83
|
+
} catch {
|
|
84
|
+
jsonPayload = undefined;
|
|
85
|
+
}
|
|
86
|
+
const completed = events.find(event => event.type === "response.completed");
|
|
87
|
+
const responseData = (completed?.response as Record<string, unknown> | undefined) ?? (jsonPayload?.status === "completed" ? jsonPayload : undefined);
|
|
88
|
+
if (level === 1) level1Passed = events.some(event => event.type === "response.output_text.delta" || event.type === "response.output_item.added") || responseData?.status === "completed";
|
|
89
|
+
if (level === 2) {
|
|
90
|
+
const itemsFromEvents = events.flatMap(event => {
|
|
91
|
+
const item = event.item as Record<string, unknown> | undefined;
|
|
92
|
+
const output = (event.response as Record<string, unknown> | undefined)?.output;
|
|
93
|
+
return [item, ...(Array.isArray(output) ? output : [])].filter(value => value?.type === "function_call") as Record<string, unknown>[];
|
|
94
|
+
});
|
|
95
|
+
const itemsFromJson = Array.isArray(jsonPayload?.output) ? (jsonPayload!.output as Record<string, unknown>[]).filter(v => v?.type === "function_call") : [];
|
|
96
|
+
const calls = [...itemsFromEvents, ...itemsFromJson];
|
|
97
|
+
level2Passed = calls.some(call => {
|
|
98
|
+
try {
|
|
99
|
+
const rawArgs = typeof call.arguments === "string" ? JSON.parse(call.arguments) : call.arguments;
|
|
100
|
+
const args = rawArgs && typeof rawArgs === "object" ? rawArgs as Record<string, unknown> : {};
|
|
101
|
+
if (call.call_id || call.id) {
|
|
102
|
+
emittedToolCallId = String(call.call_id ?? call.id);
|
|
103
|
+
}
|
|
104
|
+
return typeof args.cmd === "string" && args.cmd.includes("echo") && args.cmd.includes("smoke_test_123");
|
|
105
|
+
} catch { return false; }
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (level === 3) level3Passed = (Boolean(completed) || responseData?.status === "completed") && !/400|thought.?signature|continuity/i.test(body);
|
|
109
|
+
if (responseData?.id) previousResponseId = String(responseData.id);
|
|
110
|
+
if (![level1Passed, level2Passed, level3Passed][level - 1]) throw new Error(`level ${level} assertion failed`);
|
|
111
|
+
}
|
|
112
|
+
await recordSmokeResult(options.provider, { fingerprint, timestamp: Date.now(), status: "passed", modelsTested: [modelId] }, options.cachePath);
|
|
113
|
+
return result(options.provider, modelId, started, { status: "passed", level1Passed, level2Passed, level3Passed });
|
|
114
|
+
} catch (error) {
|
|
115
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
116
|
+
await recordSmokeResult(options.provider, { fingerprint, timestamp: Date.now(), status: "failed", reason: message, modelsTested: [modelId] }, options.cachePath);
|
|
117
|
+
return result(options.provider, modelId, started, { status: "failed", level1Passed, level2Passed, level3Passed, error: message });
|
|
118
|
+
}
|
|
119
|
+
}
|
package/src/types/config.ts
CHANGED
|
@@ -259,6 +259,19 @@ export interface OcxConfig {
|
|
|
259
259
|
port: number;
|
|
260
260
|
/** Opt in to one identical-turn retry when a Responses completion has no text or tool call. */
|
|
261
261
|
emptyCompletionRetry?: boolean;
|
|
262
|
+
/**
|
|
263
|
+
* Whether a login may open a browser on the machine running the proxy.
|
|
264
|
+
*
|
|
265
|
+
* Absent and `true` both mean "open", which is what every existing install
|
|
266
|
+
* already does. Only an explicit `false` declines — for an operator who wants
|
|
267
|
+
* to paste the authorization URL into a different browser profile, or who is
|
|
268
|
+
* driving the dashboard from a different machine than the proxy.
|
|
269
|
+
*
|
|
270
|
+
* Deliberately a boolean and not an "auto" mode: inferring headlessness from
|
|
271
|
+
* SSH_CONNECTION or a missing DISPLAY breaks a working login silently when
|
|
272
|
+
* the guess is wrong.
|
|
273
|
+
*/
|
|
274
|
+
oauthOpenBrowser?: boolean;
|
|
262
275
|
/** Maximum usage-log bytes read for one management snapshot. */
|
|
263
276
|
managementUsageMaxReadBytes?: number;
|
|
264
277
|
providers: Record<string, OcxProviderConfig>;
|
|
@@ -455,10 +468,12 @@ export interface OcxConfig {
|
|
|
455
468
|
* Routed parents get v2 tools; Sol/Terra can still spawn Grok/Claude (issue #92).
|
|
456
469
|
*/
|
|
457
470
|
keepNativeChatGptOnV1?: boolean;
|
|
471
|
+
/** Experimental routed target for eligible native V2 root parents. */
|
|
472
|
+
v2NativeParentOverride?: { enabled?: boolean; model?: string };
|
|
458
473
|
/** Experimental, default-off ChatGPT recovery for encrypted V2 routed tasks. */
|
|
459
474
|
agentTaskRecovery?: {
|
|
460
475
|
enabled?: boolean;
|
|
461
|
-
/** ChatGPT model used by the recovery request. Default: gpt-5.6-
|
|
476
|
+
/** ChatGPT model used by the recovery request. Default: gpt-5.6-luna. */
|
|
462
477
|
model?: string;
|
|
463
478
|
/** Recovery request timeout in milliseconds. Default: 45000. */
|
|
464
479
|
timeoutMs?: number;
|
package/src/types/provider.ts
CHANGED
|
@@ -8,6 +8,8 @@ import type { UpstreamHttpVersion, ReasoningSummaryDelivery, CodexAccountMode }
|
|
|
8
8
|
*/
|
|
9
9
|
export type RefreshPolicy = "proactive" | "lazy-only" | "disabled";
|
|
10
10
|
|
|
11
|
+
export type ProviderTlsProfile = "antigravity-browser";
|
|
12
|
+
|
|
11
13
|
export interface OpenRouterProviderRouting {
|
|
12
14
|
/** OpenRouter provider slugs to try first, in priority order. */
|
|
13
15
|
order?: string[];
|
|
@@ -68,6 +70,8 @@ export interface RequestPacingRule {
|
|
|
68
70
|
requestsPerMinute?: number;
|
|
69
71
|
/** Minimum delay between request starts. The slower configured value wins. */
|
|
70
72
|
minIntervalMs?: number;
|
|
73
|
+
/** Positive-only random delay added to each request-start slot. */
|
|
74
|
+
jitterMs?: number;
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
export interface ProviderRequestPacingConfig extends RequestPacingRule {
|
|
@@ -136,6 +140,8 @@ export interface OcxProviderConfig {
|
|
|
136
140
|
codexToolMode?: "code_mode_only" | "shell";
|
|
137
141
|
/** Optional outbound request-start pacing shared by this provider and its model overrides. */
|
|
138
142
|
requestPacing?: ProviderRequestPacingConfig;
|
|
143
|
+
/** Explicitly acknowledged experimental browser-compatible transport profile. */
|
|
144
|
+
tlsProfile?: ProviderTlsProfile;
|
|
139
145
|
/** Cursor MCP compatibility bounds; positive integers when configured. */
|
|
140
146
|
mcpMaxTools?: number;
|
|
141
147
|
mcpMaxSchemaBytes?: number;
|
|
@@ -245,6 +251,11 @@ export interface OcxProviderConfig {
|
|
|
245
251
|
*/
|
|
246
252
|
codexAccountMode?: CodexAccountMode;
|
|
247
253
|
apiKey?: string;
|
|
254
|
+
/** Azure OpenAI identity authentication; mutually exclusive with API-key fields. */
|
|
255
|
+
azureCredential?: {
|
|
256
|
+
type: "default-azure-credential";
|
|
257
|
+
managedIdentityClientId?: string;
|
|
258
|
+
};
|
|
248
259
|
/**
|
|
249
260
|
* Key-auth header style for Anthropic-compatible providers.
|
|
250
261
|
* Defaults to the native Anthropic `x-api-key`; gateways may require
|
|
@@ -281,6 +292,11 @@ export interface OcxProviderConfig {
|
|
|
281
292
|
modelInputModalities?: Record<string, string[]>;
|
|
282
293
|
/** Model-specific max input token limits. Values cap auto_compact_token_limit. */
|
|
283
294
|
modelMaxInputTokens?: Record<string, number>;
|
|
295
|
+
/**
|
|
296
|
+
* Per-model soft compaction budgets. Values may only lower the effective
|
|
297
|
+
* context/max-input envelope; they never raise hard admission limits.
|
|
298
|
+
*/
|
|
299
|
+
modelAutoCompactTokenLimits?: Record<string, number>;
|
|
284
300
|
/**
|
|
285
301
|
* Provider-wide fallback for chat-completions `max_tokens` when the caller omits
|
|
286
302
|
* Responses `max_output_tokens`. Adapters still let an explicit request win.
|
|
@@ -510,8 +526,9 @@ export interface OcxProviderConfig {
|
|
|
510
526
|
* Google adapter mode. "ai-studio" (default) = Generative Language API + x-goog-api-key.
|
|
511
527
|
* "vertex" = Vertex AI project/location endpoints with GCP ADC (or x-goog-api-key).
|
|
512
528
|
* "cloud-code-assist" = Google Antigravity (Cloud Code Assist) OAuth + CCA envelope.
|
|
529
|
+
* "ai-studio-web" = browser-relayed AI Studio Playground/Build session.
|
|
513
530
|
*/
|
|
514
|
-
googleMode?: "ai-studio" | "vertex" | "cloud-code-assist";
|
|
531
|
+
googleMode?: "ai-studio" | "vertex" | "cloud-code-assist" | "ai-studio-web";
|
|
515
532
|
/** Vertex AI GCP project id (or GOOGLE_CLOUD_PROJECT / GCLOUD_PROJECT env). */
|
|
516
533
|
project?: string;
|
|
517
534
|
/** Vertex AI location, e.g. "us-central1" or "global" (or GOOGLE_CLOUD_LOCATION env). */
|
package/src/types/request.ts
CHANGED
|
@@ -68,6 +68,10 @@ export interface OcxParsedRequest {
|
|
|
68
68
|
_cursorConversationId?: string;
|
|
69
69
|
/** Stable upstream client thread identity, used only to derive provider-scoped continuation ids. */
|
|
70
70
|
_clientThreadId?: string;
|
|
71
|
+
/** True when promptCacheKey is a shared cache cohort rather than a conversation identity. */
|
|
72
|
+
_promptCacheKeyIsSharedCohort?: boolean;
|
|
73
|
+
/** Provider-private Command Code session affinity id, stable across in-process request mutation. */
|
|
74
|
+
_commandCodeSessionId?: string;
|
|
71
75
|
/** Conversation/provider/account/model-bound namespace for reasoning replay state. */
|
|
72
76
|
_reasoningReplayScope?: OcxReasoningReplayScopeRef;
|
|
73
77
|
/**
|
|
@@ -271,6 +275,32 @@ export interface OcxRequestOptions {
|
|
|
271
275
|
schema?: Record<string, unknown>;
|
|
272
276
|
strict?: boolean;
|
|
273
277
|
};
|
|
278
|
+
providerOptions?: { google?: GoogleProviderOptions };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export type GoogleSafetyCategory =
|
|
282
|
+
| "HARM_CATEGORY_HATE_SPEECH"
|
|
283
|
+
| "HARM_CATEGORY_SEXUALLY_EXPLICIT"
|
|
284
|
+
| "HARM_CATEGORY_DANGEROUS_CONTENT"
|
|
285
|
+
| "HARM_CATEGORY_HARASSMENT"
|
|
286
|
+
| "HARM_CATEGORY_CIVIC_INTEGRITY"
|
|
287
|
+
| "HARM_CATEGORY_JAILBREAK";
|
|
288
|
+
export type GoogleSafetyThreshold =
|
|
289
|
+
| "HARM_BLOCK_THRESHOLD_UNSPECIFIED"
|
|
290
|
+
| "BLOCK_LOW_AND_ABOVE"
|
|
291
|
+
| "BLOCK_MEDIUM_AND_ABOVE"
|
|
292
|
+
| "BLOCK_ONLY_HIGH"
|
|
293
|
+
| "BLOCK_NONE"
|
|
294
|
+
| "OFF";
|
|
295
|
+
export interface GoogleSafetySetting {
|
|
296
|
+
category: GoogleSafetyCategory;
|
|
297
|
+
threshold: GoogleSafetyThreshold;
|
|
298
|
+
}
|
|
299
|
+
export interface GoogleProviderOptions {
|
|
300
|
+
thinkingBudget?: number;
|
|
301
|
+
includeThoughts?: boolean;
|
|
302
|
+
safetySettings?: GoogleSafetySetting[];
|
|
303
|
+
cachedContent?: string;
|
|
274
304
|
}
|
|
275
305
|
|
|
276
306
|
export type OcxMessagePhase = "commentary" | "final_answer";
|
package/src/types/tools.ts
CHANGED
|
@@ -31,6 +31,57 @@ export function namespacedToolName(namespace: string | undefined, name: string):
|
|
|
31
31
|
return namespace ? `${namespace}__${name}` : name;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Codex 0.149 unified-exec name normalization.
|
|
36
|
+
*
|
|
37
|
+
* Codex's code-mode shell tool is declared as `exec` (a freeform custom tool whose own
|
|
38
|
+
* description mentions the nested `await tools.exec_command(...)` helper). Routed models —
|
|
39
|
+
* DeepSeek in particular — sometimes echo that helper name as the tool-call name, emitting
|
|
40
|
+
* `exec_command` instead of the declared `exec`. Accept the legacy shell bridge names only
|
|
41
|
+
* when the request catalog actually declares `exec` and does not itself declare the legacy
|
|
42
|
+
* name (an MCP server may legitimately advertise `exec_command` under its own namespace).
|
|
43
|
+
*/
|
|
44
|
+
const LEGACY_SHELL_BRIDGE_TOOL_NAMES = ["exec_command", "shell_command"] as const;
|
|
45
|
+
|
|
46
|
+
export function normalizeDeclaredToolName(
|
|
47
|
+
name: string,
|
|
48
|
+
declared: ReadonlySet<string> | undefined,
|
|
49
|
+
): string {
|
|
50
|
+
if (!declared) return name;
|
|
51
|
+
if (declared.has(name)) return name;
|
|
52
|
+
if (declared.has("exec")) {
|
|
53
|
+
// When the catalog explicitly declares any legacy shell bridge name, the environment
|
|
54
|
+
// genuinely exposes that tool — turn normalization off so a call is never mis-routed
|
|
55
|
+
// to exec.
|
|
56
|
+
if ((LEGACY_SHELL_BRIDGE_TOOL_NAMES as readonly string[]).some(legacy => declared.has(legacy))) {
|
|
57
|
+
return name;
|
|
58
|
+
}
|
|
59
|
+
if ((LEGACY_SHELL_BRIDGE_TOOL_NAMES as readonly string[]).includes(name)) {
|
|
60
|
+
return "exec";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// When a model strips the namespace prefix (e.g. Gemini calling bare exec for default_api:exec),
|
|
64
|
+
// or replaces non-alphanumeric separators with underscores, resolve it if and only if exactly
|
|
65
|
+
// one declared tool matches.
|
|
66
|
+
{
|
|
67
|
+
let matched: string | undefined;
|
|
68
|
+
for (const dec of declared) {
|
|
69
|
+
const matchesSuffix = !name.includes(":") && !name.includes("__") && (dec.endsWith(":" + name) || dec.endsWith("__" + name));
|
|
70
|
+
const matchesSanitized = dec.replace(/[^A-Za-z0-9_-]/g, "_") === name;
|
|
71
|
+
if (matchesSuffix || matchesSanitized) {
|
|
72
|
+
if (matched !== undefined) {
|
|
73
|
+
return name;
|
|
74
|
+
}
|
|
75
|
+
matched = dec;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (matched !== undefined) {
|
|
79
|
+
return matched;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return name;
|
|
83
|
+
}
|
|
84
|
+
|
|
34
85
|
export function toolChoiceAliases(tool: Pick<OcxTool, "namespace" | "name">): string[] {
|
|
35
86
|
const wireName = namespacedToolName(tool.namespace, tool.name);
|
|
36
87
|
return tool.namespace ? [wireName, `${tool.namespace}.${tool.name}`] : [wireName];
|
package/src/types.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
export type { OcxTool, OcxToolChoice } from "./types/tools";
|
|
5
5
|
export {
|
|
6
6
|
namespacedToolName,
|
|
7
|
+
normalizeDeclaredToolName,
|
|
7
8
|
toolChoiceAliases,
|
|
8
9
|
createToolChoiceResolver,
|
|
9
10
|
toolChoiceCandidates,
|
|
@@ -43,6 +44,10 @@ export type {
|
|
|
43
44
|
OcxProviderOpaqueToolCallMetadata,
|
|
44
45
|
OcxAssistantContentPart,
|
|
45
46
|
OcxRequestOptions,
|
|
47
|
+
GoogleProviderOptions,
|
|
48
|
+
GoogleSafetySetting,
|
|
49
|
+
GoogleSafetyCategory,
|
|
50
|
+
GoogleSafetyThreshold,
|
|
46
51
|
OcxMessagePhase,
|
|
47
52
|
OcxProviderContinuationOwner,
|
|
48
53
|
OcxProviderContinuationState,
|
|
@@ -86,6 +91,7 @@ export type {
|
|
|
86
91
|
|
|
87
92
|
export type {
|
|
88
93
|
RefreshPolicy,
|
|
94
|
+
ProviderTlsProfile,
|
|
89
95
|
OpenRouterProviderRouting,
|
|
90
96
|
ResponsesItemIdRepairConfig,
|
|
91
97
|
RateLimitRetryPolicy,
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Cost4, ExpectedPriceOverlay } from "./expected-prices";
|
|
2
|
+
|
|
3
|
+
export interface CommandCodeModelPricing {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
slug?: string;
|
|
7
|
+
contextWindow?: number;
|
|
8
|
+
cost4: Cost4;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const COMMAND_CODE_MODELS_DATA_URL = "https://commandcode.ai/models.data";
|
|
12
|
+
export const COMMAND_CODE_PRICING_SOURCE = "https://commandcode.ai/models + https://commandcode.ai/models.data";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Parse Command Code models and 4-tuple per-1M token rates from the Turbo-stream
|
|
16
|
+
* payload served by https://commandcode.ai/models.data.
|
|
17
|
+
*/
|
|
18
|
+
export function parseCommandCodeModelsData(raw: unknown): CommandCodeModelPricing[] {
|
|
19
|
+
if (!Array.isArray(raw) || raw.length < 10) return [];
|
|
20
|
+
const modelIndices = raw[9];
|
|
21
|
+
if (!Array.isArray(modelIndices)) return [];
|
|
22
|
+
|
|
23
|
+
const resolve = (val: unknown): unknown => {
|
|
24
|
+
if (typeof val === "number") {
|
|
25
|
+
if (val < 0) return val === -5 ? null : undefined;
|
|
26
|
+
if (val < raw.length) return raw[val];
|
|
27
|
+
}
|
|
28
|
+
return val;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const results: CommandCodeModelPricing[] = [];
|
|
32
|
+
for (const idx of modelIndices) {
|
|
33
|
+
if (typeof idx !== "number" || idx < 0 || idx >= raw.length) continue;
|
|
34
|
+
const obj = raw[idx];
|
|
35
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) continue;
|
|
36
|
+
|
|
37
|
+
const fields: Record<string, unknown> = {};
|
|
38
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
39
|
+
if (!k.startsWith("_")) continue;
|
|
40
|
+
const keyIdx = Number.parseInt(k.slice(1), 10);
|
|
41
|
+
if (!Number.isFinite(keyIdx) || keyIdx < 0 || keyIdx >= raw.length) continue;
|
|
42
|
+
const keyName = raw[keyIdx];
|
|
43
|
+
if (typeof keyName === "string" && keyName.length > 0) {
|
|
44
|
+
fields[keyName] = resolve(v);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const id = typeof fields.id === "string" ? fields.id.trim() : "";
|
|
49
|
+
if (!id) continue;
|
|
50
|
+
|
|
51
|
+
const name = typeof fields.name === "string" && fields.name.trim() ? fields.name.trim() : id;
|
|
52
|
+
const slug = typeof fields.slug === "string" && fields.slug.trim() ? fields.slug.trim() : undefined;
|
|
53
|
+
const contextWindow = typeof fields.contextWindow === "number" && Number.isFinite(fields.contextWindow)
|
|
54
|
+
? fields.contextWindow
|
|
55
|
+
: undefined;
|
|
56
|
+
|
|
57
|
+
const input = typeof fields.inputCost === "number" && Number.isFinite(fields.inputCost) && fields.inputCost >= 0
|
|
58
|
+
? fields.inputCost
|
|
59
|
+
: 0;
|
|
60
|
+
const output = typeof fields.outputCost === "number" && Number.isFinite(fields.outputCost) && fields.outputCost >= 0
|
|
61
|
+
? fields.outputCost
|
|
62
|
+
: 0;
|
|
63
|
+
const cacheRead = typeof fields.cacheReadCost === "number" && Number.isFinite(fields.cacheReadCost) && fields.cacheReadCost >= 0
|
|
64
|
+
? fields.cacheReadCost
|
|
65
|
+
: 0;
|
|
66
|
+
const cacheWrite = typeof fields.cacheWriteCost === "number" && Number.isFinite(fields.cacheWriteCost) && fields.cacheWriteCost >= 0
|
|
67
|
+
? fields.cacheWriteCost
|
|
68
|
+
: 0;
|
|
69
|
+
|
|
70
|
+
results.push({
|
|
71
|
+
id,
|
|
72
|
+
name,
|
|
73
|
+
...(slug ? { slug } : {}),
|
|
74
|
+
...(contextWindow !== undefined ? { contextWindow } : {}),
|
|
75
|
+
cost4: { input, output, cacheRead, cacheWrite },
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return results;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Fetch and decode the latest Command Code model pricing from commandcode.ai.
|
|
84
|
+
*/
|
|
85
|
+
export async function fetchCommandCodeModelPricing(options?: {
|
|
86
|
+
url?: string;
|
|
87
|
+
signal?: AbortSignal;
|
|
88
|
+
fetchFn?: typeof fetch;
|
|
89
|
+
}): Promise<CommandCodeModelPricing[]> {
|
|
90
|
+
const fetcher = options?.fetchFn ?? fetch;
|
|
91
|
+
const url = options?.url ?? COMMAND_CODE_MODELS_DATA_URL;
|
|
92
|
+
const res = await fetcher(url, { signal: options?.signal });
|
|
93
|
+
if (!res.ok) throw new Error(`Failed to fetch Command Code models data: ${res.status}`);
|
|
94
|
+
const data = await res.json();
|
|
95
|
+
return parseCommandCodeModelsData(data);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Convert parsed Command Code models to opencodex ExpectedPriceOverlay entries.
|
|
100
|
+
*/
|
|
101
|
+
export function commandCodePricingToExpectedOverlays(
|
|
102
|
+
models: readonly CommandCodeModelPricing[],
|
|
103
|
+
verifiedAt = "2026-08-26",
|
|
104
|
+
): ExpectedPriceOverlay[] {
|
|
105
|
+
return models
|
|
106
|
+
.filter(m => m.cost4.input > 0 || m.cost4.output > 0 || m.cost4.cacheRead > 0 || m.cost4.cacheWrite > 0)
|
|
107
|
+
.map(m => ({
|
|
108
|
+
provider: "command-code",
|
|
109
|
+
modelId: m.id,
|
|
110
|
+
cost4: m.cost4,
|
|
111
|
+
source: COMMAND_CODE_PRICING_SOURCE,
|
|
112
|
+
verifiedAt,
|
|
113
|
+
status: "verified",
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
|
package/src/usage/cost.ts
CHANGED
|
@@ -253,7 +253,7 @@ function resolveMatchedPriceExact(
|
|
|
253
253
|
const verifiedOverride = overlays === EXPECTED_PRICE_OVERLAYS
|
|
254
254
|
? findVerifiedPriceOverride(provider, modelId)
|
|
255
255
|
: undefined;
|
|
256
|
-
if (verifiedOverride && validCost4(verifiedOverride.cost4) && hasNonZeroCost(verifiedOverride.cost4)) {
|
|
256
|
+
if (verifiedOverride && verifiedOverride.status !== "unverified" && validCost4(verifiedOverride.cost4) && hasNonZeroCost(verifiedOverride.cost4)) {
|
|
257
257
|
return {
|
|
258
258
|
provider,
|
|
259
259
|
modelId,
|
|
@@ -261,7 +261,7 @@ function resolveMatchedPriceExact(
|
|
|
261
261
|
source: "expected",
|
|
262
262
|
sourceRef: verifiedOverride.source,
|
|
263
263
|
verifiedAt: verifiedOverride.verifiedAt,
|
|
264
|
-
status:
|
|
264
|
+
status: verifiedOverride.status,
|
|
265
265
|
};
|
|
266
266
|
}
|
|
267
267
|
const metadataProvider = resolveMetadataProvider(provider);
|
|
@@ -89,6 +89,17 @@ const KIMI_PRICING = "https://platform.kimi.ai/docs/pricing (official table; cac
|
|
|
89
89
|
// anywhere. Cache stays 0 rather than inheriting the reseller's 0.15 — a reseller number
|
|
90
90
|
// under a vendor-price label would be a wrong value wearing a verified badge.
|
|
91
91
|
const QWEN38_MAX_PRICING = "https://qwen.ai/blog?id=qwen3.8 (Qwen release announcement; no Model Studio billing row yet; cache rates unpublished -> 0)";
|
|
92
|
+
const COMMAND_CODE_PRICING = "https://commandcode.ai/models + https://commandcode.ai/models.data (official model manifest)";
|
|
93
|
+
const COMMAND_CODE_VERIFIED_AT = "2026-08-26";
|
|
94
|
+
const CURSOR_DOCS_PRICING = "https://cursor.com/docs/models-and-pricing";
|
|
95
|
+
const CURSOR_GROK_46: Cost4 = { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 };
|
|
96
|
+
const CURSOR_GROK_45: Cost4 = { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 };
|
|
97
|
+
const CURSOR_COMPOSER_1: Cost4 = { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 };
|
|
98
|
+
const CURSOR_COMPOSER_25: Cost4 = { input: 0.5, output: 2.5, cacheRead: 0.2, cacheWrite: 0 };
|
|
99
|
+
const CURSOR_COMPOSER_25_FAST: Cost4 = { input: 3, output: 15, cacheRead: 0.5, cacheWrite: 0 };
|
|
100
|
+
const CURSOR_GROK_46_FAST: Cost4 = { input: 4, output: 12, cacheRead: 1, cacheWrite: 0 };
|
|
101
|
+
const CURSOR_GROK_45_FAST: Cost4 = { input: 4, output: 18, cacheRead: 1, cacheWrite: 0 };
|
|
102
|
+
const CLAUDE_OPUS_FAST: Cost4 = { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 };
|
|
92
103
|
|
|
93
104
|
export const EXPECTED_PRICE_OVERLAYS: readonly ExpectedPriceOverlay[] = [
|
|
94
105
|
// claude-opus-5 is exposed by three providers but absent from the jawcode bundle, so
|
|
@@ -179,6 +190,16 @@ export const EXPECTED_PRICE_OVERLAYS: readonly ExpectedPriceOverlay[] = [
|
|
|
179
190
|
{ provider: "alibaba-token-plan-intl", modelId: "qwen3.8-max", cost4: QWEN38_MAX, source: QWEN38_MAX_PRICING, verifiedAt: "2026-08-04", status: "verified" },
|
|
180
191
|
// Cursor Auto router — Cursor's published fixed token price (verified).
|
|
181
192
|
{ provider: "cursor", modelId: "auto", cost4: { input: 1.25, output: 6, cacheRead: 0.25, cacheWrite: 1.25 }, source: "https://docs.cursor.com/account/pricing + https://cursor.com/blog/aug-2025-pricing", verifiedAt: "2026-07-20", status: "verified" },
|
|
193
|
+
// Cursor-specific native models (verified from official docs).
|
|
194
|
+
{ provider: "cursor", modelId: "grok-4.6", cost4: CURSOR_GROK_46, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
195
|
+
{ provider: "cursor", modelId: "grok-4.5", cost4: CURSOR_GROK_45, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
196
|
+
{ provider: "cursor", modelId: "composer-1", cost4: CURSOR_COMPOSER_1, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
197
|
+
{ provider: "cursor", modelId: "composer-2.5", cost4: CURSOR_COMPOSER_25, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
198
|
+
{ provider: "cursor", modelId: "composer-2.5-fast", cost4: CURSOR_COMPOSER_25_FAST, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
199
|
+
{ provider: "cursor", modelId: "grok-4.6-fast", cost4: CURSOR_GROK_46_FAST, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
200
|
+
{ provider: "cursor", modelId: "grok-4.5-fast", cost4: CURSOR_GROK_45_FAST, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
201
|
+
{ provider: "cursor", modelId: "claude-opus-5-fast", cost4: CLAUDE_OPUS_FAST, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
202
|
+
{ provider: "cursor", modelId: "claude-opus-4-8-fast", cost4: CLAUDE_OPUS_FAST, source: CURSOR_DOCS_PRICING, verifiedAt: "2026-08-26", status: "verified" },
|
|
182
203
|
];
|
|
183
204
|
|
|
184
205
|
/**
|
|
@@ -195,6 +216,68 @@ export const VERIFIED_PRICE_OVERRIDES: readonly ExpectedPriceOverlay[] = [
|
|
|
195
216
|
verifiedAt: "2026-08-18",
|
|
196
217
|
status: "verified",
|
|
197
218
|
},
|
|
219
|
+
// Command Code official model catalog rates (sourced from https://commandcode.ai/models.data).
|
|
220
|
+
{ provider: "command-code", modelId: "zai-org/GLM-5.3", cost4: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
221
|
+
{ provider: "command-code", modelId: "zai-org/glm-5.3", cost4: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified-derived" },
|
|
222
|
+
{ provider: "command-code", modelId: "zai-org/GLM-5.2", cost4: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
223
|
+
{ provider: "command-code", modelId: "zai-org/glm-5.2", cost4: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified-derived" },
|
|
224
|
+
{ provider: "command-code", modelId: "zai-org/GLM-5.2-Fast", cost4: { input: 3, output: 10.25, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
225
|
+
{ provider: "command-code", modelId: "zai-org/glm-5.2-fast", cost4: { input: 3, output: 10.25, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified-derived" },
|
|
226
|
+
{ provider: "command-code", modelId: "zai-org/GLM-5.1", cost4: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
227
|
+
{ provider: "command-code", modelId: "zai-org/glm-5.1", cost4: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified-derived" },
|
|
228
|
+
{ provider: "command-code", modelId: "zai-org/GLM-5", cost4: { input: 1, output: 3.2, cacheRead: 0.2, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
229
|
+
{ provider: "command-code", modelId: "zai-org/glm-5", cost4: { input: 1, output: 3.2, cacheRead: 0.2, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified-derived" },
|
|
230
|
+
{ provider: "command-code", modelId: "meta/muse-spark-1.2-contributor", cost4: { input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
231
|
+
{ provider: "command-code", modelId: "meta/muse-spark-1.2", cost4: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
232
|
+
{ provider: "command-code", modelId: "meta/muse-spark-1.1", cost4: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
233
|
+
{ provider: "command-code", modelId: "google/gemini-3.7-flash", cost4: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.04167 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
234
|
+
{ provider: "command-code", modelId: "google/gemini-3.6-flash", cost4: { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
235
|
+
{ provider: "command-code", modelId: "google/gemini-3.5-flash", cost4: { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
236
|
+
{ provider: "command-code", modelId: "google/gemini-3.5-flash-lite", cost4: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
237
|
+
{ provider: "command-code", modelId: "google/gemini-3.1-flash-lite", cost4: { input: 0.25, output: 1.5, cacheRead: 0.03, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
238
|
+
{ provider: "command-code", modelId: "deepseek/deepseek-v4-pro", cost4: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
239
|
+
{ provider: "command-code", modelId: "deepseek/deepseek-v4-flash", cost4: { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
240
|
+
{ provider: "command-code", modelId: "deepseek/deepseek-v4-flash-vision-exp", cost4: { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
241
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.8-Max", cost4: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
242
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.8-27B", cost4: { input: 0.4, output: 3, cacheRead: 0.04, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
243
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.7-Max", cost4: { input: 2.5, output: 7.5, cacheRead: 0.5, cacheWrite: 3.13 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
244
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.7-Plus", cost4: { input: 0.4, output: 1.6, cacheRead: 0.08, cacheWrite: 0.5 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
245
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.7-Flash", cost4: { input: 0.03, output: 0.13, cacheRead: 0.006, cacheWrite: 0.038 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
246
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.6-Max-Preview", cost4: { input: 1.3, output: 7.8, cacheRead: 0.26, cacheWrite: 1.63 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
247
|
+
{ provider: "command-code", modelId: "Qwen/Qwen3.6-Plus", cost4: { input: 0.5, output: 3, cacheRead: 0.1, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
248
|
+
{ provider: "command-code", modelId: "MiniMaxAI/MiniMax-M3", cost4: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
249
|
+
{ provider: "command-code", modelId: "MiniMaxAI/MiniMax-M2.7", cost4: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
250
|
+
{ provider: "command-code", modelId: "MiniMaxAI/MiniMax-M2.5", cost4: { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
251
|
+
{ provider: "command-code", modelId: "stepfun/Step-3.7-Flash", cost4: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
252
|
+
{ provider: "command-code", modelId: "stepfun/Step-3.5-Flash", cost4: { input: 0.1, output: 0.3, cacheRead: 0.02, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
253
|
+
{ provider: "command-code", modelId: "xiaomi/mimo-v2.5-pro", cost4: { input: 0.435, output: 0.87, cacheRead: 0.0036, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
254
|
+
{ provider: "command-code", modelId: "xiaomi/mimo-v2.5", cost4: { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
255
|
+
{ provider: "command-code", modelId: "nvidia/nemotron-3-ultra-550b-a55b", cost4: { input: 0.6, output: 2.4, cacheRead: 0.12, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
256
|
+
{ provider: "command-code", modelId: "tencent/hy3-paid", cost4: { input: 0.14, output: 0.58, cacheRead: 0.035, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
257
|
+
{ provider: "command-code", modelId: "moonshotai/Kimi-K3", cost4: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
258
|
+
{ provider: "command-code", modelId: "moonshotai/Kimi-K2.7-Code", cost4: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
259
|
+
{ provider: "command-code", modelId: "moonshotai/Kimi-K2.7-Code-Highspeed", cost4: { input: 1.9, output: 8, cacheRead: 0.38, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
260
|
+
{ provider: "command-code", modelId: "moonshotai/Kimi-K2.6", cost4: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
261
|
+
{ provider: "command-code", modelId: "moonshotai/Kimi-K2.5", cost4: { input: 0.6, output: 3, cacheRead: 0.1, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
262
|
+
{ provider: "command-code", modelId: "claude-fable-5", cost4: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
263
|
+
{ provider: "command-code", modelId: "claude-opus-5", cost4: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
264
|
+
{ provider: "command-code", modelId: "claude-opus-4-8", cost4: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
265
|
+
{ provider: "command-code", modelId: "claude-opus-4-7", cost4: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
266
|
+
{ provider: "command-code", modelId: "claude-sonnet-5", cost4: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
267
|
+
{ provider: "command-code", modelId: "claude-sonnet-4-6", cost4: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
268
|
+
{ provider: "command-code", modelId: "claude-haiku-4-5", cost4: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
269
|
+
{ provider: "command-code", modelId: "gpt-5.6-sol", cost4: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
270
|
+
{ provider: "command-code", modelId: "gpt-5.6-terra", cost4: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
271
|
+
{ provider: "command-code", modelId: "gpt-5.6-luna", cost4: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
272
|
+
{ provider: "command-code", modelId: "gpt-5.5", cost4: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
273
|
+
{ provider: "command-code", modelId: "gpt-5.4", cost4: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
274
|
+
{ provider: "command-code", modelId: "gpt-5.4-mini", cost4: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
275
|
+
{ provider: "command-code", modelId: "gpt-5.3-codex", cost4: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
276
|
+
{ provider: "command-code", modelId: "sakana/fugu-ultra", cost4: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
277
|
+
{ provider: "command-code", modelId: "xai/grok-4.6", cost4: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
278
|
+
{ provider: "command-code", modelId: "xai/grok-4.5", cost4: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
279
|
+
{ provider: "command-code", modelId: "thinkingmachines/inkling", cost4: { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
280
|
+
{ provider: "command-code", modelId: "thinkingmachines/inkling-small", cost4: { input: 0.5, output: 1.2, cacheRead: 0.1, cacheWrite: 0 }, source: COMMAND_CODE_PRICING, verifiedAt: COMMAND_CODE_VERIFIED_AT, status: "verified" },
|
|
198
281
|
];
|
|
199
282
|
|
|
200
283
|
export function findVerifiedPriceOverride(
|
package/src/usage/log.ts
CHANGED
|
@@ -52,7 +52,7 @@ export interface PersistedUsageAttempt {
|
|
|
52
52
|
sendCount: number;
|
|
53
53
|
recoveryKinds: AttemptRecoveryKind[];
|
|
54
54
|
usageStatus: UsageStatus;
|
|
55
|
-
/** Stable non-PII identity for the
|
|
55
|
+
/** Stable non-PII identity for the account that served this attempt. */
|
|
56
56
|
accountLogLabel?: CodexUsageAccountLogLabel;
|
|
57
57
|
inputTokenEstimate?: number;
|
|
58
58
|
usage?: OcxUsage;
|
|
@@ -81,7 +81,7 @@ export interface PersistedUsageEntry {
|
|
|
81
81
|
admissionKind?: "configured" | "environment" | "loopback";
|
|
82
82
|
/** The inbound wire, not the client product — see `surface`. */
|
|
83
83
|
inboundProtocol?: "responses" | "chat" | "messages";
|
|
84
|
-
/** Stable non-PII identity for
|
|
84
|
+
/** Stable non-PII identity for account usage; absent for unauthenticated traffic. */
|
|
85
85
|
accountLogLabel?: CodexUsageAccountLogLabel;
|
|
86
86
|
/** Best-effort chat/session correlation for Logs grouping (#330). */
|
|
87
87
|
conversationId?: string;
|