billion-context-pi 0.1.73 → 0.1.74-pr.485.281

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.
@@ -24,6 +24,7 @@ export declare function makeCompressTool(runtime: AcpRuntime, overrides?: ToolPr
24
24
  type RangeEntry = Static<typeof RangeSpec>;
25
25
  export declare function normalizeRanges(args: CompressArgs): RangeEntry[] | string;
26
26
  export declare function tailRepair(s: string): string | undefined;
27
+ export declare function arrayWrapRepair(s: string): string | undefined;
27
28
  /** Panel block count, or -1 for non-panels. Accepts BOTH the legacy
28
29
  * "… B blocks)" form (0-block runs; historical transcripts replayed by
29
30
  * index/floor-stale) and the #376 "… blocks: b3=m00044–m00097*, …" form. */
package/dist/index.js CHANGED
@@ -403,7 +403,7 @@ function clampWindow(text, start, end) {
403
403
  return text.slice(s, Math.max(s, e));
404
404
  }
405
405
 
406
- // node_modules/acp-kernel/dist/chunk-UX4LINT7.js
406
+ // node_modules/acp-kernel/dist/chunk-5TQA7ZQM.js
407
407
  function createInitialState() {
408
408
  return {
409
409
  blocks: [],
@@ -418,6 +418,8 @@ function createInitialState() {
418
418
  },
419
419
  stats: { tokensCompressed: 0, compressionCount: 0, absorbedTokens: 0 },
420
420
  absorbed: [],
421
+ rules: [],
422
+ nextRuleId: 1,
421
423
  nextBlockId: 1,
422
424
  nextRunId: 1
423
425
  };
@@ -718,6 +720,8 @@ function syncBlocks(messages, state) {
718
720
  nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },
719
721
  stats: { ...state.stats },
720
722
  absorbed: (state.absorbed ?? []).map((record) => ({ ...record })),
723
+ rules: (state.rules ?? []).map((rule) => ({ ...rule })),
724
+ nextRuleId: state.nextRuleId,
721
725
  terminalStreak: state.terminalStreak,
722
726
  nextBlockId: state.nextBlockId,
723
727
  nextRunId: state.nextRunId
@@ -781,6 +785,7 @@ function defaultConfig(modelContextLimit, overrides = {}) {
781
785
  minSummaryLength: 50
782
786
  },
783
787
  protectedTools: [],
788
+ protectedLatestTools: [],
784
789
  preserveRecentMessages: 5,
785
790
  preserveRecentTokens: 5e3,
786
791
  modelContextLimit,
@@ -846,6 +851,14 @@ function validateConfig(config) {
846
851
  errors.push("absorb.contextThresholdPct must be in [0, 1]");
847
852
  }
848
853
  }
854
+ if (config.rules) {
855
+ if (config.rules.maxRules !== void 0 && (!Number.isFinite(config.rules.maxRules) || config.rules.maxRules < 1)) {
856
+ errors.push("rules.maxRules must be >= 1");
857
+ }
858
+ if (config.rules.maxRuleChars !== void 0 && (!Number.isFinite(config.rules.maxRuleChars) || config.rules.maxRuleChars < 1)) {
859
+ errors.push("rules.maxRuleChars must be >= 1");
860
+ }
861
+ }
849
862
  return errors;
850
863
  }
851
864
  var MESSAGE_REF_PATTERN = /^m0*(\d{1,5})$/;
@@ -1655,7 +1668,7 @@ var ACP_STATUS_TOOL_GOOGLE = {
1655
1668
  description: ACP_STATUS_TOOL_OPENAI.function.description,
1656
1669
  parameters: ACP_STATUS_TOOL_OPENAI.function.parameters
1657
1670
  };
1658
- var ALWAYS_PROTECTED_TOOLS = ["compress"];
1671
+ var ALWAYS_PROTECTED_TOOLS = ["compress", "acp_rule"];
1659
1672
  var NEVER_PRESERVE_RECENT_TOOLS = [
1660
1673
  "decompress",
1661
1674
  "search_context",
@@ -1704,6 +1717,31 @@ function isMessageProtectedWithPairing(msg, config, protectedCallIds) {
1704
1717
  }
1705
1718
  return false;
1706
1719
  }
1720
+ function collectLatestProtected(messages, config) {
1721
+ const callIds = /* @__PURE__ */ new Set();
1722
+ const msgIds = /* @__PURE__ */ new Set();
1723
+ const patterns = config.protectedLatestTools ?? [];
1724
+ if (patterns.length === 0) return { callIds, msgIds };
1725
+ for (const pattern of patterns) {
1726
+ let last;
1727
+ for (const m2 of messages) {
1728
+ if (m2.contentType === "tool-call" && m2.toolName && matchToolPattern(m2.toolName, pattern)) {
1729
+ last = m2;
1730
+ }
1731
+ }
1732
+ if (!last) continue;
1733
+ if (last.toolCallId) callIds.add(last.toolCallId);
1734
+ else msgIds.add(last.id);
1735
+ }
1736
+ return { callIds, msgIds };
1737
+ }
1738
+ function isMessageLatestProtected(msg, latest) {
1739
+ if (msg.contentType === "tool-call" && latest.msgIds.has(msg.id)) return true;
1740
+ if ((msg.contentType === "tool-call" || msg.contentType === "tool-result") && msg.toolCallId && latest.callIds.has(msg.toolCallId)) {
1741
+ return true;
1742
+ }
1743
+ return false;
1744
+ }
1707
1745
  var ABSORB_PROMPT_MARKER = "[ACP absorb]";
1708
1746
  var DEFAULT_ABSORB_CONFIG = {
1709
1747
  enabled: false,
@@ -1728,11 +1766,12 @@ function isAcpOrConfiguredTool(toolName, cfg) {
1728
1766
  if (toolName === cfg.toolName) return true;
1729
1767
  return ACP_TOOL_NAMES.has(toolName);
1730
1768
  }
1731
- function isAbsorbCandidate(msg, config) {
1769
+ function isAbsorbCandidate(msg, config, latest) {
1732
1770
  if (msg.contentType !== "tool-result" || !msg.toolCallId) return false;
1733
1771
  const cfg = resolveAbsorbConfig(config);
1734
1772
  if (isAcpOrConfiguredTool(msg.toolName, cfg)) return false;
1735
1773
  if (isMessageProtected(msg, config)) return false;
1774
+ if (latest && isMessageLatestProtected(msg, latest)) return false;
1736
1775
  for (const pattern of cfg.excludeTools) {
1737
1776
  if (msg.toolName && matchToolPattern(msg.toolName, pattern)) return false;
1738
1777
  }
@@ -1760,8 +1799,9 @@ function appendAbsorbPrompts(messages, state, config, tokenCount, countTokens) {
1760
1799
  if (record.resultMessageId) absorbedIds.add(record.resultMessageId);
1761
1800
  }
1762
1801
  let promptedCount = 0;
1802
+ const latest = collectLatestProtected(messages, config);
1763
1803
  const out = messages.map((msg) => {
1764
- if (!isAbsorbCandidate(msg, config)) return msg;
1804
+ if (!isAbsorbCandidate(msg, config, latest)) return msg;
1765
1805
  if (absorbedIds.has(msg.id)) return msg;
1766
1806
  const text = msg.text ?? "";
1767
1807
  if (text.includes(ABSORB_PROMPT_MARKER)) return msg;
@@ -2198,6 +2238,8 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
2198
2238
  let compressibleMsgs = [];
2199
2239
  const protectedMsgs = [];
2200
2240
  const protectedCallIds = collectProtectedToolCallIds(messages, config);
2241
+ const latest = collectLatestProtected(messages, config);
2242
+ for (const id of latest.callIds) protectedCallIds.add(id);
2201
2243
  let skipSinceCompressible = false;
2202
2244
  let skipSinceProtected = false;
2203
2245
  let msgIndex = -1;
@@ -2210,7 +2252,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
2210
2252
  skipSinceProtected = true;
2211
2253
  continue;
2212
2254
  }
2213
- if (isMessageProtectedWithPairing(msg, config, protectedCallIds)) {
2255
+ if (isMessageProtectedWithPairing(msg, config, protectedCallIds) || isMessageLatestProtected(msg, latest)) {
2214
2256
  protectedMsgs.push({
2215
2257
  ref,
2216
2258
  gapBefore: skipSinceProtected,
@@ -2412,6 +2454,39 @@ function danglingMessageRefs(state, messages, spec) {
2412
2454
  }
2413
2455
  return dangling;
2414
2456
  }
2457
+ function coveringBlockIds(state, spec) {
2458
+ const found = /* @__PURE__ */ new Set();
2459
+ for (const ref of [spec.startRef, spec.endRef]) {
2460
+ const parsed = parseBoundary(ref);
2461
+ if (!parsed) continue;
2462
+ let rawIds = [];
2463
+ if (parsed.kind === "message") {
2464
+ const rawId = state.messageRefs.byRef[parsed.raw] ?? state.messageRefs.byRef[indexToRef(parsed.numericId)];
2465
+ if (rawId) rawIds = [rawId];
2466
+ } else {
2467
+ rawIds = blockById(state, `b${parsed.numericId}`)?.effectiveMessageIds ?? [];
2468
+ }
2469
+ if (rawIds.length === 0) continue;
2470
+ for (const candidate of activeBlocks(state)) {
2471
+ if (rawIds.some((id) => candidate.effectiveMessageIds.includes(id))) {
2472
+ found.add(candidate.blockId);
2473
+ }
2474
+ }
2475
+ }
2476
+ return [...found].sort((x2, y2) => numericBlockId(x2) - numericBlockId(y2));
2477
+ }
2478
+ function tierActionHint(config, state) {
2479
+ if (!config.tiers.enabled) return "";
2480
+ const t2 = activeBlocks(state).filter((b2) => b2.tier === 2);
2481
+ if (t2.length >= config.tiers.tier3Trigger) {
2482
+ return ` Tier condensation is actionable now: compress({ content: [{ startId: "${t2[0].blockId}", endId: "${t2[t2.length - 1].blockId}", summary: "...", topic: "..." }] }) merges those tier-2 blocks into one tier-3 block.`;
2483
+ }
2484
+ const t1 = activeBlocks(state).filter((b2) => b2.tier === 1);
2485
+ if (t1.length >= config.tiers.tier2Trigger) {
2486
+ return ` Tier distillation is actionable now: compress({ content: [{ startId: "${t1[0].blockId}", endId: "${t1[t1.length - 1].blockId}", summary: "...", topic: "..." }] }) merges those tier-1 blocks into one tier-2 block.`;
2487
+ }
2488
+ return "";
2489
+ }
2415
2490
  function createCore(ports = {}) {
2416
2491
  const countTokens = ports.countTokens ?? defaultCountTokens;
2417
2492
  function applyCompression(input) {
@@ -2510,17 +2585,18 @@ function createCore(ports = {}) {
2510
2585
  }
2511
2586
  }
2512
2587
  if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {
2513
- const live = activeBlocks(state).map((b2) => b2.blockId).sort((x2, y2) => numericBlockId(x2) - numericBlockId(y2));
2514
- const liveHint = live.length > 0 ? ` Current active blocks span ${live[0]}..${live[live.length - 1]} \u2014 retry with startId/endId set to active block IDs in that span.` : "";
2515
2588
  const diagnostics = refGateDiagnostics(
2516
2589
  state,
2517
2590
  input.ranges.length,
2518
2591
  unknownCount
2519
2592
  );
2593
+ const firstConsumed = consumedRanges[0];
2594
+ const covering = firstConsumed ? coveringBlockIds(state, firstConsumed) : [];
2595
+ 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)`;
2520
2596
  const danglingRefs = consumedRanges.flatMap(
2521
2597
  (spec) => danglingMessageRefs(state, input.messages, spec)
2522
2598
  );
2523
- 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.`;
2599
+ 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.`;
2524
2600
  return {
2525
2601
  state: input.state,
2526
2602
  result: {
@@ -2664,8 +2740,9 @@ function createCore(ports = {}) {
2664
2740
  var assignRefsNode = {
2665
2741
  name: "assign-refs",
2666
2742
  run(io, ctx) {
2667
- const hasProtection = ctx.config.protectedTools.length > 0 || !!ctx.config.isToolProtected;
2668
- const protectedFn = hasProtection ? (m2) => isMessageProtected(m2, ctx.config) : void 0;
2743
+ const hasProtection = ctx.config.protectedTools.length > 0 || !!ctx.config.isToolProtected || (ctx.config.protectedLatestTools?.length ?? 0) > 0;
2744
+ const latest = hasProtection ? collectLatestProtected(io.messages, ctx.config) : void 0;
2745
+ const protectedFn = hasProtection ? (m2) => isMessageProtected(m2, ctx.config) || (latest ? isMessageLatestProtected(m2, latest) : false) : void 0;
2669
2746
  const refResult = assignRefs(io.messages, {
2670
2747
  existing: io.state.messageRefs,
2671
2748
  nextIndex: highestUsedIndex(io.state.messageRefs) + 1,
@@ -2927,7 +3004,7 @@ function applySingleRange(input) {
2927
3004
  warnings.push(
2928
3005
  `Excluded ${hitProtectedRaw.length} protected message(s) ${hitRefs.join(
2929
3006
  ", "
2930
- )} from compression range (recent/last-user zone).`
3007
+ )} from compression range (recent/last-user zone) \u2014 they stay visible outside the new block; do not target them in another compress call.`
2931
3008
  );
2932
3009
  }
2933
3010
  {
@@ -3061,6 +3138,8 @@ function validateCompressionRange(input, directMessageIds, consumedBlockCount) {
3061
3138
  function filterProtectedToolMessages(directMessageIds, messages, config) {
3062
3139
  const protectedCallIds = /* @__PURE__ */ new Set();
3063
3140
  const removedIds = /* @__PURE__ */ new Set();
3141
+ const latest = collectLatestProtected(messages, config);
3142
+ for (const id of latest.callIds) protectedCallIds.add(id);
3064
3143
  for (const msg of messages) {
3065
3144
  if (isMessageProtected(msg, config) && msg.toolCallId) {
3066
3145
  protectedCallIds.add(msg.toolCallId);
@@ -3069,7 +3148,7 @@ function filterProtectedToolMessages(directMessageIds, messages, config) {
3069
3148
  for (const id of directMessageIds) {
3070
3149
  const msg = messages.find((m2) => m2.id === id);
3071
3150
  if (!msg) continue;
3072
- if (isMessageProtected(msg, config)) {
3151
+ if (isMessageProtected(msg, config) || isMessageLatestProtected(msg, latest)) {
3073
3152
  removedIds.add(id);
3074
3153
  if (msg.toolCallId) protectedCallIds.add(msg.toolCallId);
3075
3154
  }
@@ -3327,6 +3406,8 @@ function cloneState(state) {
3327
3406
  nudge: { ...state.nudge, anchors: { ...state.nudge.anchors } },
3328
3407
  stats: { ...state.stats },
3329
3408
  absorbed: (state.absorbed ?? []).map((record) => ({ ...record })),
3409
+ rules: (state.rules ?? []).map((rule) => ({ ...rule })),
3410
+ nextRuleId: state.nextRuleId,
3330
3411
  terminalStreak: state.terminalStreak,
3331
3412
  nextBlockId: state.nextBlockId,
3332
3413
  nextRunId: state.nextRunId
@@ -4395,6 +4476,17 @@ function matchSession(sessions, selector, labelOf) {
4395
4476
  if (byLabel.length > 0) return byLabel;
4396
4477
  return sessions.filter((s) => s.id.startsWith(selector) || (labelOf(s) ?? "").startsWith(selector));
4397
4478
  }
4479
+ var DEFAULT_RULE_LIMITS = Object.freeze({
4480
+ maxRules: 50,
4481
+ maxRuleChars: 300
4482
+ });
4483
+ var RULES_USAGE_PROMPT = [
4484
+ "Use the acp_rule tool to record short, principle-level reminders that must survive context compression:",
4485
+ "- behavioral corrections the user has had to repeat more than once,",
4486
+ "- project invariants the user explicitly asked you to remember,",
4487
+ "- pitfalls you ran into once and must not run into again.",
4488
+ "Rules are re-injected into the system prompt every turn. Omit the text argument to list recorded rules."
4489
+ ].join("\n");
4398
4490
  function parseCompressArgs(input, opts) {
4399
4491
  const callId = opts?.callId;
4400
4492
  const diag = { ok: false, kind: "ok", invalidItems: 0 };
@@ -4540,12 +4632,35 @@ function finishSalvage(entries, callId, diag, truncatedShape) {
4540
4632
  diag.kind = entries.length > 0 || truncatedShape ? "truncated" : "malformed-json";
4541
4633
  return finish(ranges, diag);
4542
4634
  }
4635
+ function coalesceLineEntries(entries) {
4636
+ const out = [];
4637
+ let headerOnlyIdx = -1;
4638
+ for (const e of entries) {
4639
+ if (typeof e === "string") {
4640
+ const nl = e.indexOf("\n");
4641
+ const head = (nl === -1 ? e : e.slice(0, nl)).trim();
4642
+ const hasRef = REF_PAIR_IN_LINE.test(head) || SINGLE_REF_IN_LINE.test(head);
4643
+ if (!hasRef && headerOnlyIdx >= 0) {
4644
+ out[headerOnlyIdx] = `${out[headerOnlyIdx]}
4645
+ ${e}`;
4646
+ continue;
4647
+ }
4648
+ out.push(e);
4649
+ headerOnlyIdx = hasRef && nl === -1 ? out.length - 1 : -1;
4650
+ } else {
4651
+ out.push(e);
4652
+ headerOnlyIdx = -1;
4653
+ }
4654
+ }
4655
+ return out;
4656
+ }
4543
4657
  function validateEntries(entries, callId) {
4544
4658
  const ranges = [];
4545
4659
  const reasons = [];
4546
4660
  let invalid = 0;
4547
- for (let i = 0; i < entries.length; i++) {
4548
- const outcome = validateEntry(entries[i], callId);
4661
+ const items = coalesceLineEntries(entries);
4662
+ for (let i = 0; i < items.length; i++) {
4663
+ const outcome = validateEntry(items[i], callId);
4549
4664
  if ("range" in outcome) ranges.push(outcome.range);
4550
4665
  else {
4551
4666
  invalid++;
@@ -6081,6 +6196,8 @@ function deriveChildState(parent) {
6081
6196
  nudge: fresh.nudge,
6082
6197
  stats: fresh.stats,
6083
6198
  absorbed: [],
6199
+ rules: structuredClone(parent.rules ?? []),
6200
+ nextRuleId: parent.nextRuleId ?? fresh.nextRuleId,
6084
6201
  nextBlockId: parent.nextBlockId,
6085
6202
  nextRunId: parent.nextRunId
6086
6203
  };
@@ -6101,6 +6218,10 @@ function mergeInitialState(parsed) {
6101
6218
  tokenSnapshot: parsed.tokenSnapshot ?? fresh.tokenSnapshot,
6102
6219
  nudge: { ...fresh.nudge, ...parsed.nudge ?? {} },
6103
6220
  stats: { ...fresh.stats, ...parsed.stats ?? {} },
6221
+ absorbed: parsed.absorbed ?? fresh.absorbed,
6222
+ rules: parsed.rules ?? fresh.rules,
6223
+ nextRuleId: parsed.nextRuleId ?? fresh.nextRuleId,
6224
+ ...parsed.terminalStreak !== void 0 ? { terminalStreak: parsed.terminalStreak } : {},
6104
6225
  nextBlockId: parsed.nextBlockId ?? fresh.nextBlockId,
6105
6226
  nextRunId: parsed.nextRunId ?? fresh.nextRunId
6106
6227
  };
@@ -11746,7 +11867,7 @@ function makeCompressTool(runtime, overrides) {
11746
11867
  }, overrides);
11747
11868
  }
11748
11869
  function normalizeRanges(args) {
11749
- const effective = repairContentTail(args);
11870
+ const effective = repairContentTail(repairBareRangeObjects(args));
11750
11871
  const { ranges, diagnostics } = parseCompressArgs(effective);
11751
11872
  if (ranges.length === 0) {
11752
11873
  if (Array.isArray(effective.content) && effective.content.length === 0) return [];
@@ -11771,6 +11892,67 @@ function tailRepair(s) {
11771
11892
  }
11772
11893
  return void 0;
11773
11894
  }
11895
+ function repairBareRangeObjects(args) {
11896
+ if (typeof args.content !== "string") return args;
11897
+ const repaired = arrayWrapRepair(args.content);
11898
+ return repaired === void 0 ? args : { ...args, content: repaired };
11899
+ }
11900
+ function arrayWrapRepair(s) {
11901
+ const objects = extractTopLevelObjects(s).map((candidate) => {
11902
+ try {
11903
+ return JSON.parse(candidate);
11904
+ } catch {
11905
+ return void 0;
11906
+ }
11907
+ }).filter((o) => isRangeLikeObject(o));
11908
+ if (objects.length === 0) return void 0;
11909
+ return JSON.stringify(objects);
11910
+ }
11911
+ function extractTopLevelObjects(s) {
11912
+ const out = [];
11913
+ let depth = 0;
11914
+ let inString = false;
11915
+ let escaped = false;
11916
+ let start = -1;
11917
+ for (let i = 0; i < s.length; i++) {
11918
+ const ch = s.charAt(i);
11919
+ if (inString) {
11920
+ if (escaped) escaped = false;
11921
+ else if (ch === "\\") escaped = true;
11922
+ else if (ch === '"') inString = false;
11923
+ continue;
11924
+ }
11925
+ if (ch === '"') {
11926
+ inString = true;
11927
+ continue;
11928
+ }
11929
+ if (ch === "{" || ch === "[") {
11930
+ if (depth === 0 && ch === "{" && start === -1) start = i;
11931
+ depth++;
11932
+ continue;
11933
+ }
11934
+ if (ch === "}" || ch === "]") {
11935
+ depth--;
11936
+ if (depth < 0) {
11937
+ depth = 0;
11938
+ start = -1;
11939
+ continue;
11940
+ }
11941
+ if (depth === 0 && start !== -1) {
11942
+ out.push(s.slice(start, i + 1));
11943
+ start = -1;
11944
+ }
11945
+ }
11946
+ }
11947
+ return out;
11948
+ }
11949
+ function isRangeLikeObject(o) {
11950
+ if (o === null || typeof o !== "object" || Array.isArray(o)) return false;
11951
+ const r = o;
11952
+ const hasStart = typeof r.startId === "string" || typeof r.startRef === "string" || typeof r.messageId === "string";
11953
+ const hasEnd = typeof r.endId === "string" || typeof r.endRef === "string" || typeof r.messageId === "string";
11954
+ return hasStart && hasEnd && typeof r.summary === "string" && r.summary.length > 0;
11955
+ }
11774
11956
  function describeDiagnostics(diagnostics, content) {
11775
11957
  const shape = typeof content === "string" ? "a JSON-encoded string (non-strict-tool providers stringify array arguments)" : content === null ? "null" : `a ${typeof content}`;
11776
11958
  const base = `Invalid compress content (${diagnostics.kind}): got ${shape}`;
@@ -12065,6 +12247,12 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
12065
12247
  const lines = [`\u25A3 ACP | ${formatK2(beforeTokens)} \u2192 ${formatK2(afterTokens)} tokens (~${formatK2(reclaimed)} reclaimed, ${spanClause})`];
12066
12248
  if (warnings.length > 0) lines.push("\u26A0\uFE0F " + warnings.join("; "));
12067
12249
  if (errors.length > 0) lines.push("Errors: " + errors.join("; "));
12250
+ if (blocksCreated > 0) {
12251
+ const afterSnapshot = compressibleSnapshotText(afterTurn.nudge);
12252
+ if (!afterSnapshot.startsWith("No compressible")) {
12253
+ lines.push("Current compressible ranges (use these refs exactly as listed):\n" + afterSnapshot);
12254
+ }
12255
+ }
12068
12256
  return lines.join("\n");
12069
12257
  }
12070
12258
 
@@ -12412,7 +12600,7 @@ function resolveActivePack(adapter, cwd, provider, modelId, resolver) {
12412
12600
  }
12413
12601
  var HOST_VERSION = (() => {
12414
12602
  try {
12415
- return "0.1.73";
12603
+ return "0.1.74";
12416
12604
  } catch {
12417
12605
  return "dev";
12418
12606
  }
@@ -19160,7 +19348,7 @@ async function statusReport(runtime, ctx) {
19160
19348
  const sentTokens = estimateTokens(coreMessages, coveredIds, imageTokens) + systemPromptTokens;
19161
19349
  const viewSentTokens = adjustedTokenCount(runtime.core, coreMessages, state, config, sentTokens, imageTokens, systemPromptTokens);
19162
19350
  const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: anchorStale ? viewSentTokens : Math.max(viewSentTokens, realUsage?.tokens ?? 0) });
19163
- const versionStr = "0.1.73" ? `billion-context-pi@${"0.1.73"} \xB7 pack: ${resolveSurfaceMeta(runtime.adapter, ctx?.cwd ?? process.cwd(), ctx?.model?.provider, ctx?.model?.id).pack}` : void 0;
19351
+ const versionStr = "0.1.74" ? `billion-context-pi@${"0.1.74"} \xB7 pack: ${resolveSurfaceMeta(runtime.adapter, ctx?.cwd ?? process.cwd(), ctx?.model?.provider, ctx?.model?.id).pack}` : void 0;
19164
19352
  let text = buildStatusPanel({
19165
19353
  version: versionStr,
19166
19354
  tokenCount: sessionTokens,
@@ -19860,7 +20048,7 @@ async function autoInstallLatest(latest, extDirOverride) {
19860
20048
  "--no-fund",
19861
20049
  "--no-save"
19862
20050
  ];
19863
- const prevVersion = (await readPackageJson(join15(extDir, "package.json")))?.version ?? "0.1.73";
20051
+ const prevVersion = (await readPackageJson(join15(extDir, "package.json")))?.version ?? "0.1.74";
19864
20052
  const { code, stderr } = await runNpmImpl(installArgs(latest), { cwd: npmDir, timeout: 6e4 });
19865
20053
  if (code !== 0) {
19866
20054
  logWarn("update", {
@@ -19878,7 +20066,7 @@ async function autoInstallLatest(latest, extDirOverride) {
19878
20066
  }
19879
20067
  const verify = await verifyInstall(npmDir, latest);
19880
20068
  if (!verify.ok) {
19881
- const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.73";
20069
+ const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.74";
19882
20070
  logWarn("update", { event: "auto-install-verify-failed", latest, reason: verify.reason, rollbackTo });
19883
20071
  const rb = await runNpmImpl(installArgs(rollbackTo), { cwd: npmDir, timeout: 6e4 });
19884
20072
  logInfo("update", { event: "rollback", from: latest, to: rollbackTo, ok: rb.code === 0 });
@@ -19953,7 +20141,7 @@ async function checkForUpdate(autoUpdate, notify) {
19953
20141
  }
19954
20142
  const latest = await fetchLatestVersion(tag);
19955
20143
  if (!latest) return;
19956
- const current = runtimeVersion ?? "0.1.73";
20144
+ const current = runtimeVersion ?? "0.1.74";
19957
20145
  const hasUpdate = isVersionNewer(latest, current);
19958
20146
  debug.event("update-check", {
19959
20147
  current,
@@ -20155,7 +20343,7 @@ function wireSessionLifecycle(pi, runtime, standDownIfProxied) {
20155
20343
  setDelegatePolicy(DEFAULT_DELEGATE_POLICY);
20156
20344
  const sid = ctx.sessionManager.getSessionId();
20157
20345
  const modelInfo = ctx.model;
20158
- logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.73" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
20346
+ logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.74" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
20159
20347
  let delegateStoodDown = false;
20160
20348
  try {
20161
20349
  await runtime.reloadConfig(ctx.cwd);