acp-kernel 0.0.73-pr.305.170 → 0.0.73

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.
@@ -1 +1 @@
1
- {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkC,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAgBhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAUvD,OAAO,EAGL,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,EAEN,WAAW,EAGX,iBAAiB,EAEjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvE,YAAY,IAAI,YAAY,EAAE,CAAC;IAC/B,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,CACJ,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnC;AA2DD,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CA+U7D;AA0lCD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkC,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAgBhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAUvD,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,EAEN,WAAW,EAGX,iBAAiB,EAEjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvE,YAAY,IAAI,YAAY,EAAE,CAAC;IAC/B,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,CACJ,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnC;AA2DD,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CAyU7D;AA4iCD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,wBAAgB,aAAa,CAC3B,iBAAiB,EAAE,MAAM,EACzB,SAAS,GAAE,OAAO,CAAC,MAAM,CAAM,GAC9B,MAAM,CA+CR;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA8DvD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,wBAAgB,aAAa,CAC3B,iBAAiB,EAAE,MAAM,EACzB,SAAS,GAAE,OAAO,CAAC,MAAM,CAAM,GAC9B,MAAM,CA+CR;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAuDvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"hide-consumed.d.ts","sourceRoot":"","sources":["../src/hide-consumed.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAYhE,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AA8FD,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,GACxB,kBAAkB,CAwFpB"}
1
+ {"version":3,"file":"hide-consumed.d.ts","sourceRoot":"","sources":["../src/hide-consumed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAYhE,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AA8FD,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,GACxB,kBAAkB,CAwFpB"}
package/dist/index.js CHANGED
@@ -296,7 +296,6 @@ function syncBlocks(messages, state) {
296
296
  nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },
297
297
  stats: { ...state.stats },
298
298
  absorbed: (state.absorbed ?? []).map((record) => ({ ...record })),
299
- terminalStreak: state.terminalStreak,
300
299
  nextBlockId: state.nextBlockId,
301
300
  nextRunId: state.nextRunId
302
301
  };
@@ -354,7 +353,7 @@ function defaultConfig(modelContextLimit, overrides = {}) {
354
353
  tier2GrowthMultiplier: 1.5
355
354
  },
356
355
  promotionThreshold: 5,
357
- truncate: { threshold: 0.95, terminalEscapeAfter: 3 },
356
+ truncate: { threshold: 0.95 },
358
357
  compress: {
359
358
  minCompressRange: 5e3,
360
359
  maxSummaryLength: 2e4,
@@ -406,9 +405,6 @@ function validateConfig(config) {
406
405
  if (config.truncate.threshold <= 0 || config.truncate.threshold > 1) {
407
406
  errors.push("truncate.threshold must be in (0, 1]");
408
407
  }
409
- if (config.truncate.terminalEscapeAfter !== void 0 && (!Number.isInteger(config.truncate.terminalEscapeAfter) || config.truncate.terminalEscapeAfter < 0)) {
410
- errors.push("truncate.terminalEscapeAfter must be an integer >= 0");
411
- }
412
408
  for (const tier of [config.tiers.tier2Trigger, config.tiers.tier3Trigger]) {
413
409
  if (tier < 1) errors.push("tier triggers must be >= 1");
414
410
  }
@@ -658,89 +654,47 @@ var DEFAULTS = {
658
654
  };
659
655
  function truncateLargeToolOutputs(messages, tokenCount, config, countTokens, options = {}) {
660
656
  const opts = { ...DEFAULTS, ...options };
661
- const limit = config.modelContextLimit;
662
- if (limit <= 0 || tokenCount < config.truncate.threshold * limit) {
663
- return { messages, truncatedCount: 0, savedTokens: 0, candidatesFound: 0 };
664
- }
657
+ if (config.modelContextLimit <= 0) return { messages, truncatedCount: 0, savedTokens: 0 };
658
+ const threshold = config.truncate.threshold * config.modelContextLimit;
659
+ if (tokenCount < threshold) return { messages, truncatedCount: 0, savedTokens: 0 };
665
660
  const protectedIndex = messages.length - opts.protectRecentMessages;
666
- const findCandidates = (predicate) => {
667
- const found = [];
668
- for (let i = 0; i < protectedIndex; i++) {
669
- const message = messages[i];
670
- if (!predicate(message)) continue;
671
- const text = message.text ?? "";
672
- if (text.length === 0 || text.includes(TRUNCATION_MARKER)) continue;
673
- if (countTokens(text) < opts.minOutputTokens) continue;
674
- found.push(message);
675
- }
676
- return found.sort(
677
- (a, b) => countTokens(b.text ?? "") - countTokens(a.text ?? "")
678
- );
679
- };
680
- const toolResults = findCandidates((m) => m.contentType === "tool-result");
681
- const textMessages = options.includeTextMessages ? findCandidates(
682
- (m) => m.contentType === "text" && (m.role === "user" || m.role === "assistant") && !isRenderedSummaryMessage(m) && !m.text?.startsWith(SUMMARY_HEADER)
683
- ) : [];
684
- const candidatesFound = toolResults.length + textMessages.length;
685
- let truncatedCount = 0;
661
+ const candidates = [];
662
+ for (let index = 0; index < messages.length; index++) {
663
+ if (index >= protectedIndex) break;
664
+ const message = messages[index];
665
+ if (message.contentType !== "tool-result") continue;
666
+ const text = message.text ?? "";
667
+ if (text.length === 0 || text.includes(TRUNCATION_MARKER)) continue;
668
+ const tokens = countTokens(text);
669
+ if (tokens < opts.minOutputTokens) continue;
670
+ candidates.push({ index, tokens });
671
+ }
672
+ if (candidates.length === 0) return { messages, truncatedCount: 0, savedTokens: 0 };
673
+ candidates.sort((left, right) => right.tokens - left.tokens);
674
+ const targetTokens = threshold * 0.9;
686
675
  let savedTokens = 0;
687
- let remaining = tokenCount;
688
- const targetTokens = config.truncate.threshold * limit * 0.9;
689
- const replacements = /* @__PURE__ */ new Map();
690
- const applyTo = (candidates) => {
691
- for (const candidate of candidates) {
692
- if (remaining <= targetTokens) break;
693
- const original = candidate.text ?? "";
694
- const tokens = countTokens(original);
695
- if (original.length <= opts.keepPrefixChars + opts.keepSuffixChars) {
696
- continue;
697
- }
698
- const prefix = original.slice(0, opts.keepPrefixChars);
699
- const suffix = original.slice(-opts.keepSuffixChars);
700
- const replacement = `${prefix}
701
-
702
- ...${TRUNCATION_MARKER} \u2014 original ~${tokens} tokens]...
676
+ const edits = /* @__PURE__ */ new Map();
677
+ let truncatedCount = 0;
678
+ for (const candidate of candidates) {
679
+ if (tokenCount - savedTokens <= targetTokens) break;
680
+ const original = messages[candidate.index].text ?? "";
681
+ if (original.length <= opts.keepPrefixChars + opts.keepSuffixChars) continue;
682
+ const prefix = original.slice(0, opts.keepPrefixChars);
683
+ const suffix = original.slice(-opts.keepSuffixChars);
684
+ const replacement = prefix + `
703
685
 
704
- ${suffix}`;
705
- replacements.set(candidate.id, replacement);
706
- truncatedCount++;
707
- remaining -= tokens - countTokens(replacement);
708
- savedTokens += tokens - countTokens(replacement);
709
- }
710
- };
711
- applyTo(toolResults);
712
- applyTo(textMessages);
713
- if (replacements.size === 0) {
714
- return { messages, truncatedCount: 0, savedTokens: 0, candidatesFound };
715
- }
716
- return {
717
- messages: messages.map(
718
- (m) => replacements.has(m.id) ? { ...m, text: replacements.get(m.id) } : m
719
- ),
720
- truncatedCount,
721
- savedTokens,
722
- candidatesFound
723
- };
724
- }
686
+ ...${TRUNCATION_MARKER} \u2014 original ~${candidate.tokens} tokens]...
725
687
 
726
- // src/truncate.ts
727
- function isHighSurrogate(c) {
728
- return c >= 55296 && c <= 56319;
729
- }
730
- function isLowSurrogate(c) {
731
- return c >= 56320 && c <= 57343;
732
- }
733
- function clampPrefix(text, maxUnits) {
734
- const cut = Math.min(maxUnits, text.length);
735
- if (cut > 0 && isHighSurrogate(text.charCodeAt(cut - 1))) return text.slice(0, cut - 1);
736
- return text.slice(0, cut);
737
- }
738
- function clampWindow(text, start, end) {
739
- let s = Math.max(0, Math.min(start, text.length));
740
- let e = Math.min(text.length, Math.max(s, end));
741
- if (s > 0 && isLowSurrogate(text.charCodeAt(s))) s += 1;
742
- if (e > s && isHighSurrogate(text.charCodeAt(e - 1))) e -= 1;
743
- return text.slice(s, Math.max(s, e));
688
+ ` + suffix;
689
+ edits.set(candidate.index, replacement);
690
+ savedTokens += candidate.tokens - countTokens(replacement);
691
+ truncatedCount++;
692
+ }
693
+ if (truncatedCount === 0) return { messages, truncatedCount: 0, savedTokens: 0 };
694
+ const updated = messages.map(
695
+ (message, index) => edits.has(index) ? { ...message, text: edits.get(index) } : message
696
+ );
697
+ return { messages: updated, truncatedCount, savedTokens };
744
698
  }
745
699
 
746
700
  // src/hide-consumed.ts
@@ -795,7 +749,7 @@ function compactEntry(entry) {
795
749
  if (!entry || typeof entry !== "object") return entry;
796
750
  const e = entry;
797
751
  if (typeof e.summary !== "string" || e.summary.length <= SUMMARY_STUB_CHARS) return entry;
798
- return { ...e, summary: `${clampPrefix(e.summary, SUMMARY_STUB_CHARS - 1)}\u2026` };
752
+ return { ...e, summary: `${e.summary.slice(0, SUMMARY_STUB_CHARS - 1)}\u2026` };
799
753
  }
800
754
  function serializeCompacted(obj, content, contentWasString) {
801
755
  let changed = false;
@@ -2369,7 +2323,6 @@ function createCore(ports = {}) {
2369
2323
  state.nudge.lastPerMessageNudgeTokens = 0;
2370
2324
  state.nudge.lastNudgeShownTokens = 0;
2371
2325
  state.nudge.lastShownByTier = {};
2372
- state.terminalStreak = 0;
2373
2326
  }
2374
2327
  return {
2375
2328
  state,
@@ -2399,9 +2352,7 @@ function createCore(ports = {}) {
2399
2352
  return {
2400
2353
  messages: result.messages,
2401
2354
  state: result.state,
2402
- nudge: result.effects.nudge,
2403
- terminalEscape: result.effects.terminalEscape,
2404
- truncationSkipped: result.effects.truncationSkipped
2355
+ nudge: result.effects.nudge
2405
2356
  };
2406
2357
  }
2407
2358
  function decompress(blockId, state) {
@@ -2594,49 +2545,18 @@ var emergencyTruncateNode = {
2594
2545
  name: "emergency-truncate",
2595
2546
  run(io, ctx) {
2596
2547
  const usage = ctx.config.modelContextLimit > 0 ? ctx.tokenCount / ctx.config.modelContextLimit : 0;
2597
- const prevStreak = io.state.terminalStreak ?? 0;
2598
- if (usage < ctx.config.truncate.threshold) {
2599
- return prevStreak > 0 ? { ...io, state: { ...io.state, terminalStreak: 0 } } : io;
2600
- }
2548
+ if (usage < ctx.config.truncate.threshold) return io;
2601
2549
  const trunc = truncateLargeToolOutputs(
2602
2550
  io.messages,
2603
2551
  ctx.tokenCount,
2604
2552
  ctx.config,
2605
2553
  ctx.countTokens,
2606
- {
2607
- protectRecentMessages: ctx.config.preserveRecentMessages,
2608
- includeTextMessages: true
2609
- }
2554
+ { protectRecentMessages: ctx.config.preserveRecentMessages }
2610
2555
  );
2611
- const nudge = io.effects.nudge;
2612
- const minBenefit = nudge?.breakdown.minPressureBenefit ?? 0;
2613
- const maxPending = nudge?.breakdown.maxPending ?? 0;
2614
- const noViableCompression = nudge !== void 0 && (minBenefit > 0 ? maxPending < minBenefit : maxPending <= 0);
2615
- const stuck = noViableCompression && trunc.savedTokens <= 0;
2616
- const streak = stuck ? prevStreak + 1 : 0;
2617
- const escapeAfter = ctx.config.truncate.terminalEscapeAfter ?? 3;
2618
- const triggered = stuck && escapeAfter > 0 && streak >= escapeAfter;
2619
- const effects = {
2620
- ...io.effects,
2621
- truncatedCount: trunc.truncatedCount
2622
- };
2623
- if (trunc.savedTokens <= 0) {
2624
- effects.truncationSkipped = trunc.candidatesFound === 0 ? `emergency-truncate ran at ${Math.round(usage * 100)}% usage but found no truncatable content (no oversized tool-result or text message outside the last ${ctx.config.preserveRecentMessages} messages)` : `emergency-truncate found ${trunc.candidatesFound} candidate(s) at ${Math.round(usage * 100)}% usage but none were large enough to save tokens`;
2625
- }
2626
- if (triggered) {
2627
- effects.terminalEscape = {
2628
- message: `Usage at ${Math.round(usage * 100)}% (${ctx.tokenCount}/${ctx.config.modelContextLimit} tokens) persists with nothing compressible above the benefit floor and no truncatable content: compression cannot reduce this context below the limit. Start a new session or use native compaction.`,
2629
- usage,
2630
- tokenCount: ctx.tokenCount,
2631
- modelContextLimit: ctx.config.modelContextLimit,
2632
- stuckEvents: streak
2633
- };
2634
- }
2635
2556
  return {
2636
2557
  ...io,
2637
2558
  messages: trunc.messages,
2638
- state: { ...io.state, terminalStreak: streak },
2639
- effects
2559
+ effects: { ...io.effects, truncatedCount: trunc.truncatedCount }
2640
2560
  };
2641
2561
  }
2642
2562
  };
@@ -2729,8 +2649,7 @@ function applySingleRange(input) {
2729
2649
  for (const m of input.messages) {
2730
2650
  if (!m.id) continue;
2731
2651
  if (m.contentType === "reasoning") reasoningIds.add(m.id);
2732
- if (m.role === "assistant" && m.contentType === "tool-call")
2733
- callIds.add(m.id);
2652
+ if (m.role === "assistant" && m.contentType === "tool-call") callIds.add(m.id);
2734
2653
  }
2735
2654
  const withdrawIds = /* @__PURE__ */ new Set();
2736
2655
  let splitTurnCount = 0;
@@ -3001,7 +2920,6 @@ function decideNudge(input) {
3001
2920
  const t1Eff = tiers[1]?.pending ?? 0;
3002
2921
  const t2Pen = tiers[2]?.pending ?? 0;
3003
2922
  const t3Pen = tiers[3]?.pending ?? 0;
3004
- const maxPending = Math.max(0, t1Eff, t2Pen, t3Pen);
3005
2923
  const firstSightMassReady = state.nudge.lastNudgeShownTokens === 0 && baseline === 0 && usage >= config.nudge.minContextLimitPct && Math.max(t1Eff, t2Pen, t3Pen) >= nudgeGrowthTokens;
3006
2924
  const growthReady = firstSightMassReady || growthSinceReference >= growthFloor;
3007
2925
  const t2Count = tiers[2]?.targetBlocks.length ?? 0;
@@ -3074,6 +2992,10 @@ function decideNudge(input) {
3074
2992
  (t) => ((tiers[t]?.pending ?? 0) >= nudgeGrowthTokens || countReady(t)) && (state.nudge.lastShownByTier[t] ?? 0) > 0 && tokenCount - (state.nudge.lastShownByTier[t] ?? 0) < growthFloor
3075
2993
  ).map((t) => `T${t} (cadence)`);
3076
2994
  const blockedHint = blocked.length > 0 ? `, blocked: ${blocked.join(", ")}` : "";
2995
+ const maxPending = Math.max(
2996
+ 0,
2997
+ ...Object.values(tiers).map((t) => t.pending)
2998
+ );
3077
2999
  const pendingShort = maxPending < nudgeGrowthTokens;
3078
3000
  const growthShort = growthSinceReference < growthFloor;
3079
3001
  const parts = [];
@@ -3117,8 +3039,7 @@ function decideNudge(input) {
3117
3039
  minPressureBenefit,
3118
3040
  pendingT1: tiers[1].pending,
3119
3041
  pendingT2: tiers[2].pending,
3120
- pendingT3: tiers[3].pending,
3121
- maxPending
3042
+ pendingT3: tiers[3].pending
3122
3043
  },
3123
3044
  contextBreakdown: ctxBreakdown
3124
3045
  };
@@ -3158,7 +3079,6 @@ function cloneState(state) {
3158
3079
  nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },
3159
3080
  stats: { ...state.stats },
3160
3081
  absorbed: (state.absorbed ?? []).map((record) => ({ ...record })),
3161
- terminalStreak: state.terminalStreak,
3162
3082
  nextBlockId: state.nextBlockId,
3163
3083
  nextRunId: state.nextRunId
3164
3084
  };
@@ -3845,7 +3765,7 @@ ${block.summary}
3845
3765
  const lines = [`Active compression blocks (${activeBlocks2.length}):`];
3846
3766
  for (const block of activeBlocks2) {
3847
3767
  const range = `${block.effectiveMessageIds.length} messages`;
3848
- const preview = clampPrefix(block.summary, 200);
3768
+ const preview = block.summary.slice(0, 200);
3849
3769
  lines.push(`
3850
3770
  ${block.blockId} | ${range} | "${block.topic ?? "(none)"}"`);
3851
3771
  lines.push(` ${preview}${block.summary.length > 200 ? "..." : ""}`);
@@ -4127,7 +4047,7 @@ function deriveTopicFromSummary(summary) {
4127
4047
  const source = heading !== null ? heading[1] : summary.split("\n").find((l) => l.trim().length > 0) ?? "";
4128
4048
  const text = source.trim().replace(/^[\u2022\-*]\s+/, "");
4129
4049
  if (text.length === 0) return void 0;
4130
- return text.length > 60 ? clampPrefix(text, 60).trimEnd() : text;
4050
+ return text.length > 60 ? text.slice(0, 60).trimEnd() : text;
4131
4051
  }
4132
4052
  function splitLineEntries(content) {
4133
4053
  const parts = content.split(/\n(?=\s*(?:["']\s*,\s*)?["']?\s*[mb]\d{1,7}\s*(?:[-\u2013\u2014\u2026~]|\.\.\.|to)\s*[mb]\d{1,7}\b)/i).map((p) => p.trim().replace(/^(?:["']\s*,?\s*)+/, "").replace(/["']\s*$/, "")).filter((p) => p.length > 0);
@@ -4711,7 +4631,7 @@ function messageDocs(msgs) {
4711
4631
  kind: "message",
4712
4632
  ref: m.ref,
4713
4633
  text: m.text,
4714
- title: `${m.role}: ${clampPrefix(m.text, 60)}`,
4634
+ title: `${m.role}: ${m.text.slice(0, 60)}`,
4715
4635
  role: m.role,
4716
4636
  blockId: m.blockId,
4717
4637
  tier: m.tier,
@@ -4776,7 +4696,7 @@ async function searchBlocksAsync(docs, query, options = {}) {
4776
4696
  function makePreview(text, query, len) {
4777
4697
  if (!text) return "";
4778
4698
  const terms = query.toLowerCase().trim().split(/\s+/).filter((t) => t.length > 1);
4779
- if (terms.length === 0) return clampPrefix(text, len);
4699
+ if (terms.length === 0) return text.slice(0, len);
4780
4700
  const lower = text.toLowerCase();
4781
4701
  let hitIdx = -1;
4782
4702
  for (const term of terms) {
@@ -4786,13 +4706,13 @@ function makePreview(text, query, len) {
4786
4706
  break;
4787
4707
  }
4788
4708
  }
4789
- if (hitIdx < 0) return clampPrefix(text, len);
4709
+ if (hitIdx < 0) return text.slice(0, len);
4790
4710
  const half = Math.max(0, Math.floor(len / 2) - 10);
4791
4711
  const start = Math.max(0, hitIdx - half);
4792
4712
  const end = Math.min(text.length, start + len);
4793
4713
  const prefix = start > 0 ? "\u2026" : "";
4794
4714
  const suffix = end < text.length ? "\u2026" : "";
4795
- return prefix + clampWindow(text, start, end).trim() + suffix;
4715
+ return prefix + text.slice(start, end).trim() + suffix;
4796
4716
  }
4797
4717
  export {
4798
4718
  ABSORB_PROMPT_MARKER,