acp-kernel 0.0.7 → 0.0.8
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/dist/compress.d.ts.map +1 -1
- package/dist/index.js +95 -50
- package/dist/index.js.map +1 -1
- package/dist/nudge-text.d.ts.map +1 -1
- package/dist/protected.d.ts +14 -0
- package/dist/protected.d.ts.map +1 -1
- package/dist/recommend.d.ts.map +1 -1
- package/dist/tokenize.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/compress.d.ts.map
CHANGED
|
@@ -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,
|
|
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,CAgN7D;AA8lBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -269,9 +269,9 @@ import { createRequire } from "module";
|
|
|
269
269
|
var require2 = createRequire(import.meta.url);
|
|
270
270
|
function defaultCountTokens(text) {
|
|
271
271
|
if (!text) return 0;
|
|
272
|
-
const ascii = text.match(/[a-zA-Z][a-zA-Z0-9_'-]*/g);
|
|
273
272
|
const cjk = text.match(/[\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]/g);
|
|
274
|
-
|
|
273
|
+
const cjkCount = cjk?.length ?? 0;
|
|
274
|
+
return cjkCount + Math.ceil((text.length - cjkCount) / 4);
|
|
275
275
|
}
|
|
276
276
|
function estimateTokensFast(text) {
|
|
277
277
|
if (!text) return 0;
|
|
@@ -704,6 +704,7 @@ var renderRefsNode = {
|
|
|
704
704
|
};
|
|
705
705
|
|
|
706
706
|
// src/protected.ts
|
|
707
|
+
var ALWAYS_PROTECTED_TOOLS = ["compress"];
|
|
707
708
|
function matchToolPattern(toolName, pattern) {
|
|
708
709
|
if (pattern.endsWith("*")) {
|
|
709
710
|
return toolName.startsWith(pattern.slice(0, -1));
|
|
@@ -711,13 +712,34 @@ function matchToolPattern(toolName, pattern) {
|
|
|
711
712
|
return toolName === pattern;
|
|
712
713
|
}
|
|
713
714
|
function isMessageProtected(msg, config) {
|
|
714
|
-
if (msg.contentType !== "tool-call" || !msg.toolName)
|
|
715
|
+
if (msg.contentType !== "tool-call" && msg.contentType !== "tool-result" || !msg.toolName) {
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
if (ALWAYS_PROTECTED_TOOLS.includes(msg.toolName)) {
|
|
719
|
+
return true;
|
|
720
|
+
}
|
|
715
721
|
for (const pattern of config.protectedTools) {
|
|
716
722
|
if (matchToolPattern(msg.toolName, pattern)) return true;
|
|
717
723
|
}
|
|
718
724
|
if (config.isToolProtected?.(msg.toolName, msg.text)) return true;
|
|
719
725
|
return false;
|
|
720
726
|
}
|
|
727
|
+
function collectProtectedToolCallIds(messages, config) {
|
|
728
|
+
const ids = /* @__PURE__ */ new Set();
|
|
729
|
+
for (const m of messages) {
|
|
730
|
+
if (m.contentType === "tool-call" && m.toolCallId && isMessageProtected(m, config)) {
|
|
731
|
+
ids.add(m.toolCallId);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return ids;
|
|
735
|
+
}
|
|
736
|
+
function isMessageProtectedWithPairing(msg, config, protectedCallIds) {
|
|
737
|
+
if (isMessageProtected(msg, config)) return true;
|
|
738
|
+
if (msg.contentType === "tool-result" && msg.toolCallId && protectedCallIds.has(msg.toolCallId)) {
|
|
739
|
+
return true;
|
|
740
|
+
}
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
721
743
|
|
|
722
744
|
// src/tool-pairs.ts
|
|
723
745
|
function adjustBoundariesForToolPairs(startIndex, endIndex, messages, maxScan = 20) {
|
|
@@ -795,24 +817,27 @@ function computeProtectedRefs(messages, state, config) {
|
|
|
795
817
|
tokenAccum += visible[i].tokens;
|
|
796
818
|
}
|
|
797
819
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
820
|
+
if (preserveN > 0) {
|
|
821
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
822
|
+
const msg = messages[i];
|
|
823
|
+
if (msg.role !== "user" || isSyntheticOrPruned(msg, state)) continue;
|
|
824
|
+
const ref = state.messageRefs.byRaw[msg.id];
|
|
825
|
+
if (ref && ref !== "BLOCKED") result.add(ref);
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
804
828
|
}
|
|
805
829
|
return result;
|
|
806
830
|
}
|
|
807
831
|
function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
|
|
808
832
|
const compressibleMsgs = [];
|
|
809
833
|
const protectedMsgs = [];
|
|
834
|
+
const protectedCallIds = collectProtectedToolCallIds(messages, config);
|
|
810
835
|
for (const msg of messages) {
|
|
811
836
|
if (isSyntheticOrPruned(msg, state)) continue;
|
|
812
837
|
const ref = state.messageRefs.byRaw[msg.id];
|
|
813
838
|
if (!ref || ref === "BLOCKED") continue;
|
|
814
839
|
const rn = refNum(ref);
|
|
815
|
-
if (
|
|
840
|
+
if (isMessageProtectedWithPairing(msg, config, protectedCallIds)) {
|
|
816
841
|
protectedMsgs.push({
|
|
817
842
|
ref,
|
|
818
843
|
refNum: rn,
|
|
@@ -828,7 +853,8 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
|
|
|
828
853
|
ref,
|
|
829
854
|
refNum: rn,
|
|
830
855
|
tokens: estimateMessageTokens(msg),
|
|
831
|
-
isTool: isToolMessage(msg)
|
|
856
|
+
isTool: isToolMessage(msg),
|
|
857
|
+
isUser: msg.role === "user"
|
|
832
858
|
});
|
|
833
859
|
}
|
|
834
860
|
const compressible = [];
|
|
@@ -836,7 +862,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
|
|
|
836
862
|
let prevRefNum = -2;
|
|
837
863
|
for (const info of compressibleMsgs) {
|
|
838
864
|
const hasGap = info.refNum > prevRefNum + 1;
|
|
839
|
-
if (cur && hasGap) {
|
|
865
|
+
if (cur && (info.isUser && cur.count >= 3 || hasGap)) {
|
|
840
866
|
compressible.push(cur);
|
|
841
867
|
cur = null;
|
|
842
868
|
}
|
|
@@ -919,6 +945,7 @@ function createCore(ports = {}) {
|
|
|
919
945
|
let blocksCreated = 0;
|
|
920
946
|
let tokensCompressed = 0;
|
|
921
947
|
const errors = [];
|
|
948
|
+
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config);
|
|
922
949
|
const preExistingCoverage = collectCoverage(state);
|
|
923
950
|
const rangeIndexSets = [];
|
|
924
951
|
for (const spec of input.ranges) {
|
|
@@ -1006,7 +1033,7 @@ function createCore(ports = {}) {
|
|
|
1006
1033
|
state,
|
|
1007
1034
|
runId,
|
|
1008
1035
|
config: input.config,
|
|
1009
|
-
protectedMessageIds
|
|
1036
|
+
protectedMessageIds,
|
|
1010
1037
|
countTokens,
|
|
1011
1038
|
preExistingCoverage
|
|
1012
1039
|
});
|
|
@@ -1248,11 +1275,25 @@ function applySingleRange(input) {
|
|
|
1248
1275
|
const directMessageIds = [...effectiveMessageIds].filter(
|
|
1249
1276
|
(id) => !input.preExistingCoverage.has(id)
|
|
1250
1277
|
);
|
|
1251
|
-
const
|
|
1278
|
+
const filteredIds = filterProtectedToolMessages(
|
|
1252
1279
|
directMessageIds,
|
|
1253
1280
|
input.messages,
|
|
1254
1281
|
input.config
|
|
1255
1282
|
);
|
|
1283
|
+
const protectedRefs = input.protectedMessageIds;
|
|
1284
|
+
const hitProtectedRaw = protectedRefs ? filteredIds.filter((id) => {
|
|
1285
|
+
const ref = input.state.messageRefs.byRaw[id];
|
|
1286
|
+
return ref !== void 0 && protectedRefs.has(ref);
|
|
1287
|
+
}) : [];
|
|
1288
|
+
if (hitProtectedRaw.length > 0) {
|
|
1289
|
+
const recentN = input.config.preserveRecentMessages;
|
|
1290
|
+
const hitRefs = hitProtectedRaw.map((id) => input.state.messageRefs.byRaw[id]).filter(Boolean);
|
|
1291
|
+
throw new Error(
|
|
1292
|
+
`Range includes protected messages (the last ${recentN} messages and/or the most recent user message) which must not be compressed: ${hitRefs.join(
|
|
1293
|
+
", "
|
|
1294
|
+
)}. Adjust startId/endId to exclude them.`
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1256
1297
|
validateCompressionRange(input, filteredIds, consumedBlockIds.length);
|
|
1257
1298
|
let compressedTokens = 0;
|
|
1258
1299
|
for (const id of filteredIds) {
|
|
@@ -1266,22 +1307,12 @@ function applySingleRange(input) {
|
|
|
1266
1307
|
}
|
|
1267
1308
|
}
|
|
1268
1309
|
const blockId = allocateBlockId(input.state);
|
|
1269
|
-
const finalSummary = appendedProtectedText.length > 0 ? `${input.spec.summary}
|
|
1270
|
-
|
|
1271
|
-
The following protected tool calls were used in this conversation as well:
|
|
1272
|
-
${appendedProtectedText.join("")}` : input.spec.summary;
|
|
1273
|
-
const maxLen = input.spec.summaryMaxChars ?? input.config.compress.maxSummaryLength;
|
|
1274
|
-
if (maxLen > 0 && finalSummary.length > maxLen) {
|
|
1275
|
-
throw new Error(
|
|
1276
|
-
`Summary too long after appending protected content (${finalSummary.length} chars, max ${maxLen}). Reduce the summary or remove protected tools from the range.`
|
|
1277
|
-
);
|
|
1278
|
-
}
|
|
1279
1310
|
const block = {
|
|
1280
1311
|
blockId,
|
|
1281
1312
|
runId: input.runId,
|
|
1282
1313
|
tier: outputTier,
|
|
1283
1314
|
topic: input.spec.topic,
|
|
1284
|
-
summary:
|
|
1315
|
+
summary: input.spec.summary,
|
|
1285
1316
|
directMessageIds: filteredIds,
|
|
1286
1317
|
effectiveMessageIds: [...effectiveMessageIds],
|
|
1287
1318
|
directBlockIds: [...consumedBlockIds],
|
|
@@ -1344,41 +1375,30 @@ function validateCompressionRange(input, directMessageIds, consumedBlockCount) {
|
|
|
1344
1375
|
}
|
|
1345
1376
|
}
|
|
1346
1377
|
function filterProtectedToolMessages(directMessageIds, messages, config) {
|
|
1347
|
-
const
|
|
1348
|
-
const allProtectedCallIds = /* @__PURE__ */ new Set();
|
|
1378
|
+
const protectedCallIds = /* @__PURE__ */ new Set();
|
|
1349
1379
|
const removedIds = /* @__PURE__ */ new Set();
|
|
1350
|
-
const appendedProtectedText = [];
|
|
1351
1380
|
for (const msg of messages) {
|
|
1352
1381
|
if (isMessageProtected(msg, config) && msg.toolCallId) {
|
|
1353
|
-
|
|
1382
|
+
protectedCallIds.add(msg.toolCallId);
|
|
1354
1383
|
}
|
|
1355
1384
|
}
|
|
1356
1385
|
for (const id of directMessageIds) {
|
|
1357
1386
|
const msg = messages.find((m) => m.id === id);
|
|
1358
1387
|
if (!msg) continue;
|
|
1359
|
-
if (
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
if (msg.text) {
|
|
1363
|
-
appendedProtectedText.push(
|
|
1364
|
-
`
|
|
1365
|
-
### Protected: ${msg.toolName ?? "tool"}
|
|
1366
|
-
${msg.text}`
|
|
1367
|
-
);
|
|
1388
|
+
if (isMessageProtected(msg, config)) {
|
|
1389
|
+
removedIds.add(id);
|
|
1390
|
+
if (msg.toolCallId) protectedCallIds.add(msg.toolCallId);
|
|
1368
1391
|
}
|
|
1369
1392
|
}
|
|
1370
1393
|
for (const id of directMessageIds) {
|
|
1371
1394
|
if (removedIds.has(id)) continue;
|
|
1372
1395
|
const msg = messages.find((m) => m.id === id);
|
|
1373
1396
|
if (!msg) continue;
|
|
1374
|
-
if (msg.contentType === "tool-result" && msg.toolCallId &&
|
|
1397
|
+
if (msg.contentType === "tool-result" && msg.toolCallId && protectedCallIds.has(msg.toolCallId)) {
|
|
1375
1398
|
removedIds.add(id);
|
|
1376
1399
|
}
|
|
1377
1400
|
}
|
|
1378
|
-
return
|
|
1379
|
-
filteredIds: directMessageIds.filter((id) => !removedIds.has(id)),
|
|
1380
|
-
appendedProtectedText
|
|
1381
|
-
};
|
|
1401
|
+
return directMessageIds.filter((id) => !removedIds.has(id));
|
|
1382
1402
|
}
|
|
1383
1403
|
function resolveTargetTier(state, nestedBlockIds, isBlockBoundary) {
|
|
1384
1404
|
if (!isBlockBoundary) return 1;
|
|
@@ -1429,23 +1449,30 @@ function decideNudge(input) {
|
|
|
1429
1449
|
shouldContextNudge = growthSinceReference >= growthFloor;
|
|
1430
1450
|
}
|
|
1431
1451
|
let tier = null;
|
|
1452
|
+
let tierTargetBlocks = [];
|
|
1432
1453
|
if (config.tiers.enabled) {
|
|
1433
1454
|
const active = activeBlocks(state);
|
|
1434
1455
|
const activeT1 = active.filter((b) => b.tier === 1);
|
|
1435
1456
|
const activeT2 = active.filter((b) => b.tier === 2);
|
|
1436
|
-
if (activeT2.length >= config.tiers.tier3Trigger)
|
|
1437
|
-
|
|
1457
|
+
if (activeT2.length >= config.tiers.tier3Trigger) {
|
|
1458
|
+
tier = 3;
|
|
1459
|
+
tierTargetBlocks = activeT2;
|
|
1460
|
+
} else if (activeT1.length >= config.tiers.tier2Trigger) {
|
|
1461
|
+
tier = 2;
|
|
1462
|
+
tierTargetBlocks = activeT1;
|
|
1463
|
+
}
|
|
1438
1464
|
}
|
|
1439
1465
|
const rec = recommendation;
|
|
1440
1466
|
const nothingToCompress = rec ? rec.contextRanges.compressible.length === 0 : false;
|
|
1441
|
-
const shouldInject = shouldContextNudge
|
|
1467
|
+
const shouldInject = shouldContextNudge;
|
|
1442
1468
|
let reason;
|
|
1443
1469
|
if (!shouldInject) {
|
|
1444
|
-
|
|
1470
|
+
const tierHint = tier !== null ? `, tier-${tier} ready (distill when growth reaches threshold)` : "";
|
|
1471
|
+
reason = `growth ${growthSinceReference} < threshold ${effectiveThreshold}${hasPendingNudge ? " (halved)" : ""} (floor ${growthFloor})${tierHint}`;
|
|
1445
1472
|
} else if (emergencyOverride) {
|
|
1446
1473
|
reason = `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}%`;
|
|
1447
1474
|
} else if (tier !== null) {
|
|
1448
|
-
reason = `tier-${tier} distillation
|
|
1475
|
+
reason = `growth ${growthSinceReference} >= ${effectiveThreshold}${hasPendingNudge ? " (halved)" : ""}, usage ${Math.round(usage * 100)}%, tier-${tier} distillation`;
|
|
1449
1476
|
} else if (nothingToCompress) {
|
|
1450
1477
|
reason = `growth ${growthSinceReference} >= ${effectiveThreshold} but no specific ranges worth compressing`;
|
|
1451
1478
|
} else {
|
|
@@ -1457,6 +1484,7 @@ function decideNudge(input) {
|
|
|
1457
1484
|
reason,
|
|
1458
1485
|
compressibleRanges: rec?.recommendedRanges ?? [],
|
|
1459
1486
|
protectedRanges: rec?.contextRanges.protected ?? [],
|
|
1487
|
+
tierTargetBlocks,
|
|
1460
1488
|
contextUsage: usage,
|
|
1461
1489
|
tier,
|
|
1462
1490
|
breakdown: {
|
|
@@ -1733,6 +1761,18 @@ function mergeRanges(compressible, protected_) {
|
|
|
1733
1761
|
}
|
|
1734
1762
|
return merged;
|
|
1735
1763
|
}
|
|
1764
|
+
function formatTierTargetBlocks(blocks) {
|
|
1765
|
+
if (blocks.length === 0) {
|
|
1766
|
+
return "Target blocks: (none \u2014 no tier blocks found)";
|
|
1767
|
+
}
|
|
1768
|
+
const lines = blocks.map((b) => {
|
|
1769
|
+
const summaryTokens = Math.ceil((b.summary ?? "").length / 4);
|
|
1770
|
+
const topic = b.topic ? ` "${b.topic}"` : "";
|
|
1771
|
+
return ` ${b.blockId} ${b.effectiveMessageIds.length} msgs ${formatK(b.compressedTokens)}\u2192${formatK(summaryTokens)}${topic}`;
|
|
1772
|
+
});
|
|
1773
|
+
return `Target ${blocks[0].tier === 1 ? "tier-1" : "tier-2"} blocks to distill (${blocks.length}):
|
|
1774
|
+
${lines.join("\n")}`;
|
|
1775
|
+
}
|
|
1736
1776
|
function formatRanges(compressible, protected_) {
|
|
1737
1777
|
const merged = mergeRanges(compressible, protected_);
|
|
1738
1778
|
if (merged.length === 0) {
|
|
@@ -1756,6 +1796,10 @@ function renderNudgeText(decision) {
|
|
|
1756
1796
|
const rangesStr = formatRanges(decision.compressibleRanges, decision.protectedRanges ?? []);
|
|
1757
1797
|
if (decision.tier !== null && decision.tier >= 2) {
|
|
1758
1798
|
const isT2 = decision.tier === 2;
|
|
1799
|
+
const targets = decision.tierTargetBlocks ?? [];
|
|
1800
|
+
const blockList = formatTierTargetBlocks(targets);
|
|
1801
|
+
const startId = targets[0]?.blockId ?? "b1";
|
|
1802
|
+
const endId = targets[targets.length - 1]?.blockId ?? "b5";
|
|
1759
1803
|
return {
|
|
1760
1804
|
voice: "gentle",
|
|
1761
1805
|
text: [
|
|
@@ -1764,8 +1808,9 @@ function renderNudgeText(decision) {
|
|
|
1764
1808
|
breakdownStr,
|
|
1765
1809
|
"",
|
|
1766
1810
|
`[TIER ${decision.tier} ${isT2 ? "DISTILLATION" : "CONDENSATION"} TRIGGER]`,
|
|
1767
|
-
isT2 ?
|
|
1768
|
-
|
|
1811
|
+
isT2 ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries.` : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries.`,
|
|
1812
|
+
blockList,
|
|
1813
|
+
`Example: compress({ content: [{ startId: "${startId}", endId: "${endId}", summary: "..." }] })`,
|
|
1769
1814
|
"",
|
|
1770
1815
|
HOW_TO_COMPRESS_RULES,
|
|
1771
1816
|
"",
|