@nexus-cortex/core 4.124.45 → 4.124.47
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/.env.defaults +90 -1
- package/dist/adapters/ChatCompletionsAPIAdapter.d.ts.map +1 -1
- package/dist/adapters/ChatCompletionsAPIAdapter.js +10 -0
- package/dist/adapters/ChatCompletionsAPIAdapter.js.map +1 -1
- package/dist/adapters/GatewayTranslationLayer.d.ts.map +1 -1
- package/dist/adapters/GatewayTranslationLayer.js +33 -0
- package/dist/adapters/GatewayTranslationLayer.js.map +1 -1
- package/dist/adapters/ServerSideToolDetection.d.ts.map +1 -1
- package/dist/adapters/ServerSideToolDetection.js +5 -1
- package/dist/adapters/ServerSideToolDetection.js.map +1 -1
- package/dist/config/SettingsSchema.js +2 -2
- package/dist/config/SettingsSchema.js.map +1 -1
- package/dist/config/effectiveConfig.d.ts.map +1 -1
- package/dist/config/effectiveConfig.js +9 -0
- package/dist/config/effectiveConfig.js.map +1 -1
- package/dist/models/cards/xai/grok-4-3-chat.d.ts +15 -0
- package/dist/models/cards/xai/grok-4-3-chat.d.ts.map +1 -0
- package/dist/models/cards/xai/grok-4-3-chat.js +28 -0
- package/dist/models/cards/xai/grok-4-3-chat.js.map +1 -0
- package/dist/models/cards/xai/grok-build-0-1-chat.d.ts +17 -0
- package/dist/models/cards/xai/grok-build-0-1-chat.d.ts.map +1 -0
- package/dist/models/cards/xai/grok-build-0-1-chat.js +31 -0
- package/dist/models/cards/xai/grok-build-0-1-chat.js.map +1 -0
- package/dist/models/cards/xai/index.d.ts +2 -0
- package/dist/models/cards/xai/index.d.ts.map +1 -1
- package/dist/models/cards/xai/index.js +2 -0
- package/dist/models/cards/xai/index.js.map +1 -1
- package/dist/models/configurators/XAIConfigurator.d.ts +7 -1
- package/dist/models/configurators/XAIConfigurator.d.ts.map +1 -1
- package/dist/models/configurators/XAIConfigurator.js +15 -3
- package/dist/models/configurators/XAIConfigurator.js.map +1 -1
- package/dist/models/registry/ModularModelRegistry.d.ts.map +1 -1
- package/dist/models/registry/ModularModelRegistry.js +2 -0
- package/dist/models/registry/ModularModelRegistry.js.map +1 -1
- package/dist/orchestrator/APIClient.d.ts +4 -0
- package/dist/orchestrator/APIClient.d.ts.map +1 -1
- package/dist/orchestrator/APIClient.js +181 -25
- package/dist/orchestrator/APIClient.js.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.d.ts.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.js +8 -2
- package/dist/orchestrator/CortexOrchestrator.js.map +1 -1
- package/dist/orchestrator/appendOnlyHistory.d.ts.map +1 -1
- package/dist/orchestrator/appendOnlyHistory.js +4 -0
- package/dist/orchestrator/appendOnlyHistory.js.map +1 -1
- package/dist/orchestrator/geminiExplicitCache.d.ts +79 -0
- package/dist/orchestrator/geminiExplicitCache.d.ts.map +1 -0
- package/dist/orchestrator/geminiExplicitCache.js +324 -0
- package/dist/orchestrator/geminiExplicitCache.js.map +1 -0
- package/dist/orchestrator/transportEffortFixes.d.ts +62 -0
- package/dist/orchestrator/transportEffortFixes.d.ts.map +1 -0
- package/dist/orchestrator/transportEffortFixes.js +114 -0
- package/dist/orchestrator/transportEffortFixes.js.map +1 -0
- package/dist/orchestrator/xaiChatTransport.d.ts +27 -0
- package/dist/orchestrator/xaiChatTransport.d.ts.map +1 -0
- package/dist/orchestrator/xaiChatTransport.js +33 -0
- package/dist/orchestrator/xaiChatTransport.js.map +1 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appendOnlyHistory.d.ts","sourceRoot":"","sources":["../../src/orchestrator/appendOnlyHistory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEjF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEpF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEpF;AAED,wBAAgB,yBAAyB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEvF;AAED,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,wGAAwG;AACxG,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,CASzE;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"appendOnlyHistory.d.ts","sourceRoot":"","sources":["../../src/orchestrator/appendOnlyHistory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEjF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEpF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEpF;AAED,wBAAgB,yBAAyB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEvF;AAED,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,wGAAwG;AACxG,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,CASzE;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAUnE"}
|
|
@@ -70,6 +70,10 @@ export function isPreviousResponseUnavailable(err) {
|
|
|
70
70
|
.filter((x) => typeof x === 'string').join(' ');
|
|
71
71
|
if (/previous[_ ]?response/i.test(text) && /not[_ ]?found|expired|invalid|does not exist|unavailable|no longer|not stored|unknown/i.test(text))
|
|
72
72
|
return true;
|
|
73
|
+
// xAI (live probe 2026-10-02): 404 {"code":"not-found","error":"Response with id=resp_… not found"}; APIClient throws it as plain text
|
|
74
|
+
// ("XAI Responses API error 404: …") with no status field, so match the body wording itself.
|
|
75
|
+
if (/response with id\s*=?\s*['"]?resp_\S*['"]? not[ _-]?found/i.test(text))
|
|
76
|
+
return true;
|
|
73
77
|
return status === 404 && /\bresponse\b/i.test(text);
|
|
74
78
|
}
|
|
75
79
|
//# sourceMappingURL=appendOnlyHistory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appendOnlyHistory.js","sourceRoot":"","sources":["../../src/orchestrator/appendOnlyHistory.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"appendOnlyHistory.js","sourceRoot":"","sources":["../../src/orchestrator/appendOnlyHistory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export declare function isGeminiExplicitCacheEnabled(): boolean;
|
|
2
|
+
export declare function geminiCacheTtlSeconds(): number;
|
|
3
|
+
export declare function geminiCacheResnapshotTokens(): number;
|
|
4
|
+
/**
|
|
5
|
+
* Minimum cacheable input tokens (ai.google.dev/gemini-api/docs/caching, read 2026-10-03: Gemini 3.5–3.8 Flash
|
|
6
|
+
* and 3.1 Pro Preview 4,096; 2.5 Flash / 2.5 Pro 2,048; gemini-3-flash-preview not listed → 4,096 assumed).
|
|
7
|
+
* CORTEX_GEMINI_CACHE_MIN_TOKENS overrides.
|
|
8
|
+
*/
|
|
9
|
+
export declare function geminiMinCacheTokens(modelId: string): number;
|
|
10
|
+
/** Rough token estimate used for every threshold (chars / 4 of the JSON wire form). */
|
|
11
|
+
export declare function estimateTokens(value: unknown): number;
|
|
12
|
+
/** Body field names: REST (snake_case, top level) vs @google/genai SDK (camelCase, inside config). */
|
|
13
|
+
export type GeminiBodyFlavor = 'rest' | 'sdk';
|
|
14
|
+
export interface GeminiCachePlan {
|
|
15
|
+
slotKey: string;
|
|
16
|
+
name: string;
|
|
17
|
+
prefixLen: number;
|
|
18
|
+
/** 'created' (new snapshot this request) | 'reused' */
|
|
19
|
+
mode: 'created' | 'reused';
|
|
20
|
+
}
|
|
21
|
+
export interface GeminiCacheContext {
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
/** bare model id (no models/ prefix, no -sdk suffix) */
|
|
24
|
+
modelId: string;
|
|
25
|
+
/** API key + header used for the cachedContents REST calls */
|
|
26
|
+
apiKey: string;
|
|
27
|
+
/** v1beta base, e.g. https://generativelanguage.googleapis.com/v1beta */
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
}
|
|
30
|
+
type FetchLike = (url: string, init: {
|
|
31
|
+
method: string;
|
|
32
|
+
headers: Record<string, string>;
|
|
33
|
+
body?: string;
|
|
34
|
+
}) => Promise<{
|
|
35
|
+
ok: boolean;
|
|
36
|
+
status: number;
|
|
37
|
+
text(): Promise<string>;
|
|
38
|
+
json(): Promise<any>;
|
|
39
|
+
}>;
|
|
40
|
+
export declare const GEMINI_V1BETA_BASE = "https://generativelanguage.googleapis.com/v1beta";
|
|
41
|
+
/** `https://…/v1beta/models` (card endpoint) → `https://…/v1beta`. */
|
|
42
|
+
export declare function geminiBaseFromEndpoint(endpoint: string | undefined): string;
|
|
43
|
+
export declare class GeminiExplicitCacheManager {
|
|
44
|
+
private slots;
|
|
45
|
+
private fetchImpl;
|
|
46
|
+
private now;
|
|
47
|
+
constructor(opts?: {
|
|
48
|
+
fetchImpl?: FetchLike;
|
|
49
|
+
now?: () => number;
|
|
50
|
+
});
|
|
51
|
+
/** Live snapshot names (tests / telemetry). */
|
|
52
|
+
liveNames(): string[];
|
|
53
|
+
/**
|
|
54
|
+
* Decide + (if needed) create the snapshot for this request. Returns the plan and the rewritten body, or null
|
|
55
|
+
* (send the original body unchanged). Never throws.
|
|
56
|
+
*
|
|
57
|
+
* @param holder the object that carries system/tools/toolConfig (REST: the body; SDK: body.config)
|
|
58
|
+
*/
|
|
59
|
+
prepare(ctx: GeminiCacheContext, flavor: GeminiBodyFlavor, body: Record<string, any>): Promise<{
|
|
60
|
+
plan: GeminiCachePlan;
|
|
61
|
+
body: Record<string, any>;
|
|
62
|
+
} | null>;
|
|
63
|
+
private prepareInner;
|
|
64
|
+
/** Body for a cached request: no system/tools/toolConfig, cachedContent + the uncached tail. Never mutates the input. */
|
|
65
|
+
rewrite(flavor: GeminiBodyFlavor, body: Record<string, any>, name: string, prefixLen: number): Record<string, any>;
|
|
66
|
+
/** The cached request failed: drop the snapshot so the caller's full-request retry (and later turns) start clean. */
|
|
67
|
+
invalidate(plan: GeminiCachePlan, reason: string, ctx?: GeminiCacheContext): void;
|
|
68
|
+
/** Telemetry for a completed cached request. */
|
|
69
|
+
recordUsage(plan: GeminiCachePlan, usage: any): void;
|
|
70
|
+
private maybeExtend;
|
|
71
|
+
private deleteRemote;
|
|
72
|
+
private evict;
|
|
73
|
+
/** Best-effort DELETE of every live snapshot (session end). */
|
|
74
|
+
disposeAll(apiKey: string | undefined, baseUrl?: string): Promise<void>;
|
|
75
|
+
}
|
|
76
|
+
/** HTTP statuses on a cached request that mean "the cache is the problem" → invalidate + full retry once. */
|
|
77
|
+
export declare function isCacheUseFailure(status: number | undefined): boolean;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=geminiExplicitCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiExplicitCache.d.ts","sourceRoot":"","sources":["../../src/orchestrator/geminiExplicitCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HB-GEMINI-EXPLICIT-CACHE (DARK, CORTEX_GEMINI_EXPLICIT_CACHE; 2026-10-03).
|
|
3
|
+
*
|
|
4
|
+
* Gemini implicit caching is partial on gemini-3-flash-preview (a fixed ~12K head, the growing conversation is
|
|
5
|
+
* not cached) and absent on gemini-3.8-flash (.cortex/research/stack-portability-2026-10-02.md §"GEMINI
|
|
6
|
+
* CHAT/COMPLETIONS"). Explicit `cachedContents` caches cached 13,405/13,414 prompt tokens on both (§"GEMINI
|
|
7
|
+
* EXPLICIT cachedContents FEASIBILITY"). This module turns that into an append-only cache for the tool loop:
|
|
8
|
+
*
|
|
9
|
+
* - HEAD = (model, systemInstruction, tools, toolConfig) as the request body would have sent them. A SLOT per
|
|
10
|
+
* (session, head) holds at most one live snapshot {name, prefixLen, prefixHash, expiresAt}. Several heads per
|
|
11
|
+
* session coexist (a helper call with its own system prompt does not evict the main loop's snapshot); LRU cap.
|
|
12
|
+
* - SNAPSHOT = cachedContents.create(head + contents[0..prefixLen)), prefixLen = contents.length - 1 (the newest
|
|
13
|
+
* turn is always sent live). Created the first time head+prefix is estimated (chars/4) at or above the model's
|
|
14
|
+
* minimum cache size; re-created when the uncached tail (contents after prefixLen, newest turn excluded) exceeds
|
|
15
|
+
* CORTEX_GEMINI_CACHE_RESNAPSHOT_TOKENS, or when the snapshot is (nearly) expired. The superseded snapshot is
|
|
16
|
+
* DELETEd. A head change (system/tools/toolConfig change — e.g. the anchor lift) is a new slot = new snapshot
|
|
17
|
+
* (the one intended bust).
|
|
18
|
+
* - USE: the request drops systemInstruction/tools/toolConfig (Gemini 400s when they are set beside
|
|
19
|
+
* cachedContent — they live in the cache) and sends cachedContent + contents.slice(prefixLen). The prefix is
|
|
20
|
+
* verified by hash before every use; a rewritten history (compaction, prune, wall drop, image TTL) fails the
|
|
21
|
+
* hash → re-snapshot (or full request when too small).
|
|
22
|
+
* - TTL: CORTEX_GEMINI_CACHE_TTL_S (default 300); PATCHed (fire-and-forget) when used in the second half of its
|
|
23
|
+
* life. disposeAll() DELETEs every live snapshot (orchestrator cleanup).
|
|
24
|
+
* - FALLBACK: cache management never blocks a request. A create failure sends the normal full request and backs
|
|
25
|
+
* off re-creating until the prefix has grown by another resnapshot threshold; a 400/403/404 on a cached request
|
|
26
|
+
* invalidates the slot and the caller re-sends the normal full request once.
|
|
27
|
+
* - A request carrying a forced toolConfig (per-turn tool_choice) bypasses the cache: Gemini cannot take
|
|
28
|
+
* toolConfig beside cachedContent, and a per-turn snapshot would cost a full-price creation for one request.
|
|
29
|
+
*
|
|
30
|
+
* Off (unset) = callers never construct a plan → byte-identical requests.
|
|
31
|
+
*/
|
|
32
|
+
import { createHash } from 'crypto';
|
|
33
|
+
function flagOn(raw) {
|
|
34
|
+
const v = String(raw ?? '').trim().toLowerCase();
|
|
35
|
+
return v === 'on' || v === 'true' || v === '1';
|
|
36
|
+
}
|
|
37
|
+
export function isGeminiExplicitCacheEnabled() {
|
|
38
|
+
return flagOn(process.env.CORTEX_GEMINI_EXPLICIT_CACHE);
|
|
39
|
+
}
|
|
40
|
+
function intEnv(name, dflt, min) {
|
|
41
|
+
const n = Number.parseInt(String(process.env[name] ?? '').trim(), 10);
|
|
42
|
+
return Number.isFinite(n) && n >= min ? n : dflt;
|
|
43
|
+
}
|
|
44
|
+
export function geminiCacheTtlSeconds() {
|
|
45
|
+
return intEnv('CORTEX_GEMINI_CACHE_TTL_S', 300, 60);
|
|
46
|
+
}
|
|
47
|
+
export function geminiCacheResnapshotTokens() {
|
|
48
|
+
return intEnv('CORTEX_GEMINI_CACHE_RESNAPSHOT_TOKENS', 16000, 1024);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Minimum cacheable input tokens (ai.google.dev/gemini-api/docs/caching, read 2026-10-03: Gemini 3.5–3.8 Flash
|
|
52
|
+
* and 3.1 Pro Preview 4,096; 2.5 Flash / 2.5 Pro 2,048; gemini-3-flash-preview not listed → 4,096 assumed).
|
|
53
|
+
* CORTEX_GEMINI_CACHE_MIN_TOKENS overrides.
|
|
54
|
+
*/
|
|
55
|
+
export function geminiMinCacheTokens(modelId) {
|
|
56
|
+
const o = intEnv('CORTEX_GEMINI_CACHE_MIN_TOKENS', 0, 1);
|
|
57
|
+
if (o > 0)
|
|
58
|
+
return o;
|
|
59
|
+
return /gemini-2\.5/.test(modelId) ? 2048 : 4096;
|
|
60
|
+
}
|
|
61
|
+
/** Rough token estimate used for every threshold (chars / 4 of the JSON wire form). */
|
|
62
|
+
export function estimateTokens(value) {
|
|
63
|
+
if (value === undefined || value === null)
|
|
64
|
+
return 0;
|
|
65
|
+
return Math.ceil(JSON.stringify(value).length / 4);
|
|
66
|
+
}
|
|
67
|
+
function sha(value) {
|
|
68
|
+
return createHash('sha256').update(JSON.stringify(value ?? null)).digest('hex');
|
|
69
|
+
}
|
|
70
|
+
const FIELDS = {
|
|
71
|
+
rest: { system: 'system_instruction', tools: 'tools', toolConfig: 'tool_config', cached: 'cachedContent' },
|
|
72
|
+
sdk: { system: 'systemInstruction', tools: 'tools', toolConfig: 'toolConfig', cached: 'cachedContent' },
|
|
73
|
+
};
|
|
74
|
+
export const GEMINI_V1BETA_BASE = 'https://generativelanguage.googleapis.com/v1beta';
|
|
75
|
+
/** `https://…/v1beta/models` (card endpoint) → `https://…/v1beta`. */
|
|
76
|
+
export function geminiBaseFromEndpoint(endpoint) {
|
|
77
|
+
if (!endpoint)
|
|
78
|
+
return GEMINI_V1BETA_BASE;
|
|
79
|
+
return endpoint.replace(/\/+$/, '').replace(/\/models$/, '');
|
|
80
|
+
}
|
|
81
|
+
function toContent(system) {
|
|
82
|
+
// REST system_instruction is already a Content; the SDK accepts a bare string.
|
|
83
|
+
if (typeof system === 'string')
|
|
84
|
+
return { parts: [{ text: system }] };
|
|
85
|
+
return system;
|
|
86
|
+
}
|
|
87
|
+
function log(msg) {
|
|
88
|
+
// One line per cache event; quiet unless the lever is on (callers only reach here with it on).
|
|
89
|
+
if (process.env.CORTEX_GEMINI_CACHE_QUIET === 'true')
|
|
90
|
+
return;
|
|
91
|
+
console.error(`[gemini-cache] ${msg}`);
|
|
92
|
+
}
|
|
93
|
+
const MAX_SLOTS = 8;
|
|
94
|
+
const EXPIRY_SAFETY_MS = 15_000;
|
|
95
|
+
export class GeminiExplicitCacheManager {
|
|
96
|
+
slots = new Map();
|
|
97
|
+
fetchImpl;
|
|
98
|
+
now;
|
|
99
|
+
constructor(opts = {}) {
|
|
100
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => globalThis.fetch(url, init));
|
|
101
|
+
this.now = opts.now ?? (() => Date.now());
|
|
102
|
+
}
|
|
103
|
+
/** Live snapshot names (tests / telemetry). */
|
|
104
|
+
liveNames() {
|
|
105
|
+
return [...this.slots.values()].map((s) => s.name).filter((n) => !!n);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Decide + (if needed) create the snapshot for this request. Returns the plan and the rewritten body, or null
|
|
109
|
+
* (send the original body unchanged). Never throws.
|
|
110
|
+
*
|
|
111
|
+
* @param holder the object that carries system/tools/toolConfig (REST: the body; SDK: body.config)
|
|
112
|
+
*/
|
|
113
|
+
async prepare(ctx, flavor, body) {
|
|
114
|
+
try {
|
|
115
|
+
return await this.prepareInner(ctx, flavor, body);
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
log(`fallback reason=prepare_error ${String(e?.message ?? e).slice(0, 200)}`);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async prepareInner(ctx, flavor, body) {
|
|
123
|
+
const f = FIELDS[flavor];
|
|
124
|
+
const holder = flavor === 'sdk' ? (body.config ?? {}) : body;
|
|
125
|
+
// SDK legacy path (CORTEX_GEMINI_SYSTEM_FIX off) sets a top-level systemInstruction the SDK drops; mirror what is
|
|
126
|
+
// actually sent (config.systemInstruction only), so the cached head equals the uncached request's head.
|
|
127
|
+
const contents = Array.isArray(body.contents) ? body.contents : [];
|
|
128
|
+
if (contents.length < 2)
|
|
129
|
+
return null; // nothing to cache before the newest turn
|
|
130
|
+
if (holder.tool_config !== undefined || holder.toolConfig !== undefined) {
|
|
131
|
+
log(`bypass reason=tool_config (forced tool_choice is per-turn; cannot ride a cache)`);
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const system = holder[f.system];
|
|
135
|
+
const tools = holder[f.tools];
|
|
136
|
+
const headHash = sha({ m: ctx.modelId, s: system ?? null, t: tools ?? null, c: null });
|
|
137
|
+
const slotKey = `${ctx.sessionId ?? 'default'}|${headHash}`;
|
|
138
|
+
const base = ctx.baseUrl ?? GEMINI_V1BETA_BASE;
|
|
139
|
+
const now = this.now();
|
|
140
|
+
let slot = this.slots.get(slotKey);
|
|
141
|
+
const prefixLenWanted = contents.length - 1;
|
|
142
|
+
// 1. Is the live snapshot usable as-is?
|
|
143
|
+
if (slot?.name) {
|
|
144
|
+
const valid = slot.prefixLen <= prefixLenWanted &&
|
|
145
|
+
slot.expiresAt - EXPIRY_SAFETY_MS > now &&
|
|
146
|
+
sha(contents.slice(0, slot.prefixLen)) === slot.prefixHash;
|
|
147
|
+
if (!valid) {
|
|
148
|
+
const why = slot.expiresAt - EXPIRY_SAFETY_MS <= now ? 'expired' : 'prefix_changed';
|
|
149
|
+
log(`invalidate reason=${why} name=${slot.name}`);
|
|
150
|
+
this.deleteRemote(base, ctx.apiKey, slot.name);
|
|
151
|
+
slot.name = undefined;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const tailTokens = estimateTokens(contents.slice(slot.prefixLen, prefixLenWanted));
|
|
155
|
+
if (tailTokens <= geminiCacheResnapshotTokens()) {
|
|
156
|
+
slot.lastUsed = now;
|
|
157
|
+
this.maybeExtend(base, ctx.apiKey, slot);
|
|
158
|
+
return { plan: { slotKey, name: slot.name, prefixLen: slot.prefixLen, mode: 'reused' }, body: this.rewrite(flavor, body, slot.name, slot.prefixLen) };
|
|
159
|
+
}
|
|
160
|
+
log(`resnapshot reason=tail_tokens~${tailTokens} name=${slot.name}`);
|
|
161
|
+
// fall through: create a longer snapshot, then delete the old one
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// 2. Create (or re-create) a snapshot of head + contents[0..prefixLenWanted).
|
|
165
|
+
const prefix = contents.slice(0, prefixLenWanted);
|
|
166
|
+
const est = estimateTokens(system) + estimateTokens(tools) + estimateTokens(prefix);
|
|
167
|
+
const min = geminiMinCacheTokens(ctx.modelId);
|
|
168
|
+
if (est < min) {
|
|
169
|
+
// Still usable old snapshot (tail-threshold path)? keep using it.
|
|
170
|
+
if (slot?.name)
|
|
171
|
+
return { plan: { slotKey, name: slot.name, prefixLen: slot.prefixLen, mode: 'reused' }, body: this.rewrite(flavor, body, slot.name, slot.prefixLen) };
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
if (slot?.createFailedAtTokens !== undefined && est < slot.createFailedAtTokens + geminiCacheResnapshotTokens()) {
|
|
175
|
+
if (slot.name)
|
|
176
|
+
return { plan: { slotKey, name: slot.name, prefixLen: slot.prefixLen, mode: 'reused' }, body: this.rewrite(flavor, body, slot.name, slot.prefixLen) };
|
|
177
|
+
return null; // backoff after a failed create
|
|
178
|
+
}
|
|
179
|
+
const ttl = geminiCacheTtlSeconds();
|
|
180
|
+
const createBody = { model: `models/${ctx.modelId}`, contents: prefix, ttl: `${ttl}s` };
|
|
181
|
+
if (system !== undefined)
|
|
182
|
+
createBody.systemInstruction = toContent(system);
|
|
183
|
+
if (tools !== undefined)
|
|
184
|
+
createBody.tools = tools;
|
|
185
|
+
const res = await this.fetchImpl(`${base}/cachedContents`, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers: { 'Content-Type': 'application/json', 'x-goog-api-key': ctx.apiKey },
|
|
188
|
+
body: JSON.stringify(createBody),
|
|
189
|
+
});
|
|
190
|
+
if (!res.ok) {
|
|
191
|
+
const txt = await res.text().catch(() => '');
|
|
192
|
+
log(`fallback reason=create_${res.status} est~${est} ${txt.replace(/\s+/g, ' ').slice(0, 200)}`);
|
|
193
|
+
if (!slot) {
|
|
194
|
+
slot = { key: slotKey, prefixLen: 0, prefixHash: '', expiresAt: 0, lastUsed: now };
|
|
195
|
+
this.slots.set(slotKey, slot);
|
|
196
|
+
}
|
|
197
|
+
slot.createFailedAtTokens = est;
|
|
198
|
+
if (slot.name)
|
|
199
|
+
return { plan: { slotKey, name: slot.name, prefixLen: slot.prefixLen, mode: 'reused' }, body: this.rewrite(flavor, body, slot.name, slot.prefixLen) };
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const created = await res.json();
|
|
203
|
+
const name = created?.name;
|
|
204
|
+
if (!name) {
|
|
205
|
+
log('fallback reason=create_no_name');
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const old = slot?.name;
|
|
209
|
+
const expireMs = Date.parse(created?.expireTime ?? '');
|
|
210
|
+
const fresh = {
|
|
211
|
+
key: slotKey,
|
|
212
|
+
name,
|
|
213
|
+
prefixLen: prefixLenWanted,
|
|
214
|
+
prefixHash: sha(prefix),
|
|
215
|
+
expiresAt: Number.isFinite(expireMs) ? expireMs : now + ttl * 1000,
|
|
216
|
+
lastUsed: now,
|
|
217
|
+
};
|
|
218
|
+
this.slots.delete(slotKey);
|
|
219
|
+
this.slots.set(slotKey, fresh);
|
|
220
|
+
log(`created name=${name} model=${ctx.modelId} prefixLen=${prefixLenWanted} est~${est} tokens=${created?.usageMetadata?.totalTokenCount ?? '?'} ttl=${ttl}s`);
|
|
221
|
+
if (old)
|
|
222
|
+
this.deleteRemote(base, ctx.apiKey, old);
|
|
223
|
+
this.evict(base, ctx.apiKey);
|
|
224
|
+
return { plan: { slotKey, name, prefixLen: prefixLenWanted, mode: 'created' }, body: this.rewrite(flavor, body, name, prefixLenWanted) };
|
|
225
|
+
}
|
|
226
|
+
/** Body for a cached request: no system/tools/toolConfig, cachedContent + the uncached tail. Never mutates the input. */
|
|
227
|
+
rewrite(flavor, body, name, prefixLen) {
|
|
228
|
+
const f = FIELDS[flavor];
|
|
229
|
+
const out = { ...body, contents: body.contents.slice(prefixLen) };
|
|
230
|
+
if (flavor === 'sdk') {
|
|
231
|
+
const config = { ...(body.config ?? {}) };
|
|
232
|
+
delete config[f.system];
|
|
233
|
+
delete config[f.tools];
|
|
234
|
+
delete config[f.toolConfig];
|
|
235
|
+
config[f.cached] = name;
|
|
236
|
+
out.config = config;
|
|
237
|
+
delete out.systemInstruction; // legacy top-level slot (never valid beside a cache)
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
delete out[f.system];
|
|
241
|
+
delete out.systemInstruction;
|
|
242
|
+
delete out[f.tools];
|
|
243
|
+
delete out[f.toolConfig];
|
|
244
|
+
delete out.toolConfig;
|
|
245
|
+
out[f.cached] = name;
|
|
246
|
+
}
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
249
|
+
/** The cached request failed: drop the snapshot so the caller's full-request retry (and later turns) start clean. */
|
|
250
|
+
invalidate(plan, reason, ctx) {
|
|
251
|
+
const slot = this.slots.get(plan.slotKey);
|
|
252
|
+
log(`fallback reason=${reason} name=${plan.name}`);
|
|
253
|
+
if (slot && slot.name === plan.name) {
|
|
254
|
+
slot.name = undefined;
|
|
255
|
+
if (ctx)
|
|
256
|
+
this.deleteRemote(ctx.baseUrl ?? GEMINI_V1BETA_BASE, ctx.apiKey, plan.name);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/** Telemetry for a completed cached request. */
|
|
260
|
+
recordUsage(plan, usage) {
|
|
261
|
+
const cached = usage?.cachedContentTokenCount ?? 0;
|
|
262
|
+
const prompt = usage?.promptTokenCount ?? 0;
|
|
263
|
+
log(`${plan.mode === 'created' ? 'used(new)' : 'reused'} name=${plan.name} prefixLen=${plan.prefixLen} cachedContentTokenCount=${cached} promptTokenCount=${prompt}`);
|
|
264
|
+
}
|
|
265
|
+
maybeExtend(base, apiKey, slot) {
|
|
266
|
+
const ttl = geminiCacheTtlSeconds();
|
|
267
|
+
if (slot.extending || slot.expiresAt - this.now() > (ttl * 1000) / 2 || !slot.name)
|
|
268
|
+
return;
|
|
269
|
+
slot.extending = true;
|
|
270
|
+
const name = slot.name;
|
|
271
|
+
void this.fetchImpl(`${base}/${name}?updateMask=ttl`, {
|
|
272
|
+
method: 'PATCH',
|
|
273
|
+
headers: { 'Content-Type': 'application/json', 'x-goog-api-key': apiKey },
|
|
274
|
+
body: JSON.stringify({ ttl: `${ttl}s` }),
|
|
275
|
+
})
|
|
276
|
+
.then(async (r) => {
|
|
277
|
+
if (r.ok) {
|
|
278
|
+
const j = await r.json().catch(() => ({}));
|
|
279
|
+
const e = Date.parse(j?.expireTime ?? '');
|
|
280
|
+
if (slot.name === name)
|
|
281
|
+
slot.expiresAt = Number.isFinite(e) ? e : this.now() + ttl * 1000;
|
|
282
|
+
log(`extended name=${name} ttl=${ttl}s`);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
log(`extend_failed status=${r.status} name=${name}`);
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
.catch((e) => log(`extend_failed ${String(e?.message ?? e).slice(0, 120)}`))
|
|
289
|
+
.finally(() => { slot.extending = false; });
|
|
290
|
+
}
|
|
291
|
+
deleteRemote(base, apiKey, name) {
|
|
292
|
+
void this.fetchImpl(`${base}/${name}`, { method: 'DELETE', headers: { 'x-goog-api-key': apiKey } })
|
|
293
|
+
.then((r) => log(`deleted name=${name} status=${r.status}`))
|
|
294
|
+
.catch((e) => log(`delete_failed name=${name} ${String(e?.message ?? e).slice(0, 120)}`));
|
|
295
|
+
}
|
|
296
|
+
evict(base, apiKey) {
|
|
297
|
+
while (this.slots.size > MAX_SLOTS) {
|
|
298
|
+
let oldest;
|
|
299
|
+
for (const s of this.slots.values())
|
|
300
|
+
if (!oldest || s.lastUsed < oldest.lastUsed)
|
|
301
|
+
oldest = s;
|
|
302
|
+
if (!oldest)
|
|
303
|
+
return;
|
|
304
|
+
if (oldest.name)
|
|
305
|
+
this.deleteRemote(base, apiKey, oldest.name);
|
|
306
|
+
this.slots.delete(oldest.key);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Best-effort DELETE of every live snapshot (session end). */
|
|
310
|
+
async disposeAll(apiKey, baseUrl = GEMINI_V1BETA_BASE) {
|
|
311
|
+
const names = this.liveNames();
|
|
312
|
+
this.slots.clear();
|
|
313
|
+
if (!apiKey || names.length === 0)
|
|
314
|
+
return;
|
|
315
|
+
await Promise.all(names.map((name) => this.fetchImpl(`${baseUrl}/${name}`, { method: 'DELETE', headers: { 'x-goog-api-key': apiKey } })
|
|
316
|
+
.then((r) => log(`deleted name=${name} status=${r.status} (dispose)`))
|
|
317
|
+
.catch(() => undefined)));
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/** HTTP statuses on a cached request that mean "the cache is the problem" → invalidate + full retry once. */
|
|
321
|
+
export function isCacheUseFailure(status) {
|
|
322
|
+
return status === 400 || status === 403 || status === 404;
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=geminiExplicitCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiExplicitCache.js","sourceRoot":"","sources":["../../src/orchestrator/geminiExplicitCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport reasoning-effort fixes (2026-10-02; stack-portability map
|
|
3
|
+
* .cortex/research/stack-portability-2026-10-02.md, note N1). Each is DARK behind its own env flag; with the flag off
|
|
4
|
+
* every caller takes its pre-existing code path unchanged (byte-identical requests).
|
|
5
|
+
*
|
|
6
|
+
* - CORTEX_OPENAI_TOOLS_REASONING: the gateway forwards the request/action effort for OpenAI reasoning cards even though they
|
|
7
|
+
* do not declare `reasoning.toggleable`, so CORTEX_ACTION_EFFORT reaches `reasoning.effort` on the RESPONSES API. Chat/completions
|
|
8
|
+
* is unchanged: R19b's drop stays because OpenAI still rejects reasoning_effort + function tools there (live probe 2026-10-03:
|
|
9
|
+
* gpt-5.4-nano + gpt-5.6-luna → 400 "use /v1/responses"); Responses accepts it with tools (200 on both).
|
|
10
|
+
* - CORTEX_ANTHROPIC_EFFORT: Anthropic adaptive-thinking families (claude-4.7 / 4.8 / claude-5 / claude-fable-5) got
|
|
11
|
+
* `thinking:{type:'adaptive'}` only, so the action effort never reached the wire. On: `output_config.effort` = the
|
|
12
|
+
* effort (low|medium|high|xhigh|max; GA, no beta header). Non-adaptive families: `max` was not in the budget map and
|
|
13
|
+
* fell to 10000; on, `max` maps to a large budget clamped below max_tokens (budget_tokens must be < max_tokens, >= 1024).
|
|
14
|
+
* - CORTEX_GEMINI_TOOLS_THINKING: Gemini thinkingConfig was never sent with tools (the @google/genai builders skipped
|
|
15
|
+
* it — "cannot coexist", a Gemini 2.0-era observation) and the REST builder only ever sent a card-level thinkingLevel.
|
|
16
|
+
* On: the action effort maps to generationConfig.thinkingConfig — `thinkingLevel` on Gemini 3.x, `thinkingBudget` on
|
|
17
|
+
* 2.5 and older — on REST and SDK, with or without tools.
|
|
18
|
+
*
|
|
19
|
+
* Pure helpers — no client state. Flags are resolved per call so tests/benches can flip them.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isOpenAIToolsReasoningEnabled(): boolean;
|
|
22
|
+
export declare function isAnthropicEffortEnabled(): boolean;
|
|
23
|
+
export declare function isGeminiToolsThinkingEnabled(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* `output_config.effort` value for an adaptive-thinking family, or undefined (send nothing → provider default).
|
|
26
|
+
* 'none' / unknown values send nothing (adaptive families have no "off" effort).
|
|
27
|
+
*/
|
|
28
|
+
export declare function anthropicOutputEffort(reasoningEffort: string | undefined): string | undefined;
|
|
29
|
+
/** Target thinking budget for effort `max` on budget_tokens families (before the max_tokens clamp). */
|
|
30
|
+
export declare const ANTHROPIC_MAX_EFFORT_BUDGET = 120000;
|
|
31
|
+
/** Visible-output room kept below max_tokens when clamping the `max` budget. */
|
|
32
|
+
export declare const ANTHROPIC_MAX_EFFORT_OUTPUT_ROOM = 1024;
|
|
33
|
+
/**
|
|
34
|
+
* budget_tokens for effort `max` on a non-adaptive family: ANTHROPIC_MAX_EFFORT_BUDGET clamped to
|
|
35
|
+
* max_tokens - ANTHROPIC_MAX_EFFORT_OUTPUT_ROOM (the API requires budget_tokens < max_tokens and >= 1024).
|
|
36
|
+
* Returns undefined when max_tokens is too small to honour the floor — the caller keeps its legacy value.
|
|
37
|
+
*/
|
|
38
|
+
export declare function anthropicMaxEffortBudget(maxTokens: number | undefined): number | undefined;
|
|
39
|
+
/** Gemini 3.x takes `thinkingLevel`; 2.5 and older take `thinkingBudget` (sending both is a 400). */
|
|
40
|
+
export declare function isGeminiThinkingLevelModel(modelId: string): boolean;
|
|
41
|
+
/** thinkingBudget per effort for Gemini 2.5 (Flash range 0-24576; Pro 128-32768 — every value here is valid on both). */
|
|
42
|
+
export declare const GEMINI_BUDGET_BY_EFFORT: Record<string, number>;
|
|
43
|
+
/** thinkingLevel per effort for Gemini 3.x (levels low|medium|high; xhigh/max clamp to high). */
|
|
44
|
+
export declare const GEMINI_LEVEL_BY_EFFORT: Record<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* The generationConfig.thinkingConfig for an effort, or undefined (none / unknown effort → send nothing, API default).
|
|
47
|
+
*/
|
|
48
|
+
export declare function geminiThinkingConfigForEffort(modelId: string, reasoningEffort: string | undefined): {
|
|
49
|
+
thinkingLevel: string;
|
|
50
|
+
} | {
|
|
51
|
+
thinkingBudget: number;
|
|
52
|
+
} | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* CORTEX_ACTION_EFFORT is filled into the request params AFTER the first request of each user turn is built
|
|
55
|
+
* (CortexOrchestrator initialPrepOpts vs the `??=` in the loop setup), so request 0 ran at the card default and
|
|
56
|
+
* requests 1+ at the action effort. On DeepSeek that is harmless (card 'medium' is coerced to 'high' server-side and
|
|
57
|
+
* the anchor-lift bust lands on the same boundary); on other providers it sends a different effort on request 0 and
|
|
58
|
+
* costs one extra cache break per user turn. DARK: CORTEX_ACTION_EFFORT_FIRST=on → request 0 gets the action effort
|
|
59
|
+
* when no ramp / request param set one. Off → undefined (byte-identical).
|
|
60
|
+
*/
|
|
61
|
+
export declare function firstRequestActionEffort(env?: NodeJS.ProcessEnv): string | undefined;
|
|
62
|
+
//# sourceMappingURL=transportEffortFixes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transportEffortFixes.d.ts","sourceRoot":"","sources":["../../src/orchestrator/transportEffortFixes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,wBAAgB,6BAA6B,IAAI,OAAO,CAEvD;AACD,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AACD,wBAAgB,4BAA4B,IAAI,OAAO,CAEtD;AAQD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG7F;AAED,uGAAuG;AACvG,eAAO,MAAM,2BAA2B,SAAS,CAAC;AAClD,gFAAgF;AAChF,eAAO,MAAM,gCAAgC,OAAO,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK1F;AAMD,qGAAqG;AACrG,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,yHAAyH;AACzH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM1D,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMzD,CAAC;AAEF;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQpE;AAMD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAIjG"}
|