@bitkyc08/opencodex 2.87.0 → 2.89.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.
- package/README.md +11 -1
- package/bin/ocx.mjs +15 -4
- package/gui/dist/assets/App-BnRSujOq.js +58 -0
- package/gui/dist/assets/App-dnkJ85te.css +1 -0
- package/gui/dist/assets/{Tray-DCd-A1az.js → Tray-7z1COnmz.js} +1 -1
- package/gui/dist/assets/index-uchD-ngf.js +94 -0
- package/gui/dist/assets/{quota-summary-ChvmKGOk.js → quota-summary-BY_10IEz.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapters/anthropic/cache-retention.ts +117 -0
- package/src/adapters/anthropic/passthrough.ts +7 -4
- package/src/adapters/anthropic-rejection-memo.ts +71 -0
- package/src/adapters/anthropic-replay.ts +135 -0
- package/src/adapters/anthropic-tool-catalog.ts +11 -0
- package/src/adapters/anthropic.ts +86 -48
- package/src/adapters/coding-agent/protocol.ts +6 -0
- package/src/adapters/google-http.ts +3 -2
- package/src/adapters/google-progress-history.ts +53 -0
- package/src/adapters/google-vertex-endpoint.ts +67 -0
- package/src/adapters/google.ts +52 -30
- package/src/adapters/openai-responses/compaction-search-history.ts +27 -0
- package/src/adapters/openai-responses/passthrough.ts +17 -12
- package/src/adapters/openai-responses/reasoning.ts +68 -1
- package/src/adapters/registry.ts +1 -1
- package/src/adapters/upstream-http-error.ts +3 -2
- package/src/adapters/zed.ts +7 -4
- package/src/bridge/internal.ts +17 -3
- package/src/bridge/response-json.ts +4 -4
- package/src/bridge/sse.ts +17 -10
- package/src/claude/inbound-content-options.ts +66 -0
- package/src/claude/inbound.ts +12 -26
- package/src/claude/outbound.ts +18 -5
- package/src/cli/account-api.ts +13 -1
- package/src/cli/account-extended.ts +17 -5
- package/src/cli/account-key-quota.ts +4 -1
- package/src/cli/account.ts +1 -1
- package/src/cli/capabilities-agents-routing.ts +45 -8
- package/src/cli/capabilities-base.ts +5 -5
- package/src/cli/capabilities-provider-models.ts +5 -4
- package/src/cli/combo-result.ts +8 -2
- package/src/cli/combo.ts +17 -0
- package/src/cli/cross-home-owner.ts +16 -2
- package/src/cli/help.ts +1 -1
- package/src/cli/loopback-family.ts +31 -0
- package/src/cli/message-command.ts +4 -1
- package/src/cli/message-remote-args.ts +69 -0
- package/src/cli/message-remote-command.ts +77 -0
- package/src/cli/provider-runtime.ts +69 -1
- package/src/cli/registry.ts +3 -3
- package/src/codex/account-pause.ts +6 -1
- package/src/codex/account-runtime-state.ts +5 -0
- package/src/codex/account-store.ts +30 -3
- package/src/codex/auth-api/account-list.ts +3 -0
- package/src/codex/auth-api/main-account-probe.ts +3 -2
- package/src/codex/auth-context.ts +9 -4
- package/src/codex/catalog/aggregation.ts +15 -0
- package/src/codex/catalog/auto-review.ts +2 -1
- package/src/codex/catalog/build-entries.ts +17 -7
- package/src/codex/catalog/derive-entry.ts +3 -1
- package/src/codex/catalog/metadata.ts +2 -0
- package/src/codex/catalog/model-visibility.ts +0 -2
- package/src/codex/catalog/ownership.ts +71 -0
- package/src/codex/catalog/parsing.ts +12 -3
- package/src/codex/catalog/retained-sync.ts +2 -1
- package/src/codex/catalog/routed-gather.ts +3 -1
- package/src/codex/catalog/routed-removal.ts +4 -4
- package/src/codex/convergence.ts +2 -1
- package/src/codex/low-quota-desktop-notifier.ts +125 -0
- package/src/codex/low-quota-protection.ts +57 -31
- package/src/codex/main-account-cache.ts +77 -3
- package/src/codex/main-account.ts +6 -2
- package/src/codex/native-residue.ts +2 -3
- package/src/codex/quota.ts +26 -2
- package/src/codex/websocket-activity.ts +161 -0
- package/src/codex/websocket-registry.ts +25 -1
- package/src/combos/failover.ts +2 -1
- package/src/combos/jev-model-backend.ts +30 -7
- package/src/combos/jev-model-request.ts +20 -0
- package/src/combos/jev-quota-activation.ts +153 -0
- package/src/combos/jev-quota-config.ts +62 -0
- package/src/combos/jev-quota-route.ts +26 -0
- package/src/combos/jev-quota.ts +88 -0
- package/src/combos/jev.ts +25 -12
- package/src/combos/types.ts +27 -0
- package/src/compatibility/index.ts +3 -0
- package/src/compatibility/openai-responses.ts +8 -1
- package/src/compatibility/opengateway-responses.ts +61 -0
- package/src/config/account-auto-pause-revisions.ts +136 -0
- package/src/config/diagnostics.ts +13 -0
- package/src/config/live-reconcile.ts +9 -0
- package/src/config/opencode-zen-upgrade.ts +9 -8
- package/src/config/persist-unlocked.ts +10 -1
- package/src/config/removed-opencode-free.ts +135 -0
- package/src/config/schema/account-auto-pause.ts +14 -0
- package/src/config/schema/config-schema.ts +15 -0
- package/src/config/schema/leaf-validators.ts +7 -0
- package/src/config.ts +10 -3
- package/src/generated/compatibility-version.json +411 -175
- package/src/images/loop.ts +101 -27
- package/src/lib/account-auto-pause-response.ts +16 -0
- package/src/lib/bun-runtime.ts +18 -1
- package/src/lib/bun-transpiler-cache-scope.d.mts +8 -0
- package/src/lib/bun-transpiler-cache-scope.mjs +68 -0
- package/src/lib/decision-quota-sink.ts +76 -0
- package/src/lib/request-failure-model.ts +2 -0
- package/src/lib/state-store-registrations.ts +25 -0
- package/src/link/ssh-argv.ts +3 -0
- package/src/messaging/envelope.ts +6 -3
- package/src/messaging/remote-auth.ts +83 -0
- package/src/messaging/remote-bridge.ts +270 -0
- package/src/messaging/remote-contract.ts +108 -0
- package/src/messaging/remote-enrollment-recovery.ts +59 -0
- package/src/messaging/remote-enrollment.ts +244 -0
- package/src/messaging/remote-envelope.ts +40 -0
- package/src/messaging/remote-files.ts +117 -0
- package/src/messaging/remote-owner.ts +169 -0
- package/src/messaging/remote-ports.ts +56 -0
- package/src/messaging/remote-process.ts +131 -0
- package/src/messaging/remote-replies.ts +98 -0
- package/src/messaging/remote-rpc-admission.ts +32 -0
- package/src/messaging/remote-send.ts +72 -0
- package/src/messaging/remote-store.ts +111 -0
- package/src/messaging/remote-tunnels.ts +65 -0
- package/src/messaging/rpc.ts +13 -1
- package/src/oauth/account-auto-pause-policy.ts +66 -0
- package/src/oauth/account-auto-pause.ts +171 -0
- package/src/oauth/account-quota-rank.ts +2 -1
- package/src/oauth/anthropic-account-refusal.ts +6 -0
- package/src/oauth/anthropic-model-family.ts +8 -0
- package/src/oauth/anthropic-model-quota.ts +2 -6
- package/src/oauth/api-key-pool-preserve.ts +37 -0
- package/src/oauth/generic-account-failover.ts +7 -4
- package/src/oauth/index.ts +5 -35
- package/src/oauth/store.ts +35 -8
- package/src/oauth/types.ts +2 -0
- package/src/plugins/upstream-hooks.ts +14 -1
- package/src/protocols/encoders/adapter-events.ts +5 -5
- package/src/protocols/encoders/messages.ts +2 -2
- package/src/providers/api-key-pause.ts +32 -0
- package/src/providers/api-key-resolve.ts +10 -4
- package/src/providers/api-key-selection.ts +6 -1
- package/src/providers/api-keys.ts +8 -4
- package/src/providers/claude-cli-usage.ts +5 -0
- package/src/providers/key-failover.ts +11 -11
- package/src/providers/model-rename-fields.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +12 -73
- package/src/providers/quota/account-cache.ts +15 -1
- package/src/providers/quota/anthropic-account-quota.ts +2 -1
- package/src/providers/quota/anthropic-cooldown-recovery.ts +22 -4
- package/src/providers/quota/anthropic-decision-windows.ts +47 -0
- package/src/providers/quota/antigravity.ts +39 -6
- package/src/providers/quota/report-cache.ts +14 -0
- package/src/providers/quota/vendor-probes-oauth.ts +3 -3
- package/src/providers/quota-decision-publication.ts +77 -0
- package/src/providers/quota-decision-snapshot.ts +145 -0
- package/src/providers/quota-routing-cache.ts +3 -0
- package/src/providers/quota-types.ts +6 -1
- package/src/providers/quota.ts +3 -2
- package/src/providers/registry/entries-extended.ts +8 -52
- package/src/providers/registry/model-seeds.ts +1 -1
- package/src/providers/registry.ts +1 -2
- package/src/providers/stale-vision-classification-migration.ts +1 -1
- package/src/responses/parser.ts +18 -10
- package/src/responses/reasoning-replay-cache.ts +50 -4
- package/src/responses/web-search-replay.ts +138 -0
- package/src/routing/analytics.ts +7 -15
- package/src/routing/compatibility/behavior.ts +4 -1
- package/src/server/auth-cors.ts +7 -0
- package/src/server/background-lifecycle.ts +2 -1
- package/src/server/chat-native.ts +28 -13
- package/src/server/claude-messages.ts +4 -2
- package/src/server/index/live-sideband.ts +3 -2
- package/src/server/index/optional-listeners.ts +6 -0
- package/src/server/index/serve-options.ts +11 -5
- package/src/server/index/websocket-handler.ts +18 -4
- package/src/server/index.ts +7 -7
- package/src/server/lifecycle.ts +13 -1
- package/src/server/management/combo-routes.ts +17 -2
- package/src/server/management/oauth-account-routes.ts +10 -1
- package/src/server/management/provider-completion-test.ts +289 -0
- package/src/server/management/provider-routes.ts +9 -1
- package/src/server/management/route-registry.ts +2 -0
- package/src/server/messages-native.ts +34 -7
- package/src/server/messages-shared.ts +4 -1
- package/src/server/request-log.ts +7 -2
- package/src/server/responses/account-auto-pause-recovery.ts +26 -0
- package/src/server/responses/adapter-continuation.ts +34 -18
- package/src/server/responses/adapter-delivery.ts +53 -6
- package/src/server/responses/adapter-dispatch.ts +104 -29
- package/src/server/responses/anthropic-thinking-recovery.ts +153 -0
- package/src/server/responses/combo-session-recall.ts +25 -0
- package/src/server/responses/combo-stream-preflight.ts +6 -3
- package/src/server/responses/combo-tool-loop-pin.ts +70 -0
- package/src/server/responses/compact.ts +8 -5
- package/src/server/responses/compaction-recovery.ts +2 -0
- package/src/server/responses/context-overflow.ts +141 -2
- package/src/server/responses/core-codex-account.ts +9 -3
- package/src/server/responses/core-combo.ts +34 -7
- package/src/server/responses/core-lifetime.ts +3 -2
- package/src/server/responses/core-options.ts +2 -0
- package/src/server/responses/core-replay.ts +5 -1
- package/src/server/responses/core.ts +12 -9
- package/src/server/responses/empty-completion-guard.ts +2 -0
- package/src/server/responses/fetch-helpers.ts +35 -4
- package/src/server/responses/jev-model-invoke.ts +13 -14
- package/src/server/responses/native-steering-log.ts +2 -2
- package/src/server/responses/passthrough-delivery.ts +3 -2
- package/src/server/responses/passthrough-dispatch.ts +30 -33
- package/src/server/responses/passthrough-execution.ts +3 -2
- package/src/server/responses/passthrough-observations.ts +38 -0
- package/src/server/responses/request-compression.ts +98 -0
- package/src/server/responses/request-prepare.ts +1 -0
- package/src/server/responses/request-transport.ts +32 -3
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/response-tool-ownership.ts +21 -0
- package/src/server/responses/run-turn-execution.ts +2 -0
- package/src/server/responses/sidecar-execution.ts +59 -10
- package/src/server/responses/sidecar-send-budget.ts +2 -2
- package/src/server/responses/terminal-guard.ts +2 -0
- package/src/server/responses-undeclared-tool-guard.ts +1 -1
- package/src/server/startup-action-control.ts +2 -2
- package/src/server/startup-health-cache.ts +2 -2
- package/src/server/windows-tray-control.ts +2 -2
- package/src/server/ws-bridge.ts +2 -0
- package/src/service/definition.ts +9 -1
- package/src/types/account-auto-pause.ts +15 -0
- package/src/types/config.ts +23 -1
- package/src/types/opencode-zen.ts +9 -3
- package/src/types/provider.ts +9 -5
- package/src/types/request.ts +30 -4
- package/src/types/wire.ts +4 -2
- package/src/types.ts +2 -0
- package/src/usage/cost.ts +17 -1
- package/src/usage/expected-prices.ts +3 -1
- package/src/usage/jev-stats.ts +4 -0
- package/src/usage/log.ts +2 -0
- package/src/usage/summary.ts +16 -3
- package/src/usage/telemetry-contract.ts +1 -0
- package/src/web-search/anthropic-history.ts +59 -0
- package/src/web-search/loop.ts +212 -73
- package/src/web-search/progress-stream.ts +14 -1
- package/src/web-search/run-turn-loop.ts +9 -3
- package/src/web-search/sidecar-search-replay.ts +96 -0
- package/gui/dist/assets/App-ZfYbLHkB.js +0 -58
- package/gui/dist/assets/App-wT3mXqFz.css +0 -1
- package/gui/dist/assets/index-CfYDMj34.js +0 -94
package/src/types/config.ts
CHANGED
|
@@ -1089,7 +1089,11 @@ export interface OcxConfig {
|
|
|
1089
1089
|
modelCacheTtlMs?: number;
|
|
1090
1090
|
/** Evictable retained app-state budget in MiB. Default 256; valid 64..4096. */
|
|
1091
1091
|
appOwnedMemoryBudgetMb?: number;
|
|
1092
|
-
/**
|
|
1092
|
+
/**
|
|
1093
|
+
* Anthropic prompt-cache retention: "short" = 5-min ephemeral, "long" = 1-hour extended,
|
|
1094
|
+
* "none" = disabled. Unset = "long" on first-party api.anthropic.com, "short" on
|
|
1095
|
+
* Anthropic-compatible endpoints (adapters/anthropic/cache-retention.ts).
|
|
1096
|
+
*/
|
|
1093
1097
|
cacheRetention?: "none" | "short" | "long";
|
|
1094
1098
|
/** Web-search sidecar: route web_search for non-OpenAI models through a gpt-mini via ChatGPT passthrough. */
|
|
1095
1099
|
webSearchSidecar?: OcxWebSearchSidecarConfig;
|
|
@@ -1113,6 +1117,9 @@ export interface OcxConfig {
|
|
|
1113
1117
|
codexAccounts?: CodexAccount[];
|
|
1114
1118
|
/** Account ids administratively excluded from future pool selection until resumed. */
|
|
1115
1119
|
pausedCodexAccountIds?: string[];
|
|
1120
|
+
/** Internal policy epochs; null marks malformed disk input and suppresses automatic pause. */
|
|
1121
|
+
accountAutoPausePolicyRevisions?: Record<string, string> | null;
|
|
1122
|
+
codexAccountPauseState?: Record<string, { revision: string; details?: import("./account-auto-pause").AccountPauseDetails }>;
|
|
1116
1123
|
/**
|
|
1117
1124
|
* Account ids, `__main__` included, allowed to keep serving from ChatGPT credits once one of
|
|
1118
1125
|
* their usage windows is full. Every other account is skipped by selection at 100% until its
|
|
@@ -1293,6 +1300,13 @@ export interface OcxConfig {
|
|
|
1293
1300
|
* that work today — on Azure and custom Responses gateways as well, whose limits are unknown.
|
|
1294
1301
|
*/
|
|
1295
1302
|
maxUpstreamBodyBytes?: number;
|
|
1303
|
+
/**
|
|
1304
|
+
* Opt-in compression of native ChatGPT Responses HTTP request bodies (#7247): "gzip" or "zstd".
|
|
1305
|
+
* Omitted, "off", or any other value = identity, the default. Applies only at the final HTTP send
|
|
1306
|
+
* to chatgpt.com Codex responses/compact, to string bodies from 1 KiB to 16 MiB; WebSocket turns
|
|
1307
|
+
* and every other destination are unchanged. Compression runs synchronously on the event loop.
|
|
1308
|
+
*/
|
|
1309
|
+
upstreamRequestCompression?: "off" | "gzip" | "zstd";
|
|
1296
1310
|
/**
|
|
1297
1311
|
* Opt-in ceiling, in bytes, on a decompressed INBOUND data-plane request body (#3573).
|
|
1298
1312
|
*
|
|
@@ -1454,6 +1468,8 @@ export interface OcxComboConfig {
|
|
|
1454
1468
|
nativeAlias?: boolean;
|
|
1455
1469
|
/** Display-only label for the public catalog row. Required for native aliases. */
|
|
1456
1470
|
displayName?: string;
|
|
1471
|
+
/** Display-only description for the public catalog row; unset keeps the generated text (#7229). */
|
|
1472
|
+
description?: string;
|
|
1457
1473
|
/**
|
|
1458
1474
|
* `strategy: "jev"` only: provider id of the decision service. Omitted or `"jev"` uses the
|
|
1459
1475
|
* canonical TypeSafe endpoint; any other id must name a configured `adapter: "jev-decision"`
|
|
@@ -1469,6 +1485,10 @@ export interface OcxComboConfig {
|
|
|
1469
1485
|
* whose first call may include a cold model load.
|
|
1470
1486
|
*/
|
|
1471
1487
|
decisionTimeoutMs?: number;
|
|
1488
|
+
/** JEV-only advisory loaded quota evidence; off/unset leaves request bytes unchanged. */
|
|
1489
|
+
decisionQuotaSignals?: boolean | null;
|
|
1490
|
+
/** Partial 0..100 tier overrides; defaults limited 70/nearlyExhausted 90. null clears. */
|
|
1491
|
+
decisionQuotaTiers?: import("../combos/jev-quota-config").JevQuotaTiers | null;
|
|
1472
1492
|
}
|
|
1473
1493
|
|
|
1474
1494
|
export type OcxRoutingUnknownEvidenceMode = "allow" | "penalize" | "exclude";
|
|
@@ -1757,6 +1777,8 @@ export interface CodexLowQuotaProtectionConfig {
|
|
|
1757
1777
|
actions: {
|
|
1758
1778
|
pause: boolean;
|
|
1759
1779
|
notify: boolean;
|
|
1780
|
+
/** Opt-in: also hand each notice to this host's OS notifier (macOS, Linux). Requires notify. */
|
|
1781
|
+
desktop?: boolean;
|
|
1760
1782
|
};
|
|
1761
1783
|
windows: {
|
|
1762
1784
|
short: boolean;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/** Fixed-key OpenCode Zen destinations
|
|
1
|
+
/** Fixed-key OpenCode Zen destinations supporting native model protocols. */
|
|
2
2
|
export interface OpenCodeZenDestination {
|
|
3
3
|
readonly baseUrl?: unknown;
|
|
4
4
|
readonly authMode?: unknown;
|
|
5
5
|
readonly googleMode?: unknown;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/** Match the official Zen destination and API-key authentication. */
|
|
9
|
+
export function openCodeZenKeyBaseUrl(provider: OpenCodeZenDestination | undefined): string | undefined {
|
|
9
10
|
if (!provider || typeof provider.baseUrl !== "string") return undefined;
|
|
10
11
|
if (provider.authMode !== undefined && provider.authMode !== "key") return undefined;
|
|
11
|
-
if (provider.googleMode !== undefined && provider.googleMode !== "ai-studio") return undefined;
|
|
12
12
|
try {
|
|
13
13
|
const url = new URL(provider.baseUrl.trim());
|
|
14
14
|
const pathname = url.pathname.replace(/\/+$/, "");
|
|
@@ -20,6 +20,12 @@ export function openCodeZenBaseUrl(provider: OpenCodeZenDestination | undefined)
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/** Gemini's native endpoint applies only in AI Studio mode. */
|
|
24
|
+
export function openCodeZenBaseUrl(provider: OpenCodeZenDestination | undefined): string | undefined {
|
|
25
|
+
if (provider?.googleMode !== undefined && provider.googleMode !== "ai-studio") return undefined;
|
|
26
|
+
return openCodeZenKeyBaseUrl(provider);
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
/** Keep the selected destination; Zen omits AI Studio's /v1beta segment. */
|
|
24
30
|
export function openCodeZenGeminiEndpoint(provider: OpenCodeZenDestination, modelId: string): string | undefined {
|
|
25
31
|
const baseUrl = openCodeZenBaseUrl(provider);
|
package/src/types/provider.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { UpstreamHttpVersion, ReasoningSummaryDelivery, CodexAccountMode } from "./wire";
|
|
2
|
+
import type { AccountAutoPausePolicy, AccountPauseDetails } from "./account-auto-pause";
|
|
2
3
|
import type { AnthropicAccountPoolConfig } from "./anthropic-account-pool";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -448,8 +449,9 @@ export interface OcxProviderConfig {
|
|
|
448
449
|
*/
|
|
449
450
|
preserveResponsesMessageMetadata?: boolean;
|
|
450
451
|
/**
|
|
451
|
-
* Opt in to lossy hosted-search history notes on
|
|
452
|
-
*
|
|
452
|
+
* Opt in to lossy hosted-search history notes on canonical Codex Lite ordinary turns and
|
|
453
|
+
* native v2 compaction triggers, even when search is declared. Default off; only literal true
|
|
454
|
+
* enables it. History without a search declaration is always projected, independent of this.
|
|
453
455
|
*/
|
|
454
456
|
projectResponsesLiteHostedSearchHistory?: boolean;
|
|
455
457
|
/**
|
|
@@ -567,7 +569,9 @@ export interface OcxProviderConfig {
|
|
|
567
569
|
* entry so routing stays single-key; managed via /api/providers/keys. A legacy bare
|
|
568
570
|
* `apiKey` seeds a one-entry pool on first management touch.
|
|
569
571
|
*/
|
|
570
|
-
apiKeyPool?: Array<{ id: string; key: string; label?: string; addedAt?: number }>;
|
|
572
|
+
apiKeyPool?: Array<{ id: string; key: string; label?: string; addedAt?: number; disabled?: boolean; pauseDetails?: AccountPauseDetails; pauseRevision?: string }>;
|
|
573
|
+
/** Explicit opt-in permanent account refusal policy; default off. */
|
|
574
|
+
accountAutoPause?: AccountAutoPausePolicy;
|
|
571
575
|
/**
|
|
572
576
|
* Optional proactive ordering for `apiKeyPool` when the committed key is already
|
|
573
577
|
* cooling. Deliberately NOT named like the OAuth `accountPoolStrategy`: an API key
|
|
@@ -1110,9 +1114,9 @@ export interface OcxProviderConfig {
|
|
|
1110
1114
|
googleMode?: "ai-studio" | "vertex" | "cloud-code-assist";
|
|
1111
1115
|
/** Google tool-schema compatibility policy. Omitted preserves compatible report-only behavior. */
|
|
1112
1116
|
googleToolSchemaPolicy?: "compatible" | "reject-lossy";
|
|
1113
|
-
/** Vertex AI GCP project id
|
|
1117
|
+
/** Vertex AI GCP project id. API keys use it to select the project endpoint; ADC falls back to GOOGLE_CLOUD_PROJECT / GCLOUD_PROJECT env. */
|
|
1114
1118
|
project?: string;
|
|
1115
|
-
/** Vertex AI location, e.g. "us-central1" or "global"
|
|
1119
|
+
/** Vertex AI location, e.g. "us-central1" or "global". API-key project endpoints default to "global"; ADC falls back to GOOGLE_CLOUD_LOCATION env. */
|
|
1116
1120
|
location?: string;
|
|
1117
1121
|
/**
|
|
1118
1122
|
* Cursor adapter only: MCP servers opencodex starts/connects and exposes to the Cursor agent
|
package/src/types/request.ts
CHANGED
|
@@ -46,6 +46,14 @@ export interface OcxReasoningReplayScopeRef {
|
|
|
46
46
|
current?: Readonly<OcxReasoningReplayIdentity>;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/** One replayed hosted search cell, rebuilt as the `web_search` call/result pair `callId`. */
|
|
50
|
+
export interface OcxReplayedWebSearchCell {
|
|
51
|
+
/** The client-visible cell id; absent when the cell carried no usable id (no recorded result). */
|
|
52
|
+
cellId?: string;
|
|
53
|
+
callId: string;
|
|
54
|
+
failed: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
49
57
|
export interface OcxParsedRequest {
|
|
50
58
|
modelId: string;
|
|
51
59
|
/** Client-facing model selector retained for Anthropic routes after wire-model normalization. */
|
|
@@ -68,6 +76,11 @@ export interface OcxParsedRequest {
|
|
|
68
76
|
* them, and only for api.anthropic.com; every other destination never sees them.
|
|
69
77
|
*/
|
|
70
78
|
_anthropicServerTools?: readonly Record<string, unknown>[];
|
|
79
|
+
/**
|
|
80
|
+
* Completed server-tool exchanges from the Claude client's history, keyed by the block that
|
|
81
|
+
* followed them (`call:<tool_use id>` / `text:<text>`). Same audience as `_anthropicServerTools`.
|
|
82
|
+
*/
|
|
83
|
+
_anthropicServerReplay?: ReadonlyMap<string, readonly Record<string, unknown>[]>;
|
|
71
84
|
/**
|
|
72
85
|
* Boundary between replayed history and this turn's newly appended input. Usually the
|
|
73
86
|
* items the proxy restored from local previous_response_id state; also set when the
|
|
@@ -147,6 +160,12 @@ export interface OcxParsedRequest {
|
|
|
147
160
|
* executes searches via the gpt-5.6-luna sidecar (see src/web-search). Absent when not requested.
|
|
148
161
|
*/
|
|
149
162
|
_webSearch?: Record<string, unknown>;
|
|
163
|
+
/**
|
|
164
|
+
* Replayed hosted `web_search_call` cells the parser rebuilt as `web_search` call/result pairs
|
|
165
|
+
* (src/responses/web-search-replay.ts). The web-search sidecar swaps in the result it recorded for
|
|
166
|
+
* a cell, or removes the pairs when it does not run (src/web-search/sidecar-search-replay.ts).
|
|
167
|
+
*/
|
|
168
|
+
_replayedWebSearchCells?: OcxReplayedWebSearchCell[];
|
|
150
169
|
/** Hosted image_generation tool config stashed for the image bridge sidecar (see src/images). */
|
|
151
170
|
_imageGeneration?: { toolNames: Set<string>; originalTool?: Record<string, unknown> };
|
|
152
171
|
/**
|
|
@@ -414,6 +433,9 @@ export interface OcxProviderContinuationState {
|
|
|
414
433
|
[provider: string]: Record<string, unknown> | undefined;
|
|
415
434
|
}
|
|
416
435
|
|
|
436
|
+
/** One Anthropic server-side call as the API returned it: `server_tool_use` + its `*_tool_result`. */
|
|
437
|
+
export interface AnthropicServerBlocks { use: Record<string, unknown>; result: Record<string, unknown> }
|
|
438
|
+
|
|
417
439
|
export type AdapterEvent =
|
|
418
440
|
| { type: "heartbeat"; replayUnsafe?: true; preflightReady?: true }
|
|
419
441
|
| { type: "text_delta"; text: string; phase?: OcxMessagePhase;
|
|
@@ -440,11 +462,12 @@ export type AdapterEvent =
|
|
|
440
462
|
// "Searching the web" spinner, then `end` once it resolves. The bridge maps begin → an
|
|
441
463
|
// output_item.added(in_progress) and end → the matching output_item.done(completed|failed) under
|
|
442
464
|
// the SAME output index, so the activity animates instead of flashing completed instantly.
|
|
443
|
-
|
|
465
|
+
// `itemId` lets the loop name the client-visible cell so it can record the result for replay.
|
|
466
|
+
| { type: "web_search_call_begin"; id: string; itemId?: string }
|
|
444
467
|
| {
|
|
445
|
-
type: "web_search_call_end"; id: string; queries: string[]; status?: "completed" | "failed"; sources?: OcxUrlCitation[];
|
|
446
|
-
/** Anthropic's server-side
|
|
447
|
-
|
|
468
|
+
type: "web_search_call_end"; id: string; itemId?: string; queries: string[]; status?: "completed" | "failed"; sources?: OcxUrlCitation[];
|
|
469
|
+
/** Anthropic's server-side call (adapters/anthropic.ts): its `server_tool_use` and result block, verbatim. */
|
|
470
|
+
anthropic?: AnthropicServerBlocks;
|
|
448
471
|
}
|
|
449
472
|
| {
|
|
450
473
|
type: "done";
|
|
@@ -502,6 +525,8 @@ export interface OcxUrlCitation {
|
|
|
502
525
|
* - `cachedInputTokens` is cache READ tokens only (a subset of `inputTokens`).
|
|
503
526
|
* - `cacheReadInputTokens`/`cacheCreationInputTokens` carry the read/write split when
|
|
504
527
|
* the provider reports both; reads mirror `cachedInputTokens`.
|
|
528
|
+
* - `cacheCreation1hInputTokens` is the 1-hour-TTL subset of `cacheCreationInputTokens`
|
|
529
|
+
* (Anthropic `cache_creation.ephemeral_1h_input_tokens`), priced at the 1h write tier.
|
|
505
530
|
* - `totalTokens` = inputTokens + outputTokens. Never re-add cache detail on top.
|
|
506
531
|
*/
|
|
507
532
|
export interface OcxUsage {
|
|
@@ -519,6 +544,7 @@ export interface OcxUsage {
|
|
|
519
544
|
cachedInputTokens?: number;
|
|
520
545
|
cacheReadInputTokens?: number;
|
|
521
546
|
cacheCreationInputTokens?: number;
|
|
547
|
+
cacheCreation1hInputTokens?: number;
|
|
522
548
|
reasoningOutputTokens?: number;
|
|
523
549
|
estimated?: boolean;
|
|
524
550
|
/**
|
package/src/types/wire.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isOpenCodeGoGeminiDestination, OPENCODE_GO_BASE_URL, OPENCODE_GO_MODEL_WIRES, OPENCODE_GO_LEGACY_NAME_PINS, type OpenCodeGoDestination } from "./opencode-go";
|
|
2
|
-
import { openCodeZenBaseUrl, type OpenCodeZenDestination } from "./opencode-zen";
|
|
2
|
+
import { openCodeZenBaseUrl, openCodeZenKeyBaseUrl, type OpenCodeZenDestination } from "./opencode-zen";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Accepted values for the per-provider upstream HTTP-version pin (#1668). Shared by the
|
|
@@ -106,7 +106,9 @@ const CREDENTIAL_PINNED_ADAPTERS: Readonly<Record<string, Readonly<Record<string
|
|
|
106
106
|
|
|
107
107
|
function prefixPinsFor(providerName: string, provider: WirePinProvider | undefined): Readonly<Record<string, string>> | undefined {
|
|
108
108
|
if (Object.hasOwn(CREDENTIAL_PINNED_ADAPTERS, providerName)) return CREDENTIAL_PINNED_ADAPTERS[providerName];
|
|
109
|
-
if (providerName === "opencode-zen" &&
|
|
109
|
+
if (providerName === "opencode-zen" && openCodeZenKeyBaseUrl(provider)) {
|
|
110
|
+
return openCodeZenBaseUrl(provider) ? { "gemini-": "google", "claude-": "anthropic" } : { "claude-": "anthropic" };
|
|
111
|
+
}
|
|
110
112
|
if (!provider || !Object.hasOwn(WIRE_ADAPTER_PIN_PREFIXES, providerName)) return undefined;
|
|
111
113
|
const rule = WIRE_ADAPTER_PIN_PREFIXES[providerName]!;
|
|
112
114
|
return normalizedEndpoint(provider.baseUrl) === rule.endpoint ? rule.prefixes : undefined;
|
package/src/types.ts
CHANGED
|
@@ -41,6 +41,7 @@ export {
|
|
|
41
41
|
export type {
|
|
42
42
|
OcxReasoningReplayIdentity,
|
|
43
43
|
OcxReasoningReplayScopeRef,
|
|
44
|
+
OcxReplayedWebSearchCell,
|
|
44
45
|
OcxParsedRequest,
|
|
45
46
|
OcxContext,
|
|
46
47
|
OcxMessage,
|
|
@@ -61,6 +62,7 @@ export type {
|
|
|
61
62
|
OcxProviderContinuationOwner,
|
|
62
63
|
OcxProviderContinuationState,
|
|
63
64
|
AdapterEvent,
|
|
65
|
+
AnthropicServerBlocks,
|
|
64
66
|
OcxUrlCitation,
|
|
65
67
|
OcxUsage,
|
|
66
68
|
} from "./types/request";
|
package/src/usage/cost.ts
CHANGED
|
@@ -65,6 +65,8 @@ export interface CostTokens {
|
|
|
65
65
|
output: number;
|
|
66
66
|
cacheRead: number;
|
|
67
67
|
cacheWrite: number;
|
|
68
|
+
/** The 1-hour-TTL subset of `cacheWrite`, when the provider reports the split. */
|
|
69
|
+
cacheWrite1h?: number;
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
export interface CostBreakdown {
|
|
@@ -163,22 +165,35 @@ export function normalizeCostTokens(usage: OcxUsage): CostTokens | null {
|
|
|
163
165
|
for (const cacheRead of candidates) {
|
|
164
166
|
if (![input, output, cacheRead, cacheWrite].every(finiteNonNegative)) return null;
|
|
165
167
|
if (cacheRead + cacheWrite > input) continue;
|
|
168
|
+
const cacheWrite1h = usage.cacheCreation1hInputTokens;
|
|
166
169
|
return {
|
|
167
170
|
input: Math.max(0, input - cacheRead - cacheWrite),
|
|
168
171
|
output,
|
|
169
172
|
cacheRead,
|
|
170
173
|
cacheWrite,
|
|
174
|
+
...(typeof cacheWrite1h === "number" && finiteNonNegative(cacheWrite1h) && cacheWrite1h > 0
|
|
175
|
+
? { cacheWrite1h: Math.min(cacheWrite1h, cacheWrite) } : {}),
|
|
171
176
|
};
|
|
172
177
|
}
|
|
173
178
|
return null;
|
|
174
179
|
}
|
|
175
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Price of a 1-hour cache write relative to the 5-minute rate that Cost4.cacheWrite records.
|
|
183
|
+
* Anthropic bills 5m writes at 1.25x and 1h writes at 2x base input, so 2 / 1.25. Scaling the
|
|
184
|
+
* 5m rate (rather than input) keeps every tier multiplier already applied to the Cost4 and keeps
|
|
185
|
+
* a free-write row (cacheWrite 0) free.
|
|
186
|
+
*/
|
|
187
|
+
export const CACHE_WRITE_1H_OVER_5M = 2 / 1.25;
|
|
188
|
+
|
|
176
189
|
/** jawcode unit convention: USD per 1M tokens (jawcode stats/db.ts calculateCatalogCost). */
|
|
177
190
|
export function calculateCost(tokens: CostTokens, cost4: Cost4): CostBreakdown {
|
|
178
191
|
const input = cost4.input * tokens.input / 1_000_000;
|
|
179
192
|
const output = cost4.output * tokens.output / 1_000_000;
|
|
180
193
|
const cacheRead = cost4.cacheRead * tokens.cacheRead / 1_000_000;
|
|
181
|
-
const
|
|
194
|
+
const write1h = Math.min(tokens.cacheWrite1h ?? 0, tokens.cacheWrite);
|
|
195
|
+
const cacheWrite = (cost4.cacheWrite * (tokens.cacheWrite - write1h)
|
|
196
|
+
+ cost4.cacheWrite * CACHE_WRITE_1H_OVER_5M * write1h) / 1_000_000;
|
|
182
197
|
return { input, output, cacheRead, cacheWrite, total: input + output + cacheRead + cacheWrite };
|
|
183
198
|
}
|
|
184
199
|
|
|
@@ -656,6 +671,7 @@ export function estimateComboCost(
|
|
|
656
671
|
tokens.output += est.tokens.output;
|
|
657
672
|
tokens.cacheRead += est.tokens.cacheRead;
|
|
658
673
|
tokens.cacheWrite += est.tokens.cacheWrite;
|
|
674
|
+
if (est.tokens.cacheWrite1h) tokens.cacheWrite1h = (tokens.cacheWrite1h ?? 0) + est.tokens.cacheWrite1h;
|
|
659
675
|
cost.input += est.cost.input;
|
|
660
676
|
cost.output += est.cost.output;
|
|
661
677
|
cost.cacheRead += est.cost.cacheRead;
|
|
@@ -125,7 +125,9 @@ const GLM_52: Cost4 = { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0
|
|
|
125
125
|
const GLM_53: Cost4 = { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 };
|
|
126
126
|
const GLM_53_FLASH: Cost4 = { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 };
|
|
127
127
|
const QWEN38_MAX: Cost4 = { input: 2, output: 6, cacheRead: 0, cacheWrite: 0 };
|
|
128
|
-
// Anthropic official list prices (USD / 1M tokens). Cache write uses the published 5-minute rate
|
|
128
|
+
// Anthropic official list prices (USD / 1M tokens). Cache write uses the published 5-minute rate;
|
|
129
|
+
// writes the usage reports as 1-hour (cache_creation.ephemeral_1h_input_tokens) are priced at
|
|
130
|
+
// 2x base input through CACHE_WRITE_1H_OVER_5M in cost.ts.
|
|
129
131
|
const CLAUDE_SONNET_46: Cost4 = { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 };
|
|
130
132
|
const CLAUDE_OPUS_46: Cost4 = { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 };
|
|
131
133
|
// Claude Fable 5.1: 10 / 50, 5m cache write 12.50. Cache hits are 0.025x base input
|
package/src/usage/jev-stats.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeJevQuotaSummary, type JevQuotaDecisionSummary } from "../combos/jev-quota-config";
|
|
1
2
|
import type { OcxComboDefaultEffort } from "../types";
|
|
2
3
|
import type { PersistedUsageEntry } from "./log";
|
|
3
4
|
import { usageDisplayTotalTokens } from "./totals";
|
|
@@ -39,6 +40,7 @@ export interface PersistedJevDecisionV1 {
|
|
|
39
40
|
};
|
|
40
41
|
gate: JevDecisionGate;
|
|
41
42
|
latencyMs: number;
|
|
43
|
+
quota?: JevQuotaDecisionSummary;
|
|
42
44
|
confidence?: number;
|
|
43
45
|
chosenProbability?: number;
|
|
44
46
|
usage?: {
|
|
@@ -182,6 +184,7 @@ export function normalizePersistedJevDecision(value: unknown): PersistedJevDecis
|
|
|
182
184
|
const confidence = probability(value.confidence);
|
|
183
185
|
const chosenProbability = probability(value.chosenProbability);
|
|
184
186
|
const usage = normalizedDecisionUsage(value.usage);
|
|
187
|
+
const quota = normalizeJevQuotaSummary(value.quota);
|
|
185
188
|
const backend = value.backend === "typesafe" || value.backend === "systemone" || value.backend === "model"
|
|
186
189
|
? value.backend
|
|
187
190
|
: undefined;
|
|
@@ -196,6 +199,7 @@ export function normalizePersistedJevDecision(value: unknown): PersistedJevDecis
|
|
|
196
199
|
},
|
|
197
200
|
gate: gate as JevDecisionGate,
|
|
198
201
|
latencyMs,
|
|
202
|
+
...(quota ? { quota } : {}),
|
|
199
203
|
...(confidence !== undefined ? { confidence } : {}),
|
|
200
204
|
...(chosenProbability !== undefined ? { chosenProbability } : {}),
|
|
201
205
|
...(usage ? { usage } : {}),
|
package/src/usage/log.ts
CHANGED
|
@@ -581,6 +581,7 @@ function normalizeUsageValue(usage: OcxUsage | undefined): OcxUsage | undefined
|
|
|
581
581
|
...(typeof usage.cachedInputTokens === "number" ? { cachedInputTokens: usage.cachedInputTokens } : {}),
|
|
582
582
|
...(typeof usage.cacheReadInputTokens === "number" ? { cacheReadInputTokens: usage.cacheReadInputTokens } : {}),
|
|
583
583
|
...(typeof usage.cacheCreationInputTokens === "number" ? { cacheCreationInputTokens: usage.cacheCreationInputTokens } : {}),
|
|
584
|
+
...(typeof usage.cacheCreation1hInputTokens === "number" ? { cacheCreation1hInputTokens: usage.cacheCreation1hInputTokens } : {}),
|
|
584
585
|
...(typeof usage.reasoningOutputTokens === "number" ? { reasoningOutputTokens: usage.reasoningOutputTokens } : {}),
|
|
585
586
|
...(isNonNegativeFiniteNumber(usage.providerCredits) ? { providerCredits: usage.providerCredits } : {}),
|
|
586
587
|
...(usage.estimated ? { estimated: true } : {}),
|
|
@@ -625,6 +626,7 @@ function normalizeAttemptUsage(raw: unknown): OcxUsage | null {
|
|
|
625
626
|
"cachedInputTokens",
|
|
626
627
|
"cacheReadInputTokens",
|
|
627
628
|
"cacheCreationInputTokens",
|
|
629
|
+
"cacheCreation1hInputTokens",
|
|
628
630
|
"reasoningOutputTokens",
|
|
629
631
|
"providerCredits",
|
|
630
632
|
] as const) {
|
package/src/usage/summary.ts
CHANGED
|
@@ -520,6 +520,8 @@ function projectedComboUsage(
|
|
|
520
520
|
let cachedInputTokens = 0;
|
|
521
521
|
let cacheReadInputTokens = 0;
|
|
522
522
|
let cacheCreationInputTokens = 0;
|
|
523
|
+
let cacheCreation1hInputTokens = 0;
|
|
524
|
+
let hasCacheWrite1h = false;
|
|
523
525
|
let reasoningOutputTokens = 0;
|
|
524
526
|
let hasUsage = false;
|
|
525
527
|
let hasCacheTelemetry = false;
|
|
@@ -540,6 +542,10 @@ function projectedComboUsage(
|
|
|
540
542
|
cacheReadInputTokens += cache.read;
|
|
541
543
|
}
|
|
542
544
|
if (typeof cache.creation === "number") cacheCreationInputTokens += cache.creation;
|
|
545
|
+
if (typeof attempt.usage.cacheCreation1hInputTokens === "number") {
|
|
546
|
+
hasCacheWrite1h = true;
|
|
547
|
+
cacheCreation1hInputTokens += attempt.usage.cacheCreation1hInputTokens;
|
|
548
|
+
}
|
|
543
549
|
if (typeof attempt.usage.reasoningOutputTokens === "number") {
|
|
544
550
|
hasReasoningTelemetry = true;
|
|
545
551
|
reasoningOutputTokens += attempt.usage.reasoningOutputTokens;
|
|
@@ -559,6 +565,7 @@ function projectedComboUsage(
|
|
|
559
565
|
inputTokens,
|
|
560
566
|
outputTokens,
|
|
561
567
|
...(hasCacheTelemetry ? { cachedInputTokens, cacheReadInputTokens, cacheCreationInputTokens } : {}),
|
|
568
|
+
...(hasCacheWrite1h ? { cacheCreation1hInputTokens } : {}),
|
|
562
569
|
...(hasReasoningTelemetry ? { reasoningOutputTokens } : {}),
|
|
563
570
|
...(estimated ? { estimated: true } : {}),
|
|
564
571
|
}
|
|
@@ -665,8 +672,12 @@ function addEstimatedCost(
|
|
|
665
672
|
entry: Pick<PersistedUsageEntry, "usageStatus" | "usage" | "attempts">,
|
|
666
673
|
costInfo: EntryCostInfo,
|
|
667
674
|
): void {
|
|
668
|
-
|
|
669
|
-
|
|
675
|
+
// A row of attempts reads `unreported` when any leg lacks usage. Once one leg is measured the row
|
|
676
|
+
// is metered and the attempt-level pricing decides, matching the model and provider breakdowns.
|
|
677
|
+
const measuredAttempt = entry.attempts?.some(attempt => attempt.usage && isMeasuredStatus(attempt.usageStatus));
|
|
678
|
+
if (!measuredAttempt
|
|
679
|
+
&& (entry.usageStatus === "unreported" || entry.usageStatus === "unsupported"
|
|
680
|
+
|| (!entry.usage && !entry.attempts?.length))) {
|
|
670
681
|
totals.unmeteredRequests += 1;
|
|
671
682
|
return;
|
|
672
683
|
}
|
|
@@ -822,7 +833,9 @@ function blankRequestCounts(): UsageRequestCounts {
|
|
|
822
833
|
function spentNothing(attempt: NonNullable<PersistedUsageEntry["attempts"]>[number] | undefined): boolean {
|
|
823
834
|
if (!attempt || attempt.usage) return false;
|
|
824
835
|
if (attempt.sendCount === 0 || attempt.locallyAnswered === true) return true;
|
|
825
|
-
|
|
836
|
+
// A 499 is the client hanging up on a send upstream may already be generating for.
|
|
837
|
+
return attempt.status >= 400 && attempt.status !== 499
|
|
838
|
+
&& attempt.streamAborted !== true && attempt.firstOutputMs === undefined;
|
|
826
839
|
}
|
|
827
840
|
|
|
828
841
|
function bumpRequestCounts(counts: UsageRequestCounts, facts: number, amount = 1): void {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AdapterEvent, OcxAssistantContentPart, OcxThinkingContent, OcxToolCall } from "../types";
|
|
2
|
+
|
|
3
|
+
/** Rebuild one validated Anthropic model response without changing its search arguments or order. */
|
|
4
|
+
export function anthropicSearchAssistantContent(events: readonly AdapterEvent[]): OcxAssistantContentPart[] {
|
|
5
|
+
const content: OcxAssistantContentPart[] = [];
|
|
6
|
+
let thinking: OcxThinkingContent | undefined;
|
|
7
|
+
let text: Extract<OcxAssistantContentPart, { type: "text" }> | undefined;
|
|
8
|
+
let call: OcxToolCall | undefined;
|
|
9
|
+
let argumentsText = "";
|
|
10
|
+
for (const event of events) {
|
|
11
|
+
if (event.type === "heartbeat") continue;
|
|
12
|
+
// A signature is a replacement snapshot until the next semantic block starts.
|
|
13
|
+
if (thinking?.signature !== undefined && event.type !== "thinking_signature") thinking = undefined;
|
|
14
|
+
if (event.type !== "text_delta") text = undefined;
|
|
15
|
+
switch (event.type) {
|
|
16
|
+
case "thinking_delta":
|
|
17
|
+
if (!thinking) { thinking = { type: "thinking", thinking: "" }; content.push(thinking); }
|
|
18
|
+
thinking.thinking += event.thinking;
|
|
19
|
+
break;
|
|
20
|
+
case "thinking_signature":
|
|
21
|
+
if (!thinking) { thinking = { type: "thinking", thinking: "" }; content.push(thinking); }
|
|
22
|
+
thinking.signature = event.signature;
|
|
23
|
+
break;
|
|
24
|
+
case "redacted_thinking":
|
|
25
|
+
thinking = undefined;
|
|
26
|
+
content.push({ type: "thinking", thinking: "", redacted: [event.data] });
|
|
27
|
+
break;
|
|
28
|
+
case "text_delta":
|
|
29
|
+
thinking = undefined;
|
|
30
|
+
if (event.anthropicThinkingSignature) {
|
|
31
|
+
text = undefined;
|
|
32
|
+
content.push({ type: "thinking", thinking: event.text, signature: event.anthropicThinkingSignature });
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
if (!text) { text = { type: "text", text: "" }; content.push(text); }
|
|
36
|
+
text.text += event.text;
|
|
37
|
+
break;
|
|
38
|
+
case "tool_call_start":
|
|
39
|
+
thinking = undefined;
|
|
40
|
+
call = { type: "toolCall", id: event.id, name: event.name, arguments: {},
|
|
41
|
+
...(event.providerMetadata ? { providerMetadata: event.providerMetadata } : {}) };
|
|
42
|
+
content.push(call);
|
|
43
|
+
argumentsText = "";
|
|
44
|
+
break;
|
|
45
|
+
case "tool_call_delta":
|
|
46
|
+
argumentsText += event.arguments;
|
|
47
|
+
break;
|
|
48
|
+
case "tool_call_end": {
|
|
49
|
+
if (!call) throw new Error("search history has an unpaired tool call");
|
|
50
|
+
const args: unknown = JSON.parse(argumentsText || "{}");
|
|
51
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) throw new Error("search history tool input is not an object");
|
|
52
|
+
call.arguments = args as Record<string, unknown>;
|
|
53
|
+
call = undefined;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return content;
|
|
59
|
+
}
|