acp-kernel 0.0.9 → 0.0.11

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,EAGL,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAcpB,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;CACpB;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;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CAoN7D;AAsoBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAcpB,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;CACpB;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;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CAoN7D;AAgpBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1 +1 @@
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;AAIhE,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AAGD,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,GACxB,kBAAkB,CAwDpB"}
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;AAQhE,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AAGD,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,GACxB,kBAAkB,CAwDpB"}
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export { syncBlocks } from "./sync.js";
9
9
  export { resolveBoundaries, parseBoundary } from "./boundaries.js";
10
10
  export { defaultCountTokens, estimateTokensFast, createBpeTokenizer } from "./tokenize.js";
11
11
  export type { TokenCountFn } from "./tokenize.js";
12
- export { renderNudgeText } from "./nudge-text.js";
12
+ export { renderNudgeText, formatRanges } from "./nudge-text.js";
13
13
  export type { NudgeVoice, RenderedNudge } from "./nudge-text.js";
14
14
  export { COMPRESS_PHILOSOPHY, HOW_TO_COMPRESS_RULES, TIER2_DISTILL_RULES, TIER3_CONDENSE_RULES } from "./compression-rules.js";
15
15
  export { truncateLargeToolOutputs } from "./truncate-tools.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3F,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/H,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACH,eAAe,EACf,6BAA6B,EAC7B,kBAAkB,EAClB,eAAe,EACf,2BAA2B,GAC9B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EACL,WAAW,EACX,MAAM,EACN,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC;AACvB,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3F,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/H,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACH,eAAe,EACf,6BAA6B,EAC7B,kBAAkB,EAClB,eAAe,EACf,2BAA2B,GAC9B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EACL,WAAW,EACX,MAAM,EACN,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC;AACvB,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -505,7 +505,7 @@ function truncateLargeToolOutputs(messages, tokenCount, config, countTokens, opt
505
505
  }
506
506
 
507
507
  // src/hide-consumed.ts
508
- var KEEP_LAST_ORPHANED = 2;
508
+ var KEEP_LAST_ORPHANED = 0;
509
509
  function hideConsumedCompressCalls(state, messages) {
510
510
  const activeCallIds = /* @__PURE__ */ new Set();
511
511
  const allBlockCallIds = /* @__PURE__ */ new Set();
@@ -1492,7 +1492,13 @@ function decideNudge(input) {
1492
1492
  const blocked = eligible.filter((t) => (tiers[t]?.pending ?? 0) >= nudgeGrowthTokens && (state.nudge.lastShownByTier[t] ?? 0) > 0 && tokenCount - (state.nudge.lastShownByTier[t] ?? 0) < growthFloor).map((t) => `T${t} (cadence)`);
1493
1493
  const blockedHint = blocked.length > 0 ? `, blocked: ${blocked.join(", ")}` : "";
1494
1494
  const maxPending = Math.max(0, ...Object.values(tiers).map((t) => t.pending));
1495
- reason = `max compressible ${maxPending} < threshold ${nudgeGrowthTokens}${readyHint}${blockedHint}, growth ${growthSinceReference} (floor ${growthFloor})`;
1495
+ const pendingShort = maxPending < nudgeGrowthTokens;
1496
+ const growthShort = growthSinceReference < growthFloor;
1497
+ const parts = [];
1498
+ if (pendingShort) parts.push(`max compressible ${maxPending} < threshold ${nudgeGrowthTokens}`);
1499
+ if (growthShort) parts.push(`growth ${growthSinceReference} < floor ${growthFloor}`);
1500
+ if (parts.length === 0) parts.push(`max compressible ${maxPending}, growth ${growthSinceReference}`);
1501
+ reason = `${parts.join("; ")}${readyHint}${blockedHint}`;
1496
1502
  }
1497
1503
  const ctxBreakdown = computeContextBreakdown(input.messages, tokenCount, growthSinceReference);
1498
1504
  return {
@@ -1710,50 +1716,60 @@ function formatBreakdown(bd) {
1710
1716
  +${formatK(bd.growth)} since last nudge` : "";
1711
1717
  return `Context breakdown: ${parts.join(" | ")}${growth}`;
1712
1718
  }
1713
- function refToNum(ref) {
1714
- if (!ref) return 0;
1715
- const m = ref.match(/^m0*(\d+)$/);
1716
- return m && m[1] ? parseInt(m[1], 10) : 0;
1719
+ function formatTierTargetBlocks(blocks) {
1720
+ if (blocks.length === 0) {
1721
+ return "Target blocks: (none \u2014 no tier blocks found)";
1722
+ }
1723
+ const lines = blocks.map((b) => {
1724
+ const summaryTokens = Math.ceil((b.summary ?? "").length / 4);
1725
+ const topic = b.topic ? ` "${b.topic}"` : "";
1726
+ return ` ${b.blockId} ${b.effectiveMessageIds.length} msgs ${formatK(b.compressedTokens)}\u2192${formatK(summaryTokens)}${topic}`;
1727
+ });
1728
+ return `Target ${blocks[0].tier === 1 ? "tier-1" : "tier-2"} blocks to distill (${blocks.length}):
1729
+ ${lines.join("\n")}`;
1717
1730
  }
1718
- function mergeRanges(compressible, protected_) {
1731
+ function formatRanges(compressible, protectedRanges) {
1732
+ if (compressible.length === 0 && protectedRanges.length === 0) {
1733
+ return "[No specific ranges detected \u2014 compress any consumed content.]";
1734
+ }
1735
+ const refNum2 = (ref) => {
1736
+ const m = ref.match(/\d+/);
1737
+ return m ? parseInt(m[0], 10) : 0;
1738
+ };
1719
1739
  const entries = [];
1720
1740
  for (const r of compressible) {
1721
- const sNum = refToNum(r.startRef);
1722
- const eNum = refToNum(r.endRef);
1723
1741
  entries.push({
1724
1742
  startRef: r.startRef,
1725
1743
  endRef: r.endRef,
1726
- startNum: sNum,
1727
- endNum: eNum,
1744
+ startNum: refNum2(r.startRef),
1745
+ endNum: refNum2(r.endRef),
1728
1746
  count: r.count,
1729
1747
  tokens: r.tokens,
1748
+ toolPct: r.toolPct,
1749
+ textPct: r.textPct,
1730
1750
  compressibleTokens: r.tokens,
1731
1751
  compressibleCount: r.count,
1732
1752
  protectedTokens: 0,
1733
1753
  protectedCount: 0,
1734
1754
  protectedTools: [],
1735
- toolPct: r.toolPct,
1736
- textPct: r.textPct,
1737
1755
  dangerous: r.dangerous ?? false
1738
1756
  });
1739
1757
  }
1740
- for (const r of protected_) {
1741
- const sNum = refToNum(r.startRef);
1742
- const eNum = refToNum(r.endRef);
1758
+ for (const r of protectedRanges) {
1743
1759
  entries.push({
1744
1760
  startRef: r.startRef,
1745
1761
  endRef: r.endRef,
1746
- startNum: sNum,
1747
- endNum: eNum,
1762
+ startNum: refNum2(r.startRef),
1763
+ endNum: refNum2(r.endRef),
1748
1764
  count: r.count,
1749
1765
  tokens: r.tokens,
1766
+ toolPct: 0,
1767
+ textPct: 0,
1750
1768
  compressibleTokens: 0,
1751
1769
  compressibleCount: 0,
1752
1770
  protectedTokens: r.tokens,
1753
1771
  protectedCount: r.count,
1754
1772
  protectedTools: [...r.tools],
1755
- toolPct: 0,
1756
- textPct: 0,
1757
1773
  dangerous: false
1758
1774
  });
1759
1775
  }
@@ -1761,7 +1777,7 @@ function mergeRanges(compressible, protected_) {
1761
1777
  const merged = [];
1762
1778
  for (const e of entries) {
1763
1779
  const last = merged[merged.length - 1];
1764
- if (last && last.endNum + 1 >= e.startNum) {
1780
+ if (last && e.startNum <= last.endNum + 1) {
1765
1781
  last.endRef = e.endRef;
1766
1782
  last.endNum = Math.max(last.endNum, e.endNum);
1767
1783
  last.count += e.count;
@@ -1778,26 +1794,7 @@ function mergeRanges(compressible, protected_) {
1778
1794
  merged.push({ ...e });
1779
1795
  }
1780
1796
  }
1781
- return merged;
1782
- }
1783
- function formatTierTargetBlocks(blocks) {
1784
- if (blocks.length === 0) {
1785
- return "Target blocks: (none \u2014 no tier blocks found)";
1786
- }
1787
- const lines = blocks.map((b) => {
1788
- const summaryTokens = Math.ceil((b.summary ?? "").length / 4);
1789
- const topic = b.topic ? ` "${b.topic}"` : "";
1790
- return ` ${b.blockId} ${b.effectiveMessageIds.length} msgs ${formatK(b.compressedTokens)}\u2192${formatK(summaryTokens)}${topic}`;
1791
- });
1792
- return `Target ${blocks[0].tier === 1 ? "tier-1" : "tier-2"} blocks to distill (${blocks.length}):
1793
- ${lines.join("\n")}`;
1794
- }
1795
- function formatRanges(compressible, protected_) {
1796
- const merged = mergeRanges(compressible, protected_);
1797
- if (merged.length === 0) {
1798
- return "[No specific ranges detected \u2014 compress any consumed content.]";
1799
- }
1800
- const lines = merged.slice(0, 10).map((e) => {
1797
+ const lines = merged.map((e) => {
1801
1798
  const suffix = e.dangerous && e.compressibleTokens > 0 ? " \u26A0\uFE0F NOT recommended unless you are certain." : "";
1802
1799
  if (e.protectedTokens > 0 && e.compressibleTokens === 0) {
1803
1800
  return ` ${e.startRef}\u2013${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [PROTECTED: ${e.protectedTools.join(", ")} \u2014 not compressible]${suffix}`;
@@ -1807,7 +1804,7 @@ function formatRanges(compressible, protected_) {
1807
1804
  }
1808
1805
  return ` ${e.startRef}\u2013${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [tool ${e.toolPct}% | text ${e.textPct}%]${suffix}`;
1809
1806
  });
1810
- return `Compressible ranges (oldest first):
1807
+ return `Compressible ranges (${merged.length}, oldest first):
1811
1808
  ${lines.join("\n")}`;
1812
1809
  }
1813
1810
  function renderNudgeText(decision) {
@@ -2401,6 +2398,7 @@ export {
2401
2398
  estimateTokensFast,
2402
2399
  findActiveAncestor,
2403
2400
  findBlocksOverlappingMessages,
2401
+ formatRanges,
2404
2402
  getMessageFilter,
2405
2403
  hideConsumedCompressCalls,
2406
2404
  highestActiveTier,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/refs.ts","../src/state.ts","../src/prune.ts","../src/sync.ts","../src/tokenize.ts","../src/config.ts","../src/boundaries.ts","../src/truncate-tools.ts","../src/hide-consumed.ts","../src/filter/registry.ts","../src/filter/apply.ts","../src/render-refs.ts","../src/protected.ts","../src/tool-pairs.ts","../src/recommend.ts","../src/pipeline.ts","../src/compress.ts","../src/compression-rules.ts","../src/nudge-text.ts","../src/keep-markers.ts","../src/decompress.ts","../src/report.ts","../src/rebuild.ts","../src/search.ts"],"sourcesContent":["import type { CoreMessage, MessageRefMap } from \"./types.js\";\n\nconst REF_WIDTH = 5;\nconst MIN_INDEX = 1;\nconst MAX_INDEX = 99999;\nconst REF_PATTERN = /^m0*(\\d{1,5})$/;\n\nexport const BLOCKED_REF = \"BLOCKED\";\n\nexport function emptyRefMap(): MessageRefMap {\n return { byRaw: {}, byRef: {} };\n}\n\nexport function indexToRef(index: number): string {\n if (!Number.isInteger(index) || index < MIN_INDEX || index > MAX_INDEX) {\n throw new RangeError(\n `ref index out of bounds: ${index} (allowed ${MIN_INDEX}-${MAX_INDEX})`,\n );\n }\n return `m${String(index).padStart(REF_WIDTH, \"0\")}`;\n}\n\nexport function refToIndex(ref: string): number | null {\n const match = REF_PATTERN.exec(ref.trim().toLowerCase());\n if (!match) return null;\n const index = Number(match[1]);\n if (index < MIN_INDEX || index > MAX_INDEX) return null;\n return index;\n}\n\nexport function refForRaw(map: MessageRefMap, rawId: string): string | null {\n return map.byRaw[rawId] ?? null;\n}\n\nexport function rawForRef(map: MessageRefMap, ref: string): string | null {\n return map.byRef[ref] ?? null;\n}\n\nexport interface AssignRefsResult {\n map: MessageRefMap;\n nextIndex: number;\n newlyAssigned: number;\n}\n\nexport interface AssignRefsOptions {\n existing: MessageRefMap;\n nextIndex: number;\n isProtected?: (message: CoreMessage) => boolean;\n shouldSkip?: (message: CoreMessage) => boolean;\n}\n\nexport function assignRefs(\n messages: CoreMessage[],\n options: AssignRefsOptions,\n): AssignRefsResult {\n const map: MessageRefMap = {\n byRaw: { ...options.existing.byRaw },\n byRef: { ...options.existing.byRef },\n };\n let cursor =\n Number.isInteger(options.nextIndex) && options.nextIndex >= MIN_INDEX\n ? options.nextIndex\n : MIN_INDEX;\n let newlyAssigned = 0;\n\n for (const message of messages) {\n if (!message.id || options.shouldSkip?.(message)) continue;\n\n if (map.byRaw[message.id]) continue;\n\n if (options.isProtected?.(message)) {\n map.byRaw[message.id] = BLOCKED_REF;\n continue;\n }\n\n const ref = allocateFreeRef(map, cursor);\n cursor = ref.index + 1;\n map.byRaw[message.id] = ref.text;\n map.byRef[ref.text] = message.id;\n newlyAssigned++;\n }\n\n return { map, nextIndex: cursor, newlyAssigned };\n}\n\nfunction allocateFreeRef(\n map: MessageRefMap,\n start: number,\n): { text: string; index: number } {\n let candidate = Math.max(start, MIN_INDEX);\n while (candidate <= MAX_INDEX) {\n const text = indexToRef(candidate);\n if (!map.byRef[text]) {\n return { text, index: candidate };\n }\n candidate++;\n }\n throw new Error(\n `ref capacity exhausted: cannot allocate beyond ${indexToRef(MAX_INDEX)}`,\n );\n}\n\nexport function rebuildRefIndex(map: MessageRefMap): MessageRefMap {\n const byRef: Record<string, string> = {};\n for (const [rawId, ref] of Object.entries(map.byRaw)) {\n if (ref !== BLOCKED_REF) byRef[ref] = rawId;\n }\n return { byRaw: { ...map.byRaw }, byRef };\n}\n\nexport function highestUsedIndex(map: MessageRefMap): number {\n let highest = 0;\n for (const ref of Object.values(map.byRaw)) {\n const index = ref === BLOCKED_REF ? null : refToIndex(ref);\n if (index !== null && index > highest) highest = index;\n }\n return highest;\n}\n","import type { CompressionBlock, CompressionState } from \"./types.js\";\n\nexport function createInitialState(): CompressionState {\n return {\n blocks: [],\n messageRefs: { byRaw: {}, byRef: {} },\n nudge: {\n lastPerMessageNudgeTokens: 0,\n lastNudgeShownTokens: 0,\n baselineTokens: 0,\n anchors: {},\n lastShownByTier: {},\n },\n stats: { tokensCompressed: 0, compressionCount: 0 },\n nextBlockId: 1,\n nextRunId: 1,\n };\n}\n\nexport function allocateBlockId(state: CompressionState): string {\n const id = state.nextBlockId;\n state.nextBlockId = Math.max(1, id) + 1;\n return `b${id}`;\n}\n\nexport function allocateRunId(state: CompressionState): string {\n const id = state.nextRunId;\n state.nextRunId = Math.max(1, id) + 1;\n return `r${id}`;\n}\n\nexport function blockById(\n state: CompressionState,\n blockId: string,\n): CompressionBlock | undefined {\n return state.blocks.find((block) => block.blockId === blockId);\n}\n\nexport function activeBlocks(state: CompressionState): CompressionBlock[] {\n return state.blocks.filter((block) => block.active);\n}\n\nexport function coveredMessageIds(state: CompressionState): Set<string> {\n const covered = new Set<string>();\n for (const block of state.blocks) {\n if (!block.active) continue;\n for (const id of block.effectiveMessageIds) covered.add(id);\n }\n return covered;\n}\n\nexport function highestActiveTier(state: CompressionState): 0 | 1 | 2 | 3 {\n let highest: 0 | 1 | 2 | 3 = 0;\n for (const block of state.blocks) {\n if (block.active && block.tier > highest) highest = block.tier;\n }\n return highest;\n}\n\nexport function advanceSurvival(\n state: CompressionState,\n promotionThreshold: number,\n): void {\n for (const block of state.blocks) {\n if (!block.active) continue;\n block.survivedCount += 1;\n if (block.survivedCount >= promotionThreshold) {\n block.generation = \"old\";\n }\n }\n}\n","import { activeBlocks, coveredMessageIds } from \"./state.js\";\nimport type { CompressionState, CoreMessage } from \"./types.js\";\n\nexport const SUMMARY_HEADER = \"[Compressed conversation section]\";\n\nexport interface PruneOptions {\n injectSummaries?: boolean;\n}\n\nexport function prune(\n messages: CoreMessage[],\n state: CompressionState,\n options: PruneOptions = {},\n): CoreMessage[] {\n const covered = coveredMessageIds(state);\n if (covered.size === 0) return [...messages];\n\n const inject = options.injectSummaries ?? true;\n const firstUserIndex = messages.findIndex(\n (message) => message.role === \"user\",\n );\n\n const indexById = new Map<string, number>();\n messages.forEach((message, index) => indexById.set(message.id, index));\n\n const anchors = inject ? collectSummaryAnchors(state, indexById) : [];\n\n return stripOrphanedToolResults(\n stripOrphanedToolCalls(\n rebuildMessages(messages, covered, firstUserIndex, anchors),\n ),\n );\n}\n\ninterface SummaryAnchor {\n blockId: string;\n summary: string;\n topic?: string;\n insertAt: number;\n}\n\nfunction collectSummaryAnchors(\n state: CompressionState,\n indexById: Map<string, number>,\n): SummaryAnchor[] {\n const anchors: SummaryAnchor[] = [];\n for (const block of activeBlocks(state)) {\n let earliest: number | null = null;\n for (const id of block.effectiveMessageIds) {\n const index = indexById.get(id);\n if (index !== undefined && (earliest === null || index < earliest)) {\n earliest = index;\n }\n }\n anchors.push({\n blockId: block.blockId,\n summary: block.summary,\n topic: block.topic,\n insertAt: earliest ?? 0,\n });\n }\n anchors.sort((left, right) => left.insertAt - right.insertAt);\n return anchors;\n}\n\nfunction rebuildMessages(\n messages: CoreMessage[],\n covered: Set<string>,\n firstUserIndex: number,\n anchors: SummaryAnchor[],\n): CoreMessage[] {\n const result: CoreMessage[] = [];\n const pending = [...anchors];\n\n for (let index = 0; index < messages.length; index++) {\n while (pending.length > 0 && pending[0]!.insertAt === index) {\n result.push(renderSummary(pending.shift()!));\n }\n if (index === firstUserIndex && firstUserIndex >= 0) {\n result.push(messages[index]!);\n continue;\n }\n if (covered.has(messages[index]!.id)) continue;\n result.push(messages[index]!);\n }\n\n while (pending.length > 0) {\n result.push(renderSummary(pending.shift()!));\n }\n\n return result;\n}\n\nfunction renderSummary(anchor: SummaryAnchor): CoreMessage {\n const body = anchor.summary.trim();\n const topicLine = anchor.topic\n ? `${SUMMARY_HEADER} — ${anchor.topic}`\n : SUMMARY_HEADER;\n const text = body.length === 0 ? topicLine : `${topicLine}\\n${body}`;\n return {\n id: `acp_summary_${anchor.blockId}`,\n role: \"system\",\n contentType: \"text\",\n text,\n };\n}\n\nfunction stripOrphanedToolResults(messages: CoreMessage[]): CoreMessage[] {\n const knownCallIds = new Set<string>();\n for (const m of messages) {\n if (m.contentType === \"tool-call\" && m.toolCallId) {\n knownCallIds.add(m.toolCallId);\n }\n }\n return messages.filter(\n (m) =>\n m.contentType !== \"tool-result\" ||\n !m.toolCallId ||\n knownCallIds.has(m.toolCallId),\n );\n}\n\nfunction stripOrphanedToolCalls(messages: CoreMessage[]): CoreMessage[] {\n const knownResultIds = new Set<string>();\n for (const m of messages) {\n if (m.contentType === \"tool-result\" && m.toolCallId) {\n knownResultIds.add(m.toolCallId);\n }\n }\n return messages.filter(\n (m) =>\n m.contentType !== \"tool-call\" ||\n !m.toolCallId ||\n m.toolName === \"compress\" ||\n knownResultIds.has(m.toolCallId),\n );\n}\n","import type { CompressionState, CoreMessage } from \"./types.js\";\n\nexport interface SyncResult {\n state: CompressionState;\n deactivated: string[];\n}\n\nexport function syncBlocks(\n messages: CoreMessage[],\n state: CompressionState,\n): SyncResult {\n const presentIds = new Set(messages.map((message) => message.id));\n const deactivated: string[] = [];\n // Deep-clone (not just `{...state}`) so the caller's input state is never\n // mutated: processTurn stamps `state.nudge.*` and reassigns `messageRefs`,\n // and block sub-arrays must not alias the input. Previously nudge/stats/\n // messageRefs were shared references → input-state mutation leak.\n const result: CompressionState = {\n blocks: state.blocks.map((block) => ({\n ...block,\n directMessageIds: [...block.directMessageIds],\n effectiveMessageIds: [...block.effectiveMessageIds],\n directBlockIds: [...block.directBlockIds],\n })),\n messageRefs: {\n byRaw: { ...state.messageRefs.byRaw },\n byRef: { ...state.messageRefs.byRef },\n },\n nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },\n stats: { ...state.stats },\n nextBlockId: state.nextBlockId,\n nextRunId: state.nextRunId,\n };\n\n const consumedBlockIds = new Set<string>();\n for (const block of result.blocks) {\n for (const consumedId of block.directBlockIds) {\n consumedBlockIds.add(consumedId);\n }\n }\n\n for (const block of result.blocks) {\n if (consumedBlockIds.has(block.blockId)) {\n block.active = false;\n continue;\n }\n block.active = true;\n const stillPresent = block.effectiveMessageIds.some((id) =>\n presentIds.has(id),\n );\n if (!stillPresent) {\n block.active = false;\n deactivated.push(block.blockId);\n }\n }\n\n return { state: result, deactivated };\n}\n","import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\nexport function defaultCountTokens(text: string): number {\n if (!text) return 0;\n // CJK chars tokenize ~1:1 (chars/4 badly underestimates them). Count them\n // directly, then estimate the non-CJK remainder with chars/4 so digits,\n // punctuation, and symbols in code/JSON are not dropped to zero.\n const cjk = text.match(/[\\u4e00-\\u9fff\\u3040-\\u30ff\\uac00-\\ud7af]/g);\n const cjkCount = cjk?.length ?? 0;\n return cjkCount + Math.ceil((text.length - cjkCount) / 4);\n}\n\nexport function estimateMessageTokens(text: string | undefined): number {\n return defaultCountTokens(text ?? \"\");\n}\n\nexport function estimateTokensFast(text: string): number {\n if (!text) return 0;\n return Math.ceil(text.length / 4);\n}\n\nexport type TokenCountFn = (text: string) => number;\n\nexport function createBpeTokenizer(): TokenCountFn {\n try {\n const mod = require(\"@anthropic-ai/tokenizer\");\n const bpeCount = mod.countTokens ?? mod.default?.countTokens;\n if (typeof bpeCount !== \"function\") return defaultCountTokens;\n return (text: string) => {\n try {\n return bpeCount(text);\n } catch {\n return defaultCountTokens(text);\n }\n };\n } catch {\n return defaultCountTokens;\n }\n}\n","import type { Config } from \"./types.js\";\n\nexport function defaultConfig(\n modelContextLimit: number,\n overrides: Partial<Config> = {},\n): Config {\n const base: Config = {\n tiers: { enabled: true, tier2Trigger: 5, tier3Trigger: 10 },\n nudge: {\n maxContextLimitPct: 0.55,\n minContextLimitPct: 0.45,\n frequency: 5,\n iterationThreshold: 15,\n force: \"soft\",\n growthRatio: 0.05,\n growthFloor: Math.max(20000, Math.round(modelContextLimit * 0.05)),\n growthCap: 50000,\n minGrowthFloor: 20000,\n minGrowthRatio: 0.45,\n emergencyThresholdPct: 0.80,\n },\n promotionThreshold: 5,\n truncate: { threshold: 1 },\n compress: {\n minCompressRange: 5000,\n maxSummaryLength: 20000,\n minSummaryLength: 50,\n },\n protectedTools: [],\n preserveRecentMessages: 5,\n preserveRecentTokens: 5000,\n modelContextLimit,\n };\n return {\n ...base,\n ...overrides,\n tiers: { ...base.tiers, ...overrides.tiers },\n nudge: { ...base.nudge, ...overrides.nudge },\n truncate: { ...base.truncate, ...overrides.truncate },\n compress: { ...base.compress, ...overrides.compress },\n };\n}\n\nexport function validateConfig(config: Config): string[] {\n const errors: string[] = [];\n if (\n !Number.isFinite(config.modelContextLimit) ||\n config.modelContextLimit <= 0\n ) {\n errors.push(\"modelContextLimit must be a positive number\");\n }\n if (config.nudge.minContextLimitPct > config.nudge.maxContextLimitPct) {\n errors.push(\n \"nudge.minContextLimitPct must not exceed nudge.maxContextLimitPct\",\n );\n }\n if (config.promotionThreshold < 1) {\n errors.push(\"promotionThreshold must be >= 1\");\n }\n if (config.truncate.threshold <= 0 || config.truncate.threshold > 1) {\n errors.push(\"truncate.threshold must be in (0, 1]\");\n }\n for (const tier of [config.tiers.tier2Trigger, config.tiers.tier3Trigger]) {\n if (tier < 1) errors.push(\"tier triggers must be >= 1\");\n }\n if (config.tiers.tier3Trigger <= config.tiers.tier2Trigger) {\n errors.push(\"tiers.tier3Trigger must be greater than tiers.tier2Trigger\");\n }\n return errors;\n}\n","import { activeBlocks, blockById } from \"./state.js\";\nimport type {\n CompressionState,\n CoreMessage,\n ResolvedBoundary,\n} from \"./types.js\";\n\nexport type BoundaryKind = \"message\" | \"block\";\n\nexport interface ParsedBoundary {\n kind: BoundaryKind;\n numericId: number;\n raw: string;\n}\n\nconst MESSAGE_REF_PATTERN = /^m0*(\\d{1,5})$/;\nconst BLOCK_REF_PATTERN = /^b(\\d{1,9})$/;\n\nexport function parseBoundary(ref: string): ParsedBoundary | null {\n const normalized = ref.trim().toLowerCase();\n const messageMatch = MESSAGE_REF_PATTERN.exec(normalized);\n if (messageMatch) {\n const numericId = Number(messageMatch[1]);\n if (numericId >= 1 && numericId <= 99999) {\n return { kind: \"message\", numericId, raw: normalized };\n }\n }\n const blockMatch = BLOCK_REF_PATTERN.exec(normalized);\n if (blockMatch) {\n const numericId = Number(blockMatch[1]);\n if (numericId >= 1) return { kind: \"block\", numericId, raw: normalized };\n }\n return null;\n}\n\nexport interface ResolveBoundariesInput {\n startRef: string;\n endRef: string;\n messages: CoreMessage[];\n state: CompressionState;\n}\n\nexport interface ResolvedRange {\n startIndex: number;\n endIndex: number;\n messageIds: string[];\n nestedBlockIds: string[];\n boundaryKind: BoundaryKind;\n protectedGaps: number[];\n}\n\nexport function resolveBoundaries(\n input: ResolveBoundariesInput,\n): ResolvedRange {\n const start = parseBoundary(input.startRef);\n const end = parseBoundary(input.endRef);\n if (!start || !end) {\n throw new Error(\n `Invalid boundary ref(s): startId=\"${input.startRef}\", endId=\"${input.endRef}\". Use mNNNNN or bN.`,\n );\n }\n\n const indexByRawId = new Map<string, number>();\n input.messages.forEach((message, index) =>\n indexByRawId.set(message.id, index),\n );\n\n let startIndex = resolveAnchorIndex(start, input.state, indexByRawId);\n let endIndex = resolveAnchorIndex(end, input.state, indexByRawId);\n\n if (startIndex === null || endIndex === null) {\n throw new Error(\n `Boundary not found in visible context (likely consumed by an existing block). ` +\n `startId=\"${input.startRef}\", endId=\"${input.endRef}\".`,\n );\n }\n\n if (startIndex > endIndex) {\n [startIndex, endIndex] = [endIndex, startIndex];\n }\n\n const messageIds: string[] = [];\n for (let index = startIndex; index <= endIndex; index++) {\n const message = input.messages[index];\n if (message) messageIds.push(message.id);\n }\n\n const boundaryKind: BoundaryKind =\n start.kind === \"block\" || end.kind === \"block\" ? \"block\" : \"message\";\n\n const nestedBlockIds: string[] = [];\n const nestedSeen = new Set<string>();\n for (const block of activeBlocks(input.state)) {\n const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);\n if (anchor !== null && anchor >= startIndex && anchor <= endIndex) {\n if (!nestedSeen.has(block.blockId)) {\n nestedSeen.add(block.blockId);\n nestedBlockIds.push(block.blockId);\n }\n }\n }\n\n const protectedGaps: number[] = [];\n\n return {\n startIndex,\n endIndex,\n messageIds,\n nestedBlockIds,\n boundaryKind,\n protectedGaps,\n };\n}\n\nfunction resolveAnchorIndex(\n boundary: ParsedBoundary,\n state: CompressionState,\n indexByRawId: Map<string, number>,\n): number | null {\n if (boundary.kind === \"message\") {\n const rawId =\n state.messageRefs.byRef[boundary.raw] ??\n state.messageRefs.byRef[formatPaddedRef(boundary.numericId)];\n if (!rawId) return null;\n const index = indexByRawId.get(rawId);\n return index === undefined ? null : index;\n }\n\n const block = blockById(state, `b${boundary.numericId}`);\n if (!block || !block.active) return null;\n return earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);\n}\n\nfunction formatPaddedRef(index: number): string {\n return `m${String(index).padStart(5, \"0\")}`;\n}\n\nexport function earliestIndexOfIds(\n ids: string[],\n indexByRawId: Map<string, number>,\n): number | null {\n let earliest: number | null = null;\n for (const id of ids) {\n const index = indexByRawId.get(id);\n if (index !== undefined && (earliest === null || index < earliest)) {\n earliest = index;\n }\n }\n return earliest;\n}\n\nexport function toResolvedBoundary(range: ResolvedRange): ResolvedBoundary {\n return {\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n protectedGaps: range.protectedGaps,\n };\n}\n","import type { Config, CoreMessage } from \"./types.js\";\n\nexport interface TruncateOptions {\n minOutputTokens?: number;\n keepPrefixChars?: number;\n keepSuffixChars?: number;\n protectRecentMessages?: number;\n}\n\nexport interface TruncateResult {\n messages: CoreMessage[];\n truncatedCount: number;\n savedTokens: number;\n}\n\nconst TRUNCATION_MARKER = \"[truncated for context space]\";\nconst DEFAULTS = {\n minOutputTokens: 1000,\n keepPrefixChars: 2000,\n keepSuffixChars: 2000,\n protectRecentMessages: 3,\n} as const;\n\nexport function truncateLargeToolOutputs(\n messages: CoreMessage[],\n tokenCount: number,\n config: Config,\n countTokens: (text: string) => number,\n options: TruncateOptions = {},\n): TruncateResult {\n const opts = { ...DEFAULTS, ...options };\n if (config.modelContextLimit <= 0) return { messages, truncatedCount: 0, savedTokens: 0 };\n\n const threshold = config.truncate.threshold * config.modelContextLimit;\n if (tokenCount < threshold) return { messages, truncatedCount: 0, savedTokens: 0 };\n\n const protectedIndex = messages.length - opts.protectRecentMessages;\n const candidates: Array<{ index: number; tokens: number }> = [];\n\n for (let index = 0; index < messages.length; index++) {\n if (index >= protectedIndex) break;\n const message = messages[index]!;\n if (message.contentType !== \"tool-result\") continue;\n const text = message.text ?? \"\";\n if (text.length === 0 || text.includes(TRUNCATION_MARKER)) continue;\n const tokens = countTokens(text);\n if (tokens < opts.minOutputTokens) continue;\n candidates.push({ index, tokens });\n }\n\n if (candidates.length === 0) return { messages, truncatedCount: 0, savedTokens: 0 };\n candidates.sort((left, right) => right.tokens - left.tokens);\n\n const targetTokens = threshold * 0.9;\n let savedTokens = 0;\n const edits = new Map<number, string>();\n let truncatedCount = 0;\n\n for (const candidate of candidates) {\n if (tokenCount - savedTokens <= targetTokens) break;\n const original = messages[candidate.index]!.text ?? \"\";\n if (original.length <= opts.keepPrefixChars + opts.keepSuffixChars) continue;\n\n const prefix = original.slice(0, opts.keepPrefixChars);\n const suffix = original.slice(-opts.keepSuffixChars);\n const replacement =\n prefix +\n `\\n\\n...${TRUNCATION_MARKER} — original ~${candidate.tokens} tokens]...\\n\\n` +\n suffix;\n edits.set(candidate.index, replacement);\n savedTokens += candidate.tokens - countTokens(replacement);\n truncatedCount++;\n }\n\n if (truncatedCount === 0) return { messages, truncatedCount: 0, savedTokens: 0 };\n\n const updated = messages.map((message, index) =>\n edits.has(index) ? { ...message, text: edits.get(index)! } : message,\n );\n return { messages: updated, truncatedCount, savedTokens };\n}\n","import type { CompressionState, CoreMessage } from \"./types.js\";\n\nconst KEEP_LAST_ORPHANED = 2;\n\nexport interface HideConsumedResult {\n messages: CoreMessage[];\n hidden: number;\n}\n\n// Keep active-block compress calls + the most recent orphaned calls; hide the rest.\nexport function hideConsumedCompressCalls(\n state: CompressionState,\n messages: CoreMessage[],\n): HideConsumedResult {\n const activeCallIds = new Set<string>();\n const allBlockCallIds = new Set<string>();\n for (const block of state.blocks) {\n if (block.compressCallId) {\n allBlockCallIds.add(block.compressCallId);\n if (block.active) activeCallIds.add(block.compressCallId);\n }\n }\n\n const lastOrphanedCallIds: string[] = [];\n for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {\n const message = messages[i]!;\n if (message.toolName !== \"compress\" || message.contentType !== \"tool-call\") continue;\n const callId = message.toolCallId;\n if (callId && !allBlockCallIds.has(callId)) {\n lastOrphanedCallIds.push(callId);\n }\n }\n\n const keepCallIds = new Set([...activeCallIds, ...lastOrphanedCallIds]);\n\n const hiddenCallIds = new Set<string>();\n for (const message of messages) {\n if (\n message.toolName === \"compress\" &&\n message.contentType === \"tool-call\" &&\n (!message.toolCallId || !keepCallIds.has(message.toolCallId))\n ) {\n if (message.toolCallId) hiddenCallIds.add(message.toolCallId);\n }\n }\n\n let hidden = 0;\n const result: CoreMessage[] = [];\n for (const message of messages) {\n if (\n message.toolName === \"compress\" &&\n message.contentType === \"tool-call\" &&\n (!message.toolCallId || !keepCallIds.has(message.toolCallId))\n ) {\n hidden++;\n continue;\n }\n if (\n message.contentType === \"tool-result\" &&\n message.toolCallId &&\n hiddenCallIds.has(message.toolCallId)\n ) {\n hidden++;\n continue;\n }\n result.push(message);\n }\n\n return { messages: result, hidden };\n}\n","import type { MessageFilter } from \"./types.js\";\n\nconst registry = new Map<string, MessageFilter>();\n\nexport function registerMessageFilter(filter: MessageFilter): void {\n const existing = registry.get(filter.name);\n if (existing && existing.version !== filter.version) {\n throw new Error(\n `Message filter \"${filter.name}\" already registered with version ${existing.version}, cannot register version ${filter.version}.`,\n );\n }\n registry.set(filter.name, filter);\n}\n\nexport function getMessageFilter(name: string): MessageFilter | undefined {\n return registry.get(name);\n}\n\nexport function listMessageFilters(): MessageFilter[] {\n return [...registry.values()];\n}\n\nexport function clearMessageFilters(): void {\n registry.clear();\n}\n","import { listMessageFilters } from \"./registry.js\";\nimport type { CoreMessage } from \"../types.js\";\nimport type { FilterResult, MessageFilterContext, MessageFiltersConfig } from \"./types.js\";\n\nexport interface ApplyResult {\n messages: CoreMessage[];\n partsFiltered: number;\n partsDropped: number;\n partsModified: number;\n}\n\nexport function applyMessageFilters(\n messages: CoreMessage[],\n config: MessageFiltersConfig | undefined,\n): ApplyResult {\n if (!config?.enabled) {\n return { messages, partsFiltered: 0, partsDropped: 0, partsModified: 0 };\n }\n\n const active = listMessageFilters().filter(\n (filter) => config.filters?.[filter.name]?.enabled !== false,\n );\n if (active.length === 0) {\n return { messages, partsFiltered: 0, partsDropped: 0, partsModified: 0 };\n }\n\n let working = messages.map((message) => ({ ...message }));\n const tally = { partsFiltered: 0, partsDropped: 0, partsModified: 0 };\n const total = working.length;\n\n const immediate = active.filter((filter) => !filter.keepLastOnly);\n for (let index = 0; index < working.length; index++) {\n const message = working[index]!;\n const text = message.text ?? \"\";\n if (text.length === 0) continue;\n let current = text;\n const baseCtx: MessageFilterContext = {\n text: current,\n role: message.role,\n messageIndex: index,\n totalMessages: total,\n toolName: message.toolName,\n };\n for (const filter of immediate) {\n let decision: FilterResult;\n try {\n decision = filter.filter(baseCtx);\n } catch {\n continue;\n }\n if (decision.action === \"keep\") continue;\n tally.partsFiltered++;\n if (decision.action === \"drop\") {\n current = \"\";\n tally.partsDropped++;\n } else if (decision.action === \"modify\" && decision.text !== undefined) {\n current = decision.text;\n tally.partsModified++;\n }\n baseCtx.text = current;\n }\n if (current !== text) working[index] = { ...message, text: current };\n }\n\n const keepLast = active.filter((filter) => filter.keepLastOnly);\n for (const filter of keepLast) {\n let foundLast = false;\n for (let index = working.length - 1; index >= 0; index--) {\n const message = working[index]!;\n const text = message.text ?? \"\";\n if (text.length === 0) continue;\n const ctx: MessageFilterContext = {\n text,\n role: message.role,\n messageIndex: index,\n totalMessages: total,\n toolName: message.toolName,\n };\n let decision: FilterResult;\n try {\n decision = filter.filter(ctx);\n } catch {\n continue;\n }\n if (decision.action !== \"drop\" && decision.action !== \"modify\") continue;\n if (foundLast) {\n tally.partsFiltered++;\n tally.partsDropped++;\n working[index] = { ...message, text: \"\" };\n } else {\n foundLast = true;\n if (decision.action === \"modify\" && decision.text !== undefined) {\n tally.partsFiltered++;\n tally.partsModified++;\n working[index] = { ...message, text: decision.text };\n }\n }\n }\n }\n\n return { messages: working, ...tally };\n}\n","import type { CoreMessage, CompressionState, MessageRefMap } from \"./types.js\";\nimport { refForRaw, BLOCKED_REF } from \"./refs.js\";\nimport type { PipelineNode, PipelineContext, NodeIO } from \"./pipeline.js\";\n\n/** Format token count: <1K raw, <10K \"X.YK\", >=10K \"XK\". */\nfunction formatTokens(tokens: number): string {\n if (tokens < 1000) return String(tokens);\n if (tokens < 10000) return (tokens / 1000).toFixed(1) + \"K\";\n return Math.round(tokens / 1000) + \"K\";\n}\n\nfunction classifyType(message: CoreMessage): string {\n if (\n message.contentType === \"tool-call\" ||\n message.contentType === \"tool-result\"\n ) {\n return message.toolName || \"tool\";\n }\n return message.contentType;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst LT = \"\\x3c\";\nconst GT = \"\\x3e\";\nconst TAG_OPEN = LT + \"acp \";\nconst TAG_CLOSE = LT + \"/acp\" + GT;\n\nfunction acpTag(ref: string, tokens: number, type: string): string {\n return TAG_OPEN + 'tokens=\"' + formatTokens(tokens) + '\" type=\"' + type + '\"' + GT + ref + TAG_CLOSE;\n}\n\nfunction renderMessage(\n message: CoreMessage,\n map: MessageRefMap,\n countTokens: (text: string) => number,\n): CoreMessage {\n const ref = refForRaw(map, message.id);\n if (!ref || ref === BLOCKED_REF) return message;\n\n // Strip own stale tag BEFORE computing tokens (idempotency).\n // Match the message's own ref only — foreign tags survive (content-corruption fix).\n const ownTagRe = new RegExp(\n \"^\" + escapeRegex(TAG_OPEN) + \"[^>]*\" + GT + escapeRegex(ref) + escapeRegex(TAG_CLOSE) + \"\\\\n?\",\n );\n const cleanText = (message.text || \"\").replace(ownTagRe, \"\");\n\n const tokens = countTokens(cleanText);\n const type = classifyType(message);\n const prefix = acpTag(ref, tokens, type) + \"\\n\";\n\n if (!cleanText) return { ...message, text: prefix };\n return { ...message, text: prefix + cleanText };\n}\n\nexport function renderVisibleRefs(\n messages: CoreMessage[],\n state: CompressionState,\n countTokens: (text: string) => number = (text) =>\n Math.ceil(text.length / 4),\n): CoreMessage[] {\n const map = state.messageRefs;\n return messages.map((message) =>\n renderMessage(message, map, countTokens),\n );\n}\n\nexport const renderRefsNode: PipelineNode = {\n name: \"render-refs\",\n run(io: NodeIO, ctx: PipelineContext): NodeIO {\n return {\n ...io,\n messages: renderVisibleRefs(io.messages, io.state, ctx.countTokens),\n };\n },\n};\n","import type { Config, CoreMessage } from \"./types.js\";\n\n/** Tools that are ALWAYS protected, regardless of user config. These are ACP's\n * own metadata tools whose records must remain in context: compress calls\n * carry the summaries that decompress/search rely on, and the system prompt\n * treats past compress calls as load-bearing metadata. Letting them be\n * compressed away breaks decompress and the \"summary is historical\" contract. */\nexport const ALWAYS_PROTECTED_TOOLS = [\"compress\"] as const;\n\nexport function matchToolPattern(toolName: string, pattern: string): boolean {\n if (pattern.endsWith(\"*\")) {\n return toolName.startsWith(pattern.slice(0, -1));\n }\n return toolName === pattern;\n}\n\nexport function isMessageProtected(\n msg: CoreMessage,\n config: Pick<Config, \"protectedTools\" | \"isToolProtected\">,\n): boolean {\n // tool-result carries the same toolName as its tool-call (the host projects\n // it), so checking toolName covers both sides of a tool exchange.\n if (\n (msg.contentType !== \"tool-call\" && msg.contentType !== \"tool-result\") ||\n !msg.toolName\n ) {\n return false;\n }\n\n // Hard-coded protection: ACP metadata tools are never compressible.\n if ((ALWAYS_PROTECTED_TOOLS as readonly string[]).includes(msg.toolName)) {\n return true;\n }\n\n for (const pattern of config.protectedTools) {\n if (matchToolPattern(msg.toolName, pattern)) return true;\n }\n\n if (config.isToolProtected?.(msg.toolName, msg.text)) return true;\n\n return false;\n}\n\n/** Build the set of toolCallIds whose tool-call is protected. Use this to also\n * protect tool-results that lack a toolName (common when the host projects a\n * tool-result with only toolCallId). Without it, the result half of a\n * protected tool exchange leaks into compressible ranges. */\nexport function collectProtectedToolCallIds(\n messages: CoreMessage[],\n config: Pick<Config, \"protectedTools\" | \"isToolProtected\">,\n): Set<string> {\n const ids = new Set<string>();\n for (const m of messages) {\n if (m.contentType === \"tool-call\" && m.toolCallId && isMessageProtected(m, config)) {\n ids.add(m.toolCallId);\n }\n }\n return ids;\n}\n\n/** Like isMessageProtected, but also matches tool-results by toolCallId against\n * the protected call set. Use when you have the full message list available. */\nexport function isMessageProtectedWithPairing(\n msg: CoreMessage,\n config: Pick<Config, \"protectedTools\" | \"isToolProtected\">,\n protectedCallIds: Set<string>,\n): boolean {\n if (isMessageProtected(msg, config)) return true;\n if (\n msg.contentType === \"tool-result\" &&\n msg.toolCallId &&\n protectedCallIds.has(msg.toolCallId)\n ) {\n return true;\n }\n return false;\n}\n","import type { CoreMessage } from \"./types.js\";\n\n/**\n * Adjust compression range boundaries to include tool-call/result pairs.\n *\n * PREVENTIVE approach (adapted from opencode-acp PR #248): before compression\n * is applied, scan for tool-call or tool-result messages whose matching half\n * (the result for a call in range, or the call for a result in range) sits\n * outside the requested range. Pull the orphan half INTO the range so the\n * pair is compressed together — zero information loss.\n *\n * Only MESSAGE-boundary ranges are adjusted. Block-boundary ranges (bN) are\n * left untouched to preserve tier-detection correctness.\n *\n * @returns Adjusted { startIndex, endIndex } — may be wider than input.\n */\nexport function adjustBoundariesForToolPairs(\n startIndex: number,\n endIndex: number,\n messages: CoreMessage[],\n maxScan: number = 20,\n): { startIndex: number; endIndex: number } {\n // Collect all toolCallIds in range (both tool-call and tool-result messages).\n // Skip compress tool — it's force-protected and always survives pruning.\n const callIdsInRange = new Set<string>();\n for (let i = startIndex; i <= endIndex; i++) {\n const msg = messages[i];\n if (!msg || !msg.toolCallId) continue;\n if (msg.toolName === \"compress\") continue;\n callIdsInRange.add(msg.toolCallId);\n }\n\n if (callIdsInRange.size === 0) {\n return { startIndex, endIndex };\n }\n\n // Extend FORWARD: tool-results typically follow their tool-call.\n // Stop at the first gap after finding at least one matching message.\n let newEndIndex = endIndex;\n for (let i = endIndex + 1; i < messages.length && i <= endIndex + maxScan; i++) {\n const msg = messages[i];\n if (!msg) break;\n if (msg.toolCallId && callIdsInRange.has(msg.toolCallId)) {\n newEndIndex = i;\n } else if (newEndIndex > endIndex) {\n break;\n }\n }\n\n // Extend BACKWARD: tool-calls typically precede their tool-result.\n let newStartIndex = startIndex;\n for (let i = startIndex - 1; i >= 0 && i >= startIndex - maxScan; i--) {\n const msg = messages[i];\n if (!msg) break;\n if (msg.toolCallId && callIdsInRange.has(msg.toolCallId)) {\n newStartIndex = i;\n } else if (newStartIndex < startIndex) {\n break;\n }\n }\n\n return { startIndex: newStartIndex, endIndex: newEndIndex };\n}\n","/**\n * Recommendation engine — compression protection + recommendation.\n *\n * Clean-room reimplementation of the recommendation algorithm (MIT, ours).\n * These pure functions answer two questions every turn:\n *\n * 1. **Protection** — which messages must NOT be compressed? (protected tools,\n * recent messages, recent tokens)\n * 2. **Recommendation** — which remaining ranges are actually WORTH compressing?\n * (growth-aware threshold; suppress nudges when ranges are too small)\n *\n * Called by the `recommend` pipeline node. No side effects, no state mutation.\n */\n\nimport type {\n CompressibleRange,\n Config,\n ContextRanges,\n CoreMessage,\n ProtectedRange,\n} from \"./types.js\";\nimport type { CompressionState } from \"./types.js\";\nimport {\n collectProtectedToolCallIds,\n isMessageProtectedWithPairing,\n} from \"./protected.js\";\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction refNum(ref: string): number {\n const n = parseInt(ref.slice(1), 10);\n return Number.isNaN(n) ? -1 : n;\n}\n\nfunction estimateMessageTokens(message: CoreMessage): number {\n return Math.ceil((message.text ?? \"\").length / 4);\n}\n\nfunction isToolMessage(message: CoreMessage): boolean {\n return message.contentType === \"tool-call\" || message.contentType === \"tool-result\";\n}\n\n\nfunction isSyntheticOrPruned(\n message: CoreMessage,\n state: CompressionState,\n): boolean {\n if (message.text?.startsWith(\"[Compressed conversation section]\")) return true;\n for (const block of state.blocks) {\n if (block.active && block.effectiveMessageIds.includes(message.id)) return true;\n }\n return false;\n}\n\n// ─── 1. Protected Refs (soft protection zone) ─────────────────────────────────\n\n/**\n * Compute the set of protected message refs (mNNNNN) that form the\n * \"soft-protected zone\" at the tail of the conversation.\n *\n * Combines two rules:\n * 1. Last N messages (`config.preserveRecentMessages`)\n * 2. Last N tokens expanding backward (`config.preserveRecentTokens`)\n *\n * Only considers visible, non-synthetic, non-pruned messages that have refs.\n */\nexport function computeProtectedRefs(\n messages: CoreMessage[],\n state: CompressionState,\n config: Config,\n): Set<string> {\n const preserveN = config.preserveRecentMessages;\n const preserveTokens = config.preserveRecentTokens;\n\n const result = new Set<string>();\n const visible: { ref: string; tokens: number }[] = [];\n\n for (const msg of messages) {\n if (isSyntheticOrPruned(msg, state)) continue;\n const ref = state.messageRefs.byRaw[msg.id];\n if (!ref || ref === \"BLOCKED\") continue;\n visible.push({ ref, tokens: estimateMessageTokens(msg) });\n }\n\n // Rule 1: last N messages\n if (preserveN > 0) {\n for (const m of visible.slice(-preserveN)) {\n result.add(m.ref);\n }\n }\n\n // Rule 2: last N tokens (expand backward from tail)\n if (preserveTokens > 0) {\n let tokenAccum = 0;\n for (let i = visible.length - 1; i >= 0 && tokenAccum < preserveTokens; i--) {\n result.add(visible[i]!.ref);\n tokenAccum += visible[i]!.tokens;\n }\n }\n\n // Rule 3: last visible user message. Protected whenever recent-message\n // protection is on (preserveRecentMessages > 0) — this couples it to the\n // same switch as Rule 1, so setting preserveRecentMessages = 0 fully opts\n // out (needed by tests that compress the tail). Production defaultConfig\n // uses 5, so the last user message is always protected in practice.\n if (preserveN > 0) {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role !== \"user\" || isSyntheticOrPruned(msg, state)) continue;\n const ref = state.messageRefs.byRaw[msg.id];\n if (ref && ref !== \"BLOCKED\") result.add(ref);\n break;\n }\n }\n\n return result;\n}\n\n// ─── 2. Build Compressible + Protected Ranges ────────────────────────────────\n\n/**\n * Build compressible and protected range groups from the message list.\n *\n * Messages are classified into:\n * - **compressible**: normal messages outside the protected zone\n * - **protected**: messages from protected tools (e.g., skill, task)\n * - **skipped**: covered by blocks, synthetic, or in the protected zone\n *\n * Compressible messages are grouped into contiguous ranges. The protected\n * zone (from `computeProtectedRefs`) splits groups — the unprotected head\n * survives as its own range.\n */\nexport function buildCompressibleRanges(\n messages: CoreMessage[],\n state: CompressionState,\n config: Config,\n protectedZoneRefs?: Set<string>,\n): ContextRanges {\n const compressibleMsgs: {\n ref: string;\n refNum: number;\n tokens: number;\n isTool: boolean;\n isUser: boolean;\n }[] = [];\n const protectedMsgs: {\n ref: string;\n refNum: number;\n tokens: number;\n tools: string[];\n }[] = [];\n\n // Pairing: a tool-result may carry only toolCallId (no toolName). Collect the\n // callIds of protected tool-calls first, then protect matching results too.\n const protectedCallIds = collectProtectedToolCallIds(messages, config);\n\n for (const msg of messages) {\n if (isSyntheticOrPruned(msg, state)) continue;\n const ref = state.messageRefs.byRaw[msg.id];\n if (!ref || ref === \"BLOCKED\") continue;\n\n const rn = refNum(ref);\n\n if (isMessageProtectedWithPairing(msg, config, protectedCallIds)) {\n protectedMsgs.push({\n ref,\n refNum: rn,\n tokens: estimateMessageTokens(msg),\n tools: msg.toolName ? [msg.toolName] : [],\n });\n continue;\n }\n\n if (protectedZoneRefs?.has(ref)) {\n continue;\n }\n\n compressibleMsgs.push({\n ref,\n refNum: rn,\n tokens: estimateMessageTokens(msg),\n isTool: isToolMessage(msg),\n isUser: msg.role === \"user\",\n });\n }\n\n // Build compressible groups (contiguous, split at ref gaps and at user\n // messages once a group has >= 3 messages). Splitting at user boundaries\n // keeps each compressible range aligned to roughly one user turn, instead\n // of producing one giant range spanning many turns (or, conversely, a\n // fragment per message when ref gaps appear). Mirrors opencode-acp's\n // buildCompressibleRanges condition.\n const compressible: CompressibleRange[] = [];\n let cur: CompressibleRange | null = null;\n let prevRefNum = -2;\n\n for (const info of compressibleMsgs) {\n const hasGap = info.refNum > prevRefNum + 1;\n if (cur && ((info.isUser && cur.count >= 3) || hasGap)) {\n compressible.push(cur);\n cur = null;\n }\n prevRefNum = info.refNum;\n if (!cur) {\n cur = {\n startRef: info.ref,\n endRef: info.ref,\n count: 1,\n tokens: info.tokens,\n toolPct: info.isTool ? 100 : 0,\n textPct: info.isTool ? 0 : 100,\n };\n } else {\n cur.endRef = info.ref;\n cur.count++;\n cur.tokens += info.tokens;\n if (info.isTool) {\n cur.toolPct = Math.round((cur.toolPct * (cur.count - 1) + 100) / cur.count);\n } else {\n cur.toolPct = Math.round((cur.toolPct * (cur.count - 1)) / cur.count);\n }\n cur.textPct = 100 - cur.toolPct;\n }\n }\n if (cur) compressible.push(cur);\n\n // Build protected groups (contiguous)\n const protectedRanges: ProtectedRange[] = [];\n let pcur: ProtectedRange | null = null;\n let pPrevRefNum = -2;\n\n for (const info of protectedMsgs) {\n const hasGap = info.refNum > pPrevRefNum + 1;\n if (pcur && hasGap) {\n protectedRanges.push(pcur);\n pcur = null;\n }\n pPrevRefNum = info.refNum;\n if (!pcur) {\n pcur = {\n startRef: info.ref,\n endRef: info.ref,\n count: 1,\n tokens: info.tokens,\n tools: [...info.tools],\n };\n } else {\n pcur.endRef = info.ref;\n pcur.count++;\n pcur.tokens += info.tokens;\n for (const t of info.tools) {\n if (!pcur!.tools.includes(t)) pcur!.tools.push(t);\n }\n }\n }\n if (pcur) protectedRanges.push(pcur);\n\n return {\n compressible: compressible.filter((g) => g.tokens > 0),\n protected: protectedRanges,\n };\n}\n","import type { CompressionState, CoreMessage, NudgeDecision } from \"./types.js\";\n\nexport interface PipelineContext {\n readonly config: import(\"./types.js\").Config;\n readonly tokenCount: number;\n readonly countTokens: (text: string) => number;\n}\n\nexport interface NodeEffects {\n nudge?: NudgeDecision;\n recommendation?: import(\"./types.js\").Recommendation;\n truncatedCount?: number;\n readonly [key: string]: unknown;\n}\n\nexport interface NodeIO {\n messages: CoreMessage[];\n state: CompressionState;\n effects: NodeEffects;\n}\n\nexport interface PipelineNode {\n readonly name: string;\n run(io: NodeIO, ctx: PipelineContext): NodeIO;\n enabled?: (io: NodeIO, ctx: PipelineContext) => boolean;\n}\n\nexport function makeIO(\n messages: CoreMessage[],\n state: CompressionState,\n effects: NodeEffects = {},\n): NodeIO {\n return { messages, state, effects };\n}\n\nexport function runPipeline(\n nodes: readonly PipelineNode[],\n initial: NodeIO,\n ctx: PipelineContext,\n): NodeIO {\n let io = initial;\n for (const node of nodes) {\n if (node.enabled && !node.enabled(io, ctx)) continue;\n io = node.run(io, ctx);\n }\n return io;\n}\n","import { assignRefs, highestUsedIndex } from \"./refs.js\";\nimport { prune } from \"./prune.js\";\nimport { syncBlocks } from \"./sync.js\";\nimport { advanceSurvival, activeBlocks, blockById } from \"./state.js\";\nimport {\n allocateBlockId,\n allocateRunId,\n createInitialState,\n} from \"./state.js\";\nimport { defaultCountTokens } from \"./tokenize.js\";\nimport { validateConfig } from \"./config.js\";\nimport { resolveBoundaries, earliestIndexOfIds } from \"./boundaries.js\";\nimport { truncateLargeToolOutputs } from \"./truncate-tools.js\";\nimport { hideConsumedCompressCalls } from \"./hide-consumed.js\";\nimport { applyMessageFilters, listMessageFilters } from \"./filter/index.js\";\nimport { renderRefsNode } from \"./render-refs.js\";\nimport { isMessageProtected } from \"./protected.js\";\nimport { adjustBoundariesForToolPairs } from \"./tool-pairs.js\";\nimport {\n computeProtectedRefs,\n buildCompressibleRanges,\n} from \"./recommend.js\";\nimport {\n runPipeline,\n type PipelineContext,\n type PipelineNode,\n type NodeIO,\n} from \"./pipeline.js\";\nimport type {\n ApplyCompressionResult,\n CompressionBlock,\n CompressionState,\n CompressionTier,\n Config,\n ContextBreakdown,\n CoreMessage,\n NudgeConfig,\n NudgeDecision,\n ProcessTurnResult,\n Recommendation,\n StatusReport,\n} from \"./types.js\";\n\nexport interface Ports {\n countTokens?: (text: string) => number;\n}\n\nexport interface CompressionCore {\n processTurn(input: ProcessTurnInput): ProcessTurnResult;\n applyCompression(input: ApplyCompressionInput): ApplyCompressionResult;\n defaultNodes(): PipelineNode[];\n decompress(\n blockId: string,\n state: CompressionState,\n ): CompressionBlock | undefined;\n search(query: string, state: CompressionState): CompressionBlock[];\n status(\n state: CompressionState,\n tokenCount: number,\n config: Config,\n ): StatusReport;\n}\n\nexport interface ProcessTurnInput {\n messages: CoreMessage[];\n state: CompressionState;\n config: Config;\n tokenCount: number;\n}\n\nexport interface ApplyCompressionInput {\n ranges: {\n startRef: string;\n endRef: string;\n summary: string;\n topic?: string;\n compressCallId?: string;\n summaryMaxChars?: number;\n }[];\n messages: CoreMessage[];\n state: CompressionState;\n config: Config;\n protectedMessageIds?: Set<string>;\n}\n\nexport function createCore(ports: Ports = {}): CompressionCore {\n const countTokens = ports.countTokens ?? defaultCountTokens;\n\n function applyCompression(\n input: ApplyCompressionInput,\n ): ApplyCompressionResult {\n const state: CompressionState = cloneState(input.state);\n const runId = allocateRunId(state);\n let blocksCreated = 0;\n let tokensCompressed = 0;\n const errors: string[] = [];\n\n // Default to the soft-protected zone (recent-N + last user message) when the\n // caller doesn't pass an explicit set. This makes applyCompression safe by\n // default; applySingleRange enforces it as a hard backstop.\n const protectedMessageIds =\n input.protectedMessageIds ??\n computeProtectedRefs(input.messages, input.state, input.config);\n\n const preExistingCoverage = collectCoverage(state);\n\n const rangeIndexSets: { spec: typeof input.ranges[number]; indices: number[] }[] = [];\n for (const spec of input.ranges) {\n let resolved;\n try {\n resolved = resolveBoundaries({\n startRef: spec.startRef,\n endRef: spec.endRef,\n messages: input.messages,\n state,\n });\n } catch {\n continue;\n }\n const indices = resolved.messageIds.map((id) =>\n input.messages.findIndex((m) => m.id === id),\n ).filter((i) => i >= 0);\n rangeIndexSets.push({ spec, indices });\n }\n const sortedRanges = [...rangeIndexSets].sort((a, b) => {\n const aMin = a.indices.length > 0 ? Math.min(...a.indices) : Infinity;\n const bMin = b.indices.length > 0 ? Math.min(...b.indices) : Infinity;\n return aMin - bMin;\n });\n for (let i = 1; i < sortedRanges.length; i++) {\n const prev = sortedRanges[i - 1]!;\n const curr = sortedRanges[i]!;\n const prevMax = prev.indices.length > 0 ? Math.max(...prev.indices) : -1;\n const currMin = curr.indices.length > 0 ? Math.min(...curr.indices) : -1;\n if (prevMax >= currMin && prevMax >= 0) {\n return {\n state: input.state,\n result: {\n blocksCreated: 0,\n tokensCompressed: 0,\n errors: [\n `content: range (${prev.spec.startRef}..${prev.spec.endRef}) overlaps (${curr.spec.startRef}..${curr.spec.endRef}). Overlapping ranges cannot be compressed in the same batch.`,\n ],\n },\n };\n }\n }\n\n if (input.config.compress.minCompressRange > 0 && input.ranges.length > 0) {\n let totalRangeChars = 0;\n let hasBlockBoundaryRange = false;\n for (const spec of input.ranges) {\n let resolved;\n try {\n resolved = resolveBoundaries({\n startRef: spec.startRef,\n endRef: spec.endRef,\n messages: input.messages,\n state,\n });\n } catch {\n continue;\n }\n if (resolved.boundaryKind === \"block\") {\n hasBlockBoundaryRange = true;\n continue;\n }\n for (const id of resolved.messageIds) {\n const msg = input.messages.find((m) => m.id === id);\n totalRangeChars += msg?.text?.length ?? 0;\n }\n }\n if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {\n return {\n state: input.state,\n result: {\n blocksCreated: 0,\n tokensCompressed: 0,\n errors: [\n `Total compressible content too small (${totalRangeChars} chars across ${input.ranges.length} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`,\n ],\n },\n };\n }\n }\n\n for (const spec of input.ranges) {\n try {\n const compressed = applySingleRange({\n spec,\n messages: input.messages,\n state,\n runId,\n config: input.config,\n protectedMessageIds,\n countTokens,\n preExistingCoverage,\n });\n blocksCreated++;\n tokensCompressed += compressed;\n } catch (error) {\n errors.push(error instanceof Error ? error.message : String(error));\n }\n }\n\n state.stats.compressionCount += blocksCreated;\n state.stats.tokensCompressed += tokensCompressed;\n\n if (blocksCreated > 0) {\n // Compress succeeded: clear the growth baseline so the next turn\n // re-establishes it at the new (lower) token count. Without this the\n // nudge re-fires in a feedback loop (the §5.7 baseline-reset bug).\n state.nudge.lastPerMessageNudgeTokens = 0;\n state.nudge.lastNudgeShownTokens = 0;\n // Clearing the per-tier cadence too: after a successful compression\n // (which may have consumed blocks of tier N to produce tier N+1), every\n // tier should be eligible to re-evaluate from the new token count.\n state.nudge.lastShownByTier = {};\n }\n\n return { state, result: { blocksCreated, tokensCompressed, errors } };\n }\n\n function processTurn(input: ProcessTurnInput): ProcessTurnResult {\n const configErrors = validateConfig(input.config);\n if (configErrors.length > 0) {\n console.warn(`[acp-kernel] Config validation warnings: ${configErrors.join(\"; \")}. Thresholds may not fire correctly.`);\n }\n const ctx: PipelineContext = {\n config: input.config,\n tokenCount: input.tokenCount,\n countTokens,\n };\n const initial: NodeIO = {\n messages: input.messages,\n state: input.state,\n effects: {},\n };\n const result = runPipeline(defaultNodes(), initial, ctx);\n return {\n messages: result.messages,\n state: result.state,\n nudge: result.effects.nudge,\n };\n }\n\n function decompress(blockId: string, state: CompressionState) {\n return blockById(state, blockId);\n }\n\n function search(query: string, state: CompressionState): CompressionBlock[] {\n const terms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((term) => term.length > 0);\n if (terms.length === 0) return [];\n const scored = activeBlocks(state)\n .map((block) => ({ block, score: scoreRelevance(block, terms) }))\n .filter((entry) => entry.score > 0.1)\n .sort((left, right) => right.score - left.score);\n return scored.map((entry) => entry.block);\n }\n\n function status(\n state: CompressionState,\n tokenCount: number,\n config: Config,\n ): StatusReport {\n const active = activeBlocks(state);\n const usage =\n config.modelContextLimit > 0 ? tokenCount / config.modelContextLimit : 0;\n return {\n contextUsage: usage,\n tokenCount,\n modelContextLimit: config.modelContextLimit,\n activeBlocks: active.length,\n totalBlocks: state.blocks.length,\n tokensCompressed: state.stats.tokensCompressed,\n breakdown: { active: active.length, total: state.blocks.length },\n };\n }\n\n function defaultNodes(): PipelineNode[] {\n return [\n assignRefsNode,\n syncBlocksNode,\n pruneNode,\n filterNode,\n hideCompressCallsNode,\n recommendNode,\n nudgeNode,\n emergencyTruncateNode,\n renderRefsNode,\n ];\n }\n\n return { processTurn, applyCompression, defaultNodes, decompress, search, status };\n}\n\n// --- Pipeline nodes -------------------------------------------------------\n// Each node owns ONE concern. The ref map has a SINGLE writer (assignRefsNode);\n// tags are DERIVED at the end (renderRefsNode) — no dual source of truth, so\n// the old stripHallucinations band-aid is gone. Truncation is the LAST\n// token-reducing safety valve; render-refs is the final annotation pass.\n\nconst assignRefsNode: PipelineNode = {\n name: \"assign-refs\",\n run(io, ctx) {\n const hasProtection =\n ctx.config.protectedTools.length > 0 || !!ctx.config.isToolProtected;\n const protectedFn = hasProtection\n ? (m: CoreMessage) => isMessageProtected(m, ctx.config)\n : undefined;\n const refResult = assignRefs(io.messages, {\n existing: io.state.messageRefs,\n nextIndex: highestUsedIndex(io.state.messageRefs) + 1,\n isProtected: protectedFn,\n });\n return { ...io, state: { ...io.state, messageRefs: refResult.map } };\n },\n};\n\nconst syncBlocksNode: PipelineNode = {\n name: \"sync-blocks\",\n run(io, ctx) {\n const synced = syncBlocks(io.messages, io.state);\n advanceSurvival(synced.state, ctx.config.promotionThreshold);\n return { ...io, state: synced.state };\n },\n};\n\nconst pruneNode: PipelineNode = {\n name: \"prune\",\n run(io) {\n return { ...io, messages: prune(io.messages, io.state) };\n },\n};\n\nconst filterNode: PipelineNode = {\n name: \"filter\",\n enabled: (_io, ctx) =>\n !!ctx.config.messageFilters?.enabled && listMessageFilters().length > 0,\n run(io, ctx) {\n const applied = applyMessageFilters(io.messages, ctx.config.messageFilters);\n return { ...io, messages: applied.messages };\n },\n};\n\nconst hideCompressCallsNode: PipelineNode = {\n name: \"hide-compress-calls\",\n run(io) {\n const hidden = hideConsumedCompressCalls(io.state, io.messages);\n return { ...io, messages: hidden.messages };\n },\n};\n\nconst recommendNode: PipelineNode = {\n name: \"recommend\",\n run(io, ctx) {\n const protectedRefs = computeProtectedRefs(\n io.messages,\n io.state,\n ctx.config,\n );\n const contextRanges = buildCompressibleRanges(\n io.messages,\n io.state,\n ctx.config,\n protectedRefs,\n );\n const nothingToCompress = contextRanges.compressible.length === 0;\n const recommendation: Recommendation = {\n contextRanges,\n recommendedRanges: contextRanges.compressible,\n nothingToCompress,\n };\n return { ...io, effects: { ...io.effects, recommendation } };\n },\n};\n\nconst nudgeNode: PipelineNode = {\n name: \"nudge-inject\",\n run(io, ctx) {\n const nudge = decideNudge({\n tokenCount: ctx.tokenCount,\n config: ctx.config,\n state: io.state,\n messages: io.messages,\n recommendation: io.effects.recommendation,\n countTokens: ctx.countTokens,\n });\n\n const baseline = io.state.nudge.lastPerMessageNudgeTokens;\n const nudgeGrowthTokens = resolveAdaptiveGrowth(\n ctx.config.modelContextLimit,\n ctx.config.nudge,\n );\n\n let stamped = { ...io.state.nudge };\n\n if (\n baseline > 0 &&\n ctx.tokenCount < baseline - nudgeGrowthTokens\n ) {\n stamped.lastPerMessageNudgeTokens = ctx.tokenCount;\n stamped.lastNudgeShownTokens = 0;\n }\n\n if (stamped.lastPerMessageNudgeTokens === 0) {\n stamped.lastPerMessageNudgeTokens = ctx.tokenCount;\n }\n\n if (nudge.shouldInject) {\n stamped.lastNudgeShownTokens = ctx.tokenCount;\n // Record the injected tier's own cadence baseline. Shared baseline\n // (lastNudgeShownTokens) suppresses lower-priority tiers within this\n // turn; the per-tier entry throttles re-firing of the SAME tier.\n if (nudge.tier !== null) {\n stamped.lastShownByTier = { ...stamped.lastShownByTier, [nudge.tier]: ctx.tokenCount };\n }\n }\n\n return {\n ...io,\n state: { ...io.state, nudge: stamped },\n effects: { ...io.effects, nudge },\n };\n },\n};\n\nconst emergencyTruncateNode: PipelineNode = {\n name: \"emergency-truncate\",\n run(io, ctx) {\n const usage =\n ctx.config.modelContextLimit > 0\n ? ctx.tokenCount / ctx.config.modelContextLimit\n : 0;\n if (usage < ctx.config.truncate.threshold) return io;\n const trunc = truncateLargeToolOutputs(\n io.messages,\n ctx.tokenCount,\n ctx.config,\n ctx.countTokens,\n { protectRecentMessages: ctx.config.preserveRecentMessages },\n );\n return {\n ...io,\n messages: trunc.messages,\n effects: { ...io.effects, truncatedCount: trunc.truncatedCount },\n };\n },\n};\n\ninterface SingleRangeInput {\n spec: { startRef: string; endRef: string; summary: string; topic?: string; compressCallId?: string; summaryMaxChars?: number };\n messages: CoreMessage[];\n state: CompressionState;\n runId: string;\n config: Config;\n protectedMessageIds?: Set<string>;\n countTokens: (text: string) => number;\n preExistingCoverage: Set<string>;\n}\n\nfunction applySingleRange(input: SingleRangeInput): number {\n const resolved = resolveBoundaries({\n startRef: input.spec.startRef,\n endRef: input.spec.endRef,\n messages: input.messages,\n state: input.state,\n });\n\n const rangeMessageIds = applyToolPairAdjustment(\n resolved,\n input.messages,\n );\n\n // Re-scan for nested blocks in the ADJUSTED range (tool-pair extension may\n // have pulled in messages that are anchors of existing blocks).\n if (rangeMessageIds.length > resolved.messageIds.length) {\n const indexByRawId = new Map<string, number>();\n input.messages.forEach((m, i) => indexByRawId.set(m.id, i));\n const adjustedStart = indexByRawId.get(rangeMessageIds[0]!) ?? resolved.startIndex;\n const adjustedEnd = indexByRawId.get(rangeMessageIds[rangeMessageIds.length - 1]!) ?? resolved.endIndex;\n const nestedSeen = new Set(resolved.nestedBlockIds);\n for (const block of activeBlocks(input.state)) {\n if (nestedSeen.has(block.blockId)) continue;\n const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);\n if (anchor !== null && anchor >= adjustedStart && anchor <= adjustedEnd) {\n nestedSeen.add(block.blockId);\n resolved.nestedBlockIds.push(block.blockId);\n }\n }\n }\n\n const isBlockBoundary = resolved.boundaryKind === \"block\";\n const targetTier = resolveTargetTier(\n input.state,\n resolved.nestedBlockIds,\n isBlockBoundary,\n );\n const outputTier = isBlockBoundary\n ? (Math.min(3, targetTier + 1) as CompressionTier)\n : 1;\n\n const consumedBlockIds = resolved.nestedBlockIds.filter((id) => {\n const block = blockById(input.state, id);\n return block?.active && block.tier === targetTier;\n });\n\n const effectiveMessageIds = new Set<string>(rangeMessageIds);\n for (const consumedId of consumedBlockIds) {\n const consumed = blockById(input.state, consumedId);\n if (consumed) {\n for (const id of consumed.effectiveMessageIds)\n effectiveMessageIds.add(id);\n }\n }\n\n const directMessageIds = [...effectiveMessageIds].filter(\n (id) => !input.preExistingCoverage.has(id),\n );\n\n const filteredIds = filterProtectedToolMessages(\n directMessageIds,\n input.messages,\n input.config,\n );\n\n // HARD PROTECTION: never let the recent-N / last-user-message zone be\n // compressed, even if the model ignores the nudge and calls compress\n // directly on those refs. `protectedMessageIds` holds REF ids (mNNNNN)\n // from computeProtectedRefs; filteredIds holds RAW message ids, so convert\n // via state.messageRefs.byRaw before testing membership. applySingleRange\n // enforces this as the real backstop; the recommend/nudge path is advisory.\n const protectedRefs = input.protectedMessageIds;\n const hitProtectedRaw = protectedRefs\n ? filteredIds.filter((id) => {\n const ref = input.state.messageRefs.byRaw[id];\n return ref !== undefined && protectedRefs.has(ref);\n })\n : [];\n if (hitProtectedRaw.length > 0) {\n const recentN = input.config.preserveRecentMessages;\n const hitRefs = hitProtectedRaw\n .map((id) => input.state.messageRefs.byRaw[id])\n .filter(Boolean);\n throw new Error(\n `Range includes protected messages (the last ${recentN} messages and/or the most recent user message) which must not be compressed: ${hitRefs.join(\n \", \",\n )}. Adjust startId/endId to exclude them.`,\n );\n }\n\n validateCompressionRange(input, filteredIds, consumedBlockIds.length);\n\n let compressedTokens = 0;\n for (const id of filteredIds) {\n const message = input.messages.find((entry) => entry.id === id);\n compressedTokens += input.countTokens(message?.text ?? \"\");\n }\n for (const consumedId of consumedBlockIds) {\n const consumed = blockById(input.state, consumedId);\n if (consumed) {\n compressedTokens += input.countTokens(consumed.summary);\n }\n }\n\n const blockId = allocateBlockId(input.state);\n const block: CompressionBlock = {\n blockId,\n runId: input.runId,\n tier: outputTier,\n topic: input.spec.topic,\n summary: input.spec.summary,\n directMessageIds: filteredIds,\n effectiveMessageIds: [...effectiveMessageIds],\n directBlockIds: [...consumedBlockIds],\n compressedTokens,\n createdAt: Date.now(),\n survivedCount: 0,\n generation: \"young\",\n active: true,\n compressCallId: input.spec.compressCallId,\n };\n input.state.blocks.push(block);\n\n for (const consumedId of consumedBlockIds) {\n const consumed = blockById(input.state, consumedId);\n if (consumed) consumed.active = false;\n }\n\n return compressedTokens;\n}\n\nfunction applyToolPairAdjustment(\n resolved: { startIndex: number; endIndex: number; messageIds: string[]; boundaryKind: string },\n messages: CoreMessage[],\n): string[] {\n if (resolved.boundaryKind === \"block\") {\n return resolved.messageIds;\n }\n const adjusted = adjustBoundariesForToolPairs(\n resolved.startIndex,\n resolved.endIndex,\n messages,\n );\n if (\n adjusted.startIndex === resolved.startIndex &&\n adjusted.endIndex === resolved.endIndex\n ) {\n return resolved.messageIds;\n }\n const ids: string[] = [];\n for (let i = adjusted.startIndex; i <= adjusted.endIndex; i++) {\n const msg = messages[i];\n if (msg) ids.push(msg.id);\n }\n return ids;\n}\n\nfunction validateCompressionRange(\n input: SingleRangeInput,\n directMessageIds: string[],\n consumedBlockCount: number,\n): void {\n const cfg = input.config.compress;\n const summary = input.spec.summary?.trim() ?? \"\";\n\n if (summary.length === 0) {\n throw new Error(\n \"Summary is empty — provide a meaningful summary of the compressed range.\",\n );\n }\n\n if (cfg.minSummaryLength > 0 && summary.length < cfg.minSummaryLength) {\n throw new Error(\n `Summary too short (${summary.length} chars, min ${cfg.minSummaryLength}). The summary must capture the compressed range's key information.`,\n );\n }\n\n const effectiveMax = input.spec.summaryMaxChars ?? cfg.maxSummaryLength;\n if (\n effectiveMax > 0 &&\n summary.length > effectiveMax\n ) {\n throw new Error(\n `Summary too long (${summary.length} chars, max ${effectiveMax}). Strip noise — keep critical paths, decisions, errors, and code references. Or pass summaryMaxChars to increase the limit — don't lose critical info just to fit.`,\n );\n }\n\n if (directMessageIds.length === 0 && consumedBlockCount === 0) {\n throw new Error(\n \"Range contains no compressible messages — all are already covered by active blocks or protected.\",\n );\n }\n}\n\nfunction filterProtectedToolMessages(\n directMessageIds: string[],\n messages: CoreMessage[],\n config: Config,\n): string[] {\n // Protected tool calls (and their results, paired by toolCallId) stay in\n // visible context and are simply dropped from the compressible set. They are\n // NOT folded into the summary — the summary reflects what the author wrote,\n // nothing auto-appended.\n const protectedCallIds = new Set<string>();\n const removedIds = new Set<string>();\n for (const msg of messages) {\n if (isMessageProtected(msg, config) && msg.toolCallId) {\n protectedCallIds.add(msg.toolCallId);\n }\n }\n\n for (const id of directMessageIds) {\n const msg = messages.find((m) => m.id === id);\n if (!msg) continue;\n if (isMessageProtected(msg, config)) {\n removedIds.add(id);\n if (msg.toolCallId) protectedCallIds.add(msg.toolCallId);\n }\n }\n\n for (const id of directMessageIds) {\n if (removedIds.has(id)) continue;\n const msg = messages.find((m) => m.id === id);\n if (!msg) continue;\n if (\n msg.contentType === \"tool-result\" &&\n msg.toolCallId &&\n protectedCallIds.has(msg.toolCallId)\n ) {\n removedIds.add(id);\n }\n }\n\n return directMessageIds.filter((id) => !removedIds.has(id));\n}\n\nfunction resolveTargetTier(\n state: CompressionState,\n nestedBlockIds: string[],\n isBlockBoundary: boolean,\n): CompressionTier {\n if (!isBlockBoundary) return 1;\n if (nestedBlockIds.length === 0) return 1;\n let minTier: CompressionTier = 3;\n for (const id of nestedBlockIds) {\n const block = blockById(state, id);\n if (block && block.tier < minTier) minTier = block.tier;\n }\n return minTier;\n}\n\nfunction collectCoverage(state: CompressionState): Set<string> {\n const coverage = new Set<string>();\n for (const block of activeBlocks(state)) {\n for (const id of block.effectiveMessageIds) coverage.add(id);\n }\n return coverage;\n}\n\ninterface NudgeInput {\n tokenCount: number;\n config: Config;\n state: CompressionState;\n messages: CoreMessage[];\n recommendation?: Recommendation;\n countTokens: (t: string) => number;\n}\n\nfunction resolveAdaptiveGrowth(\n modelContextLimit: number,\n nudge: NudgeConfig,\n): number {\n if (!modelContextLimit || modelContextLimit <= 0) return nudge.growthFloor;\n return Math.min(\n nudge.growthCap,\n Math.max(\n nudge.growthFloor,\n Math.round(modelContextLimit * nudge.growthRatio),\n ),\n );\n}\n\n/** Compressible amount for each tier — all tiers use the SAME definition\n * (\"how much can be compressed at this tier\"), so they are handled by one\n * unified loop. T1 = compressible raw-message tokens (excludes protected /\n * already-covered); T2 = total summary tokens of all active tier-1 blocks;\n * T3 = total summary tokens of all active tier-2 blocks. The \"zero filter\"\n * for block tiers is simply that all blocks are compressible by default. */\nfunction pendingByTier(\n state: CompressionState,\n recommendation: Recommendation | undefined,\n countTokens: (t: string) => number,\n): Record<number, { pending: number; targetBlocks: CompressionBlock[] }> {\n const out: Record<number, { pending: number; targetBlocks: CompressionBlock[] }> = {};\n const compressible = recommendation?.contextRanges.compressible ?? [];\n out[1] = { pending: compressible.reduce((s, r) => s + r.tokens, 0), targetBlocks: [] };\n const active = activeBlocks(state);\n const t1 = active.filter((b) => b.tier === 1);\n const t2 = active.filter((b) => b.tier === 2);\n out[2] = { pending: t1.reduce((s, b) => s + countTokens(b.summary), 0), targetBlocks: t1 };\n out[3] = { pending: t2.reduce((s, b) => s + countTokens(b.summary), 0), targetBlocks: t2 };\n return out;\n}\n\nfunction decideNudge(input: NudgeInput): NudgeDecision {\n const { config, state, tokenCount, recommendation, countTokens } = input;\n const limit = config.modelContextLimit;\n const usage = limit > 0 ? tokenCount / limit : 0;\n\n const nudgeGrowthTokens = resolveAdaptiveGrowth(limit, config.nudge);\n\n const emergencyOverride = usage >= config.nudge.emergencyThresholdPct;\n\n const baseline = state.nudge.lastPerMessageNudgeTokens;\n const hadPendingNudge = state.nudge.lastNudgeShownTokens > 0;\n\n const hasPendingNudge = hadPendingNudge;\n const effectiveThreshold = hasPendingNudge\n ? Math.floor(nudgeGrowthTokens / 2)\n : nudgeGrowthTokens;\n\n const growthReference =\n state.nudge.lastNudgeShownTokens > 0\n ? state.nudge.lastNudgeShownTokens\n : baseline > 0\n ? baseline\n : tokenCount;\n\n const growthFloor = Math.max(\n config.nudge.minGrowthFloor,\n config.nudge.minGrowthRatio * nudgeGrowthTokens,\n );\n\n const growthSinceReference = tokenCount - growthReference;\n\n const rec = recommendation;\n const tiers = pendingByTier(state, rec, countTokens);\n\n // Unified injection arbitration, priority T1 > T2 > T3 (ascending). Each\n // tier has its OWN cadence (lastShownByTier) so firing one doesn't block\n // another across turns; within a turn we inject at most the FIRST eligible\n // tier and stop, which raises the shared baseline (lastNudgeShownTokens) so\n // lower-priority tiers see a higher reference and naturally defer.\n let injectedTier: CompressionTier | null = null;\n let injectedReason = \"\";\n // growth acts as the \"has accumulated since baseline\" signal; pending is the\n // \"there is enough compressible content\" signal. Both must hold for a\n // non-emergency injection. This keeps the first turn (growth 0) from firing\n // immediately even if a lot is compressible — it just establishes baseline.\n const growthReady = growthSinceReference >= growthFloor;\n if (!emergencyOverride && growthReady) {\n for (const tier of [1, 2, 3] as const) {\n if (!config.tiers.enabled && tier > 1) break;\n const info = tiers[tier];\n if (!info || info.pending < nudgeGrowthTokens) continue;\n const lastShown = state.nudge.lastShownByTier[tier] ?? 0;\n // Per-tier cadence: even with growth, a tier that fired recently waits\n // for its own cadence window. First time (lastShown===0) is always met.\n const cadenceMet = lastShown === 0 || tokenCount - lastShown >= growthFloor;\n if (!cadenceMet) continue;\n injectedTier = tier;\n injectedReason = tier === 1\n ? `T1 compressible ${info.pending} >= ${nudgeGrowthTokens}, growth ${growthSinceReference}, usage ${Math.round(usage * 100)}%`\n : `T${tier} distill ready: ${info.targetBlocks.length} tier-${tier - 1} blocks (${info.pending} tokens) >= ${nudgeGrowthTokens}, usage ${Math.round(usage * 100)}%`;\n break;\n }\n }\n\n const shouldInject = emergencyOverride || injectedTier !== null;\n\n let reason: string;\n if (emergencyOverride) {\n reason = `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}%`;\n } else if (injectedTier !== null) {\n reason = injectedReason;\n } else {\n const tiersList = [1, 2, 3] as const;\n const eligible = tiersList.filter((t) => config.tiers.enabled || t === 1);\n const ready = eligible\n .filter((t) => (tiers[t]?.pending ?? 0) >= nudgeGrowthTokens)\n .map((t) => `T${t} ${tiers[t]!.pending}`);\n const readyHint = ready.length > 0 ? `, ready: ${ready.join(\", \")}` : \"\";\n const blocked = eligible\n .filter((t) => (tiers[t]?.pending ?? 0) >= nudgeGrowthTokens && (state.nudge.lastShownByTier[t] ?? 0) > 0 && tokenCount - (state.nudge.lastShownByTier[t] ?? 0) < growthFloor)\n .map((t) => `T${t} (cadence)`);\n const blockedHint = blocked.length > 0 ? `, blocked: ${blocked.join(\", \")}` : \"\";\n const maxPending = Math.max(0, ...Object.values(tiers).map((t) => t.pending));\n reason = `max compressible ${maxPending} < threshold ${nudgeGrowthTokens}${readyHint}${blockedHint}, growth ${growthSinceReference} (floor ${growthFloor})`;\n }\n\n const ctxBreakdown = computeContextBreakdown(input.messages, tokenCount, growthSinceReference);\n\n return {\n shouldInject,\n reason,\n compressibleRanges: rec?.recommendedRanges ?? [],\n protectedRanges: rec?.contextRanges.protected ?? [],\n tierTargetBlocks: injectedTier ? tiers[injectedTier]!.targetBlocks : [],\n contextUsage: usage,\n tier: injectedTier,\n breakdown: {\n usage,\n growth: growthSinceReference,\n growthReference,\n effectiveThreshold,\n nudgeGrowthTokens,\n growthFloor,\n hasPendingNudge: hasPendingNudge ? 1 : 0,\n emergencyOverride: emergencyOverride ? 1 : 0,\n pendingT1: tiers[1]!.pending,\n pendingT2: tiers[2]!.pending,\n pendingT3: tiers[3]!.pending,\n },\n contextBreakdown: ctxBreakdown,\n };\n}\n\nfunction computeContextBreakdown(messages: CoreMessage[], total: number, growth: number): ContextBreakdown {\n let system = 0, tool = 0, summaries = 0, code = 0, text = 0;\n for (const msg of messages) {\n const tokens = Math.ceil((msg.text ?? \"\").length / 4);\n if (msg.text?.startsWith(\"[Compressed conversation section]\")) {\n summaries += tokens;\n } else if (msg.contentType === \"tool-call\" || msg.contentType === \"tool-result\") {\n tool += tokens;\n } else if (msg.role === \"system\") {\n system += tokens;\n } else if (msg.text?.includes(\"```\")) {\n code += tokens;\n } else {\n text += tokens;\n }\n }\n return { system, tool, summaries, code, text, total, growth };\n}\n\nfunction cloneState(state: CompressionState): CompressionState {\n return {\n blocks: state.blocks.map((block) => ({\n ...block,\n directMessageIds: [...block.directMessageIds],\n effectiveMessageIds: [...block.effectiveMessageIds],\n directBlockIds: [...block.directBlockIds],\n })),\n messageRefs: {\n byRaw: { ...state.messageRefs.byRaw },\n byRef: { ...state.messageRefs.byRef },\n },\n nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },\n stats: { ...state.stats },\n nextBlockId: state.nextBlockId,\n nextRunId: state.nextRunId,\n };\n}\n\nfunction scoreRelevance(block: CompressionBlock, terms: string[]): number {\n const topic = (block.topic ?? \"\").toLowerCase();\n const summary = block.summary.toLowerCase();\n let score = 0;\n for (const term of terms) {\n const topicHits = countOccurrences(topic, term);\n if (topicHits > 0) score += Math.min(topicHits * 0.15, 0.45);\n const summaryHits = countOccurrences(summary, term);\n if (summaryHits > 0) score += Math.min(summaryHits * 0.04, 0.2);\n }\n return Math.min(score, 1);\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (!haystack || !needle) return 0;\n let count = 0;\n let position = 0;\n while ((position = haystack.indexOf(needle, position)) !== -1) {\n count++;\n position += needle.length;\n }\n return count;\n}\n\nexport { createInitialState };\n","/**\n * Compression rule texts — VERBATIM copy from context-compress-algorithms (MIT, ours).\n * These were tuned over months of production use.\n *\n * DO NOT modify the wording — it is the result of extensive tuning.\n */\n\nexport const COMPRESS_PHILOSOPHY = `Compression Philosophy:\n- All compression serves the primary task, but be frugal.\n- Context capacity is precious. Save context by compressing consumed outputs, not by avoiding tools.\n- Compress by need, not by percentage.\n- Work from summaries, not raw tool outputs. All listed ranges (user prompts, tool outputs, code, logs, exploration, intermediate steps) should be compressed to summary format — the ONLY exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct.\n- Curate summaries like a well-structured document. User prompts, compressed tool outputs, code, logs, or skill-call intermediate results that are critically important should be preserved — not by exempting them from compression, but by embedding them in the summary via [[KEEP:mNNNNN]] (auto-expanded verbatim) and [[REF:mNNNNN|description]] (compact link).`;\n\nexport const HOW_TO_COMPRESS_RULES = `HOW TO COMPRESS\n\nWhen you call \\`compress\\`, the summary you write becomes the only record of the replaced conversation. Make it self-contained and complete: every user request, experiment purpose, and work task in the range must be accurately captured. A later reader (or you, after decompressing) should be able to continue the task WITHOUT needing the original.\n\nKEEP VERBATIM — never paraphrase or abbreviate these:\n- Full file paths with line numbers, directory prefix on every mention (\\`lib/hooks.ts:347\\`, \\`src/index.ts:12-18\\`, \\`gatenet_v3/model.py:45\\`). Never abbreviate to a bare filename (\\`hooks.ts\\`, \\`model.py\\`) — they are ambiguous and cannot be grepped or decompressed-to later.\n- Function, class, and type signatures (exact names, params, return types) AND critical code lines that encode logic — the line that IS the finding, not just the function name (e.g. \\`kv_keys += define_gate * a_key[i](emb)\\` is more useful than \"see model_kvnet.py\").\n- Error messages and stack traces (exact text — you need the literal string to grep for it later).\n- Key details from reports and analyses — not just the conclusion. Keep the comparison numbers and the mechanism, not \"X is worse\" alone (write \"1.76× PPL gap because KV store is static\", not \"KVNet underperforms\").\n- Decisions and their rationale (\"chose X over Y because Z\" — the \"because\" is load-bearing; without it the decision looks arbitrary).\n- Constraints discovered (\"must support Node 22\", \"no new dependencies\", \"AGENTS.md forbids \\`as any\\`\").\n- Exact values: versions, config keys, thresholds, magic numbers.\n- User intent — quote short user messages verbatim. When the message is too long to quote, preserve intent with extra care: do not change scope, constraints, priorities, acceptance criteria, or requested outcomes. Mark them clearly as past quotes (e.g., \"User said: ...\"), not as current directives. Losing these changes the task itself.\n- The user's overall goal and any changes to it — the big-picture objective plus how it evolved during the compressed range. Each summary must reflect the goal as it stood at the end of the range, including pivots (e.g., \"initially: fix bug X → pivoted to: refactor module Y after discovering root cause\"). Losing the goal or its evolution makes all subsequent work appear unmotivated.\n- Purpose behind each significant action — preserve not just what was done but why: the hypothesis behind each experiment, the question behind each exploration, the task goal behind each work action. Without purpose, the summary reads as disconnected technical steps with no through-line.\n- Open questions and unresolved TODOs — losing these changes what work appears to remain.\n- Message refs of key anchors (\\`m00420\\`, \\`m00510–m00520\\`) — they let you or a later reader jump back via decompress to the exact original.\n\nDROP — extract the signal, discard the vessel:\n- Verbose logs (build/test/\\`npm\\` output) once you have captured the error line or the result.\n- Duplicate file reads once the needed content is recorded.\n- Consumed exploration — search hits, agent return values, successful tool outputs — once you have extracted the facts you need (same rule as dead-ends, but nothing went wrong; the content is simply spent).\n- Dead-end exploration — but PRESERVE the lesson in one line: \"tried X, failed because Y\".\n- Back-and-forth discussion and self-corrections once the final position is captured (keep the outcome, drop the journey to it).\n- Repeated status checks (\\`git status\\`, \\`ls\\`) once state is known.\n\nFor each significant item you DROP (scripts, reports, large analyses, long tool outputs), add a one-line CONTENT description of what it covers — not where it lives. Bad: \"probe script at /path/probe_kvnet.py\". Good: \"probe_kvnet.py: tests n-gram baseline, generation quality, long-range dependency, position sensitivity, op pipeline, QUERY attention.\" This lets a later decompress target the right block by relevance, not by guessing locations.\n\nKEEP MARKERS: \\`[[KEEP:mNNNNN]]\\` expands original message content into the summary (truncated to a max length). Do NOT use KEEP for verbose command output, diagnostic scripts, log dumps, or any content whose value is in the conclusion rather than the raw output — summarize these or use \\`[[REF:mNNNNN|desc]\\` instead.\n\nPRIORITY — when the summary must be compact, preserve in this order:\n1. User's overall goal, goal evolution, intent, and hard constraints (losing these changes the task).\n2. Decisions and rationale.\n3. Exact technical artifacts: paths, signatures, errors, values.\n4. Conclusions and key findings.\n5. Lessons learned: what failed and why.\n\nWrite dense, scannable bullets — not narrative prose. If the range spans distinct concerns (request → findings → decision), group bullets under short thematic headers so a reader can scan to the part they need. Every line must earn its place. Do not mimic the style of existing summaries in context; follow these rules.`;\n\nexport const TIER2_DISTILL_RULES = `TIER 2 COMPRESSION — DISTILLATION\n\nYou are compressing historical summaries (not raw conversation). These summaries have already captured the details. Your job is to DISTILL them: extract only what matters for future work, discard the process.\n\nKEEP — these are the only things that survive distillation:\n- Decisions and their rationale (\"chose X over Y because Z\" — the \"because\" is load-bearing).\n- Final outcomes: version numbers shipped, PR numbers merged/closed, bugs fixed or deferred.\n- Key lessons: what failed and why (\"tried X, failed because Y\"). These prevent repeating mistakes.\n- Critical constraints discovered (\"must support Node 22\", \"AGENTS.md forbids as any\").\n- Design decisions with architectural impact (\"chose compress-as-anchor over synthetic messages because prefix cache\").\n- Whether content is OBSOLETE or SUPERSEDED — mark with one line: \"[SUPERSEDED by PR #NNN]\" or \"[OBSOLETE: deleted in vX.Y.Z]\". Do NOT keep the obsolete content's details — just the marker and reason.\n- Function/class/type names and module paths that are the SUBJECT of the work — e.g., \"fixed filterCompressedRanges in prune.ts\", \"added SessionStateRegistry in state.ts\". Not exact line numbers or full signatures — just enough to LOCATE the code without searching.\n- Exploration findings: if a block was exploratory with no decision, keep the CONCLUSION in one line (\"explored X, not viable because Y\"). Do not keep the exploration process.\n\nDROP — these were useful during the work but are no longer needed:\n- Exact line numbers, diffs, verbose function signatures, full code listings.\n- Build/deploy process details, test execution steps.\n- Review process details (who reviewed, what rounds, test counts).\n- Verbose logs, command output, intermediate debugging steps.\n\nFORMAT:\n- Start each distilled block with a source header line:\n \\`Source: bN+bM+... (XK→YK tok, Zx). [original topic]\\`\n Example: \\`Source: b5+b7 (56K+44K→268 tok, 375x). [Tool-result recap + publish]\\`\n- 3-5 bullet points per source block, each a self-contained fact.\n- Dense, scannable — no narrative prose.\n- Start with the outcome, not the process: \"v1.13.0 shipped (7 PRs bundled)\" not \"implemented 7 PRs then reviewed then merged\".\n- Cross-block synthesis: if multiple source blocks cover the same topic (same PR, same feature, same bug), MERGE them into a single group of bullets. Do not repeat the same fact from different blocks — keep it once under the most relevant source header.\n\nSIZE TARGET: 50-150 tokens per source block (excluding the header). If you can't fit it in 150 tokens, you're keeping too much process. If a block has nothing worth keeping (pure noise), output just the header followed by \"[no actionable content].\"`;\n\nexport const TIER3_CONDENSE_RULES = `TIER 3 COMPRESSION — ULTRA-CONDENSATION\n\nYou are compressing distilled summaries (Tier 2) into ultra-condensed facts (Tier 3). The distilled summaries already contain only decisions and outcomes. Your job is to reduce them to bare factual references.\n\nPRIORITY — when a source block has more facts than the size target allows, keep in this order:\n1. Shipped outcomes (versions released, PRs merged) — these are permanent record.\n2. Open work (PRs/issues still pending) — these may need follow-up.\n3. Key decisions with architectural impact (\"chose X over Y because Z\").\n4. Critical constraints (\"must support Node 22\").\nDrop everything else. Tier 3 is a lookup index, not a knowledge base.\n\nFORMAT:\n- Start with a source header line:\n \\`Source: bN+bM+... (XK→YK tok, Zx). [original topic]\\`\n- Output 1-3 facts per source block. Each fact is a single line: subject + outcome.\n- No explanations, no rationale, no process — just the fact.\n- Format: \"[PR/Issue/Version] — [outcome in ≤8 words]\"\n- Merge related facts from different source blocks if they concern the same topic.\n\nEXAMPLES:\n- \"v1.13.0 shipped — quality gate + GC fix (7 PRs)\"\n- \"PR #196 merged — preserve-first-user (supersedes #169)\"\n- \"Bug 1214 fixed — compress consumed all user messages\"\n- \"Chose compress-as-anchor — prefix cache benefit over synthetic injection\"\n- \"Constraint: AGENTS.md forbids as any — never suppress types\"\n\nDROP:\n- Multi-sentence context. If a fact needs >1 sentence, it's too detailed for Tier 3.\n- Lessons learned (\"tried X, failed because Y\") — drop UNLESS the failure is likely to recur and the block is <30 days old.\n- Design rationale details — keep the decision, drop the \"because\" unless it's a critical constraint.\n- Anything marked [OBSOLETE] or [SUPERSEDED] — drop entirely, note \"[N blocks obsolete]\" in the summary.\n\nSIZE TARGET: 30-60 tokens per source block (including header). For a batch of N source blocks, total output ≈ N × 40 tokens. If a source block has only one trivial fact, output just the header + one line.`;\n","import type { NudgeDecision, CompressibleRange, ProtectedRange, ContextBreakdown, CompressionBlock } from \"./types.js\";\nimport { COMPRESS_PHILOSOPHY, HOW_TO_COMPRESS_RULES, TIER2_DISTILL_RULES, TIER3_CONDENSE_RULES } from \"./compression-rules.js\";\n\nexport type NudgeVoice = \"gentle\" | \"emergency\";\n\nexport interface RenderedNudge {\n voice: NudgeVoice;\n text: string;\n}\n\nconst EFFICIENCY_NOTE = `This is an efficiency nudge to compress early and keep context lean — not an overflow warning. A separate, stronger alert will appear if the context is actually full.\\n\\n${COMPRESS_PHILOSOPHY}`;\n\nconst EMERGENCY_HEADER = `⚠️ Context limit reached — compress now. Prioritize consumed tool outputs.\\n\\n${COMPRESS_PHILOSOPHY}`;\n\nfunction formatK(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;\n return `${n}`;\n}\n\nfunction formatBreakdown(bd?: ContextBreakdown): string {\n if (!bd) return \"\";\n const parts: string[] = [];\n if (bd.system > 0) parts.push(`${formatK(bd.system)} system`);\n if (bd.tool > 0) parts.push(`${formatK(bd.tool)} tool`);\n if (bd.summaries > 0) parts.push(`${formatK(bd.summaries)} summaries`);\n if (bd.code > 0) parts.push(`${formatK(bd.code)} code`);\n if (bd.text > 0) parts.push(`${formatK(bd.text)} text`);\n const growth = bd.growth > 0 ? `\\n+${formatK(bd.growth)} since last nudge` : \"\";\n return `Context breakdown: ${parts.join(\" | \")}${growth}`;\n}\n\nfunction refToNum(ref: string | undefined): number {\n if (!ref) return 0;\n const m = ref.match(/^m0*(\\d+)$/);\n return m && m[1] ? parseInt(m[1], 10) : 0;\n}\n\ninterface MergedEntry {\n startRef: string;\n endRef: string;\n startNum: number;\n endNum: number;\n count: number;\n tokens: number;\n compressibleTokens: number;\n compressibleCount: number;\n protectedTokens: number;\n protectedCount: number;\n protectedTools: string[];\n toolPct: number;\n textPct: number;\n dangerous: boolean;\n}\n\nfunction mergeRanges(compressible: CompressibleRange[], protected_: ProtectedRange[]): MergedEntry[] {\n const entries: MergedEntry[] = [];\n\n for (const r of compressible) {\n const sNum = refToNum(r.startRef);\n const eNum = refToNum(r.endRef);\n entries.push({\n startRef: r.startRef, endRef: r.endRef, startNum: sNum, endNum: eNum,\n count: r.count, tokens: r.tokens,\n compressibleTokens: r.tokens, compressibleCount: r.count,\n protectedTokens: 0, protectedCount: 0, protectedTools: [],\n toolPct: r.toolPct, textPct: r.textPct, dangerous: r.dangerous ?? false,\n });\n }\n\n for (const r of protected_) {\n const sNum = refToNum(r.startRef);\n const eNum = refToNum(r.endRef);\n entries.push({\n startRef: r.startRef, endRef: r.endRef, startNum: sNum, endNum: eNum,\n count: r.count, tokens: r.tokens,\n compressibleTokens: 0, compressibleCount: 0,\n protectedTokens: r.tokens, protectedCount: r.count, protectedTools: [...r.tools],\n toolPct: 0, textPct: 0, dangerous: false,\n });\n }\n\n entries.sort((a, b) => a.startNum - b.startNum);\n\n const merged: MergedEntry[] = [];\n for (const e of entries) {\n const last = merged[merged.length - 1];\n if (last && last.endNum + 1 >= e.startNum) {\n last.endRef = e.endRef;\n last.endNum = Math.max(last.endNum, e.endNum);\n last.count += e.count;\n last.tokens += e.tokens;\n last.compressibleTokens += e.compressibleTokens;\n last.compressibleCount += e.compressibleCount;\n last.protectedTokens += e.protectedTokens;\n last.protectedCount += e.protectedCount;\n if (e.dangerous) last.dangerous = true;\n for (const t of e.protectedTools) {\n if (!last.protectedTools.includes(t)) last.protectedTools.push(t);\n }\n } else {\n merged.push({ ...e });\n }\n }\n\n return merged;\n}\n\nfunction formatTierTargetBlocks(blocks: CompressionBlock[]): string {\n if (blocks.length === 0) {\n return \"Target blocks: (none — no tier blocks found)\";\n }\n const lines = blocks.map((b) => {\n const summaryTokens = Math.ceil((b.summary ?? \"\").length / 4);\n const topic = b.topic ? ` \"${b.topic}\"` : \"\";\n return ` ${b.blockId} ${b.effectiveMessageIds.length} msgs ${formatK(b.compressedTokens)}→${formatK(summaryTokens)}${topic}`;\n });\n return `Target ${blocks[0]!.tier === 1 ? \"tier-1\" : \"tier-2\"} blocks to distill (${blocks.length}):\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatRanges(compressible: CompressibleRange[], protected_: ProtectedRange[]): string {\n const merged = mergeRanges(compressible, protected_);\n if (merged.length === 0) {\n return \"[No specific ranges detected — compress any consumed content.]\";\n }\n\n const lines = merged.slice(0, 10).map((e) => {\n const suffix = e.dangerous && e.compressibleTokens > 0\n ? \" ⚠️ NOT recommended unless you are certain.\"\n : \"\";\n\n if (e.protectedTokens > 0 && e.compressibleTokens === 0) {\n return ` ${e.startRef}–${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [PROTECTED: ${e.protectedTools.join(\", \")} — not compressible]${suffix}`;\n }\n\n if (e.protectedTokens > 0 && e.compressibleTokens > 0) {\n return ` ${e.startRef}–${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [${formatK(e.compressibleTokens)} compressible | ${formatK(e.protectedTokens)} protected: ${e.protectedTools.join(\", \")}]${suffix}`;\n }\n\n return ` ${e.startRef}–${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [tool ${e.toolPct}% | text ${e.textPct}%]${suffix}`;\n });\n\n return `Compressible ranges (oldest first):\\n${lines.join(\"\\n\")}`;\n}\n\nexport function renderNudgeText(decision: NudgeDecision): RenderedNudge {\n const breakdownStr = formatBreakdown(decision.contextBreakdown);\n const rangesStr = formatRanges(decision.compressibleRanges, decision.protectedRanges ?? []);\n\n if (decision.tier !== null && decision.tier >= 2) {\n const isT2 = decision.tier === 2;\n const targets = decision.tierTargetBlocks ?? [];\n const blockList = formatTierTargetBlocks(targets);\n const startId = targets[0]?.blockId ?? \"b1\";\n const endId = targets[targets.length - 1]?.blockId ?? \"b5\";\n return {\n voice: \"gentle\",\n text: [\n EFFICIENCY_NOTE,\n \"\",\n breakdownStr,\n \"\",\n `[TIER ${decision.tier} ${isT2 ? \"DISTILLATION\" : \"CONDENSATION\"} TRIGGER]`,\n isT2\n ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries.`\n : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries.`,\n blockList,\n `Example: compress({ content: [{ startId: \"${startId}\", endId: \"${endId}\", summary: \"...\" }] })`,\n \"\",\n HOW_TO_COMPRESS_RULES,\n \"\",\n isT2 ? TIER2_DISTILL_RULES : TIER3_CONDENSE_RULES,\n ].join(\"\\n\"),\n };\n }\n\n const isEmergency = !!decision.breakdown?.emergencyOverride;\n\n if (isEmergency) {\n return {\n voice: \"emergency\",\n text: [\n EMERGENCY_HEADER,\n \"\",\n breakdownStr,\n \"\",\n HOW_TO_COMPRESS_RULES,\n \"\",\n `{ \"topic\": \"...\", \"content\": [{ \"startId\": \"<ID>\", \"endId\": \"<ID>\", \"summary\": \"...\" }] }`,\n \"Only use IDs from visible messages above. Compress older work first.\",\n \"\",\n rangesStr,\n ].join(\"\\n\"),\n };\n }\n\n return {\n voice: \"gentle\",\n text: [\n EFFICIENCY_NOTE,\n \"\",\n breakdownStr,\n \"\",\n HOW_TO_COMPRESS_RULES,\n \"\",\n rangesStr,\n \"\",\n `💡 Compress all ranges in one call (pass multiple content entries: \\`content: [{...}, {...}]\\`).`,\n ].join(\"\\n\"),\n };\n}\n","import { refForRaw } from \"./refs.js\";\nimport type { CompressionState, CoreMessage } from \"./types.js\";\n\nconst KEEP_REGEX = /\\[\\[KEEP:(m\\d+)\\]\\]/g;\nconst REF_REGEX = /\\[\\[REF:(m\\d+)\\|([^\\]]+)\\]\\]/g;\n\nexport interface KeepMarkerResult {\n summary: string;\n expandedCount: number;\n refCount: number;\n unresolvedRefs: string[];\n}\n\nexport function resolveKeepMarkers(\n summary: string,\n messages: CoreMessage[],\n state: CompressionState,\n maxChars = 2000,\n): KeepMarkerResult {\n const messageByRef = new Map<string, CoreMessage>();\n for (const message of messages) {\n const ref = refForRaw(state.messageRefs, message.id);\n if (ref) messageByRef.set(ref, message);\n }\n\n let expandedCount = 0;\n let refCount = 0;\n const unresolvedRefs: string[] = [];\n\n const expanded = summary\n .replace(KEEP_REGEX, (match, ref: string) => {\n const normalized = normalizeRef(ref);\n const message = normalized ? messageByRef.get(normalized) : undefined;\n if (!message) {\n unresolvedRefs.push(ref);\n return match;\n }\n expandedCount++;\n return formatKeptMessage(message, normalized!, maxChars);\n })\n .replace(REF_REGEX, (_match, ref: string, desc: string) => {\n const normalized = normalizeRef(ref);\n const message = normalized ? messageByRef.get(normalized) : undefined;\n if (!message) {\n unresolvedRefs.push(ref);\n return _match;\n }\n refCount++;\n return `[→ ${normalized}: ${desc.trim()}]`;\n });\n\n return { summary: expanded, expandedCount, refCount, unresolvedRefs };\n}\n\nfunction normalizeRef(ref: string): string | null {\n const match = /^m0*(\\d{1,5})$/.exec(ref.trim().toLowerCase());\n if (!match || match[1] === undefined) return null;\n return `m${match[1].padStart(5, \"0\")}`;\n}\n\nfunction formatKeptMessage(message: CoreMessage, ref: string, maxChars: number): string {\n const label = labelFor(message);\n const body = truncate(message.text ?? \"[empty message]\", maxChars);\n return `\\n--- [${ref}: ${label}] ---\\n${body}\\n--- end ---\\n`;\n}\n\nfunction labelFor(message: CoreMessage): string {\n if (message.contentType === \"tool-call\" || message.contentType === \"tool-result\") {\n return message.toolName ?? \"tool\";\n }\n return message.role;\n}\n\nfunction truncate(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars) + `\\n... [truncated, ${text.length} chars total]`;\n}\n","import type { CompressionBlock, CompressionState, CoreMessage } from \"./types.js\";\n\nexport function parseBlockIdArg(arg: string): string | null {\n const normalized = arg.trim().toLowerCase();\n const refMatch = /^b0*(\\d+)$/.exec(normalized);\n if (refMatch && refMatch[1] !== undefined) return `b${refMatch[1]}`;\n const numMatch = /^(\\d+)$/.exec(normalized);\n if (numMatch && numMatch[1] !== undefined) return `b${numMatch[1]}`;\n return null;\n}\n\nexport function findBlocksOverlappingMessages(\n state: CompressionState,\n messageIds: Set<string>,\n): CompressionBlock[] {\n if (messageIds.size === 0) return [];\n const matched: CompressionBlock[] = [];\n for (const block of state.blocks) {\n if (!block.active) continue;\n if (block.effectiveMessageIds.some((id) => messageIds.has(id))) {\n matched.push(block);\n }\n }\n return matched.sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));\n}\n\nexport function findActiveAncestor(state: CompressionState, blockId: string): string | null {\n const start = state.blocks.find((b) => b.blockId === blockId);\n if (!start) return null;\n const queue: string[] = [...start.directBlockIds];\n const visited = new Set<string>();\n while (queue.length > 0) {\n const currentId = queue.shift()!;\n if (visited.has(currentId)) continue;\n visited.add(currentId);\n const current = state.blocks.find((b) => b.blockId === currentId);\n if (!current) continue;\n if (current.active) return current.blockId;\n for (const ancestorId of current.directBlockIds) {\n if (!visited.has(ancestorId)) queue.push(ancestorId);\n }\n }\n return null;\n}\n\nexport interface DeactivateOptions {\n deep?: boolean;\n}\n\nexport function deactivateBlock(\n state: CompressionState,\n blockIds: string[],\n options: DeactivateOptions = {},\n): CompressionState {\n const targets = new Set(blockIds);\n\n const updated = state.blocks.map((block) => {\n if (!targets.has(block.blockId) || !block.active) return block;\n return {\n ...block,\n active: false,\n durationMs: block.durationMs,\n createdAt: block.createdAt,\n };\n });\n\n let final = updated;\n if (options.deep) {\n const visited = new Set<string>();\n const queue: string[] = [];\n for (const id of blockIds) {\n const block = updated.find((b) => b.blockId === id);\n if (block) queue.push(...block.directBlockIds);\n }\n while (queue.length > 0) {\n const id = queue.shift()!;\n if (visited.has(id)) continue;\n visited.add(id);\n final = final.map((block) => {\n if (block.blockId !== id) return block;\n queue.push(...block.directBlockIds);\n return block.active ? { ...block, active: false } : block;\n });\n }\n }\n\n return { ...state, blocks: final };\n}\n\nexport interface RestoredPreviewResult {\n preview: string;\n restoredCount: number;\n}\n\nexport function buildRestoredContentPreview(\n messages: CoreMessage[],\n beforeActiveMessageIds: Set<string>,\n state: CompressionState,\n): RestoredPreviewResult {\n const restored: CoreMessage[] = [];\n for (const message of messages) {\n if (!beforeActiveMessageIds.has(message.id)) continue;\n const stillCovered = state.blocks.some(\n (b) => b.active && b.effectiveMessageIds.includes(message.id),\n );\n if (!stillCovered) restored.push(message);\n }\n\n if (restored.length === 0) return { preview: \"\", restoredCount: 0 };\n\n const lines: string[] = [];\n let totalLength = 0;\n const MAX_PREVIEW = 2000;\n const MAX_PER_MESSAGE = 200;\n\n for (const message of restored) {\n if (totalLength >= MAX_PREVIEW) break;\n const text = message.text ?? \"\";\n const truncated = text.length > MAX_PER_MESSAGE ? text.slice(0, MAX_PER_MESSAGE) + \"...\" : text;\n const label =\n message.toolName && message.contentType !== \"text\"\n ? `${message.toolName}: ${truncated}`\n : `[${message.role}] ${truncated}`;\n lines.push(label);\n totalLength += label.length + 1;\n }\n\n return { preview: lines.join(\"\\n\"), restoredCount: restored.length };\n}\n\nfunction numericPart(blockId: string): number {\n const match = /^b(\\d+)$/.exec(blockId);\n return match && match[1] !== undefined ? Number(match[1]) : 0;\n}\n","import { refForRaw } from \"./refs.js\";\nimport type { CompressionBlock, CompressionState, CoreMessage } from \"./types.js\";\n\nfunction formatTokens(n: number): string {\n if (!Number.isFinite(n) || n <= 0) return \"0\";\n return n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);\n}\n\nfunction pct(n: number, total: number): number {\n if (n <= 0 || total <= 0) return 0;\n return Math.max(1, Math.round((n / total) * 100));\n}\n\nfunction numericPart(blockId: string): number {\n const match = /^b(\\d+)$/.exec(blockId);\n return match && match[1] !== undefined ? Number(match[1]) : 0;\n}\n\nfunction summaryTokensOf(block: CompressionBlock, countTokens: (t: string) => number): number {\n return countTokens(block.summary);\n}\n\nfunction effectiveCompressedTokens(\n block: CompressionBlock,\n state: CompressionState,\n countTokens: (t: string) => number,\n visited: Set<string> = new Set(),\n): number {\n if (visited.has(block.blockId)) return 0;\n visited.add(block.blockId);\n let total = block.compressedTokens;\n for (const nestedId of block.directBlockIds) {\n const nested = state.blocks.find((b) => b.blockId === nestedId);\n if (nested) total += effectiveCompressedTokens(nested, state, countTokens, visited);\n }\n return total;\n}\n\nfunction tierLabel(block: CompressionBlock): string {\n return `T${block.tier}`;\n}\n\nfunction tierBreakdown(\n blocks: CompressionBlock[],\n countTokens: (t: string) => number,\n): string | null {\n const tierTokens: Record<number, number> = {};\n for (const block of blocks) {\n tierTokens[block.tier] = (tierTokens[block.tier] ?? 0) + summaryTokensOf(block, countTokens);\n }\n const tiers = Object.keys(tierTokens).map(Number);\n if (tiers.length <= 1) return null;\n const parts: string[] = [];\n for (const tier of [1, 2, 3]) {\n if (tierTokens[tier]) parts.push(`T${tier}: ${formatTokens(tierTokens[tier])}`);\n }\n return parts.join(\" | \");\n}\n\ninterface VisibleMessageInfo {\n ref: string;\n tokens: number;\n tool: string;\n index: number;\n}\n\nfunction collectVisible(\n messages: CoreMessage[],\n state: CompressionState,\n countTokens: (t: string) => number,\n): { visible: VisibleMessageInfo[]; summaryTokens: number } {\n const coveredIds = new Set<string>();\n for (const block of state.blocks) {\n if (!block.active) continue;\n for (const id of block.effectiveMessageIds) coveredIds.add(id);\n }\n let summaryTokens = 0;\n for (const block of state.blocks) {\n if (block.active) summaryTokens += summaryTokensOf(block, countTokens);\n }\n const visible: VisibleMessageInfo[] = [];\n messages.forEach((message, index) => {\n if (coveredIds.has(message.id)) return;\n const ref = refForRaw(state.messageRefs, message.id);\n if (!ref) return;\n const tokens = countTokens(message.text ?? \"\");\n const tool = message.toolName ?? \"text\";\n if (tokens > 0) visible.push({ ref, tokens, tool, index });\n });\n return { visible, summaryTokens };\n}\n\nexport interface StatusReportOptions {\n scope?: \"compressed\" | \"uncompressed\";\n view?: \"ranges\" | \"messages\";\n tool?: string;\n sort?: \"size\" | \"time\" | \"tool\" | \"age\";\n limit?: number;\n}\n\nexport function buildStatusReport(\n state: CompressionState,\n messages: CoreMessage[],\n countTokens: (t: string) => number,\n options: StatusReportOptions = {},\n): string {\n const scope = options.scope;\n const view = options.view ?? \"ranges\";\n const toolFilter = options.tool;\n const sort = options.sort ?? \"size\";\n const limit = options.limit ?? 30;\n\n const activeBlocks = state.blocks\n .filter((b) => b.active)\n .sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));\n\n if (scope === \"compressed\") {\n return renderCompressedDrilldown(activeBlocks, state, sort, limit, countTokens);\n }\n\n const { visible, summaryTokens } = collectVisible(messages, state, countTokens);\n\n if (scope === \"uncompressed\") {\n if (view === \"messages\") {\n return renderMessageDrilldown(visible, toolFilter, sort, limit);\n }\n return renderUncompressedRanges(visible);\n }\n\n return renderOverview(visible, summaryTokens, activeBlocks, state, countTokens, limit);\n}\n\nfunction renderOverview(\n visible: VisibleMessageInfo[],\n summaryTokens: number,\n blocks: CompressionBlock[],\n state: CompressionState,\n countTokens: (t: string) => number,\n limit: number,\n): string {\n const lines: string[] = [];\n const toolTypeMap = new Map<string, number>();\n for (const message of visible) {\n toolTypeMap.set(message.tool, (toolTypeMap.get(message.tool) ?? 0) + message.tokens);\n }\n const topTool = [...toolTypeMap.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];\n\n const totalTool = visible\n .filter((m) => m.tool !== \"text\")\n .reduce((sum, m) => sum + m.tokens, 0);\n const totalText = visible\n .filter((m) => m.tool === \"text\")\n .reduce((sum, m) => sum + m.tokens, 0);\n const total = summaryTokens + totalTool + totalText;\n\n lines.push(\"CONTEXT BREAKDOWN\");\n lines.push(\n ` ${formatTokens(totalTool)} tool (${pct(totalTool, total)}%) | ${formatTokens(totalText)} text (${pct(totalText, total)}%) | ${formatTokens(summaryTokens)} summaries (${pct(summaryTokens, total)}%)`,\n );\n const topTypes = [...toolTypeMap.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3);\n if (topTypes.length > 0) {\n lines.push(` Top tools: ${topTypes.map(([t, n]) => `${t} (${pct(n, total)}%)`).join(\", \")}`);\n }\n\n lines.push(\"\");\n if (blocks.length === 0) {\n lines.push(\"COMPRESSED BLOCKS\");\n lines.push(\" No compressed blocks.\");\n } else {\n const totalSummary = blocks.reduce((s, b) => s + summaryTokensOf(b, countTokens), 0);\n const totalEffective = blocks.reduce(\n (s, b) => s + effectiveCompressedTokens(b, state, countTokens),\n 0,\n );\n lines.push(\n `COMPRESSED BLOCKS — ${blocks.length} active (${formatTokens(totalSummary)} summary, ${formatTokens(totalEffective)} original)`,\n );\n const breakdown = tierBreakdown(blocks, countTokens);\n if (breakdown) lines.push(` Tier usage: ${breakdown}`);\n lines.push(\"\");\n const sorted = [...blocks].sort(\n (a, b) =>\n effectiveCompressedTokens(b, state, countTokens) -\n effectiveCompressedTokens(a, state, countTokens) ||\n b.createdAt - a.createdAt,\n );\n for (const block of sorted.slice(0, limit)) {\n const topic = block.topic ?? \"(no topic)\";\n const eff = effectiveCompressedTokens(block, state, countTokens);\n lines.push(\n ` ${block.blockId} (${tierLabel(block)}) ${formatTokens(eff)}→${formatTokens(summaryTokensOf(block, countTokens))} ${block.effectiveMessageIds.length} msgs \"${topic}\"`,\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\n `Tip: buildStatusReport({scope:\"uncompressed\", view:\"messages\", tool:\"${topTool ?? \"bash\"}\"}) for per-message listing`,\n );\n return lines.join(\"\\n\");\n}\n\nfunction renderUncompressedRanges(visible: VisibleMessageInfo[]): string {\n const lines: string[] = [];\n const totalTokens = visible.reduce((s, m) => s + m.tokens, 0);\n lines.push(`UNCOMPRESSED — ${formatTokens(totalTokens)} | ${visible.length} visible messages`);\n lines.push(\"\");\n if (visible.length === 0) {\n lines.push(\" (no uncompressed messages)\");\n return lines.join(\"\\n\");\n }\n // Merge consecutive messages into ranges (by numeric ref), aggregating\n // token counts and dominant tool so the view reads as blocks, not a\n // per-message firehose — mirroring the Compressible Ranges output.\n interface Merged { startRef: string; endRef: string; startNum: number; count: number; tokens: number; tool: string; }\n const refNum = (ref: string): number => {\n const m = ref.match(/\\d+/);\n return m ? parseInt(m[0], 10) : 0;\n };\n const merged: Merged[] = [];\n for (const m of visible) {\n const num = refNum(m.ref);\n const last = merged[merged.length - 1];\n if (last && num === last.startNum + last.count) {\n last.endRef = m.ref;\n last.count += 1;\n last.tokens += m.tokens;\n } else {\n merged.push({ startRef: m.ref, endRef: m.ref, startNum: num, count: 1, tokens: m.tokens, tool: m.tool });\n }\n }\n for (const r of merged.slice(0, 30)) {\n const range = r.count === 1 ? r.startRef : `${r.startRef}–${r.endRef}`;\n lines.push(` ${range} (${r.count} msgs, ${formatTokens(r.tokens)}${r.count > 1 ? ` (${Math.round(r.tokens / r.count)}/msg)` : \"\"}) ${r.tool}`);\n }\n if (merged.length > 30) {\n lines.push(` ... and ${merged.length - 30} more ranges`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderMessageDrilldown(\n visible: VisibleMessageInfo[],\n toolFilter: string | undefined,\n sort: string,\n limit: number,\n): string {\n let filtered = visible;\n if (toolFilter) filtered = filtered.filter((m) => m.tool === toolFilter);\n\n if (sort === \"time\") filtered.sort((a, b) => a.index - b.index);\n else if (sort === \"tool\") filtered.sort((a, b) => a.tool.localeCompare(b.tool) || b.tokens - a.tokens);\n else filtered.sort((a, b) => b.tokens - a.tokens);\n\n const totalTokens = filtered.reduce((s, m) => s + m.tokens, 0);\n const allTokens = visible.reduce((s, m) => s + m.tokens, 0);\n const header = toolFilter\n ? `UNCOMPRESSED — ${toolFilter}: ${formatTokens(totalTokens)} | ${filtered.length} msgs | ${pct(totalTokens, allTokens)}% of visible`\n : `UNCOMPRESSED — ${formatTokens(totalTokens)} | ${filtered.length} msgs`;\n const lines = [header, `Sorted by ${sort}`, \"\"];\n const shown = filtered.slice(0, limit);\n for (const message of shown) {\n lines.push(` ${message.ref} (${formatTokens(message.tokens)}) ${message.tool}`);\n }\n if (filtered.length > shown.length) {\n lines.push(\"\");\n lines.push(`${shown.length} of ${filtered.length} shown.`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderCompressedDrilldown(\n blocks: CompressionBlock[],\n state: CompressionState,\n sort: string,\n limit: number,\n countTokens: (t: string) => number,\n): string {\n let sorted = [...blocks];\n if (sort === \"time\") sorted.sort((a, b) => a.createdAt - b.createdAt);\n else if (sort === \"age\") sorted.sort((a, b) => b.survivedCount - a.survivedCount);\n else\n sorted.sort(\n (a, b) =>\n effectiveCompressedTokens(b, state, countTokens) -\n effectiveCompressedTokens(a, state, countTokens) ||\n b.createdAt - a.createdAt,\n );\n\n const totalSummary = sorted.reduce((s, b) => s + summaryTokensOf(b, countTokens), 0);\n const totalEffective = sorted.reduce(\n (s, b) => s + effectiveCompressedTokens(b, state, countTokens),\n 0,\n );\n const lines = [\n `COMPRESSED — ${sorted.length} blocks | ${formatTokens(totalEffective)} original → ${formatTokens(totalSummary)} summary`,\n ];\n const breakdown = tierBreakdown(sorted, countTokens);\n if (breakdown) lines.push(`Tier usage: ${breakdown}`);\n lines.push(\"\");\n const shown = sorted.slice(0, limit);\n for (const block of shown) {\n const nested = block.directBlockIds.length > 0 ? ` nested=[${block.directBlockIds.join(\",\")}]` : \"\";\n const topic = block.topic ?? \"(no topic)\";\n const eff = effectiveCompressedTokens(block, state, countTokens);\n lines.push(\n ` ${block.blockId} (${tierLabel(block)}) ${formatTokens(eff)}→${formatTokens(summaryTokensOf(block, countTokens))} ${block.effectiveMessageIds.length} msgs age=${block.survivedCount} ${block.generation}${nested}`,\n );\n lines.push(` \"${topic}\"`);\n }\n if (sorted.length > shown.length) {\n lines.push(\"\");\n lines.push(`${shown.length} of ${sorted.length} shown.`);\n }\n return lines.join(\"\\n\");\n}\n\nexport function buildRecap(\n state: CompressionState,\n blockId?: string,\n): string {\n const activeBlocks = state.blocks\n .filter((b) => b.active)\n .sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));\n\n if (blockId !== undefined) {\n const block = state.blocks.find((b) => b.blockId === blockId);\n if (!block) {\n const activeList = activeBlocks.map((b) => b.blockId).join(\", \");\n return `Block ${blockId} not found. Active blocks: ${activeList}`;\n }\n if (!block.active) {\n return `Block ${blockId} is inactive (deactivated by nested compression).`;\n }\n const range = `${block.effectiveMessageIds.length} messages`;\n return `[Compressed conversation section]\\n${block.summary}\\n\\n[${blockId} | ${range} | topic: \"${block.topic ?? \"(none)\"}\"]`;\n }\n\n if (activeBlocks.length === 0) return \"No active compression blocks.\";\n\n const lines = [`Active compression blocks (${activeBlocks.length}):`];\n for (const block of activeBlocks) {\n const range = `${block.effectiveMessageIds.length} messages`;\n const preview = block.summary.slice(0, 200);\n lines.push(`\\n${block.blockId} | ${range} | \"${block.topic ?? \"(none)\"}\"`);\n lines.push(` ${preview}${block.summary.length > 200 ? \"...\" : \"\"}`);\n }\n lines.push(`\\nCall with blockId to get the full summary.`);\n return lines.join(\"\\n\");\n}\n","import { createCore } from \"./compress.js\";\nimport { assignRefs, highestUsedIndex } from \"./refs.js\";\nimport { defaultCountTokens } from \"./tokenize.js\";\nimport type { CompressionState, CoreMessage } from \"./types.js\";\n\nexport interface CompressInputEntry {\n startId?: string;\n endId?: string;\n messageId?: string;\n summary: string;\n topic?: string;\n}\n\nexport interface RebuildResult {\n state: CompressionState;\n blocksRebuilt: number;\n}\n\nexport interface RebuildPorts {\n countTokens?: (text: string) => number;\n}\n\n/**\n * Fork-recovery: reconstruct compression state by replaying historical\n * `compress` tool-call messages. Message refs (mNNNNN) are assigned by\n * message order, so they are fork-stable — a ref in a historical compress\n * input points to the same logical message after a fork regenerates IDs.\n * The rebuilt state is an approximation: only raw model summaries are\n * replayed (no protected-content enrichments).\n */\nexport function rebuildCompressionState(\n state: CompressionState,\n messages: CoreMessage[],\n config: import(\"./types.js\").Config,\n ports: RebuildPorts = {},\n): RebuildResult {\n const core = createCore({ countTokens: ports.countTokens ?? defaultCountTokens });\n const refResult = assignRefs(messages, {\n existing: state.messageRefs,\n nextIndex: highestUsedIndex(state.messageRefs) + 1,\n });\n let working: CompressionState = { ...state, messageRefs: refResult.map };\n\n const invocations = collectCompressInvocations(messages);\n let blocksRebuilt = 0;\n\n for (const invocation of invocations) {\n const ranges = extractRanges(invocation.input, invocation.callId);\n if (ranges.length === 0) continue;\n const result = core.applyCompression({ ranges, messages, state: working, config });\n working = result.state;\n blocksRebuilt += result.result.blocksCreated;\n }\n\n return { state: working, blocksRebuilt };\n}\n\ninterface CompressInvocation {\n callId: string | undefined;\n input: unknown;\n}\n\nfunction collectCompressInvocations(messages: CoreMessage[]): CompressInvocation[] {\n const invocations: CompressInvocation[] = [];\n for (const message of messages) {\n if (message.toolName !== \"compress\" || message.contentType !== \"tool-call\") continue;\n let input: unknown;\n try {\n input = JSON.parse(message.text ?? \"\");\n } catch {\n continue;\n }\n invocations.push({ callId: message.toolCallId, input });\n }\n return invocations;\n}\n\nfunction extractRanges(\n input: unknown,\n callId: string | undefined,\n): Array<{\n startRef: string;\n endRef: string;\n summary: string;\n topic?: string;\n compressCallId?: string;\n}> {\n const content = (input as { content?: unknown[] })?.content;\n if (!Array.isArray(content)) return [];\n const ranges = [];\n for (const entry of content) {\n if (!entry || typeof entry !== \"object\") continue;\n const e = entry as CompressInputEntry;\n if (typeof e.summary !== \"string\") continue;\n const start = e.startId ?? e.messageId;\n const end = e.endId ?? e.messageId;\n if (typeof start !== \"string\" || typeof end !== \"string\") continue;\n ranges.push({\n startRef: start,\n endRef: end,\n summary: e.summary,\n topic: typeof e.topic === \"string\" ? e.topic : undefined,\n compressCallId: callId,\n });\n }\n return ranges;\n}\n","/**\n * Block search — find compressed (invisible) content by keyword.\n *\n * This is the core value of ACP: as conversations grow, most history becomes\n * invisible (compressed into summary blocks). Search is the only way to\n * retrieve specific information from that invisible content.\n *\n * Current implementation: substring counting (simple but effective for\n * dozens of blocks). Future: TF-IDF, fuzzy matching, CJK tokenization,\n * semantic search.\n */\n\nimport type { CompressionState, CompressionBlock } from \"./types.js\";\n\nexport interface SearchResult {\n blockId: string;\n tier: number;\n score: number;\n topic: string;\n preview: string;\n block: CompressionBlock;\n}\n\nexport interface SearchOptions {\n limit?: number;\n previewLength?: number;\n minScore?: number;\n}\n\nexport function searchBlocks(\n state: CompressionState,\n query: string,\n options: SearchOptions = {},\n): SearchResult[] {\n const limit = options.limit ?? 10;\n const previewLength = options.previewLength ?? 200;\n const minScore = options.minScore ?? 1;\n\n const terms = query\n .toLowerCase()\n .trim()\n .split(/\\s+/)\n .filter((t) => t.length > 0);\n\n if (terms.length === 0) return [];\n\n const active = state.blocks.filter((b: CompressionBlock) => b.active);\n\n const scored: SearchResult[] = [];\n for (const block of active) {\n const text = (block.summary || \"\").toLowerCase();\n const topic = (block.topic || \"\").toLowerCase();\n const haystack = topic + \" \" + text;\n\n let score = 0;\n for (const term of terms) {\n score += countOccurrences(haystack, term);\n }\n\n if (score >= minScore) {\n scored.push({\n blockId: block.blockId,\n tier: block.tier ?? 1,\n score,\n topic: block.topic ?? \"(no topic)\",\n preview: (block.summary || \"\").slice(0, previewLength),\n block,\n });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, limit);\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n return haystack.split(needle).length - 1;\n}\n"],"mappings":"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","names":["require","require","block","formatTokens","numericPart","activeBlocks","refNum","countOccurrences"]}
1
+ {"version":3,"sources":["../src/refs.ts","../src/state.ts","../src/prune.ts","../src/sync.ts","../src/tokenize.ts","../src/config.ts","../src/boundaries.ts","../src/truncate-tools.ts","../src/hide-consumed.ts","../src/filter/registry.ts","../src/filter/apply.ts","../src/render-refs.ts","../src/protected.ts","../src/tool-pairs.ts","../src/recommend.ts","../src/pipeline.ts","../src/compress.ts","../src/compression-rules.ts","../src/nudge-text.ts","../src/keep-markers.ts","../src/decompress.ts","../src/report.ts","../src/rebuild.ts","../src/search.ts"],"sourcesContent":["import type { CoreMessage, MessageRefMap } from \"./types.js\";\n\nconst REF_WIDTH = 5;\nconst MIN_INDEX = 1;\nconst MAX_INDEX = 99999;\nconst REF_PATTERN = /^m0*(\\d{1,5})$/;\n\nexport const BLOCKED_REF = \"BLOCKED\";\n\nexport function emptyRefMap(): MessageRefMap {\n return { byRaw: {}, byRef: {} };\n}\n\nexport function indexToRef(index: number): string {\n if (!Number.isInteger(index) || index < MIN_INDEX || index > MAX_INDEX) {\n throw new RangeError(\n `ref index out of bounds: ${index} (allowed ${MIN_INDEX}-${MAX_INDEX})`,\n );\n }\n return `m${String(index).padStart(REF_WIDTH, \"0\")}`;\n}\n\nexport function refToIndex(ref: string): number | null {\n const match = REF_PATTERN.exec(ref.trim().toLowerCase());\n if (!match) return null;\n const index = Number(match[1]);\n if (index < MIN_INDEX || index > MAX_INDEX) return null;\n return index;\n}\n\nexport function refForRaw(map: MessageRefMap, rawId: string): string | null {\n return map.byRaw[rawId] ?? null;\n}\n\nexport function rawForRef(map: MessageRefMap, ref: string): string | null {\n return map.byRef[ref] ?? null;\n}\n\nexport interface AssignRefsResult {\n map: MessageRefMap;\n nextIndex: number;\n newlyAssigned: number;\n}\n\nexport interface AssignRefsOptions {\n existing: MessageRefMap;\n nextIndex: number;\n isProtected?: (message: CoreMessage) => boolean;\n shouldSkip?: (message: CoreMessage) => boolean;\n}\n\nexport function assignRefs(\n messages: CoreMessage[],\n options: AssignRefsOptions,\n): AssignRefsResult {\n const map: MessageRefMap = {\n byRaw: { ...options.existing.byRaw },\n byRef: { ...options.existing.byRef },\n };\n let cursor =\n Number.isInteger(options.nextIndex) && options.nextIndex >= MIN_INDEX\n ? options.nextIndex\n : MIN_INDEX;\n let newlyAssigned = 0;\n\n for (const message of messages) {\n if (!message.id || options.shouldSkip?.(message)) continue;\n\n if (map.byRaw[message.id]) continue;\n\n if (options.isProtected?.(message)) {\n map.byRaw[message.id] = BLOCKED_REF;\n continue;\n }\n\n const ref = allocateFreeRef(map, cursor);\n cursor = ref.index + 1;\n map.byRaw[message.id] = ref.text;\n map.byRef[ref.text] = message.id;\n newlyAssigned++;\n }\n\n return { map, nextIndex: cursor, newlyAssigned };\n}\n\nfunction allocateFreeRef(\n map: MessageRefMap,\n start: number,\n): { text: string; index: number } {\n let candidate = Math.max(start, MIN_INDEX);\n while (candidate <= MAX_INDEX) {\n const text = indexToRef(candidate);\n if (!map.byRef[text]) {\n return { text, index: candidate };\n }\n candidate++;\n }\n throw new Error(\n `ref capacity exhausted: cannot allocate beyond ${indexToRef(MAX_INDEX)}`,\n );\n}\n\nexport function rebuildRefIndex(map: MessageRefMap): MessageRefMap {\n const byRef: Record<string, string> = {};\n for (const [rawId, ref] of Object.entries(map.byRaw)) {\n if (ref !== BLOCKED_REF) byRef[ref] = rawId;\n }\n return { byRaw: { ...map.byRaw }, byRef };\n}\n\nexport function highestUsedIndex(map: MessageRefMap): number {\n let highest = 0;\n for (const ref of Object.values(map.byRaw)) {\n const index = ref === BLOCKED_REF ? null : refToIndex(ref);\n if (index !== null && index > highest) highest = index;\n }\n return highest;\n}\n","import type { CompressionBlock, CompressionState } from \"./types.js\";\n\nexport function createInitialState(): CompressionState {\n return {\n blocks: [],\n messageRefs: { byRaw: {}, byRef: {} },\n nudge: {\n lastPerMessageNudgeTokens: 0,\n lastNudgeShownTokens: 0,\n baselineTokens: 0,\n anchors: {},\n lastShownByTier: {},\n },\n stats: { tokensCompressed: 0, compressionCount: 0 },\n nextBlockId: 1,\n nextRunId: 1,\n };\n}\n\nexport function allocateBlockId(state: CompressionState): string {\n const id = state.nextBlockId;\n state.nextBlockId = Math.max(1, id) + 1;\n return `b${id}`;\n}\n\nexport function allocateRunId(state: CompressionState): string {\n const id = state.nextRunId;\n state.nextRunId = Math.max(1, id) + 1;\n return `r${id}`;\n}\n\nexport function blockById(\n state: CompressionState,\n blockId: string,\n): CompressionBlock | undefined {\n return state.blocks.find((block) => block.blockId === blockId);\n}\n\nexport function activeBlocks(state: CompressionState): CompressionBlock[] {\n return state.blocks.filter((block) => block.active);\n}\n\nexport function coveredMessageIds(state: CompressionState): Set<string> {\n const covered = new Set<string>();\n for (const block of state.blocks) {\n if (!block.active) continue;\n for (const id of block.effectiveMessageIds) covered.add(id);\n }\n return covered;\n}\n\nexport function highestActiveTier(state: CompressionState): 0 | 1 | 2 | 3 {\n let highest: 0 | 1 | 2 | 3 = 0;\n for (const block of state.blocks) {\n if (block.active && block.tier > highest) highest = block.tier;\n }\n return highest;\n}\n\nexport function advanceSurvival(\n state: CompressionState,\n promotionThreshold: number,\n): void {\n for (const block of state.blocks) {\n if (!block.active) continue;\n block.survivedCount += 1;\n if (block.survivedCount >= promotionThreshold) {\n block.generation = \"old\";\n }\n }\n}\n","import { activeBlocks, coveredMessageIds } from \"./state.js\";\nimport type { CompressionState, CoreMessage } from \"./types.js\";\n\nexport const SUMMARY_HEADER = \"[Compressed conversation section]\";\n\nexport interface PruneOptions {\n injectSummaries?: boolean;\n}\n\nexport function prune(\n messages: CoreMessage[],\n state: CompressionState,\n options: PruneOptions = {},\n): CoreMessage[] {\n const covered = coveredMessageIds(state);\n if (covered.size === 0) return [...messages];\n\n const inject = options.injectSummaries ?? true;\n const firstUserIndex = messages.findIndex(\n (message) => message.role === \"user\",\n );\n\n const indexById = new Map<string, number>();\n messages.forEach((message, index) => indexById.set(message.id, index));\n\n const anchors = inject ? collectSummaryAnchors(state, indexById) : [];\n\n return stripOrphanedToolResults(\n stripOrphanedToolCalls(\n rebuildMessages(messages, covered, firstUserIndex, anchors),\n ),\n );\n}\n\ninterface SummaryAnchor {\n blockId: string;\n summary: string;\n topic?: string;\n insertAt: number;\n}\n\nfunction collectSummaryAnchors(\n state: CompressionState,\n indexById: Map<string, number>,\n): SummaryAnchor[] {\n const anchors: SummaryAnchor[] = [];\n for (const block of activeBlocks(state)) {\n let earliest: number | null = null;\n for (const id of block.effectiveMessageIds) {\n const index = indexById.get(id);\n if (index !== undefined && (earliest === null || index < earliest)) {\n earliest = index;\n }\n }\n anchors.push({\n blockId: block.blockId,\n summary: block.summary,\n topic: block.topic,\n insertAt: earliest ?? 0,\n });\n }\n anchors.sort((left, right) => left.insertAt - right.insertAt);\n return anchors;\n}\n\nfunction rebuildMessages(\n messages: CoreMessage[],\n covered: Set<string>,\n firstUserIndex: number,\n anchors: SummaryAnchor[],\n): CoreMessage[] {\n const result: CoreMessage[] = [];\n const pending = [...anchors];\n\n for (let index = 0; index < messages.length; index++) {\n while (pending.length > 0 && pending[0]!.insertAt === index) {\n result.push(renderSummary(pending.shift()!));\n }\n if (index === firstUserIndex && firstUserIndex >= 0) {\n result.push(messages[index]!);\n continue;\n }\n if (covered.has(messages[index]!.id)) continue;\n result.push(messages[index]!);\n }\n\n while (pending.length > 0) {\n result.push(renderSummary(pending.shift()!));\n }\n\n return result;\n}\n\nfunction renderSummary(anchor: SummaryAnchor): CoreMessage {\n const body = anchor.summary.trim();\n const topicLine = anchor.topic\n ? `${SUMMARY_HEADER} — ${anchor.topic}`\n : SUMMARY_HEADER;\n const text = body.length === 0 ? topicLine : `${topicLine}\\n${body}`;\n return {\n id: `acp_summary_${anchor.blockId}`,\n role: \"system\",\n contentType: \"text\",\n text,\n };\n}\n\nfunction stripOrphanedToolResults(messages: CoreMessage[]): CoreMessage[] {\n const knownCallIds = new Set<string>();\n for (const m of messages) {\n if (m.contentType === \"tool-call\" && m.toolCallId) {\n knownCallIds.add(m.toolCallId);\n }\n }\n return messages.filter(\n (m) =>\n m.contentType !== \"tool-result\" ||\n !m.toolCallId ||\n knownCallIds.has(m.toolCallId),\n );\n}\n\nfunction stripOrphanedToolCalls(messages: CoreMessage[]): CoreMessage[] {\n const knownResultIds = new Set<string>();\n for (const m of messages) {\n if (m.contentType === \"tool-result\" && m.toolCallId) {\n knownResultIds.add(m.toolCallId);\n }\n }\n return messages.filter(\n (m) =>\n m.contentType !== \"tool-call\" ||\n !m.toolCallId ||\n m.toolName === \"compress\" ||\n knownResultIds.has(m.toolCallId),\n );\n}\n","import type { CompressionState, CoreMessage } from \"./types.js\";\n\nexport interface SyncResult {\n state: CompressionState;\n deactivated: string[];\n}\n\nexport function syncBlocks(\n messages: CoreMessage[],\n state: CompressionState,\n): SyncResult {\n const presentIds = new Set(messages.map((message) => message.id));\n const deactivated: string[] = [];\n // Deep-clone (not just `{...state}`) so the caller's input state is never\n // mutated: processTurn stamps `state.nudge.*` and reassigns `messageRefs`,\n // and block sub-arrays must not alias the input. Previously nudge/stats/\n // messageRefs were shared references → input-state mutation leak.\n const result: CompressionState = {\n blocks: state.blocks.map((block) => ({\n ...block,\n directMessageIds: [...block.directMessageIds],\n effectiveMessageIds: [...block.effectiveMessageIds],\n directBlockIds: [...block.directBlockIds],\n })),\n messageRefs: {\n byRaw: { ...state.messageRefs.byRaw },\n byRef: { ...state.messageRefs.byRef },\n },\n nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },\n stats: { ...state.stats },\n nextBlockId: state.nextBlockId,\n nextRunId: state.nextRunId,\n };\n\n const consumedBlockIds = new Set<string>();\n for (const block of result.blocks) {\n for (const consumedId of block.directBlockIds) {\n consumedBlockIds.add(consumedId);\n }\n }\n\n for (const block of result.blocks) {\n if (consumedBlockIds.has(block.blockId)) {\n block.active = false;\n continue;\n }\n block.active = true;\n const stillPresent = block.effectiveMessageIds.some((id) =>\n presentIds.has(id),\n );\n if (!stillPresent) {\n block.active = false;\n deactivated.push(block.blockId);\n }\n }\n\n return { state: result, deactivated };\n}\n","import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\nexport function defaultCountTokens(text: string): number {\n if (!text) return 0;\n // CJK chars tokenize ~1:1 (chars/4 badly underestimates them). Count them\n // directly, then estimate the non-CJK remainder with chars/4 so digits,\n // punctuation, and symbols in code/JSON are not dropped to zero.\n const cjk = text.match(/[\\u4e00-\\u9fff\\u3040-\\u30ff\\uac00-\\ud7af]/g);\n const cjkCount = cjk?.length ?? 0;\n return cjkCount + Math.ceil((text.length - cjkCount) / 4);\n}\n\nexport function estimateMessageTokens(text: string | undefined): number {\n return defaultCountTokens(text ?? \"\");\n}\n\nexport function estimateTokensFast(text: string): number {\n if (!text) return 0;\n return Math.ceil(text.length / 4);\n}\n\nexport type TokenCountFn = (text: string) => number;\n\nexport function createBpeTokenizer(): TokenCountFn {\n try {\n const mod = require(\"@anthropic-ai/tokenizer\");\n const bpeCount = mod.countTokens ?? mod.default?.countTokens;\n if (typeof bpeCount !== \"function\") return defaultCountTokens;\n return (text: string) => {\n try {\n return bpeCount(text);\n } catch {\n return defaultCountTokens(text);\n }\n };\n } catch {\n return defaultCountTokens;\n }\n}\n","import type { Config } from \"./types.js\";\n\nexport function defaultConfig(\n modelContextLimit: number,\n overrides: Partial<Config> = {},\n): Config {\n const base: Config = {\n tiers: { enabled: true, tier2Trigger: 5, tier3Trigger: 10 },\n nudge: {\n maxContextLimitPct: 0.55,\n minContextLimitPct: 0.45,\n frequency: 5,\n iterationThreshold: 15,\n force: \"soft\",\n growthRatio: 0.05,\n growthFloor: Math.max(20000, Math.round(modelContextLimit * 0.05)),\n growthCap: 50000,\n minGrowthFloor: 20000,\n minGrowthRatio: 0.45,\n emergencyThresholdPct: 0.80,\n },\n promotionThreshold: 5,\n truncate: { threshold: 1 },\n compress: {\n minCompressRange: 5000,\n maxSummaryLength: 20000,\n minSummaryLength: 50,\n },\n protectedTools: [],\n preserveRecentMessages: 5,\n preserveRecentTokens: 5000,\n modelContextLimit,\n };\n return {\n ...base,\n ...overrides,\n tiers: { ...base.tiers, ...overrides.tiers },\n nudge: { ...base.nudge, ...overrides.nudge },\n truncate: { ...base.truncate, ...overrides.truncate },\n compress: { ...base.compress, ...overrides.compress },\n };\n}\n\nexport function validateConfig(config: Config): string[] {\n const errors: string[] = [];\n if (\n !Number.isFinite(config.modelContextLimit) ||\n config.modelContextLimit <= 0\n ) {\n errors.push(\"modelContextLimit must be a positive number\");\n }\n if (config.nudge.minContextLimitPct > config.nudge.maxContextLimitPct) {\n errors.push(\n \"nudge.minContextLimitPct must not exceed nudge.maxContextLimitPct\",\n );\n }\n if (config.promotionThreshold < 1) {\n errors.push(\"promotionThreshold must be >= 1\");\n }\n if (config.truncate.threshold <= 0 || config.truncate.threshold > 1) {\n errors.push(\"truncate.threshold must be in (0, 1]\");\n }\n for (const tier of [config.tiers.tier2Trigger, config.tiers.tier3Trigger]) {\n if (tier < 1) errors.push(\"tier triggers must be >= 1\");\n }\n if (config.tiers.tier3Trigger <= config.tiers.tier2Trigger) {\n errors.push(\"tiers.tier3Trigger must be greater than tiers.tier2Trigger\");\n }\n return errors;\n}\n","import { activeBlocks, blockById } from \"./state.js\";\nimport type {\n CompressionState,\n CoreMessage,\n ResolvedBoundary,\n} from \"./types.js\";\n\nexport type BoundaryKind = \"message\" | \"block\";\n\nexport interface ParsedBoundary {\n kind: BoundaryKind;\n numericId: number;\n raw: string;\n}\n\nconst MESSAGE_REF_PATTERN = /^m0*(\\d{1,5})$/;\nconst BLOCK_REF_PATTERN = /^b(\\d{1,9})$/;\n\nexport function parseBoundary(ref: string): ParsedBoundary | null {\n const normalized = ref.trim().toLowerCase();\n const messageMatch = MESSAGE_REF_PATTERN.exec(normalized);\n if (messageMatch) {\n const numericId = Number(messageMatch[1]);\n if (numericId >= 1 && numericId <= 99999) {\n return { kind: \"message\", numericId, raw: normalized };\n }\n }\n const blockMatch = BLOCK_REF_PATTERN.exec(normalized);\n if (blockMatch) {\n const numericId = Number(blockMatch[1]);\n if (numericId >= 1) return { kind: \"block\", numericId, raw: normalized };\n }\n return null;\n}\n\nexport interface ResolveBoundariesInput {\n startRef: string;\n endRef: string;\n messages: CoreMessage[];\n state: CompressionState;\n}\n\nexport interface ResolvedRange {\n startIndex: number;\n endIndex: number;\n messageIds: string[];\n nestedBlockIds: string[];\n boundaryKind: BoundaryKind;\n protectedGaps: number[];\n}\n\nexport function resolveBoundaries(\n input: ResolveBoundariesInput,\n): ResolvedRange {\n const start = parseBoundary(input.startRef);\n const end = parseBoundary(input.endRef);\n if (!start || !end) {\n throw new Error(\n `Invalid boundary ref(s): startId=\"${input.startRef}\", endId=\"${input.endRef}\". Use mNNNNN or bN.`,\n );\n }\n\n const indexByRawId = new Map<string, number>();\n input.messages.forEach((message, index) =>\n indexByRawId.set(message.id, index),\n );\n\n let startIndex = resolveAnchorIndex(start, input.state, indexByRawId);\n let endIndex = resolveAnchorIndex(end, input.state, indexByRawId);\n\n if (startIndex === null || endIndex === null) {\n throw new Error(\n `Boundary not found in visible context (likely consumed by an existing block). ` +\n `startId=\"${input.startRef}\", endId=\"${input.endRef}\".`,\n );\n }\n\n if (startIndex > endIndex) {\n [startIndex, endIndex] = [endIndex, startIndex];\n }\n\n const messageIds: string[] = [];\n for (let index = startIndex; index <= endIndex; index++) {\n const message = input.messages[index];\n if (message) messageIds.push(message.id);\n }\n\n const boundaryKind: BoundaryKind =\n start.kind === \"block\" || end.kind === \"block\" ? \"block\" : \"message\";\n\n const nestedBlockIds: string[] = [];\n const nestedSeen = new Set<string>();\n for (const block of activeBlocks(input.state)) {\n const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);\n if (anchor !== null && anchor >= startIndex && anchor <= endIndex) {\n if (!nestedSeen.has(block.blockId)) {\n nestedSeen.add(block.blockId);\n nestedBlockIds.push(block.blockId);\n }\n }\n }\n\n const protectedGaps: number[] = [];\n\n return {\n startIndex,\n endIndex,\n messageIds,\n nestedBlockIds,\n boundaryKind,\n protectedGaps,\n };\n}\n\nfunction resolveAnchorIndex(\n boundary: ParsedBoundary,\n state: CompressionState,\n indexByRawId: Map<string, number>,\n): number | null {\n if (boundary.kind === \"message\") {\n const rawId =\n state.messageRefs.byRef[boundary.raw] ??\n state.messageRefs.byRef[formatPaddedRef(boundary.numericId)];\n if (!rawId) return null;\n const index = indexByRawId.get(rawId);\n return index === undefined ? null : index;\n }\n\n const block = blockById(state, `b${boundary.numericId}`);\n if (!block || !block.active) return null;\n return earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);\n}\n\nfunction formatPaddedRef(index: number): string {\n return `m${String(index).padStart(5, \"0\")}`;\n}\n\nexport function earliestIndexOfIds(\n ids: string[],\n indexByRawId: Map<string, number>,\n): number | null {\n let earliest: number | null = null;\n for (const id of ids) {\n const index = indexByRawId.get(id);\n if (index !== undefined && (earliest === null || index < earliest)) {\n earliest = index;\n }\n }\n return earliest;\n}\n\nexport function toResolvedBoundary(range: ResolvedRange): ResolvedBoundary {\n return {\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n protectedGaps: range.protectedGaps,\n };\n}\n","import type { Config, CoreMessage } from \"./types.js\";\n\nexport interface TruncateOptions {\n minOutputTokens?: number;\n keepPrefixChars?: number;\n keepSuffixChars?: number;\n protectRecentMessages?: number;\n}\n\nexport interface TruncateResult {\n messages: CoreMessage[];\n truncatedCount: number;\n savedTokens: number;\n}\n\nconst TRUNCATION_MARKER = \"[truncated for context space]\";\nconst DEFAULTS = {\n minOutputTokens: 1000,\n keepPrefixChars: 2000,\n keepSuffixChars: 2000,\n protectRecentMessages: 3,\n} as const;\n\nexport function truncateLargeToolOutputs(\n messages: CoreMessage[],\n tokenCount: number,\n config: Config,\n countTokens: (text: string) => number,\n options: TruncateOptions = {},\n): TruncateResult {\n const opts = { ...DEFAULTS, ...options };\n if (config.modelContextLimit <= 0) return { messages, truncatedCount: 0, savedTokens: 0 };\n\n const threshold = config.truncate.threshold * config.modelContextLimit;\n if (tokenCount < threshold) return { messages, truncatedCount: 0, savedTokens: 0 };\n\n const protectedIndex = messages.length - opts.protectRecentMessages;\n const candidates: Array<{ index: number; tokens: number }> = [];\n\n for (let index = 0; index < messages.length; index++) {\n if (index >= protectedIndex) break;\n const message = messages[index]!;\n if (message.contentType !== \"tool-result\") continue;\n const text = message.text ?? \"\";\n if (text.length === 0 || text.includes(TRUNCATION_MARKER)) continue;\n const tokens = countTokens(text);\n if (tokens < opts.minOutputTokens) continue;\n candidates.push({ index, tokens });\n }\n\n if (candidates.length === 0) return { messages, truncatedCount: 0, savedTokens: 0 };\n candidates.sort((left, right) => right.tokens - left.tokens);\n\n const targetTokens = threshold * 0.9;\n let savedTokens = 0;\n const edits = new Map<number, string>();\n let truncatedCount = 0;\n\n for (const candidate of candidates) {\n if (tokenCount - savedTokens <= targetTokens) break;\n const original = messages[candidate.index]!.text ?? \"\";\n if (original.length <= opts.keepPrefixChars + opts.keepSuffixChars) continue;\n\n const prefix = original.slice(0, opts.keepPrefixChars);\n const suffix = original.slice(-opts.keepSuffixChars);\n const replacement =\n prefix +\n `\\n\\n...${TRUNCATION_MARKER} — original ~${candidate.tokens} tokens]...\\n\\n` +\n suffix;\n edits.set(candidate.index, replacement);\n savedTokens += candidate.tokens - countTokens(replacement);\n truncatedCount++;\n }\n\n if (truncatedCount === 0) return { messages, truncatedCount: 0, savedTokens: 0 };\n\n const updated = messages.map((message, index) =>\n edits.has(index) ? { ...message, text: edits.get(index)! } : message,\n );\n return { messages: updated, truncatedCount, savedTokens };\n}\n","import type { CompressionState, CoreMessage } from \"./types.js\";\n\n// Orphaned compress calls (no matching active block, e.g. failed attempts or\n// historical calls whose blocks predate compressCallId recording) are fully\n// hidden — they carry no recoverable information and only pollute context.\n// Active-block compress calls are kept (matched via compressCallId).\nconst KEEP_LAST_ORPHANED = 0;\n\nexport interface HideConsumedResult {\n messages: CoreMessage[];\n hidden: number;\n}\n\n// Keep active-block compress calls + the most recent orphaned calls; hide the rest.\nexport function hideConsumedCompressCalls(\n state: CompressionState,\n messages: CoreMessage[],\n): HideConsumedResult {\n const activeCallIds = new Set<string>();\n const allBlockCallIds = new Set<string>();\n for (const block of state.blocks) {\n if (block.compressCallId) {\n allBlockCallIds.add(block.compressCallId);\n if (block.active) activeCallIds.add(block.compressCallId);\n }\n }\n\n const lastOrphanedCallIds: string[] = [];\n for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {\n const message = messages[i]!;\n if (message.toolName !== \"compress\" || message.contentType !== \"tool-call\") continue;\n const callId = message.toolCallId;\n if (callId && !allBlockCallIds.has(callId)) {\n lastOrphanedCallIds.push(callId);\n }\n }\n\n const keepCallIds = new Set([...activeCallIds, ...lastOrphanedCallIds]);\n\n const hiddenCallIds = new Set<string>();\n for (const message of messages) {\n if (\n message.toolName === \"compress\" &&\n message.contentType === \"tool-call\" &&\n (!message.toolCallId || !keepCallIds.has(message.toolCallId))\n ) {\n if (message.toolCallId) hiddenCallIds.add(message.toolCallId);\n }\n }\n\n let hidden = 0;\n const result: CoreMessage[] = [];\n for (const message of messages) {\n if (\n message.toolName === \"compress\" &&\n message.contentType === \"tool-call\" &&\n (!message.toolCallId || !keepCallIds.has(message.toolCallId))\n ) {\n hidden++;\n continue;\n }\n if (\n message.contentType === \"tool-result\" &&\n message.toolCallId &&\n hiddenCallIds.has(message.toolCallId)\n ) {\n hidden++;\n continue;\n }\n result.push(message);\n }\n\n return { messages: result, hidden };\n}\n","import type { MessageFilter } from \"./types.js\";\n\nconst registry = new Map<string, MessageFilter>();\n\nexport function registerMessageFilter(filter: MessageFilter): void {\n const existing = registry.get(filter.name);\n if (existing && existing.version !== filter.version) {\n throw new Error(\n `Message filter \"${filter.name}\" already registered with version ${existing.version}, cannot register version ${filter.version}.`,\n );\n }\n registry.set(filter.name, filter);\n}\n\nexport function getMessageFilter(name: string): MessageFilter | undefined {\n return registry.get(name);\n}\n\nexport function listMessageFilters(): MessageFilter[] {\n return [...registry.values()];\n}\n\nexport function clearMessageFilters(): void {\n registry.clear();\n}\n","import { listMessageFilters } from \"./registry.js\";\nimport type { CoreMessage } from \"../types.js\";\nimport type { FilterResult, MessageFilterContext, MessageFiltersConfig } from \"./types.js\";\n\nexport interface ApplyResult {\n messages: CoreMessage[];\n partsFiltered: number;\n partsDropped: number;\n partsModified: number;\n}\n\nexport function applyMessageFilters(\n messages: CoreMessage[],\n config: MessageFiltersConfig | undefined,\n): ApplyResult {\n if (!config?.enabled) {\n return { messages, partsFiltered: 0, partsDropped: 0, partsModified: 0 };\n }\n\n const active = listMessageFilters().filter(\n (filter) => config.filters?.[filter.name]?.enabled !== false,\n );\n if (active.length === 0) {\n return { messages, partsFiltered: 0, partsDropped: 0, partsModified: 0 };\n }\n\n let working = messages.map((message) => ({ ...message }));\n const tally = { partsFiltered: 0, partsDropped: 0, partsModified: 0 };\n const total = working.length;\n\n const immediate = active.filter((filter) => !filter.keepLastOnly);\n for (let index = 0; index < working.length; index++) {\n const message = working[index]!;\n const text = message.text ?? \"\";\n if (text.length === 0) continue;\n let current = text;\n const baseCtx: MessageFilterContext = {\n text: current,\n role: message.role,\n messageIndex: index,\n totalMessages: total,\n toolName: message.toolName,\n };\n for (const filter of immediate) {\n let decision: FilterResult;\n try {\n decision = filter.filter(baseCtx);\n } catch {\n continue;\n }\n if (decision.action === \"keep\") continue;\n tally.partsFiltered++;\n if (decision.action === \"drop\") {\n current = \"\";\n tally.partsDropped++;\n } else if (decision.action === \"modify\" && decision.text !== undefined) {\n current = decision.text;\n tally.partsModified++;\n }\n baseCtx.text = current;\n }\n if (current !== text) working[index] = { ...message, text: current };\n }\n\n const keepLast = active.filter((filter) => filter.keepLastOnly);\n for (const filter of keepLast) {\n let foundLast = false;\n for (let index = working.length - 1; index >= 0; index--) {\n const message = working[index]!;\n const text = message.text ?? \"\";\n if (text.length === 0) continue;\n const ctx: MessageFilterContext = {\n text,\n role: message.role,\n messageIndex: index,\n totalMessages: total,\n toolName: message.toolName,\n };\n let decision: FilterResult;\n try {\n decision = filter.filter(ctx);\n } catch {\n continue;\n }\n if (decision.action !== \"drop\" && decision.action !== \"modify\") continue;\n if (foundLast) {\n tally.partsFiltered++;\n tally.partsDropped++;\n working[index] = { ...message, text: \"\" };\n } else {\n foundLast = true;\n if (decision.action === \"modify\" && decision.text !== undefined) {\n tally.partsFiltered++;\n tally.partsModified++;\n working[index] = { ...message, text: decision.text };\n }\n }\n }\n }\n\n return { messages: working, ...tally };\n}\n","import type { CoreMessage, CompressionState, MessageRefMap } from \"./types.js\";\nimport { refForRaw, BLOCKED_REF } from \"./refs.js\";\nimport type { PipelineNode, PipelineContext, NodeIO } from \"./pipeline.js\";\n\n/** Format token count: <1K raw, <10K \"X.YK\", >=10K \"XK\". */\nfunction formatTokens(tokens: number): string {\n if (tokens < 1000) return String(tokens);\n if (tokens < 10000) return (tokens / 1000).toFixed(1) + \"K\";\n return Math.round(tokens / 1000) + \"K\";\n}\n\nfunction classifyType(message: CoreMessage): string {\n if (\n message.contentType === \"tool-call\" ||\n message.contentType === \"tool-result\"\n ) {\n return message.toolName || \"tool\";\n }\n return message.contentType;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst LT = \"\\x3c\";\nconst GT = \"\\x3e\";\nconst TAG_OPEN = LT + \"acp \";\nconst TAG_CLOSE = LT + \"/acp\" + GT;\n\nfunction acpTag(ref: string, tokens: number, type: string): string {\n return TAG_OPEN + 'tokens=\"' + formatTokens(tokens) + '\" type=\"' + type + '\"' + GT + ref + TAG_CLOSE;\n}\n\nfunction renderMessage(\n message: CoreMessage,\n map: MessageRefMap,\n countTokens: (text: string) => number,\n): CoreMessage {\n const ref = refForRaw(map, message.id);\n if (!ref || ref === BLOCKED_REF) return message;\n\n // Strip own stale tag BEFORE computing tokens (idempotency).\n // Match the message's own ref only — foreign tags survive (content-corruption fix).\n const ownTagRe = new RegExp(\n \"^\" + escapeRegex(TAG_OPEN) + \"[^>]*\" + GT + escapeRegex(ref) + escapeRegex(TAG_CLOSE) + \"\\\\n?\",\n );\n const cleanText = (message.text || \"\").replace(ownTagRe, \"\");\n\n const tokens = countTokens(cleanText);\n const type = classifyType(message);\n const prefix = acpTag(ref, tokens, type) + \"\\n\";\n\n if (!cleanText) return { ...message, text: prefix };\n return { ...message, text: prefix + cleanText };\n}\n\nexport function renderVisibleRefs(\n messages: CoreMessage[],\n state: CompressionState,\n countTokens: (text: string) => number = (text) =>\n Math.ceil(text.length / 4),\n): CoreMessage[] {\n const map = state.messageRefs;\n return messages.map((message) =>\n renderMessage(message, map, countTokens),\n );\n}\n\nexport const renderRefsNode: PipelineNode = {\n name: \"render-refs\",\n run(io: NodeIO, ctx: PipelineContext): NodeIO {\n return {\n ...io,\n messages: renderVisibleRefs(io.messages, io.state, ctx.countTokens),\n };\n },\n};\n","import type { Config, CoreMessage } from \"./types.js\";\n\n/** Tools that are ALWAYS protected, regardless of user config. These are ACP's\n * own metadata tools whose records must remain in context: compress calls\n * carry the summaries that decompress/search rely on, and the system prompt\n * treats past compress calls as load-bearing metadata. Letting them be\n * compressed away breaks decompress and the \"summary is historical\" contract. */\nexport const ALWAYS_PROTECTED_TOOLS = [\"compress\"] as const;\n\nexport function matchToolPattern(toolName: string, pattern: string): boolean {\n if (pattern.endsWith(\"*\")) {\n return toolName.startsWith(pattern.slice(0, -1));\n }\n return toolName === pattern;\n}\n\nexport function isMessageProtected(\n msg: CoreMessage,\n config: Pick<Config, \"protectedTools\" | \"isToolProtected\">,\n): boolean {\n // tool-result carries the same toolName as its tool-call (the host projects\n // it), so checking toolName covers both sides of a tool exchange.\n if (\n (msg.contentType !== \"tool-call\" && msg.contentType !== \"tool-result\") ||\n !msg.toolName\n ) {\n return false;\n }\n\n // Hard-coded protection: ACP metadata tools are never compressible.\n if ((ALWAYS_PROTECTED_TOOLS as readonly string[]).includes(msg.toolName)) {\n return true;\n }\n\n for (const pattern of config.protectedTools) {\n if (matchToolPattern(msg.toolName, pattern)) return true;\n }\n\n if (config.isToolProtected?.(msg.toolName, msg.text)) return true;\n\n return false;\n}\n\n/** Build the set of toolCallIds whose tool-call is protected. Use this to also\n * protect tool-results that lack a toolName (common when the host projects a\n * tool-result with only toolCallId). Without it, the result half of a\n * protected tool exchange leaks into compressible ranges. */\nexport function collectProtectedToolCallIds(\n messages: CoreMessage[],\n config: Pick<Config, \"protectedTools\" | \"isToolProtected\">,\n): Set<string> {\n const ids = new Set<string>();\n for (const m of messages) {\n if (m.contentType === \"tool-call\" && m.toolCallId && isMessageProtected(m, config)) {\n ids.add(m.toolCallId);\n }\n }\n return ids;\n}\n\n/** Like isMessageProtected, but also matches tool-results by toolCallId against\n * the protected call set. Use when you have the full message list available. */\nexport function isMessageProtectedWithPairing(\n msg: CoreMessage,\n config: Pick<Config, \"protectedTools\" | \"isToolProtected\">,\n protectedCallIds: Set<string>,\n): boolean {\n if (isMessageProtected(msg, config)) return true;\n if (\n msg.contentType === \"tool-result\" &&\n msg.toolCallId &&\n protectedCallIds.has(msg.toolCallId)\n ) {\n return true;\n }\n return false;\n}\n","import type { CoreMessage } from \"./types.js\";\n\n/**\n * Adjust compression range boundaries to include tool-call/result pairs.\n *\n * PREVENTIVE approach (adapted from opencode-acp PR #248): before compression\n * is applied, scan for tool-call or tool-result messages whose matching half\n * (the result for a call in range, or the call for a result in range) sits\n * outside the requested range. Pull the orphan half INTO the range so the\n * pair is compressed together — zero information loss.\n *\n * Only MESSAGE-boundary ranges are adjusted. Block-boundary ranges (bN) are\n * left untouched to preserve tier-detection correctness.\n *\n * @returns Adjusted { startIndex, endIndex } — may be wider than input.\n */\nexport function adjustBoundariesForToolPairs(\n startIndex: number,\n endIndex: number,\n messages: CoreMessage[],\n maxScan: number = 20,\n): { startIndex: number; endIndex: number } {\n // Collect all toolCallIds in range (both tool-call and tool-result messages).\n // Skip compress tool — it's force-protected and always survives pruning.\n const callIdsInRange = new Set<string>();\n for (let i = startIndex; i <= endIndex; i++) {\n const msg = messages[i];\n if (!msg || !msg.toolCallId) continue;\n if (msg.toolName === \"compress\") continue;\n callIdsInRange.add(msg.toolCallId);\n }\n\n if (callIdsInRange.size === 0) {\n return { startIndex, endIndex };\n }\n\n // Extend FORWARD: tool-results typically follow their tool-call.\n // Stop at the first gap after finding at least one matching message.\n let newEndIndex = endIndex;\n for (let i = endIndex + 1; i < messages.length && i <= endIndex + maxScan; i++) {\n const msg = messages[i];\n if (!msg) break;\n if (msg.toolCallId && callIdsInRange.has(msg.toolCallId)) {\n newEndIndex = i;\n } else if (newEndIndex > endIndex) {\n break;\n }\n }\n\n // Extend BACKWARD: tool-calls typically precede their tool-result.\n let newStartIndex = startIndex;\n for (let i = startIndex - 1; i >= 0 && i >= startIndex - maxScan; i--) {\n const msg = messages[i];\n if (!msg) break;\n if (msg.toolCallId && callIdsInRange.has(msg.toolCallId)) {\n newStartIndex = i;\n } else if (newStartIndex < startIndex) {\n break;\n }\n }\n\n return { startIndex: newStartIndex, endIndex: newEndIndex };\n}\n","/**\n * Recommendation engine — compression protection + recommendation.\n *\n * Clean-room reimplementation of the recommendation algorithm (MIT, ours).\n * These pure functions answer two questions every turn:\n *\n * 1. **Protection** — which messages must NOT be compressed? (protected tools,\n * recent messages, recent tokens)\n * 2. **Recommendation** — which remaining ranges are actually WORTH compressing?\n * (growth-aware threshold; suppress nudges when ranges are too small)\n *\n * Called by the `recommend` pipeline node. No side effects, no state mutation.\n */\n\nimport type {\n CompressibleRange,\n Config,\n ContextRanges,\n CoreMessage,\n ProtectedRange,\n} from \"./types.js\";\nimport type { CompressionState } from \"./types.js\";\nimport {\n collectProtectedToolCallIds,\n isMessageProtectedWithPairing,\n} from \"./protected.js\";\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction refNum(ref: string): number {\n const n = parseInt(ref.slice(1), 10);\n return Number.isNaN(n) ? -1 : n;\n}\n\nfunction estimateMessageTokens(message: CoreMessage): number {\n return Math.ceil((message.text ?? \"\").length / 4);\n}\n\nfunction isToolMessage(message: CoreMessage): boolean {\n return message.contentType === \"tool-call\" || message.contentType === \"tool-result\";\n}\n\n\nfunction isSyntheticOrPruned(\n message: CoreMessage,\n state: CompressionState,\n): boolean {\n if (message.text?.startsWith(\"[Compressed conversation section]\")) return true;\n for (const block of state.blocks) {\n if (block.active && block.effectiveMessageIds.includes(message.id)) return true;\n }\n return false;\n}\n\n// ─── 1. Protected Refs (soft protection zone) ─────────────────────────────────\n\n/**\n * Compute the set of protected message refs (mNNNNN) that form the\n * \"soft-protected zone\" at the tail of the conversation.\n *\n * Combines two rules:\n * 1. Last N messages (`config.preserveRecentMessages`)\n * 2. Last N tokens expanding backward (`config.preserveRecentTokens`)\n *\n * Only considers visible, non-synthetic, non-pruned messages that have refs.\n */\nexport function computeProtectedRefs(\n messages: CoreMessage[],\n state: CompressionState,\n config: Config,\n): Set<string> {\n const preserveN = config.preserveRecentMessages;\n const preserveTokens = config.preserveRecentTokens;\n\n const result = new Set<string>();\n const visible: { ref: string; tokens: number }[] = [];\n\n for (const msg of messages) {\n if (isSyntheticOrPruned(msg, state)) continue;\n const ref = state.messageRefs.byRaw[msg.id];\n if (!ref || ref === \"BLOCKED\") continue;\n visible.push({ ref, tokens: estimateMessageTokens(msg) });\n }\n\n // Rule 1: last N messages\n if (preserveN > 0) {\n for (const m of visible.slice(-preserveN)) {\n result.add(m.ref);\n }\n }\n\n // Rule 2: last N tokens (expand backward from tail)\n if (preserveTokens > 0) {\n let tokenAccum = 0;\n for (let i = visible.length - 1; i >= 0 && tokenAccum < preserveTokens; i--) {\n result.add(visible[i]!.ref);\n tokenAccum += visible[i]!.tokens;\n }\n }\n\n // Rule 3: last visible user message. Protected whenever recent-message\n // protection is on (preserveRecentMessages > 0) — this couples it to the\n // same switch as Rule 1, so setting preserveRecentMessages = 0 fully opts\n // out (needed by tests that compress the tail). Production defaultConfig\n // uses 5, so the last user message is always protected in practice.\n if (preserveN > 0) {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role !== \"user\" || isSyntheticOrPruned(msg, state)) continue;\n const ref = state.messageRefs.byRaw[msg.id];\n if (ref && ref !== \"BLOCKED\") result.add(ref);\n break;\n }\n }\n\n return result;\n}\n\n// ─── 2. Build Compressible + Protected Ranges ────────────────────────────────\n\n/**\n * Build compressible and protected range groups from the message list.\n *\n * Messages are classified into:\n * - **compressible**: normal messages outside the protected zone\n * - **protected**: messages from protected tools (e.g., skill, task)\n * - **skipped**: covered by blocks, synthetic, or in the protected zone\n *\n * Compressible messages are grouped into contiguous ranges. The protected\n * zone (from `computeProtectedRefs`) splits groups — the unprotected head\n * survives as its own range.\n */\nexport function buildCompressibleRanges(\n messages: CoreMessage[],\n state: CompressionState,\n config: Config,\n protectedZoneRefs?: Set<string>,\n): ContextRanges {\n const compressibleMsgs: {\n ref: string;\n refNum: number;\n tokens: number;\n isTool: boolean;\n isUser: boolean;\n }[] = [];\n const protectedMsgs: {\n ref: string;\n refNum: number;\n tokens: number;\n tools: string[];\n }[] = [];\n\n // Pairing: a tool-result may carry only toolCallId (no toolName). Collect the\n // callIds of protected tool-calls first, then protect matching results too.\n const protectedCallIds = collectProtectedToolCallIds(messages, config);\n\n for (const msg of messages) {\n if (isSyntheticOrPruned(msg, state)) continue;\n const ref = state.messageRefs.byRaw[msg.id];\n if (!ref || ref === \"BLOCKED\") continue;\n\n const rn = refNum(ref);\n\n if (isMessageProtectedWithPairing(msg, config, protectedCallIds)) {\n protectedMsgs.push({\n ref,\n refNum: rn,\n tokens: estimateMessageTokens(msg),\n tools: msg.toolName ? [msg.toolName] : [],\n });\n continue;\n }\n\n if (protectedZoneRefs?.has(ref)) {\n continue;\n }\n\n compressibleMsgs.push({\n ref,\n refNum: rn,\n tokens: estimateMessageTokens(msg),\n isTool: isToolMessage(msg),\n isUser: msg.role === \"user\",\n });\n }\n\n // Build compressible groups (contiguous, split at ref gaps and at user\n // messages once a group has >= 3 messages). Splitting at user boundaries\n // keeps each compressible range aligned to roughly one user turn, instead\n // of producing one giant range spanning many turns (or, conversely, a\n // fragment per message when ref gaps appear). Mirrors opencode-acp's\n // buildCompressibleRanges condition.\n const compressible: CompressibleRange[] = [];\n let cur: CompressibleRange | null = null;\n let prevRefNum = -2;\n\n for (const info of compressibleMsgs) {\n const hasGap = info.refNum > prevRefNum + 1;\n if (cur && ((info.isUser && cur.count >= 3) || hasGap)) {\n compressible.push(cur);\n cur = null;\n }\n prevRefNum = info.refNum;\n if (!cur) {\n cur = {\n startRef: info.ref,\n endRef: info.ref,\n count: 1,\n tokens: info.tokens,\n toolPct: info.isTool ? 100 : 0,\n textPct: info.isTool ? 0 : 100,\n };\n } else {\n cur.endRef = info.ref;\n cur.count++;\n cur.tokens += info.tokens;\n if (info.isTool) {\n cur.toolPct = Math.round((cur.toolPct * (cur.count - 1) + 100) / cur.count);\n } else {\n cur.toolPct = Math.round((cur.toolPct * (cur.count - 1)) / cur.count);\n }\n cur.textPct = 100 - cur.toolPct;\n }\n }\n if (cur) compressible.push(cur);\n\n // Build protected groups (contiguous)\n const protectedRanges: ProtectedRange[] = [];\n let pcur: ProtectedRange | null = null;\n let pPrevRefNum = -2;\n\n for (const info of protectedMsgs) {\n const hasGap = info.refNum > pPrevRefNum + 1;\n if (pcur && hasGap) {\n protectedRanges.push(pcur);\n pcur = null;\n }\n pPrevRefNum = info.refNum;\n if (!pcur) {\n pcur = {\n startRef: info.ref,\n endRef: info.ref,\n count: 1,\n tokens: info.tokens,\n tools: [...info.tools],\n };\n } else {\n pcur.endRef = info.ref;\n pcur.count++;\n pcur.tokens += info.tokens;\n for (const t of info.tools) {\n if (!pcur!.tools.includes(t)) pcur!.tools.push(t);\n }\n }\n }\n if (pcur) protectedRanges.push(pcur);\n\n return {\n compressible: compressible.filter((g) => g.tokens > 0),\n protected: protectedRanges,\n };\n}\n","import type { CompressionState, CoreMessage, NudgeDecision } from \"./types.js\";\n\nexport interface PipelineContext {\n readonly config: import(\"./types.js\").Config;\n readonly tokenCount: number;\n readonly countTokens: (text: string) => number;\n}\n\nexport interface NodeEffects {\n nudge?: NudgeDecision;\n recommendation?: import(\"./types.js\").Recommendation;\n truncatedCount?: number;\n readonly [key: string]: unknown;\n}\n\nexport interface NodeIO {\n messages: CoreMessage[];\n state: CompressionState;\n effects: NodeEffects;\n}\n\nexport interface PipelineNode {\n readonly name: string;\n run(io: NodeIO, ctx: PipelineContext): NodeIO;\n enabled?: (io: NodeIO, ctx: PipelineContext) => boolean;\n}\n\nexport function makeIO(\n messages: CoreMessage[],\n state: CompressionState,\n effects: NodeEffects = {},\n): NodeIO {\n return { messages, state, effects };\n}\n\nexport function runPipeline(\n nodes: readonly PipelineNode[],\n initial: NodeIO,\n ctx: PipelineContext,\n): NodeIO {\n let io = initial;\n for (const node of nodes) {\n if (node.enabled && !node.enabled(io, ctx)) continue;\n io = node.run(io, ctx);\n }\n return io;\n}\n","import { assignRefs, highestUsedIndex } from \"./refs.js\";\nimport { prune } from \"./prune.js\";\nimport { syncBlocks } from \"./sync.js\";\nimport { advanceSurvival, activeBlocks, blockById } from \"./state.js\";\nimport {\n allocateBlockId,\n allocateRunId,\n createInitialState,\n} from \"./state.js\";\nimport { defaultCountTokens } from \"./tokenize.js\";\nimport { validateConfig } from \"./config.js\";\nimport { resolveBoundaries, earliestIndexOfIds } from \"./boundaries.js\";\nimport { truncateLargeToolOutputs } from \"./truncate-tools.js\";\nimport { hideConsumedCompressCalls } from \"./hide-consumed.js\";\nimport { applyMessageFilters, listMessageFilters } from \"./filter/index.js\";\nimport { renderRefsNode } from \"./render-refs.js\";\nimport { isMessageProtected } from \"./protected.js\";\nimport { adjustBoundariesForToolPairs } from \"./tool-pairs.js\";\nimport {\n computeProtectedRefs,\n buildCompressibleRanges,\n} from \"./recommend.js\";\nimport {\n runPipeline,\n type PipelineContext,\n type PipelineNode,\n type NodeIO,\n} from \"./pipeline.js\";\nimport type {\n ApplyCompressionResult,\n CompressionBlock,\n CompressionState,\n CompressionTier,\n Config,\n ContextBreakdown,\n CoreMessage,\n NudgeConfig,\n NudgeDecision,\n ProcessTurnResult,\n Recommendation,\n StatusReport,\n} from \"./types.js\";\n\nexport interface Ports {\n countTokens?: (text: string) => number;\n}\n\nexport interface CompressionCore {\n processTurn(input: ProcessTurnInput): ProcessTurnResult;\n applyCompression(input: ApplyCompressionInput): ApplyCompressionResult;\n defaultNodes(): PipelineNode[];\n decompress(\n blockId: string,\n state: CompressionState,\n ): CompressionBlock | undefined;\n search(query: string, state: CompressionState): CompressionBlock[];\n status(\n state: CompressionState,\n tokenCount: number,\n config: Config,\n ): StatusReport;\n}\n\nexport interface ProcessTurnInput {\n messages: CoreMessage[];\n state: CompressionState;\n config: Config;\n tokenCount: number;\n}\n\nexport interface ApplyCompressionInput {\n ranges: {\n startRef: string;\n endRef: string;\n summary: string;\n topic?: string;\n compressCallId?: string;\n summaryMaxChars?: number;\n }[];\n messages: CoreMessage[];\n state: CompressionState;\n config: Config;\n protectedMessageIds?: Set<string>;\n}\n\nexport function createCore(ports: Ports = {}): CompressionCore {\n const countTokens = ports.countTokens ?? defaultCountTokens;\n\n function applyCompression(\n input: ApplyCompressionInput,\n ): ApplyCompressionResult {\n const state: CompressionState = cloneState(input.state);\n const runId = allocateRunId(state);\n let blocksCreated = 0;\n let tokensCompressed = 0;\n const errors: string[] = [];\n\n // Default to the soft-protected zone (recent-N + last user message) when the\n // caller doesn't pass an explicit set. This makes applyCompression safe by\n // default; applySingleRange enforces it as a hard backstop.\n const protectedMessageIds =\n input.protectedMessageIds ??\n computeProtectedRefs(input.messages, input.state, input.config);\n\n const preExistingCoverage = collectCoverage(state);\n\n const rangeIndexSets: { spec: typeof input.ranges[number]; indices: number[] }[] = [];\n for (const spec of input.ranges) {\n let resolved;\n try {\n resolved = resolveBoundaries({\n startRef: spec.startRef,\n endRef: spec.endRef,\n messages: input.messages,\n state,\n });\n } catch {\n continue;\n }\n const indices = resolved.messageIds.map((id) =>\n input.messages.findIndex((m) => m.id === id),\n ).filter((i) => i >= 0);\n rangeIndexSets.push({ spec, indices });\n }\n const sortedRanges = [...rangeIndexSets].sort((a, b) => {\n const aMin = a.indices.length > 0 ? Math.min(...a.indices) : Infinity;\n const bMin = b.indices.length > 0 ? Math.min(...b.indices) : Infinity;\n return aMin - bMin;\n });\n for (let i = 1; i < sortedRanges.length; i++) {\n const prev = sortedRanges[i - 1]!;\n const curr = sortedRanges[i]!;\n const prevMax = prev.indices.length > 0 ? Math.max(...prev.indices) : -1;\n const currMin = curr.indices.length > 0 ? Math.min(...curr.indices) : -1;\n if (prevMax >= currMin && prevMax >= 0) {\n return {\n state: input.state,\n result: {\n blocksCreated: 0,\n tokensCompressed: 0,\n errors: [\n `content: range (${prev.spec.startRef}..${prev.spec.endRef}) overlaps (${curr.spec.startRef}..${curr.spec.endRef}). Overlapping ranges cannot be compressed in the same batch.`,\n ],\n },\n };\n }\n }\n\n if (input.config.compress.minCompressRange > 0 && input.ranges.length > 0) {\n let totalRangeChars = 0;\n let hasBlockBoundaryRange = false;\n for (const spec of input.ranges) {\n let resolved;\n try {\n resolved = resolveBoundaries({\n startRef: spec.startRef,\n endRef: spec.endRef,\n messages: input.messages,\n state,\n });\n } catch {\n continue;\n }\n if (resolved.boundaryKind === \"block\") {\n hasBlockBoundaryRange = true;\n continue;\n }\n for (const id of resolved.messageIds) {\n const msg = input.messages.find((m) => m.id === id);\n totalRangeChars += msg?.text?.length ?? 0;\n }\n }\n if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {\n return {\n state: input.state,\n result: {\n blocksCreated: 0,\n tokensCompressed: 0,\n errors: [\n `Total compressible content too small (${totalRangeChars} chars across ${input.ranges.length} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`,\n ],\n },\n };\n }\n }\n\n for (const spec of input.ranges) {\n try {\n const compressed = applySingleRange({\n spec,\n messages: input.messages,\n state,\n runId,\n config: input.config,\n protectedMessageIds,\n countTokens,\n preExistingCoverage,\n });\n blocksCreated++;\n tokensCompressed += compressed;\n } catch (error) {\n errors.push(error instanceof Error ? error.message : String(error));\n }\n }\n\n state.stats.compressionCount += blocksCreated;\n state.stats.tokensCompressed += tokensCompressed;\n\n if (blocksCreated > 0) {\n // Compress succeeded: clear the growth baseline so the next turn\n // re-establishes it at the new (lower) token count. Without this the\n // nudge re-fires in a feedback loop (the §5.7 baseline-reset bug).\n state.nudge.lastPerMessageNudgeTokens = 0;\n state.nudge.lastNudgeShownTokens = 0;\n // Clearing the per-tier cadence too: after a successful compression\n // (which may have consumed blocks of tier N to produce tier N+1), every\n // tier should be eligible to re-evaluate from the new token count.\n state.nudge.lastShownByTier = {};\n }\n\n return { state, result: { blocksCreated, tokensCompressed, errors } };\n }\n\n function processTurn(input: ProcessTurnInput): ProcessTurnResult {\n const configErrors = validateConfig(input.config);\n if (configErrors.length > 0) {\n console.warn(`[acp-kernel] Config validation warnings: ${configErrors.join(\"; \")}. Thresholds may not fire correctly.`);\n }\n const ctx: PipelineContext = {\n config: input.config,\n tokenCount: input.tokenCount,\n countTokens,\n };\n const initial: NodeIO = {\n messages: input.messages,\n state: input.state,\n effects: {},\n };\n const result = runPipeline(defaultNodes(), initial, ctx);\n return {\n messages: result.messages,\n state: result.state,\n nudge: result.effects.nudge,\n };\n }\n\n function decompress(blockId: string, state: CompressionState) {\n return blockById(state, blockId);\n }\n\n function search(query: string, state: CompressionState): CompressionBlock[] {\n const terms = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((term) => term.length > 0);\n if (terms.length === 0) return [];\n const scored = activeBlocks(state)\n .map((block) => ({ block, score: scoreRelevance(block, terms) }))\n .filter((entry) => entry.score > 0.1)\n .sort((left, right) => right.score - left.score);\n return scored.map((entry) => entry.block);\n }\n\n function status(\n state: CompressionState,\n tokenCount: number,\n config: Config,\n ): StatusReport {\n const active = activeBlocks(state);\n const usage =\n config.modelContextLimit > 0 ? tokenCount / config.modelContextLimit : 0;\n return {\n contextUsage: usage,\n tokenCount,\n modelContextLimit: config.modelContextLimit,\n activeBlocks: active.length,\n totalBlocks: state.blocks.length,\n tokensCompressed: state.stats.tokensCompressed,\n breakdown: { active: active.length, total: state.blocks.length },\n };\n }\n\n function defaultNodes(): PipelineNode[] {\n return [\n assignRefsNode,\n syncBlocksNode,\n pruneNode,\n filterNode,\n hideCompressCallsNode,\n recommendNode,\n nudgeNode,\n emergencyTruncateNode,\n renderRefsNode,\n ];\n }\n\n return { processTurn, applyCompression, defaultNodes, decompress, search, status };\n}\n\n// --- Pipeline nodes -------------------------------------------------------\n// Each node owns ONE concern. The ref map has a SINGLE writer (assignRefsNode);\n// tags are DERIVED at the end (renderRefsNode) — no dual source of truth, so\n// the old stripHallucinations band-aid is gone. Truncation is the LAST\n// token-reducing safety valve; render-refs is the final annotation pass.\n\nconst assignRefsNode: PipelineNode = {\n name: \"assign-refs\",\n run(io, ctx) {\n const hasProtection =\n ctx.config.protectedTools.length > 0 || !!ctx.config.isToolProtected;\n const protectedFn = hasProtection\n ? (m: CoreMessage) => isMessageProtected(m, ctx.config)\n : undefined;\n const refResult = assignRefs(io.messages, {\n existing: io.state.messageRefs,\n nextIndex: highestUsedIndex(io.state.messageRefs) + 1,\n isProtected: protectedFn,\n });\n return { ...io, state: { ...io.state, messageRefs: refResult.map } };\n },\n};\n\nconst syncBlocksNode: PipelineNode = {\n name: \"sync-blocks\",\n run(io, ctx) {\n const synced = syncBlocks(io.messages, io.state);\n advanceSurvival(synced.state, ctx.config.promotionThreshold);\n return { ...io, state: synced.state };\n },\n};\n\nconst pruneNode: PipelineNode = {\n name: \"prune\",\n run(io) {\n return { ...io, messages: prune(io.messages, io.state) };\n },\n};\n\nconst filterNode: PipelineNode = {\n name: \"filter\",\n enabled: (_io, ctx) =>\n !!ctx.config.messageFilters?.enabled && listMessageFilters().length > 0,\n run(io, ctx) {\n const applied = applyMessageFilters(io.messages, ctx.config.messageFilters);\n return { ...io, messages: applied.messages };\n },\n};\n\nconst hideCompressCallsNode: PipelineNode = {\n name: \"hide-compress-calls\",\n run(io) {\n const hidden = hideConsumedCompressCalls(io.state, io.messages);\n return { ...io, messages: hidden.messages };\n },\n};\n\nconst recommendNode: PipelineNode = {\n name: \"recommend\",\n run(io, ctx) {\n const protectedRefs = computeProtectedRefs(\n io.messages,\n io.state,\n ctx.config,\n );\n const contextRanges = buildCompressibleRanges(\n io.messages,\n io.state,\n ctx.config,\n protectedRefs,\n );\n const nothingToCompress = contextRanges.compressible.length === 0;\n const recommendation: Recommendation = {\n contextRanges,\n recommendedRanges: contextRanges.compressible,\n nothingToCompress,\n };\n return { ...io, effects: { ...io.effects, recommendation } };\n },\n};\n\nconst nudgeNode: PipelineNode = {\n name: \"nudge-inject\",\n run(io, ctx) {\n const nudge = decideNudge({\n tokenCount: ctx.tokenCount,\n config: ctx.config,\n state: io.state,\n messages: io.messages,\n recommendation: io.effects.recommendation,\n countTokens: ctx.countTokens,\n });\n\n const baseline = io.state.nudge.lastPerMessageNudgeTokens;\n const nudgeGrowthTokens = resolveAdaptiveGrowth(\n ctx.config.modelContextLimit,\n ctx.config.nudge,\n );\n\n let stamped = { ...io.state.nudge };\n\n if (\n baseline > 0 &&\n ctx.tokenCount < baseline - nudgeGrowthTokens\n ) {\n stamped.lastPerMessageNudgeTokens = ctx.tokenCount;\n stamped.lastNudgeShownTokens = 0;\n }\n\n if (stamped.lastPerMessageNudgeTokens === 0) {\n stamped.lastPerMessageNudgeTokens = ctx.tokenCount;\n }\n\n if (nudge.shouldInject) {\n stamped.lastNudgeShownTokens = ctx.tokenCount;\n // Record the injected tier's own cadence baseline. Shared baseline\n // (lastNudgeShownTokens) suppresses lower-priority tiers within this\n // turn; the per-tier entry throttles re-firing of the SAME tier.\n if (nudge.tier !== null) {\n stamped.lastShownByTier = { ...stamped.lastShownByTier, [nudge.tier]: ctx.tokenCount };\n }\n }\n\n return {\n ...io,\n state: { ...io.state, nudge: stamped },\n effects: { ...io.effects, nudge },\n };\n },\n};\n\nconst emergencyTruncateNode: PipelineNode = {\n name: \"emergency-truncate\",\n run(io, ctx) {\n const usage =\n ctx.config.modelContextLimit > 0\n ? ctx.tokenCount / ctx.config.modelContextLimit\n : 0;\n if (usage < ctx.config.truncate.threshold) return io;\n const trunc = truncateLargeToolOutputs(\n io.messages,\n ctx.tokenCount,\n ctx.config,\n ctx.countTokens,\n { protectRecentMessages: ctx.config.preserveRecentMessages },\n );\n return {\n ...io,\n messages: trunc.messages,\n effects: { ...io.effects, truncatedCount: trunc.truncatedCount },\n };\n },\n};\n\ninterface SingleRangeInput {\n spec: { startRef: string; endRef: string; summary: string; topic?: string; compressCallId?: string; summaryMaxChars?: number };\n messages: CoreMessage[];\n state: CompressionState;\n runId: string;\n config: Config;\n protectedMessageIds?: Set<string>;\n countTokens: (text: string) => number;\n preExistingCoverage: Set<string>;\n}\n\nfunction applySingleRange(input: SingleRangeInput): number {\n const resolved = resolveBoundaries({\n startRef: input.spec.startRef,\n endRef: input.spec.endRef,\n messages: input.messages,\n state: input.state,\n });\n\n const rangeMessageIds = applyToolPairAdjustment(\n resolved,\n input.messages,\n );\n\n // Re-scan for nested blocks in the ADJUSTED range (tool-pair extension may\n // have pulled in messages that are anchors of existing blocks).\n if (rangeMessageIds.length > resolved.messageIds.length) {\n const indexByRawId = new Map<string, number>();\n input.messages.forEach((m, i) => indexByRawId.set(m.id, i));\n const adjustedStart = indexByRawId.get(rangeMessageIds[0]!) ?? resolved.startIndex;\n const adjustedEnd = indexByRawId.get(rangeMessageIds[rangeMessageIds.length - 1]!) ?? resolved.endIndex;\n const nestedSeen = new Set(resolved.nestedBlockIds);\n for (const block of activeBlocks(input.state)) {\n if (nestedSeen.has(block.blockId)) continue;\n const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);\n if (anchor !== null && anchor >= adjustedStart && anchor <= adjustedEnd) {\n nestedSeen.add(block.blockId);\n resolved.nestedBlockIds.push(block.blockId);\n }\n }\n }\n\n const isBlockBoundary = resolved.boundaryKind === \"block\";\n const targetTier = resolveTargetTier(\n input.state,\n resolved.nestedBlockIds,\n isBlockBoundary,\n );\n const outputTier = isBlockBoundary\n ? (Math.min(3, targetTier + 1) as CompressionTier)\n : 1;\n\n const consumedBlockIds = resolved.nestedBlockIds.filter((id) => {\n const block = blockById(input.state, id);\n return block?.active && block.tier === targetTier;\n });\n\n const effectiveMessageIds = new Set<string>(rangeMessageIds);\n for (const consumedId of consumedBlockIds) {\n const consumed = blockById(input.state, consumedId);\n if (consumed) {\n for (const id of consumed.effectiveMessageIds)\n effectiveMessageIds.add(id);\n }\n }\n\n const directMessageIds = [...effectiveMessageIds].filter(\n (id) => !input.preExistingCoverage.has(id),\n );\n\n const filteredIds = filterProtectedToolMessages(\n directMessageIds,\n input.messages,\n input.config,\n );\n\n // HARD PROTECTION: never let the recent-N / last-user-message zone be\n // compressed, even if the model ignores the nudge and calls compress\n // directly on those refs. `protectedMessageIds` holds REF ids (mNNNNN)\n // from computeProtectedRefs; filteredIds holds RAW message ids, so convert\n // via state.messageRefs.byRaw before testing membership. applySingleRange\n // enforces this as the real backstop; the recommend/nudge path is advisory.\n const protectedRefs = input.protectedMessageIds;\n const hitProtectedRaw = protectedRefs\n ? filteredIds.filter((id) => {\n const ref = input.state.messageRefs.byRaw[id];\n return ref !== undefined && protectedRefs.has(ref);\n })\n : [];\n if (hitProtectedRaw.length > 0) {\n const recentN = input.config.preserveRecentMessages;\n const hitRefs = hitProtectedRaw\n .map((id) => input.state.messageRefs.byRaw[id])\n .filter(Boolean);\n throw new Error(\n `Range includes protected messages (the last ${recentN} messages and/or the most recent user message) which must not be compressed: ${hitRefs.join(\n \", \",\n )}. Adjust startId/endId to exclude them.`,\n );\n }\n\n validateCompressionRange(input, filteredIds, consumedBlockIds.length);\n\n let compressedTokens = 0;\n for (const id of filteredIds) {\n const message = input.messages.find((entry) => entry.id === id);\n compressedTokens += input.countTokens(message?.text ?? \"\");\n }\n for (const consumedId of consumedBlockIds) {\n const consumed = blockById(input.state, consumedId);\n if (consumed) {\n compressedTokens += input.countTokens(consumed.summary);\n }\n }\n\n const blockId = allocateBlockId(input.state);\n const block: CompressionBlock = {\n blockId,\n runId: input.runId,\n tier: outputTier,\n topic: input.spec.topic,\n summary: input.spec.summary,\n directMessageIds: filteredIds,\n effectiveMessageIds: [...effectiveMessageIds],\n directBlockIds: [...consumedBlockIds],\n compressedTokens,\n createdAt: Date.now(),\n survivedCount: 0,\n generation: \"young\",\n active: true,\n compressCallId: input.spec.compressCallId,\n };\n input.state.blocks.push(block);\n\n for (const consumedId of consumedBlockIds) {\n const consumed = blockById(input.state, consumedId);\n if (consumed) consumed.active = false;\n }\n\n return compressedTokens;\n}\n\nfunction applyToolPairAdjustment(\n resolved: { startIndex: number; endIndex: number; messageIds: string[]; boundaryKind: string },\n messages: CoreMessage[],\n): string[] {\n if (resolved.boundaryKind === \"block\") {\n return resolved.messageIds;\n }\n const adjusted = adjustBoundariesForToolPairs(\n resolved.startIndex,\n resolved.endIndex,\n messages,\n );\n if (\n adjusted.startIndex === resolved.startIndex &&\n adjusted.endIndex === resolved.endIndex\n ) {\n return resolved.messageIds;\n }\n const ids: string[] = [];\n for (let i = adjusted.startIndex; i <= adjusted.endIndex; i++) {\n const msg = messages[i];\n if (msg) ids.push(msg.id);\n }\n return ids;\n}\n\nfunction validateCompressionRange(\n input: SingleRangeInput,\n directMessageIds: string[],\n consumedBlockCount: number,\n): void {\n const cfg = input.config.compress;\n const summary = input.spec.summary?.trim() ?? \"\";\n\n if (summary.length === 0) {\n throw new Error(\n \"Summary is empty — provide a meaningful summary of the compressed range.\",\n );\n }\n\n if (cfg.minSummaryLength > 0 && summary.length < cfg.minSummaryLength) {\n throw new Error(\n `Summary too short (${summary.length} chars, min ${cfg.minSummaryLength}). The summary must capture the compressed range's key information.`,\n );\n }\n\n const effectiveMax = input.spec.summaryMaxChars ?? cfg.maxSummaryLength;\n if (\n effectiveMax > 0 &&\n summary.length > effectiveMax\n ) {\n throw new Error(\n `Summary too long (${summary.length} chars, max ${effectiveMax}). Strip noise — keep critical paths, decisions, errors, and code references. Or pass summaryMaxChars to increase the limit — don't lose critical info just to fit.`,\n );\n }\n\n if (directMessageIds.length === 0 && consumedBlockCount === 0) {\n throw new Error(\n \"Range contains no compressible messages — all are already covered by active blocks or protected.\",\n );\n }\n}\n\nfunction filterProtectedToolMessages(\n directMessageIds: string[],\n messages: CoreMessage[],\n config: Config,\n): string[] {\n // Protected tool calls (and their results, paired by toolCallId) stay in\n // visible context and are simply dropped from the compressible set. They are\n // NOT folded into the summary — the summary reflects what the author wrote,\n // nothing auto-appended.\n const protectedCallIds = new Set<string>();\n const removedIds = new Set<string>();\n for (const msg of messages) {\n if (isMessageProtected(msg, config) && msg.toolCallId) {\n protectedCallIds.add(msg.toolCallId);\n }\n }\n\n for (const id of directMessageIds) {\n const msg = messages.find((m) => m.id === id);\n if (!msg) continue;\n if (isMessageProtected(msg, config)) {\n removedIds.add(id);\n if (msg.toolCallId) protectedCallIds.add(msg.toolCallId);\n }\n }\n\n for (const id of directMessageIds) {\n if (removedIds.has(id)) continue;\n const msg = messages.find((m) => m.id === id);\n if (!msg) continue;\n if (\n msg.contentType === \"tool-result\" &&\n msg.toolCallId &&\n protectedCallIds.has(msg.toolCallId)\n ) {\n removedIds.add(id);\n }\n }\n\n return directMessageIds.filter((id) => !removedIds.has(id));\n}\n\nfunction resolveTargetTier(\n state: CompressionState,\n nestedBlockIds: string[],\n isBlockBoundary: boolean,\n): CompressionTier {\n if (!isBlockBoundary) return 1;\n if (nestedBlockIds.length === 0) return 1;\n let minTier: CompressionTier = 3;\n for (const id of nestedBlockIds) {\n const block = blockById(state, id);\n if (block && block.tier < minTier) minTier = block.tier;\n }\n return minTier;\n}\n\nfunction collectCoverage(state: CompressionState): Set<string> {\n const coverage = new Set<string>();\n for (const block of activeBlocks(state)) {\n for (const id of block.effectiveMessageIds) coverage.add(id);\n }\n return coverage;\n}\n\ninterface NudgeInput {\n tokenCount: number;\n config: Config;\n state: CompressionState;\n messages: CoreMessage[];\n recommendation?: Recommendation;\n countTokens: (t: string) => number;\n}\n\nfunction resolveAdaptiveGrowth(\n modelContextLimit: number,\n nudge: NudgeConfig,\n): number {\n if (!modelContextLimit || modelContextLimit <= 0) return nudge.growthFloor;\n return Math.min(\n nudge.growthCap,\n Math.max(\n nudge.growthFloor,\n Math.round(modelContextLimit * nudge.growthRatio),\n ),\n );\n}\n\n/** Compressible amount for each tier — all tiers use the SAME definition\n * (\"how much can be compressed at this tier\"), so they are handled by one\n * unified loop. T1 = compressible raw-message tokens (excludes protected /\n * already-covered); T2 = total summary tokens of all active tier-1 blocks;\n * T3 = total summary tokens of all active tier-2 blocks. The \"zero filter\"\n * for block tiers is simply that all blocks are compressible by default. */\nfunction pendingByTier(\n state: CompressionState,\n recommendation: Recommendation | undefined,\n countTokens: (t: string) => number,\n): Record<number, { pending: number; targetBlocks: CompressionBlock[] }> {\n const out: Record<number, { pending: number; targetBlocks: CompressionBlock[] }> = {};\n const compressible = recommendation?.contextRanges.compressible ?? [];\n out[1] = { pending: compressible.reduce((s, r) => s + r.tokens, 0), targetBlocks: [] };\n const active = activeBlocks(state);\n const t1 = active.filter((b) => b.tier === 1);\n const t2 = active.filter((b) => b.tier === 2);\n out[2] = { pending: t1.reduce((s, b) => s + countTokens(b.summary), 0), targetBlocks: t1 };\n out[3] = { pending: t2.reduce((s, b) => s + countTokens(b.summary), 0), targetBlocks: t2 };\n return out;\n}\n\nfunction decideNudge(input: NudgeInput): NudgeDecision {\n const { config, state, tokenCount, recommendation, countTokens } = input;\n const limit = config.modelContextLimit;\n const usage = limit > 0 ? tokenCount / limit : 0;\n\n const nudgeGrowthTokens = resolveAdaptiveGrowth(limit, config.nudge);\n\n const emergencyOverride = usage >= config.nudge.emergencyThresholdPct;\n\n const baseline = state.nudge.lastPerMessageNudgeTokens;\n const hadPendingNudge = state.nudge.lastNudgeShownTokens > 0;\n\n const hasPendingNudge = hadPendingNudge;\n const effectiveThreshold = hasPendingNudge\n ? Math.floor(nudgeGrowthTokens / 2)\n : nudgeGrowthTokens;\n\n const growthReference =\n state.nudge.lastNudgeShownTokens > 0\n ? state.nudge.lastNudgeShownTokens\n : baseline > 0\n ? baseline\n : tokenCount;\n\n const growthFloor = Math.max(\n config.nudge.minGrowthFloor,\n config.nudge.minGrowthRatio * nudgeGrowthTokens,\n );\n\n const growthSinceReference = tokenCount - growthReference;\n\n const rec = recommendation;\n const tiers = pendingByTier(state, rec, countTokens);\n\n // Unified injection arbitration, priority T1 > T2 > T3 (ascending). Each\n // tier has its OWN cadence (lastShownByTier) so firing one doesn't block\n // another across turns; within a turn we inject at most the FIRST eligible\n // tier and stop, which raises the shared baseline (lastNudgeShownTokens) so\n // lower-priority tiers see a higher reference and naturally defer.\n let injectedTier: CompressionTier | null = null;\n let injectedReason = \"\";\n // growth acts as the \"has accumulated since baseline\" signal; pending is the\n // \"there is enough compressible content\" signal. Both must hold for a\n // non-emergency injection. This keeps the first turn (growth 0) from firing\n // immediately even if a lot is compressible — it just establishes baseline.\n const growthReady = growthSinceReference >= growthFloor;\n if (!emergencyOverride && growthReady) {\n for (const tier of [1, 2, 3] as const) {\n if (!config.tiers.enabled && tier > 1) break;\n const info = tiers[tier];\n if (!info || info.pending < nudgeGrowthTokens) continue;\n const lastShown = state.nudge.lastShownByTier[tier] ?? 0;\n // Per-tier cadence: even with growth, a tier that fired recently waits\n // for its own cadence window. First time (lastShown===0) is always met.\n const cadenceMet = lastShown === 0 || tokenCount - lastShown >= growthFloor;\n if (!cadenceMet) continue;\n injectedTier = tier;\n injectedReason = tier === 1\n ? `T1 compressible ${info.pending} >= ${nudgeGrowthTokens}, growth ${growthSinceReference}, usage ${Math.round(usage * 100)}%`\n : `T${tier} distill ready: ${info.targetBlocks.length} tier-${tier - 1} blocks (${info.pending} tokens) >= ${nudgeGrowthTokens}, usage ${Math.round(usage * 100)}%`;\n break;\n }\n }\n\n const shouldInject = emergencyOverride || injectedTier !== null;\n\n let reason: string;\n if (emergencyOverride) {\n reason = `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}%`;\n } else if (injectedTier !== null) {\n reason = injectedReason;\n } else {\n const tiersList = [1, 2, 3] as const;\n const eligible = tiersList.filter((t) => config.tiers.enabled || t === 1);\n const ready = eligible\n .filter((t) => (tiers[t]?.pending ?? 0) >= nudgeGrowthTokens)\n .map((t) => `T${t} ${tiers[t]!.pending}`);\n const readyHint = ready.length > 0 ? `, ready: ${ready.join(\", \")}` : \"\";\n const blocked = eligible\n .filter((t) => (tiers[t]?.pending ?? 0) >= nudgeGrowthTokens && (state.nudge.lastShownByTier[t] ?? 0) > 0 && tokenCount - (state.nudge.lastShownByTier[t] ?? 0) < growthFloor)\n .map((t) => `T${t} (cadence)`);\n const blockedHint = blocked.length > 0 ? `, blocked: ${blocked.join(\", \")}` : \"\";\n const maxPending = Math.max(0, ...Object.values(tiers).map((t) => t.pending));\n // Report the ACTUAL blocking condition, not a fixed template. A session\n // can have plenty to compress (pending >= threshold) but still not\n // inject because growth/floor/cadence isn't met — the old fixed\n // \"< threshold\" string lied in that case.\n const pendingShort = maxPending < nudgeGrowthTokens;\n const growthShort = growthSinceReference < growthFloor;\n const parts: string[] = [];\n if (pendingShort) parts.push(`max compressible ${maxPending} < threshold ${nudgeGrowthTokens}`);\n if (growthShort) parts.push(`growth ${growthSinceReference} < floor ${growthFloor}`);\n if (parts.length === 0) parts.push(`max compressible ${maxPending}, growth ${growthSinceReference}`);\n reason = `${parts.join(\"; \")}${readyHint}${blockedHint}`;\n }\n\n const ctxBreakdown = computeContextBreakdown(input.messages, tokenCount, growthSinceReference);\n\n return {\n shouldInject,\n reason,\n compressibleRanges: rec?.recommendedRanges ?? [],\n protectedRanges: rec?.contextRanges.protected ?? [],\n tierTargetBlocks: injectedTier ? tiers[injectedTier]!.targetBlocks : [],\n contextUsage: usage,\n tier: injectedTier,\n breakdown: {\n usage,\n growth: growthSinceReference,\n growthReference,\n effectiveThreshold,\n nudgeGrowthTokens,\n growthFloor,\n hasPendingNudge: hasPendingNudge ? 1 : 0,\n emergencyOverride: emergencyOverride ? 1 : 0,\n pendingT1: tiers[1]!.pending,\n pendingT2: tiers[2]!.pending,\n pendingT3: tiers[3]!.pending,\n },\n contextBreakdown: ctxBreakdown,\n };\n}\n\nfunction computeContextBreakdown(messages: CoreMessage[], total: number, growth: number): ContextBreakdown {\n let system = 0, tool = 0, summaries = 0, code = 0, text = 0;\n for (const msg of messages) {\n const tokens = Math.ceil((msg.text ?? \"\").length / 4);\n if (msg.text?.startsWith(\"[Compressed conversation section]\")) {\n summaries += tokens;\n } else if (msg.contentType === \"tool-call\" || msg.contentType === \"tool-result\") {\n tool += tokens;\n } else if (msg.role === \"system\") {\n system += tokens;\n } else if (msg.text?.includes(\"```\")) {\n code += tokens;\n } else {\n text += tokens;\n }\n }\n return { system, tool, summaries, code, text, total, growth };\n}\n\nfunction cloneState(state: CompressionState): CompressionState {\n return {\n blocks: state.blocks.map((block) => ({\n ...block,\n directMessageIds: [...block.directMessageIds],\n effectiveMessageIds: [...block.effectiveMessageIds],\n directBlockIds: [...block.directBlockIds],\n })),\n messageRefs: {\n byRaw: { ...state.messageRefs.byRaw },\n byRef: { ...state.messageRefs.byRef },\n },\n nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },\n stats: { ...state.stats },\n nextBlockId: state.nextBlockId,\n nextRunId: state.nextRunId,\n };\n}\n\nfunction scoreRelevance(block: CompressionBlock, terms: string[]): number {\n const topic = (block.topic ?? \"\").toLowerCase();\n const summary = block.summary.toLowerCase();\n let score = 0;\n for (const term of terms) {\n const topicHits = countOccurrences(topic, term);\n if (topicHits > 0) score += Math.min(topicHits * 0.15, 0.45);\n const summaryHits = countOccurrences(summary, term);\n if (summaryHits > 0) score += Math.min(summaryHits * 0.04, 0.2);\n }\n return Math.min(score, 1);\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (!haystack || !needle) return 0;\n let count = 0;\n let position = 0;\n while ((position = haystack.indexOf(needle, position)) !== -1) {\n count++;\n position += needle.length;\n }\n return count;\n}\n\nexport { createInitialState };\n","/**\n * Compression rule texts — VERBATIM copy from context-compress-algorithms (MIT, ours).\n * These were tuned over months of production use.\n *\n * DO NOT modify the wording — it is the result of extensive tuning.\n */\n\nexport const COMPRESS_PHILOSOPHY = `Compression Philosophy:\n- All compression serves the primary task, but be frugal.\n- Context capacity is precious. Save context by compressing consumed outputs, not by avoiding tools.\n- Compress by need, not by percentage.\n- Work from summaries, not raw tool outputs. All listed ranges (user prompts, tool outputs, code, logs, exploration, intermediate steps) should be compressed to summary format — the ONLY exceptions are protected content, content the current step is actively using, or critical content you cannot reconstruct.\n- Curate summaries like a well-structured document. User prompts, compressed tool outputs, code, logs, or skill-call intermediate results that are critically important should be preserved — not by exempting them from compression, but by embedding them in the summary via [[KEEP:mNNNNN]] (auto-expanded verbatim) and [[REF:mNNNNN|description]] (compact link).`;\n\nexport const HOW_TO_COMPRESS_RULES = `HOW TO COMPRESS\n\nWhen you call \\`compress\\`, the summary you write becomes the only record of the replaced conversation. Make it self-contained and complete: every user request, experiment purpose, and work task in the range must be accurately captured. A later reader (or you, after decompressing) should be able to continue the task WITHOUT needing the original.\n\nKEEP VERBATIM — never paraphrase or abbreviate these:\n- Full file paths with line numbers, directory prefix on every mention (\\`lib/hooks.ts:347\\`, \\`src/index.ts:12-18\\`, \\`gatenet_v3/model.py:45\\`). Never abbreviate to a bare filename (\\`hooks.ts\\`, \\`model.py\\`) — they are ambiguous and cannot be grepped or decompressed-to later.\n- Function, class, and type signatures (exact names, params, return types) AND critical code lines that encode logic — the line that IS the finding, not just the function name (e.g. \\`kv_keys += define_gate * a_key[i](emb)\\` is more useful than \"see model_kvnet.py\").\n- Error messages and stack traces (exact text — you need the literal string to grep for it later).\n- Key details from reports and analyses — not just the conclusion. Keep the comparison numbers and the mechanism, not \"X is worse\" alone (write \"1.76× PPL gap because KV store is static\", not \"KVNet underperforms\").\n- Decisions and their rationale (\"chose X over Y because Z\" — the \"because\" is load-bearing; without it the decision looks arbitrary).\n- Constraints discovered (\"must support Node 22\", \"no new dependencies\", \"AGENTS.md forbids \\`as any\\`\").\n- Exact values: versions, config keys, thresholds, magic numbers.\n- User intent — quote short user messages verbatim. When the message is too long to quote, preserve intent with extra care: do not change scope, constraints, priorities, acceptance criteria, or requested outcomes. Mark them clearly as past quotes (e.g., \"User said: ...\"), not as current directives. Losing these changes the task itself.\n- The user's overall goal and any changes to it — the big-picture objective plus how it evolved during the compressed range. Each summary must reflect the goal as it stood at the end of the range, including pivots (e.g., \"initially: fix bug X → pivoted to: refactor module Y after discovering root cause\"). Losing the goal or its evolution makes all subsequent work appear unmotivated.\n- Purpose behind each significant action — preserve not just what was done but why: the hypothesis behind each experiment, the question behind each exploration, the task goal behind each work action. Without purpose, the summary reads as disconnected technical steps with no through-line.\n- Open questions and unresolved TODOs — losing these changes what work appears to remain.\n- Message refs of key anchors (\\`m00420\\`, \\`m00510–m00520\\`) — they let you or a later reader jump back via decompress to the exact original.\n\nDROP — extract the signal, discard the vessel:\n- Verbose logs (build/test/\\`npm\\` output) once you have captured the error line or the result.\n- Duplicate file reads once the needed content is recorded.\n- Consumed exploration — search hits, agent return values, successful tool outputs — once you have extracted the facts you need (same rule as dead-ends, but nothing went wrong; the content is simply spent).\n- Dead-end exploration — but PRESERVE the lesson in one line: \"tried X, failed because Y\".\n- Back-and-forth discussion and self-corrections once the final position is captured (keep the outcome, drop the journey to it).\n- Repeated status checks (\\`git status\\`, \\`ls\\`) once state is known.\n\nFor each significant item you DROP (scripts, reports, large analyses, long tool outputs), add a one-line CONTENT description of what it covers — not where it lives. Bad: \"probe script at /path/probe_kvnet.py\". Good: \"probe_kvnet.py: tests n-gram baseline, generation quality, long-range dependency, position sensitivity, op pipeline, QUERY attention.\" This lets a later decompress target the right block by relevance, not by guessing locations.\n\nKEEP MARKERS: \\`[[KEEP:mNNNNN]]\\` expands original message content into the summary (truncated to a max length). Do NOT use KEEP for verbose command output, diagnostic scripts, log dumps, or any content whose value is in the conclusion rather than the raw output — summarize these or use \\`[[REF:mNNNNN|desc]\\` instead.\n\nPRIORITY — when the summary must be compact, preserve in this order:\n1. User's overall goal, goal evolution, intent, and hard constraints (losing these changes the task).\n2. Decisions and rationale.\n3. Exact technical artifacts: paths, signatures, errors, values.\n4. Conclusions and key findings.\n5. Lessons learned: what failed and why.\n\nWrite dense, scannable bullets — not narrative prose. If the range spans distinct concerns (request → findings → decision), group bullets under short thematic headers so a reader can scan to the part they need. Every line must earn its place. Do not mimic the style of existing summaries in context; follow these rules.`;\n\nexport const TIER2_DISTILL_RULES = `TIER 2 COMPRESSION — DISTILLATION\n\nYou are compressing historical summaries (not raw conversation). These summaries have already captured the details. Your job is to DISTILL them: extract only what matters for future work, discard the process.\n\nKEEP — these are the only things that survive distillation:\n- Decisions and their rationale (\"chose X over Y because Z\" — the \"because\" is load-bearing).\n- Final outcomes: version numbers shipped, PR numbers merged/closed, bugs fixed or deferred.\n- Key lessons: what failed and why (\"tried X, failed because Y\"). These prevent repeating mistakes.\n- Critical constraints discovered (\"must support Node 22\", \"AGENTS.md forbids as any\").\n- Design decisions with architectural impact (\"chose compress-as-anchor over synthetic messages because prefix cache\").\n- Whether content is OBSOLETE or SUPERSEDED — mark with one line: \"[SUPERSEDED by PR #NNN]\" or \"[OBSOLETE: deleted in vX.Y.Z]\". Do NOT keep the obsolete content's details — just the marker and reason.\n- Function/class/type names and module paths that are the SUBJECT of the work — e.g., \"fixed filterCompressedRanges in prune.ts\", \"added SessionStateRegistry in state.ts\". Not exact line numbers or full signatures — just enough to LOCATE the code without searching.\n- Exploration findings: if a block was exploratory with no decision, keep the CONCLUSION in one line (\"explored X, not viable because Y\"). Do not keep the exploration process.\n\nDROP — these were useful during the work but are no longer needed:\n- Exact line numbers, diffs, verbose function signatures, full code listings.\n- Build/deploy process details, test execution steps.\n- Review process details (who reviewed, what rounds, test counts).\n- Verbose logs, command output, intermediate debugging steps.\n\nFORMAT:\n- Start each distilled block with a source header line:\n \\`Source: bN+bM+... (XK→YK tok, Zx). [original topic]\\`\n Example: \\`Source: b5+b7 (56K+44K→268 tok, 375x). [Tool-result recap + publish]\\`\n- 3-5 bullet points per source block, each a self-contained fact.\n- Dense, scannable — no narrative prose.\n- Start with the outcome, not the process: \"v1.13.0 shipped (7 PRs bundled)\" not \"implemented 7 PRs then reviewed then merged\".\n- Cross-block synthesis: if multiple source blocks cover the same topic (same PR, same feature, same bug), MERGE them into a single group of bullets. Do not repeat the same fact from different blocks — keep it once under the most relevant source header.\n\nSIZE TARGET: 50-150 tokens per source block (excluding the header). If you can't fit it in 150 tokens, you're keeping too much process. If a block has nothing worth keeping (pure noise), output just the header followed by \"[no actionable content].\"`;\n\nexport const TIER3_CONDENSE_RULES = `TIER 3 COMPRESSION — ULTRA-CONDENSATION\n\nYou are compressing distilled summaries (Tier 2) into ultra-condensed facts (Tier 3). The distilled summaries already contain only decisions and outcomes. Your job is to reduce them to bare factual references.\n\nPRIORITY — when a source block has more facts than the size target allows, keep in this order:\n1. Shipped outcomes (versions released, PRs merged) — these are permanent record.\n2. Open work (PRs/issues still pending) — these may need follow-up.\n3. Key decisions with architectural impact (\"chose X over Y because Z\").\n4. Critical constraints (\"must support Node 22\").\nDrop everything else. Tier 3 is a lookup index, not a knowledge base.\n\nFORMAT:\n- Start with a source header line:\n \\`Source: bN+bM+... (XK→YK tok, Zx). [original topic]\\`\n- Output 1-3 facts per source block. Each fact is a single line: subject + outcome.\n- No explanations, no rationale, no process — just the fact.\n- Format: \"[PR/Issue/Version] — [outcome in ≤8 words]\"\n- Merge related facts from different source blocks if they concern the same topic.\n\nEXAMPLES:\n- \"v1.13.0 shipped — quality gate + GC fix (7 PRs)\"\n- \"PR #196 merged — preserve-first-user (supersedes #169)\"\n- \"Bug 1214 fixed — compress consumed all user messages\"\n- \"Chose compress-as-anchor — prefix cache benefit over synthetic injection\"\n- \"Constraint: AGENTS.md forbids as any — never suppress types\"\n\nDROP:\n- Multi-sentence context. If a fact needs >1 sentence, it's too detailed for Tier 3.\n- Lessons learned (\"tried X, failed because Y\") — drop UNLESS the failure is likely to recur and the block is <30 days old.\n- Design rationale details — keep the decision, drop the \"because\" unless it's a critical constraint.\n- Anything marked [OBSOLETE] or [SUPERSEDED] — drop entirely, note \"[N blocks obsolete]\" in the summary.\n\nSIZE TARGET: 30-60 tokens per source block (including header). For a batch of N source blocks, total output ≈ N × 40 tokens. If a source block has only one trivial fact, output just the header + one line.`;\n","import type { NudgeDecision, CompressibleRange, ProtectedRange, ContextBreakdown, CompressionBlock } from \"./types.js\";\nimport { COMPRESS_PHILOSOPHY, HOW_TO_COMPRESS_RULES, TIER2_DISTILL_RULES, TIER3_CONDENSE_RULES } from \"./compression-rules.js\";\n\nexport type NudgeVoice = \"gentle\" | \"emergency\";\n\nexport interface RenderedNudge {\n voice: NudgeVoice;\n text: string;\n}\n\nconst EFFICIENCY_NOTE = `This is an efficiency nudge to compress early and keep context lean — not an overflow warning. A separate, stronger alert will appear if the context is actually full.\\n\\n${COMPRESS_PHILOSOPHY}`;\n\nconst EMERGENCY_HEADER = `⚠️ Context limit reached — compress now. Prioritize consumed tool outputs.\\n\\n${COMPRESS_PHILOSOPHY}`;\n\nfunction formatK(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;\n return `${n}`;\n}\n\nfunction formatBreakdown(bd?: ContextBreakdown): string {\n if (!bd) return \"\";\n const parts: string[] = [];\n if (bd.system > 0) parts.push(`${formatK(bd.system)} system`);\n if (bd.tool > 0) parts.push(`${formatK(bd.tool)} tool`);\n if (bd.summaries > 0) parts.push(`${formatK(bd.summaries)} summaries`);\n if (bd.code > 0) parts.push(`${formatK(bd.code)} code`);\n if (bd.text > 0) parts.push(`${formatK(bd.text)} text`);\n const growth = bd.growth > 0 ? `\\n+${formatK(bd.growth)} since last nudge` : \"\";\n return `Context breakdown: ${parts.join(\" | \")}${growth}`;\n}\n\n\n\nfunction formatTierTargetBlocks(blocks: CompressionBlock[]): string {\n if (blocks.length === 0) {\n return \"Target blocks: (none — no tier blocks found)\";\n }\n const lines = blocks.map((b) => {\n const summaryTokens = Math.ceil((b.summary ?? \"\").length / 4);\n const topic = b.topic ? ` \"${b.topic}\"` : \"\";\n return ` ${b.blockId} ${b.effectiveMessageIds.length} msgs ${formatK(b.compressedTokens)}→${formatK(summaryTokens)}${topic}`;\n });\n return `Target ${blocks[0]!.tier === 1 ? \"tier-1\" : \"tier-2\"} blocks to distill (${blocks.length}):\\n${lines.join(\"\\n\")}`;\n}\n\nexport function formatRanges(compressible: CompressibleRange[], protectedRanges: ProtectedRange[]): string {\n if (compressible.length === 0 && protectedRanges.length === 0) {\n return \"[No specific ranges detected — compress any consumed content.]\";\n }\n\n // Merge compressible + protected into a single oldest-first list, mirroring\n // opencode-acp's formatCompressibleRanges. Splitting them into two sections\n // lost the time order and hid overlaps; a range can be partly compressible\n // and partly protected, which only the merged view shows correctly.\n interface Merged {\n startRef: string; endRef: string; startNum: number; endNum: number;\n count: number; tokens: number;\n compressibleTokens: number; compressibleCount: number;\n protectedTokens: number; protectedCount: number; protectedTools: string[];\n toolPct: number; textPct: number; dangerous: boolean;\n }\n const refNum = (ref: string): number => {\n const m = ref.match(/\\d+/);\n return m ? parseInt(m[0], 10) : 0;\n };\n const entries: Merged[] = [];\n for (const r of compressible) {\n entries.push({\n startRef: r.startRef, endRef: r.endRef, startNum: refNum(r.startRef), endNum: refNum(r.endRef),\n count: r.count, tokens: r.tokens, toolPct: r.toolPct, textPct: r.textPct,\n compressibleTokens: r.tokens, compressibleCount: r.count,\n protectedTokens: 0, protectedCount: 0, protectedTools: [], dangerous: r.dangerous ?? false,\n });\n }\n for (const r of protectedRanges) {\n entries.push({\n startRef: r.startRef, endRef: r.endRef, startNum: refNum(r.startRef), endNum: refNum(r.endRef),\n count: r.count, tokens: r.tokens, toolPct: 0, textPct: 0,\n compressibleTokens: 0, compressibleCount: 0,\n protectedTokens: r.tokens, protectedCount: r.count, protectedTools: [...r.tools], dangerous: false,\n });\n }\n entries.sort((a, b) => a.startNum - b.startNum);\n // Merge adjacent/overlapping ranges (gap ≤ 1 ref).\n const merged: Merged[] = [];\n for (const e of entries) {\n const last = merged[merged.length - 1];\n if (last && e.startNum <= last.endNum + 1) {\n last.endRef = e.endRef;\n last.endNum = Math.max(last.endNum, e.endNum);\n last.count += e.count;\n last.tokens += e.tokens;\n last.compressibleTokens += e.compressibleTokens;\n last.compressibleCount += e.compressibleCount;\n last.protectedTokens += e.protectedTokens;\n last.protectedCount += e.protectedCount;\n if (e.dangerous) last.dangerous = true;\n for (const t of e.protectedTools) {\n if (!last.protectedTools.includes(t)) last.protectedTools.push(t);\n }\n } else {\n merged.push({ ...e });\n }\n }\n const lines = merged.map((e) => {\n const suffix = e.dangerous && e.compressibleTokens > 0 ? \" ⚠️ NOT recommended unless you are certain.\" : \"\";\n if (e.protectedTokens > 0 && e.compressibleTokens === 0) {\n return ` ${e.startRef}–${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [PROTECTED: ${e.protectedTools.join(\", \")} — not compressible]${suffix}`;\n }\n if (e.protectedTokens > 0 && e.compressibleTokens > 0) {\n return ` ${e.startRef}–${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [${formatK(e.compressibleTokens)} compressible | ${formatK(e.protectedTokens)} protected: ${e.protectedTools.join(\", \")}]${suffix}`;\n }\n return ` ${e.startRef}–${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [tool ${e.toolPct}% | text ${e.textPct}%]${suffix}`;\n });\n return `Compressible ranges (${merged.length}, oldest first):\\n${lines.join(\"\\n\")}`;\n}\n\nexport function renderNudgeText(decision: NudgeDecision): RenderedNudge {\n const breakdownStr = formatBreakdown(decision.contextBreakdown);\n const rangesStr = formatRanges(decision.compressibleRanges, decision.protectedRanges ?? []);\n\n if (decision.tier !== null && decision.tier >= 2) {\n const isT2 = decision.tier === 2;\n const targets = decision.tierTargetBlocks ?? [];\n const blockList = formatTierTargetBlocks(targets);\n const startId = targets[0]?.blockId ?? \"b1\";\n const endId = targets[targets.length - 1]?.blockId ?? \"b5\";\n return {\n voice: \"gentle\",\n text: [\n EFFICIENCY_NOTE,\n \"\",\n breakdownStr,\n \"\",\n `[TIER ${decision.tier} ${isT2 ? \"DISTILLATION\" : \"CONDENSATION\"} TRIGGER]`,\n isT2\n ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries.`\n : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries.`,\n blockList,\n `Example: compress({ content: [{ startId: \"${startId}\", endId: \"${endId}\", summary: \"...\" }] })`,\n \"\",\n HOW_TO_COMPRESS_RULES,\n \"\",\n isT2 ? TIER2_DISTILL_RULES : TIER3_CONDENSE_RULES,\n ].join(\"\\n\"),\n };\n }\n\n const isEmergency = !!decision.breakdown?.emergencyOverride;\n\n if (isEmergency) {\n return {\n voice: \"emergency\",\n text: [\n EMERGENCY_HEADER,\n \"\",\n breakdownStr,\n \"\",\n HOW_TO_COMPRESS_RULES,\n \"\",\n `{ \"topic\": \"...\", \"content\": [{ \"startId\": \"<ID>\", \"endId\": \"<ID>\", \"summary\": \"...\" }] }`,\n \"Only use IDs from visible messages above. Compress older work first.\",\n \"\",\n rangesStr,\n ].join(\"\\n\"),\n };\n }\n\n return {\n voice: \"gentle\",\n text: [\n EFFICIENCY_NOTE,\n \"\",\n breakdownStr,\n \"\",\n HOW_TO_COMPRESS_RULES,\n \"\",\n rangesStr,\n \"\",\n `💡 Compress all ranges in one call (pass multiple content entries: \\`content: [{...}, {...}]\\`).`,\n ].join(\"\\n\"),\n };\n}\n","import { refForRaw } from \"./refs.js\";\nimport type { CompressionState, CoreMessage } from \"./types.js\";\n\nconst KEEP_REGEX = /\\[\\[KEEP:(m\\d+)\\]\\]/g;\nconst REF_REGEX = /\\[\\[REF:(m\\d+)\\|([^\\]]+)\\]\\]/g;\n\nexport interface KeepMarkerResult {\n summary: string;\n expandedCount: number;\n refCount: number;\n unresolvedRefs: string[];\n}\n\nexport function resolveKeepMarkers(\n summary: string,\n messages: CoreMessage[],\n state: CompressionState,\n maxChars = 2000,\n): KeepMarkerResult {\n const messageByRef = new Map<string, CoreMessage>();\n for (const message of messages) {\n const ref = refForRaw(state.messageRefs, message.id);\n if (ref) messageByRef.set(ref, message);\n }\n\n let expandedCount = 0;\n let refCount = 0;\n const unresolvedRefs: string[] = [];\n\n const expanded = summary\n .replace(KEEP_REGEX, (match, ref: string) => {\n const normalized = normalizeRef(ref);\n const message = normalized ? messageByRef.get(normalized) : undefined;\n if (!message) {\n unresolvedRefs.push(ref);\n return match;\n }\n expandedCount++;\n return formatKeptMessage(message, normalized!, maxChars);\n })\n .replace(REF_REGEX, (_match, ref: string, desc: string) => {\n const normalized = normalizeRef(ref);\n const message = normalized ? messageByRef.get(normalized) : undefined;\n if (!message) {\n unresolvedRefs.push(ref);\n return _match;\n }\n refCount++;\n return `[→ ${normalized}: ${desc.trim()}]`;\n });\n\n return { summary: expanded, expandedCount, refCount, unresolvedRefs };\n}\n\nfunction normalizeRef(ref: string): string | null {\n const match = /^m0*(\\d{1,5})$/.exec(ref.trim().toLowerCase());\n if (!match || match[1] === undefined) return null;\n return `m${match[1].padStart(5, \"0\")}`;\n}\n\nfunction formatKeptMessage(message: CoreMessage, ref: string, maxChars: number): string {\n const label = labelFor(message);\n const body = truncate(message.text ?? \"[empty message]\", maxChars);\n return `\\n--- [${ref}: ${label}] ---\\n${body}\\n--- end ---\\n`;\n}\n\nfunction labelFor(message: CoreMessage): string {\n if (message.contentType === \"tool-call\" || message.contentType === \"tool-result\") {\n return message.toolName ?? \"tool\";\n }\n return message.role;\n}\n\nfunction truncate(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars) + `\\n... [truncated, ${text.length} chars total]`;\n}\n","import type { CompressionBlock, CompressionState, CoreMessage } from \"./types.js\";\n\nexport function parseBlockIdArg(arg: string): string | null {\n const normalized = arg.trim().toLowerCase();\n const refMatch = /^b0*(\\d+)$/.exec(normalized);\n if (refMatch && refMatch[1] !== undefined) return `b${refMatch[1]}`;\n const numMatch = /^(\\d+)$/.exec(normalized);\n if (numMatch && numMatch[1] !== undefined) return `b${numMatch[1]}`;\n return null;\n}\n\nexport function findBlocksOverlappingMessages(\n state: CompressionState,\n messageIds: Set<string>,\n): CompressionBlock[] {\n if (messageIds.size === 0) return [];\n const matched: CompressionBlock[] = [];\n for (const block of state.blocks) {\n if (!block.active) continue;\n if (block.effectiveMessageIds.some((id) => messageIds.has(id))) {\n matched.push(block);\n }\n }\n return matched.sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));\n}\n\nexport function findActiveAncestor(state: CompressionState, blockId: string): string | null {\n const start = state.blocks.find((b) => b.blockId === blockId);\n if (!start) return null;\n const queue: string[] = [...start.directBlockIds];\n const visited = new Set<string>();\n while (queue.length > 0) {\n const currentId = queue.shift()!;\n if (visited.has(currentId)) continue;\n visited.add(currentId);\n const current = state.blocks.find((b) => b.blockId === currentId);\n if (!current) continue;\n if (current.active) return current.blockId;\n for (const ancestorId of current.directBlockIds) {\n if (!visited.has(ancestorId)) queue.push(ancestorId);\n }\n }\n return null;\n}\n\nexport interface DeactivateOptions {\n deep?: boolean;\n}\n\nexport function deactivateBlock(\n state: CompressionState,\n blockIds: string[],\n options: DeactivateOptions = {},\n): CompressionState {\n const targets = new Set(blockIds);\n\n const updated = state.blocks.map((block) => {\n if (!targets.has(block.blockId) || !block.active) return block;\n return {\n ...block,\n active: false,\n durationMs: block.durationMs,\n createdAt: block.createdAt,\n };\n });\n\n let final = updated;\n if (options.deep) {\n const visited = new Set<string>();\n const queue: string[] = [];\n for (const id of blockIds) {\n const block = updated.find((b) => b.blockId === id);\n if (block) queue.push(...block.directBlockIds);\n }\n while (queue.length > 0) {\n const id = queue.shift()!;\n if (visited.has(id)) continue;\n visited.add(id);\n final = final.map((block) => {\n if (block.blockId !== id) return block;\n queue.push(...block.directBlockIds);\n return block.active ? { ...block, active: false } : block;\n });\n }\n }\n\n return { ...state, blocks: final };\n}\n\nexport interface RestoredPreviewResult {\n preview: string;\n restoredCount: number;\n}\n\nexport function buildRestoredContentPreview(\n messages: CoreMessage[],\n beforeActiveMessageIds: Set<string>,\n state: CompressionState,\n): RestoredPreviewResult {\n const restored: CoreMessage[] = [];\n for (const message of messages) {\n if (!beforeActiveMessageIds.has(message.id)) continue;\n const stillCovered = state.blocks.some(\n (b) => b.active && b.effectiveMessageIds.includes(message.id),\n );\n if (!stillCovered) restored.push(message);\n }\n\n if (restored.length === 0) return { preview: \"\", restoredCount: 0 };\n\n const lines: string[] = [];\n let totalLength = 0;\n const MAX_PREVIEW = 2000;\n const MAX_PER_MESSAGE = 200;\n\n for (const message of restored) {\n if (totalLength >= MAX_PREVIEW) break;\n const text = message.text ?? \"\";\n const truncated = text.length > MAX_PER_MESSAGE ? text.slice(0, MAX_PER_MESSAGE) + \"...\" : text;\n const label =\n message.toolName && message.contentType !== \"text\"\n ? `${message.toolName}: ${truncated}`\n : `[${message.role}] ${truncated}`;\n lines.push(label);\n totalLength += label.length + 1;\n }\n\n return { preview: lines.join(\"\\n\"), restoredCount: restored.length };\n}\n\nfunction numericPart(blockId: string): number {\n const match = /^b(\\d+)$/.exec(blockId);\n return match && match[1] !== undefined ? Number(match[1]) : 0;\n}\n","import { refForRaw } from \"./refs.js\";\nimport type { CompressionBlock, CompressionState, CoreMessage } from \"./types.js\";\n\nfunction formatTokens(n: number): string {\n if (!Number.isFinite(n) || n <= 0) return \"0\";\n return n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);\n}\n\nfunction pct(n: number, total: number): number {\n if (n <= 0 || total <= 0) return 0;\n return Math.max(1, Math.round((n / total) * 100));\n}\n\nfunction numericPart(blockId: string): number {\n const match = /^b(\\d+)$/.exec(blockId);\n return match && match[1] !== undefined ? Number(match[1]) : 0;\n}\n\nfunction summaryTokensOf(block: CompressionBlock, countTokens: (t: string) => number): number {\n return countTokens(block.summary);\n}\n\nfunction effectiveCompressedTokens(\n block: CompressionBlock,\n state: CompressionState,\n countTokens: (t: string) => number,\n visited: Set<string> = new Set(),\n): number {\n if (visited.has(block.blockId)) return 0;\n visited.add(block.blockId);\n let total = block.compressedTokens;\n for (const nestedId of block.directBlockIds) {\n const nested = state.blocks.find((b) => b.blockId === nestedId);\n if (nested) total += effectiveCompressedTokens(nested, state, countTokens, visited);\n }\n return total;\n}\n\nfunction tierLabel(block: CompressionBlock): string {\n return `T${block.tier}`;\n}\n\nfunction tierBreakdown(\n blocks: CompressionBlock[],\n countTokens: (t: string) => number,\n): string | null {\n const tierTokens: Record<number, number> = {};\n for (const block of blocks) {\n tierTokens[block.tier] = (tierTokens[block.tier] ?? 0) + summaryTokensOf(block, countTokens);\n }\n const tiers = Object.keys(tierTokens).map(Number);\n if (tiers.length <= 1) return null;\n const parts: string[] = [];\n for (const tier of [1, 2, 3]) {\n if (tierTokens[tier]) parts.push(`T${tier}: ${formatTokens(tierTokens[tier])}`);\n }\n return parts.join(\" | \");\n}\n\ninterface VisibleMessageInfo {\n ref: string;\n tokens: number;\n tool: string;\n index: number;\n}\n\nfunction collectVisible(\n messages: CoreMessage[],\n state: CompressionState,\n countTokens: (t: string) => number,\n): { visible: VisibleMessageInfo[]; summaryTokens: number } {\n const coveredIds = new Set<string>();\n for (const block of state.blocks) {\n if (!block.active) continue;\n for (const id of block.effectiveMessageIds) coveredIds.add(id);\n }\n let summaryTokens = 0;\n for (const block of state.blocks) {\n if (block.active) summaryTokens += summaryTokensOf(block, countTokens);\n }\n const visible: VisibleMessageInfo[] = [];\n messages.forEach((message, index) => {\n if (coveredIds.has(message.id)) return;\n const ref = refForRaw(state.messageRefs, message.id);\n if (!ref) return;\n const tokens = countTokens(message.text ?? \"\");\n const tool = message.toolName ?? \"text\";\n if (tokens > 0) visible.push({ ref, tokens, tool, index });\n });\n return { visible, summaryTokens };\n}\n\nexport interface StatusReportOptions {\n scope?: \"compressed\" | \"uncompressed\";\n view?: \"ranges\" | \"messages\";\n tool?: string;\n sort?: \"size\" | \"time\" | \"tool\" | \"age\";\n limit?: number;\n}\n\nexport function buildStatusReport(\n state: CompressionState,\n messages: CoreMessage[],\n countTokens: (t: string) => number,\n options: StatusReportOptions = {},\n): string {\n const scope = options.scope;\n const view = options.view ?? \"ranges\";\n const toolFilter = options.tool;\n const sort = options.sort ?? \"size\";\n const limit = options.limit ?? 30;\n\n const activeBlocks = state.blocks\n .filter((b) => b.active)\n .sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));\n\n if (scope === \"compressed\") {\n return renderCompressedDrilldown(activeBlocks, state, sort, limit, countTokens);\n }\n\n const { visible, summaryTokens } = collectVisible(messages, state, countTokens);\n\n if (scope === \"uncompressed\") {\n if (view === \"messages\") {\n return renderMessageDrilldown(visible, toolFilter, sort, limit);\n }\n return renderUncompressedRanges(visible);\n }\n\n return renderOverview(visible, summaryTokens, activeBlocks, state, countTokens, limit);\n}\n\nfunction renderOverview(\n visible: VisibleMessageInfo[],\n summaryTokens: number,\n blocks: CompressionBlock[],\n state: CompressionState,\n countTokens: (t: string) => number,\n limit: number,\n): string {\n const lines: string[] = [];\n const toolTypeMap = new Map<string, number>();\n for (const message of visible) {\n toolTypeMap.set(message.tool, (toolTypeMap.get(message.tool) ?? 0) + message.tokens);\n }\n const topTool = [...toolTypeMap.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];\n\n const totalTool = visible\n .filter((m) => m.tool !== \"text\")\n .reduce((sum, m) => sum + m.tokens, 0);\n const totalText = visible\n .filter((m) => m.tool === \"text\")\n .reduce((sum, m) => sum + m.tokens, 0);\n const total = summaryTokens + totalTool + totalText;\n\n lines.push(\"CONTEXT BREAKDOWN\");\n lines.push(\n ` ${formatTokens(totalTool)} tool (${pct(totalTool, total)}%) | ${formatTokens(totalText)} text (${pct(totalText, total)}%) | ${formatTokens(summaryTokens)} summaries (${pct(summaryTokens, total)}%)`,\n );\n const topTypes = [...toolTypeMap.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3);\n if (topTypes.length > 0) {\n lines.push(` Top tools: ${topTypes.map(([t, n]) => `${t} (${pct(n, total)}%)`).join(\", \")}`);\n }\n\n lines.push(\"\");\n if (blocks.length === 0) {\n lines.push(\"COMPRESSED BLOCKS\");\n lines.push(\" No compressed blocks.\");\n } else {\n const totalSummary = blocks.reduce((s, b) => s + summaryTokensOf(b, countTokens), 0);\n const totalEffective = blocks.reduce(\n (s, b) => s + effectiveCompressedTokens(b, state, countTokens),\n 0,\n );\n lines.push(\n `COMPRESSED BLOCKS — ${blocks.length} active (${formatTokens(totalSummary)} summary, ${formatTokens(totalEffective)} original)`,\n );\n const breakdown = tierBreakdown(blocks, countTokens);\n if (breakdown) lines.push(` Tier usage: ${breakdown}`);\n lines.push(\"\");\n const sorted = [...blocks].sort(\n (a, b) =>\n effectiveCompressedTokens(b, state, countTokens) -\n effectiveCompressedTokens(a, state, countTokens) ||\n b.createdAt - a.createdAt,\n );\n for (const block of sorted.slice(0, limit)) {\n const topic = block.topic ?? \"(no topic)\";\n const eff = effectiveCompressedTokens(block, state, countTokens);\n lines.push(\n ` ${block.blockId} (${tierLabel(block)}) ${formatTokens(eff)}→${formatTokens(summaryTokensOf(block, countTokens))} ${block.effectiveMessageIds.length} msgs \"${topic}\"`,\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\n `Tip: buildStatusReport({scope:\"uncompressed\", view:\"messages\", tool:\"${topTool ?? \"bash\"}\"}) for per-message listing`,\n );\n return lines.join(\"\\n\");\n}\n\nfunction renderUncompressedRanges(visible: VisibleMessageInfo[]): string {\n const lines: string[] = [];\n const totalTokens = visible.reduce((s, m) => s + m.tokens, 0);\n lines.push(`UNCOMPRESSED — ${formatTokens(totalTokens)} | ${visible.length} visible messages`);\n lines.push(\"\");\n if (visible.length === 0) {\n lines.push(\" (no uncompressed messages)\");\n return lines.join(\"\\n\");\n }\n // Merge consecutive messages into ranges (by numeric ref), aggregating\n // token counts and dominant tool so the view reads as blocks, not a\n // per-message firehose — mirroring the Compressible Ranges output.\n interface Merged { startRef: string; endRef: string; startNum: number; count: number; tokens: number; tool: string; }\n const refNum = (ref: string): number => {\n const m = ref.match(/\\d+/);\n return m ? parseInt(m[0], 10) : 0;\n };\n const merged: Merged[] = [];\n for (const m of visible) {\n const num = refNum(m.ref);\n const last = merged[merged.length - 1];\n if (last && num === last.startNum + last.count) {\n last.endRef = m.ref;\n last.count += 1;\n last.tokens += m.tokens;\n } else {\n merged.push({ startRef: m.ref, endRef: m.ref, startNum: num, count: 1, tokens: m.tokens, tool: m.tool });\n }\n }\n for (const r of merged.slice(0, 30)) {\n const range = r.count === 1 ? r.startRef : `${r.startRef}–${r.endRef}`;\n lines.push(` ${range} (${r.count} msgs, ${formatTokens(r.tokens)}${r.count > 1 ? ` (${Math.round(r.tokens / r.count)}/msg)` : \"\"}) ${r.tool}`);\n }\n if (merged.length > 30) {\n lines.push(` ... and ${merged.length - 30} more ranges`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderMessageDrilldown(\n visible: VisibleMessageInfo[],\n toolFilter: string | undefined,\n sort: string,\n limit: number,\n): string {\n let filtered = visible;\n if (toolFilter) filtered = filtered.filter((m) => m.tool === toolFilter);\n\n if (sort === \"time\") filtered.sort((a, b) => a.index - b.index);\n else if (sort === \"tool\") filtered.sort((a, b) => a.tool.localeCompare(b.tool) || b.tokens - a.tokens);\n else filtered.sort((a, b) => b.tokens - a.tokens);\n\n const totalTokens = filtered.reduce((s, m) => s + m.tokens, 0);\n const allTokens = visible.reduce((s, m) => s + m.tokens, 0);\n const header = toolFilter\n ? `UNCOMPRESSED — ${toolFilter}: ${formatTokens(totalTokens)} | ${filtered.length} msgs | ${pct(totalTokens, allTokens)}% of visible`\n : `UNCOMPRESSED — ${formatTokens(totalTokens)} | ${filtered.length} msgs`;\n const lines = [header, `Sorted by ${sort}`, \"\"];\n const shown = filtered.slice(0, limit);\n for (const message of shown) {\n lines.push(` ${message.ref} (${formatTokens(message.tokens)}) ${message.tool}`);\n }\n if (filtered.length > shown.length) {\n lines.push(\"\");\n lines.push(`${shown.length} of ${filtered.length} shown.`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderCompressedDrilldown(\n blocks: CompressionBlock[],\n state: CompressionState,\n sort: string,\n limit: number,\n countTokens: (t: string) => number,\n): string {\n let sorted = [...blocks];\n if (sort === \"time\") sorted.sort((a, b) => a.createdAt - b.createdAt);\n else if (sort === \"age\") sorted.sort((a, b) => b.survivedCount - a.survivedCount);\n else\n sorted.sort(\n (a, b) =>\n effectiveCompressedTokens(b, state, countTokens) -\n effectiveCompressedTokens(a, state, countTokens) ||\n b.createdAt - a.createdAt,\n );\n\n const totalSummary = sorted.reduce((s, b) => s + summaryTokensOf(b, countTokens), 0);\n const totalEffective = sorted.reduce(\n (s, b) => s + effectiveCompressedTokens(b, state, countTokens),\n 0,\n );\n const lines = [\n `COMPRESSED — ${sorted.length} blocks | ${formatTokens(totalEffective)} original → ${formatTokens(totalSummary)} summary`,\n ];\n const breakdown = tierBreakdown(sorted, countTokens);\n if (breakdown) lines.push(`Tier usage: ${breakdown}`);\n lines.push(\"\");\n const shown = sorted.slice(0, limit);\n for (const block of shown) {\n const nested = block.directBlockIds.length > 0 ? ` nested=[${block.directBlockIds.join(\",\")}]` : \"\";\n const topic = block.topic ?? \"(no topic)\";\n const eff = effectiveCompressedTokens(block, state, countTokens);\n lines.push(\n ` ${block.blockId} (${tierLabel(block)}) ${formatTokens(eff)}→${formatTokens(summaryTokensOf(block, countTokens))} ${block.effectiveMessageIds.length} msgs age=${block.survivedCount} ${block.generation}${nested}`,\n );\n lines.push(` \"${topic}\"`);\n }\n if (sorted.length > shown.length) {\n lines.push(\"\");\n lines.push(`${shown.length} of ${sorted.length} shown.`);\n }\n return lines.join(\"\\n\");\n}\n\nexport function buildRecap(\n state: CompressionState,\n blockId?: string,\n): string {\n const activeBlocks = state.blocks\n .filter((b) => b.active)\n .sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));\n\n if (blockId !== undefined) {\n const block = state.blocks.find((b) => b.blockId === blockId);\n if (!block) {\n const activeList = activeBlocks.map((b) => b.blockId).join(\", \");\n return `Block ${blockId} not found. Active blocks: ${activeList}`;\n }\n if (!block.active) {\n return `Block ${blockId} is inactive (deactivated by nested compression).`;\n }\n const range = `${block.effectiveMessageIds.length} messages`;\n return `[Compressed conversation section]\\n${block.summary}\\n\\n[${blockId} | ${range} | topic: \"${block.topic ?? \"(none)\"}\"]`;\n }\n\n if (activeBlocks.length === 0) return \"No active compression blocks.\";\n\n const lines = [`Active compression blocks (${activeBlocks.length}):`];\n for (const block of activeBlocks) {\n const range = `${block.effectiveMessageIds.length} messages`;\n const preview = block.summary.slice(0, 200);\n lines.push(`\\n${block.blockId} | ${range} | \"${block.topic ?? \"(none)\"}\"`);\n lines.push(` ${preview}${block.summary.length > 200 ? \"...\" : \"\"}`);\n }\n lines.push(`\\nCall with blockId to get the full summary.`);\n return lines.join(\"\\n\");\n}\n","import { createCore } from \"./compress.js\";\nimport { assignRefs, highestUsedIndex } from \"./refs.js\";\nimport { defaultCountTokens } from \"./tokenize.js\";\nimport type { CompressionState, CoreMessage } from \"./types.js\";\n\nexport interface CompressInputEntry {\n startId?: string;\n endId?: string;\n messageId?: string;\n summary: string;\n topic?: string;\n}\n\nexport interface RebuildResult {\n state: CompressionState;\n blocksRebuilt: number;\n}\n\nexport interface RebuildPorts {\n countTokens?: (text: string) => number;\n}\n\n/**\n * Fork-recovery: reconstruct compression state by replaying historical\n * `compress` tool-call messages. Message refs (mNNNNN) are assigned by\n * message order, so they are fork-stable — a ref in a historical compress\n * input points to the same logical message after a fork regenerates IDs.\n * The rebuilt state is an approximation: only raw model summaries are\n * replayed (no protected-content enrichments).\n */\nexport function rebuildCompressionState(\n state: CompressionState,\n messages: CoreMessage[],\n config: import(\"./types.js\").Config,\n ports: RebuildPorts = {},\n): RebuildResult {\n const core = createCore({ countTokens: ports.countTokens ?? defaultCountTokens });\n const refResult = assignRefs(messages, {\n existing: state.messageRefs,\n nextIndex: highestUsedIndex(state.messageRefs) + 1,\n });\n let working: CompressionState = { ...state, messageRefs: refResult.map };\n\n const invocations = collectCompressInvocations(messages);\n let blocksRebuilt = 0;\n\n for (const invocation of invocations) {\n const ranges = extractRanges(invocation.input, invocation.callId);\n if (ranges.length === 0) continue;\n const result = core.applyCompression({ ranges, messages, state: working, config });\n working = result.state;\n blocksRebuilt += result.result.blocksCreated;\n }\n\n return { state: working, blocksRebuilt };\n}\n\ninterface CompressInvocation {\n callId: string | undefined;\n input: unknown;\n}\n\nfunction collectCompressInvocations(messages: CoreMessage[]): CompressInvocation[] {\n const invocations: CompressInvocation[] = [];\n for (const message of messages) {\n if (message.toolName !== \"compress\" || message.contentType !== \"tool-call\") continue;\n let input: unknown;\n try {\n input = JSON.parse(message.text ?? \"\");\n } catch {\n continue;\n }\n invocations.push({ callId: message.toolCallId, input });\n }\n return invocations;\n}\n\nfunction extractRanges(\n input: unknown,\n callId: string | undefined,\n): Array<{\n startRef: string;\n endRef: string;\n summary: string;\n topic?: string;\n compressCallId?: string;\n}> {\n const content = (input as { content?: unknown[] })?.content;\n if (!Array.isArray(content)) return [];\n const ranges = [];\n for (const entry of content) {\n if (!entry || typeof entry !== \"object\") continue;\n const e = entry as CompressInputEntry;\n if (typeof e.summary !== \"string\") continue;\n const start = e.startId ?? e.messageId;\n const end = e.endId ?? e.messageId;\n if (typeof start !== \"string\" || typeof end !== \"string\") continue;\n ranges.push({\n startRef: start,\n endRef: end,\n summary: e.summary,\n topic: typeof e.topic === \"string\" ? e.topic : undefined,\n compressCallId: callId,\n });\n }\n return ranges;\n}\n","/**\n * Block search — find compressed (invisible) content by keyword.\n *\n * This is the core value of ACP: as conversations grow, most history becomes\n * invisible (compressed into summary blocks). Search is the only way to\n * retrieve specific information from that invisible content.\n *\n * Current implementation: substring counting (simple but effective for\n * dozens of blocks). Future: TF-IDF, fuzzy matching, CJK tokenization,\n * semantic search.\n */\n\nimport type { CompressionState, CompressionBlock } from \"./types.js\";\n\nexport interface SearchResult {\n blockId: string;\n tier: number;\n score: number;\n topic: string;\n preview: string;\n block: CompressionBlock;\n}\n\nexport interface SearchOptions {\n limit?: number;\n previewLength?: number;\n minScore?: number;\n}\n\nexport function searchBlocks(\n state: CompressionState,\n query: string,\n options: SearchOptions = {},\n): SearchResult[] {\n const limit = options.limit ?? 10;\n const previewLength = options.previewLength ?? 200;\n const minScore = options.minScore ?? 1;\n\n const terms = query\n .toLowerCase()\n .trim()\n .split(/\\s+/)\n .filter((t) => t.length > 0);\n\n if (terms.length === 0) return [];\n\n const active = state.blocks.filter((b: CompressionBlock) => b.active);\n\n const scored: SearchResult[] = [];\n for (const block of active) {\n const text = (block.summary || \"\").toLowerCase();\n const topic = (block.topic || \"\").toLowerCase();\n const haystack = topic + \" \" + text;\n\n let score = 0;\n for (const term of terms) {\n score += countOccurrences(haystack, term);\n }\n\n if (score >= minScore) {\n scored.push({\n blockId: block.blockId,\n tier: block.tier ?? 1,\n score,\n topic: block.topic ?? \"(no topic)\",\n preview: (block.summary || \"\").slice(0, previewLength),\n block,\n });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, limit);\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n return haystack.split(needle).length - 1;\n}\n"],"mappings":";AAEA,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,cAAc;AAEb,IAAM,cAAc;AAEpB,SAAS,cAA6B;AAC3C,SAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAChC;AAEO,SAAS,WAAW,OAAuB;AAChD,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,aAAa,QAAQ,WAAW;AACtE,UAAM,IAAI;AAAA,MACR,4BAA4B,KAAK,aAAa,SAAS,IAAI,SAAS;AAAA,IACtE;AAAA,EACF;AACA,SAAO,IAAI,OAAO,KAAK,EAAE,SAAS,WAAW,GAAG,CAAC;AACnD;AAEO,SAAS,WAAW,KAA4B;AACrD,QAAM,QAAQ,YAAY,KAAK,IAAI,KAAK,EAAE,YAAY,CAAC;AACvD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC7B,MAAI,QAAQ,aAAa,QAAQ,UAAW,QAAO;AACnD,SAAO;AACT;AAEO,SAAS,UAAU,KAAoB,OAA8B;AAC1E,SAAO,IAAI,MAAM,KAAK,KAAK;AAC7B;AAEO,SAAS,UAAU,KAAoB,KAA4B;AACxE,SAAO,IAAI,MAAM,GAAG,KAAK;AAC3B;AAeO,SAAS,WACd,UACA,SACkB;AAClB,QAAM,MAAqB;AAAA,IACzB,OAAO,EAAE,GAAG,QAAQ,SAAS,MAAM;AAAA,IACnC,OAAO,EAAE,GAAG,QAAQ,SAAS,MAAM;AAAA,EACrC;AACA,MAAI,SACF,OAAO,UAAU,QAAQ,SAAS,KAAK,QAAQ,aAAa,YACxD,QAAQ,YACR;AACN,MAAI,gBAAgB;AAEpB,aAAW,WAAW,UAAU;AAC9B,QAAI,CAAC,QAAQ,MAAM,QAAQ,aAAa,OAAO,EAAG;AAElD,QAAI,IAAI,MAAM,QAAQ,EAAE,EAAG;AAE3B,QAAI,QAAQ,cAAc,OAAO,GAAG;AAClC,UAAI,MAAM,QAAQ,EAAE,IAAI;AACxB;AAAA,IACF;AAEA,UAAM,MAAM,gBAAgB,KAAK,MAAM;AACvC,aAAS,IAAI,QAAQ;AACrB,QAAI,MAAM,QAAQ,EAAE,IAAI,IAAI;AAC5B,QAAI,MAAM,IAAI,IAAI,IAAI,QAAQ;AAC9B;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,WAAW,QAAQ,cAAc;AACjD;AAEA,SAAS,gBACP,KACA,OACiC;AACjC,MAAI,YAAY,KAAK,IAAI,OAAO,SAAS;AACzC,SAAO,aAAa,WAAW;AAC7B,UAAM,OAAO,WAAW,SAAS;AACjC,QAAI,CAAC,IAAI,MAAM,IAAI,GAAG;AACpB,aAAO,EAAE,MAAM,OAAO,UAAU;AAAA,IAClC;AACA;AAAA,EACF;AACA,QAAM,IAAI;AAAA,IACR,kDAAkD,WAAW,SAAS,CAAC;AAAA,EACzE;AACF;AAUO,SAAS,iBAAiB,KAA4B;AAC3D,MAAI,UAAU;AACd,aAAW,OAAO,OAAO,OAAO,IAAI,KAAK,GAAG;AAC1C,UAAM,QAAQ,QAAQ,cAAc,OAAO,WAAW,GAAG;AACzD,QAAI,UAAU,QAAQ,QAAQ,QAAS,WAAU;AAAA,EACnD;AACA,SAAO;AACT;;;ACnHO,SAAS,qBAAuC;AACrD,SAAO;AAAA,IACL,QAAQ,CAAC;AAAA,IACT,aAAa,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,IACpC,OAAO;AAAA,MACL,2BAA2B;AAAA,MAC3B,sBAAsB;AAAA,MACtB,gBAAgB;AAAA,MAChB,SAAS,CAAC;AAAA,MACV,iBAAiB,CAAC;AAAA,IACpB;AAAA,IACA,OAAO,EAAE,kBAAkB,GAAG,kBAAkB,EAAE;AAAA,IAClD,aAAa;AAAA,IACb,WAAW;AAAA,EACb;AACF;AAEO,SAAS,gBAAgB,OAAiC;AAC/D,QAAM,KAAK,MAAM;AACjB,QAAM,cAAc,KAAK,IAAI,GAAG,EAAE,IAAI;AACtC,SAAO,IAAI,EAAE;AACf;AAEO,SAAS,cAAc,OAAiC;AAC7D,QAAM,KAAK,MAAM;AACjB,QAAM,YAAY,KAAK,IAAI,GAAG,EAAE,IAAI;AACpC,SAAO,IAAI,EAAE;AACf;AAEO,SAAS,UACd,OACA,SAC8B;AAC9B,SAAO,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,YAAY,OAAO;AAC/D;AAEO,SAAS,aAAa,OAA6C;AACxE,SAAO,MAAM,OAAO,OAAO,CAAC,UAAU,MAAM,MAAM;AACpD;AAEO,SAAS,kBAAkB,OAAsC;AACtE,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,SAAS,MAAM,QAAQ;AAChC,QAAI,CAAC,MAAM,OAAQ;AACnB,eAAW,MAAM,MAAM,oBAAqB,SAAQ,IAAI,EAAE;AAAA,EAC5D;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,OAAwC;AACxE,MAAI,UAAyB;AAC7B,aAAW,SAAS,MAAM,QAAQ;AAChC,QAAI,MAAM,UAAU,MAAM,OAAO,QAAS,WAAU,MAAM;AAAA,EAC5D;AACA,SAAO;AACT;AAEO,SAAS,gBACd,OACA,oBACM;AACN,aAAW,SAAS,MAAM,QAAQ;AAChC,QAAI,CAAC,MAAM,OAAQ;AACnB,UAAM,iBAAiB;AACvB,QAAI,MAAM,iBAAiB,oBAAoB;AAC7C,YAAM,aAAa;AAAA,IACrB;AAAA,EACF;AACF;;;ACnEO,IAAM,iBAAiB;AAMvB,SAAS,MACd,UACA,OACA,UAAwB,CAAC,GACV;AACf,QAAM,UAAU,kBAAkB,KAAK;AACvC,MAAI,QAAQ,SAAS,EAAG,QAAO,CAAC,GAAG,QAAQ;AAE3C,QAAM,SAAS,QAAQ,mBAAmB;AAC1C,QAAM,iBAAiB,SAAS;AAAA,IAC9B,CAAC,YAAY,QAAQ,SAAS;AAAA,EAChC;AAEA,QAAM,YAAY,oBAAI,IAAoB;AAC1C,WAAS,QAAQ,CAAC,SAAS,UAAU,UAAU,IAAI,QAAQ,IAAI,KAAK,CAAC;AAErE,QAAM,UAAU,SAAS,sBAAsB,OAAO,SAAS,IAAI,CAAC;AAEpE,SAAO;AAAA,IACL;AAAA,MACE,gBAAgB,UAAU,SAAS,gBAAgB,OAAO;AAAA,IAC5D;AAAA,EACF;AACF;AASA,SAAS,sBACP,OACA,WACiB;AACjB,QAAM,UAA2B,CAAC;AAClC,aAAW,SAAS,aAAa,KAAK,GAAG;AACvC,QAAI,WAA0B;AAC9B,eAAW,MAAM,MAAM,qBAAqB;AAC1C,YAAM,QAAQ,UAAU,IAAI,EAAE;AAC9B,UAAI,UAAU,WAAc,aAAa,QAAQ,QAAQ,WAAW;AAClE,mBAAW;AAAA,MACb;AAAA,IACF;AACA,YAAQ,KAAK;AAAA,MACX,SAAS,MAAM;AAAA,MACf,SAAS,MAAM;AAAA,MACf,OAAO,MAAM;AAAA,MACb,UAAU,YAAY;AAAA,IACxB,CAAC;AAAA,EACH;AACA,UAAQ,KAAK,CAAC,MAAM,UAAU,KAAK,WAAW,MAAM,QAAQ;AAC5D,SAAO;AACT;AAEA,SAAS,gBACP,UACA,SACA,gBACA,SACe;AACf,QAAM,SAAwB,CAAC;AAC/B,QAAM,UAAU,CAAC,GAAG,OAAO;AAE3B,WAAS,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS;AACpD,WAAO,QAAQ,SAAS,KAAK,QAAQ,CAAC,EAAG,aAAa,OAAO;AAC3D,aAAO,KAAK,cAAc,QAAQ,MAAM,CAAE,CAAC;AAAA,IAC7C;AACA,QAAI,UAAU,kBAAkB,kBAAkB,GAAG;AACnD,aAAO,KAAK,SAAS,KAAK,CAAE;AAC5B;AAAA,IACF;AACA,QAAI,QAAQ,IAAI,SAAS,KAAK,EAAG,EAAE,EAAG;AACtC,WAAO,KAAK,SAAS,KAAK,CAAE;AAAA,EAC9B;AAEA,SAAO,QAAQ,SAAS,GAAG;AACzB,WAAO,KAAK,cAAc,QAAQ,MAAM,CAAE,CAAC;AAAA,EAC7C;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,QAAoC;AACzD,QAAM,OAAO,OAAO,QAAQ,KAAK;AACjC,QAAM,YAAY,OAAO,QACrB,GAAG,cAAc,WAAM,OAAO,KAAK,KACnC;AACJ,QAAM,OAAO,KAAK,WAAW,IAAI,YAAY,GAAG,SAAS;AAAA,EAAK,IAAI;AAClE,SAAO;AAAA,IACL,IAAI,eAAe,OAAO,OAAO;AAAA,IACjC,MAAM;AAAA,IACN,aAAa;AAAA,IACb;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,UAAwC;AACxE,QAAM,eAAe,oBAAI,IAAY;AACrC,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,gBAAgB,eAAe,EAAE,YAAY;AACjD,mBAAa,IAAI,EAAE,UAAU;AAAA,IAC/B;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IACd,CAAC,MACC,EAAE,gBAAgB,iBAClB,CAAC,EAAE,cACH,aAAa,IAAI,EAAE,UAAU;AAAA,EACjC;AACF;AAEA,SAAS,uBAAuB,UAAwC;AACtE,QAAM,iBAAiB,oBAAI,IAAY;AACvC,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,gBAAgB,iBAAiB,EAAE,YAAY;AACnD,qBAAe,IAAI,EAAE,UAAU;AAAA,IACjC;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IACd,CAAC,MACC,EAAE,gBAAgB,eAClB,CAAC,EAAE,cACH,EAAE,aAAa,cACf,eAAe,IAAI,EAAE,UAAU;AAAA,EACnC;AACF;;;ACjIO,SAAS,WACd,UACA,OACY;AACZ,QAAM,aAAa,IAAI,IAAI,SAAS,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;AAChE,QAAM,cAAwB,CAAC;AAK/B,QAAM,SAA2B;AAAA,IAC/B,QAAQ,MAAM,OAAO,IAAI,CAAC,WAAW;AAAA,MACnC,GAAG;AAAA,MACH,kBAAkB,CAAC,GAAG,MAAM,gBAAgB;AAAA,MAC5C,qBAAqB,CAAC,GAAG,MAAM,mBAAmB;AAAA,MAClD,gBAAgB,CAAC,GAAG,MAAM,cAAc;AAAA,IAC1C,EAAE;AAAA,IACF,aAAa;AAAA,MACX,OAAO,EAAE,GAAG,MAAM,YAAY,MAAM;AAAA,MACpC,OAAO,EAAE,GAAG,MAAM,YAAY,MAAM;AAAA,IACtC;AAAA,IACA,OAAO,EAAE,GAAG,MAAM,OAAO,SAAS,EAAE,GAAG,MAAM,MAAM,QAAQ,EAAE;AAAA,IAC7D,OAAO,EAAE,GAAG,MAAM,MAAM;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,WAAW,MAAM;AAAA,EACnB;AAEA,QAAM,mBAAmB,oBAAI,IAAY;AACzC,aAAW,SAAS,OAAO,QAAQ;AACjC,eAAW,cAAc,MAAM,gBAAgB;AAC7C,uBAAiB,IAAI,UAAU;AAAA,IACjC;AAAA,EACF;AAEA,aAAW,SAAS,OAAO,QAAQ;AACjC,QAAI,iBAAiB,IAAI,MAAM,OAAO,GAAG;AACvC,YAAM,SAAS;AACf;AAAA,IACF;AACA,UAAM,SAAS;AACf,UAAM,eAAe,MAAM,oBAAoB;AAAA,MAAK,CAAC,OACnD,WAAW,IAAI,EAAE;AAAA,IACnB;AACA,QAAI,CAAC,cAAc;AACjB,YAAM,SAAS;AACf,kBAAY,KAAK,MAAM,OAAO;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAQ,YAAY;AACtC;;;ACzDA,SAAS,qBAAqB;AAE9B,IAAMA,WAAU,cAAc,YAAY,GAAG;AAEtC,SAAS,mBAAmB,MAAsB;AACvD,MAAI,CAAC,KAAM,QAAO;AAIlB,QAAM,MAAM,KAAK,MAAM,4CAA4C;AACnE,QAAM,WAAW,KAAK,UAAU;AAChC,SAAO,WAAW,KAAK,MAAM,KAAK,SAAS,YAAY,CAAC;AAC1D;AAMO,SAAS,mBAAmB,MAAsB;AACvD,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;AAIO,SAAS,qBAAmC;AACjD,MAAI;AACF,UAAM,MAAMC,SAAQ,yBAAyB;AAC7C,UAAM,WAAW,IAAI,eAAe,IAAI,SAAS;AACjD,QAAI,OAAO,aAAa,WAAY,QAAO;AAC3C,WAAO,CAAC,SAAiB;AACvB,UAAI;AACF,eAAO,SAAS,IAAI;AAAA,MACtB,QAAQ;AACN,eAAO,mBAAmB,IAAI;AAAA,MAChC;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACtCO,SAAS,cACd,mBACA,YAA6B,CAAC,GACtB;AACR,QAAM,OAAe;AAAA,IACnB,OAAO,EAAE,SAAS,MAAM,cAAc,GAAG,cAAc,GAAG;AAAA,IAC1D,OAAO;AAAA,MACL,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,MACpB,WAAW;AAAA,MACX,oBAAoB;AAAA,MACpB,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,KAAK,IAAI,KAAO,KAAK,MAAM,oBAAoB,IAAI,CAAC;AAAA,MACjE,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,uBAAuB;AAAA,IACzB;AAAA,IACA,oBAAoB;AAAA,IACpB,UAAU,EAAE,WAAW,EAAE;AAAA,IACzB,UAAU;AAAA,MACR,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,IACpB;AAAA,IACA,gBAAgB,CAAC;AAAA,IACjB,wBAAwB;AAAA,IACxB,sBAAsB;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,OAAO,EAAE,GAAG,KAAK,OAAO,GAAG,UAAU,MAAM;AAAA,IAC3C,OAAO,EAAE,GAAG,KAAK,OAAO,GAAG,UAAU,MAAM;AAAA,IAC3C,UAAU,EAAE,GAAG,KAAK,UAAU,GAAG,UAAU,SAAS;AAAA,IACpD,UAAU,EAAE,GAAG,KAAK,UAAU,GAAG,UAAU,SAAS;AAAA,EACtD;AACF;AAEO,SAAS,eAAe,QAA0B;AACvD,QAAM,SAAmB,CAAC;AAC1B,MACE,CAAC,OAAO,SAAS,OAAO,iBAAiB,KACzC,OAAO,qBAAqB,GAC5B;AACA,WAAO,KAAK,6CAA6C;AAAA,EAC3D;AACA,MAAI,OAAO,MAAM,qBAAqB,OAAO,MAAM,oBAAoB;AACrE,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,qBAAqB,GAAG;AACjC,WAAO,KAAK,iCAAiC;AAAA,EAC/C;AACA,MAAI,OAAO,SAAS,aAAa,KAAK,OAAO,SAAS,YAAY,GAAG;AACnE,WAAO,KAAK,sCAAsC;AAAA,EACpD;AACA,aAAW,QAAQ,CAAC,OAAO,MAAM,cAAc,OAAO,MAAM,YAAY,GAAG;AACzE,QAAI,OAAO,EAAG,QAAO,KAAK,4BAA4B;AAAA,EACxD;AACA,MAAI,OAAO,MAAM,gBAAgB,OAAO,MAAM,cAAc;AAC1D,WAAO,KAAK,4DAA4D;AAAA,EAC1E;AACA,SAAO;AACT;;;ACtDA,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAEnB,SAAS,cAAc,KAAoC;AAChE,QAAM,aAAa,IAAI,KAAK,EAAE,YAAY;AAC1C,QAAM,eAAe,oBAAoB,KAAK,UAAU;AACxD,MAAI,cAAc;AAChB,UAAM,YAAY,OAAO,aAAa,CAAC,CAAC;AACxC,QAAI,aAAa,KAAK,aAAa,OAAO;AACxC,aAAO,EAAE,MAAM,WAAW,WAAW,KAAK,WAAW;AAAA,IACvD;AAAA,EACF;AACA,QAAM,aAAa,kBAAkB,KAAK,UAAU;AACpD,MAAI,YAAY;AACd,UAAM,YAAY,OAAO,WAAW,CAAC,CAAC;AACtC,QAAI,aAAa,EAAG,QAAO,EAAE,MAAM,SAAS,WAAW,KAAK,WAAW;AAAA,EACzE;AACA,SAAO;AACT;AAkBO,SAAS,kBACd,OACe;AACf,QAAM,QAAQ,cAAc,MAAM,QAAQ;AAC1C,QAAM,MAAM,cAAc,MAAM,MAAM;AACtC,MAAI,CAAC,SAAS,CAAC,KAAK;AAClB,UAAM,IAAI;AAAA,MACR,qCAAqC,MAAM,QAAQ,aAAa,MAAM,MAAM;AAAA,IAC9E;AAAA,EACF;AAEA,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,SAAS;AAAA,IAAQ,CAAC,SAAS,UAC/B,aAAa,IAAI,QAAQ,IAAI,KAAK;AAAA,EACpC;AAEA,MAAI,aAAa,mBAAmB,OAAO,MAAM,OAAO,YAAY;AACpE,MAAI,WAAW,mBAAmB,KAAK,MAAM,OAAO,YAAY;AAEhE,MAAI,eAAe,QAAQ,aAAa,MAAM;AAC5C,UAAM,IAAI;AAAA,MACR,0FACc,MAAM,QAAQ,aAAa,MAAM,MAAM;AAAA,IACvD;AAAA,EACF;AAEA,MAAI,aAAa,UAAU;AACzB,KAAC,YAAY,QAAQ,IAAI,CAAC,UAAU,UAAU;AAAA,EAChD;AAEA,QAAM,aAAuB,CAAC;AAC9B,WAAS,QAAQ,YAAY,SAAS,UAAU,SAAS;AACvD,UAAM,UAAU,MAAM,SAAS,KAAK;AACpC,QAAI,QAAS,YAAW,KAAK,QAAQ,EAAE;AAAA,EACzC;AAEA,QAAM,eACJ,MAAM,SAAS,WAAW,IAAI,SAAS,UAAU,UAAU;AAE7D,QAAM,iBAA2B,CAAC;AAClC,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,SAAS,aAAa,MAAM,KAAK,GAAG;AAC7C,UAAM,SAAS,mBAAmB,MAAM,qBAAqB,YAAY;AACzE,QAAI,WAAW,QAAQ,UAAU,cAAc,UAAU,UAAU;AACjE,UAAI,CAAC,WAAW,IAAI,MAAM,OAAO,GAAG;AAClC,mBAAW,IAAI,MAAM,OAAO;AAC5B,uBAAe,KAAK,MAAM,OAAO;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAA0B,CAAC;AAEjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,mBACP,UACA,OACA,cACe;AACf,MAAI,SAAS,SAAS,WAAW;AAC/B,UAAM,QACJ,MAAM,YAAY,MAAM,SAAS,GAAG,KACpC,MAAM,YAAY,MAAM,gBAAgB,SAAS,SAAS,CAAC;AAC7D,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,QAAQ,aAAa,IAAI,KAAK;AACpC,WAAO,UAAU,SAAY,OAAO;AAAA,EACtC;AAEA,QAAM,QAAQ,UAAU,OAAO,IAAI,SAAS,SAAS,EAAE;AACvD,MAAI,CAAC,SAAS,CAAC,MAAM,OAAQ,QAAO;AACpC,SAAO,mBAAmB,MAAM,qBAAqB,YAAY;AACnE;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,IAAI,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AAC3C;AAEO,SAAS,mBACd,KACA,cACe;AACf,MAAI,WAA0B;AAC9B,aAAW,MAAM,KAAK;AACpB,UAAM,QAAQ,aAAa,IAAI,EAAE;AACjC,QAAI,UAAU,WAAc,aAAa,QAAQ,QAAQ,WAAW;AAClE,iBAAW;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;;;ACtIA,IAAM,oBAAoB;AAC1B,IAAM,WAAW;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,uBAAuB;AAC3B;AAEO,SAAS,yBACZ,UACA,YACA,QACA,aACA,UAA2B,CAAC,GACd;AACd,QAAM,OAAO,EAAE,GAAG,UAAU,GAAG,QAAQ;AACvC,MAAI,OAAO,qBAAqB,EAAG,QAAO,EAAE,UAAU,gBAAgB,GAAG,aAAa,EAAE;AAExF,QAAM,YAAY,OAAO,SAAS,YAAY,OAAO;AACrD,MAAI,aAAa,UAAW,QAAO,EAAE,UAAU,gBAAgB,GAAG,aAAa,EAAE;AAEjF,QAAM,iBAAiB,SAAS,SAAS,KAAK;AAC9C,QAAM,aAAuD,CAAC;AAE9D,WAAS,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS;AAClD,QAAI,SAAS,eAAgB;AAC7B,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,QAAQ,gBAAgB,cAAe;AAC3C,UAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAI,KAAK,WAAW,KAAK,KAAK,SAAS,iBAAiB,EAAG;AAC3D,UAAM,SAAS,YAAY,IAAI;AAC/B,QAAI,SAAS,KAAK,gBAAiB;AACnC,eAAW,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,EACrC;AAEA,MAAI,WAAW,WAAW,EAAG,QAAO,EAAE,UAAU,gBAAgB,GAAG,aAAa,EAAE;AAClF,aAAW,KAAK,CAAC,MAAM,UAAU,MAAM,SAAS,KAAK,MAAM;AAE3D,QAAM,eAAe,YAAY;AACjC,MAAI,cAAc;AAClB,QAAM,QAAQ,oBAAI,IAAoB;AACtC,MAAI,iBAAiB;AAErB,aAAW,aAAa,YAAY;AAChC,QAAI,aAAa,eAAe,aAAc;AAC9C,UAAM,WAAW,SAAS,UAAU,KAAK,EAAG,QAAQ;AACpD,QAAI,SAAS,UAAU,KAAK,kBAAkB,KAAK,gBAAiB;AAEpE,UAAM,SAAS,SAAS,MAAM,GAAG,KAAK,eAAe;AACrD,UAAM,SAAS,SAAS,MAAM,CAAC,KAAK,eAAe;AACnD,UAAM,cACF,SACA;AAAA;AAAA,KAAU,iBAAiB,qBAAgB,UAAU,MAAM;AAAA;AAAA,IAC3D;AACJ,UAAM,IAAI,UAAU,OAAO,WAAW;AACtC,mBAAe,UAAU,SAAS,YAAY,WAAW;AACzD;AAAA,EACJ;AAEA,MAAI,mBAAmB,EAAG,QAAO,EAAE,UAAU,gBAAgB,GAAG,aAAa,EAAE;AAE/E,QAAM,UAAU,SAAS;AAAA,IAAI,CAAC,SAAS,UACnC,MAAM,IAAI,KAAK,IAAI,EAAE,GAAG,SAAS,MAAM,MAAM,IAAI,KAAK,EAAG,IAAI;AAAA,EACjE;AACA,SAAO,EAAE,UAAU,SAAS,gBAAgB,YAAY;AAC5D;;;AC1EA,IAAM,qBAAqB;AAQpB,SAAS,0BACZ,OACA,UACkB;AAClB,QAAM,gBAAgB,oBAAI,IAAY;AACtC,QAAM,kBAAkB,oBAAI,IAAY;AACxC,aAAW,SAAS,MAAM,QAAQ;AAC9B,QAAI,MAAM,gBAAgB;AACtB,sBAAgB,IAAI,MAAM,cAAc;AACxC,UAAI,MAAM,OAAQ,eAAc,IAAI,MAAM,cAAc;AAAA,IAC5D;AAAA,EACJ;AAEA,QAAM,sBAAgC,CAAC;AACvC,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,KAAK,oBAAoB,SAAS,oBAAoB,KAAK;AAC9F,UAAM,UAAU,SAAS,CAAC;AAC1B,QAAI,QAAQ,aAAa,cAAc,QAAQ,gBAAgB,YAAa;AAC5E,UAAM,SAAS,QAAQ;AACvB,QAAI,UAAU,CAAC,gBAAgB,IAAI,MAAM,GAAG;AACxC,0BAAoB,KAAK,MAAM;AAAA,IACnC;AAAA,EACJ;AAEA,QAAM,cAAc,oBAAI,IAAI,CAAC,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAEtE,QAAM,gBAAgB,oBAAI,IAAY;AACtC,aAAW,WAAW,UAAU;AAC5B,QACI,QAAQ,aAAa,cACrB,QAAQ,gBAAgB,gBACvB,CAAC,QAAQ,cAAc,CAAC,YAAY,IAAI,QAAQ,UAAU,IAC7D;AACE,UAAI,QAAQ,WAAY,eAAc,IAAI,QAAQ,UAAU;AAAA,IAChE;AAAA,EACJ;AAEA,MAAI,SAAS;AACb,QAAM,SAAwB,CAAC;AAC/B,aAAW,WAAW,UAAU;AAC5B,QACI,QAAQ,aAAa,cACrB,QAAQ,gBAAgB,gBACvB,CAAC,QAAQ,cAAc,CAAC,YAAY,IAAI,QAAQ,UAAU,IAC7D;AACE;AACA;AAAA,IACJ;AACA,QACI,QAAQ,gBAAgB,iBACxB,QAAQ,cACR,cAAc,IAAI,QAAQ,UAAU,GACtC;AACE;AACA;AAAA,IACJ;AACA,WAAO,KAAK,OAAO;AAAA,EACvB;AAEA,SAAO,EAAE,UAAU,QAAQ,OAAO;AACtC;;;ACvEA,IAAM,WAAW,oBAAI,IAA2B;AAEzC,SAAS,sBAAsB,QAA6B;AAC/D,QAAM,WAAW,SAAS,IAAI,OAAO,IAAI;AACzC,MAAI,YAAY,SAAS,YAAY,OAAO,SAAS;AACjD,UAAM,IAAI;AAAA,MACN,mBAAmB,OAAO,IAAI,qCAAqC,SAAS,OAAO,6BAA6B,OAAO,OAAO;AAAA,IAClI;AAAA,EACJ;AACA,WAAS,IAAI,OAAO,MAAM,MAAM;AACpC;AAEO,SAAS,iBAAiB,MAAyC;AACtE,SAAO,SAAS,IAAI,IAAI;AAC5B;AAEO,SAAS,qBAAsC;AAClD,SAAO,CAAC,GAAG,SAAS,OAAO,CAAC;AAChC;AAEO,SAAS,sBAA4B;AACxC,WAAS,MAAM;AACnB;;;ACbO,SAAS,oBACZ,UACA,QACW;AACX,MAAI,CAAC,QAAQ,SAAS;AAClB,WAAO,EAAE,UAAU,eAAe,GAAG,cAAc,GAAG,eAAe,EAAE;AAAA,EAC3E;AAEA,QAAM,SAAS,mBAAmB,EAAE;AAAA,IAChC,CAAC,WAAW,OAAO,UAAU,OAAO,IAAI,GAAG,YAAY;AAAA,EAC3D;AACA,MAAI,OAAO,WAAW,GAAG;AACrB,WAAO,EAAE,UAAU,eAAe,GAAG,cAAc,GAAG,eAAe,EAAE;AAAA,EAC3E;AAEA,MAAI,UAAU,SAAS,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,EAAE;AACxD,QAAM,QAAQ,EAAE,eAAe,GAAG,cAAc,GAAG,eAAe,EAAE;AACpE,QAAM,QAAQ,QAAQ;AAEtB,QAAM,YAAY,OAAO,OAAO,CAAC,WAAW,CAAC,OAAO,YAAY;AAChE,WAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS;AACjD,UAAM,UAAU,QAAQ,KAAK;AAC7B,UAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAI,KAAK,WAAW,EAAG;AACvB,QAAI,UAAU;AACd,UAAM,UAAgC;AAAA,MAClC,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,cAAc;AAAA,MACd,eAAe;AAAA,MACf,UAAU,QAAQ;AAAA,IACtB;AACA,eAAW,UAAU,WAAW;AAC5B,UAAI;AACJ,UAAI;AACA,mBAAW,OAAO,OAAO,OAAO;AAAA,MACpC,QAAQ;AACJ;AAAA,MACJ;AACA,UAAI,SAAS,WAAW,OAAQ;AAChC,YAAM;AACN,UAAI,SAAS,WAAW,QAAQ;AAC5B,kBAAU;AACV,cAAM;AAAA,MACV,WAAW,SAAS,WAAW,YAAY,SAAS,SAAS,QAAW;AACpE,kBAAU,SAAS;AACnB,cAAM;AAAA,MACV;AACA,cAAQ,OAAO;AAAA,IACnB;AACA,QAAI,YAAY,KAAM,SAAQ,KAAK,IAAI,EAAE,GAAG,SAAS,MAAM,QAAQ;AAAA,EACvE;AAEA,QAAM,WAAW,OAAO,OAAO,CAAC,WAAW,OAAO,YAAY;AAC9D,aAAW,UAAU,UAAU;AAC3B,QAAI,YAAY;AAChB,aAAS,QAAQ,QAAQ,SAAS,GAAG,SAAS,GAAG,SAAS;AACtD,YAAM,UAAU,QAAQ,KAAK;AAC7B,YAAM,OAAO,QAAQ,QAAQ;AAC7B,UAAI,KAAK,WAAW,EAAG;AACvB,YAAM,MAA4B;AAAA,QAC9B;AAAA,QACA,MAAM,QAAQ;AAAA,QACd,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU,QAAQ;AAAA,MACtB;AACA,UAAI;AACJ,UAAI;AACA,mBAAW,OAAO,OAAO,GAAG;AAAA,MAChC,QAAQ;AACJ;AAAA,MACJ;AACA,UAAI,SAAS,WAAW,UAAU,SAAS,WAAW,SAAU;AAChE,UAAI,WAAW;AACX,cAAM;AACN,cAAM;AACN,gBAAQ,KAAK,IAAI,EAAE,GAAG,SAAS,MAAM,GAAG;AAAA,MAC5C,OAAO;AACH,oBAAY;AACZ,YAAI,SAAS,WAAW,YAAY,SAAS,SAAS,QAAW;AAC7D,gBAAM;AACN,gBAAM;AACN,kBAAQ,KAAK,IAAI,EAAE,GAAG,SAAS,MAAM,SAAS,KAAK;AAAA,QACvD;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,EAAE,UAAU,SAAS,GAAG,MAAM;AACzC;;;AChGA,SAAS,aAAa,QAAwB;AAC5C,MAAI,SAAS,IAAM,QAAO,OAAO,MAAM;AACvC,MAAI,SAAS,IAAO,SAAQ,SAAS,KAAM,QAAQ,CAAC,IAAI;AACxD,SAAO,KAAK,MAAM,SAAS,GAAI,IAAI;AACrC;AAEA,SAAS,aAAa,SAA8B;AAClD,MACE,QAAQ,gBAAgB,eACxB,QAAQ,gBAAgB,eACxB;AACA,WAAO,QAAQ,YAAY;AAAA,EAC7B;AACA,SAAO,QAAQ;AACjB;AAEA,SAAS,YAAY,GAAmB;AACtC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAEA,IAAM,KAAK;AACX,IAAM,KAAK;AACX,IAAM,WAAW,KAAK;AACtB,IAAM,YAAY,KAAK,SAAS;AAEhC,SAAS,OAAO,KAAa,QAAgB,MAAsB;AACjE,SAAO,WAAW,aAAa,aAAa,MAAM,IAAI,aAAa,OAAO,MAAM,KAAK,MAAM;AAC7F;AAEA,SAAS,cACP,SACA,KACA,aACa;AACb,QAAM,MAAM,UAAU,KAAK,QAAQ,EAAE;AACrC,MAAI,CAAC,OAAO,QAAQ,YAAa,QAAO;AAIxC,QAAM,WAAW,IAAI;AAAA,IACnB,MAAM,YAAY,QAAQ,IAAI,UAAU,KAAK,YAAY,GAAG,IAAI,YAAY,SAAS,IAAI;AAAA,EAC3F;AACA,QAAM,aAAa,QAAQ,QAAQ,IAAI,QAAQ,UAAU,EAAE;AAE3D,QAAM,SAAS,YAAY,SAAS;AACpC,QAAM,OAAO,aAAa,OAAO;AACjC,QAAM,SAAS,OAAO,KAAK,QAAQ,IAAI,IAAI;AAE3C,MAAI,CAAC,UAAW,QAAO,EAAE,GAAG,SAAS,MAAM,OAAO;AAClD,SAAO,EAAE,GAAG,SAAS,MAAM,SAAS,UAAU;AAChD;AAEO,SAAS,kBACd,UACA,OACA,cAAwC,CAAC,SACvC,KAAK,KAAK,KAAK,SAAS,CAAC,GACZ;AACf,QAAM,MAAM,MAAM;AAClB,SAAO,SAAS;AAAA,IAAI,CAAC,YACnB,cAAc,SAAS,KAAK,WAAW;AAAA,EACzC;AACF;AAEO,IAAM,iBAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,IAAI,IAAY,KAA8B;AAC5C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,kBAAkB,GAAG,UAAU,GAAG,OAAO,IAAI,WAAW;AAAA,IACpE;AAAA,EACF;AACF;;;ACtEO,IAAM,yBAAyB,CAAC,UAAU;AAE1C,SAAS,iBAAiB,UAAkB,SAA0B;AAC3E,MAAI,QAAQ,SAAS,GAAG,GAAG;AACzB,WAAO,SAAS,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC;AAAA,EACjD;AACA,SAAO,aAAa;AACtB;AAEO,SAAS,mBACd,KACA,QACS;AAGT,MACG,IAAI,gBAAgB,eAAe,IAAI,gBAAgB,iBACxD,CAAC,IAAI,UACL;AACA,WAAO;AAAA,EACT;AAGA,MAAK,uBAA6C,SAAS,IAAI,QAAQ,GAAG;AACxE,WAAO;AAAA,EACT;AAEA,aAAW,WAAW,OAAO,gBAAgB;AAC3C,QAAI,iBAAiB,IAAI,UAAU,OAAO,EAAG,QAAO;AAAA,EACtD;AAEA,MAAI,OAAO,kBAAkB,IAAI,UAAU,IAAI,IAAI,EAAG,QAAO;AAE7D,SAAO;AACT;AAMO,SAAS,4BACd,UACA,QACa;AACb,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,gBAAgB,eAAe,EAAE,cAAc,mBAAmB,GAAG,MAAM,GAAG;AAClF,UAAI,IAAI,EAAE,UAAU;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AACT;AAIO,SAAS,8BACd,KACA,QACA,kBACS;AACT,MAAI,mBAAmB,KAAK,MAAM,EAAG,QAAO;AAC5C,MACE,IAAI,gBAAgB,iBACpB,IAAI,cACJ,iBAAiB,IAAI,IAAI,UAAU,GACnC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AC5DO,SAAS,6BACZ,YACA,UACA,UACA,UAAkB,IACsB;AAGxC,QAAM,iBAAiB,oBAAI,IAAY;AACvC,WAAS,IAAI,YAAY,KAAK,UAAU,KAAK;AACzC,UAAM,MAAM,SAAS,CAAC;AACtB,QAAI,CAAC,OAAO,CAAC,IAAI,WAAY;AAC7B,QAAI,IAAI,aAAa,WAAY;AACjC,mBAAe,IAAI,IAAI,UAAU;AAAA,EACrC;AAEA,MAAI,eAAe,SAAS,GAAG;AAC3B,WAAO,EAAE,YAAY,SAAS;AAAA,EAClC;AAIA,MAAI,cAAc;AAClB,WAAS,IAAI,WAAW,GAAG,IAAI,SAAS,UAAU,KAAK,WAAW,SAAS,KAAK;AAC5E,UAAM,MAAM,SAAS,CAAC;AACtB,QAAI,CAAC,IAAK;AACV,QAAI,IAAI,cAAc,eAAe,IAAI,IAAI,UAAU,GAAG;AACtD,oBAAc;AAAA,IAClB,WAAW,cAAc,UAAU;AAC/B;AAAA,IACJ;AAAA,EACJ;AAGA,MAAI,gBAAgB;AACpB,WAAS,IAAI,aAAa,GAAG,KAAK,KAAK,KAAK,aAAa,SAAS,KAAK;AACnE,UAAM,MAAM,SAAS,CAAC;AACtB,QAAI,CAAC,IAAK;AACV,QAAI,IAAI,cAAc,eAAe,IAAI,IAAI,UAAU,GAAG;AACtD,sBAAgB;AAAA,IACpB,WAAW,gBAAgB,YAAY;AACnC;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,EAAE,YAAY,eAAe,UAAU,YAAY;AAC9D;;;ACjCA,SAAS,OAAO,KAAqB;AACnC,QAAM,IAAI,SAAS,IAAI,MAAM,CAAC,GAAG,EAAE;AACnC,SAAO,OAAO,MAAM,CAAC,IAAI,KAAK;AAChC;AAEA,SAAS,sBAAsB,SAA8B;AAC3D,SAAO,KAAK,MAAM,QAAQ,QAAQ,IAAI,SAAS,CAAC;AAClD;AAEA,SAAS,cAAc,SAA+B;AACpD,SAAO,QAAQ,gBAAgB,eAAe,QAAQ,gBAAgB;AACxE;AAGA,SAAS,oBACP,SACA,OACS;AACT,MAAI,QAAQ,MAAM,WAAW,mCAAmC,EAAG,QAAO;AAC1E,aAAW,SAAS,MAAM,QAAQ;AAChC,QAAI,MAAM,UAAU,MAAM,oBAAoB,SAAS,QAAQ,EAAE,EAAG,QAAO;AAAA,EAC7E;AACA,SAAO;AACT;AAcO,SAAS,qBACd,UACA,OACA,QACa;AACb,QAAM,YAAY,OAAO;AACzB,QAAM,iBAAiB,OAAO;AAE9B,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,UAA6C,CAAC;AAEpD,aAAW,OAAO,UAAU;AAC1B,QAAI,oBAAoB,KAAK,KAAK,EAAG;AACrC,UAAM,MAAM,MAAM,YAAY,MAAM,IAAI,EAAE;AAC1C,QAAI,CAAC,OAAO,QAAQ,UAAW;AAC/B,YAAQ,KAAK,EAAE,KAAK,QAAQ,sBAAsB,GAAG,EAAE,CAAC;AAAA,EAC1D;AAGA,MAAI,YAAY,GAAG;AACjB,eAAW,KAAK,QAAQ,MAAM,CAAC,SAAS,GAAG;AACzC,aAAO,IAAI,EAAE,GAAG;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,iBAAiB,GAAG;AACtB,QAAI,aAAa;AACjB,aAAS,IAAI,QAAQ,SAAS,GAAG,KAAK,KAAK,aAAa,gBAAgB,KAAK;AAC3E,aAAO,IAAI,QAAQ,CAAC,EAAG,GAAG;AAC1B,oBAAc,QAAQ,CAAC,EAAG;AAAA,IAC5B;AAAA,EACF;AAOA,MAAI,YAAY,GAAG;AACjB,aAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,YAAM,MAAM,SAAS,CAAC;AACtB,UAAI,IAAI,SAAS,UAAU,oBAAoB,KAAK,KAAK,EAAG;AAC5D,YAAM,MAAM,MAAM,YAAY,MAAM,IAAI,EAAE;AAC1C,UAAI,OAAO,QAAQ,UAAW,QAAO,IAAI,GAAG;AAC5C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAgBO,SAAS,wBACd,UACA,OACA,QACA,mBACe;AACf,QAAM,mBAMA,CAAC;AACP,QAAM,gBAKA,CAAC;AAIP,QAAM,mBAAmB,4BAA4B,UAAU,MAAM;AAErE,aAAW,OAAO,UAAU;AAC1B,QAAI,oBAAoB,KAAK,KAAK,EAAG;AACrC,UAAM,MAAM,MAAM,YAAY,MAAM,IAAI,EAAE;AAC1C,QAAI,CAAC,OAAO,QAAQ,UAAW;AAE/B,UAAM,KAAK,OAAO,GAAG;AAErB,QAAI,8BAA8B,KAAK,QAAQ,gBAAgB,GAAG;AAChE,oBAAc,KAAK;AAAA,QACjB;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ,sBAAsB,GAAG;AAAA,QACjC,OAAO,IAAI,WAAW,CAAC,IAAI,QAAQ,IAAI,CAAC;AAAA,MAC1C,CAAC;AACD;AAAA,IACF;AAEA,QAAI,mBAAmB,IAAI,GAAG,GAAG;AAC/B;AAAA,IACF;AAEA,qBAAiB,KAAK;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,sBAAsB,GAAG;AAAA,MACjC,QAAQ,cAAc,GAAG;AAAA,MACzB,QAAQ,IAAI,SAAS;AAAA,IACvB,CAAC;AAAA,EACH;AAQA,QAAM,eAAoC,CAAC;AAC3C,MAAI,MAAgC;AACpC,MAAI,aAAa;AAEjB,aAAW,QAAQ,kBAAkB;AACnC,UAAM,SAAS,KAAK,SAAS,aAAa;AAC1C,QAAI,QAAS,KAAK,UAAU,IAAI,SAAS,KAAM,SAAS;AACtD,mBAAa,KAAK,GAAG;AACrB,YAAM;AAAA,IACR;AACA,iBAAa,KAAK;AAClB,QAAI,CAAC,KAAK;AACR,YAAM;AAAA,QACJ,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,OAAO;AAAA,QACP,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK,SAAS,MAAM;AAAA,QAC7B,SAAS,KAAK,SAAS,IAAI;AAAA,MAC7B;AAAA,IACF,OAAO;AACL,UAAI,SAAS,KAAK;AAClB,UAAI;AACJ,UAAI,UAAU,KAAK;AACnB,UAAI,KAAK,QAAQ;AACf,YAAI,UAAU,KAAK,OAAO,IAAI,WAAW,IAAI,QAAQ,KAAK,OAAO,IAAI,KAAK;AAAA,MAC5E,OAAO;AACL,YAAI,UAAU,KAAK,MAAO,IAAI,WAAW,IAAI,QAAQ,KAAM,IAAI,KAAK;AAAA,MACtE;AACA,UAAI,UAAU,MAAM,IAAI;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,IAAK,cAAa,KAAK,GAAG;AAG9B,QAAM,kBAAoC,CAAC;AAC3C,MAAI,OAA8B;AAClC,MAAI,cAAc;AAElB,aAAW,QAAQ,eAAe;AAChC,UAAM,SAAS,KAAK,SAAS,cAAc;AAC3C,QAAI,QAAQ,QAAQ;AAClB,sBAAgB,KAAK,IAAI;AACzB,aAAO;AAAA,IACT;AACA,kBAAc,KAAK;AACnB,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,OAAO;AAAA,QACP,QAAQ,KAAK;AAAA,QACb,OAAO,CAAC,GAAG,KAAK,KAAK;AAAA,MACvB;AAAA,IACF,OAAO;AACL,WAAK,SAAS,KAAK;AACnB,WAAK;AACL,WAAK,UAAU,KAAK;AACpB,iBAAW,KAAK,KAAK,OAAO;AAC1B,YAAI,CAAC,KAAM,MAAM,SAAS,CAAC,EAAG,MAAM,MAAM,KAAK,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAM,iBAAgB,KAAK,IAAI;AAEnC,SAAO;AAAA,IACL,cAAc,aAAa,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,IACrD,WAAW;AAAA,EACb;AACF;;;AC1OO,SAAS,OACd,UACA,OACA,UAAuB,CAAC,GAChB;AACR,SAAO,EAAE,UAAU,OAAO,QAAQ;AACpC;AAEO,SAAS,YACd,OACA,SACA,KACQ;AACR,MAAI,KAAK;AACT,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,WAAW,CAAC,KAAK,QAAQ,IAAI,GAAG,EAAG;AAC5C,SAAK,KAAK,IAAI,IAAI,GAAG;AAAA,EACvB;AACA,SAAO;AACT;;;ACuCO,SAAS,WAAW,QAAe,CAAC,GAAoB;AAC7D,QAAM,cAAc,MAAM,eAAe;AAEzC,WAAS,iBACP,OACwB;AACxB,UAAM,QAA0B,WAAW,MAAM,KAAK;AACtD,UAAM,QAAQ,cAAc,KAAK;AACjC,QAAI,gBAAgB;AACpB,QAAI,mBAAmB;AACvB,UAAM,SAAmB,CAAC;AAK1B,UAAM,sBACJ,MAAM,uBACN,qBAAqB,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM;AAEhE,UAAM,sBAAsB,gBAAgB,KAAK;AAEjD,UAAM,iBAA6E,CAAC;AACpF,eAAW,QAAQ,MAAM,QAAQ;AAC/B,UAAI;AACJ,UAAI;AACF,mBAAW,kBAAkB;AAAA,UAC3B,UAAU,KAAK;AAAA,UACf,QAAQ,KAAK;AAAA,UACb,UAAU,MAAM;AAAA,UAChB;AAAA,QACF,CAAC;AAAA,MACH,QAAQ;AACN;AAAA,MACF;AACA,YAAM,UAAU,SAAS,WAAW;AAAA,QAAI,CAAC,OACvC,MAAM,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,MAC7C,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;AACtB,qBAAe,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,IACvC;AACA,UAAM,eAAe,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,MAAM;AACtD,YAAM,OAAO,EAAE,QAAQ,SAAS,IAAI,KAAK,IAAI,GAAG,EAAE,OAAO,IAAI;AAC7D,YAAM,OAAO,EAAE,QAAQ,SAAS,IAAI,KAAK,IAAI,GAAG,EAAE,OAAO,IAAI;AAC7D,aAAO,OAAO;AAAA,IAChB,CAAC;AACD,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,YAAM,OAAO,aAAa,IAAI,CAAC;AAC/B,YAAM,OAAO,aAAa,CAAC;AAC3B,YAAM,UAAU,KAAK,QAAQ,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI;AACtE,YAAM,UAAU,KAAK,QAAQ,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI;AACtE,UAAI,WAAW,WAAW,WAAW,GAAG;AACtC,eAAO;AAAA,UACL,OAAO,MAAM;AAAA,UACb,QAAQ;AAAA,YACN,eAAe;AAAA,YACf,kBAAkB;AAAA,YAClB,QAAQ;AAAA,cACN,mBAAmB,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM,eAAe,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA,YAClH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,OAAO,SAAS,mBAAmB,KAAK,MAAM,OAAO,SAAS,GAAG;AACzE,UAAI,kBAAkB;AACtB,UAAI,wBAAwB;AAC5B,iBAAW,QAAQ,MAAM,QAAQ;AAC/B,YAAI;AACJ,YAAI;AACF,qBAAW,kBAAkB;AAAA,YAC3B,UAAU,KAAK;AAAA,YACf,QAAQ,KAAK;AAAA,YACb,UAAU,MAAM;AAAA,YAChB;AAAA,UACF,CAAC;AAAA,QACH,QAAQ;AACN;AAAA,QACF;AACA,YAAI,SAAS,iBAAiB,SAAS;AACrC,kCAAwB;AACxB;AAAA,QACF;AACA,mBAAW,MAAM,SAAS,YAAY;AACpC,gBAAM,MAAM,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAClD,6BAAmB,KAAK,MAAM,UAAU;AAAA,QAC1C;AAAA,MACF;AACA,UAAI,CAAC,yBAAyB,kBAAkB,MAAM,OAAO,SAAS,kBAAkB;AACtF,eAAO;AAAA,UACL,OAAO,MAAM;AAAA,UACb,QAAQ;AAAA,YACN,eAAe;AAAA,YACf,kBAAkB;AAAA,YAClB,QAAQ;AAAA,cACN,yCAAyC,eAAe,iBAAiB,MAAM,OAAO,MAAM,kBAAkB,MAAM,OAAO,SAAS,gBAAgB;AAAA,YACtJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,eAAW,QAAQ,MAAM,QAAQ;AAC/B,UAAI;AACF,cAAM,aAAa,iBAAiB;AAAA,UAClC;AAAA,UACA,UAAU,MAAM;AAAA,UAChB;AAAA,UACA;AAAA,UACA,QAAQ,MAAM;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD;AACA,4BAAoB;AAAA,MACtB,SAAS,OAAO;AACd,eAAO,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACpE;AAAA,IACF;AAEA,UAAM,MAAM,oBAAoB;AAChC,UAAM,MAAM,oBAAoB;AAEhC,QAAI,gBAAgB,GAAG;AAIrB,YAAM,MAAM,4BAA4B;AACxC,YAAM,MAAM,uBAAuB;AAInC,YAAM,MAAM,kBAAkB,CAAC;AAAA,IACjC;AAEA,WAAO,EAAE,OAAO,QAAQ,EAAE,eAAe,kBAAkB,OAAO,EAAE;AAAA,EACtE;AAEA,WAAS,YAAY,OAA4C;AAC/D,UAAM,eAAe,eAAe,MAAM,MAAM;AAChD,QAAI,aAAa,SAAS,GAAG;AAC3B,cAAQ,KAAK,4CAA4C,aAAa,KAAK,IAAI,CAAC,sCAAsC;AAAA,IACxH;AACA,UAAM,MAAuB;AAAA,MAC3B,QAAQ,MAAM;AAAA,MACd,YAAY,MAAM;AAAA,MAClB;AAAA,IACF;AACA,UAAM,UAAkB;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,SAAS,CAAC;AAAA,IACZ;AACA,UAAM,SAAS,YAAY,aAAa,GAAG,SAAS,GAAG;AACvD,WAAO;AAAA,MACL,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO;AAAA,MACd,OAAO,OAAO,QAAQ;AAAA,IACxB;AAAA,EACF;AAEA,WAAS,WAAW,SAAiB,OAAyB;AAC5D,WAAO,UAAU,OAAO,OAAO;AAAA,EACjC;AAEA,WAAS,OAAO,OAAe,OAA6C;AAC1E,UAAM,QAAQ,MACX,YAAY,EACZ,MAAM,KAAK,EACX,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACnC,QAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAChC,UAAM,SAAS,aAAa,KAAK,EAC9B,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,eAAe,OAAO,KAAK,EAAE,EAAE,EAC/D,OAAO,CAAC,UAAU,MAAM,QAAQ,GAAG,EACnC,KAAK,CAAC,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK;AACjD,WAAO,OAAO,IAAI,CAAC,UAAU,MAAM,KAAK;AAAA,EAC1C;AAEA,WAAS,OACP,OACA,YACA,QACc;AACd,UAAM,SAAS,aAAa,KAAK;AACjC,UAAM,QACJ,OAAO,oBAAoB,IAAI,aAAa,OAAO,oBAAoB;AACzE,WAAO;AAAA,MACL,cAAc;AAAA,MACd;AAAA,MACA,mBAAmB,OAAO;AAAA,MAC1B,cAAc,OAAO;AAAA,MACrB,aAAa,MAAM,OAAO;AAAA,MAC1B,kBAAkB,MAAM,MAAM;AAAA,MAC9B,WAAW,EAAE,QAAQ,OAAO,QAAQ,OAAO,MAAM,OAAO,OAAO;AAAA,IACjE;AAAA,EACF;AAEA,WAAS,eAA+B;AACtC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,aAAa,kBAAkB,cAAc,YAAY,QAAQ,OAAO;AACnF;AAQA,IAAM,iBAA+B;AAAA,EACnC,MAAM;AAAA,EACN,IAAI,IAAI,KAAK;AACX,UAAM,gBACJ,IAAI,OAAO,eAAe,SAAS,KAAK,CAAC,CAAC,IAAI,OAAO;AACvD,UAAM,cAAc,gBAChB,CAAC,MAAmB,mBAAmB,GAAG,IAAI,MAAM,IACpD;AACJ,UAAM,YAAY,WAAW,GAAG,UAAU;AAAA,MACxC,UAAU,GAAG,MAAM;AAAA,MACnB,WAAW,iBAAiB,GAAG,MAAM,WAAW,IAAI;AAAA,MACpD,aAAa;AAAA,IACf,CAAC;AACD,WAAO,EAAE,GAAG,IAAI,OAAO,EAAE,GAAG,GAAG,OAAO,aAAa,UAAU,IAAI,EAAE;AAAA,EACrE;AACF;AAEA,IAAM,iBAA+B;AAAA,EACnC,MAAM;AAAA,EACN,IAAI,IAAI,KAAK;AACX,UAAM,SAAS,WAAW,GAAG,UAAU,GAAG,KAAK;AAC/C,oBAAgB,OAAO,OAAO,IAAI,OAAO,kBAAkB;AAC3D,WAAO,EAAE,GAAG,IAAI,OAAO,OAAO,MAAM;AAAA,EACtC;AACF;AAEA,IAAM,YAA0B;AAAA,EAC9B,MAAM;AAAA,EACN,IAAI,IAAI;AACN,WAAO,EAAE,GAAG,IAAI,UAAU,MAAM,GAAG,UAAU,GAAG,KAAK,EAAE;AAAA,EACzD;AACF;AAEA,IAAM,aAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,SAAS,CAAC,KAAK,QACb,CAAC,CAAC,IAAI,OAAO,gBAAgB,WAAW,mBAAmB,EAAE,SAAS;AAAA,EACxE,IAAI,IAAI,KAAK;AACX,UAAM,UAAU,oBAAoB,GAAG,UAAU,IAAI,OAAO,cAAc;AAC1E,WAAO,EAAE,GAAG,IAAI,UAAU,QAAQ,SAAS;AAAA,EAC7C;AACF;AAEA,IAAM,wBAAsC;AAAA,EAC1C,MAAM;AAAA,EACN,IAAI,IAAI;AACN,UAAM,SAAS,0BAA0B,GAAG,OAAO,GAAG,QAAQ;AAC9D,WAAO,EAAE,GAAG,IAAI,UAAU,OAAO,SAAS;AAAA,EAC5C;AACF;AAEA,IAAM,gBAA8B;AAAA,EAClC,MAAM;AAAA,EACN,IAAI,IAAI,KAAK;AACX,UAAM,gBAAgB;AAAA,MACpB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,IAAI;AAAA,IACN;AACA,UAAM,gBAAgB;AAAA,MACpB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,IAAI;AAAA,MACJ;AAAA,IACF;AACA,UAAM,oBAAoB,cAAc,aAAa,WAAW;AAChE,UAAM,iBAAiC;AAAA,MACrC;AAAA,MACA,mBAAmB,cAAc;AAAA,MACjC;AAAA,IACF;AACA,WAAO,EAAE,GAAG,IAAI,SAAS,EAAE,GAAG,GAAG,SAAS,eAAe,EAAE;AAAA,EAC7D;AACF;AAEA,IAAM,YAA0B;AAAA,EAC9B,MAAM;AAAA,EACN,IAAI,IAAI,KAAK;AACX,UAAM,QAAQ,YAAY;AAAA,MACxB,YAAY,IAAI;AAAA,MAChB,QAAQ,IAAI;AAAA,MACZ,OAAO,GAAG;AAAA,MACV,UAAU,GAAG;AAAA,MACb,gBAAgB,GAAG,QAAQ;AAAA,MAC3B,aAAa,IAAI;AAAA,IACnB,CAAC;AAED,UAAM,WAAW,GAAG,MAAM,MAAM;AAChC,UAAM,oBAAoB;AAAA,MACxB,IAAI,OAAO;AAAA,MACX,IAAI,OAAO;AAAA,IACb;AAEA,QAAI,UAAU,EAAE,GAAG,GAAG,MAAM,MAAM;AAElC,QACE,WAAW,KACX,IAAI,aAAa,WAAW,mBAC5B;AACA,cAAQ,4BAA4B,IAAI;AACxC,cAAQ,uBAAuB;AAAA,IACjC;AAEA,QAAI,QAAQ,8BAA8B,GAAG;AAC3C,cAAQ,4BAA4B,IAAI;AAAA,IAC1C;AAEA,QAAI,MAAM,cAAc;AACtB,cAAQ,uBAAuB,IAAI;AAInC,UAAI,MAAM,SAAS,MAAM;AACvB,gBAAQ,kBAAkB,EAAE,GAAG,QAAQ,iBAAiB,CAAC,MAAM,IAAI,GAAG,IAAI,WAAW;AAAA,MACvF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO,EAAE,GAAG,GAAG,OAAO,OAAO,QAAQ;AAAA,MACrC,SAAS,EAAE,GAAG,GAAG,SAAS,MAAM;AAAA,IAClC;AAAA,EACF;AACF;AAEA,IAAM,wBAAsC;AAAA,EAC1C,MAAM;AAAA,EACN,IAAI,IAAI,KAAK;AACX,UAAM,QACJ,IAAI,OAAO,oBAAoB,IAC3B,IAAI,aAAa,IAAI,OAAO,oBAC5B;AACN,QAAI,QAAQ,IAAI,OAAO,SAAS,UAAW,QAAO;AAClD,UAAM,QAAQ;AAAA,MACZ,GAAG;AAAA,MACH,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,EAAE,uBAAuB,IAAI,OAAO,uBAAuB;AAAA,IAC7D;AACA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,MAAM;AAAA,MAChB,SAAS,EAAE,GAAG,GAAG,SAAS,gBAAgB,MAAM,eAAe;AAAA,IACjE;AAAA,EACF;AACF;AAaA,SAAS,iBAAiB,OAAiC;AACzD,QAAM,WAAW,kBAAkB;AAAA,IACjC,UAAU,MAAM,KAAK;AAAA,IACrB,QAAQ,MAAM,KAAK;AAAA,IACnB,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,EACf,CAAC;AAED,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA,MAAM;AAAA,EACR;AAIA,MAAI,gBAAgB,SAAS,SAAS,WAAW,QAAQ;AACvD,UAAM,eAAe,oBAAI,IAAoB;AAC7C,UAAM,SAAS,QAAQ,CAAC,GAAG,MAAM,aAAa,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1D,UAAM,gBAAgB,aAAa,IAAI,gBAAgB,CAAC,CAAE,KAAK,SAAS;AACxE,UAAM,cAAc,aAAa,IAAI,gBAAgB,gBAAgB,SAAS,CAAC,CAAE,KAAK,SAAS;AAC/F,UAAM,aAAa,IAAI,IAAI,SAAS,cAAc;AAClD,eAAWC,UAAS,aAAa,MAAM,KAAK,GAAG;AAC7C,UAAI,WAAW,IAAIA,OAAM,OAAO,EAAG;AACnC,YAAM,SAAS,mBAAmBA,OAAM,qBAAqB,YAAY;AACzE,UAAI,WAAW,QAAQ,UAAU,iBAAiB,UAAU,aAAa;AACvE,mBAAW,IAAIA,OAAM,OAAO;AAC5B,iBAAS,eAAe,KAAKA,OAAM,OAAO;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,kBAAkB,SAAS,iBAAiB;AAClD,QAAM,aAAa;AAAA,IACjB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,EACF;AACA,QAAM,aAAa,kBACd,KAAK,IAAI,GAAG,aAAa,CAAC,IAC3B;AAEJ,QAAM,mBAAmB,SAAS,eAAe,OAAO,CAAC,OAAO;AAC9D,UAAMA,SAAQ,UAAU,MAAM,OAAO,EAAE;AACvC,WAAOA,QAAO,UAAUA,OAAM,SAAS;AAAA,EACzC,CAAC;AAED,QAAM,sBAAsB,IAAI,IAAY,eAAe;AAC3D,aAAW,cAAc,kBAAkB;AACzC,UAAM,WAAW,UAAU,MAAM,OAAO,UAAU;AAClD,QAAI,UAAU;AACZ,iBAAW,MAAM,SAAS;AACxB,4BAAoB,IAAI,EAAE;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,mBAAmB,CAAC,GAAG,mBAAmB,EAAE;AAAA,IAChD,CAAC,OAAO,CAAC,MAAM,oBAAoB,IAAI,EAAE;AAAA,EAC3C;AAEA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAQA,QAAM,gBAAgB,MAAM;AAC5B,QAAM,kBAAkB,gBACpB,YAAY,OAAO,CAAC,OAAO;AACzB,UAAM,MAAM,MAAM,MAAM,YAAY,MAAM,EAAE;AAC5C,WAAO,QAAQ,UAAa,cAAc,IAAI,GAAG;AAAA,EACnD,CAAC,IACD,CAAC;AACL,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,UAAU,MAAM,OAAO;AAC7B,UAAM,UAAU,gBACb,IAAI,CAAC,OAAO,MAAM,MAAM,YAAY,MAAM,EAAE,CAAC,EAC7C,OAAO,OAAO;AACjB,UAAM,IAAI;AAAA,MACR,+CAA+C,OAAO,gFAAgF,QAAQ;AAAA,QAC5I;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,2BAAyB,OAAO,aAAa,iBAAiB,MAAM;AAEpE,MAAI,mBAAmB;AACvB,aAAW,MAAM,aAAa;AAC5B,UAAM,UAAU,MAAM,SAAS,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE;AAC9D,wBAAoB,MAAM,YAAY,SAAS,QAAQ,EAAE;AAAA,EAC3D;AACA,aAAW,cAAc,kBAAkB;AACzC,UAAM,WAAW,UAAU,MAAM,OAAO,UAAU;AAClD,QAAI,UAAU;AACZ,0BAAoB,MAAM,YAAY,SAAS,OAAO;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,UAAU,gBAAgB,MAAM,KAAK;AAC3C,QAAM,QAA0B;AAAA,IAC9B;AAAA,IACA,OAAO,MAAM;AAAA,IACb,MAAM;AAAA,IACN,OAAO,MAAM,KAAK;AAAA,IAClB,SAAS,MAAM,KAAK;AAAA,IACpB,kBAAkB;AAAA,IAClB,qBAAqB,CAAC,GAAG,mBAAmB;AAAA,IAC5C,gBAAgB,CAAC,GAAG,gBAAgB;AAAA,IACpC;AAAA,IACA,WAAW,KAAK,IAAI;AAAA,IACpB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,gBAAgB,MAAM,KAAK;AAAA,EAC7B;AACA,QAAM,MAAM,OAAO,KAAK,KAAK;AAE7B,aAAW,cAAc,kBAAkB;AACzC,UAAM,WAAW,UAAU,MAAM,OAAO,UAAU;AAClD,QAAI,SAAU,UAAS,SAAS;AAAA,EAClC;AAEA,SAAO;AACT;AAEA,SAAS,wBACP,UACA,UACU;AACV,MAAI,SAAS,iBAAiB,SAAS;AACrC,WAAO,SAAS;AAAA,EAClB;AACA,QAAM,WAAW;AAAA,IACf,SAAS;AAAA,IACT,SAAS;AAAA,IACT;AAAA,EACF;AACA,MACE,SAAS,eAAe,SAAS,cACjC,SAAS,aAAa,SAAS,UAC/B;AACA,WAAO,SAAS;AAAA,EAClB;AACA,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,SAAS,YAAY,KAAK,SAAS,UAAU,KAAK;AAC7D,UAAM,MAAM,SAAS,CAAC;AACtB,QAAI,IAAK,KAAI,KAAK,IAAI,EAAE;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,yBACP,OACA,kBACA,oBACM;AACN,QAAM,MAAM,MAAM,OAAO;AACzB,QAAM,UAAU,MAAM,KAAK,SAAS,KAAK,KAAK;AAE9C,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,IAAI,mBAAmB,KAAK,QAAQ,SAAS,IAAI,kBAAkB;AACrE,UAAM,IAAI;AAAA,MACR,sBAAsB,QAAQ,MAAM,eAAe,IAAI,gBAAgB;AAAA,IACzE;AAAA,EACF;AAEA,QAAM,eAAe,MAAM,KAAK,mBAAmB,IAAI;AACvD,MACE,eAAe,KACf,QAAQ,SAAS,cACjB;AACA,UAAM,IAAI;AAAA,MACR,qBAAqB,QAAQ,MAAM,eAAe,YAAY;AAAA,IAChE;AAAA,EACF;AAEA,MAAI,iBAAiB,WAAW,KAAK,uBAAuB,GAAG;AAC7D,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,4BACP,kBACA,UACA,QACU;AAKV,QAAM,mBAAmB,oBAAI,IAAY;AACzC,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,OAAO,UAAU;AAC1B,QAAI,mBAAmB,KAAK,MAAM,KAAK,IAAI,YAAY;AACrD,uBAAiB,IAAI,IAAI,UAAU;AAAA,IACrC;AAAA,EACF;AAEA,aAAW,MAAM,kBAAkB;AACjC,UAAM,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC5C,QAAI,CAAC,IAAK;AACV,QAAI,mBAAmB,KAAK,MAAM,GAAG;AACnC,iBAAW,IAAI,EAAE;AACjB,UAAI,IAAI,WAAY,kBAAiB,IAAI,IAAI,UAAU;AAAA,IACzD;AAAA,EACF;AAEA,aAAW,MAAM,kBAAkB;AACjC,QAAI,WAAW,IAAI,EAAE,EAAG;AACxB,UAAM,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC5C,QAAI,CAAC,IAAK;AACV,QACE,IAAI,gBAAgB,iBACpB,IAAI,cACJ,iBAAiB,IAAI,IAAI,UAAU,GACnC;AACA,iBAAW,IAAI,EAAE;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,iBAAiB,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;AAC5D;AAEA,SAAS,kBACP,OACA,gBACA,iBACiB;AACjB,MAAI,CAAC,gBAAiB,QAAO;AAC7B,MAAI,eAAe,WAAW,EAAG,QAAO;AACxC,MAAI,UAA2B;AAC/B,aAAW,MAAM,gBAAgB;AAC/B,UAAM,QAAQ,UAAU,OAAO,EAAE;AACjC,QAAI,SAAS,MAAM,OAAO,QAAS,WAAU,MAAM;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAsC;AAC7D,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,SAAS,aAAa,KAAK,GAAG;AACvC,eAAW,MAAM,MAAM,oBAAqB,UAAS,IAAI,EAAE;AAAA,EAC7D;AACA,SAAO;AACT;AAWA,SAAS,sBACP,mBACA,OACQ;AACR,MAAI,CAAC,qBAAqB,qBAAqB,EAAG,QAAO,MAAM;AAC/D,SAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,KAAK;AAAA,MACH,MAAM;AAAA,MACN,KAAK,MAAM,oBAAoB,MAAM,WAAW;AAAA,IAClD;AAAA,EACF;AACF;AAQA,SAAS,cACP,OACA,gBACA,aACuE;AACvE,QAAM,MAA6E,CAAC;AACpF,QAAM,eAAe,gBAAgB,cAAc,gBAAgB,CAAC;AACpE,MAAI,CAAC,IAAI,EAAE,SAAS,aAAa,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,GAAG,cAAc,CAAC,EAAE;AACrF,QAAM,SAAS,aAAa,KAAK;AACjC,QAAM,KAAK,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC5C,QAAM,KAAK,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC5C,MAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,MAAM,IAAI,YAAY,EAAE,OAAO,GAAG,CAAC,GAAG,cAAc,GAAG;AACzF,MAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,MAAM,IAAI,YAAY,EAAE,OAAO,GAAG,CAAC,GAAG,cAAc,GAAG;AACzF,SAAO;AACT;AAEA,SAAS,YAAY,OAAkC;AACrD,QAAM,EAAE,QAAQ,OAAO,YAAY,gBAAgB,YAAY,IAAI;AACnE,QAAM,QAAQ,OAAO;AACrB,QAAM,QAAQ,QAAQ,IAAI,aAAa,QAAQ;AAE/C,QAAM,oBAAoB,sBAAsB,OAAO,OAAO,KAAK;AAEnE,QAAM,oBAAoB,SAAS,OAAO,MAAM;AAEhD,QAAM,WAAW,MAAM,MAAM;AAC7B,QAAM,kBAAkB,MAAM,MAAM,uBAAuB;AAE3D,QAAM,kBAAkB;AACxB,QAAM,qBAAqB,kBACvB,KAAK,MAAM,oBAAoB,CAAC,IAChC;AAEJ,QAAM,kBACJ,MAAM,MAAM,uBAAuB,IAC/B,MAAM,MAAM,uBACZ,WAAW,IACT,WACA;AAER,QAAM,cAAc,KAAK;AAAA,IACvB,OAAO,MAAM;AAAA,IACb,OAAO,MAAM,iBAAiB;AAAA,EAChC;AAEA,QAAM,uBAAuB,aAAa;AAE1C,QAAM,MAAM;AACZ,QAAM,QAAQ,cAAc,OAAO,KAAK,WAAW;AAOnD,MAAI,eAAuC;AAC3C,MAAI,iBAAiB;AAKrB,QAAM,cAAc,wBAAwB;AAC5C,MAAI,CAAC,qBAAqB,aAAa;AACrC,eAAW,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAY;AACrC,UAAI,CAAC,OAAO,MAAM,WAAW,OAAO,EAAG;AACvC,YAAM,OAAO,MAAM,IAAI;AACvB,UAAI,CAAC,QAAQ,KAAK,UAAU,kBAAmB;AAC/C,YAAM,YAAY,MAAM,MAAM,gBAAgB,IAAI,KAAK;AAGvD,YAAM,aAAa,cAAc,KAAK,aAAa,aAAa;AAChE,UAAI,CAAC,WAAY;AACjB,qBAAe;AACf,uBAAiB,SAAS,IACtB,mBAAmB,KAAK,OAAO,OAAO,iBAAiB,YAAY,oBAAoB,WAAW,KAAK,MAAM,QAAQ,GAAG,CAAC,MACzH,IAAI,IAAI,mBAAmB,KAAK,aAAa,MAAM,SAAS,OAAO,CAAC,YAAY,KAAK,OAAO,eAAe,iBAAiB,WAAW,KAAK,MAAM,QAAQ,GAAG,CAAC;AAClK;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,qBAAqB,iBAAiB;AAE3D,MAAI;AACJ,MAAI,mBAAmB;AACrB,aAAS,oBAAoB,KAAK,MAAM,QAAQ,GAAG,CAAC,QAAQ,KAAK,MAAM,OAAO,MAAM,wBAAwB,GAAG,CAAC;AAAA,EAClH,WAAW,iBAAiB,MAAM;AAChC,aAAS;AAAA,EACX,OAAO;AACL,UAAM,YAAY,CAAC,GAAG,GAAG,CAAC;AAC1B,UAAM,WAAW,UAAU,OAAO,CAAC,MAAM,OAAO,MAAM,WAAW,MAAM,CAAC;AACxE,UAAM,QAAQ,SACX,OAAO,CAAC,OAAO,MAAM,CAAC,GAAG,WAAW,MAAM,iBAAiB,EAC3D,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,EAAG,OAAO,EAAE;AAC1C,UAAM,YAAY,MAAM,SAAS,IAAI,YAAY,MAAM,KAAK,IAAI,CAAC,KAAK;AACtE,UAAM,UAAU,SACb,OAAO,CAAC,OAAO,MAAM,CAAC,GAAG,WAAW,MAAM,sBAAsB,MAAM,MAAM,gBAAgB,CAAC,KAAK,KAAK,KAAK,cAAc,MAAM,MAAM,gBAAgB,CAAC,KAAK,KAAK,WAAW,EAC5K,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY;AAC/B,UAAM,cAAc,QAAQ,SAAS,IAAI,cAAc,QAAQ,KAAK,IAAI,CAAC,KAAK;AAC9E,UAAM,aAAa,KAAK,IAAI,GAAG,GAAG,OAAO,OAAO,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAK5E,UAAM,eAAe,aAAa;AAClC,UAAM,cAAc,uBAAuB;AAC3C,UAAM,QAAkB,CAAC;AACzB,QAAI,aAAc,OAAM,KAAK,oBAAoB,UAAU,gBAAgB,iBAAiB,EAAE;AAC9F,QAAI,YAAa,OAAM,KAAK,UAAU,oBAAoB,YAAY,WAAW,EAAE;AACnF,QAAI,MAAM,WAAW,EAAG,OAAM,KAAK,oBAAoB,UAAU,YAAY,oBAAoB,EAAE;AACnG,aAAS,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,WAAW;AAAA,EACxD;AAEA,QAAM,eAAe,wBAAwB,MAAM,UAAU,YAAY,oBAAoB;AAE7F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,oBAAoB,KAAK,qBAAqB,CAAC;AAAA,IAC/C,iBAAiB,KAAK,cAAc,aAAa,CAAC;AAAA,IAClD,kBAAkB,eAAe,MAAM,YAAY,EAAG,eAAe,CAAC;AAAA,IACtE,cAAc;AAAA,IACd,MAAM;AAAA,IACN,WAAW;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,kBAAkB,IAAI;AAAA,MACvC,mBAAmB,oBAAoB,IAAI;AAAA,MAC3C,WAAW,MAAM,CAAC,EAAG;AAAA,MACrB,WAAW,MAAM,CAAC,EAAG;AAAA,MACrB,WAAW,MAAM,CAAC,EAAG;AAAA,IACvB;AAAA,IACA,kBAAkB;AAAA,EACpB;AACF;AAEA,SAAS,wBAAwB,UAAyB,OAAe,QAAkC;AACzG,MAAI,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,OAAO,GAAG,OAAO;AAC1D,aAAW,OAAO,UAAU;AAC1B,UAAM,SAAS,KAAK,MAAM,IAAI,QAAQ,IAAI,SAAS,CAAC;AACpD,QAAI,IAAI,MAAM,WAAW,mCAAmC,GAAG;AAC7D,mBAAa;AAAA,IACf,WAAW,IAAI,gBAAgB,eAAe,IAAI,gBAAgB,eAAe;AAC/E,cAAQ;AAAA,IACV,WAAW,IAAI,SAAS,UAAU;AAChC,gBAAU;AAAA,IACZ,WAAW,IAAI,MAAM,SAAS,KAAK,GAAG;AACpC,cAAQ;AAAA,IACV,OAAO;AACL,cAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,MAAM,WAAW,MAAM,MAAM,OAAO,OAAO;AAC9D;AAEA,SAAS,WAAW,OAA2C;AAC7D,SAAO;AAAA,IACL,QAAQ,MAAM,OAAO,IAAI,CAAC,WAAW;AAAA,MACnC,GAAG;AAAA,MACH,kBAAkB,CAAC,GAAG,MAAM,gBAAgB;AAAA,MAC5C,qBAAqB,CAAC,GAAG,MAAM,mBAAmB;AAAA,MAClD,gBAAgB,CAAC,GAAG,MAAM,cAAc;AAAA,IAC1C,EAAE;AAAA,IACF,aAAa;AAAA,MACX,OAAO,EAAE,GAAG,MAAM,YAAY,MAAM;AAAA,MACpC,OAAO,EAAE,GAAG,MAAM,YAAY,MAAM;AAAA,IACtC;AAAA,IACA,OAAO,EAAE,GAAG,MAAM,OAAO,SAAS,EAAE,GAAG,MAAM,MAAM,QAAQ,EAAE;AAAA,IAC7D,OAAO,EAAE,GAAG,MAAM,MAAM;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,WAAW,MAAM;AAAA,EACnB;AACF;AAEA,SAAS,eAAe,OAAyB,OAAyB;AACxE,QAAM,SAAS,MAAM,SAAS,IAAI,YAAY;AAC9C,QAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,MAAI,QAAQ;AACZ,aAAW,QAAQ,OAAO;AACxB,UAAM,YAAY,iBAAiB,OAAO,IAAI;AAC9C,QAAI,YAAY,EAAG,UAAS,KAAK,IAAI,YAAY,MAAM,IAAI;AAC3D,UAAM,cAAc,iBAAiB,SAAS,IAAI;AAClD,QAAI,cAAc,EAAG,UAAS,KAAK,IAAI,cAAc,MAAM,GAAG;AAAA,EAChE;AACA,SAAO,KAAK,IAAI,OAAO,CAAC;AAC1B;AAEA,SAAS,iBAAiB,UAAkB,QAAwB;AAClE,MAAI,CAAC,YAAY,CAAC,OAAQ,QAAO;AACjC,MAAI,QAAQ;AACZ,MAAI,WAAW;AACf,UAAQ,WAAW,SAAS,QAAQ,QAAQ,QAAQ,OAAO,IAAI;AAC7D;AACA,gBAAY,OAAO;AAAA,EACrB;AACA,SAAO;AACT;;;ACh7BO,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAO5B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuC9B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+B5B,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC1EpC,IAAM,kBAAkB;AAAA;AAAA,EAA6K,mBAAmB;AAExN,IAAM,mBAAmB;AAAA;AAAA,EAAiF,mBAAmB;AAE7H,SAAS,QAAQ,GAAmB;AAClC,MAAI,KAAK,IAAM,QAAO,IAAI,IAAI,KAAM,QAAQ,CAAC,CAAC;AAC9C,SAAO,GAAG,CAAC;AACb;AAEA,SAAS,gBAAgB,IAA+B;AACtD,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,QAAkB,CAAC;AACzB,MAAI,GAAG,SAAS,EAAG,OAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,SAAS;AAC5D,MAAI,GAAG,OAAO,EAAG,OAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC,OAAO;AACtD,MAAI,GAAG,YAAY,EAAG,OAAM,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC,YAAY;AACrE,MAAI,GAAG,OAAO,EAAG,OAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC,OAAO;AACtD,MAAI,GAAG,OAAO,EAAG,OAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC,OAAO;AACtD,QAAM,SAAS,GAAG,SAAS,IAAI;AAAA,GAAM,QAAQ,GAAG,MAAM,CAAC,sBAAsB;AAC7E,SAAO,sBAAsB,MAAM,KAAK,KAAK,CAAC,GAAG,MAAM;AACzD;AAIA,SAAS,uBAAuB,QAAoC;AAClE,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,OAAO,IAAI,CAAC,MAAM;AAC9B,UAAM,gBAAgB,KAAK,MAAM,EAAE,WAAW,IAAI,SAAS,CAAC;AAC5D,UAAM,QAAQ,EAAE,QAAQ,MAAM,EAAE,KAAK,MAAM;AAC3C,WAAO,KAAK,EAAE,OAAO,KAAK,EAAE,oBAAoB,MAAM,UAAU,QAAQ,EAAE,gBAAgB,CAAC,SAAI,QAAQ,aAAa,CAAC,GAAG,KAAK;AAAA,EAC/H,CAAC;AACD,SAAO,UAAU,OAAO,CAAC,EAAG,SAAS,IAAI,WAAW,QAAQ,uBAAuB,OAAO,MAAM;AAAA,EAAO,MAAM,KAAK,IAAI,CAAC;AACzH;AAEO,SAAS,aAAa,cAAmC,iBAA2C;AACzG,MAAI,aAAa,WAAW,KAAK,gBAAgB,WAAW,GAAG;AAC7D,WAAO;AAAA,EACT;AAaA,QAAMC,UAAS,CAAC,QAAwB;AACtC,UAAM,IAAI,IAAI,MAAM,KAAK;AACzB,WAAO,IAAI,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI;AAAA,EAClC;AACA,QAAM,UAAoB,CAAC;AAC3B,aAAW,KAAK,cAAc;AAC5B,YAAQ,KAAK;AAAA,MACX,UAAU,EAAE;AAAA,MAAU,QAAQ,EAAE;AAAA,MAAQ,UAAUA,QAAO,EAAE,QAAQ;AAAA,MAAG,QAAQA,QAAO,EAAE,MAAM;AAAA,MAC7F,OAAO,EAAE;AAAA,MAAO,QAAQ,EAAE;AAAA,MAAQ,SAAS,EAAE;AAAA,MAAS,SAAS,EAAE;AAAA,MACjE,oBAAoB,EAAE;AAAA,MAAQ,mBAAmB,EAAE;AAAA,MACnD,iBAAiB;AAAA,MAAG,gBAAgB;AAAA,MAAG,gBAAgB,CAAC;AAAA,MAAG,WAAW,EAAE,aAAa;AAAA,IACvF,CAAC;AAAA,EACH;AACA,aAAW,KAAK,iBAAiB;AAC/B,YAAQ,KAAK;AAAA,MACX,UAAU,EAAE;AAAA,MAAU,QAAQ,EAAE;AAAA,MAAQ,UAAUA,QAAO,EAAE,QAAQ;AAAA,MAAG,QAAQA,QAAO,EAAE,MAAM;AAAA,MAC7F,OAAO,EAAE;AAAA,MAAO,QAAQ,EAAE;AAAA,MAAQ,SAAS;AAAA,MAAG,SAAS;AAAA,MACvD,oBAAoB;AAAA,MAAG,mBAAmB;AAAA,MAC1C,iBAAiB,EAAE;AAAA,MAAQ,gBAAgB,EAAE;AAAA,MAAO,gBAAgB,CAAC,GAAG,EAAE,KAAK;AAAA,MAAG,WAAW;AAAA,IAC/F,CAAC;AAAA,EACH;AACA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAE9C,QAAM,SAAmB,CAAC;AAC1B,aAAW,KAAK,SAAS;AACvB,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAI,QAAQ,EAAE,YAAY,KAAK,SAAS,GAAG;AACzC,WAAK,SAAS,EAAE;AAChB,WAAK,SAAS,KAAK,IAAI,KAAK,QAAQ,EAAE,MAAM;AAC5C,WAAK,SAAS,EAAE;AAChB,WAAK,UAAU,EAAE;AACjB,WAAK,sBAAsB,EAAE;AAC7B,WAAK,qBAAqB,EAAE;AAC5B,WAAK,mBAAmB,EAAE;AAC1B,WAAK,kBAAkB,EAAE;AACzB,UAAI,EAAE,UAAW,MAAK,YAAY;AAClC,iBAAW,KAAK,EAAE,gBAAgB;AAChC,YAAI,CAAC,KAAK,eAAe,SAAS,CAAC,EAAG,MAAK,eAAe,KAAK,CAAC;AAAA,MAClE;AAAA,IACF,OAAO;AACL,aAAO,KAAK,EAAE,GAAG,EAAE,CAAC;AAAA,IACtB;AAAA,EACF;AACA,QAAM,QAAQ,OAAO,IAAI,CAAC,MAAM;AAC9B,UAAM,SAAS,EAAE,aAAa,EAAE,qBAAqB,IAAI,2DAAiD;AAC1G,QAAI,EAAE,kBAAkB,KAAK,EAAE,uBAAuB,GAAG;AACvD,aAAO,KAAK,EAAE,QAAQ,SAAI,EAAE,MAAM,KAAK,EAAE,KAAK,UAAU,QAAQ,EAAE,MAAM,CAAC,gBAAgB,EAAE,eAAe,KAAK,IAAI,CAAC,4BAAuB,MAAM;AAAA,IACnJ;AACA,QAAI,EAAE,kBAAkB,KAAK,EAAE,qBAAqB,GAAG;AACrD,aAAO,KAAK,EAAE,QAAQ,SAAI,EAAE,MAAM,KAAK,EAAE,KAAK,UAAU,QAAQ,EAAE,MAAM,CAAC,KAAK,QAAQ,EAAE,kBAAkB,CAAC,mBAAmB,QAAQ,EAAE,eAAe,CAAC,eAAe,EAAE,eAAe,KAAK,IAAI,CAAC,IAAI,MAAM;AAAA,IAC9M;AACA,WAAO,KAAK,EAAE,QAAQ,SAAI,EAAE,MAAM,KAAK,EAAE,KAAK,UAAU,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,MAAM;AAAA,EAC9H,CAAC;AACD,SAAO,wBAAwB,OAAO,MAAM;AAAA,EAAqB,MAAM,KAAK,IAAI,CAAC;AACnF;AAEO,SAAS,gBAAgB,UAAwC;AACtE,QAAM,eAAe,gBAAgB,SAAS,gBAAgB;AAC9D,QAAM,YAAY,aAAa,SAAS,oBAAoB,SAAS,mBAAmB,CAAC,CAAC;AAE1F,MAAI,SAAS,SAAS,QAAQ,SAAS,QAAQ,GAAG;AAChD,UAAM,OAAO,SAAS,SAAS;AAC/B,UAAM,UAAU,SAAS,oBAAoB,CAAC;AAC9C,UAAM,YAAY,uBAAuB,OAAO;AAChD,UAAM,UAAU,QAAQ,CAAC,GAAG,WAAW;AACvC,UAAM,QAAQ,QAAQ,QAAQ,SAAS,CAAC,GAAG,WAAW;AACtD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,SAAS,IAAI,IAAI,OAAO,iBAAiB,cAAc;AAAA,QAChE,OACI,uIACA;AAAA,QACJ;AAAA,QACA,6CAA6C,OAAO,cAAc,KAAK;AAAA,QACvE;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,sBAAsB;AAAA,MAC/B,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AAEA,QAAM,cAAc,CAAC,CAAC,SAAS,WAAW;AAE1C,MAAI,aAAa;AACf,WAAO;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;;;ACnLA,IAAM,aAAa;AACnB,IAAM,YAAY;AASX,SAAS,mBACZ,SACA,UACA,OACA,WAAW,KACK;AAChB,QAAM,eAAe,oBAAI,IAAyB;AAClD,aAAW,WAAW,UAAU;AAC5B,UAAM,MAAM,UAAU,MAAM,aAAa,QAAQ,EAAE;AACnD,QAAI,IAAK,cAAa,IAAI,KAAK,OAAO;AAAA,EAC1C;AAEA,MAAI,gBAAgB;AACpB,MAAI,WAAW;AACf,QAAM,iBAA2B,CAAC;AAElC,QAAM,WAAW,QACZ,QAAQ,YAAY,CAAC,OAAO,QAAgB;AACzC,UAAM,aAAa,aAAa,GAAG;AACnC,UAAM,UAAU,aAAa,aAAa,IAAI,UAAU,IAAI;AAC5D,QAAI,CAAC,SAAS;AACV,qBAAe,KAAK,GAAG;AACvB,aAAO;AAAA,IACX;AACA;AACA,WAAO,kBAAkB,SAAS,YAAa,QAAQ;AAAA,EAC3D,CAAC,EACA,QAAQ,WAAW,CAAC,QAAQ,KAAa,SAAiB;AACvD,UAAM,aAAa,aAAa,GAAG;AACnC,UAAM,UAAU,aAAa,aAAa,IAAI,UAAU,IAAI;AAC5D,QAAI,CAAC,SAAS;AACV,qBAAe,KAAK,GAAG;AACvB,aAAO;AAAA,IACX;AACA;AACA,WAAO,WAAM,UAAU,KAAK,KAAK,KAAK,CAAC;AAAA,EAC3C,CAAC;AAEL,SAAO,EAAE,SAAS,UAAU,eAAe,UAAU,eAAe;AACxE;AAEA,SAAS,aAAa,KAA4B;AAC9C,QAAM,QAAQ,iBAAiB,KAAK,IAAI,KAAK,EAAE,YAAY,CAAC;AAC5D,MAAI,CAAC,SAAS,MAAM,CAAC,MAAM,OAAW,QAAO;AAC7C,SAAO,IAAI,MAAM,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AACxC;AAEA,SAAS,kBAAkB,SAAsB,KAAa,UAA0B;AACpF,QAAM,QAAQ,SAAS,OAAO;AAC9B,QAAM,OAAO,SAAS,QAAQ,QAAQ,mBAAmB,QAAQ;AACjE,SAAO;AAAA,OAAU,GAAG,KAAK,KAAK;AAAA,EAAU,IAAI;AAAA;AAAA;AAChD;AAEA,SAAS,SAAS,SAA8B;AAC5C,MAAI,QAAQ,gBAAgB,eAAe,QAAQ,gBAAgB,eAAe;AAC9E,WAAO,QAAQ,YAAY;AAAA,EAC/B;AACA,SAAO,QAAQ;AACnB;AAEA,SAAS,SAAS,MAAc,UAA0B;AACtD,MAAI,KAAK,UAAU,SAAU,QAAO;AACpC,SAAO,KAAK,MAAM,GAAG,QAAQ,IAAI;AAAA,kBAAqB,KAAK,MAAM;AACrE;;;AC1EO,SAAS,gBAAgB,KAA4B;AACxD,QAAM,aAAa,IAAI,KAAK,EAAE,YAAY;AAC1C,QAAM,WAAW,aAAa,KAAK,UAAU;AAC7C,MAAI,YAAY,SAAS,CAAC,MAAM,OAAW,QAAO,IAAI,SAAS,CAAC,CAAC;AACjE,QAAM,WAAW,UAAU,KAAK,UAAU;AAC1C,MAAI,YAAY,SAAS,CAAC,MAAM,OAAW,QAAO,IAAI,SAAS,CAAC,CAAC;AACjE,SAAO;AACX;AAEO,SAAS,8BACZ,OACA,YACkB;AAClB,MAAI,WAAW,SAAS,EAAG,QAAO,CAAC;AACnC,QAAM,UAA8B,CAAC;AACrC,aAAW,SAAS,MAAM,QAAQ;AAC9B,QAAI,CAAC,MAAM,OAAQ;AACnB,QAAI,MAAM,oBAAoB,KAAK,CAAC,OAAO,WAAW,IAAI,EAAE,CAAC,GAAG;AAC5D,cAAQ,KAAK,KAAK;AAAA,IACtB;AAAA,EACJ;AACA,SAAO,QAAQ,KAAK,CAAC,GAAG,MAAM,YAAY,EAAE,OAAO,IAAI,YAAY,EAAE,OAAO,CAAC;AACjF;AAEO,SAAS,mBAAmB,OAAyB,SAAgC;AACxF,QAAM,QAAQ,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC5D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAkB,CAAC,GAAG,MAAM,cAAc;AAChD,QAAM,UAAU,oBAAI,IAAY;AAChC,SAAO,MAAM,SAAS,GAAG;AACrB,UAAM,YAAY,MAAM,MAAM;AAC9B,QAAI,QAAQ,IAAI,SAAS,EAAG;AAC5B,YAAQ,IAAI,SAAS;AACrB,UAAM,UAAU,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,SAAS;AAChE,QAAI,CAAC,QAAS;AACd,QAAI,QAAQ,OAAQ,QAAO,QAAQ;AACnC,eAAW,cAAc,QAAQ,gBAAgB;AAC7C,UAAI,CAAC,QAAQ,IAAI,UAAU,EAAG,OAAM,KAAK,UAAU;AAAA,IACvD;AAAA,EACJ;AACA,SAAO;AACX;AAMO,SAAS,gBACZ,OACA,UACA,UAA6B,CAAC,GACd;AAChB,QAAM,UAAU,IAAI,IAAI,QAAQ;AAEhC,QAAM,UAAU,MAAM,OAAO,IAAI,CAAC,UAAU;AACxC,QAAI,CAAC,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,MAAM,OAAQ,QAAO;AACzD,WAAO;AAAA,MACH,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,YAAY,MAAM;AAAA,MAClB,WAAW,MAAM;AAAA,IACrB;AAAA,EACJ,CAAC;AAED,MAAI,QAAQ;AACZ,MAAI,QAAQ,MAAM;AACd,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,QAAkB,CAAC;AACzB,eAAW,MAAM,UAAU;AACvB,YAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE;AAClD,UAAI,MAAO,OAAM,KAAK,GAAG,MAAM,cAAc;AAAA,IACjD;AACA,WAAO,MAAM,SAAS,GAAG;AACrB,YAAM,KAAK,MAAM,MAAM;AACvB,UAAI,QAAQ,IAAI,EAAE,EAAG;AACrB,cAAQ,IAAI,EAAE;AACd,cAAQ,MAAM,IAAI,CAAC,UAAU;AACzB,YAAI,MAAM,YAAY,GAAI,QAAO;AACjC,cAAM,KAAK,GAAG,MAAM,cAAc;AAClC,eAAO,MAAM,SAAS,EAAE,GAAG,OAAO,QAAQ,MAAM,IAAI;AAAA,MACxD,CAAC;AAAA,IACL;AAAA,EACJ;AAEA,SAAO,EAAE,GAAG,OAAO,QAAQ,MAAM;AACrC;AAOO,SAAS,4BACZ,UACA,wBACA,OACqB;AACrB,QAAM,WAA0B,CAAC;AACjC,aAAW,WAAW,UAAU;AAC5B,QAAI,CAAC,uBAAuB,IAAI,QAAQ,EAAE,EAAG;AAC7C,UAAM,eAAe,MAAM,OAAO;AAAA,MAC9B,CAAC,MAAM,EAAE,UAAU,EAAE,oBAAoB,SAAS,QAAQ,EAAE;AAAA,IAChE;AACA,QAAI,CAAC,aAAc,UAAS,KAAK,OAAO;AAAA,EAC5C;AAEA,MAAI,SAAS,WAAW,EAAG,QAAO,EAAE,SAAS,IAAI,eAAe,EAAE;AAElE,QAAM,QAAkB,CAAC;AACzB,MAAI,cAAc;AAClB,QAAM,cAAc;AACpB,QAAM,kBAAkB;AAExB,aAAW,WAAW,UAAU;AAC5B,QAAI,eAAe,YAAa;AAChC,UAAM,OAAO,QAAQ,QAAQ;AAC7B,UAAM,YAAY,KAAK,SAAS,kBAAkB,KAAK,MAAM,GAAG,eAAe,IAAI,QAAQ;AAC3F,UAAM,QACF,QAAQ,YAAY,QAAQ,gBAAgB,SACtC,GAAG,QAAQ,QAAQ,KAAK,SAAS,KACjC,IAAI,QAAQ,IAAI,KAAK,SAAS;AACxC,UAAM,KAAK,KAAK;AAChB,mBAAe,MAAM,SAAS;AAAA,EAClC;AAEA,SAAO,EAAE,SAAS,MAAM,KAAK,IAAI,GAAG,eAAe,SAAS,OAAO;AACvE;AAEA,SAAS,YAAY,SAAyB;AAC1C,QAAM,QAAQ,WAAW,KAAK,OAAO;AACrC,SAAO,SAAS,MAAM,CAAC,MAAM,SAAY,OAAO,MAAM,CAAC,CAAC,IAAI;AAChE;;;AClIA,SAASC,cAAa,GAAmB;AACrC,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,QAAO;AAC1C,SAAO,KAAK,MAAO,IAAI,IAAI,KAAM,QAAQ,CAAC,CAAC,MAAM,OAAO,CAAC;AAC7D;AAEA,SAAS,IAAI,GAAW,OAAuB;AAC3C,MAAI,KAAK,KAAK,SAAS,EAAG,QAAO;AACjC,SAAO,KAAK,IAAI,GAAG,KAAK,MAAO,IAAI,QAAS,GAAG,CAAC;AACpD;AAEA,SAASC,aAAY,SAAyB;AAC1C,QAAM,QAAQ,WAAW,KAAK,OAAO;AACrC,SAAO,SAAS,MAAM,CAAC,MAAM,SAAY,OAAO,MAAM,CAAC,CAAC,IAAI;AAChE;AAEA,SAAS,gBAAgB,OAAyB,aAA4C;AAC1F,SAAO,YAAY,MAAM,OAAO;AACpC;AAEA,SAAS,0BACL,OACA,OACA,aACA,UAAuB,oBAAI,IAAI,GACzB;AACN,MAAI,QAAQ,IAAI,MAAM,OAAO,EAAG,QAAO;AACvC,UAAQ,IAAI,MAAM,OAAO;AACzB,MAAI,QAAQ,MAAM;AAClB,aAAW,YAAY,MAAM,gBAAgB;AACzC,UAAM,SAAS,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,QAAQ;AAC9D,QAAI,OAAQ,UAAS,0BAA0B,QAAQ,OAAO,aAAa,OAAO;AAAA,EACtF;AACA,SAAO;AACX;AAEA,SAAS,UAAU,OAAiC;AAChD,SAAO,IAAI,MAAM,IAAI;AACzB;AAEA,SAAS,cACL,QACA,aACa;AACb,QAAM,aAAqC,CAAC;AAC5C,aAAW,SAAS,QAAQ;AACxB,eAAW,MAAM,IAAI,KAAK,WAAW,MAAM,IAAI,KAAK,KAAK,gBAAgB,OAAO,WAAW;AAAA,EAC/F;AACA,QAAM,QAAQ,OAAO,KAAK,UAAU,EAAE,IAAI,MAAM;AAChD,MAAI,MAAM,UAAU,EAAG,QAAO;AAC9B,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG;AAC1B,QAAI,WAAW,IAAI,EAAG,OAAM,KAAK,IAAI,IAAI,KAAKD,cAAa,WAAW,IAAI,CAAC,CAAC,EAAE;AAAA,EAClF;AACA,SAAO,MAAM,KAAK,KAAK;AAC3B;AASA,SAAS,eACL,UACA,OACA,aACwD;AACxD,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,SAAS,MAAM,QAAQ;AAC9B,QAAI,CAAC,MAAM,OAAQ;AACnB,eAAW,MAAM,MAAM,oBAAqB,YAAW,IAAI,EAAE;AAAA,EACjE;AACA,MAAI,gBAAgB;AACpB,aAAW,SAAS,MAAM,QAAQ;AAC9B,QAAI,MAAM,OAAQ,kBAAiB,gBAAgB,OAAO,WAAW;AAAA,EACzE;AACA,QAAM,UAAgC,CAAC;AACvC,WAAS,QAAQ,CAAC,SAAS,UAAU;AACjC,QAAI,WAAW,IAAI,QAAQ,EAAE,EAAG;AAChC,UAAM,MAAM,UAAU,MAAM,aAAa,QAAQ,EAAE;AACnD,QAAI,CAAC,IAAK;AACV,UAAM,SAAS,YAAY,QAAQ,QAAQ,EAAE;AAC7C,UAAM,OAAO,QAAQ,YAAY;AACjC,QAAI,SAAS,EAAG,SAAQ,KAAK,EAAE,KAAK,QAAQ,MAAM,MAAM,CAAC;AAAA,EAC7D,CAAC;AACD,SAAO,EAAE,SAAS,cAAc;AACpC;AAUO,SAAS,kBACZ,OACA,UACA,aACA,UAA+B,CAAC,GAC1B;AACN,QAAM,QAAQ,QAAQ;AACtB,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,aAAa,QAAQ;AAC3B,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,QAAQ,QAAQ,SAAS;AAE/B,QAAME,gBAAe,MAAM,OACtB,OAAO,CAAC,MAAM,EAAE,MAAM,EACtB,KAAK,CAAC,GAAG,MAAMD,aAAY,EAAE,OAAO,IAAIA,aAAY,EAAE,OAAO,CAAC;AAEnE,MAAI,UAAU,cAAc;AACxB,WAAO,0BAA0BC,eAAc,OAAO,MAAM,OAAO,WAAW;AAAA,EAClF;AAEA,QAAM,EAAE,SAAS,cAAc,IAAI,eAAe,UAAU,OAAO,WAAW;AAE9E,MAAI,UAAU,gBAAgB;AAC1B,QAAI,SAAS,YAAY;AACrB,aAAO,uBAAuB,SAAS,YAAY,MAAM,KAAK;AAAA,IAClE;AACA,WAAO,yBAAyB,OAAO;AAAA,EAC3C;AAEA,SAAO,eAAe,SAAS,eAAeA,eAAc,OAAO,aAAa,KAAK;AACzF;AAEA,SAAS,eACL,SACA,eACA,QACA,OACA,aACA,OACM;AACN,QAAM,QAAkB,CAAC;AACzB,QAAM,cAAc,oBAAI,IAAoB;AAC5C,aAAW,WAAW,SAAS;AAC3B,gBAAY,IAAI,QAAQ,OAAO,YAAY,IAAI,QAAQ,IAAI,KAAK,KAAK,QAAQ,MAAM;AAAA,EACvF;AACA,QAAM,UAAU,CAAC,GAAG,YAAY,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC;AAE7E,QAAM,YAAY,QACb,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAC/B,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACzC,QAAM,YAAY,QACb,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAC/B,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACzC,QAAM,QAAQ,gBAAgB,YAAY;AAE1C,QAAM,KAAK,mBAAmB;AAC9B,QAAM;AAAA,IACF,KAAKF,cAAa,SAAS,CAAC,UAAU,IAAI,WAAW,KAAK,CAAC,QAAQA,cAAa,SAAS,CAAC,UAAU,IAAI,WAAW,KAAK,CAAC,QAAQA,cAAa,aAAa,CAAC,eAAe,IAAI,eAAe,KAAK,CAAC;AAAA,EACxM;AACA,QAAM,WAAW,CAAC,GAAG,YAAY,QAAQ,CAAC,EACrC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,CAAC;AACf,MAAI,SAAS,SAAS,GAAG;AACrB,UAAM,KAAK,gBAAgB,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAChG;AAEA,QAAM,KAAK,EAAE;AACb,MAAI,OAAO,WAAW,GAAG;AACrB,UAAM,KAAK,mBAAmB;AAC9B,UAAM,KAAK,yBAAyB;AAAA,EACxC,OAAO;AACH,UAAM,eAAe,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,gBAAgB,GAAG,WAAW,GAAG,CAAC;AACnF,UAAM,iBAAiB,OAAO;AAAA,MAC1B,CAAC,GAAG,MAAM,IAAI,0BAA0B,GAAG,OAAO,WAAW;AAAA,MAC7D;AAAA,IACJ;AACA,UAAM;AAAA,MACF,4BAAuB,OAAO,MAAM,YAAYA,cAAa,YAAY,CAAC,aAAaA,cAAa,cAAc,CAAC;AAAA,IACvH;AACA,UAAM,YAAY,cAAc,QAAQ,WAAW;AACnD,QAAI,UAAW,OAAM,KAAK,iBAAiB,SAAS,EAAE;AACtD,UAAM,KAAK,EAAE;AACb,UAAM,SAAS,CAAC,GAAG,MAAM,EAAE;AAAA,MACvB,CAAC,GAAG,MACA,0BAA0B,GAAG,OAAO,WAAW,IAC3C,0BAA0B,GAAG,OAAO,WAAW,KACnD,EAAE,YAAY,EAAE;AAAA,IACxB;AACA,eAAW,SAAS,OAAO,MAAM,GAAG,KAAK,GAAG;AACxC,YAAM,QAAQ,MAAM,SAAS;AAC7B,YAAM,MAAM,0BAA0B,OAAO,OAAO,WAAW;AAC/D,YAAM;AAAA,QACF,KAAK,MAAM,OAAO,KAAK,UAAU,KAAK,CAAC,MAAMA,cAAa,GAAG,CAAC,SAAIA,cAAa,gBAAgB,OAAO,WAAW,CAAC,CAAC,KAAK,MAAM,oBAAoB,MAAM,WAAW,KAAK;AAAA,MAC5K;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,KAAK,EAAE;AACb,QAAM;AAAA,IACF,wEAAwE,WAAW,MAAM;AAAA,EAC7F;AACA,SAAO,MAAM,KAAK,IAAI;AAC1B;AAEA,SAAS,yBAAyB,SAAuC;AACrE,QAAM,QAAkB,CAAC;AACzB,QAAM,cAAc,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAC5D,QAAM,KAAK,uBAAkBA,cAAa,WAAW,CAAC,MAAM,QAAQ,MAAM,mBAAmB;AAC7F,QAAM,KAAK,EAAE;AACb,MAAI,QAAQ,WAAW,GAAG;AACtB,UAAM,KAAK,8BAA8B;AACzC,WAAO,MAAM,KAAK,IAAI;AAAA,EAC1B;AAKA,QAAMG,UAAS,CAAC,QAAwB;AACpC,UAAM,IAAI,IAAI,MAAM,KAAK;AACzB,WAAO,IAAI,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI;AAAA,EACpC;AACA,QAAM,SAAmB,CAAC;AAC1B,aAAW,KAAK,SAAS;AACrB,UAAM,MAAMA,QAAO,EAAE,GAAG;AACxB,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAI,QAAQ,QAAQ,KAAK,WAAW,KAAK,OAAO;AAC5C,WAAK,SAAS,EAAE;AAChB,WAAK,SAAS;AACd,WAAK,UAAU,EAAE;AAAA,IACrB,OAAO;AACH,aAAO,KAAK,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,KAAK,OAAO,GAAG,QAAQ,EAAE,QAAQ,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3G;AAAA,EACJ;AACA,aAAW,KAAK,OAAO,MAAM,GAAG,EAAE,GAAG;AACjC,UAAM,QAAQ,EAAE,UAAU,IAAI,EAAE,WAAW,GAAG,EAAE,QAAQ,SAAI,EAAE,MAAM;AACpE,UAAM,KAAK,KAAK,KAAK,MAAM,EAAE,KAAK,UAAUH,cAAa,EAAE,MAAM,CAAC,GAAG,EAAE,QAAQ,IAAI,KAAK,KAAK,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE;AAAA,EACnJ;AACA,MAAI,OAAO,SAAS,IAAI;AACpB,UAAM,KAAK,aAAa,OAAO,SAAS,EAAE,cAAc;AAAA,EAC5D;AACA,SAAO,MAAM,KAAK,IAAI;AAC1B;AAEA,SAAS,uBACL,SACA,YACA,MACA,OACM;AACN,MAAI,WAAW;AACf,MAAI,WAAY,YAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU;AAEvE,MAAI,SAAS,OAAQ,UAAS,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAAA,WACrD,SAAS,OAAQ,UAAS,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,SAAS,EAAE,MAAM;AAAA,MAChG,UAAS,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAEhD,QAAM,cAAc,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAC7D,QAAM,YAAY,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAC1D,QAAM,SAAS,aACT,uBAAkB,UAAU,KAAKA,cAAa,WAAW,CAAC,MAAM,SAAS,MAAM,WAAW,IAAI,aAAa,SAAS,CAAC,iBACrH,uBAAkBA,cAAa,WAAW,CAAC,MAAM,SAAS,MAAM;AACtE,QAAM,QAAQ,CAAC,QAAQ,aAAa,IAAI,IAAI,EAAE;AAC9C,QAAM,QAAQ,SAAS,MAAM,GAAG,KAAK;AACrC,aAAW,WAAW,OAAO;AACzB,UAAM,KAAK,KAAK,QAAQ,GAAG,KAAKA,cAAa,QAAQ,MAAM,CAAC,KAAK,QAAQ,IAAI,EAAE;AAAA,EACnF;AACA,MAAI,SAAS,SAAS,MAAM,QAAQ;AAChC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,MAAM,MAAM,OAAO,SAAS,MAAM,SAAS;AAAA,EAC7D;AACA,SAAO,MAAM,KAAK,IAAI;AAC1B;AAEA,SAAS,0BACL,QACA,OACA,MACA,OACA,aACM;AACN,MAAI,SAAS,CAAC,GAAG,MAAM;AACvB,MAAI,SAAS,OAAQ,QAAO,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAAA,WAC3D,SAAS,MAAO,QAAO,KAAK,CAAC,GAAG,MAAM,EAAE,gBAAgB,EAAE,aAAa;AAAA;AAE5E,WAAO;AAAA,MACH,CAAC,GAAG,MACA,0BAA0B,GAAG,OAAO,WAAW,IAC3C,0BAA0B,GAAG,OAAO,WAAW,KACnD,EAAE,YAAY,EAAE;AAAA,IACxB;AAEJ,QAAM,eAAe,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,gBAAgB,GAAG,WAAW,GAAG,CAAC;AACnF,QAAM,iBAAiB,OAAO;AAAA,IAC1B,CAAC,GAAG,MAAM,IAAI,0BAA0B,GAAG,OAAO,WAAW;AAAA,IAC7D;AAAA,EACJ;AACA,QAAM,QAAQ;AAAA,IACV,qBAAgB,OAAO,MAAM,aAAaA,cAAa,cAAc,CAAC,oBAAeA,cAAa,YAAY,CAAC;AAAA,EACnH;AACA,QAAM,YAAY,cAAc,QAAQ,WAAW;AACnD,MAAI,UAAW,OAAM,KAAK,eAAe,SAAS,EAAE;AACpD,QAAM,KAAK,EAAE;AACb,QAAM,QAAQ,OAAO,MAAM,GAAG,KAAK;AACnC,aAAW,SAAS,OAAO;AACvB,UAAM,SAAS,MAAM,eAAe,SAAS,IAAI,YAAY,MAAM,eAAe,KAAK,GAAG,CAAC,MAAM;AACjG,UAAM,QAAQ,MAAM,SAAS;AAC7B,UAAM,MAAM,0BAA0B,OAAO,OAAO,WAAW;AAC/D,UAAM;AAAA,MACF,KAAK,MAAM,OAAO,KAAK,UAAU,KAAK,CAAC,MAAMA,cAAa,GAAG,CAAC,SAAIA,cAAa,gBAAgB,OAAO,WAAW,CAAC,CAAC,KAAK,MAAM,oBAAoB,MAAM,cAAc,MAAM,aAAa,IAAI,MAAM,UAAU,GAAG,MAAM;AAAA,IAC1N;AACA,UAAM,KAAK,QAAQ,KAAK,GAAG;AAAA,EAC/B;AACA,MAAI,OAAO,SAAS,MAAM,QAAQ;AAC9B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,MAAM,MAAM,OAAO,OAAO,MAAM,SAAS;AAAA,EAC3D;AACA,SAAO,MAAM,KAAK,IAAI;AAC1B;AAEO,SAAS,WACZ,OACA,SACM;AACN,QAAME,gBAAe,MAAM,OACtB,OAAO,CAAC,MAAM,EAAE,MAAM,EACtB,KAAK,CAAC,GAAG,MAAMD,aAAY,EAAE,OAAO,IAAIA,aAAY,EAAE,OAAO,CAAC;AAEnE,MAAI,YAAY,QAAW;AACvB,UAAM,QAAQ,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC5D,QAAI,CAAC,OAAO;AACR,YAAM,aAAaC,cAAa,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;AAC/D,aAAO,SAAS,OAAO,8BAA8B,UAAU;AAAA,IACnE;AACA,QAAI,CAAC,MAAM,QAAQ;AACf,aAAO,SAAS,OAAO;AAAA,IAC3B;AACA,UAAM,QAAQ,GAAG,MAAM,oBAAoB,MAAM;AACjD,WAAO;AAAA,EAAsC,MAAM,OAAO;AAAA;AAAA,GAAQ,OAAO,MAAM,KAAK,cAAc,MAAM,SAAS,QAAQ;AAAA,EAC7H;AAEA,MAAIA,cAAa,WAAW,EAAG,QAAO;AAEtC,QAAM,QAAQ,CAAC,8BAA8BA,cAAa,MAAM,IAAI;AACpE,aAAW,SAASA,eAAc;AAC9B,UAAM,QAAQ,GAAG,MAAM,oBAAoB,MAAM;AACjD,UAAM,UAAU,MAAM,QAAQ,MAAM,GAAG,GAAG;AAC1C,UAAM,KAAK;AAAA,EAAK,MAAM,OAAO,MAAM,KAAK,OAAO,MAAM,SAAS,QAAQ,GAAG;AACzE,UAAM,KAAK,KAAK,OAAO,GAAG,MAAM,QAAQ,SAAS,MAAM,QAAQ,EAAE,EAAE;AAAA,EACvE;AACA,QAAM,KAAK;AAAA,2CAA8C;AACzD,SAAO,MAAM,KAAK,IAAI;AAC1B;;;ACjUO,SAAS,wBACZ,OACA,UACA,QACA,QAAsB,CAAC,GACV;AACb,QAAM,OAAO,WAAW,EAAE,aAAa,MAAM,eAAe,mBAAmB,CAAC;AAChF,QAAM,YAAY,WAAW,UAAU;AAAA,IACnC,UAAU,MAAM;AAAA,IAChB,WAAW,iBAAiB,MAAM,WAAW,IAAI;AAAA,EACrD,CAAC;AACD,MAAI,UAA4B,EAAE,GAAG,OAAO,aAAa,UAAU,IAAI;AAEvE,QAAM,cAAc,2BAA2B,QAAQ;AACvD,MAAI,gBAAgB;AAEpB,aAAW,cAAc,aAAa;AAClC,UAAM,SAAS,cAAc,WAAW,OAAO,WAAW,MAAM;AAChE,QAAI,OAAO,WAAW,EAAG;AACzB,UAAM,SAAS,KAAK,iBAAiB,EAAE,QAAQ,UAAU,OAAO,SAAS,OAAO,CAAC;AACjF,cAAU,OAAO;AACjB,qBAAiB,OAAO,OAAO;AAAA,EACnC;AAEA,SAAO,EAAE,OAAO,SAAS,cAAc;AAC3C;AAOA,SAAS,2BAA2B,UAA+C;AAC/E,QAAM,cAAoC,CAAC;AAC3C,aAAW,WAAW,UAAU;AAC5B,QAAI,QAAQ,aAAa,cAAc,QAAQ,gBAAgB,YAAa;AAC5E,QAAI;AACJ,QAAI;AACA,cAAQ,KAAK,MAAM,QAAQ,QAAQ,EAAE;AAAA,IACzC,QAAQ;AACJ;AAAA,IACJ;AACA,gBAAY,KAAK,EAAE,QAAQ,QAAQ,YAAY,MAAM,CAAC;AAAA,EAC1D;AACA,SAAO;AACX;AAEA,SAAS,cACL,OACA,QAOD;AACC,QAAM,UAAW,OAAmC;AACpD,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO,CAAC;AACrC,QAAM,SAAS,CAAC;AAChB,aAAW,SAAS,SAAS;AACzB,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,UAAM,IAAI;AACV,QAAI,OAAO,EAAE,YAAY,SAAU;AACnC,UAAM,QAAQ,EAAE,WAAW,EAAE;AAC7B,UAAM,MAAM,EAAE,SAAS,EAAE;AACzB,QAAI,OAAO,UAAU,YAAY,OAAO,QAAQ,SAAU;AAC1D,WAAO,KAAK;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,EAAE;AAAA,MACX,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;AAAA,MAC/C,gBAAgB;AAAA,IACpB,CAAC;AAAA,EACL;AACA,SAAO;AACX;;;AC7EO,SAAS,aACZ,OACA,OACA,UAAyB,CAAC,GACZ;AACd,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,QAAM,WAAW,QAAQ,YAAY;AAErC,QAAM,QAAQ,MACT,YAAY,EACZ,KAAK,EACL,MAAM,KAAK,EACX,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAE/B,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAEhC,QAAM,SAAS,MAAM,OAAO,OAAO,CAAC,MAAwB,EAAE,MAAM;AAEpE,QAAM,SAAyB,CAAC;AAChC,aAAW,SAAS,QAAQ;AACxB,UAAM,QAAQ,MAAM,WAAW,IAAI,YAAY;AAC/C,UAAM,SAAS,MAAM,SAAS,IAAI,YAAY;AAC9C,UAAM,WAAW,QAAQ,MAAM;AAE/B,QAAI,QAAQ;AACZ,eAAW,QAAQ,OAAO;AACtB,eAASE,kBAAiB,UAAU,IAAI;AAAA,IAC5C;AAEA,QAAI,SAAS,UAAU;AACnB,aAAO,KAAK;AAAA,QACR,SAAS,MAAM;AAAA,QACf,MAAM,MAAM,QAAQ;AAAA,QACpB;AAAA,QACA,OAAO,MAAM,SAAS;AAAA,QACtB,UAAU,MAAM,WAAW,IAAI,MAAM,GAAG,aAAa;AAAA,QACrD;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ;AAEA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACvC,SAAO,OAAO,MAAM,GAAG,KAAK;AAChC;AAEA,SAASA,kBAAiB,UAAkB,QAAwB;AAChE,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO,SAAS,MAAM,MAAM,EAAE,SAAS;AAC3C;","names":["require","require","block","refNum","formatTokens","numericPart","activeBlocks","refNum","countOccurrences"]}
@@ -1,8 +1,9 @@
1
- import type { NudgeDecision } from "./types.js";
1
+ import type { NudgeDecision, CompressibleRange, ProtectedRange } from "./types.js";
2
2
  export type NudgeVoice = "gentle" | "emergency";
3
3
  export interface RenderedNudge {
4
4
  voice: NudgeVoice;
5
5
  text: string;
6
6
  }
7
+ export declare function formatRanges(compressible: CompressibleRange[], protectedRanges: ProtectedRange[]): string;
7
8
  export declare function renderNudgeText(decision: NudgeDecision): RenderedNudge;
8
9
  //# sourceMappingURL=nudge-text.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nudge-text.d.ts","sourceRoot":"","sources":["../src/nudge-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAyE,MAAM,YAAY,CAAC;AAGvH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAwID,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAiEtE"}
1
+ {"version":3,"file":"nudge-text.d.ts","sourceRoot":"","sources":["../src/nudge-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAsC,MAAM,YAAY,CAAC;AAGvH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAqCD,wBAAgB,YAAY,CAAC,YAAY,EAAE,iBAAiB,EAAE,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,MAAM,CAsEzG;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAiEtE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acp-kernel",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Framework-agnostic context-compression engine (model-driven, 3-tier LSM). Pure core: no host dependency.",
5
5
  "license": "MIT",
6
6
  "author": "ranxianglei",