acp-kernel 0.0.10 → 0.0.12

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;AAgpBD,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;AAipBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -11,4 +11,33 @@ export interface RestoredPreviewResult {
11
11
  restoredCount: number;
12
12
  }
13
13
  export declare function buildRestoredContentPreview(messages: CoreMessage[], beforeActiveMessageIds: Set<string>, state: CompressionState): RestoredPreviewResult;
14
+ export interface CollectedContentResult {
15
+ /** Rendered, human-readable content string (empty when count is 0). */
16
+ text: string;
17
+ /** Number of items rendered: direct messages + nested summaries (full=false) or all messages (full=true). */
18
+ count: number;
19
+ }
20
+ export interface CollectContentOptions {
21
+ /** When true, recurse through all nested tiers to original messages. Default: false (one tier up — nested active children stay folded, their summaries shown). */
22
+ full?: boolean;
23
+ }
24
+ /**
25
+ * Collect a block's content as a readable string WITHOUT modifying state.
26
+ *
27
+ * This is the cache-safe decompress primitive: the block stays compressed
28
+ * (folded), its summary stays in place, and the full content is returned as
29
+ * text for the caller to surface (e.g. as a tool result appended to the
30
+ * conversation). Unlike deactivateBlock + prune, this does not mutate the
31
+ * message-array prefix, so prompt cache is preserved.
32
+ *
33
+ * full=false (default): one tier up. Nested ACTIVE children of this block
34
+ * stay folded; their summaries are rendered in place of their messages.
35
+ * The block's own direct messages (not covered by any active child) are
36
+ * rendered in full.
37
+ * full=true: recurse through all nested tiers; every effective message is
38
+ * rendered in full.
39
+ *
40
+ * Returns { text: "", count: 0 } when the block covers no messages.
41
+ */
42
+ export declare function collectBlockContent(state: CompressionState, block: CompressionBlock, messages: CoreMessage[], options?: CollectContentOptions): CollectedContentResult;
14
43
  //# sourceMappingURL=decompress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decompress.d.ts","sourceRoot":"","sources":["../src/decompress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAElF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO1D;AAED,wBAAgB,6BAA6B,CACzC,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACxB,gBAAgB,EAAE,CAUpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB1F;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,eAAe,CAC3B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,iBAAsB,GAChC,gBAAgB,CAkClB;AAED,MAAM,WAAW,qBAAqB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,2BAA2B,CACvC,QAAQ,EAAE,WAAW,EAAE,EACvB,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,EACnC,KAAK,EAAE,gBAAgB,GACxB,qBAAqB,CA8BvB"}
1
+ {"version":3,"file":"decompress.d.ts","sourceRoot":"","sources":["../src/decompress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAElF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO1D;AAED,wBAAgB,6BAA6B,CACzC,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACxB,gBAAgB,EAAE,CAUpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB1F;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,eAAe,CAC3B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,iBAAsB,GAChC,gBAAgB,CAkClB;AAED,MAAM,WAAW,qBAAqB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,2BAA2B,CACvC,QAAQ,EAAE,WAAW,EAAE,EACvB,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,EACnC,KAAK,EAAE,gBAAgB,GACxB,qBAAqB,CA8BvB;AAED,MAAM,WAAW,sBAAsB;IACnC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,6GAA6G;IAC7G,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IAClC,kKAAkK;IAClK,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAC/B,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,GAAE,qBAA0B,GACpC,sBAAsB,CAsCxB"}
package/dist/index.d.ts CHANGED
@@ -9,15 +9,15 @@ 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";
16
16
  export type { TruncateOptions, TruncateResult } from "./truncate-tools.js";
17
17
  export { resolveKeepMarkers } from "./keep-markers.js";
18
18
  export type { KeepMarkerResult } from "./keep-markers.js";
19
- export { parseBlockIdArg, findBlocksOverlappingMessages, findActiveAncestor, deactivateBlock, buildRestoredContentPreview, } from "./decompress.js";
20
- export type { DeactivateOptions } from "./decompress.js";
19
+ export { parseBlockIdArg, findBlocksOverlappingMessages, findActiveAncestor, deactivateBlock, buildRestoredContentPreview, collectBlockContent, } from "./decompress.js";
20
+ export type { DeactivateOptions, CollectedContentResult, CollectContentOptions } from "./decompress.js";
21
21
  export { buildStatusReport, buildRecap } from "./report.js";
22
22
  export type { StatusReportOptions } from "./report.js";
23
23
  export { hideConsumedCompressCalls } from "./hide-consumed.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,EAC3B,mBAAmB,GACtB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxG,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
@@ -1500,7 +1500,7 @@ function decideNudge(input) {
1500
1500
  if (parts.length === 0) parts.push(`max compressible ${maxPending}, growth ${growthSinceReference}`);
1501
1501
  reason = `${parts.join("; ")}${readyHint}${blockedHint}`;
1502
1502
  }
1503
- const ctxBreakdown = computeContextBreakdown(input.messages, tokenCount, growthSinceReference);
1503
+ const ctxBreakdown = computeContextBreakdown(input.messages, tokenCount, growthSinceReference, countTokens);
1504
1504
  return {
1505
1505
  shouldInject,
1506
1506
  reason,
@@ -1525,10 +1525,11 @@ function decideNudge(input) {
1525
1525
  contextBreakdown: ctxBreakdown
1526
1526
  };
1527
1527
  }
1528
- function computeContextBreakdown(messages, total, growth) {
1528
+ function computeContextBreakdown(messages, total, growth, countTokens) {
1529
+ const count = countTokens ?? ((t) => Math.ceil(t.length / 4));
1529
1530
  let system = 0, tool = 0, summaries = 0, code = 0, text = 0;
1530
1531
  for (const msg of messages) {
1531
- const tokens = Math.ceil((msg.text ?? "").length / 4);
1532
+ const tokens = count(msg.text ?? "");
1532
1533
  if (msg.text?.startsWith("[Compressed conversation section]")) {
1533
1534
  summaries += tokens;
1534
1535
  } else if (msg.contentType === "tool-call" || msg.contentType === "tool-result") {
@@ -1728,25 +1729,88 @@ function formatTierTargetBlocks(blocks) {
1728
1729
  return `Target ${blocks[0].tier === 1 ? "tier-1" : "tier-2"} blocks to distill (${blocks.length}):
1729
1730
  ${lines.join("\n")}`;
1730
1731
  }
1731
- function formatRanges(compressible) {
1732
- if (compressible.length === 0) {
1732
+ function formatRanges(compressible, protectedRanges) {
1733
+ if (compressible.length === 0 && protectedRanges.length === 0) {
1733
1734
  return "[No specific ranges detected \u2014 compress any consumed content.]";
1734
1735
  }
1735
1736
  const refNum2 = (ref) => {
1736
1737
  const m = ref.match(/\d+/);
1737
1738
  return m ? parseInt(m[0], 10) : 0;
1738
1739
  };
1739
- const sorted = [...compressible].sort((a, b) => refNum2(a.startRef) - refNum2(b.startRef));
1740
- const lines = sorted.map((e) => {
1741
- const suffix = e.dangerous ? " \u26A0\uFE0F NOT recommended unless you are certain." : "";
1740
+ const entries = [];
1741
+ for (const r of compressible) {
1742
+ entries.push({
1743
+ startRef: r.startRef,
1744
+ endRef: r.endRef,
1745
+ startNum: refNum2(r.startRef),
1746
+ endNum: refNum2(r.endRef),
1747
+ count: r.count,
1748
+ tokens: r.tokens,
1749
+ toolPct: r.toolPct,
1750
+ textPct: r.textPct,
1751
+ compressibleTokens: r.tokens,
1752
+ compressibleCount: r.count,
1753
+ protectedTokens: 0,
1754
+ protectedCount: 0,
1755
+ protectedTools: [],
1756
+ dangerous: r.dangerous ?? false
1757
+ });
1758
+ }
1759
+ for (const r of protectedRanges) {
1760
+ entries.push({
1761
+ startRef: r.startRef,
1762
+ endRef: r.endRef,
1763
+ startNum: refNum2(r.startRef),
1764
+ endNum: refNum2(r.endRef),
1765
+ count: r.count,
1766
+ tokens: r.tokens,
1767
+ toolPct: 0,
1768
+ textPct: 0,
1769
+ compressibleTokens: 0,
1770
+ compressibleCount: 0,
1771
+ protectedTokens: r.tokens,
1772
+ protectedCount: r.count,
1773
+ protectedTools: [...r.tools],
1774
+ dangerous: false
1775
+ });
1776
+ }
1777
+ entries.sort((a, b) => a.startNum - b.startNum);
1778
+ const merged = [];
1779
+ for (const e of entries) {
1780
+ const last = merged[merged.length - 1];
1781
+ if (last && e.startNum <= last.endNum + 1) {
1782
+ last.endRef = e.endRef;
1783
+ last.endNum = Math.max(last.endNum, e.endNum);
1784
+ last.count += e.count;
1785
+ last.tokens += e.tokens;
1786
+ last.compressibleTokens += e.compressibleTokens;
1787
+ last.compressibleCount += e.compressibleCount;
1788
+ last.protectedTokens += e.protectedTokens;
1789
+ last.protectedCount += e.protectedCount;
1790
+ if (e.dangerous) last.dangerous = true;
1791
+ for (const t of e.protectedTools) {
1792
+ if (!last.protectedTools.includes(t)) last.protectedTools.push(t);
1793
+ }
1794
+ } else {
1795
+ merged.push({ ...e });
1796
+ }
1797
+ }
1798
+ const lines = merged.map((e) => {
1799
+ const suffix = e.dangerous && e.compressibleTokens > 0 ? " \u26A0\uFE0F NOT recommended unless you are certain." : "";
1800
+ if (e.protectedTokens > 0 && e.compressibleTokens === 0) {
1801
+ return ` ${e.startRef}\u2013${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [PROTECTED: ${e.protectedTools.join(", ")} \u2014 not compressible]${suffix}`;
1802
+ }
1803
+ if (e.protectedTokens > 0 && e.compressibleTokens > 0) {
1804
+ return ` ${e.startRef}\u2013${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [${formatK(e.compressibleTokens)} compressible | ${formatK(e.protectedTokens)} protected: ${e.protectedTools.join(", ")}]${suffix}`;
1805
+ }
1742
1806
  return ` ${e.startRef}\u2013${e.endRef} ${e.count} msgs ${formatK(e.tokens)} [tool ${e.toolPct}% | text ${e.textPct}%]${suffix}`;
1743
1807
  });
1744
- return `Compressible ranges (${compressible.length}, oldest first):
1808
+ return `Compressible ranges (${merged.length}, oldest first):
1745
1809
  ${lines.join("\n")}`;
1746
1810
  }
1747
1811
  function renderNudgeText(decision) {
1748
1812
  const breakdownStr = formatBreakdown(decision.contextBreakdown);
1749
- const rangesStr = formatRanges(decision.compressibleRanges);
1813
+ const rangesStr = formatRanges(decision.compressibleRanges, decision.protectedRanges ?? []);
1750
1814
  if (decision.tier !== null && decision.tier >= 2) {
1751
1815
  const isT2 = decision.tier === 2;
1752
1816
  const targets = decision.tierTargetBlocks ?? [];
@@ -1958,6 +2022,48 @@ function buildRestoredContentPreview(messages, beforeActiveMessageIds, state) {
1958
2022
  }
1959
2023
  return { preview: lines.join("\n"), restoredCount: restored.length };
1960
2024
  }
2025
+ function collectBlockContent(state, block, messages, options = {}) {
2026
+ const full = options.full ?? false;
2027
+ const targetIds = new Set(block.effectiveMessageIds);
2028
+ if (full) {
2029
+ const msgs = messages.filter((m) => targetIds.has(m.id));
2030
+ if (msgs.length === 0) return { text: "", count: 0 };
2031
+ return { text: msgs.map(formatMessage).join("\n\n"), count: msgs.length };
2032
+ }
2033
+ const nestedChildren = [];
2034
+ const nestedCovered = /* @__PURE__ */ new Set();
2035
+ for (const childId of block.directBlockIds) {
2036
+ const child = state.blocks.find((b) => b.blockId === childId);
2037
+ if (!child?.active) continue;
2038
+ nestedChildren.push(child);
2039
+ for (const id of child.effectiveMessageIds) nestedCovered.add(id);
2040
+ }
2041
+ const parts = [];
2042
+ for (const child of nestedChildren) {
2043
+ const label = child.topic ? `${child.blockId}: ${child.topic}` : child.blockId;
2044
+ parts.push(`${SUMMARY_HEADER} \u2014 ${label}
2045
+ ${child.summary}`);
2046
+ }
2047
+ let directCount = 0;
2048
+ for (const m of messages) {
2049
+ if (targetIds.has(m.id) && !nestedCovered.has(m.id)) {
2050
+ parts.push(formatMessage(m));
2051
+ directCount++;
2052
+ }
2053
+ }
2054
+ const count = directCount + nestedChildren.length;
2055
+ if (count === 0) return { text: "", count: 0 };
2056
+ return { text: parts.join("\n\n"), count };
2057
+ }
2058
+ function formatMessage(message) {
2059
+ const text = message.text ?? "";
2060
+ if (message.toolName && message.contentType !== "text") {
2061
+ return `[${message.role} \u2022 ${message.toolName}]
2062
+ ${text}`;
2063
+ }
2064
+ return `[${message.role}]
2065
+ ${text}`;
2066
+ }
1961
2067
  function numericPart(blockId) {
1962
2068
  const match = /^b(\d+)$/.exec(blockId);
1963
2069
  return match && match[1] !== void 0 ? Number(match[1]) : 0;
@@ -1979,15 +2085,8 @@ function numericPart2(blockId) {
1979
2085
  function summaryTokensOf(block, countTokens) {
1980
2086
  return countTokens(block.summary);
1981
2087
  }
1982
- function effectiveCompressedTokens(block, state, countTokens, visited = /* @__PURE__ */ new Set()) {
1983
- if (visited.has(block.blockId)) return 0;
1984
- visited.add(block.blockId);
1985
- let total = block.compressedTokens;
1986
- for (const nestedId of block.directBlockIds) {
1987
- const nested = state.blocks.find((b) => b.blockId === nestedId);
1988
- if (nested) total += effectiveCompressedTokens(nested, state, countTokens, visited);
1989
- }
1990
- return total;
2088
+ function effectiveCompressedTokens(block, _state, _countTokens) {
2089
+ return block.compressedTokens;
1991
2090
  }
1992
2091
  function tierLabel(block) {
1993
2092
  return `T${block.tier}`;
@@ -2324,6 +2423,7 @@ export {
2324
2423
  buildRestoredContentPreview,
2325
2424
  buildStatusReport,
2326
2425
  clearMessageFilters,
2426
+ collectBlockContent,
2327
2427
  coveredMessageIds,
2328
2428
  createBpeTokenizer,
2329
2429
  createCore,
@@ -2335,6 +2435,7 @@ export {
2335
2435
  estimateTokensFast,
2336
2436
  findActiveAncestor,
2337
2437
  findBlocksOverlappingMessages,
2438
+ formatRanges,
2338
2439
  getMessageFilter,
2339
2440
  hideConsumedCompressCalls,
2340
2441
  highestActiveTier,