acp-kernel 0.0.88 → 0.0.89-pr.177.263
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 +16 -0
- package/dist/boundaries.d.ts +1 -0
- package/dist/boundaries.d.ts.map +1 -1
- package/dist/compress-tools.d.ts +10 -63
- package/dist/compress-tools.d.ts.map +1 -1
- package/dist/compress.d.ts.map +1 -1
- package/dist/hide-consumed.d.ts +4 -0
- package/dist/hide-consumed.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +156 -36
- package/dist/index.js.map +1 -1
- package/dist/message-kind.d.ts +11 -0
- package/dist/message-kind.d.ts.map +1 -0
- package/dist/persist/index.js +43 -4
- package/dist/persist/index.js.map +1 -1
- package/dist/persist/store.d.ts +13 -1
- package/dist/persist/store.d.ts.map +1 -1
- package/dist/protected.d.ts.map +1 -1
- package/dist/prune.d.ts +15 -0
- package/dist/prune.d.ts.map +1 -1
- package/dist/recommend.d.ts +0 -1
- 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 +34 -10
- package/dist/search/doc-cache.d.ts.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/types.d.ts +14 -0
- 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 +8 -2
- package/dist/wire/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -111,33 +111,45 @@ 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
|
+
}
|
|
114
121
|
function isRenderedSummaryMessage(message) {
|
|
115
122
|
return isSummaryMessageId(message.id) && message.role === "system" && message.contentType === "text";
|
|
116
123
|
}
|
|
117
124
|
function prune(messages, state, options = {}) {
|
|
118
125
|
const covered = coveredMessageIds(state);
|
|
119
126
|
if (covered.size === 0) return [...messages];
|
|
127
|
+
const coveredBases = /* @__PURE__ */ new Set();
|
|
128
|
+
for (const id of covered) coveredBases.add(baseIdOf(id));
|
|
120
129
|
const inject = options.injectSummaries ?? true;
|
|
121
130
|
const firstUserIndex = messages.findIndex(
|
|
122
131
|
(message) => message.role === "user"
|
|
123
132
|
);
|
|
124
|
-
const
|
|
133
|
+
const baseIndexById = /* @__PURE__ */ new Map();
|
|
125
134
|
const summaryIndexById = /* @__PURE__ */ new Map();
|
|
126
135
|
messages.forEach((message, index) => {
|
|
127
|
-
|
|
136
|
+
const base = baseIdOf(message.id);
|
|
137
|
+
const existing = baseIndexById.get(base);
|
|
138
|
+
if (existing === void 0 || index < existing)
|
|
139
|
+
baseIndexById.set(base, index);
|
|
128
140
|
if (isRenderedSummaryMessage(message))
|
|
129
141
|
summaryIndexById.set(message.id, index);
|
|
130
142
|
});
|
|
131
|
-
const anchors = inject ? collectSummaryAnchors(state,
|
|
143
|
+
const anchors = inject ? collectSummaryAnchors(state, baseIndexById, summaryIndexById) : [];
|
|
132
144
|
return stripOrphanedReasoning(
|
|
133
145
|
stripOrphanedToolResults(
|
|
134
146
|
stripOrphanedToolCalls(
|
|
135
|
-
rebuildMessages(messages,
|
|
147
|
+
rebuildMessages(messages, coveredBases, firstUserIndex, anchors)
|
|
136
148
|
)
|
|
137
149
|
)
|
|
138
150
|
);
|
|
139
151
|
}
|
|
140
|
-
function collectSummaryAnchors(state,
|
|
152
|
+
function collectSummaryAnchors(state, baseIndexById, summaryIndexById) {
|
|
141
153
|
const anchors = [];
|
|
142
154
|
for (const block of activeBlocks(state)) {
|
|
143
155
|
const existingIndex = summaryIndexById.get(summaryMessageId(block.blockId));
|
|
@@ -152,7 +164,7 @@ function collectSummaryAnchors(state, indexById, summaryIndexById) {
|
|
|
152
164
|
}
|
|
153
165
|
let earliest = null;
|
|
154
166
|
for (const id of block.effectiveMessageIds) {
|
|
155
|
-
const index =
|
|
167
|
+
const index = baseIndexById.get(baseIdOf(id));
|
|
156
168
|
if (index !== void 0 && (earliest === null || index < earliest)) {
|
|
157
169
|
earliest = index;
|
|
158
170
|
}
|
|
@@ -197,7 +209,7 @@ function pairSafeAnchorIndex(messages, index) {
|
|
|
197
209
|
}
|
|
198
210
|
return safe;
|
|
199
211
|
}
|
|
200
|
-
function rebuildMessages(messages,
|
|
212
|
+
function rebuildMessages(messages, coveredBases, firstUserIndex, anchors) {
|
|
201
213
|
const safeAnchors = anchors.map((anchor) => ({
|
|
202
214
|
...anchor,
|
|
203
215
|
insertAt: pairSafeAnchorIndex(messages, anchor.insertAt)
|
|
@@ -215,7 +227,7 @@ function rebuildMessages(messages, covered, firstUserIndex, anchors) {
|
|
|
215
227
|
result.push(messages[index]);
|
|
216
228
|
continue;
|
|
217
229
|
}
|
|
218
|
-
if (
|
|
230
|
+
if (isCovered(messages[index].id, coveredBases)) continue;
|
|
219
231
|
if (isRenderedSummaryMessage(messages[index]) && anchoredSummaryIds.has(messages[index].id))
|
|
220
232
|
continue;
|
|
221
233
|
result.push(messages[index]);
|
|
@@ -281,6 +293,8 @@ function stripOrphanedReasoning(messages) {
|
|
|
281
293
|
// src/sync.ts
|
|
282
294
|
function syncBlocks(messages, state) {
|
|
283
295
|
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));
|
|
284
298
|
const deactivated = [];
|
|
285
299
|
const result = {
|
|
286
300
|
blocks: state.blocks.map((block) => ({
|
|
@@ -330,7 +344,7 @@ function syncBlocks(messages, state) {
|
|
|
330
344
|
continue;
|
|
331
345
|
}
|
|
332
346
|
block.active = true;
|
|
333
|
-
const stillPresent = block.effectiveMessageIds.some((id) =>
|
|
347
|
+
const stillPresent = block.effectiveMessageIds.some((id) => presentBases.has(baseIdOf(id))) || presentIds.has(summaryMessageId(block.blockId));
|
|
334
348
|
if (!stillPresent) {
|
|
335
349
|
block.active = false;
|
|
336
350
|
deactivated.push(block.blockId);
|
|
@@ -658,14 +672,7 @@ var COMPRESS_PARAMETERS = {
|
|
|
658
672
|
type: "string",
|
|
659
673
|
description: "Flat single-range form (no content): self-contained summary replacing the range"
|
|
660
674
|
}
|
|
661
|
-
}
|
|
662
|
-
anyOf: [
|
|
663
|
-
{ required: ["content"] },
|
|
664
|
-
{
|
|
665
|
-
required: ["summary"],
|
|
666
|
-
anyOf: [{ required: ["startId", "endId"] }, { required: ["startRef", "endRef"] }]
|
|
667
|
-
}
|
|
668
|
-
]
|
|
675
|
+
}
|
|
669
676
|
};
|
|
670
677
|
var COMPRESS_TOOL = {
|
|
671
678
|
name: COMPRESS_TOOL_NAME,
|
|
@@ -1255,7 +1262,12 @@ function hasMediaPayload(msg) {
|
|
|
1255
1262
|
if (m.rawOpenaiContent != null) return true;
|
|
1256
1263
|
if (Array.isArray(m.rawOpenaiContentParts) && m.rawOpenaiContentParts.length > 0)
|
|
1257
1264
|
return true;
|
|
1258
|
-
|
|
1265
|
+
const ab = m.rawAnthropicBlock;
|
|
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
|
+
}
|
|
1259
1271
|
const item = m.rawResponsesItem;
|
|
1260
1272
|
if (isObjWith(item, "type", "input_image")) return true;
|
|
1261
1273
|
if (item && typeof item === "object") {
|
|
@@ -1619,8 +1631,10 @@ function resolveBoundaries(input) {
|
|
|
1619
1631
|
if (endAnchor.snapped) snappedBoundaries.push(endAnchor.snapped);
|
|
1620
1632
|
let startIndex = startAnchor.index;
|
|
1621
1633
|
let endIndex = endAnchor.index;
|
|
1634
|
+
let reversedNote;
|
|
1622
1635
|
if (startIndex > endIndex) {
|
|
1623
1636
|
[startIndex, endIndex] = [endIndex, startIndex];
|
|
1637
|
+
reversedNote = `note: refs were given reversed (${start.raw}\u2192${end.raw}), normalized to ${end.raw}..${start.raw}`;
|
|
1624
1638
|
}
|
|
1625
1639
|
const messageIds = [];
|
|
1626
1640
|
for (let index = startIndex; index <= endIndex; index++) {
|
|
@@ -1647,7 +1661,8 @@ function resolveBoundaries(input) {
|
|
|
1647
1661
|
nestedBlockIds,
|
|
1648
1662
|
boundaryKind,
|
|
1649
1663
|
protectedGaps,
|
|
1650
|
-
snappedBoundaries
|
|
1664
|
+
snappedBoundaries,
|
|
1665
|
+
reversedNote
|
|
1651
1666
|
};
|
|
1652
1667
|
}
|
|
1653
1668
|
function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
|
|
@@ -1672,6 +1687,27 @@ function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
|
|
|
1672
1687
|
snapped: `${label}="${boundary.raw}" refers to a message already compressed into an active block \u2014 anchored to the active block covering it instead.`
|
|
1673
1688
|
};
|
|
1674
1689
|
}
|
|
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
|
+
}
|
|
1675
1711
|
throw new BoundaryNotFoundError(
|
|
1676
1712
|
"consumed",
|
|
1677
1713
|
endpoint,
|
|
@@ -1748,6 +1784,26 @@ function inheritedContentIds(state, block) {
|
|
|
1748
1784
|
}
|
|
1749
1785
|
return ids;
|
|
1750
1786
|
}
|
|
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
|
+
}
|
|
1751
1807
|
function formatPaddedRef(index) {
|
|
1752
1808
|
return `m${String(index).padStart(5, "0")}`;
|
|
1753
1809
|
}
|
|
@@ -1962,14 +2018,26 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
1962
2018
|
}
|
|
1963
2019
|
}
|
|
1964
2020
|
let hidden = 0;
|
|
2021
|
+
const hiddenOrphanRefs = [];
|
|
2022
|
+
const rememberHiddenRef = (message) => {
|
|
2023
|
+
if (message.toolCallId && allBlockCallIds.has(message.toolCallId)) {
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
2026
|
+
const ref = state.messageRefs.byRaw[message.id];
|
|
2027
|
+
if (ref && ref !== BLOCKED_REF && !hiddenOrphanRefs.includes(ref)) {
|
|
2028
|
+
hiddenOrphanRefs.push(ref);
|
|
2029
|
+
}
|
|
2030
|
+
};
|
|
1965
2031
|
const result = [];
|
|
1966
2032
|
for (const message of messages) {
|
|
1967
2033
|
if (message.toolName === "compress" && message.contentType === "tool-call" && (!message.toolCallId || !keepCallIds.has(message.toolCallId))) {
|
|
1968
2034
|
hidden++;
|
|
2035
|
+
rememberHiddenRef(message);
|
|
1969
2036
|
continue;
|
|
1970
2037
|
}
|
|
1971
2038
|
if (message.contentType === "tool-result" && message.toolCallId && hiddenCallIds.has(message.toolCallId)) {
|
|
1972
2039
|
hidden++;
|
|
2040
|
+
rememberHiddenRef(message);
|
|
1973
2041
|
continue;
|
|
1974
2042
|
}
|
|
1975
2043
|
if (message.toolName === "compress" && message.contentType === "tool-call" && message.toolCallId && keepCallIds.has(message.toolCallId)) {
|
|
@@ -1989,7 +2057,7 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
1989
2057
|
}
|
|
1990
2058
|
result.push(message);
|
|
1991
2059
|
}
|
|
1992
|
-
return { messages: result, hidden };
|
|
2060
|
+
return { messages: result, hidden, hiddenOrphanRefs };
|
|
1993
2061
|
}
|
|
1994
2062
|
|
|
1995
2063
|
// src/absorb.ts
|
|
@@ -3747,6 +3815,11 @@ function createRenderRefsNode(strategy) {
|
|
|
3747
3815
|
}
|
|
3748
3816
|
var renderRefsNode = createRenderRefsNode("all");
|
|
3749
3817
|
|
|
3818
|
+
// src/message-kind.ts
|
|
3819
|
+
function isToolMessage(message) {
|
|
3820
|
+
return message.contentType === "tool-call" || message.contentType === "tool-result";
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3750
3823
|
// src/tool-pairs.ts
|
|
3751
3824
|
function adjustBoundariesForToolPairs(startIndex, endIndex, messages, maxScan = 20) {
|
|
3752
3825
|
const callIdsInRange = /* @__PURE__ */ new Set();
|
|
@@ -3951,9 +4024,6 @@ function computeIntegrityWithdrawals(messages, foldedIds) {
|
|
|
3951
4024
|
function estimateTextTokens(text) {
|
|
3952
4025
|
return Math.ceil(text.length / 4);
|
|
3953
4026
|
}
|
|
3954
|
-
function isToolMessage(message) {
|
|
3955
|
-
return message.contentType === "tool-call" || message.contentType === "tool-result";
|
|
3956
|
-
}
|
|
3957
4027
|
function isSyntheticOrPruned(message, state) {
|
|
3958
4028
|
if (message.text?.startsWith("[Compressed conversation section]")) return true;
|
|
3959
4029
|
for (const block of state.blocks) {
|
|
@@ -4282,6 +4352,7 @@ function createCore(ports = {}) {
|
|
|
4282
4352
|
let tokensCompressed = 0;
|
|
4283
4353
|
const errors = [];
|
|
4284
4354
|
const warnings = [];
|
|
4355
|
+
const notes = [];
|
|
4285
4356
|
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(
|
|
4286
4357
|
input.messages,
|
|
4287
4358
|
input.state,
|
|
@@ -4382,7 +4453,28 @@ function createCore(ports = {}) {
|
|
|
4382
4453
|
const danglingRefs = consumedRanges.flatMap(
|
|
4383
4454
|
(spec) => danglingMessageRefs(state, input.messages, spec)
|
|
4384
4455
|
);
|
|
4385
|
-
|
|
4456
|
+
let 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)}` : countedRanges > 0 ? `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.` : null;
|
|
4457
|
+
if (gateMessage === null) {
|
|
4458
|
+
return {
|
|
4459
|
+
state: input.state,
|
|
4460
|
+
result: {
|
|
4461
|
+
blocksCreated: 0,
|
|
4462
|
+
tokensCompressed: 0,
|
|
4463
|
+
errors: [...classificationErrors],
|
|
4464
|
+
warnings: []
|
|
4465
|
+
}
|
|
4466
|
+
};
|
|
4467
|
+
}
|
|
4468
|
+
const reversalNotes = [];
|
|
4469
|
+
for (const [spec, resolution] of classifications) {
|
|
4470
|
+
if (resolution.status === "ok" && !skipSpecs.has(spec)) {
|
|
4471
|
+
const note = resolution.resolved.reversedNote;
|
|
4472
|
+
if (note) reversalNotes.push(note);
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
if (reversalNotes.length > 0) {
|
|
4476
|
+
gateMessage += ` ${reversalNotes.join(" ")}`;
|
|
4477
|
+
}
|
|
4386
4478
|
return {
|
|
4387
4479
|
state: input.state,
|
|
4388
4480
|
result: {
|
|
@@ -4409,6 +4501,8 @@ function createCore(ports = {}) {
|
|
|
4409
4501
|
continue;
|
|
4410
4502
|
}
|
|
4411
4503
|
warnings.push(...resolution.resolved.snappedBoundaries);
|
|
4504
|
+
const note = resolution.resolved.reversedNote;
|
|
4505
|
+
if (note) notes.push(note);
|
|
4412
4506
|
try {
|
|
4413
4507
|
const outcome = applySingleRange({
|
|
4414
4508
|
spec,
|
|
@@ -4442,7 +4536,13 @@ function createCore(ports = {}) {
|
|
|
4442
4536
|
}
|
|
4443
4537
|
return {
|
|
4444
4538
|
state,
|
|
4445
|
-
result: {
|
|
4539
|
+
result: {
|
|
4540
|
+
blocksCreated,
|
|
4541
|
+
tokensCompressed,
|
|
4542
|
+
errors,
|
|
4543
|
+
warnings,
|
|
4544
|
+
...notes.length > 0 ? { notes } : {}
|
|
4545
|
+
}
|
|
4446
4546
|
};
|
|
4447
4547
|
}
|
|
4448
4548
|
function processTurn(input) {
|
|
@@ -4626,7 +4726,11 @@ var hideCompressCallsNode = {
|
|
|
4626
4726
|
name: "hide-compress-calls",
|
|
4627
4727
|
run(io) {
|
|
4628
4728
|
const hidden = hideConsumedCompressCalls(io.state, io.messages);
|
|
4629
|
-
return {
|
|
4729
|
+
return {
|
|
4730
|
+
...io,
|
|
4731
|
+
messages: hidden.messages,
|
|
4732
|
+
state: { ...io.state, hiddenOrphanRefs: hidden.hiddenOrphanRefs }
|
|
4733
|
+
};
|
|
4630
4734
|
}
|
|
4631
4735
|
};
|
|
4632
4736
|
var recommendNode = {
|
|
@@ -5226,7 +5330,7 @@ function computeContextBreakdown(messages, total, growth, countTokens) {
|
|
|
5226
5330
|
const tokens = countMessageTokens(msg, count);
|
|
5227
5331
|
if (msg.text?.startsWith("[Compressed conversation section]")) {
|
|
5228
5332
|
summaries += tokens;
|
|
5229
|
-
} else if (msg
|
|
5333
|
+
} else if (isToolMessage(msg)) {
|
|
5230
5334
|
tool += tokens;
|
|
5231
5335
|
} else if (msg.role === "system") {
|
|
5232
5336
|
system += tokens;
|
|
@@ -5258,7 +5362,8 @@ function cloneState(state) {
|
|
|
5258
5362
|
nextRuleId: state.nextRuleId,
|
|
5259
5363
|
terminalStreak: state.terminalStreak,
|
|
5260
5364
|
nextBlockId: state.nextBlockId,
|
|
5261
|
-
nextRunId: state.nextRunId
|
|
5365
|
+
nextRunId: state.nextRunId,
|
|
5366
|
+
hiddenOrphanRefs: state.hiddenOrphanRefs ? [...state.hiddenOrphanRefs] : void 0
|
|
5262
5367
|
};
|
|
5263
5368
|
}
|
|
5264
5369
|
function scoreRelevance(block, terms) {
|
|
@@ -5693,14 +5798,16 @@ function tierLabel(block) {
|
|
|
5693
5798
|
}
|
|
5694
5799
|
function tierBreakdown(blocks, countTokens) {
|
|
5695
5800
|
const tierTokens = {};
|
|
5801
|
+
const tierCounts = {};
|
|
5696
5802
|
for (const block of blocks) {
|
|
5697
5803
|
tierTokens[block.tier] = (tierTokens[block.tier] ?? 0) + summaryTokensOf(block, countTokens);
|
|
5804
|
+
tierCounts[block.tier] = (tierCounts[block.tier] ?? 0) + 1;
|
|
5698
5805
|
}
|
|
5699
5806
|
const tiers = Object.keys(tierTokens).map(Number);
|
|
5700
5807
|
if (tiers.length <= 1) return null;
|
|
5701
5808
|
const parts = [];
|
|
5702
5809
|
for (const tier of [1, 2, 3]) {
|
|
5703
|
-
if (tierTokens[tier]) parts.push(`T${tier}: ${formatTokens2(tierTokens[tier])}`);
|
|
5810
|
+
if (tierTokens[tier]) parts.push(`T${tier}: ${formatTokens2(tierTokens[tier])} (${tierCounts[tier]} blocks)`);
|
|
5704
5811
|
}
|
|
5705
5812
|
return parts.join(" | ");
|
|
5706
5813
|
}
|
|
@@ -5726,8 +5833,9 @@ function collectVisible(messages, state, countTokens) {
|
|
|
5726
5833
|
const ref = refForRaw(state.messageRefs, message.id);
|
|
5727
5834
|
if (!ref) return;
|
|
5728
5835
|
const tokens = countMessageTokens(message, countTokens);
|
|
5729
|
-
const
|
|
5730
|
-
|
|
5836
|
+
const isTool = isToolMessage(message);
|
|
5837
|
+
const tool = isTool ? message.toolName ?? (message.toolCallId ? toolCallNames.get(message.toolCallId) : void 0) ?? "tool" : "text";
|
|
5838
|
+
if (tokens > 0) visible.push({ ref, tokens, tool, isTool, index });
|
|
5731
5839
|
});
|
|
5732
5840
|
return { visible, summaryTokens };
|
|
5733
5841
|
}
|
|
@@ -5770,8 +5878,8 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
5770
5878
|
toolTypeMap.set(message.tool, (toolTypeMap.get(message.tool) ?? 0) + message.tokens);
|
|
5771
5879
|
}
|
|
5772
5880
|
const topTool = [...toolTypeMap.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
5773
|
-
const totalTool = visible.filter((m) => m.
|
|
5774
|
-
const totalText = visible.filter((m) => m.
|
|
5881
|
+
const totalTool = visible.filter((m) => m.isTool).reduce((sum, m) => sum + m.tokens, 0);
|
|
5882
|
+
const totalText = visible.filter((m) => !m.isTool).reduce((sum, m) => sum + m.tokens, 0);
|
|
5775
5883
|
const total = summaryTokens + totalTool + totalText;
|
|
5776
5884
|
lines.push("CONTEXT BREAKDOWN");
|
|
5777
5885
|
lines.push(
|
|
@@ -5807,6 +5915,11 @@ function renderOverview(visible, summaryTokens, blocks, state, countTokens, limi
|
|
|
5807
5915
|
` ${block.blockId} (${tierLabel(block)}) ${formatTokens2(eff)}\u2192${formatTokens2(summaryTokensOf(block, countTokens))} ${block.effectiveMessageIds.length} msgs "${topic}"`
|
|
5808
5916
|
);
|
|
5809
5917
|
}
|
|
5918
|
+
if (blocks.length > limit) {
|
|
5919
|
+
lines.push(
|
|
5920
|
+
` ... and ${blocks.length - limit} more blocks not shown (scope:"compressed", limit:${blocks.length} for full list)`
|
|
5921
|
+
);
|
|
5922
|
+
}
|
|
5810
5923
|
}
|
|
5811
5924
|
lines.push("");
|
|
5812
5925
|
lines.push(
|
|
@@ -7489,7 +7602,11 @@ function build(text) {
|
|
|
7489
7602
|
}
|
|
7490
7603
|
function docFeatures(text) {
|
|
7491
7604
|
const hit = cache.get(text);
|
|
7492
|
-
if (hit)
|
|
7605
|
+
if (hit) {
|
|
7606
|
+
cache.delete(text);
|
|
7607
|
+
cache.set(text, hit);
|
|
7608
|
+
return hit;
|
|
7609
|
+
}
|
|
7493
7610
|
const f = build(text);
|
|
7494
7611
|
if (text.length > 0 && text.length <= capChars) {
|
|
7495
7612
|
while (cachedChars + text.length > capChars && cache.size > 0) {
|
|
@@ -7600,8 +7717,8 @@ var hybridAlgorithm = {
|
|
|
7600
7717
|
score(docs, query) {
|
|
7601
7718
|
const bm = bm25Algorithm.score(docs, query);
|
|
7602
7719
|
const fz = fuzzyAlgorithm.score(docs, query);
|
|
7603
|
-
const maxBm =
|
|
7604
|
-
const maxFz =
|
|
7720
|
+
const maxBm = bm.reduce((m, r) => r.score > m ? r.score : m, 1e-9);
|
|
7721
|
+
const maxFz = fz.reduce((m, r) => r.score > m ? r.score : m, 1e-9);
|
|
7605
7722
|
const bmMap = new Map(bm.map((r) => [r.ref, r.score / maxBm]));
|
|
7606
7723
|
const fzMap = new Map(fz.map((r) => [r.ref, r.score / maxFz]));
|
|
7607
7724
|
return docs.map((d) => ({
|
|
@@ -7965,6 +8082,7 @@ export {
|
|
|
7965
8082
|
applySectionOverrides,
|
|
7966
8083
|
applySteeringToPrompt,
|
|
7967
8084
|
assignRefs,
|
|
8085
|
+
baseIdOf,
|
|
7968
8086
|
blockById,
|
|
7969
8087
|
blockDocs,
|
|
7970
8088
|
blockVisibleInRange,
|
|
@@ -8041,6 +8159,7 @@ export {
|
|
|
8041
8159
|
imageShrinksForRef,
|
|
8042
8160
|
indexToRef,
|
|
8043
8161
|
isAbsorbCandidate,
|
|
8162
|
+
isCovered,
|
|
8044
8163
|
isImageFullRestored,
|
|
8045
8164
|
isMessageLatestProtected,
|
|
8046
8165
|
isMessageProtected,
|
|
@@ -8048,6 +8167,7 @@ export {
|
|
|
8048
8167
|
isRetrievedMessage,
|
|
8049
8168
|
isStoredPlaceholderText,
|
|
8050
8169
|
isSummaryMessageId,
|
|
8170
|
+
isToolMessage,
|
|
8051
8171
|
isValidPackName,
|
|
8052
8172
|
jsonFoldPlugin,
|
|
8053
8173
|
leanPack,
|