acp-kernel 0.0.17 → 0.0.18

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.
@@ -1 +1 @@
1
- {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAQpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,EAEN,WAAW,EAGX,iBAAiB,EAEjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvE,YAAY,IAAI,YAAY,EAAE,CAAC;IAC/B,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,CACJ,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CAqO7D;AAmrBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAQpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,EAEN,WAAW,EAGX,iBAAiB,EAEjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvE,YAAY,IAAI,YAAY,EAAE,CAAC;IAC/B,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,CACJ,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CAoO7D;AAurBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hide-consumed.d.ts","sourceRoot":"","sources":["../src/hide-consumed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQhE,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AAGD,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,GACxB,kBAAkB,CAwDpB"}
1
+ {"version":3,"file":"hide-consumed.d.ts","sourceRoot":"","sources":["../src/hide-consumed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIhE,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AA8BD,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,WAAW,EAAE,GACxB,kBAAkB,CAmFpB"}
package/dist/index.js CHANGED
@@ -506,14 +506,49 @@ function truncateLargeToolOutputs(messages, tokenCount, config, countTokens, opt
506
506
 
507
507
  // src/hide-consumed.ts
508
508
  var KEEP_LAST_ORPHANED = 0;
509
+ function rangeKey(startRef, endRef) {
510
+ return `${startRef}::${endRef}`;
511
+ }
512
+ function rewriteCompressText(text, liveKeys) {
513
+ let parsed;
514
+ try {
515
+ parsed = JSON.parse(text ?? "");
516
+ } catch {
517
+ return null;
518
+ }
519
+ if (!parsed || typeof parsed !== "object") return null;
520
+ const obj = parsed;
521
+ const content = obj.content;
522
+ if (!Array.isArray(content) || content.length === 0) return null;
523
+ const kept = content.filter((entry) => {
524
+ if (!entry || typeof entry !== "object") return false;
525
+ const s = typeof entry.startId === "string" ? entry.startId : typeof entry.messageId === "string" ? entry.messageId : "";
526
+ const e = typeof entry.endId === "string" ? entry.endId : typeof entry.messageId === "string" ? entry.messageId : "";
527
+ return liveKeys.has(rangeKey(s, e));
528
+ });
529
+ if (kept.length === content.length || kept.length === 0) return null;
530
+ return JSON.stringify({ ...obj, content: kept });
531
+ }
509
532
  function hideConsumedCompressCalls(state, messages) {
510
- const activeCallIds = /* @__PURE__ */ new Set();
511
533
  const allBlockCallIds = /* @__PURE__ */ new Set();
534
+ const activeCallIds = /* @__PURE__ */ new Set();
535
+ const liveRangeKeysByCallId = /* @__PURE__ */ new Map();
536
+ const legacyLiveByCallId = /* @__PURE__ */ new Set();
512
537
  for (const block of state.blocks) {
513
- if (block.compressCallId) {
514
- allBlockCallIds.add(block.compressCallId);
515
- if (block.active) activeCallIds.add(block.compressCallId);
538
+ if (!block.compressCallId) continue;
539
+ allBlockCallIds.add(block.compressCallId);
540
+ if (!block.active) continue;
541
+ activeCallIds.add(block.compressCallId);
542
+ if (block.startRef === void 0 || block.endRef === void 0) {
543
+ legacyLiveByCallId.add(block.compressCallId);
544
+ continue;
516
545
  }
546
+ let keys = liveRangeKeysByCallId.get(block.compressCallId);
547
+ if (!keys) {
548
+ keys = /* @__PURE__ */ new Set();
549
+ liveRangeKeysByCallId.set(block.compressCallId, keys);
550
+ }
551
+ keys.add(rangeKey(block.startRef, block.endRef));
517
552
  }
518
553
  const lastOrphanedCallIds = [];
519
554
  for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {
@@ -542,6 +577,16 @@ function hideConsumedCompressCalls(state, messages) {
542
577
  hidden++;
543
578
  continue;
544
579
  }
580
+ if (message.toolName === "compress" && message.contentType === "tool-call" && message.toolCallId && keepCallIds.has(message.toolCallId)) {
581
+ const liveKeys = liveRangeKeysByCallId.get(message.toolCallId);
582
+ if (liveKeys && liveKeys.size > 0 && !legacyLiveByCallId.has(message.toolCallId)) {
583
+ const rewritten = rewriteCompressText(message.text, liveKeys);
584
+ if (rewritten !== null) {
585
+ result.push({ ...message, text: rewritten });
586
+ continue;
587
+ }
588
+ }
589
+ }
545
590
  result.push(message);
546
591
  }
547
592
  return { messages: result, hidden };
@@ -802,8 +847,8 @@ function refNum(ref) {
802
847
  const n = parseInt(ref.slice(1), 10);
803
848
  return Number.isNaN(n) ? -1 : n;
804
849
  }
805
- function estimateMessageTokens(message) {
806
- return Math.ceil((message.text ?? "").length / 4);
850
+ function estimateTextTokens(text) {
851
+ return Math.ceil(text.length / 4);
807
852
  }
808
853
  function isToolMessage(message) {
809
854
  return message.contentType === "tool-call" || message.contentType === "tool-result";
@@ -815,7 +860,7 @@ function isSyntheticOrPruned(message, state) {
815
860
  }
816
861
  return false;
817
862
  }
818
- function computeProtectedRefs(messages, state, config) {
863
+ function computeProtectedRefs(messages, state, config, countTokens = estimateTextTokens) {
819
864
  const preserveN = config.preserveRecentMessages;
820
865
  const preserveTokens = config.preserveRecentTokens;
821
866
  const result = /* @__PURE__ */ new Set();
@@ -825,7 +870,7 @@ function computeProtectedRefs(messages, state, config) {
825
870
  if (isNeverPreserveRecent(msg)) continue;
826
871
  const ref = state.messageRefs.byRaw[msg.id];
827
872
  if (!ref || ref === "BLOCKED") continue;
828
- visible.push({ ref, tokens: estimateMessageTokens(msg) });
873
+ visible.push({ ref, tokens: countTokens(msg.text ?? "") });
829
874
  }
830
875
  if (preserveN > 0) {
831
876
  for (const m of visible.slice(-preserveN)) {
@@ -850,7 +895,7 @@ function computeProtectedRefs(messages, state, config) {
850
895
  }
851
896
  return result;
852
897
  }
853
- function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
898
+ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, countTokens = estimateTextTokens) {
854
899
  const compressibleMsgs = [];
855
900
  const protectedMsgs = [];
856
901
  const protectedCallIds = collectProtectedToolCallIds(messages, config);
@@ -863,7 +908,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
863
908
  protectedMsgs.push({
864
909
  ref,
865
910
  refNum: rn,
866
- tokens: estimateMessageTokens(msg),
911
+ tokens: countTokens(msg.text ?? ""),
867
912
  tools: msg.toolName ? [msg.toolName] : []
868
913
  });
869
914
  continue;
@@ -874,7 +919,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs) {
874
919
  compressibleMsgs.push({
875
920
  ref,
876
921
  refNum: rn,
877
- tokens: estimateMessageTokens(msg),
922
+ tokens: countTokens(msg.text ?? ""),
878
923
  isTool: isToolMessage(msg),
879
924
  isUser: msg.role === "user"
880
925
  });
@@ -968,7 +1013,7 @@ function createCore(ports = {}) {
968
1013
  let tokensCompressed = 0;
969
1014
  const errors = [];
970
1015
  const warnings = [];
971
- const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config);
1016
+ const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config, countTokens);
972
1017
  const preExistingCoverage = collectCoverage(state);
973
1018
  const rangeIndexSets = [];
974
1019
  for (const spec of input.ranges) {
@@ -993,29 +1038,25 @@ function createCore(ports = {}) {
993
1038
  const bMin = b.indices.length > 0 ? Math.min(...b.indices) : Infinity;
994
1039
  return aMin - bMin;
995
1040
  });
996
- for (let i = 1; i < sortedRanges.length; i++) {
997
- const prev = sortedRanges[i - 1];
998
- const curr = sortedRanges[i];
999
- const prevMax = prev.indices.length > 0 ? Math.max(...prev.indices) : -1;
1000
- const currMin = curr.indices.length > 0 ? Math.min(...curr.indices) : -1;
1001
- if (prevMax >= currMin && prevMax >= 0) {
1002
- return {
1003
- state: input.state,
1004
- result: {
1005
- blocksCreated: 0,
1006
- tokensCompressed: 0,
1007
- errors: [
1008
- `content: range (${prev.spec.startRef}..${prev.spec.endRef}) overlaps (${curr.spec.startRef}..${curr.spec.endRef}). Overlapping ranges cannot be compressed in the same batch.`
1009
- ],
1010
- warnings: []
1011
- }
1012
- };
1041
+ const skipSpecs = /* @__PURE__ */ new Set();
1042
+ let acceptedMaxIndex = -1;
1043
+ for (const entry of sortedRanges) {
1044
+ const entryMax = entry.indices.length > 0 ? Math.max(...entry.indices) : -1;
1045
+ const entryMin = entry.indices.length > 0 ? Math.min(...entry.indices) : -1;
1046
+ if (entryMin >= 0 && entryMin <= acceptedMaxIndex) {
1047
+ skipSpecs.add(entry.spec);
1048
+ warnings.push(
1049
+ `Skipped range (${entry.spec.startRef}..${entry.spec.endRef}) \u2014 overlaps an earlier range in the batch; the earlier range takes precedence. Keep ranges disjoint.`
1050
+ );
1051
+ continue;
1013
1052
  }
1053
+ if (entryMax > acceptedMaxIndex) acceptedMaxIndex = entryMax;
1014
1054
  }
1015
1055
  if (input.config.compress.minCompressRange > 0 && input.ranges.length > 0) {
1016
1056
  let totalRangeChars = 0;
1017
1057
  let hasBlockBoundaryRange = false;
1018
1058
  for (const spec of input.ranges) {
1059
+ if (skipSpecs.has(spec)) continue;
1019
1060
  let resolved;
1020
1061
  try {
1021
1062
  resolved = resolveBoundaries({
@@ -1051,6 +1092,7 @@ function createCore(ports = {}) {
1051
1092
  }
1052
1093
  }
1053
1094
  for (const spec of input.ranges) {
1095
+ if (skipSpecs.has(spec)) continue;
1054
1096
  try {
1055
1097
  const outcome = applySingleRange({
1056
1098
  spec,
@@ -1191,13 +1233,15 @@ var recommendNode = {
1191
1233
  const protectedRefs = computeProtectedRefs(
1192
1234
  io.messages,
1193
1235
  io.state,
1194
- ctx.config
1236
+ ctx.config,
1237
+ ctx.countTokens
1195
1238
  );
1196
1239
  const contextRanges = buildCompressibleRanges(
1197
1240
  io.messages,
1198
1241
  io.state,
1199
1242
  ctx.config,
1200
- protectedRefs
1243
+ protectedRefs,
1244
+ ctx.countTokens
1201
1245
  );
1202
1246
  const nothingToCompress = contextRanges.compressible.length === 0;
1203
1247
  const recommendation = {
@@ -1375,7 +1419,9 @@ function applySingleRange(input) {
1375
1419
  survivedCount: 0,
1376
1420
  generation: "young",
1377
1421
  active: true,
1378
- compressCallId: input.spec.compressCallId
1422
+ compressCallId: input.spec.compressCallId,
1423
+ startRef: input.spec.startRef,
1424
+ endRef: input.spec.endRef
1379
1425
  };
1380
1426
  input.state.blocks.push(block);
1381
1427
  for (const consumedId of consumedBlockIds) {
@@ -1870,7 +1916,7 @@ function renderNudgeText(decision) {
1870
1916
  breakdownStr,
1871
1917
  "",
1872
1918
  `[TIER ${decision.tier} ${isT2 ? "DISTILLATION" : "CONDENSATION"} TRIGGER]`,
1873
- 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.`,
1919
+ 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.`,
1874
1920
  blockList,
1875
1921
  `Example: compress({ content: [{ startId: "${startId}", endId: "${endId}", summary: "..." }] })`,
1876
1922
  "",