@bitkyc08/opencodex 2.6.7 → 2.6.8
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/gui/dist/assets/index-CgCKvnPc.js +9 -0
- package/gui/dist/assets/{index-CSI5RHdZ.css → index-DIBiVVC0.css} +1 -1
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/azure.ts +2 -2
- package/src/adapters/base.ts +6 -1
- package/src/adapters/google-antigravity-replay.ts +136 -0
- package/src/adapters/google-antigravity-wire.ts +94 -0
- package/src/adapters/google-errors.ts +95 -0
- package/src/adapters/google-http.ts +109 -0
- package/src/adapters/google-tool-schema.ts +89 -0
- package/src/adapters/google-truncation.ts +13 -0
- package/src/adapters/google.ts +163 -20
- package/src/adapters/kiro-tools.ts +55 -2
- package/src/cli-status.ts +4 -0
- package/src/cli.ts +7 -0
- package/src/codex-history-provider.ts +195 -22
- package/src/codex-plugins-doctor.ts +242 -0
- package/src/config.ts +1 -0
- package/src/lib/gcp-adc.ts +292 -0
- package/src/oauth/google-antigravity.ts +225 -0
- package/src/oauth/index.ts +19 -1
- package/src/oauth/store.ts +1 -0
- package/src/oauth/types.ts +2 -0
- package/src/provider-context-cap.ts +30 -1
- package/src/providers/antigravity-models.ts +30 -0
- package/src/providers/derive.ts +6 -0
- package/src/providers/registry.ts +7 -0
- package/src/redact.ts +26 -0
- package/src/router.ts +6 -0
- package/src/server.ts +45 -9
- package/src/types.ts +12 -0
- package/src/usage-summary.ts +30 -3
- package/src/web-search/loop.ts +1 -1
- package/gui/dist/assets/index-Ct8koBOe.js +0 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { OcxProviderConfig } from "../types";
|
|
2
2
|
import { KIRO_MODELS, KIRO_MODEL_CONTEXT_WINDOWS, KIRO_MODEL_REASONING_EFFORTS } from "./kiro-models";
|
|
3
|
+
import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS } from "./antigravity-models";
|
|
3
4
|
|
|
4
5
|
export type ProviderAuthKind = "forward" | "oauth" | "key" | "local";
|
|
5
6
|
export type MetadataModelIdNormalize = "case-insensitive";
|
|
@@ -34,6 +35,9 @@ export interface ProviderRegistryEntry {
|
|
|
34
35
|
jawcodeBundle?: string;
|
|
35
36
|
extraMetadataAliases?: string[];
|
|
36
37
|
metadataModelIdNormalize?: MetadataModelIdNormalize;
|
|
38
|
+
googleMode?: "ai-studio" | "vertex" | "cloud-code-assist";
|
|
39
|
+
project?: string;
|
|
40
|
+
location?: string;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
export type ProviderConfigSeed = Pick<
|
|
@@ -43,6 +47,7 @@ export type ProviderConfigSeed = Pick<
|
|
|
43
47
|
| "reasoningEfforts" | "modelReasoningEfforts" | "reasoningEffortMap" | "modelReasoningEffortMap"
|
|
44
48
|
| "noVisionModels" | "noReasoningModels" | "noTemperatureModels" | "noTopPModels" | "noPenaltyModels"
|
|
45
49
|
| "autoToolChoiceOnlyModels" | "preserveReasoningContentModels" | "escapeBuiltinToolNames"
|
|
50
|
+
| "googleMode" | "project" | "location"
|
|
46
51
|
>;
|
|
47
52
|
|
|
48
53
|
|
|
@@ -260,6 +265,8 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
260
265
|
{ id: "openrouter", label: "OpenRouter", adapter: "openai-chat", baseUrl: "https://openrouter.ai/api/v1", authKind: "key", featured: true, dashboardUrl: "https://openrouter.ai/keys", jawcodeBundle: "openrouter" },
|
|
261
266
|
{ id: "groq", label: "Groq", adapter: "openai-chat", baseUrl: "https://api.groq.com/openai/v1", authKind: "key", featured: true, dashboardUrl: "https://console.groq.com/keys" },
|
|
262
267
|
{ id: "google", label: "Google Gemini", adapter: "google", baseUrl: "https://generativelanguage.googleapis.com", authKind: "key", featured: true, dashboardUrl: "https://aistudio.google.com/apikey", defaultModel: "gemini-3-pro", jawcodeBundle: "google", extraMetadataAliases: ["gemini"] },
|
|
268
|
+
{ id: "google-vertex", label: "Google Vertex AI", adapter: "google", baseUrl: "https://aiplatform.googleapis.com", authKind: "key", dashboardUrl: "https://console.cloud.google.com/vertex-ai", defaultModel: "gemini-3-pro", googleMode: "vertex", jawcodeBundle: "google", extraMetadataAliases: ["gemini-vertex"] },
|
|
269
|
+
{ id: "google-antigravity", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, defaultModel: "gemini-3.5-flash-low", modelContextWindows: ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, googleMode: "cloud-code-assist", jawcodeBundle: "google", extraMetadataAliases: ["antigravity", "gemini-antigravity"] },
|
|
263
270
|
{ id: "azure-openai", label: "Azure OpenAI", adapter: "azure-openai", baseUrl: "https://{resource}.openai.azure.com/openai", authKind: "key", featured: true, dashboardUrl: "https://portal.azure.com" },
|
|
264
271
|
{ id: "ollama", label: "Ollama (local)", adapter: "openai-chat", baseUrl: "http://localhost:11434/v1", authKind: "local", featured: true, note: "Local — key usually blank", reasoningEffortMap: OLLAMA_REASONING_MAP },
|
|
265
272
|
{ id: "vllm", label: "vLLM (local)", adapter: "openai-chat", baseUrl: "http://localhost:8000/v1", authKind: "local", featured: true, note: "Local — key usually blank" },
|
package/src/redact.ts
CHANGED
|
@@ -69,3 +69,29 @@ export function redactUrlForLog(url: string): string {
|
|
|
69
69
|
return redactSecretString(url.split("?")[0] ?? url);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
+
|
|
73
|
+
const USER_HOME_PATH_PATTERNS: Array<[RegExp, string]> = [
|
|
74
|
+
// Windows: C:\Users\<name>\... -> C:\Users\[USER]\...
|
|
75
|
+
[/([A-Za-z]:\\Users\\)[^\\/]+/gi, "$1[USER]"],
|
|
76
|
+
// POSIX: /Users/<name>/... (macOS) and /home/<name>/... (Linux)
|
|
77
|
+
[/(\/(?:Users|home)\/)[^/]+/gi, "$1[USER]"],
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
// Path segments whose name alone looks sensitive. Masked so a configured path
|
|
81
|
+
// cannot surface a secret-flavored substring in diagnostics or logs.
|
|
82
|
+
const SENSITIVE_SEGMENT_PATTERN = /(^|[\\/])([^\\/]*(?:secret|password|passwd|token|api[-_]?key|apikey|credential|email)[^\\/]*)(?=[\\/]|$)/gi;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Mask the username segment of an absolute home path so diagnostics can print
|
|
86
|
+
* paths without leaking the OS account name, and mask any path segment whose
|
|
87
|
+
* name looks sensitive (token/secret/password/credential/email/...). Path-focused
|
|
88
|
+
* and secret-safe: also runs {@link redactSecretString} for token-shaped values.
|
|
89
|
+
*/
|
|
90
|
+
export function redactUserPath(path: string): string {
|
|
91
|
+
let masked = path;
|
|
92
|
+
for (const [pattern, replacement] of USER_HOME_PATH_PATTERNS) {
|
|
93
|
+
masked = masked.replace(pattern, replacement);
|
|
94
|
+
}
|
|
95
|
+
masked = masked.replace(SENSITIVE_SEGMENT_PATTERN, (_m, sep: string) => `${sep}[REDACTED]`);
|
|
96
|
+
return redactSecretString(masked);
|
|
97
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -94,6 +94,12 @@ function routedProviderConfig(providerName: string, provider: OcxProviderConfig)
|
|
|
94
94
|
baseUrl: registryEntry.baseUrl,
|
|
95
95
|
authMode: canonicalAuthMode,
|
|
96
96
|
apiKey: resolveEnvValue(provider.apiKey),
|
|
97
|
+
// Backfill the Google wire mode + Vertex project/location from the registry when the user
|
|
98
|
+
// config omits them, so a minimal `google-vertex`/`google-antigravity` entry still routes
|
|
99
|
+
// through the correct branch (CCA/Vertex) instead of falling back to AI Studio.
|
|
100
|
+
...(provider.googleMode === undefined && registryEntry.googleMode !== undefined ? { googleMode: registryEntry.googleMode } : {}),
|
|
101
|
+
...(provider.project === undefined && registryEntry.project !== undefined ? { project: registryEntry.project } : {}),
|
|
102
|
+
...(provider.location === undefined && registryEntry.location !== undefined ? { location: registryEntry.location } : {}),
|
|
97
103
|
...(provider.contextWindow === undefined && registryEntry.contextWindow !== undefined ? { contextWindow: registryEntry.contextWindow } : {}),
|
|
98
104
|
...(provider.reasoningEfforts === undefined && registryEntry.reasoningEfforts !== undefined ? { reasoningEfforts: registryEntry.reasoningEfforts } : {}),
|
|
99
105
|
...(provider.escapeBuiltinToolNames === undefined && registryEntry.escapeBuiltinToolNames !== undefined ? { escapeBuiltinToolNames: registryEntry.escapeBuiltinToolNames } : {}),
|
package/src/server.ts
CHANGED
|
@@ -35,7 +35,7 @@ import { parseRequest } from "./responses/parser";
|
|
|
35
35
|
import { routeModel } from "./router";
|
|
36
36
|
import { namespacedToolName } from "./types";
|
|
37
37
|
import {
|
|
38
|
-
clearLoginState, getLoginStatus, getValidAccessToken, isOAuthProvider,
|
|
38
|
+
clearLoginState, getLoginStatus, getOAuthCredentialProjectId, getValidAccessToken, isOAuthProvider,
|
|
39
39
|
listOAuthProviders, reconcileOAuthProviders, startLoginFlow, UnsupportedOAuthProviderError, upsertOAuthProvider,
|
|
40
40
|
} from "./oauth/index";
|
|
41
41
|
import type { CatalogModel } from "./codex-catalog";
|
|
@@ -48,7 +48,7 @@ import { enrichProviderFromCatalog, listKeyLoginProviders } from "./oauth/key-pr
|
|
|
48
48
|
import { deriveProviderPresets } from "./providers/derive";
|
|
49
49
|
import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "./types";
|
|
50
50
|
import type { OcxUsage } from "./types";
|
|
51
|
-
import { DEFAULT_PROVIDER_CONTEXT_CAP, providerContextCap, providerContextCaps, setProviderContextCap } from "./provider-context-cap";
|
|
51
|
+
import { DEFAULT_PROVIDER_CONTEXT_CAP, globalContextCapValue, providerContextCap, providerContextCaps, setAllProviderContextCaps, setGlobalContextCapValue, setProviderContextCap } from "./provider-context-cap";
|
|
52
52
|
import {
|
|
53
53
|
appendUsageEntry,
|
|
54
54
|
readUsageEntries,
|
|
@@ -423,6 +423,12 @@ async function handleResponses(
|
|
|
423
423
|
if (route.provider.authMode === "oauth") {
|
|
424
424
|
try {
|
|
425
425
|
route.provider = { ...route.provider, apiKey: await getValidAccessToken(route.providerName) };
|
|
426
|
+
// Antigravity (cloud-code-assist) needs the discovered Cloud Code Assist project id in the
|
|
427
|
+
// CCA envelope; the server injects only the bare token, so pull project from the credential.
|
|
428
|
+
if (route.provider.googleMode === "cloud-code-assist" && !route.provider.project) {
|
|
429
|
+
const projectId = getOAuthCredentialProjectId(route.providerName);
|
|
430
|
+
if (projectId) route.provider = { ...route.provider, project: projectId };
|
|
431
|
+
}
|
|
426
432
|
} catch (err) {
|
|
427
433
|
if (err instanceof UnsupportedOAuthProviderError) {
|
|
428
434
|
return formatErrorResponse(
|
|
@@ -449,7 +455,7 @@ async function handleResponses(
|
|
|
449
455
|
const recordTerminalOutcomes = options.recordTerminalOutcomes !== false;
|
|
450
456
|
|
|
451
457
|
if ("passthrough" in adapter && adapter.passthrough) {
|
|
452
|
-
const request = adapter.buildRequest(parsed, { headers: selectedForwardHeaders });
|
|
458
|
+
const request = await adapter.buildRequest(parsed, { headers: selectedForwardHeaders });
|
|
453
459
|
// Abort the upstream if the client disconnects. A directly-relayed body does not propagate the
|
|
454
460
|
// consumer's cancel to a signalled fetch, so we pass the signal and relay through relayWithAbort,
|
|
455
461
|
// whose cancel() aborts the upstream — preventing leaked connections (RC2, passthrough path).
|
|
@@ -589,7 +595,7 @@ async function handleResponses(
|
|
|
589
595
|
const cleanupUpstreamAbort = linkAbortSignal(upstream, options.abortSignal);
|
|
590
596
|
const connectMs = config.connectTimeoutMs ?? 100_000;
|
|
591
597
|
|
|
592
|
-
const request = adapter.buildRequest(parsed, { headers: selectedForwardHeaders });
|
|
598
|
+
const request = await adapter.buildRequest(parsed, { headers: selectedForwardHeaders });
|
|
593
599
|
if (typeof request.usageLog?.inputTokens === "number") {
|
|
594
600
|
logCtx.usageLogInputTokens = request.usageLog.inputTokens;
|
|
595
601
|
}
|
|
@@ -1802,12 +1808,44 @@ async function handleManagementAPI(req: Request, url: URL, config: OcxConfig): P
|
|
|
1802
1808
|
}
|
|
1803
1809
|
|
|
1804
1810
|
if (url.pathname === "/api/provider-context-caps" && req.method === "GET") {
|
|
1805
|
-
return jsonResponse({ cap: DEFAULT_PROVIDER_CONTEXT_CAP, caps: providerContextCaps(config) });
|
|
1811
|
+
return jsonResponse({ cap: DEFAULT_PROVIDER_CONTEXT_CAP, value: globalContextCapValue(config), caps: providerContextCaps(config) });
|
|
1806
1812
|
}
|
|
1807
1813
|
|
|
1808
1814
|
if (url.pathname === "/api/provider-context-caps" && req.method === "PUT") {
|
|
1809
|
-
let body: { provider?: unknown; enabled?: unknown };
|
|
1815
|
+
let body: { provider?: unknown; enabled?: unknown; value?: unknown; setAll?: unknown };
|
|
1810
1816
|
try { body = await req.json(); } catch { return jsonResponse({ error: "invalid JSON body" }, 400); }
|
|
1817
|
+
const { saveConfig: save } = await import("./config");
|
|
1818
|
+
const { clearModelCache } = await import("./model-cache");
|
|
1819
|
+
const respond = () => jsonResponse({ ok: true, cap: DEFAULT_PROVIDER_CONTEXT_CAP, value: globalContextCapValue(config), caps: providerContextCaps(config) });
|
|
1820
|
+
|
|
1821
|
+
// Branch 1: set the global cap value and re-point every enabled provider to it.
|
|
1822
|
+
if (body.value !== undefined) {
|
|
1823
|
+
if (typeof body.value !== "number" || !Number.isFinite(body.value) || body.value <= 0) {
|
|
1824
|
+
return jsonResponse({ error: "value must be a positive number" }, 400);
|
|
1825
|
+
}
|
|
1826
|
+
const affected = Object.keys(providerContextCaps(config));
|
|
1827
|
+
setGlobalContextCapValue(config, body.value);
|
|
1828
|
+
save(config);
|
|
1829
|
+
for (const provider of affected) clearModelCache(provider);
|
|
1830
|
+
await refreshCodexCatalogBestEffort();
|
|
1831
|
+
return respond();
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// Branch 2: enable/clear the cap for every provider at once.
|
|
1835
|
+
if (body.setAll !== undefined) {
|
|
1836
|
+
if (typeof body.setAll !== "boolean") {
|
|
1837
|
+
return jsonResponse({ error: "setAll must be a boolean" }, 400);
|
|
1838
|
+
}
|
|
1839
|
+
const before = Object.keys(providerContextCaps(config));
|
|
1840
|
+
const names = Object.keys(config.providers);
|
|
1841
|
+
setAllProviderContextCaps(config, names, body.setAll);
|
|
1842
|
+
save(config);
|
|
1843
|
+
for (const provider of new Set([...before, ...names])) clearModelCache(provider);
|
|
1844
|
+
await refreshCodexCatalogBestEffort();
|
|
1845
|
+
return respond();
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
// Branch 3: existing per-provider toggle (enable writes the current global value).
|
|
1811
1849
|
if (typeof body.provider !== "string" || typeof body.enabled !== "boolean") {
|
|
1812
1850
|
return jsonResponse({ error: "provider string and enabled boolean are required" }, 400);
|
|
1813
1851
|
}
|
|
@@ -1819,12 +1857,10 @@ async function handleManagementAPI(req: Request, url: URL, config: OcxConfig): P
|
|
|
1819
1857
|
return jsonResponse({ error: "unknown provider" }, 404);
|
|
1820
1858
|
}
|
|
1821
1859
|
setProviderContextCap(config, provider, body.enabled);
|
|
1822
|
-
const { saveConfig: save } = await import("./config");
|
|
1823
1860
|
save(config);
|
|
1824
|
-
const { clearModelCache } = await import("./model-cache");
|
|
1825
1861
|
clearModelCache(provider);
|
|
1826
1862
|
await refreshCodexCatalogBestEffort();
|
|
1827
|
-
return
|
|
1863
|
+
return respond();
|
|
1828
1864
|
}
|
|
1829
1865
|
|
|
1830
1866
|
// Enable/disable models: which routed models Codex sees. PUT hides them from the catalog +
|
package/src/types.ts
CHANGED
|
@@ -207,6 +207,8 @@ export interface OcxConfig {
|
|
|
207
207
|
disabledModels?: string[];
|
|
208
208
|
/** Provider-level Codex-visible context caps. Values only lower known model context windows. */
|
|
209
209
|
providerContextCaps?: Record<string, number>;
|
|
210
|
+
/** Global Codex-visible context cap value (tokens). Falls back to DEFAULT_PROVIDER_CONTEXT_CAP. */
|
|
211
|
+
contextCapValue?: number;
|
|
210
212
|
/** Bind hostname. Default "127.0.0.1" (loopback only). Set "0.0.0.0" to expose on all interfaces. */
|
|
211
213
|
hostname?: string;
|
|
212
214
|
/** Upstream stall timeout (seconds). After this many seconds of no upstream data, emits response.incomplete. Default 90. Min 1. */
|
|
@@ -326,6 +328,16 @@ export interface OcxProviderConfig {
|
|
|
326
328
|
* attached images are described by a gpt vision model and replaced with text before the call.
|
|
327
329
|
*/
|
|
328
330
|
noVisionModels?: string[];
|
|
331
|
+
/**
|
|
332
|
+
* Google adapter mode. "ai-studio" (default) = Generative Language API + x-goog-api-key.
|
|
333
|
+
* "vertex" = Vertex AI project/location endpoints with GCP ADC (or x-goog-api-key).
|
|
334
|
+
* "cloud-code-assist" = Google Antigravity (Cloud Code Assist) OAuth + CCA envelope.
|
|
335
|
+
*/
|
|
336
|
+
googleMode?: "ai-studio" | "vertex" | "cloud-code-assist";
|
|
337
|
+
/** Vertex AI GCP project id (or GOOGLE_CLOUD_PROJECT / GCLOUD_PROJECT env). */
|
|
338
|
+
project?: string;
|
|
339
|
+
/** Vertex AI location, e.g. "us-central1" or "global" (or GOOGLE_CLOUD_LOCATION env). */
|
|
340
|
+
location?: string;
|
|
329
341
|
}
|
|
330
342
|
|
|
331
343
|
export interface CodexAccount {
|
package/src/usage-summary.ts
CHANGED
|
@@ -22,6 +22,14 @@ export interface UsageDay {
|
|
|
22
22
|
requests: number;
|
|
23
23
|
reportedRequests: number;
|
|
24
24
|
totalTokens: number;
|
|
25
|
+
models: UsageDayModel[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UsageDayModel {
|
|
29
|
+
model: string;
|
|
30
|
+
provider: string;
|
|
31
|
+
requests: number;
|
|
32
|
+
totalTokens: number;
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
export interface UsageModel {
|
|
@@ -124,24 +132,43 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
|
|
|
124
132
|
const window = rangeWindow(range, now);
|
|
125
133
|
const days = range === "all" ? dayCountForAllRange(entries, now) : window.days;
|
|
126
134
|
const grid = new Map<string, UsageDay>();
|
|
135
|
+
// Per-day model breakdown accumulator, keyed by day then provider/model, so the 7d bar chart can
|
|
136
|
+
// render a per-model stacked bar with a hover tooltip without a second pass over the entries.
|
|
137
|
+
const dayModels = new Map<string, Map<string, UsageDayModel>>();
|
|
138
|
+
const bumpDayModel = (dayKey: string, entry: PersistedUsageEntry): void => {
|
|
139
|
+
let models = dayModels.get(dayKey);
|
|
140
|
+
if (!models) { models = new Map(); dayModels.set(dayKey, models); }
|
|
141
|
+
const mKey = `${entry.provider}/${entry.model}`;
|
|
142
|
+
let m = models.get(mKey);
|
|
143
|
+
if (!m) { m = { model: entry.model, provider: entry.provider, requests: 0, totalTokens: 0 }; models.set(mKey, m); }
|
|
144
|
+
m.requests += 1;
|
|
145
|
+
if (typeof entry.totalTokens === "number") m.totalTokens += entry.totalTokens;
|
|
146
|
+
else if (entry.usage) m.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
147
|
+
};
|
|
127
148
|
for (let i = days - 1; i >= 0; i--) {
|
|
128
149
|
const key = localDateKey(now - i * DAY_MS);
|
|
129
|
-
grid.set(key, { date: key, requests: 0, reportedRequests: 0, totalTokens: 0 });
|
|
150
|
+
grid.set(key, { date: key, requests: 0, reportedRequests: 0, totalTokens: 0, models: [] });
|
|
130
151
|
}
|
|
131
152
|
for (const entry of entries) {
|
|
132
153
|
const key = localDateKey(entry.timestamp);
|
|
133
154
|
let day = grid.get(key);
|
|
134
155
|
if (!day) {
|
|
135
|
-
day = { date: key, requests: 0, reportedRequests: 0, totalTokens: 0 };
|
|
156
|
+
day = { date: key, requests: 0, reportedRequests: 0, totalTokens: 0, models: [] };
|
|
136
157
|
grid.set(key, day);
|
|
137
158
|
}
|
|
138
159
|
day.requests += 1;
|
|
139
160
|
if (entry.usageStatus === "reported") day.reportedRequests += 1;
|
|
140
161
|
if (typeof entry.totalTokens === "number") day.totalTokens += entry.totalTokens;
|
|
141
162
|
else if (entry.usage) day.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
163
|
+
bumpDayModel(key, entry);
|
|
142
164
|
}
|
|
143
165
|
void since;
|
|
144
|
-
|
|
166
|
+
const out = [...grid.values()].sort((a, b) => a.date.localeCompare(b.date));
|
|
167
|
+
for (const day of out) {
|
|
168
|
+
const models = dayModels.get(day.date);
|
|
169
|
+
if (models) day.models = [...models.values()].sort((a, b) => b.requests - a.requests);
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
function buildModels(entries: PersistedUsageEntry[], totalRequests: number): UsageModel[] {
|
package/src/web-search/loop.ts
CHANGED
|
@@ -130,7 +130,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
130
130
|
...parsed, stream: false,
|
|
131
131
|
context: { ...parsed.context, messages, tools: forceAnswer ? toolsNoWebSearch : allTools },
|
|
132
132
|
};
|
|
133
|
-
const request = adapter.buildRequest(iterParsed, { headers: selectedForwardHeaders });
|
|
133
|
+
const request = await adapter.buildRequest(iterParsed, { headers: selectedForwardHeaders });
|
|
134
134
|
let resp: Response;
|
|
135
135
|
try {
|
|
136
136
|
resp = adapter.fetchResponse
|