billion-context-omp 0.2.8 → 0.2.9

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
@@ -395,8 +395,13 @@ function resolveBoundaries(input) {
395
395
  input.messages.forEach(
396
396
  (message, index) => indexByRawId.set(message.id, index)
397
397
  );
398
- let startIndex = resolveAnchorIndex(start, input.state, indexByRawId, "start");
399
- let endIndex = resolveAnchorIndex(end, input.state, indexByRawId, "end");
398
+ let snappedBoundaries = [];
399
+ const startAnchor = resolveAnchorIndex(start, input.state, indexByRawId, "start");
400
+ if (startAnchor.snapped) snappedBoundaries.push(startAnchor.snapped);
401
+ const endAnchor = resolveAnchorIndex(end, input.state, indexByRawId, "end");
402
+ if (endAnchor.snapped) snappedBoundaries.push(endAnchor.snapped);
403
+ let startIndex = startAnchor.index;
404
+ let endIndex = endAnchor.index;
400
405
  if (startIndex > endIndex) {
401
406
  [startIndex, endIndex] = [endIndex, startIndex];
402
407
  }
@@ -424,7 +429,8 @@ function resolveBoundaries(input) {
424
429
  messageIds,
425
430
  nestedBlockIds,
426
431
  boundaryKind,
427
- protectedGaps
432
+ protectedGaps,
433
+ snappedBoundaries
428
434
  };
429
435
  }
430
436
  function resolveAnchorIndex(boundary, state, indexByRawId, endpoint) {
@@ -439,14 +445,21 @@ function resolveAnchorIndex(boundary, state, indexByRawId, endpoint) {
439
445
  );
440
446
  }
441
447
  const index = indexByRawId.get(rawId);
442
- if (index === void 0) {
443
- throw new BoundaryNotFoundError(
444
- "consumed",
445
- endpoint,
446
- `${label}="${boundary.raw}" not found in visible context (likely consumed by an existing block).`
447
- );
448
+ if (index !== void 0) {
449
+ return { index, snapped: null };
450
+ }
451
+ const owner2 = activeOwnerAnchor(state, [rawId], indexByRawId);
452
+ if (owner2 !== null) {
453
+ return {
454
+ index: owner2,
455
+ snapped: `${label}="${boundary.raw}" refers to a message already compressed into an active block \u2014 anchored to that block's summary instead.`
456
+ };
448
457
  }
449
- return index;
458
+ throw new BoundaryNotFoundError(
459
+ "consumed",
460
+ endpoint,
461
+ `${label}="${boundary.raw}" not found in visible context (likely consumed by an existing block).`
462
+ );
450
463
  }
451
464
  const block = blockById(state, `b${boundary.numericId}`);
452
465
  if (!block) {
@@ -456,6 +469,19 @@ function resolveAnchorIndex(boundary, state, indexByRawId, endpoint) {
456
469
  `${label}="b${boundary.numericId}" does not exist in this session (typo or wrong session) \u2014 run acp_status for current refs.`
457
470
  );
458
471
  }
472
+ if (block.active) {
473
+ const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);
474
+ if (anchor !== null) {
475
+ return { index: anchor, snapped: null };
476
+ }
477
+ }
478
+ const owner = activeOwnerAnchor(state, block.effectiveMessageIds, indexByRawId);
479
+ if (owner !== null) {
480
+ return {
481
+ index: owner,
482
+ snapped: `${label}="b${boundary.numericId}" was consumed by a higher-tier block \u2014 anchored to the active block covering its content instead.`
483
+ };
484
+ }
459
485
  if (!block.active) {
460
486
  throw new BoundaryNotFoundError(
461
487
  "consumed",
@@ -463,15 +489,26 @@ function resolveAnchorIndex(boundary, state, indexByRawId, endpoint) {
463
489
  `${label}="b${boundary.numericId}" not found in visible context (block distilled/consumed by a higher-tier block).`
464
490
  );
465
491
  }
466
- const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);
467
- if (anchor === null) {
468
- throw new BoundaryNotFoundError(
469
- "consumed",
470
- endpoint,
471
- `${label}="b${boundary.numericId}" not found in visible context (block messages consumed by a higher-tier block).`
472
- );
492
+ throw new BoundaryNotFoundError(
493
+ "consumed",
494
+ endpoint,
495
+ `${label}="b${boundary.numericId}" not found in visible context (block messages consumed by a higher-tier block).`
496
+ );
497
+ }
498
+ function activeOwnerAnchor(state, ownedIds, indexByRawId) {
499
+ if (ownedIds.length === 0) return null;
500
+ const owned = new Set(ownedIds);
501
+ let best = null;
502
+ for (const block of state.blocks) {
503
+ if (!block.active) continue;
504
+ const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);
505
+ if (anchor === null) continue;
506
+ const ownsContent = block.effectiveMessageIds.some((id) => owned.has(id));
507
+ if (ownsContent && (best === null || anchor < best)) {
508
+ best = anchor;
509
+ }
473
510
  }
474
- return anchor;
511
+ return best;
475
512
  }
476
513
  function formatPaddedRef(index) {
477
514
  return `m${String(index).padStart(5, "0")}`;
@@ -1092,6 +1129,10 @@ function runPipeline(nodes, initial, ctx) {
1092
1129
  function rangeError(spec, message) {
1093
1130
  return `range ${spec.startRef}..${spec.endRef}: ${message}`;
1094
1131
  }
1132
+ function numericBlockId(id) {
1133
+ const parsed = /^b(\d+)$/.exec(id);
1134
+ return parsed ? Number(parsed[1]) : 0;
1135
+ }
1095
1136
  function createCore(ports = {}) {
1096
1137
  const countTokens = ports.countTokens ?? defaultCountTokens;
1097
1138
  function applyCompression(input) {
@@ -1137,6 +1178,12 @@ function createCore(ports = {}) {
1137
1178
  }
1138
1179
  }
1139
1180
  }
1181
+ let resolvableCount = 0;
1182
+ let unknownCount = 0;
1183
+ for (const resolution of classifications.values()) {
1184
+ if (resolution.status === "ok") resolvableCount++;
1185
+ else if (resolution.status === "unknown") unknownCount++;
1186
+ }
1140
1187
  const rangeIndexSets = [];
1141
1188
  for (const [spec, resolution] of classifications) {
1142
1189
  if (resolution.status !== "ok") continue;
@@ -1181,7 +1228,9 @@ function createCore(ports = {}) {
1181
1228
  }
1182
1229
  }
1183
1230
  if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {
1184
- const gateMessage = consumedRanges.length > 0 ? `Requested range(s) already compressed (e.g. ${consumedRanges[0].startRef}..${consumedRanges[0].endRef}); remaining compressible content ${totalRangeChars} chars < min ${input.config.compress.minCompressRange}. Nothing to do \u2014 run acp_status to see current compressible ranges.` : `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.`;
1231
+ const live = activeBlocks(state).map((b) => b.blockId).sort((x, y) => numericBlockId(x) - numericBlockId(y));
1232
+ 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.` : "";
1233
+ const gateMessage = resolvableCount === 0 && consumedRanges.length === 0 && unknownCount > 0 ? `None of the ${input.ranges.length} requested range(s) resolved \u2014 every ref failed with "does not exist in this session". Refs recorded before an earlier compress are stale: each successful compress renumbers the remaining refs. Run acp_status, then re-issue the compress in the same turn using only the refs it reports.` : consumedRanges.length > 0 ? `Requested range(s) already compressed (e.g. ${consumedRanges[0].startRef}..${consumedRanges[0].endRef}); remaining compressible content ${totalRangeChars} chars < min ${input.config.compress.minCompressRange}. Nothing to do.${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.`;
1185
1234
  return {
1186
1235
  state: input.state,
1187
1236
  result: {
@@ -1207,6 +1256,7 @@ function createCore(ports = {}) {
1207
1256
  errors.push(rangeError(spec, resolution.error.message));
1208
1257
  continue;
1209
1258
  }
1259
+ warnings.push(...resolution.resolved.snappedBoundaries);
1210
1260
  try {
1211
1261
  const outcome = applySingleRange({
1212
1262
  spec,
@@ -2422,24 +2472,6 @@ function renderCompressedDrilldown(blocks, state, sort, limit, countTokens) {
2422
2472
  }
2423
2473
  return lines.join("\n");
2424
2474
  }
2425
- var substringAlgorithm = {
2426
- name: "substring",
2427
- description: "Exact substring counting (original baseline). Predictable, no normalization.",
2428
- score(docs, query) {
2429
- const terms = query.toLowerCase().trim().split(/\s+/).filter((t) => t.length > 0);
2430
- if (terms.length === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
2431
- return docs.map((d) => {
2432
- const haystack = d.text.toLowerCase();
2433
- let score = 0;
2434
- for (const term of terms) score += countOccurrences2(haystack, term);
2435
- return { ref: d.ref, score };
2436
- });
2437
- }
2438
- };
2439
- function countOccurrences2(haystack, needle) {
2440
- if (!needle) return 0;
2441
- return haystack.split(needle).length - 1;
2442
- }
2443
2475
  function stem(word) {
2444
2476
  let w = word;
2445
2477
  if (w.length <= 3) return w;
@@ -2458,8 +2490,17 @@ function stem(word) {
2458
2490
  return w;
2459
2491
  }
2460
2492
  var CJK = /[\u3400-\u9fff\uf900-\ufaff\u3040-\u30ff\uac00-\ud7af]/;
2461
- var CJK_RUN = new RegExp(`${CJK.source}+`, "g");
2462
2493
  var LATIN_WORD = /[a-z][a-z0-9_]*[a-z0-9]|[a-z0-9]/g;
2494
+ var cjkSegmenter = new Intl.Segmenter("zh", { granularity: "word" });
2495
+ function cjkRunTokens(segs) {
2496
+ const words = segs.filter((w) => w.length >= 2);
2497
+ if (words.length > 0) return words;
2498
+ const run = segs.join("");
2499
+ const out = [];
2500
+ for (let i = 0; i < run.length - 1; i++) out.push(run.slice(i, i + 2));
2501
+ for (const ch of run) out.push(ch);
2502
+ return out;
2503
+ }
2463
2504
  function tokenize(text, opts = {}) {
2464
2505
  const lower = text.toLowerCase();
2465
2506
  const tokens = [];
@@ -2470,15 +2511,23 @@ function tokenize(text, opts = {}) {
2470
2511
  tokens.push(w);
2471
2512
  }
2472
2513
  }
2473
- const cjkRuns = lower.match(CJK_RUN) ?? [];
2474
- for (const run of cjkRuns) {
2475
- if (run.length === 1) {
2476
- tokens.push(run);
2477
- } else {
2478
- for (let i = 0; i < run.length - 1; i++) tokens.push(run.slice(i, i + 2));
2479
- for (const ch of run) tokens.push(ch);
2514
+ if (!CJK.test(lower)) return tokens;
2515
+ const runSegs = [];
2516
+ let cur = null;
2517
+ for (const s of cjkSegmenter.segment(lower)) {
2518
+ const t = s.segment;
2519
+ if (t.length === 0) continue;
2520
+ if (CJK.test(t)) {
2521
+ (cur ??= []).push(t);
2522
+ } else if (cur) {
2523
+ runSegs.push(cur);
2524
+ cur = null;
2480
2525
  }
2481
2526
  }
2527
+ if (cur) runSegs.push(cur);
2528
+ for (const segs of runSegs) {
2529
+ tokens.push(...cjkRunTokens(segs));
2530
+ }
2482
2531
  return tokens;
2483
2532
  }
2484
2533
  function charBigrams(text) {
@@ -2494,6 +2543,50 @@ function tfMap(text, stem22) {
2494
2543
  for (const t of tokenize(text, { stem: stem22 })) m.set(t, (m.get(t) ?? 0) + 1);
2495
2544
  return m;
2496
2545
  }
2546
+ var DEFAULT_CAP_CHARS = 8 * 1024 * 1024;
2547
+ var capChars = DEFAULT_CAP_CHARS;
2548
+ var cache = /* @__PURE__ */ new Map();
2549
+ var cachedChars = 0;
2550
+ function build(text) {
2551
+ const tf = tfMap(text, true);
2552
+ let len = 0;
2553
+ for (const v of tf.values()) len += v;
2554
+ const lower = text.toLowerCase();
2555
+ return { tf, len, lower, grams: new Set(charBigrams(lower)) };
2556
+ }
2557
+ function docFeatures(text) {
2558
+ const hit = cache.get(text);
2559
+ if (hit) return hit;
2560
+ const f = build(text);
2561
+ if (text.length > 0 && text.length <= capChars) {
2562
+ while (cachedChars + text.length > capChars && cache.size > 0) {
2563
+ const k = cache.keys().next().value;
2564
+ cachedChars -= k.length;
2565
+ cache.delete(k);
2566
+ }
2567
+ cache.set(text, f);
2568
+ cachedChars += text.length;
2569
+ }
2570
+ return f;
2571
+ }
2572
+ var substringAlgorithm = {
2573
+ name: "substring",
2574
+ description: "Exact substring counting (original baseline). Predictable, no normalization.",
2575
+ score(docs, query) {
2576
+ const terms = query.toLowerCase().trim().split(/\s+/).filter((t) => t.length > 0);
2577
+ if (terms.length === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
2578
+ return docs.map((d) => {
2579
+ const haystack = docFeatures(d.text).lower;
2580
+ let score = 0;
2581
+ for (const term of terms) score += countOccurrences2(haystack, term);
2582
+ return { ref: d.ref, score };
2583
+ });
2584
+ }
2585
+ };
2586
+ function countOccurrences2(haystack, needle) {
2587
+ if (!needle) return 0;
2588
+ return haystack.split(needle).length - 1;
2589
+ }
2497
2590
  var bm25Algorithm = {
2498
2591
  name: "bm25",
2499
2592
  description: "BM25 with stemming + CJK bigram tokenization. IR-standard relevance ranking.",
@@ -2502,11 +2595,8 @@ var bm25Algorithm = {
2502
2595
  const k1 = 1.2;
2503
2596
  const b = 0.75;
2504
2597
  const parsed = docs.map((d) => {
2505
- const text = d.text;
2506
- const tf = tfMap(text, true);
2507
- let len = 0;
2508
- for (const v of tf.values()) len += v;
2509
- return { id: d.ref, tf, len };
2598
+ const f = docFeatures(d.text);
2599
+ return { id: d.ref, tf: f.tf, len: f.len };
2510
2600
  });
2511
2601
  const avgdl = parsed.reduce((s, d) => s + d.len, 0) / (N || 1);
2512
2602
  const qTerms = tokenize(query, { stem: true });
@@ -2533,14 +2623,13 @@ var fuzzyAlgorithm = {
2533
2623
  name: "fuzzy",
2534
2624
  description: "Character bigram overlap. Typo-tolerant, script-agnostic, high recall.",
2535
2625
  score(docs, query) {
2536
- const qTokens = query.toLowerCase().split(/[\s,]+/).filter((t) => t.length >= 4);
2626
+ const qTokens = query.toLowerCase().split(/[\s,]+/).filter((t) => t.length >= 4 || t.length >= 2 && CJK.test(t));
2537
2627
  if (qTokens.length === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
2538
2628
  const qGrams = /* @__PURE__ */ new Set();
2539
2629
  for (const t of qTokens) for (const g of charBigrams(t)) qGrams.add(g);
2540
2630
  if (qGrams.size === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
2541
2631
  return docs.map((d) => {
2542
- const haystack = d.text.toLowerCase();
2543
- const docGrams = new Set(charBigrams(haystack));
2632
+ const docGrams = docFeatures(d.text).grams;
2544
2633
  let hits = 0;
2545
2634
  for (const g of qGrams) if (docGrams.has(g)) hits++;
2546
2635
  return { ref: d.ref, score: hits / qGrams.size };
@@ -3099,14 +3188,17 @@ function openaiToCore(body) {
3099
3188
  }
3100
3189
  case "user": {
3101
3190
  const text = stringContent(m.content);
3102
- const img = firstImagePart(m.content);
3191
+ const imgs = allImageParts(m.content);
3192
+ const firstImg = imgs[0];
3193
+ const firstUrl = firstImg ? firstImg.image_url.url : void 0;
3194
+ const firstParsed = firstUrl ? parseDataUrl(firstUrl) : void 0;
3103
3195
  const base = deriveMessageId("user", "text", text);
3104
3196
  msgs.push({
3105
3197
  id: clusters.next(base),
3106
3198
  role: "user",
3107
3199
  contentType: "text",
3108
3200
  text,
3109
- ...img ? { rawOpenaiContent: img.part, imageMediaType: img.mediaType, imageBase64: img.base64 } : {}
3201
+ ...imgs.length === 1 && firstParsed ? { rawOpenaiContent: imgs[0], imageMediaType: firstParsed.mediaType, imageBase64: firstParsed.base64 } : imgs.length > 1 ? { rawOpenaiContentParts: imgs } : {}
3110
3202
  });
3111
3203
  break;
3112
3204
  }
@@ -3201,10 +3293,12 @@ function coreToOpenai(messages) {
3201
3293
  if (m.role === "system") {
3202
3294
  out.push({ role: m.originalRole === "developer" ? "developer" : "system", content: m.text ?? "" });
3203
3295
  } else if (m.role === "user") {
3204
- if (m.rawOpenaiContent || m.imageBase64) {
3296
+ if (m.rawOpenaiContent || m.imageBase64 || m.rawOpenaiContentParts) {
3205
3297
  const parts = [];
3206
3298
  if (m.text) parts.push({ type: "text", text: m.text });
3207
- if (m.rawOpenaiContent) {
3299
+ if (m.rawOpenaiContentParts && m.rawOpenaiContentParts.length > 0) {
3300
+ for (const part of m.rawOpenaiContentParts) parts.push(part);
3301
+ } else if (m.rawOpenaiContent) {
3208
3302
  parts.push(m.rawOpenaiContent);
3209
3303
  } else if (m.imageBase64 && m.imageMediaType) {
3210
3304
  parts.push({ type: "image_url", image_url: { url: `data:${m.imageMediaType};base64,${m.imageBase64}` } });
@@ -3229,19 +3323,17 @@ function stringContent(content) {
3229
3323
  }
3230
3324
  return "";
3231
3325
  }
3232
- function firstImagePart(content) {
3233
- if (!Array.isArray(content)) return void 0;
3326
+ function allImageParts(content) {
3327
+ if (!Array.isArray(content)) return [];
3328
+ const out = [];
3234
3329
  for (const p of content) {
3235
- if (p && typeof p === "object" && p.type === "image_url") {
3236
- const iu = p.image_url;
3237
- const url = iu?.url;
3238
- if (typeof url === "string") {
3239
- const parsed = parseDataUrl(url);
3240
- if (parsed) return { part: p, mediaType: parsed.mediaType, base64: parsed.base64 };
3241
- }
3242
- }
3330
+ if (typeof p !== "object" || p === null) continue;
3331
+ if (!("type" in p) || p.type !== "image_url" || !("image_url" in p)) continue;
3332
+ const imagePart = p;
3333
+ const url = imagePart.image_url.url;
3334
+ if (typeof url === "string" && parseDataUrl(url)) out.push(p);
3243
3335
  }
3244
- return void 0;
3336
+ return out;
3245
3337
  }
3246
3338
  function createSubagentNamespaces() {
3247
3339
  const anchors = /* @__PURE__ */ new Map();
@@ -3728,7 +3820,6 @@ function unrepresentableOpenaiMessage(message) {
3728
3820
  const content = message.content;
3729
3821
  if (content == null || typeof content === "string") return null;
3730
3822
  if (!Array.isArray(content)) return "content neither string nor part array";
3731
- let dataImages = 0;
3732
3823
  for (const part of content) {
3733
3824
  if (typeof part === "string") continue;
3734
3825
  const type5 = part?.type;
@@ -3736,7 +3827,6 @@ function unrepresentableOpenaiMessage(message) {
3736
3827
  if (type5 === "image_url" && role === "user") {
3737
3828
  const url = part?.image_url?.url;
3738
3829
  if (typeof url !== "string" || !url.startsWith("data:")) return "image_url without a data: URL is dropped";
3739
- if (++dataImages > 1) return "second image_url in one message is dropped";
3740
3830
  continue;
3741
3831
  }
3742
3832
  return `openai content part type ${JSON.stringify(type5) ?? "missing"}`;
@@ -5096,7 +5186,7 @@ function stem2(word) {
5096
5186
  return w;
5097
5187
  }
5098
5188
  var CJK2 = /[\u3400-\u9fff\uf900-\ufaff\u3040-\u30ff\uac00-\ud7af]/;
5099
- var CJK_RUN2 = new RegExp(`${CJK2.source}+`, "g");
5189
+ var CJK_RUN = new RegExp(`${CJK2.source}+`, "g");
5100
5190
  var LATIN_WORD2 = /[a-z][a-z0-9_]*[a-z0-9]|[a-z0-9]/g;
5101
5191
  function tokenize2(text, opts = {}) {
5102
5192
  const lower = text.toLowerCase();
@@ -5108,7 +5198,7 @@ function tokenize2(text, opts = {}) {
5108
5198
  tokens.push(w);
5109
5199
  }
5110
5200
  }
5111
- const cjkRuns = lower.match(CJK_RUN2) ?? [];
5201
+ const cjkRuns = lower.match(CJK_RUN) ?? [];
5112
5202
  for (const run of cjkRuns) {
5113
5203
  if (run.length === 1) {
5114
5204
  tokens.push(run);
@@ -5472,7 +5562,7 @@ async function statusReport(runtime, ctx) {
5472
5562
  const coveredIds = collectCoveredMessageIds(state);
5473
5563
  const sentTokens = estimateTokens(coreMessages, coveredIds) + systemPromptTokens;
5474
5564
  const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: sentTokens });
5475
- const versionStr = "0.2.8" ? `billion-context-omp@${"0.2.8"}` : void 0;
5565
+ const versionStr = "0.2.9" ? `billion-context-omp@${"0.2.9"}` : void 0;
5476
5566
  return buildStatusPanel({
5477
5567
  version: versionStr,
5478
5568
  tokenCount: sessionTokens,
@@ -5766,7 +5856,7 @@ async function checkForUpdate(autoUpdate, notify) {
5766
5856
  const data = await res.json();
5767
5857
  const latest = data.version;
5768
5858
  if (!latest) return;
5769
- const current = runtimeVersion ?? "0.2.8";
5859
+ const current = runtimeVersion ?? "0.2.9";
5770
5860
  const hasUpdate = isNewer(latest, current);
5771
5861
  debug.event("update-check", {
5772
5862
  current,
@@ -6041,9 +6131,9 @@ var index_default = createAcpExtension();
6041
6131
  function wireSessionLifecycle(pi, runtime) {
6042
6132
  pi.on("session_start", async (_event, ctx) => {
6043
6133
  const sid = ctx.sessionManager.getSessionId();
6044
- logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.2.8" : null });
6134
+ logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.2.9" : null });
6045
6135
  const selfPath = import.meta.url;
6046
- const conflict = stampAndDetect(selfPath, true ? "0.2.8" : null);
6136
+ const conflict = stampAndDetect(selfPath, true ? "0.2.9" : null);
6047
6137
  if (conflict) {
6048
6138
  logWarn("instance", { event: "dual-instance", self: selfPath, other: conflict.path, otherPid: conflict.pid, otherVersion: conflict.version });
6049
6139
  try {
@@ -6389,18 +6479,18 @@ function wireProviderDebug(pi) {
6389
6479
  pi.on("after_provider_response", (event, ctx) => {
6390
6480
  if (!debug.enabled) return;
6391
6481
  const h = event.headers;
6392
- const cache = {};
6482
+ const cache2 = {};
6393
6483
  for (const [k, v] of Object.entries(h)) {
6394
6484
  const lk = k.toLowerCase();
6395
6485
  if (lk.includes("cache") || lk.includes("usage") || lk.includes("token") || lk.includes("rate") || lk.includes("x-")) {
6396
- cache[lk] = v;
6486
+ cache2[lk] = v;
6397
6487
  }
6398
6488
  }
6399
6489
  debug.event("provider-response", {
6400
6490
  sid: ctx.sessionManager.getSessionId(),
6401
6491
  status: event.status,
6402
6492
  requestId: event.requestId ?? null,
6403
- cache
6493
+ cache: cache2
6404
6494
  });
6405
6495
  });
6406
6496
  }