@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.
Files changed (33) hide show
  1. package/dist/ai-assistant.api.json +269 -5
  2. package/dist/ai-assistant.d.ts +256 -31
  3. package/dist/chat-driver.cjs +125 -58
  4. package/dist/chat-driver.cjs.map +2 -2
  5. package/dist/chat-driver.mjs +125 -58
  6. package/dist/chat-driver.mjs.map +2 -2
  7. package/dist/custom-elements.json +125 -6
  8. package/dist/dts/components/ai-driver/ai-driver.d.ts +63 -0
  9. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
  10. package/dist/dts/components/chat-driver/chat-driver.d.ts +7 -0
  11. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  12. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +9 -1
  13. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  14. package/dist/dts/config/config.d.ts +53 -17
  15. package/dist/dts/config/config.d.ts.map +1 -1
  16. package/dist/dts/config/define-stateful-agent.d.ts +16 -1
  17. package/dist/dts/config/define-stateful-agent.d.ts.map +1 -1
  18. package/dist/dts/main/main.d.ts +102 -14
  19. package/dist/dts/main/main.d.ts.map +1 -1
  20. package/dist/dts/utils/context-tokens.d.ts +100 -43
  21. package/dist/dts/utils/context-tokens.d.ts.map +1 -1
  22. package/dist/dts/utils/history-transform.d.ts +7 -1
  23. package/dist/dts/utils/history-transform.d.ts.map +1 -1
  24. package/dist/dts/utils/resolve-context-budget.d.ts +8 -5
  25. package/dist/dts/utils/resolve-context-budget.d.ts.map +1 -1
  26. package/dist/esm/components/chat-driver/chat-driver.js +22 -2
  27. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +92 -0
  28. package/dist/esm/config/define-stateful-agent.js +1 -0
  29. package/dist/esm/main/main.js +170 -27
  30. package/dist/esm/utils/context-tokens.js +331 -106
  31. package/dist/esm/utils/history-transform.js +5 -5
  32. package/dist/esm/utils/resolve-context-budget.js +37 -7
  33. package/package.json +16 -16
@@ -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 estimateMessageTokens(history) {
3835
- const estimates = history.map(baselineTokens);
3836
- const compactedAt = compactedAtOf(history);
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 estimates;
3853
+ return -1;
3861
3854
  }
3862
- function estimateSystemOverhead(history) {
3863
- const first = firstAnchor(history, compactedAtOf(history));
3864
- if (first < 0) return 0;
3865
- const estimates = estimateMessageTokens(history);
3866
- let messages = 0;
3867
- for (let i = 0; i < first; i += 1) messages += estimates[i];
3868
- return Math.max(0, history[first].inputTokens - messages);
3869
- }
3870
- function estimateContextTokens(history) {
3871
- const estimates = estimateMessageTokens(history);
3872
- let total = estimateSystemOverhead(history);
3873
- for (const t of estimates) total += t;
3874
- return total;
3875
- }
3876
- function estimateRequestTokens(storedHistory, requestHistory) {
3877
- const overhead = estimateSystemOverhead(storedHistory);
3878
- const calibratedMessages = Math.max(0, estimateContextTokens(storedHistory) - overhead);
3879
- let storedBaseline = 0;
3880
- for (const m of storedHistory) storedBaseline += baselineTokens(m);
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
- if (storedBaseline <= 0) return overhead + requestBaseline;
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 = estimateMessageTokens(history);
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
- let all = 0;
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(history, cut);
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) {