billion-context-pi 0.1.72 → 0.1.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
@@ -14,7 +14,7 @@ import { readFileSync as readFileSync6 } from "fs";
14
14
  import { homedir as homedir10 } from "os";
15
15
  import { join as join16 } from "path";
16
16
 
17
- // node_modules/acp-kernel/dist/chunk-QPVKTDYF.js
17
+ // node_modules/acp-kernel/dist/chunk-VPRKYTHW.js
18
18
  import { createRequire } from "module";
19
19
  var require2 = createRequire(import.meta.url);
20
20
  function defaultCountTokens(text) {
@@ -227,6 +227,8 @@ function formatRanges(compressible, protectedRanges) {
227
227
  endRef: r.endRef,
228
228
  startNum: refNum3(r.startRef),
229
229
  endNum: refNum3(r.endRef),
230
+ startPos: r.startIndex ?? refNum3(r.startRef),
231
+ endPos: r.endIndex ?? refNum3(r.endRef),
230
232
  count: r.count,
231
233
  tokens: r.tokens,
232
234
  userMsgs: r.userMsgs ?? 0,
@@ -246,6 +248,8 @@ function formatRanges(compressible, protectedRanges) {
246
248
  endRef: r.endRef,
247
249
  startNum: refNum3(r.startRef),
248
250
  endNum: refNum3(r.endRef),
251
+ startPos: r.startIndex ?? refNum3(r.startRef),
252
+ endPos: r.endIndex ?? refNum3(r.endRef),
249
253
  count: r.count,
250
254
  tokens: r.tokens,
251
255
  userMsgs: 0,
@@ -259,13 +263,14 @@ function formatRanges(compressible, protectedRanges) {
259
263
  dangerous: false
260
264
  });
261
265
  }
262
- entries.sort((a, b2) => a.startNum - b2.startNum);
266
+ entries.sort((a, b2) => a.startPos - b2.startPos || a.startNum - b2.startNum);
263
267
  const merged = [];
264
268
  for (const e of entries) {
265
269
  const last = merged[merged.length - 1];
266
- if (last && e.startNum <= last.endNum + 1) {
270
+ if (last && e.startPos <= last.endPos + 1) {
267
271
  last.endRef = e.endRef;
268
272
  last.endNum = Math.max(last.endNum, e.endNum);
273
+ last.endPos = Math.max(last.endPos, e.endPos);
269
274
  last.count += e.count;
270
275
  last.tokens += e.tokens;
271
276
  last.userMsgs += e.userMsgs;
@@ -1519,7 +1524,7 @@ var ACP_STATUS_TOOL_OPENAI = {
1519
1524
  }
1520
1525
  }
1521
1526
  };
1522
- var ACP_CACHE_TOOL_DESCRIPTION = "Prompt-cache reconciliation: grand ledger (total input/cached/output, overall hit rate) with every request's miss split into new content / compression re-pay / TTL expiry, plus per-fold economics (breakeven turns vs measured cadence). Read-only. Call when asked about cache hits, cache invalidation, or what compression costs.";
1527
+ var ACP_CACHE_TOOL_DESCRIPTION = `Prompt-cache reconciliation: grand ledger (total input/cached/output, overall hit rate) with every request's miss split into new content / compression re-pay / TTL expiry, plus per-fold economics (breakeven turns vs measured cadence). Defaults to a compact summary (totals + verdicts + anomalies only); pass detail="full" for every fold and line item. Read-only. Call when asked about cache hits, cache invalidation, or what compression costs.`;
1523
1528
  var ACP_CACHE_TOOL_OPENAI = {
1524
1529
  type: "function",
1525
1530
  function: {
@@ -1527,7 +1532,13 @@ var ACP_CACHE_TOOL_OPENAI = {
1527
1532
  description: ACP_CACHE_TOOL_DESCRIPTION,
1528
1533
  parameters: {
1529
1534
  type: "object",
1530
- properties: {}
1535
+ properties: {
1536
+ detail: {
1537
+ type: "string",
1538
+ enum: ["summary", "full"],
1539
+ description: '"summary" (default): totals, verdicts, notable folds, anomalous requests only. "full": every retained fold and line item.'
1540
+ }
1541
+ }
1531
1542
  }
1532
1543
  }
1533
1544
  };
@@ -1588,6 +1599,62 @@ var ACP_TOOL_NAMES = /* @__PURE__ */ new Set([
1588
1599
  ACP_STATUS_TOOL_NAME,
1589
1600
  ACP_CACHE_TOOL_NAME
1590
1601
  ]);
1602
+ var COMPRESS_TOOL_GOOGLE = {
1603
+ name: COMPRESS_TOOL_NAME,
1604
+ description: COMPRESS_TOOL.description,
1605
+ // `anyOf` is rejected by older API revisions, so `content` declares the
1606
+ // object form; a JSON-encoded string of that array is still accepted by
1607
+ // parseCompressInput, and the line form (a summary whose first line is
1608
+ // 'm00150–m00220 optional topic') is documented in the description.
1609
+ parameters: {
1610
+ type: "object",
1611
+ properties: {
1612
+ topic: {
1613
+ type: "string",
1614
+ description: "Optional short title for the compressed range"
1615
+ },
1616
+ content: {
1617
+ type: "array",
1618
+ description: "One or more ranges to compress into separate summary blocks. Object form: {startId,endId,summary,topic?}. A JSON-encoded string of that array is also accepted; in the line form the summary begins with its own first line 'm00150\u2013m00220 optional topic', the rest being the summary markdown verbatim. REQUIRED \u2014 compress without content is invalid.",
1619
+ items: {
1620
+ type: "object",
1621
+ properties: {
1622
+ topic: { type: "string" },
1623
+ startId: {
1624
+ type: "string",
1625
+ description: "mNNNNN ref at the start of the range"
1626
+ },
1627
+ endId: {
1628
+ type: "string",
1629
+ description: "mNNNNN ref at the end of the range"
1630
+ },
1631
+ summary: {
1632
+ type: "string",
1633
+ description: "Self-contained summary replacing the range"
1634
+ }
1635
+ },
1636
+ required: ["startId", "endId", "summary"]
1637
+ }
1638
+ }
1639
+ },
1640
+ required: ["content"]
1641
+ }
1642
+ };
1643
+ var DECOMPRESS_TOOL_GOOGLE = {
1644
+ name: DECOMPRESS_TOOL_NAME,
1645
+ description: DECOMPRESS_TOOL_OPENAI.function.description,
1646
+ parameters: DECOMPRESS_TOOL_OPENAI.function.parameters
1647
+ };
1648
+ var SEARCH_CONTEXT_TOOL_GOOGLE = {
1649
+ name: SEARCH_CONTEXT_TOOL_NAME,
1650
+ description: SEARCH_CONTEXT_TOOL_OPENAI.function.description,
1651
+ parameters: SEARCH_CONTEXT_TOOL_OPENAI.function.parameters
1652
+ };
1653
+ var ACP_STATUS_TOOL_GOOGLE = {
1654
+ name: ACP_STATUS_TOOL_NAME,
1655
+ description: ACP_STATUS_TOOL_OPENAI.function.description,
1656
+ parameters: ACP_STATUS_TOOL_OPENAI.function.parameters
1657
+ };
1591
1658
  var ALWAYS_PROTECTED_TOOLS = ["compress"];
1592
1659
  var NEVER_PRESERVE_RECENT_TOOLS = [
1593
1660
  "decompress",
@@ -2012,6 +2079,73 @@ function computeTurnGroups(messages) {
2012
2079
  }
2013
2080
  return groups;
2014
2081
  }
2082
+ function computeIntegrityWithdrawals(messages, foldedIds) {
2083
+ const remaining = new Set(foldedIds);
2084
+ const withdrawn = /* @__PURE__ */ new Set();
2085
+ const handledTurns = /* @__PURE__ */ new Set();
2086
+ const handledPairs = /* @__PURE__ */ new Set();
2087
+ const reasoningIds = /* @__PURE__ */ new Set();
2088
+ const callIds = /* @__PURE__ */ new Set();
2089
+ const callIdByMessageId = /* @__PURE__ */ new Map();
2090
+ const resultIdByCallId = /* @__PURE__ */ new Map();
2091
+ for (const m2 of messages) {
2092
+ if (!m2.id) continue;
2093
+ if (m2.contentType === "reasoning") reasoningIds.add(m2.id);
2094
+ if (m2.role === "assistant" && m2.contentType === "tool-call") {
2095
+ callIds.add(m2.id);
2096
+ if (typeof m2.toolCallId === "string") {
2097
+ callIdByMessageId.set(m2.id, m2.toolCallId);
2098
+ }
2099
+ }
2100
+ if (m2.contentType === "tool-result" && typeof m2.toolCallId === "string") {
2101
+ if (!resultIdByCallId.has(m2.toolCallId)) {
2102
+ resultIdByCallId.set(m2.toolCallId, m2.id);
2103
+ }
2104
+ }
2105
+ }
2106
+ const groups = computeTurnGroups(messages);
2107
+ let changed = true;
2108
+ while (changed) {
2109
+ changed = false;
2110
+ for (let g2 = 0; g2 < groups.length; g2++) {
2111
+ if (handledTurns.has(g2)) continue;
2112
+ const group = groups[g2];
2113
+ const foldHasReasoning = group.some(
2114
+ (id) => remaining.has(id) && reasoningIds.has(id)
2115
+ );
2116
+ if (!foldHasReasoning) continue;
2117
+ const keptHasCall = group.some(
2118
+ (id) => !remaining.has(id) && callIds.has(id)
2119
+ );
2120
+ if (!keptHasCall) continue;
2121
+ handledTurns.add(g2);
2122
+ for (const id of group) {
2123
+ remaining.delete(id);
2124
+ withdrawn.add(id);
2125
+ }
2126
+ changed = true;
2127
+ }
2128
+ for (const m2 of messages) {
2129
+ if (!m2.id || !callIds.has(m2.id)) continue;
2130
+ const callId = callIdByMessageId.get(m2.id);
2131
+ if (callId === void 0 || handledPairs.has(callId)) continue;
2132
+ const resultId = resultIdByCallId.get(callId);
2133
+ if (resultId === void 0) continue;
2134
+ if (remaining.has(m2.id) === remaining.has(resultId)) continue;
2135
+ handledPairs.add(callId);
2136
+ remaining.delete(m2.id);
2137
+ remaining.delete(resultId);
2138
+ withdrawn.add(m2.id);
2139
+ withdrawn.add(resultId);
2140
+ changed = true;
2141
+ }
2142
+ }
2143
+ return {
2144
+ withdrawn,
2145
+ splitTurnCount: handledTurns.size,
2146
+ splitPairCount: handledPairs.size
2147
+ };
2148
+ }
2015
2149
  function estimateTextTokens(text) {
2016
2150
  return Math.ceil(text.length / 4);
2017
2151
  }
@@ -2061,12 +2195,14 @@ function computeProtectedRefs(messages, state, config, countTokens = estimateTex
2061
2195
  return result;
2062
2196
  }
2063
2197
  function buildCompressibleRanges(messages, state, config, protectedZoneRefs, countTokens = estimateTextTokens) {
2064
- const compressibleMsgs = [];
2198
+ let compressibleMsgs = [];
2065
2199
  const protectedMsgs = [];
2066
2200
  const protectedCallIds = collectProtectedToolCallIds(messages, config);
2067
2201
  let skipSinceCompressible = false;
2068
2202
  let skipSinceProtected = false;
2203
+ let msgIndex = -1;
2069
2204
  for (const msg of messages) {
2205
+ msgIndex++;
2070
2206
  const ref = state.messageRefs.byRaw[msg.id];
2071
2207
  if (!ref || ref === "BLOCKED") continue;
2072
2208
  if (isSyntheticOrPruned(msg, state)) {
@@ -2079,7 +2215,8 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
2079
2215
  ref,
2080
2216
  gapBefore: skipSinceProtected,
2081
2217
  tokens: countMessageTokens(msg, countTokens),
2082
- tools: msg.toolName ? [msg.toolName] : []
2218
+ tools: msg.toolName ? [msg.toolName] : [],
2219
+ index: msgIndex
2083
2220
  });
2084
2221
  skipSinceProtected = false;
2085
2222
  skipSinceCompressible = true;
@@ -2091,16 +2228,35 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
2091
2228
  continue;
2092
2229
  }
2093
2230
  compressibleMsgs.push({
2231
+ id: msg.id,
2094
2232
  ref,
2095
2233
  gapBefore: skipSinceCompressible,
2096
2234
  tokens: countMessageTokens(msg, countTokens),
2097
2235
  chars: (msg.text ?? "").length,
2098
2236
  isTool: isToolMessage(msg),
2099
- isUser: msg.role === "user"
2237
+ isUser: msg.role === "user",
2238
+ index: msgIndex
2100
2239
  });
2101
2240
  skipSinceCompressible = false;
2102
2241
  skipSinceProtected = true;
2103
2242
  }
2243
+ const unfoldedIds = computeIntegrityWithdrawals(
2244
+ messages,
2245
+ new Set(compressibleMsgs.map((info) => info.id))
2246
+ ).withdrawn;
2247
+ if (unfoldedIds.size > 0) {
2248
+ let gapPending = false;
2249
+ const kept = [];
2250
+ for (const info of compressibleMsgs) {
2251
+ if (unfoldedIds.has(info.id)) {
2252
+ gapPending = true;
2253
+ continue;
2254
+ }
2255
+ kept.push(gapPending ? { ...info, gapBefore: true } : info);
2256
+ gapPending = false;
2257
+ }
2258
+ compressibleMsgs = kept;
2259
+ }
2104
2260
  const compressible = [];
2105
2261
  let cur = null;
2106
2262
  for (const info of compressibleMsgs) {
@@ -2117,10 +2273,13 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
2117
2273
  chars: info.chars,
2118
2274
  toolPct: info.isTool ? 100 : 0,
2119
2275
  textPct: info.isTool ? 0 : 100,
2120
- userMsgs: info.isUser ? 1 : 0
2276
+ userMsgs: info.isUser ? 1 : 0,
2277
+ startIndex: info.index,
2278
+ endIndex: info.index
2121
2279
  };
2122
2280
  } else {
2123
2281
  cur.endRef = info.ref;
2282
+ cur.endIndex = info.index;
2124
2283
  cur.count++;
2125
2284
  cur.tokens += info.tokens;
2126
2285
  cur.chars = (cur.chars ?? 0) + info.chars;
@@ -2147,10 +2306,13 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
2147
2306
  endRef: info.ref,
2148
2307
  count: 1,
2149
2308
  tokens: info.tokens,
2150
- tools: [...info.tools]
2309
+ tools: [...info.tools],
2310
+ startIndex: info.index,
2311
+ endIndex: info.index
2151
2312
  };
2152
2313
  } else {
2153
2314
  pcur.endRef = info.ref;
2315
+ pcur.endIndex = info.index;
2154
2316
  pcur.count++;
2155
2317
  pcur.tokens += info.tokens;
2156
2318
  for (const t of info.tools) {
@@ -2183,6 +2345,10 @@ function mergeBatch(batch) {
2183
2345
  textPct: 100 - toolPct,
2184
2346
  userMsgs: batch.reduce((s, r) => s + (r.userMsgs ?? 0), 0)
2185
2347
  };
2348
+ if (first.startIndex !== void 0 && last.endIndex !== void 0) {
2349
+ merged.startIndex = Math.min(...batch.map((r) => r.startIndex ?? Infinity));
2350
+ merged.endIndex = Math.max(...batch.map((r) => r.endIndex ?? -Infinity));
2351
+ }
2186
2352
  if (batch.some((r) => r.dangerous === true)) {
2187
2353
  merged.dangerous = true;
2188
2354
  }
@@ -2765,49 +2931,11 @@ function applySingleRange(input) {
2765
2931
  );
2766
2932
  }
2767
2933
  {
2768
- const reasoningIds = /* @__PURE__ */ new Set();
2769
- const callIds = /* @__PURE__ */ new Set();
2770
- for (const m2 of input.messages) {
2771
- if (!m2.id) continue;
2772
- if (m2.contentType === "reasoning") reasoningIds.add(m2.id);
2773
- if (m2.role === "assistant" && m2.contentType === "tool-call")
2774
- callIds.add(m2.id);
2775
- }
2776
- const withdrawIds = /* @__PURE__ */ new Set();
2777
- let splitTurnCount = 0;
2778
- for (const group of computeTurnGroups(input.messages)) {
2779
- const foldHasReasoning = group.some(
2780
- (id) => effectiveMessageIds.has(id) && reasoningIds.has(id)
2781
- );
2782
- if (!foldHasReasoning) continue;
2783
- const keptHasCall = group.some(
2784
- (id) => !effectiveMessageIds.has(id) && callIds.has(id)
2785
- );
2786
- if (!keptHasCall) continue;
2787
- splitTurnCount++;
2788
- for (const id of group) withdrawIds.add(id);
2789
- }
2790
- const resultIdByCallId = /* @__PURE__ */ new Map();
2791
- for (const m2 of input.messages) {
2792
- if (!m2.id || m2.contentType !== "tool-result") continue;
2793
- if (typeof m2.toolCallId !== "string") continue;
2794
- if (!resultIdByCallId.has(m2.toolCallId)) {
2795
- resultIdByCallId.set(m2.toolCallId, m2.id);
2796
- }
2797
- }
2798
- let splitPairCount = 0;
2799
- for (const m2 of input.messages) {
2800
- if (!m2.id || m2.contentType !== "tool-call") continue;
2801
- if (typeof m2.toolCallId !== "string") continue;
2802
- const resultId = resultIdByCallId.get(m2.toolCallId);
2803
- if (resultId === void 0) continue;
2804
- if (effectiveMessageIds.has(m2.id) === effectiveMessageIds.has(resultId)) {
2805
- continue;
2806
- }
2807
- withdrawIds.add(m2.id);
2808
- withdrawIds.add(resultId);
2809
- splitPairCount++;
2810
- }
2934
+ const {
2935
+ withdrawn: withdrawIds,
2936
+ splitTurnCount,
2937
+ splitPairCount
2938
+ } = computeIntegrityWithdrawals(input.messages, effectiveMessageIds);
2811
2939
  if (withdrawIds.size > 0) {
2812
2940
  for (const id of withdrawIds) effectiveMessageIds.delete(id);
2813
2941
  const beforeWithdraw = filteredIds.length;
@@ -3972,13 +4100,35 @@ function fmtTime(at) {
3972
4100
  const p = (x2) => String(x2).padStart(2, "0");
3973
4101
  return `${p(d2.getHours())}:${p(d2.getMinutes())}:${p(d2.getSeconds())}`;
3974
4102
  }
3975
- function formatCacheReport(report, sessionLabel) {
4103
+ var HIT_HEALTHY_PCT = 90;
4104
+ var HIT_WATCH_PCT = 70;
4105
+ var ANOMALY_HIT_PCT = 85;
4106
+ var ANOMALY_MISS_TOK = 5e3;
4107
+ var TTL_SPIKE_TOK = 1e4;
4108
+ var SUMMARY_FOLD_TOPS = 3;
4109
+ var SUMMARY_ANOMALY_CAP = 20;
4110
+ function hitVerdict(pct2) {
4111
+ if (pct2 >= HIT_HEALTHY_PCT) return "HEALTHY";
4112
+ if (pct2 >= HIT_WATCH_PCT) return "WATCH";
4113
+ return "INVESTIGATE";
4114
+ }
4115
+ function medianHitPct(lines) {
4116
+ if (lines.length === 0) return null;
4117
+ const xs = lines.map((l3) => l3.hitPct).sort((a, b2) => a - b2);
4118
+ return xs[Math.floor(xs.length / 2)] ?? null;
4119
+ }
4120
+ function fmtIdleGap(ms) {
4121
+ if (ms < 9e4) return `${Math.max(1, Math.round(ms / 1e3))}s`;
4122
+ if (ms < 90 * 6e4) return `${Math.round(ms / 6e4)}m`;
4123
+ if (ms < 36 * 36e5) return `${(ms / 36e5).toFixed(1)}h`;
4124
+ return `${(ms / 864e5).toFixed(1)}d`;
4125
+ }
4126
+ function foldVerdict(f) {
4127
+ return f.paidBack === null ? "?" : f.paidBack ? "PAID BACK" : "NOT PAID BACK";
4128
+ }
4129
+ function formatCacheReportFull(report) {
3976
4130
  const t = report.totals;
3977
4131
  const out = [];
3978
- out.push(
3979
- `ACP CACHE REPORT${sessionLabel ? ` (${sessionLabel})` : ""} \u2014 ${t.requests} requests`
3980
- );
3981
- out.push("");
3982
4132
  out.push("GRAND LEDGER");
3983
4133
  out.push(` total input ${fmtTok(t.input)} tok`);
3984
4134
  out.push(
@@ -4038,6 +4188,145 @@ function formatCacheReport(report, sessionLabel) {
4038
4188
  }
4039
4189
  return out.join("\n");
4040
4190
  }
4191
+ function formatCacheReportSummary(report) {
4192
+ const t = report.totals;
4193
+ const out = [];
4194
+ out.push("GRAND LEDGER");
4195
+ out.push(` total input ${fmtTok(t.input)} tok`);
4196
+ out.push(
4197
+ ` total cached ${fmtTok(t.cached)} tok (hit ${t.hitPct.toFixed(1)}% \u2192 ${hitVerdict(t.hitPct)})`
4198
+ );
4199
+ out.push(` total output ${fmtTok(t.output)} tok`);
4200
+ out.push(
4201
+ ` miss breakdown (input \u2212 cached = ${fmtTok(Math.max(0, t.input - t.cached))} tok):`
4202
+ );
4203
+ const avgNew = t.requests > 0 ? t.newContent / t.requests : 0;
4204
+ out.push(
4205
+ ` new content ${fmtTok(t.newContent)} tok (~${fmtTok(avgNew)}/req fresh append \u2014 not an invalidation)`
4206
+ );
4207
+ out.push(
4208
+ ` compress re-pay ${fmtTok(t.compRepay)} tok (${report.economics.folds} folds \u2014 re-billed prefix)`
4209
+ );
4210
+ const spikeIdx = [];
4211
+ report.lines.forEach((l3, i) => {
4212
+ if (l3.ttlRepay >= TTL_SPIKE_TOK) spikeIdx.push(i);
4213
+ });
4214
+ const spikes = [...spikeIdx].sort(
4215
+ (a, b2) => (report.lines[b2]?.ttlRepay ?? 0) - (report.lines[a]?.ttlRepay ?? 0)
4216
+ ).slice(0, SUMMARY_FOLD_TOPS).sort((a, b2) => a - b2);
4217
+ const spikeText = spikes.map((i) => {
4218
+ const l3 = report.lines[i];
4219
+ if (!l3) return "";
4220
+ let idle = "";
4221
+ const prev = report.lines[i - 1];
4222
+ if (prev && l3.at > prev.at) idle = `, idle ${fmtIdleGap(l3.at - prev.at)}`;
4223
+ return `#${l3.seq} ${fmtTok(l3.ttlRepay)}${idle}`;
4224
+ }).join(" \xB7 ");
4225
+ out.push(
4226
+ ` ttl/other ${fmtTok(t.ttlRepay)} tok (stable-prefix misses: TTL expiry / eviction${spikeText ? `; top spikes: ${spikeText}` : ""})`
4227
+ );
4228
+ out.push(
4229
+ ` identity check ${t.balanced ? "OK" : "BROKEN"} \u2014 ${fmtTok(t.input)} = ${fmtTok(t.cached)} + ${fmtTok(t.newContent)} + ${fmtTok(t.compRepay)} + ${fmtTok(t.ttlRepay)} (residual ${t.residual})`
4230
+ );
4231
+ const e = report.economics;
4232
+ if (e.folds > 0) {
4233
+ const p = report.profile;
4234
+ out.push("");
4235
+ out.push(`FOLD ECONOMICS (${e.folds} folds @ w=${p.w} r=${p.r} q=${p.q})`);
4236
+ out.push(
4237
+ ` gross saved ${fmtTok(e.grossSaved)} tok \xB7 repay cost ${fmtTok(e.repayCost)} tok \xB7 summary cost ${fmtTok(e.summaryCost)} tok \u2192 net ${e.netTokens >= 0 ? "+" : ""}${fmtTok(e.netTokens)} tok`
4238
+ );
4239
+ out.push(
4240
+ ` verdict: ${e.paidBackCount} PAID BACK / ${e.notPaidBackCount} NOT PAID BACK / ${e.unobservedCount} unobserved`
4241
+ );
4242
+ if (e.notPaidBackCount > 0)
4243
+ out.push(
4244
+ ` NOT PAID BACK = measured post-fold cadence never reached n* (end-of-session / back-to-back folds \u2014 one-time cost, not data loss)`
4245
+ );
4246
+ if (report.folds.length <= SUMMARY_FOLD_TOPS * 2) {
4247
+ for (const f of report.folds) {
4248
+ const nstar = f.breakevenTurns === null ? "n/a" : f.breakevenTurns.toFixed(1);
4249
+ const k = f.turnsToNextFold === null ? "\u2014" : String(f.turnsToNextFold);
4250
+ const h = f.hPct === null ? "n/a" : `${f.hPct.toFixed(1)}%`;
4251
+ out.push(
4252
+ ` #${f.seq} ${fmtTime(f.at)} S=${fmtTok(f.S)} \u03C3=${fmtTok(f.sigma)} h=${h} T=${fmtTok(f.T)} \u0394C\u2081=${fmtTok(f.oneTimeCostUnits)} \u0394s=${fmtTok(f.perTurnSavingUnits)}/turn n*=${nstar} k=${k} \u2192 ${foldVerdict(f)}`
4253
+ );
4254
+ }
4255
+ } else {
4256
+ const largest = [...report.folds].sort((a, b2) => b2.S - a.S).slice(0, SUMMARY_FOLD_TOPS);
4257
+ const worst = [...report.folds].sort((a, b2) => b2.oneTimeCostUnits - a.oneTimeCostUnits).slice(0, SUMMARY_FOLD_TOPS);
4258
+ out.push(
4259
+ ` largest folds: ${largest.map((f) => `#${f.seq} S=${fmtTok(f.S)} ${foldVerdict(f)}`).join(" \xB7 ")}`
4260
+ );
4261
+ out.push(
4262
+ ` worst one-time: ${worst.map((f) => `#${f.seq} \u0394C\u2081=${fmtTok(f.oneTimeCostUnits)} (${foldVerdict(f)}${f.turnsToNextFold !== null ? `, k=${f.turnsToNextFold}` : ""})`).join(" \xB7 ")}`
4263
+ );
4264
+ const shown = /* @__PURE__ */ new Set([...largest, ...worst]);
4265
+ if (report.folds.length > shown.size)
4266
+ out.push(
4267
+ ` \u2192 ${report.folds.length - shown.size} more folds omitted (detail:"full" lists every fold)`
4268
+ );
4269
+ }
4270
+ }
4271
+ if (report.lines.length > 0) {
4272
+ out.push("");
4273
+ const shownIdx = [];
4274
+ report.lines.forEach((l3, i) => {
4275
+ if (l3.hitPct < ANOMALY_HIT_PCT || l3.missed >= ANOMALY_MISS_TOK)
4276
+ shownIdx.push(i);
4277
+ });
4278
+ const last = report.lines.length - 1;
4279
+ if (!shownIdx.includes(last)) shownIdx.push(last);
4280
+ const kept = shownIdx.slice(Math.max(0, shownIdx.length - SUMMARY_ANOMALY_CAP));
4281
+ const anomalies = kept.filter((i) => {
4282
+ const l3 = report.lines[i];
4283
+ if (!l3) return false;
4284
+ return l3.hitPct < ANOMALY_HIT_PCT || l3.missed >= ANOMALY_MISS_TOK;
4285
+ }).length;
4286
+ if (anomalies === 0) {
4287
+ const med = medianHitPct(report.lines);
4288
+ out.push(
4289
+ `LINE ITEMS \u2014 no anomalies (${report.lines.length} requests, median hit ${med !== null ? med.toFixed(1) : "n/a"}%${report.linesOmitted > 0 ? `, ${report.linesOmitted} older outside window` : ""})`
4290
+ );
4291
+ } else {
4292
+ out.push(
4293
+ `LINE ITEMS (anomalies: hit<${ANOMALY_HIT_PCT}% or miss\u2265${fmtTok(ANOMALY_MISS_TOK)}):`
4294
+ );
4295
+ out.push(
4296
+ " # time input cached hit% new comp ttl fold"
4297
+ );
4298
+ for (const i of kept) {
4299
+ const l3 = report.lines[i];
4300
+ if (!l3) continue;
4301
+ const fold = l3.foldSeq !== null ? `#${l3.foldSeq}` : "";
4302
+ out.push(
4303
+ ` ${String(l3.seq).padStart(4)} ${fmtTime(l3.at)} ${fmtTok(l3.input).padStart(7)} ${fmtTok(l3.cached).padStart(7)} ${l3.hitPct.toFixed(1).padStart(5)}% ${fmtTok(l3.newContent).padStart(6)} ${fmtTok(l3.compRepay).padStart(6)} ${fmtTok(l3.ttlRepay).padStart(6)} ${fold}`
4304
+ );
4305
+ }
4306
+ const omitted = report.lines.length - kept.length;
4307
+ if (omitted > 0) {
4308
+ const rest = report.lines.filter((_2, i) => !kept.includes(i));
4309
+ const med = medianHitPct(rest);
4310
+ out.push(
4311
+ ` \u2026 ${omitted} lines omitted (median hit ${med !== null ? med.toFixed(1) : "n/a"}%${report.linesOmitted > 0 ? `, ${report.linesOmitted} older outside window` : ""} \u2014 detail:"full" lists all)`
4312
+ );
4313
+ }
4314
+ }
4315
+ }
4316
+ return out.join("\n");
4317
+ }
4318
+ function formatCacheReport(report, sessionLabel, opts) {
4319
+ const t = report.totals;
4320
+ const header = `ACP CACHE REPORT${sessionLabel ? ` (${sessionLabel})` : ""} \u2014 ${t.requests} requests`;
4321
+ if (opts?.detail === "full") {
4322
+ return [header, "", formatCacheReportFull(report)].join("\n");
4323
+ }
4324
+ return [
4325
+ header + ` [summary \u2014 detail:"full" for every fold & line]`,
4326
+ "",
4327
+ formatCacheReportSummary(report)
4328
+ ].join("\n");
4329
+ }
4041
4330
  function renderMessage2(m2) {
4042
4331
  const parts = [];
4043
4332
  switch (m2.contentType) {
@@ -12123,7 +12412,7 @@ function resolveActivePack(adapter, cwd, provider, modelId, resolver) {
12123
12412
  }
12124
12413
  var HOST_VERSION = (() => {
12125
12414
  try {
12126
- return "0.1.72";
12415
+ return "0.1.73";
12127
12416
  } catch {
12128
12417
  return "dev";
12129
12418
  }
@@ -14172,7 +14461,9 @@ ${extra.join("\n")}` : base;
14172
14461
  }
14173
14462
 
14174
14463
  // src/cache-tool.ts
14175
- var CacheParams = typebox_exports.Object({});
14464
+ var CacheParams = typebox_exports.Object({
14465
+ detail: typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("summary"), typebox_exports.Literal("full")], { description: '"summary" (default): totals, verdicts, notable folds, anomalous requests only. "full": every retained fold and line item.' }))
14466
+ });
14176
14467
  var num = (v2) => typeof v2 === "number" && Number.isFinite(v2) && v2 > 0 ? v2 : 0;
14177
14468
  var refNum2 = (ref) => Number(ref.replace(/\D/g, "")) || 0;
14178
14469
  function cacheSamples(entries) {
@@ -14207,26 +14498,26 @@ function foldEvents(state) {
14207
14498
  firstFoldStartTokens: prefixBefore(b2.startRef)
14208
14499
  }));
14209
14500
  }
14210
- async function cacheReportText(runtime, ctx) {
14501
+ async function cacheReportText(runtime, ctx, detail = "summary") {
14211
14502
  const { state, entries } = await runtime.stateFor(ctx);
14212
14503
  const report = buildCacheReport(cacheSamples(entries), foldEvents(state));
14213
- return formatCacheReport(report, ctx.sessionManager.getSessionId());
14504
+ return formatCacheReport(report, ctx.sessionManager.getSessionId(), { detail });
14214
14505
  }
14215
14506
  function makeCacheTool(runtime, overrides) {
14216
14507
  return applyToolPromptOverrides({
14217
14508
  name: "acp_cache",
14218
14509
  label: "ACP Cache Report",
14219
- description: "Prompt-cache reconciliation: grand ledger (total input/cached/output, session hit rate) with every request's miss split into new content / compression re-pay / TTL expiry, plus per-fold economics (one-time cost, breakeven turns vs measured cadence). Read-only.",
14510
+ description: `Prompt-cache reconciliation: grand ledger (total input/cached/output, session hit rate) with every request's miss split into new content / compression re-pay / TTL expiry, plus per-fold economics (one-time cost, breakeven turns vs measured cadence). Defaults to a compact summary (totals + verdicts + anomalies only); pass detail="full" for every fold and line item. Read-only.`,
14220
14511
  promptSnippet: "acp_cache({})",
14221
14512
  promptGuidelines: [
14222
14513
  "Call when asked about cache hits, cache invalidation, or what compression costs.",
14223
14514
  "Read-only: reports numbers, never mutates context."
14224
14515
  ],
14225
14516
  parameters: CacheParams,
14226
- async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
14517
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
14227
14518
  if (runtime.refused) return { details: void 0, content: [{ type: "text", text: runtime.refusalMessage ?? UNSUPPORTED_HOST_MESSAGE }] };
14228
14519
  try {
14229
- const text = await cacheReportText(runtime, ctx);
14520
+ const text = await cacheReportText(runtime, ctx, params.detail === "full" ? "full" : "summary");
14230
14521
  return { details: void 0, content: [{ type: "text", text }] };
14231
14522
  } catch (e) {
14232
14523
  logThrow("cache", e, { sid: ctx.sessionManager.getSessionId() });
@@ -18714,11 +19005,12 @@ function makeCommands(runtime, pi) {
18714
19005
  {
18715
19006
  name: "acp-cache",
18716
19007
  options: {
18717
- description: "Prompt-cache reconciliation: grand ledger (input/cached/hit rate) with every request's miss split into new content / compression re-pay / TTL expiry, plus per-fold economics.",
18718
- handler: async (_args, ctx) => {
19008
+ description: "Prompt-cache reconciliation: grand ledger (input/cached/hit rate) with every request's miss split into new content / compression re-pay / TTL expiry, plus per-fold economics. Append 'full' for the every-line listing.",
19009
+ handler: async (args, ctx) => {
18719
19010
  let text;
18720
19011
  try {
18721
- text = await cacheReportText(runtime, ctx);
19012
+ const detail = /(^|\s)(--)?full(\s|$)/.test(args ?? "") ? "full" : "summary";
19013
+ text = await cacheReportText(runtime, ctx, detail);
18722
19014
  } catch (e) {
18723
19015
  ctx.ui.notify(e instanceof Error ? e.message : String(e), "error");
18724
19016
  return;
@@ -18868,7 +19160,7 @@ async function statusReport(runtime, ctx) {
18868
19160
  const sentTokens = estimateTokens(coreMessages, coveredIds, imageTokens) + systemPromptTokens;
18869
19161
  const viewSentTokens = adjustedTokenCount(runtime.core, coreMessages, state, config, sentTokens, imageTokens, systemPromptTokens);
18870
19162
  const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: anchorStale ? viewSentTokens : Math.max(viewSentTokens, realUsage?.tokens ?? 0) });
18871
- const versionStr = "0.1.72" ? `billion-context-pi@${"0.1.72"} \xB7 pack: ${resolveSurfaceMeta(runtime.adapter, ctx?.cwd ?? process.cwd(), ctx?.model?.provider, ctx?.model?.id).pack}` : void 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;
18872
19164
  let text = buildStatusPanel({
18873
19165
  version: versionStr,
18874
19166
  tokenCount: sessionTokens,
@@ -18889,6 +19181,94 @@ async function statusReport(runtime, ctx) {
18889
19181
  return text;
18890
19182
  }
18891
19183
 
19184
+ // src/live-only-tail.ts
19185
+ var MAX_LIVE_ONLY_TAIL = 8;
19186
+ function sigText(content) {
19187
+ if (typeof content === "string") return content;
19188
+ if (!Array.isArray(content)) return "";
19189
+ const parts = [];
19190
+ for (const block of content) {
19191
+ const b2 = block;
19192
+ if (b2?.type === "text" && typeof b2.text === "string") parts.push(b2.text);
19193
+ }
19194
+ return parts.join("\n");
19195
+ }
19196
+ function weakMessageSig(message) {
19197
+ const m2 = message ?? {};
19198
+ const role = typeof m2.role === "string" ? m2.role : "";
19199
+ const customType = typeof m2.customType === "string" ? m2.customType : "";
19200
+ const toolCallId = typeof m2.toolCallId === "string" ? m2.toolCallId : "";
19201
+ const text = sigText(m2.content);
19202
+ return [role, customType, toolCallId, String(text.length), text.slice(0, 32), text.length > 32 ? text.slice(-32) : ""].join("\0");
19203
+ }
19204
+ function entryAsLiveShape(entry) {
19205
+ if (entry.type === "message") {
19206
+ const msg = entry.message;
19207
+ return { role: msg.role, customType: msg.customType, toolCallId: msg.toolCallId, content: msg.content };
19208
+ }
19209
+ if (entry.type === "custom_message") {
19210
+ return { role: "custom", customType: entry.customType, content: entry.content };
19211
+ }
19212
+ return void 0;
19213
+ }
19214
+ function liveOnlyTail(entries, live) {
19215
+ const persisted = entries.filter((e) => e.type === "message" || e.type === "custom_message").map((e) => entryAsLiveShape(e)).filter((shape) => shape !== void 0);
19216
+ const max = Math.min(persisted.length, live.length);
19217
+ let i = 0;
19218
+ while (i < max && weakMessageSig(persisted[i]) === weakMessageSig(live[i])) i++;
19219
+ if (i === max) {
19220
+ const tail = live.slice(max);
19221
+ return tail.length > 0 && tail.length <= MAX_LIVE_ONLY_TAIL ? tail : null;
19222
+ }
19223
+ if (i === max - 1 && i === persisted.length - 1 && i === live.length - 1) {
19224
+ const liveMsg = live[i];
19225
+ if (liveMsg && typeof liveMsg.role === "string" && liveMsg.role === "user") {
19226
+ const before = sigText(persisted[i]?.content);
19227
+ const after = sigText(liveMsg.content);
19228
+ if (before && after && after.startsWith(before)) {
19229
+ const suffix = after.slice(before.length).trim();
19230
+ if (suffix.length > 0) {
19231
+ return [{ role: "user", content: [{ type: "text", text: suffix }], timestamp: Date.now() }];
19232
+ }
19233
+ }
19234
+ }
19235
+ }
19236
+ return null;
19237
+ }
19238
+
19239
+ // src/system-passthrough.ts
19240
+ function isSystem(message) {
19241
+ return typeof message === "object" && message !== null && message.role === "system";
19242
+ }
19243
+ function carryHostSystemMessages(rebuilt, input) {
19244
+ const inputSystems = input.filter(isSystem);
19245
+ if (inputSystems.length === 0) return rebuilt;
19246
+ const rebuiltSystems = rebuilt.filter(isSystem);
19247
+ if (rebuiltSystems.length === 0) return [...inputSystems, ...rebuilt];
19248
+ let changed = false;
19249
+ let sysIdx = 0;
19250
+ const patched = rebuilt.map((message) => {
19251
+ if (!isSystem(message)) return message;
19252
+ const source = inputSystems[sysIdx++];
19253
+ if (!source) return message;
19254
+ const out = message;
19255
+ const src = source;
19256
+ let next = null;
19257
+ for (const key of Object.keys(src)) {
19258
+ if (out[key] === void 0 && src[key] !== void 0) {
19259
+ next ??= { ...out };
19260
+ next[key] = src[key];
19261
+ }
19262
+ }
19263
+ if (next !== null) {
19264
+ changed = true;
19265
+ return next;
19266
+ }
19267
+ return message;
19268
+ });
19269
+ return changed ? patched : rebuilt;
19270
+ }
19271
+
18892
19272
  // src/degeneration.ts
18893
19273
  var DEFAULT_DEGENERATION_GUARD = { enabled: true, minRun: 200 };
18894
19274
  var MIN_VALID_MIN_RUN = 8;
@@ -19480,7 +19860,7 @@ async function autoInstallLatest(latest, extDirOverride) {
19480
19860
  "--no-fund",
19481
19861
  "--no-save"
19482
19862
  ];
19483
- const prevVersion = (await readPackageJson(join15(extDir, "package.json")))?.version ?? "0.1.72";
19863
+ const prevVersion = (await readPackageJson(join15(extDir, "package.json")))?.version ?? "0.1.73";
19484
19864
  const { code, stderr } = await runNpmImpl(installArgs(latest), { cwd: npmDir, timeout: 6e4 });
19485
19865
  if (code !== 0) {
19486
19866
  logWarn("update", {
@@ -19498,7 +19878,7 @@ async function autoInstallLatest(latest, extDirOverride) {
19498
19878
  }
19499
19879
  const verify = await verifyInstall(npmDir, latest);
19500
19880
  if (!verify.ok) {
19501
- const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.72";
19881
+ const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.1.73";
19502
19882
  logWarn("update", { event: "auto-install-verify-failed", latest, reason: verify.reason, rollbackTo });
19503
19883
  const rb = await runNpmImpl(installArgs(rollbackTo), { cwd: npmDir, timeout: 6e4 });
19504
19884
  logInfo("update", { event: "rollback", from: latest, to: rollbackTo, ok: rb.code === 0 });
@@ -19573,7 +19953,7 @@ async function checkForUpdate(autoUpdate, notify) {
19573
19953
  }
19574
19954
  const latest = await fetchLatestVersion(tag);
19575
19955
  if (!latest) return;
19576
- const current = runtimeVersion ?? "0.1.72";
19956
+ const current = runtimeVersion ?? "0.1.73";
19577
19957
  const hasUpdate = isVersionNewer(latest, current);
19578
19958
  debug.event("update-check", {
19579
19959
  current,
@@ -19775,7 +20155,7 @@ function wireSessionLifecycle(pi, runtime, standDownIfProxied) {
19775
20155
  setDelegatePolicy(DEFAULT_DELEGATE_POLICY);
19776
20156
  const sid = ctx.sessionManager.getSessionId();
19777
20157
  const modelInfo = ctx.model;
19778
- logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.72" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
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 });
19779
20159
  let delegateStoodDown = false;
19780
20160
  try {
19781
20161
  await runtime.reloadConfig(ctx.cwd);
@@ -20031,6 +20411,16 @@ ${rendered.text}${example}`);
20031
20411
  ctx.ui.notify(`[ACP] compress failed ${outcome.count}\xD7 this turn \u2014 nudge paused until the next user message (emergency truncation still active).`);
20032
20412
  }
20033
20413
  }
20414
+ const liveTail = liveOnlyTail(entries, event.messages);
20415
+ if (liveTail && liveTail.length > 0) {
20416
+ rebuilt.push(...liveTail);
20417
+ logInfo("live-only-tail", { sid, event: "appended", tail: liveTail.length, outMsgs: rebuilt.length });
20418
+ }
20419
+ const withHostSystem = carryHostSystemMessages(rebuilt, event.messages);
20420
+ if (withHostSystem !== rebuilt) {
20421
+ rebuilt = withHostSystem;
20422
+ logInfo("system-passthrough", { sid, event: "carried", systems: event.messages.filter((m2) => m2.role === "system").length, outMsgs: rebuilt.length });
20423
+ }
20034
20424
  debug.event("context-out", { outMsgs: rebuilt.length, injected: turn.nudge?.shouldInject ?? false, emergency: turn.nudge?.breakdown?.emergencyOverride === 1 });
20035
20425
  const updateCheck = checkForUpdate(runtime.adapter.autoUpdate ?? true, (msg) => {
20036
20426
  if (ctx.hasUI) ctx.ui.notify(msg);