@genesislcap/ai-assistant 15.23.0 → 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 +125 -58
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +125 -58
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +125 -6
- 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/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/package.json +16 -16
package/dist/chat-driver.mjs
CHANGED
|
@@ -3787,6 +3787,21 @@ function createInteractionContext(interactionId) {
|
|
|
3787
3787
|
var APPROX_CHARS_PER_TOKEN = 4;
|
|
3788
3788
|
var IMAGE_TOKEN_ESTIMATE = 1600;
|
|
3789
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
|
+
}
|
|
3790
3805
|
var COMPACTION_SUMMARY_TOKEN_ESTIMATE = 1200;
|
|
3791
3806
|
function reachesProvider(m) {
|
|
3792
3807
|
if (m.role === "system-event" || m.role === "synthetic-user") return false;
|
|
@@ -3831,66 +3846,66 @@ function usableAnchor(m, compactedAt) {
|
|
|
3831
3846
|
function firstAnchor(history, compactedAt) {
|
|
3832
3847
|
return history.findIndex((m) => usableAnchor(m, compactedAt));
|
|
3833
3848
|
}
|
|
3834
|
-
function
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
const anchors = [];
|
|
3838
|
-
history.forEach((m, i) => {
|
|
3839
|
-
if (usableAnchor(m, compactedAt)) anchors.push(i);
|
|
3840
|
-
});
|
|
3841
|
-
for (let a = 0; a < anchors.length - 1; a += 1) {
|
|
3842
|
-
const from = anchors[a];
|
|
3843
|
-
const to = anchors[a + 1];
|
|
3844
|
-
const measured = history[to].inputTokens - history[from].inputTokens;
|
|
3845
|
-
if (measured <= 0) continue;
|
|
3846
|
-
let baseline = 0;
|
|
3847
|
-
for (let i = from; i < to; i += 1) baseline += estimates[i];
|
|
3848
|
-
if (baseline <= 0) {
|
|
3849
|
-
estimates[from] = measured;
|
|
3850
|
-
continue;
|
|
3851
|
-
}
|
|
3852
|
-
const scale = measured / baseline;
|
|
3853
|
-
let assigned = 0;
|
|
3854
|
-
for (let i = from; i < to - 1; i += 1) {
|
|
3855
|
-
estimates[i] = Math.round(estimates[i] * scale);
|
|
3856
|
-
assigned += estimates[i];
|
|
3857
|
-
}
|
|
3858
|
-
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;
|
|
3859
3852
|
}
|
|
3860
|
-
return
|
|
3853
|
+
return -1;
|
|
3861
3854
|
}
|
|
3862
|
-
function
|
|
3863
|
-
const
|
|
3864
|
-
|
|
3865
|
-
const
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
let
|
|
3880
|
-
|
|
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);
|
|
3881
3900
|
let requestBaseline = 0;
|
|
3882
3901
|
for (const m of requestHistory) requestBaseline += baselineTokens(m);
|
|
3883
|
-
|
|
3884
|
-
return Math.round(overhead + calibratedMessages * (requestBaseline / storedBaseline));
|
|
3902
|
+
return Math.round(overhead + requestBaseline);
|
|
3885
3903
|
}
|
|
3886
|
-
function projectCompaction(history, cut, summaryTokens = COMPACTION_SUMMARY_TOKEN_ESTIMATE) {
|
|
3887
|
-
const estimates =
|
|
3888
|
-
const overhead = estimateSystemOverhead(history);
|
|
3904
|
+
function projectCompaction(history, cut, summaryTokens = COMPACTION_SUMMARY_TOKEN_ESTIMATE, preambleTokens) {
|
|
3905
|
+
const { estimates, overhead, total } = calibrate(history, preambleTokens);
|
|
3889
3906
|
let tail = 0;
|
|
3890
3907
|
for (let i = cut; i < estimates.length; i += 1) tail += estimates[i];
|
|
3891
|
-
|
|
3892
|
-
for (const t of estimates) all += t;
|
|
3893
|
-
const tokensBefore = overhead + all;
|
|
3908
|
+
const tokensBefore = total;
|
|
3894
3909
|
const tokensAfter = overhead + summaryTokens + tail;
|
|
3895
3910
|
return {
|
|
3896
3911
|
cut,
|
|
@@ -4158,8 +4173,8 @@ function isSafeCompactionCut(history, i) {
|
|
|
4158
4173
|
}
|
|
4159
4174
|
return true;
|
|
4160
4175
|
}
|
|
4161
|
-
function findCompactionCut(history, tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET) {
|
|
4162
|
-
const estimates = estimateMessageTokens(history);
|
|
4176
|
+
function findCompactionCut(history, tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET, preambleTokens) {
|
|
4177
|
+
const estimates = estimateMessageTokens(history, preambleTokens);
|
|
4163
4178
|
let messagesTotal = 0;
|
|
4164
4179
|
for (const t of estimates) messagesTotal += t;
|
|
4165
4180
|
if (messagesTotal <= tailTokenBudget) return null;
|
|
@@ -4180,9 +4195,14 @@ function planCompaction(history, options = {}) {
|
|
|
4180
4195
|
tailTokenBudget = DEFAULT_TAIL_TOKEN_BUDGET,
|
|
4181
4196
|
minReclaimTokens = DEFAULT_MIN_RECLAIM_TOKENS
|
|
4182
4197
|
} = options;
|
|
4183
|
-
const cut = findCompactionCut(history, tailTokenBudget);
|
|
4198
|
+
const cut = findCompactionCut(history, tailTokenBudget, options.preambleTokens);
|
|
4184
4199
|
if (cut == null) return null;
|
|
4185
|
-
const projection = projectCompaction(
|
|
4200
|
+
const projection = projectCompaction(
|
|
4201
|
+
history,
|
|
4202
|
+
cut,
|
|
4203
|
+
COMPACTION_SUMMARY_TOKEN_ESTIMATE,
|
|
4204
|
+
options.preambleTokens
|
|
4205
|
+
);
|
|
4186
4206
|
return projection.reclaimed >= minReclaimTokens ? projection : null;
|
|
4187
4207
|
}
|
|
4188
4208
|
function renderMessageForSummary(m) {
|
|
@@ -5146,7 +5166,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
5146
5166
|
attachments: pendingInput.attachments
|
|
5147
5167
|
}
|
|
5148
5168
|
] : requestHistory;
|
|
5149
|
-
const estimated = estimateRequestTokens(this.history, request);
|
|
5169
|
+
const estimated = estimateRequestTokens(this.history, request, this.lastPreambleTokens);
|
|
5150
5170
|
if (estimated < threshold) return void 0;
|
|
5151
5171
|
logger2.error(
|
|
5152
5172
|
`ChatDriver: ending the turn \u2014 the request would fill the context window (~${estimated} of ${limit})`
|
|
@@ -5334,6 +5354,10 @@ Output format (strict):
|
|
|
5334
5354
|
this.loadHistory([summaryMessage, ...tail]);
|
|
5335
5355
|
return summaryMessage;
|
|
5336
5356
|
}
|
|
5357
|
+
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
5358
|
+
getPreambleTokens() {
|
|
5359
|
+
return this.lastPreambleTokens;
|
|
5360
|
+
}
|
|
5337
5361
|
isBusy() {
|
|
5338
5362
|
return this.busy;
|
|
5339
5363
|
}
|
|
@@ -6196,6 +6220,11 @@ ${tailBody}
|
|
|
6196
6220
|
const attachmentsForCall = currentAttachments;
|
|
6197
6221
|
currentInput = "";
|
|
6198
6222
|
currentAttachments = void 0;
|
|
6223
|
+
this.lastPreambleTokens = estimatePreambleTokens({
|
|
6224
|
+
systemPrompt,
|
|
6225
|
+
toolDefinitions: this.toolDefinitions,
|
|
6226
|
+
tailContext
|
|
6227
|
+
});
|
|
6199
6228
|
const options = {
|
|
6200
6229
|
systemPrompt,
|
|
6201
6230
|
// Strip fold-only properties (foldEvent, foldPath) before sending to provider
|
|
@@ -6865,6 +6894,13 @@ function isSpecialist(agent) {
|
|
|
6865
6894
|
function isFallback(agent) {
|
|
6866
6895
|
return agent.fallback === true;
|
|
6867
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
|
+
}
|
|
6868
6904
|
var UNROUTABLE_PLACEHOLDER = "{{unroutable}}";
|
|
6869
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.
|
|
6870
6906
|
|
|
@@ -7066,6 +7102,10 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
7066
7102
|
canCompact(options) {
|
|
7067
7103
|
return this.chatDriver.canCompact(options);
|
|
7068
7104
|
}
|
|
7105
|
+
/** {@inheritDoc AiDriver.getPreambleTokens} */
|
|
7106
|
+
getPreambleTokens() {
|
|
7107
|
+
return this.chatDriver.getPreambleTokens();
|
|
7108
|
+
}
|
|
7069
7109
|
/** {@inheritDoc AiDriver.getCompactionPlan} */
|
|
7070
7110
|
getCompactionPlan(options) {
|
|
7071
7111
|
return this.chatDriver.getCompactionPlan(options);
|
|
@@ -7187,6 +7227,32 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
7187
7227
|
primeRestoredAgentState(snapshots) {
|
|
7188
7228
|
this.restoredAgentStates = { ...snapshots };
|
|
7189
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
|
+
}
|
|
7190
7256
|
/** {@inheritDoc AiDriver.getActiveAgent} */
|
|
7191
7257
|
getActiveAgent() {
|
|
7192
7258
|
return this.activeAgent;
|
|
@@ -7696,6 +7762,7 @@ function defineStatefulAgent(opts) {
|
|
|
7696
7762
|
onUnresolvedTool: wrappedOnUnresolvedTool,
|
|
7697
7763
|
resumable: wrappedResumable,
|
|
7698
7764
|
notResumableMessage: opts.notResumableMessage,
|
|
7765
|
+
contextReserve: opts.contextReserve,
|
|
7699
7766
|
onActivate: async (ctx) => {
|
|
7700
7767
|
state = await opts.init(ctx);
|
|
7701
7768
|
if (opts.toolHandlers) {
|