billion-context-pi 0.1.55 → 0.1.56-pr.282.73

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 CHANGED
@@ -430,42 +430,18 @@ function assignRefs(messages, options) {
430
430
  return { map, nextIndex: cursor, newlyAssigned };
431
431
  }
432
432
  function allocateFreeRef(map, start) {
433
- const from = Math.max(start, MIN_INDEX);
434
- for (let candidate = from; candidate <= MAX_INDEX; candidate++) {
435
- const text = indexToRef(candidate);
436
- if (!map.byRef[text]) {
437
- return { text, index: candidate };
438
- }
439
- }
440
- for (let candidate = MIN_INDEX; candidate < from; candidate++) {
433
+ let candidate = Math.max(start, MIN_INDEX);
434
+ while (candidate <= MAX_INDEX) {
441
435
  const text = indexToRef(candidate);
442
436
  if (!map.byRef[text]) {
443
437
  return { text, index: candidate };
444
438
  }
439
+ candidate++;
445
440
  }
446
441
  throw new Error(
447
- `ref capacity exhausted: all ${MAX_INDEX} ref slots are occupied by live messages \u2014 nothing left to reclaim`
442
+ `ref capacity exhausted: cannot allocate beyond ${indexToRef(MAX_INDEX)}`
448
443
  );
449
444
  }
450
- function pruneDeadRefs(map, liveIds) {
451
- let pruned = 0;
452
- const byRaw = {};
453
- for (const [rawId, ref] of Object.entries(map.byRaw)) {
454
- if (liveIds.has(rawId)) {
455
- byRaw[rawId] = ref;
456
- continue;
457
- }
458
- pruned++;
459
- }
460
- return { map: rebuildRefIndex({ byRaw, byRef: {} }), pruned };
461
- }
462
- function rebuildRefIndex(map) {
463
- const byRef = {};
464
- for (const [rawId, ref] of Object.entries(map.byRaw)) {
465
- if (ref !== BLOCKED_REF) byRef[ref] = rawId;
466
- }
467
- return { byRaw: { ...map.byRaw }, byRef };
468
- }
469
445
  function highestUsedIndex(map) {
470
446
  let highest = 0;
471
447
  for (const ref of Object.values(map.byRaw)) {
@@ -664,13 +640,6 @@ function syncBlocks(messages, state) {
664
640
  deactivated.push(block.blockId);
665
641
  }
666
642
  }
667
- const liveIds = new Set(presentIds);
668
- for (const block of result.blocks) {
669
- if (!block.active) continue;
670
- for (const id of block.effectiveMessageIds) liveIds.add(id);
671
- }
672
- const prunedRefs = pruneDeadRefs(result.messageRefs, liveIds);
673
- result.messageRefs = prunedRefs.map;
674
643
  return { state: result, deactivated };
675
644
  }
676
645
  function defaultConfig(modelContextLimit, overrides = {}) {
@@ -781,14 +750,12 @@ var BoundaryNotFoundError = class extends Error {
781
750
  code = "BOUNDARY_NOT_FOUND";
782
751
  kind;
783
752
  endpoint;
784
- reason;
785
- constructor(kind, endpoint, message, reason = null) {
753
+ constructor(kind, endpoint, message) {
786
754
  super(message);
787
755
  this.name = "BoundaryNotFoundError";
788
756
  this.code = "BOUNDARY_NOT_FOUND";
789
757
  this.kind = kind;
790
758
  this.endpoint = endpoint;
791
- this.reason = reason;
792
759
  }
793
760
  };
794
761
  function resolveBoundaries(input) {
@@ -859,7 +826,7 @@ function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
859
826
  throw new BoundaryNotFoundError(
860
827
  "unknown",
861
828
  endpoint,
862
- `${label}="${boundary.raw}" does not exist in this session (typo, wrong session, or the message was edited/removed and its ref released) \u2014 run acp_status for current refs.`
829
+ `${label}="${boundary.raw}" does not exist in this session (typo or wrong session) \u2014 run acp_status for current refs.`
863
830
  );
864
831
  }
865
832
  const index = indexByMessageId.get(rawId);
@@ -873,33 +840,10 @@ function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
873
840
  snapped: `${label}="${boundary.raw}" refers to a message already compressed into an active block \u2014 anchored to the active block covering it instead.`
874
841
  };
875
842
  }
876
- const coveringActive = state.blocks.filter(
877
- (block2) => block2.active && block2.effectiveMessageIds.includes(rawId)
878
- );
879
- if (coveringActive.length > 0) {
880
- throw new BoundaryNotFoundError(
881
- "consumed",
882
- endpoint,
883
- `${label}="${boundary.raw}" is already compressed into active block(s) ${coveringActive.map((block2) => block2.blockId).join(", ")} \u2014 retry with the block ref(s) instead of the message ref.`,
884
- "consumed"
885
- );
886
- }
887
- const generationReplaced = state.blocks.some(
888
- (block2) => !block2.active && block2.effectiveMessageIds.includes(rawId)
889
- );
890
- if (generationReplaced) {
891
- throw new BoundaryNotFoundError(
892
- "consumed",
893
- endpoint,
894
- `${label}="${boundary.raw}" was compressed into a block that has since been distilled or consumed \u2014 its content is no longer available in this session; run acp_status for current refs.`,
895
- "generation-replaced"
896
- );
897
- }
898
843
  throw new BoundaryNotFoundError(
899
844
  "consumed",
900
845
  endpoint,
901
- `${label}="${boundary.raw}" no longer exists \u2014 the message was edited or removed (its content id changed); run acp_status for current refs.`,
902
- "edit-drift"
846
+ `${label}="${boundary.raw}" not found in visible context (likely consumed by an existing block).`
903
847
  );
904
848
  }
905
849
  const block = blockById(state, `b${boundary.numericId}`);
@@ -928,21 +872,16 @@ function resolveAnchorIndex(boundary, state, indexByMessageId, endpoint) {
928
872
  };
929
873
  }
930
874
  if (!block.active) {
931
- const consumer = state.blocks.find(
932
- (candidate) => candidate.active && candidate.directBlockIds.includes(block.blockId) && visibleBlockAnchor(candidate, indexByMessageId) !== null
933
- );
934
875
  throw new BoundaryNotFoundError(
935
876
  "consumed",
936
877
  endpoint,
937
- consumer ? `${label}="b${boundary.numericId}" was consumed by ${consumer.blockId} (higher-tier block) \u2014 retry with ${consumer.blockId} instead.` : `${label}="b${boundary.numericId}" is inactive (distilled or garbage-collected) and none of its content is visible in the current context \u2014 run acp_status for current refs.`,
938
- "generation-replaced"
878
+ `${label}="b${boundary.numericId}" not found in visible context (block distilled/consumed by a higher-tier block).`
939
879
  );
940
880
  }
941
881
  throw new BoundaryNotFoundError(
942
882
  "consumed",
943
883
  endpoint,
944
- `${label}="b${boundary.numericId}" is an active block but none of its content (raw messages or rendered summary) is present in the current view \u2014 its messages were likely edited or removed (id drift); it will be deactivated on the next state sync. Run acp_status to verify.`,
945
- "edit-drift"
884
+ `${label}="b${boundary.numericId}" is an active block but none of its content (raw messages or rendered summary) is visible in the current context \u2014 run acp_status to verify.`
946
885
  );
947
886
  }
948
887
  function activeOwnerAnchor(state, ownedIds, indexByMessageId) {
@@ -1890,10 +1829,7 @@ function danglingMessageRefs(state, messages, spec) {
1890
1829
  function createCore(ports = {}) {
1891
1830
  const countTokens = ports.countTokens ?? defaultCountTokens;
1892
1831
  function applyCompression(input) {
1893
- const state = syncBlocks(
1894
- input.messages,
1895
- input.state
1896
- ).state;
1832
+ const state = cloneState(input.state);
1897
1833
  const runId = allocateRunId(state);
1898
1834
  let blocksCreated = 0;
1899
1835
  let tokensCompressed = 0;
@@ -1998,7 +1934,7 @@ function createCore(ports = {}) {
1998
1934
  const danglingRefs = consumedRanges.flatMap(
1999
1935
  (spec) => danglingMessageRefs(state, input.messages, spec)
2000
1936
  );
2001
- 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), a typo, or a message that was edited or removed (its old ref was released when the content id changed). ${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. ${consumedRanges[0].startRef}..${consumedRanges[0].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. ${consumedRanges[0].startRef}..${consumedRanges[0].endRef}) \u2014 those refs no longer point to directly compressible content: the range is covered by active block(s) or the block ref(s) are stale (distilled or consumed). ${diagnostics} Run acp_status, then call the compress tool again using only the CURRENT compressible ranges it reports.${liveHint}` : `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.`;
1937
+ 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. ${consumedRanges[0].startRef}..${consumedRanges[0].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. ${consumedRanges[0].startRef}..${consumedRanges[0].endRef}) \u2014 those refs no longer point to directly compressible content: the range is covered by active block(s) or the block ref(s) are stale (distilled or consumed). ${diagnostics} Run acp_status, then call the compress tool again using only the CURRENT compressible ranges it reports.${liveHint}` : `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.`;
2002
1938
  return {
2003
1939
  state: input.state,
2004
1940
  result: {
@@ -2141,15 +2077,9 @@ var assignRefsNode = {
2141
2077
  run(io, ctx) {
2142
2078
  const hasProtection = ctx.config.protectedTools.length > 0 || !!ctx.config.isToolProtected;
2143
2079
  const protectedFn = hasProtection ? (m) => isMessageProtected(m, ctx.config) : void 0;
2144
- const liveIds = new Set(io.messages.map((m) => m.id));
2145
- for (const block of io.state.blocks) {
2146
- if (!block.active) continue;
2147
- for (const id of block.effectiveMessageIds) liveIds.add(id);
2148
- }
2149
- const pruned = pruneDeadRefs(io.state.messageRefs, liveIds);
2150
2080
  const refResult = assignRefs(io.messages, {
2151
- existing: pruned.map,
2152
- nextIndex: highestUsedIndex(pruned.map) + 1,
2081
+ existing: io.state.messageRefs,
2082
+ nextIndex: highestUsedIndex(io.state.messageRefs) + 1,
2153
2083
  isProtected: protectedFn
2154
2084
  });
2155
2085
  return { ...io, state: { ...io.state, messageRefs: refResult.map } };
@@ -2721,6 +2651,26 @@ function computeContextBreakdown(messages, total, growth, countTokens) {
2721
2651
  }
2722
2652
  return { system, tool, summaries, code, text, total, growth };
2723
2653
  }
2654
+ function cloneState(state) {
2655
+ return {
2656
+ blocks: state.blocks.map((block) => ({
2657
+ ...block,
2658
+ directMessageIds: [...block.directMessageIds],
2659
+ effectiveMessageIds: [...block.effectiveMessageIds],
2660
+ directBlockIds: [...block.directBlockIds]
2661
+ })),
2662
+ messageRefs: {
2663
+ byRaw: { ...state.messageRefs.byRaw },
2664
+ byRef: { ...state.messageRefs.byRef }
2665
+ },
2666
+ tokenSnapshot: { ...state.tokenSnapshot ?? {} },
2667
+ nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },
2668
+ stats: { ...state.stats },
2669
+ absorbed: (state.absorbed ?? []).map((record) => ({ ...record })),
2670
+ nextBlockId: state.nextBlockId,
2671
+ nextRunId: state.nextRunId
2672
+ };
2673
+ }
2724
2674
  function scoreRelevance(block, terms) {
2725
2675
  const topic = (block.topic ?? "").toLowerCase();
2726
2676
  const summary = block.summary.toLowerCase();
@@ -11959,7 +11909,7 @@ async function statusReport(runtime, ctx) {
11959
11909
  const coveredIds = collectCoveredMessageIds(state);
11960
11910
  const sentTokens = estimateTokens(coreMessages, coveredIds, imageTokens) + systemPromptTokens;
11961
11911
  const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: anchorStale ? sentTokens : Math.max(sentTokens, realUsage?.tokens ?? 0) });
11962
- const versionStr = "0.1.55" ? `billion-context-pi@${"0.1.55"}` : void 0;
11912
+ const versionStr = "0.1.56" ? `billion-context-pi@${"0.1.56"}` : void 0;
11963
11913
  let text = buildStatusPanel({
11964
11914
  version: versionStr,
11965
11915
  tokenCount: sessionTokens,
@@ -12322,7 +12272,7 @@ async function autoInstallLatest(latest, extDirOverride) {
12322
12272
  "--no-fund",
12323
12273
  "--no-save"
12324
12274
  ];
12325
- const prevVersion = (await readPackageJson(join8(extDir, "package.json")))?.version ?? "0.1.55";
12275
+ const prevVersion = (await readPackageJson(join8(extDir, "package.json")))?.version ?? "0.1.56";
12326
12276
  const { code, stderr } = await runNpmImpl(installArgs(latest), { cwd: npmDir, timeout: 6e4 });
12327
12277
  if (code !== 0) {
12328
12278
  logWarn("update", {
@@ -12335,7 +12285,7 @@ async function autoInstallLatest(latest, extDirOverride) {
12335
12285
  }
12336
12286
  const verify = await verifyInstall(npmDir, latest);
12337
12287
  if (!verify.ok) {
12338
- const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.55";
12288
+ const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.56";
12339
12289
  logWarn("update", { event: "auto-install-verify-failed", latest, reason: verify.reason, rollbackTo });
12340
12290
  const rb = await runNpmImpl(installArgs(rollbackTo), { cwd: npmDir, timeout: 6e4 });
12341
12291
  logInfo("update", { event: "rollback", from: latest, to: rollbackTo, ok: rb.code === 0 });
@@ -12396,7 +12346,7 @@ async function checkForUpdate(autoUpdate, notify) {
12396
12346
  const runtimeVersion = await getRuntimeVersion();
12397
12347
  const latest = await fetchLatestVersion();
12398
12348
  if (!latest) return;
12399
- const current = runtimeVersion ?? "0.1.55";
12349
+ const current = runtimeVersion ?? "0.1.56";
12400
12350
  const hasUpdate = isNewer(latest, current);
12401
12351
  debug.event("update-check", {
12402
12352
  current,
@@ -12505,7 +12455,7 @@ function wireSessionLifecycle(pi, runtime) {
12505
12455
  setDelegateDisplayUsage("separate");
12506
12456
  const sid = ctx.sessionManager.getSessionId();
12507
12457
  const modelInfo = ctx.model;
12508
- logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.55" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
12458
+ logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.56" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
12509
12459
  try {
12510
12460
  await runtime.reloadConfig(ctx.cwd);
12511
12461
  setDelegateDisplayUsage(resolveDelegate(runtime.adapter).displayUsage);