@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.mjs
CHANGED
|
@@ -1134,6 +1134,7 @@ var SUPPORTED_GEMINI_MODEL_IDS = [
|
|
|
1134
1134
|
"gemini-2.5-pro",
|
|
1135
1135
|
"gemini-2.5-flash",
|
|
1136
1136
|
"gemini-2.5-flash-lite",
|
|
1137
|
+
"gemini-3.8-flash",
|
|
1137
1138
|
"gemini-3.5-flash",
|
|
1138
1139
|
"gemini-3.1-flash-lite",
|
|
1139
1140
|
"gemini-3.1-pro-preview"
|
|
@@ -1236,6 +1237,22 @@ var GEMINI_PRICING = {
|
|
|
1236
1237
|
rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 }
|
|
1237
1238
|
},
|
|
1238
1239
|
"gemini-3.5-flash": { kind: "flat", rate: { promptPerMillion: 1.5, candidatePerMillion: 9 } },
|
|
1240
|
+
// INTRODUCTORY RATE, and the only dated entry in this file. Google publishes
|
|
1241
|
+
// $0.75 / $3.75 per MTok **through 2026-12-31**, rising to $1.50 / $7.50 on 2027-01-01 —
|
|
1242
|
+
// so today this model is CHEAPER than gemini-3.5-flash above and in January it is not.
|
|
1243
|
+
//
|
|
1244
|
+
// The listed figure is the one in force, not the one coming. That is the lesson the
|
|
1245
|
+
// `claude-sonnet-5` entry records from the other direction: charging a scheduled future
|
|
1246
|
+
// rate early over-billed every request by 50% for as long as nobody noticed. A rate that
|
|
1247
|
+
// has not taken effect is not a price, and `GeminiPricing` deliberately has no time
|
|
1248
|
+
// dimension to express one — flip these two numbers on 2027-01-01 instead.
|
|
1249
|
+
//
|
|
1250
|
+
// That flip is ENFORCED, not remembered: `token-cost.test.ts` carries a dated assertion that
|
|
1251
|
+
// turns the build red on 2027-01-01 and names the three-line edit (these two rates, plus the
|
|
1252
|
+
// now-false `< gemini-3.5-flash` comparison in that same test — both models are $1.50 input
|
|
1253
|
+
// from that date). There is no ticket to lose.
|
|
1254
|
+
// https://ai.google.dev/gemini-api/docs/pricing
|
|
1255
|
+
"gemini-3.8-flash": { kind: "flat", rate: { promptPerMillion: 0.75, candidatePerMillion: 3.75 } },
|
|
1239
1256
|
"gemini-3.1-pro-preview": {
|
|
1240
1257
|
kind: "tiered",
|
|
1241
1258
|
standard: { promptPerMillion: 2, candidatePerMillion: 12 },
|
|
@@ -2722,6 +2739,7 @@ var GEMINI_CONTEXT_LIMITS = {
|
|
|
2722
2739
|
"gemini-2.5-pro": 1048576,
|
|
2723
2740
|
"gemini-2.5-flash": 1048576,
|
|
2724
2741
|
"gemini-2.5-flash-lite": 1048576,
|
|
2742
|
+
"gemini-3.8-flash": 1048576,
|
|
2725
2743
|
"gemini-3.5-flash": 1048576,
|
|
2726
2744
|
"gemini-3.1-flash-lite": 1048576,
|
|
2727
2745
|
"gemini-3.1-pro-preview": 1048576
|
|
@@ -2746,6 +2764,10 @@ var GEMINI_MODEL_WARNINGS = {
|
|
|
2746
2764
|
"gemini-2.5-flash": "GeminiTransport: using gemini-2.5-flash \u2014 higher cost than flash-lite; use for harder reasoning or agent tasks.",
|
|
2747
2765
|
"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.",
|
|
2748
2766
|
"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.",
|
|
2767
|
+
// Warns despite currently costing LESS than gemini-3.5-flash, because that is temporary: the
|
|
2768
|
+
// rate doubles on 2027-01-01 (see GEMINI_PRICING). A caller that picks this tier on today's
|
|
2769
|
+
// price and never revisits the choice gets twice the bill in January without changing a line.
|
|
2770
|
+
"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.",
|
|
2749
2771
|
"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."
|
|
2750
2772
|
};
|
|
2751
2773
|
var GEMINI_THINKING_DISABLEABLE = [
|
|
@@ -2753,15 +2775,32 @@ var GEMINI_THINKING_DISABLEABLE = [
|
|
|
2753
2775
|
"gemini-2.5-flash-lite"
|
|
2754
2776
|
];
|
|
2755
2777
|
var GEMINI_MEDIA_RESOLUTION_TIERS = [
|
|
2778
|
+
"gemini-3.8-flash",
|
|
2756
2779
|
"gemini-3.5-flash",
|
|
2757
2780
|
"gemini-3.1-flash-lite",
|
|
2758
2781
|
"gemini-3.1-pro-preview"
|
|
2759
2782
|
];
|
|
2760
|
-
var
|
|
2761
|
-
|
|
2762
|
-
"gemini-3.
|
|
2763
|
-
"gemini-3.
|
|
2764
|
-
]
|
|
2783
|
+
var GEMINI_LEVEL_LADDER = ["minimal", "low", "medium", "high"];
|
|
2784
|
+
var GEMINI_THINKING_LEVELS = {
|
|
2785
|
+
"gemini-3.8-flash": ["low", "medium", "high"],
|
|
2786
|
+
"gemini-3.5-flash": ["minimal", "low", "medium", "high"],
|
|
2787
|
+
"gemini-3.1-flash-lite": ["minimal", "low", "medium", "high"],
|
|
2788
|
+
"gemini-3.1-pro-preview": ["low", "medium", "high"]
|
|
2789
|
+
};
|
|
2790
|
+
function clampThinkingLevel(supported, level) {
|
|
2791
|
+
if (!(supported === null || supported === void 0 ? void 0 : supported.length) || supported.includes(level)) {
|
|
2792
|
+
return level;
|
|
2793
|
+
}
|
|
2794
|
+
const target = GEMINI_LEVEL_LADDER.indexOf(level);
|
|
2795
|
+
const distance = (candidate) => Math.abs(GEMINI_LEVEL_LADDER.indexOf(candidate) - target);
|
|
2796
|
+
let best = supported[0];
|
|
2797
|
+
for (const candidate of supported) {
|
|
2798
|
+
if (distance(candidate) <= distance(best)) {
|
|
2799
|
+
best = candidate;
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
return best;
|
|
2803
|
+
}
|
|
2765
2804
|
var GEMINI_THINKING_LEVEL = {
|
|
2766
2805
|
minimal: "minimal",
|
|
2767
2806
|
low: "low",
|
|
@@ -2769,25 +2808,16 @@ var GEMINI_THINKING_LEVEL = {
|
|
|
2769
2808
|
high: "high",
|
|
2770
2809
|
max: "high"
|
|
2771
2810
|
};
|
|
2772
|
-
var GEMINI_COARSE_LEVEL_TIERS = [
|
|
2773
|
-
"gemini-3.5-flash",
|
|
2774
|
-
"gemini-3.1-flash-lite",
|
|
2775
|
-
"gemini-3.1-pro-preview"
|
|
2776
|
-
];
|
|
2777
|
-
var GEMINI_COARSE_LEVEL = {
|
|
2778
|
-
minimal: "low",
|
|
2779
|
-
low: "low",
|
|
2780
|
-
medium: "high",
|
|
2781
|
-
high: "high"
|
|
2782
|
-
};
|
|
2783
2811
|
var isGradedLevel = (p) => p !== void 0 && p !== "auto" && p !== "off";
|
|
2784
2812
|
function geminiThinkingConfig(model, policy) {
|
|
2785
|
-
if (isGradedLevel(policy)
|
|
2786
|
-
const
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2813
|
+
if (isGradedLevel(policy)) {
|
|
2814
|
+
const accepted = GEMINI_THINKING_LEVELS[model];
|
|
2815
|
+
if (accepted) {
|
|
2816
|
+
return {
|
|
2817
|
+
includeThoughts: true,
|
|
2818
|
+
thinkingLevel: clampThinkingLevel(accepted, GEMINI_THINKING_LEVEL[policy])
|
|
2819
|
+
};
|
|
2820
|
+
}
|
|
2791
2821
|
}
|
|
2792
2822
|
if (policy === "off" && GEMINI_THINKING_DISABLEABLE.includes(model)) {
|
|
2793
2823
|
return { includeThoughts: false, thinkingBudget: 0 };
|
|
@@ -2828,7 +2858,7 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2828
2858
|
/**
|
|
2829
2859
|
* Warn once when a requested policy cannot be honoured on this model — a *cost* decision the
|
|
2830
2860
|
* caller made that the wire silently reversed, so they hear about it, but only once, not per
|
|
2831
|
-
* turn.
|
|
2861
|
+
* turn. Three shapes reach here (the Anthropic twin warns on the first two):
|
|
2832
2862
|
*
|
|
2833
2863
|
* - `'off'` on a tier that can't disable thinking — only the flash tiers accept a zero thinking
|
|
2834
2864
|
* budget; everything else keeps paying for reasoning it was told to stop. (`'auto'` is NOT this
|
|
@@ -2838,6 +2868,12 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2838
2868
|
* not the Gemini 3 `thinkingLevel` enum, so the level is dropped and the turn runs at the
|
|
2839
2869
|
* default posture. Without this, a caller asking for `high` on `gemini-2.5-pro` and quietly
|
|
2840
2870
|
* getting the default is left to wonder why.
|
|
2871
|
+
* - A graded depth whose DIALECT a Gemini 3 tier speaks but whose particular value it does not
|
|
2872
|
+
* accept — `minimal` on `gemini-3.8-flash` or `gemini-3.1-pro-preview`, the two tiers that
|
|
2873
|
+
* reject it outright. Nothing is dropped here; `clampThinkingLevel` MOVES the level onto the
|
|
2874
|
+
* nearest one the tier takes, and since ties resolve upward the move is usually to something
|
|
2875
|
+
* DEARER than the caller chose. A cost decision reversed on the wire in the expensive
|
|
2876
|
+
* direction is exactly what this warning exists for — without it the only trace is the bill.
|
|
2841
2877
|
*/
|
|
2842
2878
|
warnIfThinkingUnclampable(policy) {
|
|
2843
2879
|
if (this.warnedThinkingClamped) {
|
|
@@ -2848,9 +2884,19 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2848
2884
|
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.`);
|
|
2849
2885
|
return;
|
|
2850
2886
|
}
|
|
2851
|
-
if (isGradedLevel(policy)
|
|
2852
|
-
|
|
2853
|
-
|
|
2887
|
+
if (isGradedLevel(policy)) {
|
|
2888
|
+
const accepted = GEMINI_THINKING_LEVELS[this.model];
|
|
2889
|
+
if (!accepted) {
|
|
2890
|
+
this.warnedThinkingClamped = true;
|
|
2891
|
+
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.`);
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2894
|
+
const requested = GEMINI_THINKING_LEVEL[policy];
|
|
2895
|
+
const sent = clampThinkingLevel(accepted, requested);
|
|
2896
|
+
if (sent !== requested) {
|
|
2897
|
+
this.warnedThinkingClamped = true;
|
|
2898
|
+
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.`);
|
|
2899
|
+
}
|
|
2854
2900
|
}
|
|
2855
2901
|
}
|
|
2856
2902
|
constructor(config = {}) {
|
|
@@ -3741,6 +3787,21 @@ function createInteractionContext(interactionId) {
|
|
|
3741
3787
|
var APPROX_CHARS_PER_TOKEN = 4;
|
|
3742
3788
|
var IMAGE_TOKEN_ESTIMATE = 1600;
|
|
3743
3789
|
var PER_MESSAGE_FRAMING_TOKENS = 4;
|
|
3790
|
+
var PREAMBLE_PROSE_CHARS_PER_TOKEN = 4;
|
|
3791
|
+
var PREAMBLE_JSON_CHARS_PER_TOKEN = 3;
|
|
3792
|
+
var PER_TOOL_FRAMING_TOKENS = 8;
|
|
3793
|
+
function estimatePreambleTokens(input) {
|
|
3794
|
+
const prose = (input.systemPrompt?.length ?? 0) + (input.tailContext?.length ?? 0);
|
|
3795
|
+
let json = 0;
|
|
3796
|
+
for (const def of input.toolDefinitions ?? []) {
|
|
3797
|
+
try {
|
|
3798
|
+
json += JSON.stringify(def).length;
|
|
3799
|
+
} catch {
|
|
3800
|
+
json += def.name?.length ?? 0;
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
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;
|
|
3804
|
+
}
|
|
3744
3805
|
var COMPACTION_SUMMARY_TOKEN_ESTIMATE = 1200;
|
|
3745
3806
|
function reachesProvider(m) {
|
|
3746
3807
|
if (m.role === "system-event" || m.role === "synthetic-user") return false;
|
|
@@ -3785,66 +3846,66 @@ function usableAnchor(m, compactedAt) {
|
|
|
3785
3846
|
function firstAnchor(history, compactedAt) {
|
|
3786
3847
|
return history.findIndex((m) => usableAnchor(m, compactedAt));
|
|
3787
3848
|
}
|
|
3788
|
-
function
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
const anchors = [];
|
|
3792
|
-
history.forEach((m, i) => {
|
|
3793
|
-
if (usableAnchor(m, compactedAt)) anchors.push(i);
|
|
3794
|
-
});
|
|
3795
|
-
for (let a = 0; a < anchors.length - 1; a += 1) {
|
|
3796
|
-
const from = anchors[a];
|
|
3797
|
-
const to = anchors[a + 1];
|
|
3798
|
-
const measured = history[to].inputTokens - history[from].inputTokens;
|
|
3799
|
-
if (measured <= 0) continue;
|
|
3800
|
-
let baseline = 0;
|
|
3801
|
-
for (let i = from; i < to; i += 1) baseline += estimates[i];
|
|
3802
|
-
if (baseline <= 0) {
|
|
3803
|
-
estimates[from] = measured;
|
|
3804
|
-
continue;
|
|
3805
|
-
}
|
|
3806
|
-
const scale = measured / baseline;
|
|
3807
|
-
let assigned = 0;
|
|
3808
|
-
for (let i = from; i < to - 1; i += 1) {
|
|
3809
|
-
estimates[i] = Math.round(estimates[i] * scale);
|
|
3810
|
-
assigned += estimates[i];
|
|
3811
|
-
}
|
|
3812
|
-
estimates[to - 1] = measured - assigned;
|
|
3849
|
+
function lastAnchor(history, compactedAt) {
|
|
3850
|
+
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
3851
|
+
if (usableAnchor(history[i], compactedAt)) return i;
|
|
3813
3852
|
}
|
|
3814
|
-
return
|
|
3853
|
+
return -1;
|
|
3815
3854
|
}
|
|
3816
|
-
function
|
|
3817
|
-
const
|
|
3818
|
-
|
|
3819
|
-
const
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
let
|
|
3834
|
-
|
|
3855
|
+
function calibrate(history, preambleTokens) {
|
|
3856
|
+
const baselines = history.map(baselineTokens);
|
|
3857
|
+
let baselineTotal = 0;
|
|
3858
|
+
for (const b of baselines) baselineTotal += b;
|
|
3859
|
+
const compactedAt = compactedAtOf(history);
|
|
3860
|
+
const first = firstAnchor(history, compactedAt);
|
|
3861
|
+
const last = lastAnchor(history, compactedAt);
|
|
3862
|
+
if (first < 0 || last < 0) {
|
|
3863
|
+
const measured = Math.max(0, preambleTokens ?? 0);
|
|
3864
|
+
return {
|
|
3865
|
+
overhead: measured,
|
|
3866
|
+
total: baselineTotal + measured,
|
|
3867
|
+
estimates: baselines,
|
|
3868
|
+
scale: 1
|
|
3869
|
+
};
|
|
3870
|
+
}
|
|
3871
|
+
let sinceLast = 0;
|
|
3872
|
+
for (let i = last; i < baselines.length; i += 1) sinceLast += baselines[i];
|
|
3873
|
+
const total = history[last].inputTokens + sinceLast;
|
|
3874
|
+
let beforeFirst = 0;
|
|
3875
|
+
for (let i = 0; i < first; i += 1) beforeFirst += baselines[i];
|
|
3876
|
+
const derived = Math.max(0, history[first].inputTokens - beforeFirst);
|
|
3877
|
+
const claimed = preambleTokens ?? derived;
|
|
3878
|
+
const contradicted = baselineTotal > 0 && claimed >= total;
|
|
3879
|
+
const overhead = Math.min(contradicted ? derived : claimed, total);
|
|
3880
|
+
const messages = Math.max(0, total - overhead);
|
|
3881
|
+
if (baselineTotal <= 0) {
|
|
3882
|
+
return { overhead, total, estimates: baselines, scale: 1 };
|
|
3883
|
+
}
|
|
3884
|
+
const scale = messages / baselineTotal;
|
|
3885
|
+
const estimates = baselines.map((b) => Math.round(b * scale));
|
|
3886
|
+
let assigned = 0;
|
|
3887
|
+
let heaviest = -1;
|
|
3888
|
+
for (let i = 0; i < estimates.length; i += 1) {
|
|
3889
|
+
assigned += estimates[i];
|
|
3890
|
+
if (baselines[i] > 0 && (heaviest < 0 || baselines[i] > baselines[heaviest])) heaviest = i;
|
|
3891
|
+
}
|
|
3892
|
+
if (heaviest >= 0) estimates[heaviest] += messages - assigned;
|
|
3893
|
+
return { overhead, total, estimates, scale };
|
|
3894
|
+
}
|
|
3895
|
+
function estimateMessageTokens(history, preambleTokens) {
|
|
3896
|
+
return calibrate(history, preambleTokens).estimates;
|
|
3897
|
+
}
|
|
3898
|
+
function estimateRequestTokens(storedHistory, requestHistory, preambleTokens) {
|
|
3899
|
+
const { overhead } = calibrate(storedHistory, preambleTokens);
|
|
3835
3900
|
let requestBaseline = 0;
|
|
3836
3901
|
for (const m of requestHistory) requestBaseline += baselineTokens(m);
|
|
3837
|
-
|
|
3838
|
-
return Math.round(overhead + calibratedMessages * (requestBaseline / storedBaseline));
|
|
3902
|
+
return Math.round(overhead + requestBaseline);
|
|
3839
3903
|
}
|
|
3840
|
-
function projectCompaction(history, cut, summaryTokens = COMPACTION_SUMMARY_TOKEN_ESTIMATE) {
|
|
3841
|
-
const estimates =
|
|
3842
|
-
const overhead = estimateSystemOverhead(history);
|
|
3904
|
+
function projectCompaction(history, cut, summaryTokens = COMPACTION_SUMMARY_TOKEN_ESTIMATE, preambleTokens) {
|
|
3905
|
+
const { estimates, overhead, total } = calibrate(history, preambleTokens);
|
|
3843
3906
|
let tail = 0;
|
|
3844
3907
|
for (let i = cut; i < estimates.length; i += 1) tail += estimates[i];
|
|
3845
|
-
|
|
3846
|
-
for (const t of estimates) all += t;
|
|
3847
|
-
const tokensBefore = overhead + all;
|
|
3908
|
+
const tokensBefore = total;
|
|
3848
3909
|
const tokensAfter = overhead + summaryTokens + tail;
|
|
3849
3910
|
return {
|
|
3850
3911
|
cut,
|
|
@@ -4112,8 +4173,8 @@ function isSafeCompactionCut(history, i) {
|
|
|
4112
4173
|
}
|
|
4113
4174
|
return true;
|
|
4114
4175
|
}
|
|
4115
|
-
function findCompactionCut(history, tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET) {
|
|
4116
|
-
const estimates = estimateMessageTokens(history);
|
|
4176
|
+
function findCompactionCut(history, tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET, preambleTokens) {
|
|
4177
|
+
const estimates = estimateMessageTokens(history, preambleTokens);
|
|
4117
4178
|
let messagesTotal = 0;
|
|
4118
4179
|
for (const t of estimates) messagesTotal += t;
|
|
4119
4180
|
if (messagesTotal <= tailTokenBudget) return null;
|
|
@@ -4134,9 +4195,14 @@ function planCompaction(history, options = {}) {
|
|
|
4134
4195
|
tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET,
|
|
4135
4196
|
minReclaimTokens = DEFAULT_MIN_RECLAIM_TOKENS
|
|
4136
4197
|
} = options;
|
|
4137
|
-
const cut = findCompactionCut(history, tailTokenBudget);
|
|
4198
|
+
const cut = findCompactionCut(history, tailTokenBudget, options.preambleTokens);
|
|
4138
4199
|
if (cut == null) return null;
|
|
4139
|
-
const projection = projectCompaction(
|
|
4200
|
+
const projection = projectCompaction(
|
|
4201
|
+
history,
|
|
4202
|
+
cut,
|
|
4203
|
+
COMPACTION_SUMMARY_TOKEN_ESTIMATE,
|
|
4204
|
+
options.preambleTokens
|
|
4205
|
+
);
|
|
4140
4206
|
return projection.reclaimed >= minReclaimTokens ? projection : null;
|
|
4141
4207
|
}
|
|
4142
4208
|
function renderMessageForSummary(m) {
|
|
@@ -5100,7 +5166,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
5100
5166
|
attachments: pendingInput.attachments
|
|
5101
5167
|
}
|
|
5102
5168
|
] : requestHistory;
|
|
5103
|
-
const estimated = estimateRequestTokens(this.history, request);
|
|
5169
|
+
const estimated = estimateRequestTokens(this.history, request, this.lastPreambleTokens);
|
|
5104
5170
|
if (estimated < threshold) return void 0;
|
|
5105
5171
|
logger2.error(
|
|
5106
5172
|
`ChatDriver: ending the turn \u2014 the request would fill the context window (~${estimated} of ${limit})`
|
|
@@ -5288,6 +5354,10 @@ Output format (strict):
|
|
|
5288
5354
|
this.loadHistory([summaryMessage, ...tail]);
|
|
5289
5355
|
return summaryMessage;
|
|
5290
5356
|
}
|
|
5357
|
+
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
5358
|
+
getPreambleTokens() {
|
|
5359
|
+
return this.lastPreambleTokens;
|
|
5360
|
+
}
|
|
5291
5361
|
isBusy() {
|
|
5292
5362
|
return this.busy;
|
|
5293
5363
|
}
|
|
@@ -6150,6 +6220,11 @@ ${tailBody}
|
|
|
6150
6220
|
const attachmentsForCall = currentAttachments;
|
|
6151
6221
|
currentInput = "";
|
|
6152
6222
|
currentAttachments = void 0;
|
|
6223
|
+
this.lastPreambleTokens = estimatePreambleTokens({
|
|
6224
|
+
systemPrompt,
|
|
6225
|
+
toolDefinitions: this.toolDefinitions,
|
|
6226
|
+
tailContext
|
|
6227
|
+
});
|
|
6153
6228
|
const options = {
|
|
6154
6229
|
systemPrompt,
|
|
6155
6230
|
// Strip fold-only properties (foldEvent, foldPath) before sending to provider
|
|
@@ -6819,6 +6894,13 @@ function isSpecialist(agent) {
|
|
|
6819
6894
|
function isFallback(agent) {
|
|
6820
6895
|
return agent.fallback === true;
|
|
6821
6896
|
}
|
|
6897
|
+
function normalizeContextReserve(input) {
|
|
6898
|
+
if (input == null) return void 0;
|
|
6899
|
+
const positive = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
|
|
6900
|
+
if (typeof input === "number") return positive(input) ? { tokens: input } : void 0;
|
|
6901
|
+
if (!positive(input.tokens)) return void 0;
|
|
6902
|
+
return positive(input.warnAheadTokens) ? { tokens: input.tokens, warnAheadTokens: input.warnAheadTokens } : { tokens: input.tokens };
|
|
6903
|
+
}
|
|
6822
6904
|
var UNROUTABLE_PLACEHOLDER = "{{unroutable}}";
|
|
6823
6905
|
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.
|
|
6824
6906
|
|
|
@@ -7020,6 +7102,10 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
7020
7102
|
canCompact(options) {
|
|
7021
7103
|
return this.chatDriver.canCompact(options);
|
|
7022
7104
|
}
|
|
7105
|
+
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
7106
|
+
getPreambleTokens() {
|
|
7107
|
+
return this.chatDriver.getPreambleTokens();
|
|
7108
|
+
}
|
|
7023
7109
|
/** {@inheritDoc AiDriver.getCompactionPlan} */
|
|
7024
7110
|
getCompactionPlan(options) {
|
|
7025
7111
|
return this.chatDriver.getCompactionPlan(options);
|
|
@@ -7141,6 +7227,32 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
7141
7227
|
primeRestoredAgentState(snapshots) {
|
|
7142
7228
|
this.restoredAgentStates = { ...snapshots };
|
|
7143
7229
|
}
|
|
7230
|
+
/**
|
|
7231
|
+
* {@inheritDoc AiDriver.getContextReserve}
|
|
7232
|
+
*
|
|
7233
|
+
* Two cases, because routing has two modes and they need opposite answers.
|
|
7234
|
+
*/
|
|
7235
|
+
getContextReserve() {
|
|
7236
|
+
const locked = this.resolvePinnedAgent();
|
|
7237
|
+
if (locked) {
|
|
7238
|
+
const reserve = normalizeContextReserve(locked.contextReserve);
|
|
7239
|
+
return reserve == null ? void 0 : { ...reserve, agentName: locked.name, basis: "locked" };
|
|
7240
|
+
}
|
|
7241
|
+
const candidates = [...this.specialists];
|
|
7242
|
+
if (this.fallback) candidates.push(this.fallback);
|
|
7243
|
+
if (this.activeAgent) candidates.push(this.activeAgent);
|
|
7244
|
+
let winner;
|
|
7245
|
+
let agentName = "";
|
|
7246
|
+
for (const agent of candidates) {
|
|
7247
|
+
const reserve = normalizeContextReserve(agent.contextReserve);
|
|
7248
|
+
if (!reserve) continue;
|
|
7249
|
+
if (!winner || reserve.tokens > winner.tokens) {
|
|
7250
|
+
winner = reserve;
|
|
7251
|
+
agentName = agent.name;
|
|
7252
|
+
}
|
|
7253
|
+
}
|
|
7254
|
+
return winner ? { ...winner, agentName, basis: "reachable-max" } : void 0;
|
|
7255
|
+
}
|
|
7144
7256
|
/** {@inheritDoc AiDriver.getActiveAgent} */
|
|
7145
7257
|
getActiveAgent() {
|
|
7146
7258
|
return this.activeAgent;
|
|
@@ -7650,6 +7762,7 @@ function defineStatefulAgent(opts) {
|
|
|
7650
7762
|
onUnresolvedTool: wrappedOnUnresolvedTool,
|
|
7651
7763
|
resumable: wrappedResumable,
|
|
7652
7764
|
notResumableMessage: opts.notResumableMessage,
|
|
7765
|
+
contextReserve: opts.contextReserve,
|
|
7653
7766
|
onActivate: async (ctx) => {
|
|
7654
7767
|
state = await opts.init(ctx);
|
|
7655
7768
|
if (opts.toolHandlers) {
|