@genesislcap/ai-assistant 15.22.2 → 15.23.1-FUI-0.4
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/dist/ai-assistant.api.json +269 -5
- package/dist/ai-assistant.d.ts +256 -31
- package/dist/chat-driver.cjs +197 -84
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +197 -84
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +5483 -5364
- package/dist/dts/components/ai-driver/ai-driver.d.ts +63 -0
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +7 -0
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +9 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/config/config.d.ts +53 -17
- package/dist/dts/config/config.d.ts.map +1 -1
- package/dist/dts/config/define-stateful-agent.d.ts +16 -1
- package/dist/dts/config/define-stateful-agent.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +102 -14
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/react.d.ts +12 -12
- package/dist/dts/utils/context-tokens.d.ts +100 -43
- package/dist/dts/utils/context-tokens.d.ts.map +1 -1
- package/dist/dts/utils/history-transform.d.ts +7 -1
- package/dist/dts/utils/history-transform.d.ts.map +1 -1
- package/dist/dts/utils/resolve-context-budget.d.ts +8 -5
- package/dist/dts/utils/resolve-context-budget.d.ts.map +1 -1
- package/dist/esm/components/chat-driver/chat-driver.js +22 -2
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +92 -0
- package/dist/esm/config/define-stateful-agent.js +1 -0
- package/dist/esm/main/main.js +170 -27
- package/dist/esm/utils/context-tokens.js +331 -106
- package/dist/esm/utils/history-transform.js +5 -5
- package/dist/esm/utils/resolve-context-budget.js +37 -7
- package/dist/react.cjs +21 -21
- package/dist/react.mjs +20 -20
- package/package.json +16 -16
package/dist/chat-driver.cjs
CHANGED
|
@@ -1205,6 +1205,7 @@ var SUPPORTED_GEMINI_MODEL_IDS = [
|
|
|
1205
1205
|
"gemini-2.5-pro",
|
|
1206
1206
|
"gemini-2.5-flash",
|
|
1207
1207
|
"gemini-2.5-flash-lite",
|
|
1208
|
+
"gemini-3.8-flash",
|
|
1208
1209
|
"gemini-3.5-flash",
|
|
1209
1210
|
"gemini-3.1-flash-lite",
|
|
1210
1211
|
"gemini-3.1-pro-preview"
|
|
@@ -1307,6 +1308,22 @@ var GEMINI_PRICING = {
|
|
|
1307
1308
|
rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 }
|
|
1308
1309
|
},
|
|
1309
1310
|
"gemini-3.5-flash": { kind: "flat", rate: { promptPerMillion: 1.5, candidatePerMillion: 9 } },
|
|
1311
|
+
// INTRODUCTORY RATE, and the only dated entry in this file. Google publishes
|
|
1312
|
+
// $0.75 / $3.75 per MTok **through 2026-12-31**, rising to $1.50 / $7.50 on 2027-01-01 —
|
|
1313
|
+
// so today this model is CHEAPER than gemini-3.5-flash above and in January it is not.
|
|
1314
|
+
//
|
|
1315
|
+
// The listed figure is the one in force, not the one coming. That is the lesson the
|
|
1316
|
+
// `claude-sonnet-5` entry records from the other direction: charging a scheduled future
|
|
1317
|
+
// rate early over-billed every request by 50% for as long as nobody noticed. A rate that
|
|
1318
|
+
// has not taken effect is not a price, and `GeminiPricing` deliberately has no time
|
|
1319
|
+
// dimension to express one — flip these two numbers on 2027-01-01 instead.
|
|
1320
|
+
//
|
|
1321
|
+
// That flip is ENFORCED, not remembered: `token-cost.test.ts` carries a dated assertion that
|
|
1322
|
+
// turns the build red on 2027-01-01 and names the three-line edit (these two rates, plus the
|
|
1323
|
+
// now-false `< gemini-3.5-flash` comparison in that same test — both models are $1.50 input
|
|
1324
|
+
// from that date). There is no ticket to lose.
|
|
1325
|
+
// https://ai.google.dev/gemini-api/docs/pricing
|
|
1326
|
+
"gemini-3.8-flash": { kind: "flat", rate: { promptPerMillion: 0.75, candidatePerMillion: 3.75 } },
|
|
1310
1327
|
"gemini-3.1-pro-preview": {
|
|
1311
1328
|
kind: "tiered",
|
|
1312
1329
|
standard: { promptPerMillion: 2, candidatePerMillion: 12 },
|
|
@@ -2793,6 +2810,7 @@ var GEMINI_CONTEXT_LIMITS = {
|
|
|
2793
2810
|
"gemini-2.5-pro": 1048576,
|
|
2794
2811
|
"gemini-2.5-flash": 1048576,
|
|
2795
2812
|
"gemini-2.5-flash-lite": 1048576,
|
|
2813
|
+
"gemini-3.8-flash": 1048576,
|
|
2796
2814
|
"gemini-3.5-flash": 1048576,
|
|
2797
2815
|
"gemini-3.1-flash-lite": 1048576,
|
|
2798
2816
|
"gemini-3.1-pro-preview": 1048576
|
|
@@ -2817,6 +2835,10 @@ var GEMINI_MODEL_WARNINGS = {
|
|
|
2817
2835
|
"gemini-2.5-flash": "GeminiTransport: using gemini-2.5-flash \u2014 higher cost than flash-lite; use for harder reasoning or agent tasks.",
|
|
2818
2836
|
"gemini-2.5-pro": "GeminiTransport: using gemini-2.5-pro \u2014 significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient.",
|
|
2819
2837
|
"gemini-3.5-flash": "GeminiTransport: using gemini-3.5-flash \u2014 frontier model, materially higher cost than flash-lite; use for harder reasoning or agent tasks.",
|
|
2838
|
+
// Warns despite currently costing LESS than gemini-3.5-flash, because that is temporary: the
|
|
2839
|
+
// rate doubles on 2027-01-01 (see GEMINI_PRICING). A caller that picks this tier on today's
|
|
2840
|
+
// price and never revisits the choice gets twice the bill in January without changing a line.
|
|
2841
|
+
"gemini-3.8-flash": "GeminiTransport: using gemini-3.8-flash \u2014 frontier model, materially higher cost than flash-lite. Its $0.75/$3.75 per-MTok rate is introductory and DOUBLES to $1.50/$7.50 on 2027-01-01; re-check this tier choice before then.",
|
|
2820
2842
|
"gemini-3.1-pro-preview": "GeminiTransport: using gemini-3.1-pro-preview \u2014 PREVIEW model (no stability guarantee, may be withdrawn) with significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient."
|
|
2821
2843
|
};
|
|
2822
2844
|
var GEMINI_THINKING_DISABLEABLE = [
|
|
@@ -2824,15 +2846,32 @@ var GEMINI_THINKING_DISABLEABLE = [
|
|
|
2824
2846
|
"gemini-2.5-flash-lite"
|
|
2825
2847
|
];
|
|
2826
2848
|
var GEMINI_MEDIA_RESOLUTION_TIERS = [
|
|
2849
|
+
"gemini-3.8-flash",
|
|
2827
2850
|
"gemini-3.5-flash",
|
|
2828
2851
|
"gemini-3.1-flash-lite",
|
|
2829
2852
|
"gemini-3.1-pro-preview"
|
|
2830
2853
|
];
|
|
2831
|
-
var
|
|
2832
|
-
|
|
2833
|
-
"gemini-3.
|
|
2834
|
-
"gemini-3.
|
|
2835
|
-
]
|
|
2854
|
+
var GEMINI_LEVEL_LADDER = ["minimal", "low", "medium", "high"];
|
|
2855
|
+
var GEMINI_THINKING_LEVELS = {
|
|
2856
|
+
"gemini-3.8-flash": ["low", "medium", "high"],
|
|
2857
|
+
"gemini-3.5-flash": ["minimal", "low", "medium", "high"],
|
|
2858
|
+
"gemini-3.1-flash-lite": ["minimal", "low", "medium", "high"],
|
|
2859
|
+
"gemini-3.1-pro-preview": ["low", "medium", "high"]
|
|
2860
|
+
};
|
|
2861
|
+
function clampThinkingLevel(supported, level) {
|
|
2862
|
+
if (!(supported === null || supported === void 0 ? void 0 : supported.length) || supported.includes(level)) {
|
|
2863
|
+
return level;
|
|
2864
|
+
}
|
|
2865
|
+
const target = GEMINI_LEVEL_LADDER.indexOf(level);
|
|
2866
|
+
const distance = (candidate) => Math.abs(GEMINI_LEVEL_LADDER.indexOf(candidate) - target);
|
|
2867
|
+
let best = supported[0];
|
|
2868
|
+
for (const candidate of supported) {
|
|
2869
|
+
if (distance(candidate) <= distance(best)) {
|
|
2870
|
+
best = candidate;
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
return best;
|
|
2874
|
+
}
|
|
2836
2875
|
var GEMINI_THINKING_LEVEL = {
|
|
2837
2876
|
minimal: "minimal",
|
|
2838
2877
|
low: "low",
|
|
@@ -2840,25 +2879,16 @@ var GEMINI_THINKING_LEVEL = {
|
|
|
2840
2879
|
high: "high",
|
|
2841
2880
|
max: "high"
|
|
2842
2881
|
};
|
|
2843
|
-
var GEMINI_COARSE_LEVEL_TIERS = [
|
|
2844
|
-
"gemini-3.5-flash",
|
|
2845
|
-
"gemini-3.1-flash-lite",
|
|
2846
|
-
"gemini-3.1-pro-preview"
|
|
2847
|
-
];
|
|
2848
|
-
var GEMINI_COARSE_LEVEL = {
|
|
2849
|
-
minimal: "low",
|
|
2850
|
-
low: "low",
|
|
2851
|
-
medium: "high",
|
|
2852
|
-
high: "high"
|
|
2853
|
-
};
|
|
2854
2882
|
var isGradedLevel = (p) => p !== void 0 && p !== "auto" && p !== "off";
|
|
2855
2883
|
function geminiThinkingConfig(model, policy) {
|
|
2856
|
-
if (isGradedLevel(policy)
|
|
2857
|
-
const
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2884
|
+
if (isGradedLevel(policy)) {
|
|
2885
|
+
const accepted = GEMINI_THINKING_LEVELS[model];
|
|
2886
|
+
if (accepted) {
|
|
2887
|
+
return {
|
|
2888
|
+
includeThoughts: true,
|
|
2889
|
+
thinkingLevel: clampThinkingLevel(accepted, GEMINI_THINKING_LEVEL[policy])
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2862
2892
|
}
|
|
2863
2893
|
if (policy === "off" && GEMINI_THINKING_DISABLEABLE.includes(model)) {
|
|
2864
2894
|
return { includeThoughts: false, thinkingBudget: 0 };
|
|
@@ -2899,7 +2929,7 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2899
2929
|
/**
|
|
2900
2930
|
* Warn once when a requested policy cannot be honoured on this model — a *cost* decision the
|
|
2901
2931
|
* caller made that the wire silently reversed, so they hear about it, but only once, not per
|
|
2902
|
-
* turn.
|
|
2932
|
+
* turn. Three shapes reach here (the Anthropic twin warns on the first two):
|
|
2903
2933
|
*
|
|
2904
2934
|
* - `'off'` on a tier that can't disable thinking — only the flash tiers accept a zero thinking
|
|
2905
2935
|
* budget; everything else keeps paying for reasoning it was told to stop. (`'auto'` is NOT this
|
|
@@ -2909,6 +2939,12 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2909
2939
|
* not the Gemini 3 `thinkingLevel` enum, so the level is dropped and the turn runs at the
|
|
2910
2940
|
* default posture. Without this, a caller asking for `high` on `gemini-2.5-pro` and quietly
|
|
2911
2941
|
* getting the default is left to wonder why.
|
|
2942
|
+
* - A graded depth whose DIALECT a Gemini 3 tier speaks but whose particular value it does not
|
|
2943
|
+
* accept — `minimal` on `gemini-3.8-flash` or `gemini-3.1-pro-preview`, the two tiers that
|
|
2944
|
+
* reject it outright. Nothing is dropped here; `clampThinkingLevel` MOVES the level onto the
|
|
2945
|
+
* nearest one the tier takes, and since ties resolve upward the move is usually to something
|
|
2946
|
+
* DEARER than the caller chose. A cost decision reversed on the wire in the expensive
|
|
2947
|
+
* direction is exactly what this warning exists for — without it the only trace is the bill.
|
|
2912
2948
|
*/
|
|
2913
2949
|
warnIfThinkingUnclampable(policy) {
|
|
2914
2950
|
if (this.warnedThinkingClamped) {
|
|
@@ -2919,9 +2955,19 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2919
2955
|
logger.warn(`GeminiTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} runs its default thinking posture and takes no budget we can safely set. Reasoning tokens are still billed at the candidate rate; use a flash tier if you need them gone.`);
|
|
2920
2956
|
return;
|
|
2921
2957
|
}
|
|
2922
|
-
if (isGradedLevel(policy)
|
|
2923
|
-
|
|
2924
|
-
|
|
2958
|
+
if (isGradedLevel(policy)) {
|
|
2959
|
+
const accepted = GEMINI_THINKING_LEVELS[this.model];
|
|
2960
|
+
if (!accepted) {
|
|
2961
|
+
this.warnedThinkingClamped = true;
|
|
2962
|
+
logger.warn(`GeminiTransport: thinkingPolicy '${policy}' ignored \u2014 ${this.model} takes a numeric thinking budget, not the graded 'thinkingLevel' the Gemini 3 tiers use, so this turn runs at its default reasoning posture. Use a Gemini 3 tier to set reasoning depth.`);
|
|
2963
|
+
return;
|
|
2964
|
+
}
|
|
2965
|
+
const requested = GEMINI_THINKING_LEVEL[policy];
|
|
2966
|
+
const sent = clampThinkingLevel(accepted, requested);
|
|
2967
|
+
if (sent !== requested) {
|
|
2968
|
+
this.warnedThinkingClamped = true;
|
|
2969
|
+
logger.warn(`GeminiTransport: thinkingPolicy '${policy}' sent as thinkingLevel '${sent}' \u2014 ${this.model} does not accept '${requested}' (it takes ${accepted.join("/")}). Reasoning bills at the candidate rate, so an upward clamp costs more than you asked for.`);
|
|
2970
|
+
}
|
|
2925
2971
|
}
|
|
2926
2972
|
}
|
|
2927
2973
|
constructor(config = {}) {
|
|
@@ -3812,6 +3858,21 @@ function createInteractionContext(interactionId) {
|
|
|
3812
3858
|
var APPROX_CHARS_PER_TOKEN = 4;
|
|
3813
3859
|
var IMAGE_TOKEN_ESTIMATE = 1600;
|
|
3814
3860
|
var PER_MESSAGE_FRAMING_TOKENS = 4;
|
|
3861
|
+
var PREAMBLE_PROSE_CHARS_PER_TOKEN = 4;
|
|
3862
|
+
var PREAMBLE_JSON_CHARS_PER_TOKEN = 3;
|
|
3863
|
+
var PER_TOOL_FRAMING_TOKENS = 8;
|
|
3864
|
+
function estimatePreambleTokens(input) {
|
|
3865
|
+
const prose = (input.systemPrompt?.length ?? 0) + (input.tailContext?.length ?? 0);
|
|
3866
|
+
let json = 0;
|
|
3867
|
+
for (const def of input.toolDefinitions ?? []) {
|
|
3868
|
+
try {
|
|
3869
|
+
json += JSON.stringify(def).length;
|
|
3870
|
+
} catch {
|
|
3871
|
+
json += def.name?.length ?? 0;
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
return Math.ceil(prose / PREAMBLE_PROSE_CHARS_PER_TOKEN) + Math.ceil(json / PREAMBLE_JSON_CHARS_PER_TOKEN) + (input.toolDefinitions?.length ?? 0) * PER_TOOL_FRAMING_TOKENS;
|
|
3875
|
+
}
|
|
3815
3876
|
var COMPACTION_SUMMARY_TOKEN_ESTIMATE = 1200;
|
|
3816
3877
|
function reachesProvider(m) {
|
|
3817
3878
|
if (m.role === "system-event" || m.role === "synthetic-user") return false;
|
|
@@ -3856,66 +3917,66 @@ function usableAnchor(m, compactedAt) {
|
|
|
3856
3917
|
function firstAnchor(history, compactedAt) {
|
|
3857
3918
|
return history.findIndex((m) => usableAnchor(m, compactedAt));
|
|
3858
3919
|
}
|
|
3859
|
-
function
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
const anchors = [];
|
|
3863
|
-
history.forEach((m, i) => {
|
|
3864
|
-
if (usableAnchor(m, compactedAt)) anchors.push(i);
|
|
3865
|
-
});
|
|
3866
|
-
for (let a = 0; a < anchors.length - 1; a += 1) {
|
|
3867
|
-
const from = anchors[a];
|
|
3868
|
-
const to = anchors[a + 1];
|
|
3869
|
-
const measured = history[to].inputTokens - history[from].inputTokens;
|
|
3870
|
-
if (measured <= 0) continue;
|
|
3871
|
-
let baseline = 0;
|
|
3872
|
-
for (let i = from; i < to; i += 1) baseline += estimates[i];
|
|
3873
|
-
if (baseline <= 0) {
|
|
3874
|
-
estimates[from] = measured;
|
|
3875
|
-
continue;
|
|
3876
|
-
}
|
|
3877
|
-
const scale = measured / baseline;
|
|
3878
|
-
let assigned = 0;
|
|
3879
|
-
for (let i = from; i < to - 1; i += 1) {
|
|
3880
|
-
estimates[i] = Math.round(estimates[i] * scale);
|
|
3881
|
-
assigned += estimates[i];
|
|
3882
|
-
}
|
|
3883
|
-
estimates[to - 1] = measured - assigned;
|
|
3920
|
+
function lastAnchor(history, compactedAt) {
|
|
3921
|
+
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
3922
|
+
if (usableAnchor(history[i], compactedAt)) return i;
|
|
3884
3923
|
}
|
|
3885
|
-
return
|
|
3924
|
+
return -1;
|
|
3886
3925
|
}
|
|
3887
|
-
function
|
|
3888
|
-
const
|
|
3889
|
-
|
|
3890
|
-
const
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
let
|
|
3905
|
-
|
|
3926
|
+
function calibrate(history, preambleTokens) {
|
|
3927
|
+
const baselines = history.map(baselineTokens);
|
|
3928
|
+
let baselineTotal = 0;
|
|
3929
|
+
for (const b of baselines) baselineTotal += b;
|
|
3930
|
+
const compactedAt = compactedAtOf(history);
|
|
3931
|
+
const first = firstAnchor(history, compactedAt);
|
|
3932
|
+
const last = lastAnchor(history, compactedAt);
|
|
3933
|
+
if (first < 0 || last < 0) {
|
|
3934
|
+
const measured = Math.max(0, preambleTokens ?? 0);
|
|
3935
|
+
return {
|
|
3936
|
+
overhead: measured,
|
|
3937
|
+
total: baselineTotal + measured,
|
|
3938
|
+
estimates: baselines,
|
|
3939
|
+
scale: 1
|
|
3940
|
+
};
|
|
3941
|
+
}
|
|
3942
|
+
let sinceLast = 0;
|
|
3943
|
+
for (let i = last; i < baselines.length; i += 1) sinceLast += baselines[i];
|
|
3944
|
+
const total = history[last].inputTokens + sinceLast;
|
|
3945
|
+
let beforeFirst = 0;
|
|
3946
|
+
for (let i = 0; i < first; i += 1) beforeFirst += baselines[i];
|
|
3947
|
+
const derived = Math.max(0, history[first].inputTokens - beforeFirst);
|
|
3948
|
+
const claimed = preambleTokens ?? derived;
|
|
3949
|
+
const contradicted = baselineTotal > 0 && claimed >= total;
|
|
3950
|
+
const overhead = Math.min(contradicted ? derived : claimed, total);
|
|
3951
|
+
const messages = Math.max(0, total - overhead);
|
|
3952
|
+
if (baselineTotal <= 0) {
|
|
3953
|
+
return { overhead, total, estimates: baselines, scale: 1 };
|
|
3954
|
+
}
|
|
3955
|
+
const scale = messages / baselineTotal;
|
|
3956
|
+
const estimates = baselines.map((b) => Math.round(b * scale));
|
|
3957
|
+
let assigned = 0;
|
|
3958
|
+
let heaviest = -1;
|
|
3959
|
+
for (let i = 0; i < estimates.length; i += 1) {
|
|
3960
|
+
assigned += estimates[i];
|
|
3961
|
+
if (baselines[i] > 0 && (heaviest < 0 || baselines[i] > baselines[heaviest])) heaviest = i;
|
|
3962
|
+
}
|
|
3963
|
+
if (heaviest >= 0) estimates[heaviest] += messages - assigned;
|
|
3964
|
+
return { overhead, total, estimates, scale };
|
|
3965
|
+
}
|
|
3966
|
+
function estimateMessageTokens(history, preambleTokens) {
|
|
3967
|
+
return calibrate(history, preambleTokens).estimates;
|
|
3968
|
+
}
|
|
3969
|
+
function estimateRequestTokens(storedHistory, requestHistory, preambleTokens) {
|
|
3970
|
+
const { overhead } = calibrate(storedHistory, preambleTokens);
|
|
3906
3971
|
let requestBaseline = 0;
|
|
3907
3972
|
for (const m of requestHistory) requestBaseline += baselineTokens(m);
|
|
3908
|
-
|
|
3909
|
-
return Math.round(overhead + calibratedMessages * (requestBaseline / storedBaseline));
|
|
3973
|
+
return Math.round(overhead + requestBaseline);
|
|
3910
3974
|
}
|
|
3911
|
-
function projectCompaction(history, cut, summaryTokens = COMPACTION_SUMMARY_TOKEN_ESTIMATE) {
|
|
3912
|
-
const estimates =
|
|
3913
|
-
const overhead = estimateSystemOverhead(history);
|
|
3975
|
+
function projectCompaction(history, cut, summaryTokens = COMPACTION_SUMMARY_TOKEN_ESTIMATE, preambleTokens) {
|
|
3976
|
+
const { estimates, overhead, total } = calibrate(history, preambleTokens);
|
|
3914
3977
|
let tail = 0;
|
|
3915
3978
|
for (let i = cut; i < estimates.length; i += 1) tail += estimates[i];
|
|
3916
|
-
|
|
3917
|
-
for (const t of estimates) all += t;
|
|
3918
|
-
const tokensBefore = overhead + all;
|
|
3979
|
+
const tokensBefore = total;
|
|
3919
3980
|
const tokensAfter = overhead + summaryTokens + tail;
|
|
3920
3981
|
return {
|
|
3921
3982
|
cut,
|
|
@@ -4183,8 +4244,8 @@ function isSafeCompactionCut(history, i) {
|
|
|
4183
4244
|
}
|
|
4184
4245
|
return true;
|
|
4185
4246
|
}
|
|
4186
|
-
function findCompactionCut(history, tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET) {
|
|
4187
|
-
const estimates = estimateMessageTokens(history);
|
|
4247
|
+
function findCompactionCut(history, tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET, preambleTokens) {
|
|
4248
|
+
const estimates = estimateMessageTokens(history, preambleTokens);
|
|
4188
4249
|
let messagesTotal = 0;
|
|
4189
4250
|
for (const t of estimates) messagesTotal += t;
|
|
4190
4251
|
if (messagesTotal <= tailTokenBudget) return null;
|
|
@@ -4205,9 +4266,14 @@ function planCompaction(history, options = {}) {
|
|
|
4205
4266
|
tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET,
|
|
4206
4267
|
minReclaimTokens = DEFAULT_MIN_RECLAIM_TOKENS
|
|
4207
4268
|
} = options;
|
|
4208
|
-
const cut = findCompactionCut(history, tailTokenBudget);
|
|
4269
|
+
const cut = findCompactionCut(history, tailTokenBudget, options.preambleTokens);
|
|
4209
4270
|
if (cut == null) return null;
|
|
4210
|
-
const projection = projectCompaction(
|
|
4271
|
+
const projection = projectCompaction(
|
|
4272
|
+
history,
|
|
4273
|
+
cut,
|
|
4274
|
+
COMPACTION_SUMMARY_TOKEN_ESTIMATE,
|
|
4275
|
+
options.preambleTokens
|
|
4276
|
+
);
|
|
4211
4277
|
return projection.reclaimed >= minReclaimTokens ? projection : null;
|
|
4212
4278
|
}
|
|
4213
4279
|
function renderMessageForSummary(m) {
|
|
@@ -5171,7 +5237,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
5171
5237
|
attachments: pendingInput.attachments
|
|
5172
5238
|
}
|
|
5173
5239
|
] : requestHistory;
|
|
5174
|
-
const estimated = estimateRequestTokens(this.history, request);
|
|
5240
|
+
const estimated = estimateRequestTokens(this.history, request, this.lastPreambleTokens);
|
|
5175
5241
|
if (estimated < threshold) return void 0;
|
|
5176
5242
|
logger2.error(
|
|
5177
5243
|
`ChatDriver: ending the turn \u2014 the request would fill the context window (~${estimated} of ${limit})`
|
|
@@ -5359,6 +5425,10 @@ Output format (strict):
|
|
|
5359
5425
|
this.loadHistory([summaryMessage, ...tail]);
|
|
5360
5426
|
return summaryMessage;
|
|
5361
5427
|
}
|
|
5428
|
+
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
5429
|
+
getPreambleTokens() {
|
|
5430
|
+
return this.lastPreambleTokens;
|
|
5431
|
+
}
|
|
5362
5432
|
isBusy() {
|
|
5363
5433
|
return this.busy;
|
|
5364
5434
|
}
|
|
@@ -6221,6 +6291,11 @@ ${tailBody}
|
|
|
6221
6291
|
const attachmentsForCall = currentAttachments;
|
|
6222
6292
|
currentInput = "";
|
|
6223
6293
|
currentAttachments = void 0;
|
|
6294
|
+
this.lastPreambleTokens = estimatePreambleTokens({
|
|
6295
|
+
systemPrompt,
|
|
6296
|
+
toolDefinitions: this.toolDefinitions,
|
|
6297
|
+
tailContext
|
|
6298
|
+
});
|
|
6224
6299
|
const options = {
|
|
6225
6300
|
systemPrompt,
|
|
6226
6301
|
// Strip fold-only properties (foldEvent, foldPath) before sending to provider
|
|
@@ -6890,6 +6965,13 @@ function isSpecialist(agent) {
|
|
|
6890
6965
|
function isFallback(agent) {
|
|
6891
6966
|
return agent.fallback === true;
|
|
6892
6967
|
}
|
|
6968
|
+
function normalizeContextReserve(input) {
|
|
6969
|
+
if (input == null) return void 0;
|
|
6970
|
+
const positive = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
|
|
6971
|
+
if (typeof input === "number") return positive(input) ? { tokens: input } : void 0;
|
|
6972
|
+
if (!positive(input.tokens)) return void 0;
|
|
6973
|
+
return positive(input.warnAheadTokens) ? { tokens: input.tokens, warnAheadTokens: input.warnAheadTokens } : { tokens: input.tokens };
|
|
6974
|
+
}
|
|
6893
6975
|
var UNROUTABLE_PLACEHOLDER = "{{unroutable}}";
|
|
6894
6976
|
var UNROUTABLE_INSTRUCTION = `When the request is substantive but nothing above covers it, say so directly. Do not offer to do it yourself, and do not imply a specialist will pick it up.
|
|
6895
6977
|
|
|
@@ -7091,6 +7173,10 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
7091
7173
|
canCompact(options) {
|
|
7092
7174
|
return this.chatDriver.canCompact(options);
|
|
7093
7175
|
}
|
|
7176
|
+
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
7177
|
+
getPreambleTokens() {
|
|
7178
|
+
return this.chatDriver.getPreambleTokens();
|
|
7179
|
+
}
|
|
7094
7180
|
/** {@inheritDoc AiDriver.getCompactionPlan} */
|
|
7095
7181
|
getCompactionPlan(options) {
|
|
7096
7182
|
return this.chatDriver.getCompactionPlan(options);
|
|
@@ -7212,6 +7298,32 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
7212
7298
|
primeRestoredAgentState(snapshots) {
|
|
7213
7299
|
this.restoredAgentStates = { ...snapshots };
|
|
7214
7300
|
}
|
|
7301
|
+
/**
|
|
7302
|
+
* {@inheritDoc AiDriver.getContextReserve}
|
|
7303
|
+
*
|
|
7304
|
+
* Two cases, because routing has two modes and they need opposite answers.
|
|
7305
|
+
*/
|
|
7306
|
+
getContextReserve() {
|
|
7307
|
+
const locked = this.resolvePinnedAgent();
|
|
7308
|
+
if (locked) {
|
|
7309
|
+
const reserve = normalizeContextReserve(locked.contextReserve);
|
|
7310
|
+
return reserve == null ? void 0 : { ...reserve, agentName: locked.name, basis: "locked" };
|
|
7311
|
+
}
|
|
7312
|
+
const candidates = [...this.specialists];
|
|
7313
|
+
if (this.fallback) candidates.push(this.fallback);
|
|
7314
|
+
if (this.activeAgent) candidates.push(this.activeAgent);
|
|
7315
|
+
let winner;
|
|
7316
|
+
let agentName = "";
|
|
7317
|
+
for (const agent of candidates) {
|
|
7318
|
+
const reserve = normalizeContextReserve(agent.contextReserve);
|
|
7319
|
+
if (!reserve) continue;
|
|
7320
|
+
if (!winner || reserve.tokens > winner.tokens) {
|
|
7321
|
+
winner = reserve;
|
|
7322
|
+
agentName = agent.name;
|
|
7323
|
+
}
|
|
7324
|
+
}
|
|
7325
|
+
return winner ? { ...winner, agentName, basis: "reachable-max" } : void 0;
|
|
7326
|
+
}
|
|
7215
7327
|
/** {@inheritDoc AiDriver.getActiveAgent} */
|
|
7216
7328
|
getActiveAgent() {
|
|
7217
7329
|
return this.activeAgent;
|
|
@@ -7721,6 +7833,7 @@ function defineStatefulAgent(opts) {
|
|
|
7721
7833
|
onUnresolvedTool: wrappedOnUnresolvedTool,
|
|
7722
7834
|
resumable: wrappedResumable,
|
|
7723
7835
|
notResumableMessage: opts.notResumableMessage,
|
|
7836
|
+
contextReserve: opts.contextReserve,
|
|
7724
7837
|
onActivate: async (ctx) => {
|
|
7725
7838
|
state = await opts.init(ctx);
|
|
7726
7839
|
if (opts.toolHandlers) {
|