@genesislcap/ai-assistant 15.5.0 → 15.6.1

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.
@@ -5662,6 +5662,33 @@
5662
5662
  "endIndex": 2
5663
5663
  }
5664
5664
  },
5665
+ {
5666
+ "kind": "PropertySignature",
5667
+ "canonicalReference": "@genesislcap/ai-assistant!ChatDriverConfig#condenseBatchCalls:member",
5668
+ "docComment": "/**\n * Collapse `condenseWhen` payloads in batches of this many model-calls rather than as soon as each trigger fires. A positive integer; decimals are floored and anything below `1` becomes `1`. Default `1` — collapse immediately, the historical behaviour.\n *\n * Condensation rewrites history in place, so collapsing continuously breaks the provider's prompt cache on nearly every call of a re-read loop. Raising this trades up to that many calls' worth of extra context for one cache break per batch.\n */\n",
5669
+ "excerptTokens": [
5670
+ {
5671
+ "kind": "Content",
5672
+ "text": "condenseBatchCalls?: "
5673
+ },
5674
+ {
5675
+ "kind": "Content",
5676
+ "text": "number"
5677
+ },
5678
+ {
5679
+ "kind": "Content",
5680
+ "text": ";"
5681
+ }
5682
+ ],
5683
+ "isReadonly": false,
5684
+ "isOptional": true,
5685
+ "releaseTag": "Beta",
5686
+ "name": "condenseBatchCalls",
5687
+ "propertyTypeTokenRange": {
5688
+ "startIndex": 1,
5689
+ "endIndex": 2
5690
+ }
5691
+ },
5665
5692
  {
5666
5693
  "kind": "PropertySignature",
5667
5694
  "canonicalReference": "@genesislcap/ai-assistant!ChatDriverConfig#maxFoldOperations:member",
@@ -1377,6 +1377,8 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
1377
1377
  private unsubscribeRegistry?;
1378
1378
  /** Hard cap on tool-loop iterations. */
1379
1379
  private readonly maxToolIterations;
1380
+ /** Model-calls per condensation batch; `1` collapses as soon as a trigger fires. */
1381
+ private readonly condenseBatchCalls;
1380
1382
  /** Session identity used to file meta events onto the shared debug-log timeline. */
1381
1383
  private readonly sessionKey;
1382
1384
  /** Injected activity bus; defaults to a no-op off-browser (Node/tests/headless). */
@@ -1713,6 +1715,16 @@ export declare interface ChatDriverConfig {
1713
1715
  maxToolIterations?: number;
1714
1716
  /** Hard cap on fold operations. Default `5`. */
1715
1717
  maxFoldOperations?: number;
1718
+ /**
1719
+ * Collapse `condenseWhen` payloads in batches of this many model-calls rather than as
1720
+ * soon as each trigger fires. A positive integer; decimals are floored and anything
1721
+ * below `1` becomes `1`. Default `1` — collapse immediately, the historical behaviour.
1722
+ *
1723
+ * Condensation rewrites history in place, so collapsing continuously breaks the
1724
+ * provider's prompt cache on nearly every call of a re-read loop. Raising this trades
1725
+ * up to that many calls' worth of extra context for one cache break per batch.
1726
+ */
1727
+ condenseBatchCalls?: number;
1716
1728
  /** Ring-buffer size for per-turn snapshots. Default `400`. */
1717
1729
  maxTurnSnapshots?: number;
1718
1730
  /** Session identity used to file meta events onto the shared debug-log timeline. */
@@ -2840,9 +2840,15 @@ function triggerLabel(trigger) {
2840
2840
  function estimateTokensSaved(origLen, stubLen) {
2841
2841
  return Math.max(0, Math.ceil((origLen - stubLen) / APPROX_CHARS_PER_TOKEN));
2842
2842
  }
2843
+ function marksDiscontinuity(kind) {
2844
+ return kind === "agentEnd" || kind === "phaseEnd";
2845
+ }
2843
2846
  function applyCondensation(history, policies, ctx, onCondensed) {
2844
2847
  if (policies.size === 0) return history;
2845
2848
  const triggersOf = (entry) => Array.isArray(entry.policy.on) ? entry.policy.on : [entry.policy.on];
2849
+ const batchCalls = Math.max(1, Math.floor(ctx.batchCalls ?? 1));
2850
+ const asOf = batchCalls === 1 ? ctx.modelCall : Math.floor(ctx.modelCall / batchCalls) * batchCalls;
2851
+ const withinBatch = (entry) => batchCalls === 1 || entry.iteration <= asOf;
2846
2852
  const latestByKey = /* @__PURE__ */ new Map();
2847
2853
  const nameById = /* @__PURE__ */ new Map();
2848
2854
  for (const msg of history) {
@@ -2850,7 +2856,7 @@ function applyCondensation(history, policies, ctx, onCondensed) {
2850
2856
  for (const tc of msg.toolCalls) {
2851
2857
  nameById.set(tc.id, tc.name);
2852
2858
  const entry = policies.get(tc.id);
2853
- if (!entry) continue;
2859
+ if (!entry || !withinBatch(entry)) continue;
2854
2860
  for (const t of triggersOf(entry)) {
2855
2861
  if (t.kind === "superseded") latestByKey.set(t.by, tc.id);
2856
2862
  }
@@ -2862,7 +2868,7 @@ function applyCondensation(history, policies, ctx, onCondensed) {
2862
2868
  // past the last allowed view: turns:1 → seen once, then gone. Monotonic
2863
2869
  // clock, so this holds across turn boundaries too.
2864
2870
  case "age":
2865
- return ctx.modelCall - entry.iteration > trig.turns;
2871
+ return asOf - entry.iteration > trig.turns;
2866
2872
  case "turnEnd":
2867
2873
  return ctx.turn > entry.turn;
2868
2874
  case "agentEnd":
@@ -2876,7 +2882,9 @@ function applyCondensation(history, policies, ctx, onCondensed) {
2876
2882
  return latestByKey.get(trig.by) !== toolCallId;
2877
2883
  }
2878
2884
  };
2879
- const firstFired = (toolCallId, entry) => triggersOf(entry).find((t) => triggerFires(toolCallId, entry, t));
2885
+ const firstFired = (toolCallId, entry) => triggersOf(entry).find(
2886
+ (t) => (marksDiscontinuity(t.kind) || withinBatch(entry)) && triggerFires(toolCallId, entry, t)
2887
+ );
2880
2888
  return history.map((msg) => {
2881
2889
  if (msg.toolCalls?.length) {
2882
2890
  let changed = false;
@@ -3257,11 +3265,13 @@ var ChatDriver = class _ChatDriver extends EventTarget {
3257
3265
  primerHistory,
3258
3266
  maxToolIterations = DEFAULT_MAX_TOOL_ITERATIONS,
3259
3267
  maxFoldOperations = DEFAULT_MAX_FOLD_OPERATIONS,
3268
+ condenseBatchCalls = 1,
3260
3269
  maxTurnSnapshots = DEFAULT_MAX_TURN_SNAPSHOTS,
3261
3270
  sessionKey = "",
3262
3271
  activityBus = NOOP_ACTIVITY_BUS
3263
3272
  } = config;
3264
3273
  this.maxToolIterations = maxToolIterations;
3274
+ this.condenseBatchCalls = condenseBatchCalls;
3265
3275
  this.sessionKey = sessionKey;
3266
3276
  this.activityBus = activityBus;
3267
3277
  if (typeof toolHandlers === "function") {
@@ -4500,7 +4510,8 @@ Output format (strict):
4500
4510
  activationEnded: (activation) => activation < this.currentActivation,
4501
4511
  // A call's phase has ended once the app declared a later phase epoch
4502
4512
  // current via `endPhase()`.
4503
- phaseEnded: (phaseEpoch) => phaseEpoch < this.currentPhaseEpoch
4513
+ phaseEnded: (phaseEpoch) => phaseEpoch < this.currentPhaseEpoch,
4514
+ batchCalls: this.condenseBatchCalls
4504
4515
  },
4505
4516
  (detail) => recordMetaEvent(this.sessionKey, "context.condensed", detail)
4506
4517
  );