billion-context-pi 0.1.31 → 0.1.32
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/index.js +82 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -463,14 +463,49 @@ function truncateLargeToolOutputs(messages, tokenCount, config, countTokens, opt
|
|
|
463
463
|
return { messages: updated, truncatedCount, savedTokens };
|
|
464
464
|
}
|
|
465
465
|
var KEEP_LAST_ORPHANED = 0;
|
|
466
|
+
function rangeKey(startRef, endRef) {
|
|
467
|
+
return `${startRef}::${endRef}`;
|
|
468
|
+
}
|
|
469
|
+
function rewriteCompressText(text, liveKeys) {
|
|
470
|
+
let parsed;
|
|
471
|
+
try {
|
|
472
|
+
parsed = JSON.parse(text ?? "");
|
|
473
|
+
} catch {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
477
|
+
const obj = parsed;
|
|
478
|
+
const content = obj.content;
|
|
479
|
+
if (!Array.isArray(content) || content.length === 0) return null;
|
|
480
|
+
const kept = content.filter((entry) => {
|
|
481
|
+
if (!entry || typeof entry !== "object") return false;
|
|
482
|
+
const s = typeof entry.startId === "string" ? entry.startId : typeof entry.messageId === "string" ? entry.messageId : "";
|
|
483
|
+
const e = typeof entry.endId === "string" ? entry.endId : typeof entry.messageId === "string" ? entry.messageId : "";
|
|
484
|
+
return liveKeys.has(rangeKey(s, e));
|
|
485
|
+
});
|
|
486
|
+
if (kept.length === content.length || kept.length === 0) return null;
|
|
487
|
+
return JSON.stringify({ ...obj, content: kept });
|
|
488
|
+
}
|
|
466
489
|
function hideConsumedCompressCalls(state, messages) {
|
|
467
|
-
const activeCallIds = /* @__PURE__ */ new Set();
|
|
468
490
|
const allBlockCallIds = /* @__PURE__ */ new Set();
|
|
491
|
+
const activeCallIds = /* @__PURE__ */ new Set();
|
|
492
|
+
const liveRangeKeysByCallId = /* @__PURE__ */ new Map();
|
|
493
|
+
const legacyLiveByCallId = /* @__PURE__ */ new Set();
|
|
469
494
|
for (const block of state.blocks) {
|
|
470
|
-
if (block.compressCallId)
|
|
471
|
-
|
|
472
|
-
|
|
495
|
+
if (!block.compressCallId) continue;
|
|
496
|
+
allBlockCallIds.add(block.compressCallId);
|
|
497
|
+
if (!block.active) continue;
|
|
498
|
+
activeCallIds.add(block.compressCallId);
|
|
499
|
+
if (block.startRef === void 0 || block.endRef === void 0) {
|
|
500
|
+
legacyLiveByCallId.add(block.compressCallId);
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
let keys = liveRangeKeysByCallId.get(block.compressCallId);
|
|
504
|
+
if (!keys) {
|
|
505
|
+
keys = /* @__PURE__ */ new Set();
|
|
506
|
+
liveRangeKeysByCallId.set(block.compressCallId, keys);
|
|
473
507
|
}
|
|
508
|
+
keys.add(rangeKey(block.startRef, block.endRef));
|
|
474
509
|
}
|
|
475
510
|
const lastOrphanedCallIds = [];
|
|
476
511
|
for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {
|
|
@@ -499,6 +534,16 @@ function hideConsumedCompressCalls(state, messages) {
|
|
|
499
534
|
hidden++;
|
|
500
535
|
continue;
|
|
501
536
|
}
|
|
537
|
+
if (message.toolName === "compress" && message.contentType === "tool-call" && message.toolCallId && keepCallIds.has(message.toolCallId)) {
|
|
538
|
+
const liveKeys = liveRangeKeysByCallId.get(message.toolCallId);
|
|
539
|
+
if (liveKeys && liveKeys.size > 0 && !legacyLiveByCallId.has(message.toolCallId)) {
|
|
540
|
+
const rewritten = rewriteCompressText(message.text, liveKeys);
|
|
541
|
+
if (rewritten !== null) {
|
|
542
|
+
result.push({ ...message, text: rewritten });
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
502
547
|
result.push(message);
|
|
503
548
|
}
|
|
504
549
|
return { messages: result, hidden };
|
|
@@ -732,8 +777,8 @@ function refNum(ref) {
|
|
|
732
777
|
const n = parseInt(ref.slice(1), 10);
|
|
733
778
|
return Number.isNaN(n) ? -1 : n;
|
|
734
779
|
}
|
|
735
|
-
function
|
|
736
|
-
return Math.ceil(
|
|
780
|
+
function estimateTextTokens(text) {
|
|
781
|
+
return Math.ceil(text.length / 4);
|
|
737
782
|
}
|
|
738
783
|
function isToolMessage(message) {
|
|
739
784
|
return message.contentType === "tool-call" || message.contentType === "tool-result";
|
|
@@ -745,7 +790,7 @@ function isSyntheticOrPruned(message, state) {
|
|
|
745
790
|
}
|
|
746
791
|
return false;
|
|
747
792
|
}
|
|
748
|
-
function computeProtectedRefs(messages, state, config) {
|
|
793
|
+
function computeProtectedRefs(messages, state, config, countTokens = estimateTextTokens) {
|
|
749
794
|
const preserveN = config.preserveRecentMessages;
|
|
750
795
|
const preserveTokens = config.preserveRecentTokens;
|
|
751
796
|
const result = /* @__PURE__ */ new Set();
|
|
@@ -755,7 +800,7 @@ function computeProtectedRefs(messages, state, config) {
|
|
|
755
800
|
if (isNeverPreserveRecent(msg)) continue;
|
|
756
801
|
const ref = state.messageRefs.byRaw[msg.id];
|
|
757
802
|
if (!ref || ref === "BLOCKED") continue;
|
|
758
|
-
visible.push({ ref, tokens:
|
|
803
|
+
visible.push({ ref, tokens: countTokens(msg.text ?? "") });
|
|
759
804
|
}
|
|
760
805
|
if (preserveN > 0) {
|
|
761
806
|
for (const m of visible.slice(-preserveN)) {
|
|
@@ -780,7 +825,7 @@ function computeProtectedRefs(messages, state, config) {
|
|
|
780
825
|
}
|
|
781
826
|
return result;
|
|
782
827
|
}
|
|
783
|
-
function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
|
|
828
|
+
function buildCompressibleRanges(messages, state, config, protectedZoneRefs, countTokens = estimateTextTokens) {
|
|
784
829
|
const compressibleMsgs = [];
|
|
785
830
|
const protectedMsgs = [];
|
|
786
831
|
const protectedCallIds = collectProtectedToolCallIds(messages, config);
|
|
@@ -793,7 +838,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
|
|
|
793
838
|
protectedMsgs.push({
|
|
794
839
|
ref,
|
|
795
840
|
refNum: rn,
|
|
796
|
-
tokens:
|
|
841
|
+
tokens: countTokens(msg.text ?? ""),
|
|
797
842
|
tools: msg.toolName ? [msg.toolName] : []
|
|
798
843
|
});
|
|
799
844
|
continue;
|
|
@@ -804,7 +849,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
|
|
|
804
849
|
compressibleMsgs.push({
|
|
805
850
|
ref,
|
|
806
851
|
refNum: rn,
|
|
807
|
-
tokens:
|
|
852
|
+
tokens: countTokens(msg.text ?? ""),
|
|
808
853
|
isTool: isToolMessage(msg),
|
|
809
854
|
isUser: msg.role === "user"
|
|
810
855
|
});
|
|
@@ -891,7 +936,7 @@ function createCore(ports = {}) {
|
|
|
891
936
|
let tokensCompressed = 0;
|
|
892
937
|
const errors = [];
|
|
893
938
|
const warnings = [];
|
|
894
|
-
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config);
|
|
939
|
+
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config, countTokens);
|
|
895
940
|
const preExistingCoverage = collectCoverage(state);
|
|
896
941
|
const rangeIndexSets = [];
|
|
897
942
|
for (const spec of input.ranges) {
|
|
@@ -916,29 +961,25 @@ function createCore(ports = {}) {
|
|
|
916
961
|
const bMin = b.indices.length > 0 ? Math.min(...b.indices) : Infinity;
|
|
917
962
|
return aMin - bMin;
|
|
918
963
|
});
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
const
|
|
923
|
-
const
|
|
924
|
-
if (
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
errors: [
|
|
931
|
-
`content: range (${prev.spec.startRef}..${prev.spec.endRef}) overlaps (${curr.spec.startRef}..${curr.spec.endRef}). Overlapping ranges cannot be compressed in the same batch.`
|
|
932
|
-
],
|
|
933
|
-
warnings: []
|
|
934
|
-
}
|
|
935
|
-
};
|
|
964
|
+
const skipSpecs = /* @__PURE__ */ new Set();
|
|
965
|
+
let acceptedMaxIndex = -1;
|
|
966
|
+
for (const entry of sortedRanges) {
|
|
967
|
+
const entryMax = entry.indices.length > 0 ? Math.max(...entry.indices) : -1;
|
|
968
|
+
const entryMin = entry.indices.length > 0 ? Math.min(...entry.indices) : -1;
|
|
969
|
+
if (entryMin >= 0 && entryMin <= acceptedMaxIndex) {
|
|
970
|
+
skipSpecs.add(entry.spec);
|
|
971
|
+
warnings.push(
|
|
972
|
+
`Skipped range (${entry.spec.startRef}..${entry.spec.endRef}) \u2014 overlaps an earlier range in the batch; the earlier range takes precedence. Keep ranges disjoint.`
|
|
973
|
+
);
|
|
974
|
+
continue;
|
|
936
975
|
}
|
|
976
|
+
if (entryMax > acceptedMaxIndex) acceptedMaxIndex = entryMax;
|
|
937
977
|
}
|
|
938
978
|
if (input.config.compress.minCompressRange > 0 && input.ranges.length > 0) {
|
|
939
979
|
let totalRangeChars = 0;
|
|
940
980
|
let hasBlockBoundaryRange = false;
|
|
941
981
|
for (const spec of input.ranges) {
|
|
982
|
+
if (skipSpecs.has(spec)) continue;
|
|
942
983
|
let resolved;
|
|
943
984
|
try {
|
|
944
985
|
resolved = resolveBoundaries({
|
|
@@ -974,6 +1015,7 @@ function createCore(ports = {}) {
|
|
|
974
1015
|
}
|
|
975
1016
|
}
|
|
976
1017
|
for (const spec of input.ranges) {
|
|
1018
|
+
if (skipSpecs.has(spec)) continue;
|
|
977
1019
|
try {
|
|
978
1020
|
const outcome = applySingleRange({
|
|
979
1021
|
spec,
|
|
@@ -1114,13 +1156,15 @@ var recommendNode = {
|
|
|
1114
1156
|
const protectedRefs = computeProtectedRefs(
|
|
1115
1157
|
io.messages,
|
|
1116
1158
|
io.state,
|
|
1117
|
-
ctx.config
|
|
1159
|
+
ctx.config,
|
|
1160
|
+
ctx.countTokens
|
|
1118
1161
|
);
|
|
1119
1162
|
const contextRanges = buildCompressibleRanges(
|
|
1120
1163
|
io.messages,
|
|
1121
1164
|
io.state,
|
|
1122
1165
|
ctx.config,
|
|
1123
|
-
protectedRefs
|
|
1166
|
+
protectedRefs,
|
|
1167
|
+
ctx.countTokens
|
|
1124
1168
|
);
|
|
1125
1169
|
const nothingToCompress = contextRanges.compressible.length === 0;
|
|
1126
1170
|
const recommendation = {
|
|
@@ -1298,7 +1342,9 @@ function applySingleRange(input) {
|
|
|
1298
1342
|
survivedCount: 0,
|
|
1299
1343
|
generation: "young",
|
|
1300
1344
|
active: true,
|
|
1301
|
-
compressCallId: input.spec.compressCallId
|
|
1345
|
+
compressCallId: input.spec.compressCallId,
|
|
1346
|
+
startRef: input.spec.startRef,
|
|
1347
|
+
endRef: input.spec.endRef
|
|
1302
1348
|
};
|
|
1303
1349
|
input.state.blocks.push(block);
|
|
1304
1350
|
for (const consumedId of consumedBlockIds) {
|
|
@@ -1789,7 +1835,7 @@ function renderNudgeText(decision) {
|
|
|
1789
1835
|
breakdownStr,
|
|
1790
1836
|
"",
|
|
1791
1837
|
`[TIER ${decision.tier} ${isT2 ? "DISTILLATION" : "CONDENSATION"} TRIGGER]`,
|
|
1792
|
-
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.`,
|
|
1838
|
+
isT2 ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries (startId and endId as bN). Any raw (uncompressed) messages sitting between the boundary blocks are absorbed into the tier-2 block as well \u2014 apply HOW TO COMPRESS to those raw messages and the TIER 2 distillation rules to the existing summaries, so the whole span is covered and nothing is lost.` : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries (startId and endId as bN). Any raw (uncompressed) messages sitting between the boundary blocks are absorbed into the tier-3 block as well \u2014 apply HOW TO COMPRESS to those raw messages and the TIER 3 condensation rules to the existing summaries, so the whole span is covered and nothing is lost.`,
|
|
1793
1839
|
blockList,
|
|
1794
1840
|
`Example: compress({ content: [{ startId: "${startId}", endId: "${endId}", summary: "..." }] })`,
|
|
1795
1841
|
"",
|
|
@@ -8744,7 +8790,7 @@ async function statusReport(runtime, ctx) {
|
|
|
8744
8790
|
const activeBlocksList = state.blocks.filter((b) => b.active);
|
|
8745
8791
|
const totalBlocksList = state.blocks;
|
|
8746
8792
|
const lines = [];
|
|
8747
|
-
const versionStr = "0.1.
|
|
8793
|
+
const versionStr = "0.1.32" ? `billion-context-pi@${"0.1.32"}` : "";
|
|
8748
8794
|
lines.push("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E");
|
|
8749
8795
|
lines.push("\u2502 ACP Context Analysis \u2502");
|
|
8750
8796
|
lines.push("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F");
|
|
@@ -9110,7 +9156,7 @@ async function checkForUpdate(autoUpdate, notify) {
|
|
|
9110
9156
|
const data = await res.json();
|
|
9111
9157
|
const latest = data.version;
|
|
9112
9158
|
if (!latest) return;
|
|
9113
|
-
const current = runtimeVersion ?? "0.1.
|
|
9159
|
+
const current = runtimeVersion ?? "0.1.32";
|
|
9114
9160
|
const hasUpdate = isNewer(latest, current);
|
|
9115
9161
|
debug.event("update-check", {
|
|
9116
9162
|
current,
|
|
@@ -9349,7 +9395,7 @@ function wireSessionLifecycle(pi, runtime) {
|
|
|
9349
9395
|
runtime.store.invalidate();
|
|
9350
9396
|
runtime.clearNudgeTracking();
|
|
9351
9397
|
const sid = ctx.sessionManager.getSessionId();
|
|
9352
|
-
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.
|
|
9398
|
+
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.32" : null });
|
|
9353
9399
|
try {
|
|
9354
9400
|
const user = await loadUserConfig(ctx.cwd);
|
|
9355
9401
|
runtime.setAdapter(applyUserConfig(runtime.adapter, user));
|