@nexus-cortex/core 4.124.46 → 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.
Files changed (50) hide show
  1. package/.env.defaults +49 -1
  2. package/dist/adapters/ChatCompletionsAPIAdapter.d.ts.map +1 -1
  3. package/dist/adapters/ChatCompletionsAPIAdapter.js +10 -0
  4. package/dist/adapters/ChatCompletionsAPIAdapter.js.map +1 -1
  5. package/dist/adapters/GatewayTranslationLayer.d.ts.map +1 -1
  6. package/dist/adapters/GatewayTranslationLayer.js +10 -0
  7. package/dist/adapters/GatewayTranslationLayer.js.map +1 -1
  8. package/dist/adapters/ServerSideToolDetection.d.ts.map +1 -1
  9. package/dist/adapters/ServerSideToolDetection.js +5 -1
  10. package/dist/adapters/ServerSideToolDetection.js.map +1 -1
  11. package/dist/config/SettingsSchema.js +2 -2
  12. package/dist/config/SettingsSchema.js.map +1 -1
  13. package/dist/config/effectiveConfig.d.ts.map +1 -1
  14. package/dist/config/effectiveConfig.js +5 -0
  15. package/dist/config/effectiveConfig.js.map +1 -1
  16. package/dist/models/cards/xai/grok-4-3-chat.d.ts +15 -0
  17. package/dist/models/cards/xai/grok-4-3-chat.d.ts.map +1 -0
  18. package/dist/models/cards/xai/grok-4-3-chat.js +28 -0
  19. package/dist/models/cards/xai/grok-4-3-chat.js.map +1 -0
  20. package/dist/models/cards/xai/grok-build-0-1-chat.d.ts +17 -0
  21. package/dist/models/cards/xai/grok-build-0-1-chat.d.ts.map +1 -0
  22. package/dist/models/cards/xai/grok-build-0-1-chat.js +31 -0
  23. package/dist/models/cards/xai/grok-build-0-1-chat.js.map +1 -0
  24. package/dist/models/cards/xai/index.d.ts +2 -0
  25. package/dist/models/cards/xai/index.d.ts.map +1 -1
  26. package/dist/models/cards/xai/index.js +2 -0
  27. package/dist/models/cards/xai/index.js.map +1 -1
  28. package/dist/models/configurators/XAIConfigurator.d.ts +7 -1
  29. package/dist/models/configurators/XAIConfigurator.d.ts.map +1 -1
  30. package/dist/models/configurators/XAIConfigurator.js +15 -3
  31. package/dist/models/configurators/XAIConfigurator.js.map +1 -1
  32. package/dist/models/registry/ModularModelRegistry.d.ts.map +1 -1
  33. package/dist/models/registry/ModularModelRegistry.js +2 -0
  34. package/dist/models/registry/ModularModelRegistry.js.map +1 -1
  35. package/dist/orchestrator/APIClient.d.ts +4 -0
  36. package/dist/orchestrator/APIClient.d.ts.map +1 -1
  37. package/dist/orchestrator/APIClient.js +127 -10
  38. package/dist/orchestrator/APIClient.js.map +1 -1
  39. package/dist/orchestrator/CortexOrchestrator.d.ts.map +1 -1
  40. package/dist/orchestrator/CortexOrchestrator.js +5 -0
  41. package/dist/orchestrator/CortexOrchestrator.js.map +1 -1
  42. package/dist/orchestrator/geminiExplicitCache.d.ts +79 -0
  43. package/dist/orchestrator/geminiExplicitCache.d.ts.map +1 -0
  44. package/dist/orchestrator/geminiExplicitCache.js +324 -0
  45. package/dist/orchestrator/geminiExplicitCache.js.map +1 -0
  46. package/dist/orchestrator/xaiChatTransport.d.ts +27 -0
  47. package/dist/orchestrator/xaiChatTransport.d.ts.map +1 -0
  48. package/dist/orchestrator/xaiChatTransport.js +33 -0
  49. package/dist/orchestrator/xaiChatTransport.js.map +1 -0
  50. package/package.json +3 -3
@@ -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,27 @@
1
+ /**
2
+ * xAI chat/completions transport helpers (2026-10-03; stack-portability map
3
+ * .cortex/research/stack-portability-2026-10-02.md §"xAI CHAT/COMPLETIONS THEORY TEST").
4
+ *
5
+ * The third xAI transport, ADDITIVE beside /v1/messages (the interleaved-thinking path — untouched) and /v1/responses.
6
+ * Selected per card (`apiMode: 'chat'`, e.g. grok-4.3-chat / grok-build-0.1-chat) or globally for un-pinned xAI cards via
7
+ * XAI_API_MODE=chat. Reachable ONLY when an xAI card resolves to pattern 'chat/completions' — nothing on the shipped default
8
+ * path does, so every helper here is dark by construction.
9
+ *
10
+ * Pure helpers — no client state.
11
+ */
12
+ import type { ModelConfig } from '../models/ModelConfig.interface.js';
13
+ /** True when this request rides api.x.ai /v1/chat/completions. */
14
+ export declare function isXAIChatRoute(modelConfig: Pick<ModelConfig, 'provider' | 'api'>): boolean;
15
+ /**
16
+ * `reasoning_effort` for an xAI chat/completions request, or undefined (send nothing → provider default, 'high').
17
+ *
18
+ * Per-card capability: a card that declares no default effort (`reasoning.defaultEffort` / `reasoning.effort` — the
19
+ * XAIConfigurator `reasoningEffort` option) NEVER gets the field. grok-build-0.1 400s on it ("does not support parameter
20
+ * reasoningEffort", live 2026-10-02) and its cards deliberately omit `reasoningEffort`.
21
+ *
22
+ * Precedence: explicit request / action effort (CORTEX_ACTION_EFFORT, effort pulse) > card default. Mapping: the harness's
23
+ * `max` (the DeepSeek ladder top) → `high` (xAI has no `max`; `xhigh` is not accepted on every grok — pass it explicitly to
24
+ * use it); `none` / unknown → the card default (xAI reasoning cannot be disabled).
25
+ */
26
+ export declare function xaiChatReasoningEffort(requested: unknown, modelConfig: Pick<ModelConfig, 'reasoning'>): string | undefined;
27
+ //# sourceMappingURL=xaiChatTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xaiChatTransport.d.ts","sourceRoot":"","sources":["../../src/orchestrator/xaiChatTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEtE,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,KAAK,CAAC,GAAG,OAAO,CAE1F;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAW1H"}
@@ -0,0 +1,33 @@
1
+ /** True when this request rides api.x.ai /v1/chat/completions. */
2
+ export function isXAIChatRoute(modelConfig) {
3
+ return modelConfig.api?.pattern === 'chat/completions' && String(modelConfig.provider ?? '').toLowerCase() === 'xai';
4
+ }
5
+ /** xAI reasoning_effort values (docs: model-capabilities/text/reasoning). `xhigh` = grok-4.6+; older models treat it as high. */
6
+ const XAI_EFFORT_LEVELS = new Set(['low', 'medium', 'high', 'xhigh']);
7
+ /**
8
+ * `reasoning_effort` for an xAI chat/completions request, or undefined (send nothing → provider default, 'high').
9
+ *
10
+ * Per-card capability: a card that declares no default effort (`reasoning.defaultEffort` / `reasoning.effort` — the
11
+ * XAIConfigurator `reasoningEffort` option) NEVER gets the field. grok-build-0.1 400s on it ("does not support parameter
12
+ * reasoningEffort", live 2026-10-02) and its cards deliberately omit `reasoningEffort`.
13
+ *
14
+ * Precedence: explicit request / action effort (CORTEX_ACTION_EFFORT, effort pulse) > card default. Mapping: the harness's
15
+ * `max` (the DeepSeek ladder top) → `high` (xAI has no `max`; `xhigh` is not accepted on every grok — pass it explicitly to
16
+ * use it); `none` / unknown → the card default (xAI reasoning cannot be disabled).
17
+ */
18
+ export function xaiChatReasoningEffort(requested, modelConfig) {
19
+ const r = modelConfig.reasoning;
20
+ if (!r?.supported)
21
+ return undefined;
22
+ const cardDefault = r.effort ?? r.defaultEffort;
23
+ if (!cardDefault)
24
+ return undefined; // capability gate — no declared effort, no field
25
+ const norm = (v) => {
26
+ const e = String(v ?? '').trim().toLowerCase();
27
+ if (e === 'max')
28
+ return 'high';
29
+ return XAI_EFFORT_LEVELS.has(e) ? e : undefined;
30
+ };
31
+ return norm(requested) ?? norm(cardDefault);
32
+ }
33
+ //# sourceMappingURL=xaiChatTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xaiChatTransport.js","sourceRoot":"","sources":["../../src/orchestrator/xaiChatTransport.ts"],"names":[],"mappings":"AAaA,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,WAAkD;IAC/E,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,KAAK,kBAAkB,IAAI,MAAM,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;AACvH,CAAC;AAED,iIAAiI;AACjI,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAkB,EAAE,WAA2C;IACpG,MAAM,CAAC,GAAG,WAAW,CAAC,SAAyF,CAAC;IAChH,IAAI,CAAC,CAAC,EAAE,SAAS;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,CAAC;IAChD,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAC,CAAC,iDAAiD;IACrF,MAAM,IAAI,GAAG,CAAC,CAAU,EAAsB,EAAE;QAC9C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,IAAI,CAAC,KAAK,KAAK;YAAE,OAAO,MAAM,CAAC;QAC/B,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC;AAC9C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexus-cortex/core",
3
- "version": "4.124.46",
3
+ "version": "4.124.47",
4
4
  "description": "Core orchestration library implementing Claude CLI architecture patterns",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -47,8 +47,8 @@
47
47
  "@google/generative-ai": "^0.2.1",
48
48
  "@gradio/client": "^2.3.1",
49
49
  "@modelcontextprotocol/sdk": "^1.20.2",
50
- "@nexus-cortex/executors": "4.124.46",
51
- "@nexus-cortex/types": "4.124.46",
50
+ "@nexus-cortex/executors": "4.124.47",
51
+ "@nexus-cortex/types": "4.124.47",
52
52
  "@types/uuid": "^10.0.0",
53
53
  "ajv": "^8.12.0",
54
54
  "chokidar": "^3.6.0",