billion-context 0.1.32 → 0.1.33

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
@@ -43930,14 +43930,49 @@ function truncateLargeToolOutputs(messages, tokenCount, config, countTokens, opt
43930
43930
  return { messages: updated, truncatedCount, savedTokens };
43931
43931
  }
43932
43932
  var KEEP_LAST_ORPHANED = 0;
43933
+ function rangeKey(startRef, endRef) {
43934
+ return `${startRef}::${endRef}`;
43935
+ }
43936
+ function rewriteCompressText(text, liveKeys) {
43937
+ let parsed;
43938
+ try {
43939
+ parsed = JSON.parse(text ?? "");
43940
+ } catch {
43941
+ return null;
43942
+ }
43943
+ if (!parsed || typeof parsed !== "object") return null;
43944
+ const obj = parsed;
43945
+ const content = obj.content;
43946
+ if (!Array.isArray(content) || content.length === 0) return null;
43947
+ const kept = content.filter((entry) => {
43948
+ if (!entry || typeof entry !== "object") return false;
43949
+ const s3 = typeof entry.startId === "string" ? entry.startId : typeof entry.messageId === "string" ? entry.messageId : "";
43950
+ const e = typeof entry.endId === "string" ? entry.endId : typeof entry.messageId === "string" ? entry.messageId : "";
43951
+ return liveKeys.has(rangeKey(s3, e));
43952
+ });
43953
+ if (kept.length === content.length || kept.length === 0) return null;
43954
+ return JSON.stringify({ ...obj, content: kept });
43955
+ }
43933
43956
  function hideConsumedCompressCalls(state, messages) {
43934
- const activeCallIds = /* @__PURE__ */ new Set();
43935
43957
  const allBlockCallIds = /* @__PURE__ */ new Set();
43958
+ const activeCallIds = /* @__PURE__ */ new Set();
43959
+ const liveRangeKeysByCallId = /* @__PURE__ */ new Map();
43960
+ const legacyLiveByCallId = /* @__PURE__ */ new Set();
43936
43961
  for (const block of state.blocks) {
43937
- if (block.compressCallId) {
43938
- allBlockCallIds.add(block.compressCallId);
43939
- if (block.active) activeCallIds.add(block.compressCallId);
43962
+ if (!block.compressCallId) continue;
43963
+ allBlockCallIds.add(block.compressCallId);
43964
+ if (!block.active) continue;
43965
+ activeCallIds.add(block.compressCallId);
43966
+ if (block.startRef === void 0 || block.endRef === void 0) {
43967
+ legacyLiveByCallId.add(block.compressCallId);
43968
+ continue;
43969
+ }
43970
+ let keys = liveRangeKeysByCallId.get(block.compressCallId);
43971
+ if (!keys) {
43972
+ keys = /* @__PURE__ */ new Set();
43973
+ liveRangeKeysByCallId.set(block.compressCallId, keys);
43940
43974
  }
43975
+ keys.add(rangeKey(block.startRef, block.endRef));
43941
43976
  }
43942
43977
  const lastOrphanedCallIds = [];
43943
43978
  for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {
@@ -43966,6 +44001,16 @@ function hideConsumedCompressCalls(state, messages) {
43966
44001
  hidden++;
43967
44002
  continue;
43968
44003
  }
44004
+ if (message.toolName === "compress" && message.contentType === "tool-call" && message.toolCallId && keepCallIds.has(message.toolCallId)) {
44005
+ const liveKeys = liveRangeKeysByCallId.get(message.toolCallId);
44006
+ if (liveKeys && liveKeys.size > 0 && !legacyLiveByCallId.has(message.toolCallId)) {
44007
+ const rewritten = rewriteCompressText(message.text, liveKeys);
44008
+ if (rewritten !== null) {
44009
+ result.push({ ...message, text: rewritten });
44010
+ continue;
44011
+ }
44012
+ }
44013
+ }
43969
44014
  result.push(message);
43970
44015
  }
43971
44016
  return { messages: result, hidden };
@@ -44199,8 +44244,8 @@ function refNum(ref) {
44199
44244
  const n = parseInt(ref.slice(1), 10);
44200
44245
  return Number.isNaN(n) ? -1 : n;
44201
44246
  }
44202
- function estimateMessageTokens(message) {
44203
- return Math.ceil((message.text ?? "").length / 4);
44247
+ function estimateTextTokens(text) {
44248
+ return Math.ceil(text.length / 4);
44204
44249
  }
44205
44250
  function isToolMessage(message) {
44206
44251
  return message.contentType === "tool-call" || message.contentType === "tool-result";
@@ -44212,7 +44257,7 @@ function isSyntheticOrPruned(message, state) {
44212
44257
  }
44213
44258
  return false;
44214
44259
  }
44215
- function computeProtectedRefs(messages, state, config) {
44260
+ function computeProtectedRefs(messages, state, config, countTokens = estimateTextTokens) {
44216
44261
  const preserveN = config.preserveRecentMessages;
44217
44262
  const preserveTokens = config.preserveRecentTokens;
44218
44263
  const result = /* @__PURE__ */ new Set();
@@ -44222,7 +44267,7 @@ function computeProtectedRefs(messages, state, config) {
44222
44267
  if (isNeverPreserveRecent(msg2)) continue;
44223
44268
  const ref = state.messageRefs.byRaw[msg2.id];
44224
44269
  if (!ref || ref === "BLOCKED") continue;
44225
- visible.push({ ref, tokens: estimateMessageTokens(msg2) });
44270
+ visible.push({ ref, tokens: countTokens(msg2.text ?? "") });
44226
44271
  }
44227
44272
  if (preserveN > 0) {
44228
44273
  for (const m2 of visible.slice(-preserveN)) {
@@ -44247,7 +44292,7 @@ function computeProtectedRefs(messages, state, config) {
44247
44292
  }
44248
44293
  return result;
44249
44294
  }
44250
- function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
44295
+ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, countTokens = estimateTextTokens) {
44251
44296
  const compressibleMsgs = [];
44252
44297
  const protectedMsgs = [];
44253
44298
  const protectedCallIds = collectProtectedToolCallIds(messages, config);
@@ -44260,7 +44305,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
44260
44305
  protectedMsgs.push({
44261
44306
  ref,
44262
44307
  refNum: rn2,
44263
- tokens: estimateMessageTokens(msg2),
44308
+ tokens: countTokens(msg2.text ?? ""),
44264
44309
  tools: msg2.toolName ? [msg2.toolName] : []
44265
44310
  });
44266
44311
  continue;
@@ -44271,7 +44316,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
44271
44316
  compressibleMsgs.push({
44272
44317
  ref,
44273
44318
  refNum: rn2,
44274
- tokens: estimateMessageTokens(msg2),
44319
+ tokens: countTokens(msg2.text ?? ""),
44275
44320
  isTool: isToolMessage(msg2),
44276
44321
  isUser: msg2.role === "user"
44277
44322
  });
@@ -44358,7 +44403,7 @@ function createCore(ports = {}) {
44358
44403
  let tokensCompressed = 0;
44359
44404
  const errors = [];
44360
44405
  const warnings = [];
44361
- const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config);
44406
+ const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config, countTokens);
44362
44407
  const preExistingCoverage = collectCoverage(state);
44363
44408
  const rangeIndexSets = [];
44364
44409
  for (const spec of input.ranges) {
@@ -44383,29 +44428,25 @@ function createCore(ports = {}) {
44383
44428
  const bMin = b2.indices.length > 0 ? Math.min(...b2.indices) : Infinity;
44384
44429
  return aMin - bMin;
44385
44430
  });
44386
- for (let i = 1; i < sortedRanges.length; i++) {
44387
- const prev = sortedRanges[i - 1];
44388
- const curr = sortedRanges[i];
44389
- const prevMax = prev.indices.length > 0 ? Math.max(...prev.indices) : -1;
44390
- const currMin = curr.indices.length > 0 ? Math.min(...curr.indices) : -1;
44391
- if (prevMax >= currMin && prevMax >= 0) {
44392
- return {
44393
- state: input.state,
44394
- result: {
44395
- blocksCreated: 0,
44396
- tokensCompressed: 0,
44397
- errors: [
44398
- `content: range (${prev.spec.startRef}..${prev.spec.endRef}) overlaps (${curr.spec.startRef}..${curr.spec.endRef}). Overlapping ranges cannot be compressed in the same batch.`
44399
- ],
44400
- warnings: []
44401
- }
44402
- };
44431
+ const skipSpecs = /* @__PURE__ */ new Set();
44432
+ let acceptedMaxIndex = -1;
44433
+ for (const entry of sortedRanges) {
44434
+ const entryMax = entry.indices.length > 0 ? Math.max(...entry.indices) : -1;
44435
+ const entryMin = entry.indices.length > 0 ? Math.min(...entry.indices) : -1;
44436
+ if (entryMin >= 0 && entryMin <= acceptedMaxIndex) {
44437
+ skipSpecs.add(entry.spec);
44438
+ warnings.push(
44439
+ `Skipped range (${entry.spec.startRef}..${entry.spec.endRef}) \u2014 overlaps an earlier range in the batch; the earlier range takes precedence. Keep ranges disjoint.`
44440
+ );
44441
+ continue;
44403
44442
  }
44443
+ if (entryMax > acceptedMaxIndex) acceptedMaxIndex = entryMax;
44404
44444
  }
44405
44445
  if (input.config.compress.minCompressRange > 0 && input.ranges.length > 0) {
44406
44446
  let totalRangeChars = 0;
44407
44447
  let hasBlockBoundaryRange = false;
44408
44448
  for (const spec of input.ranges) {
44449
+ if (skipSpecs.has(spec)) continue;
44409
44450
  let resolved;
44410
44451
  try {
44411
44452
  resolved = resolveBoundaries({
@@ -44441,6 +44482,7 @@ function createCore(ports = {}) {
44441
44482
  }
44442
44483
  }
44443
44484
  for (const spec of input.ranges) {
44485
+ if (skipSpecs.has(spec)) continue;
44444
44486
  try {
44445
44487
  const outcome = applySingleRange({
44446
44488
  spec,
@@ -44581,13 +44623,15 @@ var recommendNode = {
44581
44623
  const protectedRefs = computeProtectedRefs(
44582
44624
  io2.messages,
44583
44625
  io2.state,
44584
- ctx.config
44626
+ ctx.config,
44627
+ ctx.countTokens
44585
44628
  );
44586
44629
  const contextRanges = buildCompressibleRanges(
44587
44630
  io2.messages,
44588
44631
  io2.state,
44589
44632
  ctx.config,
44590
- protectedRefs
44633
+ protectedRefs,
44634
+ ctx.countTokens
44591
44635
  );
44592
44636
  const nothingToCompress = contextRanges.compressible.length === 0;
44593
44637
  const recommendation = {
@@ -44765,7 +44809,9 @@ function applySingleRange(input) {
44765
44809
  survivedCount: 0,
44766
44810
  generation: "young",
44767
44811
  active: true,
44768
- compressCallId: input.spec.compressCallId
44812
+ compressCallId: input.spec.compressCallId,
44813
+ startRef: input.spec.startRef,
44814
+ endRef: input.spec.endRef
44769
44815
  };
44770
44816
  input.state.blocks.push(block);
44771
44817
  for (const consumedId of consumedBlockIds) {
@@ -45256,7 +45302,7 @@ function renderNudgeText(decision) {
45256
45302
  breakdownStr,
45257
45303
  "",
45258
45304
  `[TIER ${decision.tier} ${isT2 ? "DISTILLATION" : "CONDENSATION"} TRIGGER]`,
45259
- isT2 ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries.` : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries.`,
45305
+ isT2 ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries (startId and endId as bN). Any raw (uncompressed) messages sitting between the boundary blocks are absorbed into the tier-2 block as well \u2014 apply HOW TO COMPRESS to those raw messages and the TIER 2 distillation rules to the existing summaries, so the whole span is covered and nothing is lost.` : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries (startId and endId as bN). Any raw (uncompressed) messages sitting between the boundary blocks are absorbed into the tier-3 block as well \u2014 apply HOW TO COMPRESS to those raw messages and the TIER 3 condensation rules to the existing summaries, so the whole span is covered and nothing is lost.`,
45260
45306
  blockList,
45261
45307
  `Example: compress({ content: [{ startId: "${startId}", endId: "${endId}", summary: "..." }] })`,
45262
45308
  "",
@@ -52018,11 +52064,24 @@ async function handle(req, res, opts, core, config, log2) {
52018
52064
  return;
52019
52065
  }
52020
52066
  let bodyBuffer;
52067
+ let urlPath;
52068
+ let responsesCompact;
52069
+ let route;
52070
+ let upstreamOrigin;
52071
+ let protocol;
52021
52072
  try {
52022
52073
  bodyBuffer = await readBody(req);
52023
- const decoded = await decodeRequestBody(headerValue(req, "content-encoding"), bodyBuffer, MAX_REQUEST_BYTES);
52024
- bodyBuffer = decoded.body;
52025
- if (decoded.decoded) delete req.headers["content-encoding"];
52074
+ const url = req.url ?? "";
52075
+ urlPath = url.split("?", 2)[0];
52076
+ responsesCompact = urlPath.endsWith("/responses/compact");
52077
+ route = resolveUpstream(opts, req.url ?? "", req);
52078
+ upstreamOrigin = route ? route.upstream : opts.upstream;
52079
+ protocol = route?.explicitProtocol ?? (req.method === "POST" && bodyBuffer.length > 0 ? urlPath.endsWith("/chat/completions") ? "openai" : urlPath.endsWith("/v1/messages") || urlPath.endsWith("/messages") ? "anthropic" : urlPath.endsWith("/responses") || responsesCompact ? "responses" : null : null);
52080
+ if (protocol !== null && bodyBuffer.length > 0) {
52081
+ const decoded = await decodeRequestBody(headerValue(req, "content-encoding"), bodyBuffer, MAX_REQUEST_BYTES);
52082
+ bodyBuffer = decoded.body;
52083
+ if (decoded.decoded) delete req.headers["content-encoding"];
52084
+ }
52026
52085
  } catch (err2) {
52027
52086
  if (err2 instanceof BodyTooLargeError) {
52028
52087
  log2("warn", `413: request body exceeds ${err2.limit} bytes`);
@@ -52035,13 +52094,7 @@ async function handle(req, res, opts, core, config, log2) {
52035
52094
  res.end(JSON.stringify({ error: { type: "invalid_request", message: String(err2) } }));
52036
52095
  return;
52037
52096
  }
52038
- const url = req.url ?? "";
52039
- const urlPath = url.split("?", 2)[0];
52040
- const responsesCompact = urlPath.endsWith("/responses/compact");
52041
52097
  const countTokens = isCountTokensRequest(req.method ?? "GET", urlPath, bodyBuffer.length > 0);
52042
- const route = resolveUpstream(opts, req.url ?? "", req);
52043
- const upstreamOrigin = route ? route.upstream : opts.upstream;
52044
- const protocol = route?.explicitProtocol ?? (req.method === "POST" && bodyBuffer.length > 0 ? urlPath.endsWith("/chat/completions") ? "openai" : urlPath.endsWith("/v1/messages") || urlPath.endsWith("/messages") ? "anthropic" : urlPath.endsWith("/responses") || responsesCompact ? "responses" : null : null);
52045
52098
  let parsed = null;
52046
52099
  if (protocol && bodyBuffer.length > 0) {
52047
52100
  try {
@@ -52098,7 +52151,7 @@ async function handle(req, res, opts, core, config, log2) {
52098
52151
  }
52099
52152
  if (!prepared) {
52100
52153
  if (protocol === null && !opts.passthrough) {
52101
- log2("warn", `unrecognized path ${url} \u2014 not a known protocol (/chat/completions, /v1/messages, /responses, /responses/compact); forwarding unchanged`);
52154
+ log2("warn", `unrecognized path ${req.url ?? ""} \u2014 not a known protocol (/chat/completions, /v1/messages, /responses, /responses/compact); forwarding unchanged`);
52102
52155
  }
52103
52156
  await forward(req, res, opts, bodyBuffer, null, core, reqConfig, log2, route, void 0);
52104
52157
  }