acp-kernel 0.0.89-pr.415.269 → 0.0.89
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.
- package/DESIGN.md +0 -16
- package/dist/boundaries.d.ts +0 -1
- package/dist/boundaries.d.ts.map +1 -1
- package/dist/compress.d.ts.map +1 -1
- package/dist/decompress.d.ts +0 -25
- package/dist/decompress.d.ts.map +1 -1
- package/dist/hide-consumed.d.ts +0 -4
- package/dist/hide-consumed.d.ts.map +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +266 -593
- package/dist/index.js.map +1 -1
- package/dist/persist/index.js +4 -43
- package/dist/persist/index.js.map +1 -1
- package/dist/persist/store.d.ts +1 -13
- package/dist/persist/store.d.ts.map +1 -1
- package/dist/protected.d.ts.map +1 -1
- package/dist/prune.d.ts +0 -15
- package/dist/prune.d.ts.map +1 -1
- package/dist/recommend.d.ts +1 -0
- package/dist/recommend.d.ts.map +1 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/search/algorithms/hybrid.d.ts.map +1 -1
- package/dist/search/doc-cache.d.ts +10 -34
- package/dist/search/doc-cache.d.ts.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/types.d.ts +0 -21
- package/dist/types.d.ts.map +1 -1
- package/dist/wire/anthropic.d.ts +1 -1
- package/dist/wire/anthropic.d.ts.map +1 -1
- package/dist/wire/index.js +2 -8
- package/dist/wire/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/message-kind.d.ts +0 -11
- package/dist/message-kind.d.ts.map +0 -1
- package/dist/segment.d.ts +0 -33
- package/dist/segment.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -111,45 +111,33 @@ function summaryMessageId(blockId) {
|
|
|
111
111
|
function isSummaryMessageId(id) {
|
|
112
112
|
return id.startsWith(SUMMARY_ID_PREFIX);
|
|
113
113
|
}
|
|
114
|
-
function baseIdOf(id) {
|
|
115
|
-
const hash = id.indexOf("#");
|
|
116
|
-
return hash > 0 ? id.substring(0, hash) : id;
|
|
117
|
-
}
|
|
118
|
-
function isCovered(id, coveredBases) {
|
|
119
|
-
return coveredBases.has(baseIdOf(id));
|
|
120
|
-
}
|
|
121
114
|
function isRenderedSummaryMessage(message) {
|
|
122
115
|
return isSummaryMessageId(message.id) && message.role === "system" && message.contentType === "text";
|
|
123
116
|
}
|
|
124
117
|
function prune(messages, state, options = {}) {
|
|
125
118
|
const covered = coveredMessageIds(state);
|
|
126
119
|
if (covered.size === 0) return [...messages];
|
|
127
|
-
const coveredBases = /* @__PURE__ */ new Set();
|
|
128
|
-
for (const id of covered) coveredBases.add(baseIdOf(id));
|
|
129
120
|
const inject = options.injectSummaries ?? true;
|
|
130
121
|
const firstUserIndex = messages.findIndex(
|
|
131
122
|
(message) => message.role === "user"
|
|
132
123
|
);
|
|
133
|
-
const
|
|
124
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
134
125
|
const summaryIndexById = /* @__PURE__ */ new Map();
|
|
135
126
|
messages.forEach((message, index) => {
|
|
136
|
-
|
|
137
|
-
const existing = baseIndexById.get(base);
|
|
138
|
-
if (existing === void 0 || index < existing)
|
|
139
|
-
baseIndexById.set(base, index);
|
|
127
|
+
indexById.set(message.id, index);
|
|
140
128
|
if (isRenderedSummaryMessage(message))
|
|
141
129
|
summaryIndexById.set(message.id, index);
|
|
142
130
|
});
|
|
143
|
-
const anchors = inject ? collectSummaryAnchors(state,
|
|
131
|
+
const anchors = inject ? collectSummaryAnchors(state, indexById, summaryIndexById) : [];
|
|
144
132
|
return stripOrphanedReasoning(
|
|
145
133
|
stripOrphanedToolResults(
|
|
146
134
|
stripOrphanedToolCalls(
|
|
147
|
-
rebuildMessages(messages,
|
|
135
|
+
rebuildMessages(messages, covered, firstUserIndex, anchors)
|
|
148
136
|
)
|
|
149
137
|
)
|
|
150
138
|
);
|
|
151
139
|
}
|
|
152
|
-
function collectSummaryAnchors(state,
|
|
140
|
+
function collectSummaryAnchors(state, indexById, summaryIndexById) {
|
|
153
141
|
const anchors = [];
|
|
154
142
|
for (const block of activeBlocks(state)) {
|
|
155
143
|
const existingIndex = summaryIndexById.get(summaryMessageId(block.blockId));
|
|
@@ -164,7 +152,7 @@ function collectSummaryAnchors(state, baseIndexById, summaryIndexById) {
|
|
|
164
152
|
}
|
|
165
153
|
let earliest = null;
|
|
166
154
|
for (const id of block.effectiveMessageIds) {
|
|
167
|
-
const index =
|
|
155
|
+
const index = indexById.get(id);
|
|
168
156
|
if (index !== void 0 && (earliest === null || index < earliest)) {
|
|
169
157
|
earliest = index;
|
|
170
158
|
}
|
|
@@ -209,7 +197,7 @@ function pairSafeAnchorIndex(messages, index) {
|
|
|
209
197
|
}
|
|
210
198
|
return safe;
|
|
211
199
|
}
|
|
212
|
-
function rebuildMessages(messages,
|
|
200
|
+
function rebuildMessages(messages, covered, firstUserIndex, anchors) {
|
|
213
201
|
const safeAnchors = anchors.map((anchor) => ({
|
|
214
202
|
...anchor,
|
|
215
203
|
insertAt: pairSafeAnchorIndex(messages, anchor.insertAt)
|
|
@@ -227,7 +215,7 @@ function rebuildMessages(messages, coveredBases, firstUserIndex, anchors) {
|
|
|
227
215
|
result.push(messages[index]);
|
|
228
216
|
continue;
|
|
229
217
|
}
|
|
230
|
-
if (
|
|
218
|
+
if (covered.has(messages[index].id)) continue;
|
|
231
219
|
if (isRenderedSummaryMessage(messages[index]) && anchoredSummaryIds.has(messages[index].id))
|
|
232
220
|
continue;
|
|
233
221
|
result.push(messages[index]);
|
|
@@ -293,8 +281,6 @@ function stripOrphanedReasoning(messages) {
|
|
|
293
281
|
// src/sync.ts
|
|
294
282
|
function syncBlocks(messages, state) {
|
|
295
283
|
const presentIds = new Set(messages.map((message) => message.id));
|
|
296
|
-
const presentBases = /* @__PURE__ */ new Set();
|
|
297
|
-
for (const message of messages) presentBases.add(baseIdOf(message.id));
|
|
298
284
|
const deactivated = [];
|
|
299
285
|
const result = {
|
|
300
286
|
blocks: state.blocks.map((block) => ({
|
|
@@ -344,7 +330,7 @@ function syncBlocks(messages, state) {
|
|
|
344
330
|
continue;
|
|
345
331
|
}
|
|
346
332
|
block.active = true;
|
|
347
|
-
const stillPresent = block.effectiveMessageIds.some((id) =>
|
|
333
|
+
const stillPresent = block.effectiveMessageIds.some((id) => presentIds.has(id)) || presentIds.has(summaryMessageId(block.blockId));
|
|
348
334
|
if (!stillPresent) {
|
|
349
335
|
block.active = false;
|
|
350
336
|
deactivated.push(block.blockId);
|
|
@@ -1262,12 +1248,7 @@ function hasMediaPayload(msg) {
|
|
|
1262
1248
|
if (m.rawOpenaiContent != null) return true;
|
|
1263
1249
|
if (Array.isArray(m.rawOpenaiContentParts) && m.rawOpenaiContentParts.length > 0)
|
|
1264
1250
|
return true;
|
|
1265
|
-
|
|
1266
|
-
if (isObjWith(ab, "type", "image")) return true;
|
|
1267
|
-
if (isObjWith(ab, "type", "tool_result")) {
|
|
1268
|
-
const content = ab.content;
|
|
1269
|
-
if (Array.isArray(content)) return content.some((p) => !isObjWith(p, "type", "text"));
|
|
1270
|
-
}
|
|
1251
|
+
if (isObjWith(m.rawAnthropicBlock, "type", "image")) return true;
|
|
1271
1252
|
const item = m.rawResponsesItem;
|
|
1272
1253
|
if (isObjWith(item, "type", "input_image")) return true;
|
|
1273
1254
|
if (item && typeof item === "object") {
|
|
@@ -1631,10 +1612,8 @@ function resolveBoundaries(input) {
|
|
|
1631
1612
|
if (endAnchor.snapped) snappedBoundaries.push(endAnchor.snapped);
|
|
1632
1613
|
let startIndex = startAnchor.index;
|
|
1633
1614
|
let endIndex = endAnchor.index;
|
|
1634
|
-
let reversedNote;
|
|
1635
1615
|
if (startIndex > endIndex) {
|
|
1636
1616
|
[startIndex, endIndex] = [endIndex, startIndex];
|
|
1637
|
-
reversedNote = `note: refs were given reversed (${start.raw}\u2192${end.raw}), normalized to ${end.raw}..${start.raw}`;
|
|
1638
1617
|
}
|
|
1639
1618
|
const messageIds = [];
|
|
1640
1619
|
for (let index = startIndex; index <= endIndex; index++) {
|
|
@@ -1661,8 +1640,7 @@ function resolveBoundaries(input) {
|
|
|
1661
1640
|
nestedBlockIds,
|
|
1662
1641
|
boundaryKind,
|
|
1663
1642
|
protectedGaps,
|
|
1664
|
-
snappedBoundaries
|
|
1665
|
-
reversedNote
|
|
1643
|
+
snappedBoundaries
|
|
1666
1644
|
};
|
|
1667
1645
|
}
|
|
1668
1646
|
function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
|
|
@@ -1687,27 +1665,6 @@ function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
|
|
|
1687
1665
|
snapped: `${label}="${boundary.raw}" refers to a message already compressed into an active block \u2014 anchored to the active block covering it instead.`
|
|
1688
1666
|
};
|
|
1689
1667
|
}
|
|
1690
|
-
const paddedRef = formatPaddedRef(boundary.numericId);
|
|
1691
|
-
if (state.hiddenOrphanRefs?.includes(paddedRef)) {
|
|
1692
|
-
const neighbor = snapToNeighborVisible(
|
|
1693
|
-
state,
|
|
1694
|
-
indexByMessageId,
|
|
1695
|
-
boundary.numericId,
|
|
1696
|
-
endpoint
|
|
1697
|
-
);
|
|
1698
|
-
if (neighbor !== null) {
|
|
1699
|
-
const dir = endpoint === "start" ? "the next visible message after it" : "the previous visible message before it";
|
|
1700
|
-
return {
|
|
1701
|
-
index: neighbor,
|
|
1702
|
-
snapped: `${label}="${boundary.raw}" is a hidden orphan compress call (no matching block) \u2014 snapped to ${dir} instead.`
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
throw new BoundaryNotFoundError(
|
|
1706
|
-
"consumed",
|
|
1707
|
-
endpoint,
|
|
1708
|
-
`${label}="${boundary.raw}" is a hidden orphan compress call with no adjacent visible message to anchor to \u2014 run acp_status for current refs.`
|
|
1709
|
-
);
|
|
1710
|
-
}
|
|
1711
1668
|
throw new BoundaryNotFoundError(
|
|
1712
1669
|
"consumed",
|
|
1713
1670
|
endpoint,
|
|
@@ -1784,26 +1741,6 @@ function inheritedContentIds(state, block) {
|
|
|
1784
1741
|
}
|
|
1785
1742
|
return ids;
|
|
1786
1743
|
}
|
|
1787
|
-
function snapToNeighborVisible(state, indexByMessageId, refNumber, endpoint) {
|
|
1788
|
-
let bestIndex = null;
|
|
1789
|
-
let bestRef = null;
|
|
1790
|
-
for (const [rawId, index] of indexByMessageId) {
|
|
1791
|
-
const refText = state.messageRefs.byRaw[rawId];
|
|
1792
|
-
if (!refText || refText === BLOCKED_REF) continue;
|
|
1793
|
-
const ref = refToIndex(refText);
|
|
1794
|
-
if (ref === null) continue;
|
|
1795
|
-
if (endpoint === "start") {
|
|
1796
|
-
if (ref > refNumber && (bestRef === null || ref < bestRef)) {
|
|
1797
|
-
bestRef = ref;
|
|
1798
|
-
bestIndex = index;
|
|
1799
|
-
}
|
|
1800
|
-
} else if (ref < refNumber && (bestRef === null || ref > bestRef)) {
|
|
1801
|
-
bestRef = ref;
|
|
1802
|
-
bestIndex = index;
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
return bestIndex;
|
|
1806
|
-
}
|
|
1807
1744
|
function formatPaddedRef(index) {
|
|
1808
1745
|
return `m${String(index).padStart(5, "0")}`;
|
|
1809
1746
|
}
|
|
@@ -1834,214 +1771,6 @@ function earliestIndexOfIds(ids, indexByMessageId) {
|
|
|
1834
1771
|
return earliest;
|
|
1835
1772
|
}
|
|
1836
1773
|
|
|
1837
|
-
// src/block-map.ts
|
|
1838
|
-
function refNum(ref) {
|
|
1839
|
-
const m = ref.match(/\d+/);
|
|
1840
|
-
return m ? parseInt(m[0], 10) : 0;
|
|
1841
|
-
}
|
|
1842
|
-
var M_REF = /^m\d+$/;
|
|
1843
|
-
function resolveBlockSpan(block, byRaw) {
|
|
1844
|
-
if (block.startRef && block.endRef && M_REF.test(block.startRef) && M_REF.test(block.endRef)) {
|
|
1845
|
-
return { startRef: block.startRef, endRef: block.endRef };
|
|
1846
|
-
}
|
|
1847
|
-
const refs = block.effectiveMessageIds.map((id) => byRaw[id]).filter((r) => typeof r === "string" && r !== "BLOCKED");
|
|
1848
|
-
if (refs.length === 0) return null;
|
|
1849
|
-
const sorted = [...refs].sort((a, b) => refNum(a) - refNum(b));
|
|
1850
|
-
return { startRef: sorted[0], endRef: sorted[sorted.length - 1] };
|
|
1851
|
-
}
|
|
1852
|
-
function activeBlockSpans(state) {
|
|
1853
|
-
const spans = [];
|
|
1854
|
-
for (const block of state.blocks) {
|
|
1855
|
-
if (!block.active) continue;
|
|
1856
|
-
const span = resolveBlockSpan(block, state.messageRefs.byRaw);
|
|
1857
|
-
if (!span) continue;
|
|
1858
|
-
spans.push({ blockId: block.blockId, tier: block.tier, ...span });
|
|
1859
|
-
}
|
|
1860
|
-
return spans;
|
|
1861
|
-
}
|
|
1862
|
-
function formatCreatedBlocks(state, newBlocks) {
|
|
1863
|
-
const parts = [];
|
|
1864
|
-
for (const block of newBlocks) {
|
|
1865
|
-
const span = resolveBlockSpan(block, state.messageRefs.byRaw);
|
|
1866
|
-
parts.push(
|
|
1867
|
-
span ? `${block.blockId}=${span.startRef}\u2013${span.endRef}` : block.blockId
|
|
1868
|
-
);
|
|
1869
|
-
}
|
|
1870
|
-
return parts.length > 0 ? `blocks: ${parts.join(", ")}` : "";
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
// src/decompress.ts
|
|
1874
|
-
function parseBlockIdArg(arg) {
|
|
1875
|
-
const normalized = arg.trim().toLowerCase();
|
|
1876
|
-
const refMatch = /^b0*(\d+)$/.exec(normalized);
|
|
1877
|
-
if (refMatch && refMatch[1] !== void 0) return `b${refMatch[1]}`;
|
|
1878
|
-
const numMatch = /^(\d+)$/.exec(normalized);
|
|
1879
|
-
if (numMatch && numMatch[1] !== void 0) return `b${numMatch[1]}`;
|
|
1880
|
-
return null;
|
|
1881
|
-
}
|
|
1882
|
-
function findBlocksOverlappingMessages(state, messageIds) {
|
|
1883
|
-
if (messageIds.size === 0) return [];
|
|
1884
|
-
const matched = [];
|
|
1885
|
-
for (const block of state.blocks) {
|
|
1886
|
-
if (!block.active) continue;
|
|
1887
|
-
if (block.effectiveMessageIds.some((id) => messageIds.has(id))) {
|
|
1888
|
-
matched.push(block);
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
return matched.sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));
|
|
1892
|
-
}
|
|
1893
|
-
function findActiveAncestor(state, blockId) {
|
|
1894
|
-
const start = state.blocks.find((b) => b.blockId === blockId);
|
|
1895
|
-
if (!start) return null;
|
|
1896
|
-
const queue = [...start.directBlockIds];
|
|
1897
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1898
|
-
while (queue.length > 0) {
|
|
1899
|
-
const currentId = queue.shift();
|
|
1900
|
-
if (visited.has(currentId)) continue;
|
|
1901
|
-
visited.add(currentId);
|
|
1902
|
-
const current = state.blocks.find((b) => b.blockId === currentId);
|
|
1903
|
-
if (!current) continue;
|
|
1904
|
-
if (current.active) return current.blockId;
|
|
1905
|
-
for (const ancestorId of current.directBlockIds) {
|
|
1906
|
-
if (!visited.has(ancestorId)) queue.push(ancestorId);
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
return null;
|
|
1910
|
-
}
|
|
1911
|
-
function deactivateBlock(state, blockIds, options = {}) {
|
|
1912
|
-
const targets = new Set(blockIds);
|
|
1913
|
-
const updated = state.blocks.map((block) => {
|
|
1914
|
-
if (!targets.has(block.blockId) || !block.active) return block;
|
|
1915
|
-
return {
|
|
1916
|
-
...block,
|
|
1917
|
-
active: false,
|
|
1918
|
-
durationMs: block.durationMs,
|
|
1919
|
-
createdAt: block.createdAt
|
|
1920
|
-
};
|
|
1921
|
-
});
|
|
1922
|
-
let final = updated;
|
|
1923
|
-
if (options.deep) {
|
|
1924
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1925
|
-
const queue = [];
|
|
1926
|
-
for (const id of blockIds) {
|
|
1927
|
-
const block = updated.find((b) => b.blockId === id);
|
|
1928
|
-
if (block) queue.push(...block.directBlockIds);
|
|
1929
|
-
}
|
|
1930
|
-
while (queue.length > 0) {
|
|
1931
|
-
const id = queue.shift();
|
|
1932
|
-
if (visited.has(id)) continue;
|
|
1933
|
-
visited.add(id);
|
|
1934
|
-
final = final.map((block) => {
|
|
1935
|
-
if (block.blockId !== id) return block;
|
|
1936
|
-
queue.push(...block.directBlockIds);
|
|
1937
|
-
return block.active ? { ...block, active: false } : block;
|
|
1938
|
-
});
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
return { ...state, blocks: final };
|
|
1942
|
-
}
|
|
1943
|
-
function buildRestoredContentPreview(messages, beforeActiveMessageIds, state) {
|
|
1944
|
-
const restored = [];
|
|
1945
|
-
for (const message of messages) {
|
|
1946
|
-
if (!beforeActiveMessageIds.has(message.id)) continue;
|
|
1947
|
-
const stillCovered = state.blocks.some(
|
|
1948
|
-
(b) => b.active && b.effectiveMessageIds.includes(message.id)
|
|
1949
|
-
);
|
|
1950
|
-
if (!stillCovered) restored.push(message);
|
|
1951
|
-
}
|
|
1952
|
-
if (restored.length === 0) return { preview: "", restoredCount: 0 };
|
|
1953
|
-
const lines = [];
|
|
1954
|
-
let totalLength = 0;
|
|
1955
|
-
const MAX_PREVIEW = 2e3;
|
|
1956
|
-
const MAX_PER_MESSAGE = 200;
|
|
1957
|
-
for (const message of restored) {
|
|
1958
|
-
if (totalLength >= MAX_PREVIEW) break;
|
|
1959
|
-
const text = message.text ?? "";
|
|
1960
|
-
const truncated = text.length > MAX_PER_MESSAGE ? clampPrefix(text, MAX_PER_MESSAGE) + "..." : text;
|
|
1961
|
-
const label = message.toolName && message.contentType !== "text" ? `${message.toolName}: ${truncated}` : `[${message.role}] ${truncated}`;
|
|
1962
|
-
lines.push(label);
|
|
1963
|
-
totalLength += label.length + 1;
|
|
1964
|
-
}
|
|
1965
|
-
return { preview: lines.join("\n"), restoredCount: restored.length };
|
|
1966
|
-
}
|
|
1967
|
-
function collectBlockContent(state, block, messages, options = {}) {
|
|
1968
|
-
const full = options.full ?? false;
|
|
1969
|
-
const targetIds = new Set(block.effectiveMessageIds);
|
|
1970
|
-
if (full) {
|
|
1971
|
-
const msgs = messages.filter((m) => targetIds.has(m.id));
|
|
1972
|
-
if (msgs.length === 0) return { text: "", count: 0 };
|
|
1973
|
-
return { text: msgs.map(formatMessage).join("\n\n"), count: msgs.length };
|
|
1974
|
-
}
|
|
1975
|
-
const nestedChildren = [];
|
|
1976
|
-
const nestedCovered = /* @__PURE__ */ new Set();
|
|
1977
|
-
for (const childId of block.directBlockIds) {
|
|
1978
|
-
const child = state.blocks.find((b) => b.blockId === childId);
|
|
1979
|
-
if (!child?.active) continue;
|
|
1980
|
-
nestedChildren.push(child);
|
|
1981
|
-
for (const id of child.effectiveMessageIds) nestedCovered.add(id);
|
|
1982
|
-
}
|
|
1983
|
-
const parts = [];
|
|
1984
|
-
for (const child of nestedChildren) {
|
|
1985
|
-
const label = child.topic ? `${child.blockId}: ${child.topic}` : child.blockId;
|
|
1986
|
-
parts.push(`${SUMMARY_HEADER} \u2014 ${label}
|
|
1987
|
-
${child.summary}`);
|
|
1988
|
-
}
|
|
1989
|
-
let directCount = 0;
|
|
1990
|
-
for (const m of messages) {
|
|
1991
|
-
if (targetIds.has(m.id) && !nestedCovered.has(m.id)) {
|
|
1992
|
-
parts.push(formatMessage(m));
|
|
1993
|
-
directCount++;
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
const count = directCount + nestedChildren.length;
|
|
1997
|
-
if (count === 0) return { text: "", count: 0 };
|
|
1998
|
-
return { text: parts.join("\n\n"), count };
|
|
1999
|
-
}
|
|
2000
|
-
function formatMessage(message) {
|
|
2001
|
-
const text = message.text ?? "";
|
|
2002
|
-
if (message.toolName && message.contentType !== "text") {
|
|
2003
|
-
return `[${message.role} \u2022 ${message.toolName}]
|
|
2004
|
-
${text}`;
|
|
2005
|
-
}
|
|
2006
|
-
return `[${message.role}]
|
|
2007
|
-
${text}`;
|
|
2008
|
-
}
|
|
2009
|
-
function numericPart(blockId) {
|
|
2010
|
-
const match = /^b(\d+)$/.exec(blockId);
|
|
2011
|
-
return match && match[1] !== void 0 ? Number(match[1]) : 0;
|
|
2012
|
-
}
|
|
2013
|
-
function markBlockRestoredInline(state, blockId) {
|
|
2014
|
-
const existing = state.blocks.find((b) => b.blockId === blockId);
|
|
2015
|
-
if (!existing) return { state, result: null };
|
|
2016
|
-
const blocks = state.blocks.map(
|
|
2017
|
-
(block) => block.blockId === blockId ? { ...block, restoredInline: true } : block
|
|
2018
|
-
);
|
|
2019
|
-
const span = resolveBlockSpan(existing, state.messageRefs.byRaw);
|
|
2020
|
-
const result = {
|
|
2021
|
-
restored: true,
|
|
2022
|
-
blockId,
|
|
2023
|
-
...span ? { restoredStartRef: span.startRef, restoredEndRef: span.endRef } : {}
|
|
2024
|
-
};
|
|
2025
|
-
return { state: { ...state, blocks }, result };
|
|
2026
|
-
}
|
|
2027
|
-
function activeAncestorIds(state, blockId) {
|
|
2028
|
-
const out = [];
|
|
2029
|
-
const visited = /* @__PURE__ */ new Set([blockId]);
|
|
2030
|
-
let frontier = [blockId];
|
|
2031
|
-
while (frontier.length > 0) {
|
|
2032
|
-
const next = [];
|
|
2033
|
-
for (const block of state.blocks) {
|
|
2034
|
-
if (visited.has(block.blockId)) continue;
|
|
2035
|
-
if (!block.directBlockIds.some((id) => frontier.includes(id))) continue;
|
|
2036
|
-
visited.add(block.blockId);
|
|
2037
|
-
if (block.active) out.push(block.blockId);
|
|
2038
|
-
next.push(block.blockId);
|
|
2039
|
-
}
|
|
2040
|
-
frontier = next;
|
|
2041
|
-
}
|
|
2042
|
-
return out;
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
1774
|
// src/truncate-tools.ts
|
|
2046
1775
|
var TRUNCATION_MARKER = "[truncated for context space]";
|
|
2047
1776
|
var DEFAULTS = {
|
|
@@ -2226,26 +1955,14 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
2226
1955
|
}
|
|
2227
1956
|
}
|
|
2228
1957
|
let hidden = 0;
|
|
2229
|
-
const hiddenOrphanRefs = [];
|
|
2230
|
-
const rememberHiddenRef = (message) => {
|
|
2231
|
-
if (message.toolCallId && allBlockCallIds.has(message.toolCallId)) {
|
|
2232
|
-
return;
|
|
2233
|
-
}
|
|
2234
|
-
const ref = state.messageRefs.byRaw[message.id];
|
|
2235
|
-
if (ref && ref !== BLOCKED_REF && !hiddenOrphanRefs.includes(ref)) {
|
|
2236
|
-
hiddenOrphanRefs.push(ref);
|
|
2237
|
-
}
|
|
2238
|
-
};
|
|
2239
1958
|
const result = [];
|
|
2240
1959
|
for (const message of messages) {
|
|
2241
1960
|
if (message.toolName === "compress" && message.contentType === "tool-call" && (!message.toolCallId || !keepCallIds.has(message.toolCallId))) {
|
|
2242
1961
|
hidden++;
|
|
2243
|
-
rememberHiddenRef(message);
|
|
2244
1962
|
continue;
|
|
2245
1963
|
}
|
|
2246
1964
|
if (message.contentType === "tool-result" && message.toolCallId && hiddenCallIds.has(message.toolCallId)) {
|
|
2247
1965
|
hidden++;
|
|
2248
|
-
rememberHiddenRef(message);
|
|
2249
1966
|
continue;
|
|
2250
1967
|
}
|
|
2251
1968
|
if (message.toolName === "compress" && message.contentType === "tool-call" && message.toolCallId && keepCallIds.has(message.toolCallId)) {
|
|
@@ -2265,7 +1982,7 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
2265
1982
|
}
|
|
2266
1983
|
result.push(message);
|
|
2267
1984
|
}
|
|
2268
|
-
return { messages: result, hidden
|
|
1985
|
+
return { messages: result, hidden };
|
|
2269
1986
|
}
|
|
2270
1987
|
|
|
2271
1988
|
// src/absorb.ts
|
|
@@ -3915,6 +3632,42 @@ function applyMessageFilters(messages, config) {
|
|
|
3915
3632
|
return { messages: working, ...tally };
|
|
3916
3633
|
}
|
|
3917
3634
|
|
|
3635
|
+
// src/block-map.ts
|
|
3636
|
+
function refNum(ref) {
|
|
3637
|
+
const m = ref.match(/\d+/);
|
|
3638
|
+
return m ? parseInt(m[0], 10) : 0;
|
|
3639
|
+
}
|
|
3640
|
+
var M_REF = /^m\d+$/;
|
|
3641
|
+
function resolveBlockSpan(block, byRaw) {
|
|
3642
|
+
if (block.startRef && block.endRef && M_REF.test(block.startRef) && M_REF.test(block.endRef)) {
|
|
3643
|
+
return { startRef: block.startRef, endRef: block.endRef };
|
|
3644
|
+
}
|
|
3645
|
+
const refs = block.effectiveMessageIds.map((id) => byRaw[id]).filter((r) => typeof r === "string" && r !== "BLOCKED");
|
|
3646
|
+
if (refs.length === 0) return null;
|
|
3647
|
+
const sorted = [...refs].sort((a, b) => refNum(a) - refNum(b));
|
|
3648
|
+
return { startRef: sorted[0], endRef: sorted[sorted.length - 1] };
|
|
3649
|
+
}
|
|
3650
|
+
function activeBlockSpans(state) {
|
|
3651
|
+
const spans = [];
|
|
3652
|
+
for (const block of state.blocks) {
|
|
3653
|
+
if (!block.active) continue;
|
|
3654
|
+
const span = resolveBlockSpan(block, state.messageRefs.byRaw);
|
|
3655
|
+
if (!span) continue;
|
|
3656
|
+
spans.push({ blockId: block.blockId, tier: block.tier, ...span });
|
|
3657
|
+
}
|
|
3658
|
+
return spans;
|
|
3659
|
+
}
|
|
3660
|
+
function formatCreatedBlocks(state, newBlocks) {
|
|
3661
|
+
const parts = [];
|
|
3662
|
+
for (const block of newBlocks) {
|
|
3663
|
+
const span = resolveBlockSpan(block, state.messageRefs.byRaw);
|
|
3664
|
+
parts.push(
|
|
3665
|
+
span ? `${block.blockId}=${span.startRef}\u2013${span.endRef}` : block.blockId
|
|
3666
|
+
);
|
|
3667
|
+
}
|
|
3668
|
+
return parts.length > 0 ? `blocks: ${parts.join(", ")}` : "";
|
|
3669
|
+
}
|
|
3670
|
+
|
|
3918
3671
|
// src/render-refs.ts
|
|
3919
3672
|
function formatTokens(tokens) {
|
|
3920
3673
|
if (tokens < 1e3) return String(tokens);
|
|
@@ -3987,11 +3740,6 @@ function createRenderRefsNode(strategy) {
|
|
|
3987
3740
|
}
|
|
3988
3741
|
var renderRefsNode = createRenderRefsNode("all");
|
|
3989
3742
|
|
|
3990
|
-
// src/message-kind.ts
|
|
3991
|
-
function isToolMessage(message) {
|
|
3992
|
-
return message.contentType === "tool-call" || message.contentType === "tool-result";
|
|
3993
|
-
}
|
|
3994
|
-
|
|
3995
3743
|
// src/tool-pairs.ts
|
|
3996
3744
|
function adjustBoundariesForToolPairs(startIndex, endIndex, messages, maxScan = 20) {
|
|
3997
3745
|
const callIdsInRange = /* @__PURE__ */ new Set();
|
|
@@ -4192,26 +3940,13 @@ function computeIntegrityWithdrawals(messages, foldedIds) {
|
|
|
4192
3940
|
};
|
|
4193
3941
|
}
|
|
4194
3942
|
|
|
4195
|
-
// src/segment.ts
|
|
4196
|
-
function segmentGroups(items) {
|
|
4197
|
-
const groups = [];
|
|
4198
|
-
let cur = null;
|
|
4199
|
-
for (const item of items) {
|
|
4200
|
-
if (cur !== null && (item.isUser && cur.length >= 3 || item.gapBefore)) {
|
|
4201
|
-
groups.push(cur);
|
|
4202
|
-
cur = null;
|
|
4203
|
-
}
|
|
4204
|
-
if (cur === null) cur = [item];
|
|
4205
|
-
else cur.push(item);
|
|
4206
|
-
}
|
|
4207
|
-
if (cur !== null) groups.push(cur);
|
|
4208
|
-
return groups;
|
|
4209
|
-
}
|
|
4210
|
-
|
|
4211
3943
|
// src/recommend.ts
|
|
4212
3944
|
function estimateTextTokens(text) {
|
|
4213
3945
|
return Math.ceil(text.length / 4);
|
|
4214
3946
|
}
|
|
3947
|
+
function isToolMessage(message) {
|
|
3948
|
+
return message.contentType === "tool-call" || message.contentType === "tool-result";
|
|
3949
|
+
}
|
|
4215
3950
|
function isSyntheticOrPruned(message, state) {
|
|
4216
3951
|
if (message.text?.startsWith("[Compressed conversation section]")) return true;
|
|
4217
3952
|
for (const block of state.blocks) {
|
|
@@ -4325,37 +4060,41 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
|
|
|
4325
4060
|
compressibleMsgs = kept;
|
|
4326
4061
|
}
|
|
4327
4062
|
const compressible = [];
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4063
|
+
let cur = null;
|
|
4064
|
+
for (const info of compressibleMsgs) {
|
|
4065
|
+
if (cur && (info.isUser && cur.count >= 3 || info.gapBefore)) {
|
|
4066
|
+
compressible.push(cur);
|
|
4067
|
+
cur = null;
|
|
4068
|
+
}
|
|
4069
|
+
if (!cur) {
|
|
4070
|
+
cur = {
|
|
4071
|
+
startRef: info.ref,
|
|
4072
|
+
endRef: info.ref,
|
|
4073
|
+
count: 1,
|
|
4074
|
+
tokens: info.tokens,
|
|
4075
|
+
chars: info.chars,
|
|
4076
|
+
toolPct: info.isTool ? 100 : 0,
|
|
4077
|
+
textPct: info.isTool ? 0 : 100,
|
|
4078
|
+
userMsgs: info.isUser ? 1 : 0,
|
|
4079
|
+
startIndex: info.index,
|
|
4080
|
+
endIndex: info.index
|
|
4081
|
+
};
|
|
4082
|
+
} else {
|
|
4083
|
+
cur.endRef = info.ref;
|
|
4084
|
+
cur.endIndex = info.index;
|
|
4085
|
+
cur.count++;
|
|
4086
|
+
cur.tokens += info.tokens;
|
|
4087
|
+
cur.chars = (cur.chars ?? 0) + info.chars;
|
|
4088
|
+
if (info.isUser) cur.userMsgs = (cur.userMsgs ?? 0) + 1;
|
|
4350
4089
|
if (info.isTool) {
|
|
4351
|
-
|
|
4090
|
+
cur.toolPct = Math.round((cur.toolPct * (cur.count - 1) + 100) / cur.count);
|
|
4352
4091
|
} else {
|
|
4353
|
-
|
|
4092
|
+
cur.toolPct = Math.round(cur.toolPct * (cur.count - 1) / cur.count);
|
|
4354
4093
|
}
|
|
4355
|
-
|
|
4094
|
+
cur.textPct = 100 - cur.toolPct;
|
|
4356
4095
|
}
|
|
4357
|
-
compressible.push(range);
|
|
4358
4096
|
}
|
|
4097
|
+
if (cur) compressible.push(cur);
|
|
4359
4098
|
const protectedRanges = [];
|
|
4360
4099
|
let pcur = null;
|
|
4361
4100
|
for (const info of protectedMsgs) {
|
|
@@ -4527,79 +4266,6 @@ function tierActionHint(config, state) {
|
|
|
4527
4266
|
}
|
|
4528
4267
|
return "";
|
|
4529
4268
|
}
|
|
4530
|
-
function requestedRefoldSpan(state, spec) {
|
|
4531
|
-
const nums = [];
|
|
4532
|
-
for (const ref of [spec.startRef, spec.endRef]) {
|
|
4533
|
-
const parsed = parseBoundary(ref);
|
|
4534
|
-
if (!parsed) return null;
|
|
4535
|
-
if (parsed.kind === "message") {
|
|
4536
|
-
nums.push(parsed.numericId);
|
|
4537
|
-
continue;
|
|
4538
|
-
}
|
|
4539
|
-
const block = blockById(state, `b${parsed.numericId}`);
|
|
4540
|
-
if (!block) return null;
|
|
4541
|
-
const span = resolveBlockSpan(block, state.messageRefs.byRaw);
|
|
4542
|
-
if (!span) return null;
|
|
4543
|
-
const lo = parseBoundary(span.startRef);
|
|
4544
|
-
const hi = parseBoundary(span.endRef);
|
|
4545
|
-
if (!lo || !hi) return null;
|
|
4546
|
-
nums.push(lo.numericId, hi.numericId);
|
|
4547
|
-
}
|
|
4548
|
-
return { lo: Math.min(...nums), hi: Math.max(...nums) };
|
|
4549
|
-
}
|
|
4550
|
-
function evaluateRefold(state, spec) {
|
|
4551
|
-
const span = requestedRefoldSpan(state, spec);
|
|
4552
|
-
if (!span) return { kind: "blocked", reasons: [] };
|
|
4553
|
-
const reasons = [];
|
|
4554
|
-
const blocks = [];
|
|
4555
|
-
for (const block of state.blocks) {
|
|
4556
|
-
if (!block.active) continue;
|
|
4557
|
-
const resolved = resolveBlockSpan(block, state.messageRefs.byRaw);
|
|
4558
|
-
if (!resolved) {
|
|
4559
|
-
reasons.push(`partially covered ${block.blockId}`);
|
|
4560
|
-
continue;
|
|
4561
|
-
}
|
|
4562
|
-
const ownLo = parseBoundary(resolved.startRef)?.numericId;
|
|
4563
|
-
const ownHi = parseBoundary(resolved.endRef)?.numericId;
|
|
4564
|
-
if (ownLo === void 0 || ownHi === void 0) continue;
|
|
4565
|
-
if (ownHi < span.lo || ownLo > span.hi) continue;
|
|
4566
|
-
if (!block.restoredInline) {
|
|
4567
|
-
reasons.push(`blocked by ${block.blockId} (not restored)`);
|
|
4568
|
-
continue;
|
|
4569
|
-
}
|
|
4570
|
-
if (ownLo < span.lo || ownHi > span.hi) {
|
|
4571
|
-
reasons.push(`partially covered ${block.blockId}`);
|
|
4572
|
-
continue;
|
|
4573
|
-
}
|
|
4574
|
-
const blockers = activeAncestorIds(state, block.blockId).filter(
|
|
4575
|
-
(ancestorId) => !blockById(state, ancestorId)?.restoredInline
|
|
4576
|
-
);
|
|
4577
|
-
if (blockers.length > 0) {
|
|
4578
|
-
for (const id of blockers)
|
|
4579
|
-
reasons.push(`blocked by ${id} (not restored)`);
|
|
4580
|
-
continue;
|
|
4581
|
-
}
|
|
4582
|
-
blocks.push(block);
|
|
4583
|
-
}
|
|
4584
|
-
const uniqueReasons = [...new Set(reasons)];
|
|
4585
|
-
if (uniqueReasons.length > 0)
|
|
4586
|
-
return { kind: "blocked", reasons: uniqueReasons };
|
|
4587
|
-
if (blocks.length > 0) return { kind: "refold", blocks };
|
|
4588
|
-
return { kind: "blocked", reasons: [] };
|
|
4589
|
-
}
|
|
4590
|
-
function applyRefolds(input) {
|
|
4591
|
-
validateSummaryLength(input.spec, input.config.compress);
|
|
4592
|
-
const targets = new Set(input.blockIds);
|
|
4593
|
-
input.state.blocks = input.state.blocks.map(
|
|
4594
|
-
(block) => targets.has(block.blockId) ? {
|
|
4595
|
-
...block,
|
|
4596
|
-
summary: input.spec.summary,
|
|
4597
|
-
topic: input.spec.topic ?? block.topic,
|
|
4598
|
-
runId: input.runId,
|
|
4599
|
-
restoredInline: false
|
|
4600
|
-
} : block
|
|
4601
|
-
);
|
|
4602
|
-
}
|
|
4603
4269
|
function createCore(ports = {}) {
|
|
4604
4270
|
const countTokens = ports.countTokens ?? defaultCountTokens;
|
|
4605
4271
|
function applyCompression(input) {
|
|
@@ -4609,7 +4275,6 @@ function createCore(ports = {}) {
|
|
|
4609
4275
|
let tokensCompressed = 0;
|
|
4610
4276
|
const errors = [];
|
|
4611
4277
|
const warnings = [];
|
|
4612
|
-
const notes = [];
|
|
4613
4278
|
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(
|
|
4614
4279
|
input.messages,
|
|
4615
4280
|
input.state,
|
|
@@ -4660,18 +4325,6 @@ function createCore(ports = {}) {
|
|
|
4660
4325
|
if (resolution.status === "ok") resolvableCount++;
|
|
4661
4326
|
else if (resolution.status === "unknown") unknownCount++;
|
|
4662
4327
|
}
|
|
4663
|
-
const refoldDecisions = /* @__PURE__ */ new Map();
|
|
4664
|
-
const isRefoldCandidate = (resolution) => resolution.status === "consumed" || resolution.status === "ok" && resolution.resolved.boundaryKind !== "block" && resolution.resolved.messageIds.every(
|
|
4665
|
-
(id) => preExistingCoverage.has(id)
|
|
4666
|
-
);
|
|
4667
|
-
for (const [spec, resolution] of classifications) {
|
|
4668
|
-
if (isRefoldCandidate(resolution)) {
|
|
4669
|
-
refoldDecisions.set(spec, evaluateRefold(state, spec));
|
|
4670
|
-
}
|
|
4671
|
-
}
|
|
4672
|
-
const allRefold = input.ranges.length > 0 && unknownCount === 0 && [...classifications.entries()].every(
|
|
4673
|
-
([spec, resolution]) => isRefoldCandidate(resolution) && refoldDecisions.get(spec)?.kind === "refold"
|
|
4674
|
-
);
|
|
4675
4328
|
const rangeSpans = [];
|
|
4676
4329
|
for (const [spec, resolution] of classifications) {
|
|
4677
4330
|
if (resolution.status !== "ok") continue;
|
|
@@ -4710,7 +4363,7 @@ function createCore(ports = {}) {
|
|
|
4710
4363
|
totalRangeChars += msg?.text?.length ?? 0;
|
|
4711
4364
|
}
|
|
4712
4365
|
}
|
|
4713
|
-
if (!
|
|
4366
|
+
if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {
|
|
4714
4367
|
const diagnostics = refGateDiagnostics(
|
|
4715
4368
|
state,
|
|
4716
4369
|
input.ranges.length,
|
|
@@ -4719,50 +4372,10 @@ function createCore(ports = {}) {
|
|
|
4719
4372
|
const firstConsumed = consumedRanges[0];
|
|
4720
4373
|
const covering = firstConsumed ? coveringBlockIds(state, firstConsumed) : [];
|
|
4721
4374
|
const coverDetail = covering.length > 0 ? `its content is already summarized in active block(s) ${covering.join(", ")}${covering.length === 1 ? ` \u2014 use search_context or decompress ${covering[0]} if you need details from it` : ""}` : `its refs no longer point to directly compressible content (stale block ref(s) distilled or consumed by higher-tier blocks)`;
|
|
4722
|
-
const refoldReasons = [
|
|
4723
|
-
...new Set(
|
|
4724
|
-
consumedRanges.flatMap((spec) => {
|
|
4725
|
-
const decision = refoldDecisions.get(spec);
|
|
4726
|
-
return decision?.kind === "blocked" ? decision.reasons : [];
|
|
4727
|
-
})
|
|
4728
|
-
)
|
|
4729
|
-
];
|
|
4730
|
-
const refoldSuffix = (reasons) => reasons.length > 0 ? ` Refold blocked: ${reasons.join("; ")}. Restore the affected block(s) inline (decompress with inline:true), then recompressing the same range updates them in place` : "";
|
|
4731
|
-
const refoldDetail = refoldSuffix(refoldReasons);
|
|
4732
|
-
const okBlockedReasons = [
|
|
4733
|
-
...new Set(
|
|
4734
|
-
[...classifications.entries()].flatMap(([spec, resolution]) => {
|
|
4735
|
-
if (skipSpecs.has(spec) || resolution.status !== "ok") return [];
|
|
4736
|
-
const decision = refoldDecisions.get(spec);
|
|
4737
|
-
return decision?.kind === "blocked" ? decision.reasons : [];
|
|
4738
|
-
})
|
|
4739
|
-
)
|
|
4740
|
-
];
|
|
4741
4375
|
const danglingRefs = consumedRanges.flatMap(
|
|
4742
4376
|
(spec) => danglingMessageRefs(state, input.messages, spec)
|
|
4743
4377
|
);
|
|
4744
|
-
|
|
4745
|
-
if (gateMessage === null) {
|
|
4746
|
-
return {
|
|
4747
|
-
state: input.state,
|
|
4748
|
-
result: {
|
|
4749
|
-
blocksCreated: 0,
|
|
4750
|
-
tokensCompressed: 0,
|
|
4751
|
-
errors: [...classificationErrors],
|
|
4752
|
-
warnings: []
|
|
4753
|
-
}
|
|
4754
|
-
};
|
|
4755
|
-
}
|
|
4756
|
-
const reversalNotes = [];
|
|
4757
|
-
for (const [spec, resolution] of classifications) {
|
|
4758
|
-
if (resolution.status === "ok" && !skipSpecs.has(spec)) {
|
|
4759
|
-
const note = resolution.resolved.reversedNote;
|
|
4760
|
-
if (note) reversalNotes.push(note);
|
|
4761
|
-
}
|
|
4762
|
-
}
|
|
4763
|
-
if (reversalNotes.length > 0) {
|
|
4764
|
-
gateMessage += ` ${reversalNotes.join(" ")}`;
|
|
4765
|
-
}
|
|
4378
|
+
const gateMessage = resolvableCount === 0 && consumedRanges.length === 0 && unknownCount > 0 ? `None of the ${input.ranges.length} requested range(s) resolved \u2014 every ref is unknown to this session. Refs are per-session snapshots, assigned once when a message is first rendered; no compress reassigns them, so unknown refs cannot come from an earlier compress in this session. They come from a different generation: a previous session instance (switching model or upstream mid-conversation starts a fresh session whose refs restart at m00001), the generation before a native-compaction rebase (which also resets refs to m00001), or a typo. ${diagnostics} Run acp_status, then call the compress tool again using only the refs it reports.` : consumedRanges.length > 0 ? danglingRefs.length > 0 ? `Requested range(s) cannot be anchored (e.g. ${firstConsumed.startRef}..${firstConsumed.endRef}) \u2014 the refs exist in this session's ref map, but the messages they point to are no longer in the visible context and no active block covers them: the message content changed (or the message was filtered out of the view) and now carries a new ref, leaving your old refs dangling. ${diagnostics} Run acp_status, then call the compress tool again using only the refs it reports.` : `Requested range(s) already compressed (e.g. ${firstConsumed.startRef}..${firstConsumed.endRef}) \u2014 ${coverDetail}. Nothing new to compress in that window. ${diagnostics} Continue the task, or run acp_status and target one of the CURRENT compressible ranges it reports.${tierActionHint(input.config, state)}` : `Total compressible content too small (${totalRangeChars} chars across ${countedRanges} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`;
|
|
4766
4379
|
return {
|
|
4767
4380
|
state: input.state,
|
|
4768
4381
|
result: {
|
|
@@ -4779,30 +4392,8 @@ function createCore(ports = {}) {
|
|
|
4779
4392
|
const resolution = classifications.get(spec);
|
|
4780
4393
|
if (resolution === void 0) continue;
|
|
4781
4394
|
if (resolution.status === "consumed") {
|
|
4782
|
-
const decision = refoldDecisions.get(spec);
|
|
4783
|
-
if (decision?.kind === "refold") {
|
|
4784
|
-
try {
|
|
4785
|
-
applyRefolds({
|
|
4786
|
-
spec,
|
|
4787
|
-
state,
|
|
4788
|
-
runId,
|
|
4789
|
-
config: input.config,
|
|
4790
|
-
blockIds: decision.blocks.map((block) => block.blockId)
|
|
4791
|
-
});
|
|
4792
|
-
blocksCreated += decision.blocks.length;
|
|
4793
|
-
} catch (error) {
|
|
4794
|
-
errors.push(
|
|
4795
|
-
rangeError(
|
|
4796
|
-
spec,
|
|
4797
|
-
error instanceof Error ? error.message : String(error)
|
|
4798
|
-
)
|
|
4799
|
-
);
|
|
4800
|
-
}
|
|
4801
|
-
continue;
|
|
4802
|
-
}
|
|
4803
|
-
const reasons = decision?.kind === "blocked" ? decision.reasons : [];
|
|
4804
4395
|
warnings.push(
|
|
4805
|
-
`Skipped range (${spec.startRef}..${spec.endRef}) \u2014 already compressed
|
|
4396
|
+
`Skipped range (${spec.startRef}..${spec.endRef}) \u2014 already compressed (messages consumed by existing block(s)); nothing to compress.`
|
|
4806
4397
|
);
|
|
4807
4398
|
continue;
|
|
4808
4399
|
}
|
|
@@ -4811,8 +4402,6 @@ function createCore(ports = {}) {
|
|
|
4811
4402
|
continue;
|
|
4812
4403
|
}
|
|
4813
4404
|
warnings.push(...resolution.resolved.snappedBoundaries);
|
|
4814
|
-
const note = resolution.resolved.reversedNote;
|
|
4815
|
-
if (note) notes.push(note);
|
|
4816
4405
|
try {
|
|
4817
4406
|
const outcome = applySingleRange({
|
|
4818
4407
|
spec,
|
|
@@ -4824,7 +4413,7 @@ function createCore(ports = {}) {
|
|
|
4824
4413
|
countTokens,
|
|
4825
4414
|
preExistingCoverage
|
|
4826
4415
|
});
|
|
4827
|
-
blocksCreated
|
|
4416
|
+
blocksCreated++;
|
|
4828
4417
|
tokensCompressed += outcome.tokens;
|
|
4829
4418
|
warnings.push(...outcome.warnings);
|
|
4830
4419
|
} catch (error) {
|
|
@@ -4846,13 +4435,7 @@ function createCore(ports = {}) {
|
|
|
4846
4435
|
}
|
|
4847
4436
|
return {
|
|
4848
4437
|
state,
|
|
4849
|
-
result: {
|
|
4850
|
-
blocksCreated,
|
|
4851
|
-
tokensCompressed,
|
|
4852
|
-
errors,
|
|
4853
|
-
warnings,
|
|
4854
|
-
...notes.length > 0 ? { notes } : {}
|
|
4855
|
-
}
|
|
4438
|
+
result: { blocksCreated, tokensCompressed, errors, warnings }
|
|
4856
4439
|
};
|
|
4857
4440
|
}
|
|
4858
4441
|
function processTurn(input) {
|
|
@@ -5036,11 +4619,7 @@ var hideCompressCallsNode = {
|
|
|
5036
4619
|
name: "hide-compress-calls",
|
|
5037
4620
|
run(io) {
|
|
5038
4621
|
const hidden = hideConsumedCompressCalls(io.state, io.messages);
|
|
5039
|
-
return {
|
|
5040
|
-
...io,
|
|
5041
|
-
messages: hidden.messages,
|
|
5042
|
-
state: { ...io.state, hiddenOrphanRefs: hidden.hiddenOrphanRefs }
|
|
5043
|
-
};
|
|
4622
|
+
return { ...io, messages: hidden.messages };
|
|
5044
4623
|
}
|
|
5045
4624
|
};
|
|
5046
4625
|
var recommendNode = {
|
|
@@ -5298,21 +4877,6 @@ function applySingleRange(input) {
|
|
|
5298
4877
|
}
|
|
5299
4878
|
}
|
|
5300
4879
|
if (!isBlockBoundary && filteredIds.length === 0 && consumedBlockIds.length > 0) {
|
|
5301
|
-
const decision = evaluateRefold(input.state, input.spec);
|
|
5302
|
-
if (decision.kind === "refold") {
|
|
5303
|
-
applyRefolds({
|
|
5304
|
-
spec: input.spec,
|
|
5305
|
-
state: input.state,
|
|
5306
|
-
runId: input.runId,
|
|
5307
|
-
config: input.config,
|
|
5308
|
-
blockIds: decision.blocks.map((block2) => block2.blockId)
|
|
5309
|
-
});
|
|
5310
|
-
return {
|
|
5311
|
-
tokens: 0,
|
|
5312
|
-
warnings,
|
|
5313
|
-
refolded: decision.blocks.map((block2) => block2.blockId)
|
|
5314
|
-
};
|
|
5315
|
-
}
|
|
5316
4880
|
const first = consumedBlockIds[0];
|
|
5317
4881
|
const last = consumedBlockIds[consumedBlockIds.length - 1];
|
|
5318
4882
|
throw new Error(
|
|
@@ -5393,15 +4957,7 @@ function applyPairBoundaryAdjustments(resolved, messages) {
|
|
|
5393
4957
|
}
|
|
5394
4958
|
function validateCompressionRange(input, directMessageIds, consumedBlockCount) {
|
|
5395
4959
|
const cfg = input.config.compress;
|
|
5396
|
-
|
|
5397
|
-
if (directMessageIds.length === 0 && consumedBlockCount === 0) {
|
|
5398
|
-
throw new Error(
|
|
5399
|
-
"Range contains no compressible messages \u2014 all are already covered by active blocks or protected."
|
|
5400
|
-
);
|
|
5401
|
-
}
|
|
5402
|
-
}
|
|
5403
|
-
function validateSummaryLength(spec, cfg) {
|
|
5404
|
-
const summary = spec.summary?.trim() ?? "";
|
|
4960
|
+
const summary = input.spec.summary?.trim() ?? "";
|
|
5405
4961
|
if (summary.length === 0) {
|
|
5406
4962
|
throw new Error(
|
|
5407
4963
|
"Summary is empty \u2014 provide a meaningful summary of the compressed range."
|
|
@@ -5412,12 +4968,17 @@ function validateSummaryLength(spec, cfg) {
|
|
|
5412
4968
|
`Summary too short (${summary.length} chars, min ${cfg.minSummaryLength}). The summary must capture the compressed range's key information.`
|
|
5413
4969
|
);
|
|
5414
4970
|
}
|
|
5415
|
-
const effectiveMax = spec.summaryMaxChars ?? cfg.maxSummaryLength;
|
|
4971
|
+
const effectiveMax = input.spec.summaryMaxChars ?? cfg.maxSummaryLength;
|
|
5416
4972
|
if (effectiveMax > 0 && summary.length > effectiveMax) {
|
|
5417
4973
|
throw new Error(
|
|
5418
4974
|
`Summary too long (${summary.length} chars, max ${effectiveMax}). Strip noise \u2014 keep critical paths, decisions, errors, and code references. Or pass summaryMaxChars to increase the limit \u2014 don't lose critical info just to fit.`
|
|
5419
4975
|
);
|
|
5420
4976
|
}
|
|
4977
|
+
if (directMessageIds.length === 0 && consumedBlockCount === 0) {
|
|
4978
|
+
throw new Error(
|
|
4979
|
+
"Range contains no compressible messages \u2014 all are already covered by active blocks or protected."
|
|
4980
|
+
);
|
|
4981
|
+
}
|
|
5421
4982
|
}
|
|
5422
4983
|
function filterProtectedToolMessages(directMessageIds, messages, config) {
|
|
5423
4984
|
const protectedCallIds = /* @__PURE__ */ new Set();
|
|
@@ -5658,7 +5219,7 @@ function computeContextBreakdown(messages, total, growth, countTokens) {
|
|
|
5658
5219
|
const tokens = countMessageTokens(msg, count);
|
|
5659
5220
|
if (msg.text?.startsWith("[Compressed conversation section]")) {
|
|
5660
5221
|
summaries += tokens;
|
|
5661
|
-
} else if (
|
|
5222
|
+
} else if (msg.contentType === "tool-call" || msg.contentType === "tool-result") {
|
|
5662
5223
|
tool += tokens;
|
|
5663
5224
|
} else if (msg.role === "system") {
|
|
5664
5225
|
system += tokens;
|
|
@@ -5690,8 +5251,7 @@ function cloneState(state) {
|
|
|
5690
5251
|
nextRuleId: state.nextRuleId,
|
|
5691
5252
|
terminalStreak: state.terminalStreak,
|
|
5692
5253
|
nextBlockId: state.nextBlockId,
|
|
5693
|
-
nextRunId: state.nextRunId
|
|
5694
|
-
hiddenOrphanRefs: state.hiddenOrphanRefs ? [...state.hiddenOrphanRefs] : void 0
|
|
5254
|
+
nextRunId: state.nextRunId
|
|
5695
5255
|
};
|
|
5696
5256
|
}
|
|
5697
5257
|
function scoreRelevance(block, terms) {
|
|
@@ -5961,6 +5521,147 @@ function defaultPackSources(opts) {
|
|
|
5961
5521
|
return sources;
|
|
5962
5522
|
}
|
|
5963
5523
|
|
|
5524
|
+
// src/decompress.ts
|
|
5525
|
+
function parseBlockIdArg(arg) {
|
|
5526
|
+
const normalized = arg.trim().toLowerCase();
|
|
5527
|
+
const refMatch = /^b0*(\d+)$/.exec(normalized);
|
|
5528
|
+
if (refMatch && refMatch[1] !== void 0) return `b${refMatch[1]}`;
|
|
5529
|
+
const numMatch = /^(\d+)$/.exec(normalized);
|
|
5530
|
+
if (numMatch && numMatch[1] !== void 0) return `b${numMatch[1]}`;
|
|
5531
|
+
return null;
|
|
5532
|
+
}
|
|
5533
|
+
function findBlocksOverlappingMessages(state, messageIds) {
|
|
5534
|
+
if (messageIds.size === 0) return [];
|
|
5535
|
+
const matched = [];
|
|
5536
|
+
for (const block of state.blocks) {
|
|
5537
|
+
if (!block.active) continue;
|
|
5538
|
+
if (block.effectiveMessageIds.some((id) => messageIds.has(id))) {
|
|
5539
|
+
matched.push(block);
|
|
5540
|
+
}
|
|
5541
|
+
}
|
|
5542
|
+
return matched.sort((a, b) => numericPart(a.blockId) - numericPart(b.blockId));
|
|
5543
|
+
}
|
|
5544
|
+
function findActiveAncestor(state, blockId) {
|
|
5545
|
+
const start = state.blocks.find((b) => b.blockId === blockId);
|
|
5546
|
+
if (!start) return null;
|
|
5547
|
+
const queue = [...start.directBlockIds];
|
|
5548
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5549
|
+
while (queue.length > 0) {
|
|
5550
|
+
const currentId = queue.shift();
|
|
5551
|
+
if (visited.has(currentId)) continue;
|
|
5552
|
+
visited.add(currentId);
|
|
5553
|
+
const current = state.blocks.find((b) => b.blockId === currentId);
|
|
5554
|
+
if (!current) continue;
|
|
5555
|
+
if (current.active) return current.blockId;
|
|
5556
|
+
for (const ancestorId of current.directBlockIds) {
|
|
5557
|
+
if (!visited.has(ancestorId)) queue.push(ancestorId);
|
|
5558
|
+
}
|
|
5559
|
+
}
|
|
5560
|
+
return null;
|
|
5561
|
+
}
|
|
5562
|
+
function deactivateBlock(state, blockIds, options = {}) {
|
|
5563
|
+
const targets = new Set(blockIds);
|
|
5564
|
+
const updated = state.blocks.map((block) => {
|
|
5565
|
+
if (!targets.has(block.blockId) || !block.active) return block;
|
|
5566
|
+
return {
|
|
5567
|
+
...block,
|
|
5568
|
+
active: false,
|
|
5569
|
+
durationMs: block.durationMs,
|
|
5570
|
+
createdAt: block.createdAt
|
|
5571
|
+
};
|
|
5572
|
+
});
|
|
5573
|
+
let final = updated;
|
|
5574
|
+
if (options.deep) {
|
|
5575
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5576
|
+
const queue = [];
|
|
5577
|
+
for (const id of blockIds) {
|
|
5578
|
+
const block = updated.find((b) => b.blockId === id);
|
|
5579
|
+
if (block) queue.push(...block.directBlockIds);
|
|
5580
|
+
}
|
|
5581
|
+
while (queue.length > 0) {
|
|
5582
|
+
const id = queue.shift();
|
|
5583
|
+
if (visited.has(id)) continue;
|
|
5584
|
+
visited.add(id);
|
|
5585
|
+
final = final.map((block) => {
|
|
5586
|
+
if (block.blockId !== id) return block;
|
|
5587
|
+
queue.push(...block.directBlockIds);
|
|
5588
|
+
return block.active ? { ...block, active: false } : block;
|
|
5589
|
+
});
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
return { ...state, blocks: final };
|
|
5593
|
+
}
|
|
5594
|
+
function buildRestoredContentPreview(messages, beforeActiveMessageIds, state) {
|
|
5595
|
+
const restored = [];
|
|
5596
|
+
for (const message of messages) {
|
|
5597
|
+
if (!beforeActiveMessageIds.has(message.id)) continue;
|
|
5598
|
+
const stillCovered = state.blocks.some(
|
|
5599
|
+
(b) => b.active && b.effectiveMessageIds.includes(message.id)
|
|
5600
|
+
);
|
|
5601
|
+
if (!stillCovered) restored.push(message);
|
|
5602
|
+
}
|
|
5603
|
+
if (restored.length === 0) return { preview: "", restoredCount: 0 };
|
|
5604
|
+
const lines = [];
|
|
5605
|
+
let totalLength = 0;
|
|
5606
|
+
const MAX_PREVIEW = 2e3;
|
|
5607
|
+
const MAX_PER_MESSAGE = 200;
|
|
5608
|
+
for (const message of restored) {
|
|
5609
|
+
if (totalLength >= MAX_PREVIEW) break;
|
|
5610
|
+
const text = message.text ?? "";
|
|
5611
|
+
const truncated = text.length > MAX_PER_MESSAGE ? clampPrefix(text, MAX_PER_MESSAGE) + "..." : text;
|
|
5612
|
+
const label = message.toolName && message.contentType !== "text" ? `${message.toolName}: ${truncated}` : `[${message.role}] ${truncated}`;
|
|
5613
|
+
lines.push(label);
|
|
5614
|
+
totalLength += label.length + 1;
|
|
5615
|
+
}
|
|
5616
|
+
return { preview: lines.join("\n"), restoredCount: restored.length };
|
|
5617
|
+
}
|
|
5618
|
+
function collectBlockContent(state, block, messages, options = {}) {
|
|
5619
|
+
const full = options.full ?? false;
|
|
5620
|
+
const targetIds = new Set(block.effectiveMessageIds);
|
|
5621
|
+
if (full) {
|
|
5622
|
+
const msgs = messages.filter((m) => targetIds.has(m.id));
|
|
5623
|
+
if (msgs.length === 0) return { text: "", count: 0 };
|
|
5624
|
+
return { text: msgs.map(formatMessage).join("\n\n"), count: msgs.length };
|
|
5625
|
+
}
|
|
5626
|
+
const nestedChildren = [];
|
|
5627
|
+
const nestedCovered = /* @__PURE__ */ new Set();
|
|
5628
|
+
for (const childId of block.directBlockIds) {
|
|
5629
|
+
const child = state.blocks.find((b) => b.blockId === childId);
|
|
5630
|
+
if (!child?.active) continue;
|
|
5631
|
+
nestedChildren.push(child);
|
|
5632
|
+
for (const id of child.effectiveMessageIds) nestedCovered.add(id);
|
|
5633
|
+
}
|
|
5634
|
+
const parts = [];
|
|
5635
|
+
for (const child of nestedChildren) {
|
|
5636
|
+
const label = child.topic ? `${child.blockId}: ${child.topic}` : child.blockId;
|
|
5637
|
+
parts.push(`${SUMMARY_HEADER} \u2014 ${label}
|
|
5638
|
+
${child.summary}`);
|
|
5639
|
+
}
|
|
5640
|
+
let directCount = 0;
|
|
5641
|
+
for (const m of messages) {
|
|
5642
|
+
if (targetIds.has(m.id) && !nestedCovered.has(m.id)) {
|
|
5643
|
+
parts.push(formatMessage(m));
|
|
5644
|
+
directCount++;
|
|
5645
|
+
}
|
|
5646
|
+
}
|
|
5647
|
+
const count = directCount + nestedChildren.length;
|
|
5648
|
+
if (count === 0) return { text: "", count: 0 };
|
|
5649
|
+
return { text: parts.join("\n\n"), count };
|
|
5650
|
+
}
|
|
5651
|
+
function formatMessage(message) {
|
|
5652
|
+
const text = message.text ?? "";
|
|
5653
|
+
if (message.toolName && message.contentType !== "text") {
|
|
5654
|
+
return `[${message.role} \u2022 ${message.toolName}]
|
|
5655
|
+
${text}`;
|
|
5656
|
+
}
|
|
5657
|
+
return `[${message.role}]
|
|
5658
|
+
${text}`;
|
|
5659
|
+
}
|
|
5660
|
+
function numericPart(blockId) {
|
|
5661
|
+
const match = /^b(\d+)$/.exec(blockId);
|
|
5662
|
+
return match && match[1] !== void 0 ? Number(match[1]) : 0;
|
|
5663
|
+
}
|
|
5664
|
+
|
|
5964
5665
|
// src/report.ts
|
|
5965
5666
|
function formatTokens2(n) {
|
|
5966
5667
|
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
@@ -5985,16 +5686,14 @@ function tierLabel(block) {
|
|
|
5985
5686
|
}
|
|
5986
5687
|
function tierBreakdown(blocks, countTokens) {
|
|
5987
5688
|
const tierTokens = {};
|
|
5988
|
-
const tierCounts = {};
|
|
5989
5689
|
for (const block of blocks) {
|
|
5990
5690
|
tierTokens[block.tier] = (tierTokens[block.tier] ?? 0) + summaryTokensOf(block, countTokens);
|
|
5991
|
-
tierCounts[block.tier] = (tierCounts[block.tier] ?? 0) + 1;
|
|
5992
5691
|
}
|
|
5993
5692
|
const tiers = Object.keys(tierTokens).map(Number);
|
|
5994
5693
|
if (tiers.length <= 1) return null;
|
|
5995
5694
|
const parts = [];
|
|
5996
5695
|
for (const tier of [1, 2, 3]) {
|
|
5997
|
-
if (tierTokens[tier]) parts.push(`T${tier}: ${formatTokens2(tierTokens[tier])}
|
|
5696
|
+
if (tierTokens[tier]) parts.push(`T${tier}: ${formatTokens2(tierTokens[tier])}`);
|
|
5998
5697
|
}
|
|
5999
5698
|
return parts.join(" | ");
|
|
6000
5699
|
}
|
|
@@ -6015,19 +5714,13 @@ function collectVisible(messages, state, countTokens) {
|
|
|
6015
5714
|
toolCallNames.set(message.toolCallId, message.toolName);
|
|
6016
5715
|
}
|
|
6017
5716
|
}
|
|
6018
|
-
let pendingGap = false;
|
|
6019
5717
|
messages.forEach((message, index) => {
|
|
5718
|
+
if (coveredIds.has(message.id)) return;
|
|
6020
5719
|
const ref = refForRaw(state.messageRefs, message.id);
|
|
6021
5720
|
if (!ref) return;
|
|
6022
5721
|
const tokens = countMessageTokens(message, countTokens);
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
const tool = isTool ? message.toolName ?? (message.toolCallId ? toolCallNames.get(message.toolCallId) : void 0) ?? "tool" : "text";
|
|
6026
|
-
visible.push({ ref, tokens, tool, isTool, index, isUser: message.role === "user", gapBefore: pendingGap });
|
|
6027
|
-
pendingGap = false;
|
|
6028
|
-
return;
|
|
6029
|
-
}
|
|
6030
|
-
if (ref !== BLOCKED_REF && tokens > 0) pendingGap = true;
|
|
5722
|
+
const tool = isToolMessage(message) ? message.toolName ?? (message.toolCallId ? toolCallNames.get(message.toolCallId) : void 0) ?? "tool" : "text";
|
|
5723
|
+
if (tokens > 0) visible.push({ ref, tokens, tool, index });
|
|
6031
5724
|
});
|
|
6032
5725
|
return { visible, summaryTokens };
|
|
6033
5726
|
}
|
|
@@ -6046,7 +5739,7 @@ function buildStatusReport(state, messages, countTokens, options = {}) {
|
|
|
6046
5739
|
if (view === "messages") {
|
|
6047
5740
|
return renderMessageDrilldown(visible, toolFilter, sort, limit);
|
|
6048
5741
|
}
|
|
6049
|
-
return renderUncompressedRanges(visible
|
|
5742
|
+
return renderUncompressedRanges(visible);
|
|
6050
5743
|
}
|
|
6051
5744
|
return renderOverview(visible, summaryTokens, activeBlocks2, state, countTokens, limit, options.meta);
|
|
6052
5745
|
}
|
|
@@ -6070,8 +5763,8 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
6070
5763
|
toolTypeMap.set(message.tool, (toolTypeMap.get(message.tool) ?? 0) + message.tokens);
|
|
6071
5764
|
}
|
|
6072
5765
|
const topTool = [...toolTypeMap.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
6073
|
-
const totalTool = visible.filter((m) => m.
|
|
6074
|
-
const totalText = visible.filter((m) =>
|
|
5766
|
+
const totalTool = visible.filter((m) => m.tool !== "text").reduce((sum, m) => sum + m.tokens, 0);
|
|
5767
|
+
const totalText = visible.filter((m) => m.tool === "text").reduce((sum, m) => sum + m.tokens, 0);
|
|
6075
5768
|
const total = summaryTokens + totalTool + totalText;
|
|
6076
5769
|
lines.push("CONTEXT BREAKDOWN");
|
|
6077
5770
|
lines.push(
|
|
@@ -6107,11 +5800,6 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
6107
5800
|
` ${block.blockId} (${tierLabel(block)}) ${formatTokens2(eff)}\u2192${formatTokens2(summaryTokensOf(block, countTokens))} ${block.effectiveMessageIds.length} msgs "${topic}"`
|
|
6108
5801
|
);
|
|
6109
5802
|
}
|
|
6110
|
-
if (blocks.length > limit) {
|
|
6111
|
-
lines.push(
|
|
6112
|
-
` ... and ${blocks.length - limit} more blocks not shown (scope:"compressed", limit:${blocks.length} for full list)`
|
|
6113
|
-
);
|
|
6114
|
-
}
|
|
6115
5803
|
}
|
|
6116
5804
|
lines.push("");
|
|
6117
5805
|
lines.push(
|
|
@@ -6119,7 +5807,7 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
6119
5807
|
);
|
|
6120
5808
|
return lines.join("\n");
|
|
6121
5809
|
}
|
|
6122
|
-
function renderUncompressedRanges(visible
|
|
5810
|
+
function renderUncompressedRanges(visible) {
|
|
6123
5811
|
const lines = [];
|
|
6124
5812
|
const totalTokens = visible.reduce((s, m) => s + m.tokens, 0);
|
|
6125
5813
|
lines.push(`UNCOMPRESSED \u2014 ${formatTokens2(totalTokens)} | ${visible.length} visible messages`);
|
|
@@ -6128,6 +5816,10 @@ function renderUncompressedRanges(visible, sort, limit) {
|
|
|
6128
5816
|
lines.push(" (no uncompressed messages)");
|
|
6129
5817
|
return lines.join("\n");
|
|
6130
5818
|
}
|
|
5819
|
+
const refNum2 = (ref) => {
|
|
5820
|
+
const m = ref.match(/\d+/);
|
|
5821
|
+
return m ? parseInt(m[0], 10) : 0;
|
|
5822
|
+
};
|
|
6131
5823
|
const dominantTool = (toolTokens) => {
|
|
6132
5824
|
let best = "text";
|
|
6133
5825
|
let bestN = -1;
|
|
@@ -6140,34 +5832,25 @@ function renderUncompressedRanges(visible, sort, limit) {
|
|
|
6140
5832
|
return best;
|
|
6141
5833
|
};
|
|
6142
5834
|
const merged = [];
|
|
6143
|
-
for (const
|
|
6144
|
-
const
|
|
6145
|
-
const
|
|
6146
|
-
|
|
6147
|
-
endRef
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
const m = group[i];
|
|
6155
|
-
r.endRef = m.ref;
|
|
6156
|
-
r.count += 1;
|
|
6157
|
-
r.tokens += m.tokens;
|
|
6158
|
-
r.toolTokens.set(m.tool, (r.toolTokens.get(m.tool) ?? 0) + m.tokens);
|
|
5835
|
+
for (const m of visible) {
|
|
5836
|
+
const num = refNum2(m.ref);
|
|
5837
|
+
const last = merged[merged.length - 1];
|
|
5838
|
+
if (last && num === last.startNum + last.count) {
|
|
5839
|
+
last.endRef = m.ref;
|
|
5840
|
+
last.count += 1;
|
|
5841
|
+
last.tokens += m.tokens;
|
|
5842
|
+
last.toolTokens.set(m.tool, (last.toolTokens.get(m.tool) ?? 0) + m.tokens);
|
|
5843
|
+
} else {
|
|
5844
|
+
const toolTokens = /* @__PURE__ */ new Map([[m.tool, m.tokens]]);
|
|
5845
|
+
merged.push({ startRef: m.ref, endRef: m.ref, startNum: num, count: 1, tokens: m.tokens, toolTokens });
|
|
6159
5846
|
}
|
|
6160
|
-
merged.push(r);
|
|
6161
5847
|
}
|
|
6162
|
-
|
|
6163
|
-
lines.push(`Sorted by ${sort === "time" ? "time" : "size"}`);
|
|
6164
|
-
lines.push("");
|
|
6165
|
-
for (const r of merged.slice(0, limit)) {
|
|
5848
|
+
for (const r of merged.slice(0, 30)) {
|
|
6166
5849
|
const range = r.count === 1 ? r.startRef : `${r.startRef}\u2013${r.endRef}`;
|
|
6167
5850
|
lines.push(` ${range} (${r.count} msgs, ${formatTokens2(r.tokens)}${r.count > 1 ? ` (${Math.round(r.tokens / r.count)}/msg)` : ""}) ${dominantTool(r.toolTokens)}`);
|
|
6168
5851
|
}
|
|
6169
|
-
if (merged.length >
|
|
6170
|
-
lines.push(` ... and ${merged.length -
|
|
5852
|
+
if (merged.length > 30) {
|
|
5853
|
+
lines.push(` ... and ${merged.length - 30} more ranges`);
|
|
6171
5854
|
}
|
|
6172
5855
|
return lines.join("\n");
|
|
6173
5856
|
}
|
|
@@ -7799,11 +7482,7 @@ function build(text) {
|
|
|
7799
7482
|
}
|
|
7800
7483
|
function docFeatures(text) {
|
|
7801
7484
|
const hit = cache.get(text);
|
|
7802
|
-
if (hit)
|
|
7803
|
-
cache.delete(text);
|
|
7804
|
-
cache.set(text, hit);
|
|
7805
|
-
return hit;
|
|
7806
|
-
}
|
|
7485
|
+
if (hit) return hit;
|
|
7807
7486
|
const f = build(text);
|
|
7808
7487
|
if (text.length > 0 && text.length <= capChars) {
|
|
7809
7488
|
while (cachedChars + text.length > capChars && cache.size > 0) {
|
|
@@ -7914,8 +7593,8 @@ var hybridAlgorithm = {
|
|
|
7914
7593
|
score(docs, query) {
|
|
7915
7594
|
const bm = bm25Algorithm.score(docs, query);
|
|
7916
7595
|
const fz = fuzzyAlgorithm.score(docs, query);
|
|
7917
|
-
const maxBm = bm.
|
|
7918
|
-
const maxFz = fz.
|
|
7596
|
+
const maxBm = Math.max(...bm.map((r) => r.score), 1e-9);
|
|
7597
|
+
const maxFz = Math.max(...fz.map((r) => r.score), 1e-9);
|
|
7919
7598
|
const bmMap = new Map(bm.map((r) => [r.ref, r.score / maxBm]));
|
|
7920
7599
|
const fzMap = new Map(fz.map((r) => [r.ref, r.score / maxFz]));
|
|
7921
7600
|
return docs.map((d) => ({
|
|
@@ -8262,7 +7941,6 @@ export {
|
|
|
8262
7941
|
TIER3_CONDENSE_RULES,
|
|
8263
7942
|
VERBOSITY_LEVELS,
|
|
8264
7943
|
VIABLE_RANGE_MIN_TOKENS,
|
|
8265
|
-
activeAncestorIds,
|
|
8266
7944
|
activeBlockSpans,
|
|
8267
7945
|
activeBlocks,
|
|
8268
7946
|
addRule,
|
|
@@ -8280,7 +7958,6 @@ export {
|
|
|
8280
7958
|
applySectionOverrides,
|
|
8281
7959
|
applySteeringToPrompt,
|
|
8282
7960
|
assignRefs,
|
|
8283
|
-
baseIdOf,
|
|
8284
7961
|
blockById,
|
|
8285
7962
|
blockDocs,
|
|
8286
7963
|
blockVisibleInRange,
|
|
@@ -8357,7 +8034,6 @@ export {
|
|
|
8357
8034
|
imageShrinksForRef,
|
|
8358
8035
|
indexToRef,
|
|
8359
8036
|
isAbsorbCandidate,
|
|
8360
|
-
isCovered,
|
|
8361
8037
|
isImageFullRestored,
|
|
8362
8038
|
isMessageLatestProtected,
|
|
8363
8039
|
isMessageProtected,
|
|
@@ -8365,7 +8041,6 @@ export {
|
|
|
8365
8041
|
isRetrievedMessage,
|
|
8366
8042
|
isStoredPlaceholderText,
|
|
8367
8043
|
isSummaryMessageId,
|
|
8368
|
-
isToolMessage,
|
|
8369
8044
|
isValidPackName,
|
|
8370
8045
|
jsonFoldPlugin,
|
|
8371
8046
|
leanPack,
|
|
@@ -8375,7 +8050,6 @@ export {
|
|
|
8375
8050
|
listSearchAlgorithms,
|
|
8376
8051
|
logSelectPlugin,
|
|
8377
8052
|
makeIO,
|
|
8378
|
-
markBlockRestoredInline,
|
|
8379
8053
|
matchSession,
|
|
8380
8054
|
matchToolPattern,
|
|
8381
8055
|
messageDocs,
|
|
@@ -8425,7 +8099,6 @@ export {
|
|
|
8425
8099
|
sanitizePackSurface,
|
|
8426
8100
|
searchBlocks,
|
|
8427
8101
|
searchBlocksAsync,
|
|
8428
|
-
segmentGroups,
|
|
8429
8102
|
setDocCacheCap,
|
|
8430
8103
|
storeCoveredOriginals,
|
|
8431
8104
|
storeLargeResults,
|