acp-kernel 0.0.100 → 0.0.101

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
@@ -180,11 +180,8 @@ function collectSummaryAnchors(state, baseIndexById, summaryIndexById) {
180
180
  anchors.sort((left, right) => left.insertAt - right.insertAt);
181
181
  return anchors;
182
182
  }
183
- function pairSafeAnchorIndex(messages, index) {
184
- let safe = index;
185
- while (safe > 0 && safe < messages.length && messages[safe - 1].role === "assistant" && messages[safe].role === "assistant") {
186
- safe--;
187
- }
183
+ function buildAnchorPairingIndex(messages) {
184
+ const n = messages.length;
188
185
  const resultIndexByCallId = /* @__PURE__ */ new Map();
189
186
  messages.forEach((message, at) => {
190
187
  if (message.contentType !== "tool-result") return;
@@ -193,27 +190,51 @@ function pairSafeAnchorIndex(messages, index) {
193
190
  resultIndexByCallId.set(message.toolCallId, at);
194
191
  }
195
192
  });
196
- for (let guard = 0; guard < messages.length; guard++) {
197
- let moved = safe;
198
- for (let at = 0; at < safe && at < messages.length; at++) {
199
- const message = messages[at];
200
- if (message.role !== "assistant") continue;
201
- if (message.contentType !== "tool-call") continue;
202
- if (typeof message.toolCallId !== "string") continue;
193
+ const runStart = new Int32Array(n).fill(-1);
194
+ for (let i = 0; i < n; ) {
195
+ if (messages[i].role !== "assistant") {
196
+ i++;
197
+ continue;
198
+ }
199
+ let j = i;
200
+ while (j + 1 < n && messages[j + 1].role === "assistant") j++;
201
+ for (let k = i; k <= j; k++) runStart[k] = i;
202
+ i = j + 1;
203
+ }
204
+ const prefixEnd = new Int32Array(n + 1);
205
+ for (let i = 0; i < n; i++) {
206
+ const message = messages[i];
207
+ let end = 0;
208
+ if (message.role === "assistant" && message.contentType === "tool-call" && typeof message.toolCallId === "string") {
203
209
  const resultIndex = resultIndexByCallId.get(message.toolCallId);
204
- if (resultIndex !== void 0 && resultIndex >= safe && resultIndex + 1 > moved) {
205
- moved = resultIndex + 1;
206
- }
210
+ if (resultIndex !== void 0) end = resultIndex + 1;
211
+ }
212
+ prefixEnd[i + 1] = Math.max(prefixEnd[i], end);
213
+ }
214
+ return { runStart, prefixEnd };
215
+ }
216
+ function pairSafeAnchorIndex(messages, index, ix) {
217
+ const n = messages.length;
218
+ let safe = index;
219
+ if (safe > 0 && safe < n) {
220
+ const start = ix.runStart[safe];
221
+ if (start >= 0 && messages[safe - 1].role === "assistant") {
222
+ safe = start;
207
223
  }
208
- if (moved === safe) break;
209
- safe = moved;
224
+ }
225
+ if (safe < 0 || safe > n) return safe;
226
+ for (let guard = 0; guard < n; guard++) {
227
+ const next = Math.max(safe, ix.prefixEnd[safe]);
228
+ if (next === safe) break;
229
+ safe = next;
210
230
  }
211
231
  return safe;
212
232
  }
213
233
  function rebuildMessages(messages, coveredBases, firstUserIndex, anchors) {
234
+ const ix = anchors.length > 0 ? buildAnchorPairingIndex(messages) : null;
214
235
  const safeAnchors = anchors.map((anchor) => ({
215
236
  ...anchor,
216
- insertAt: pairSafeAnchorIndex(messages, anchor.insertAt)
237
+ insertAt: ix ? pairSafeAnchorIndex(messages, anchor.insertAt, ix) : anchor.insertAt
217
238
  })).sort((left, right) => left.insertAt - right.insertAt);
218
239
  const result = [];
219
240
  const pending = [...safeAnchors];
@@ -4408,22 +4429,18 @@ function segmentGroups(items) {
4408
4429
  function estimateTextTokens(text) {
4409
4430
  return Math.ceil(text.length / 4);
4410
4431
  }
4411
- function isSyntheticOrPruned(message, state) {
4412
- if (message.text?.startsWith("[Compressed conversation section]"))
4413
- return true;
4414
- for (const block of state.blocks) {
4415
- if (block.active && block.effectiveMessageIds.includes(message.id))
4416
- return true;
4417
- }
4418
- return false;
4432
+ function isSyntheticOrPruned(message, covered) {
4433
+ if (message.text?.startsWith(SUMMARY_HEADER)) return true;
4434
+ return covered.has(message.id);
4419
4435
  }
4420
4436
  function computeProtectedRefs(messages, state, config, countTokens = estimateTextTokens) {
4421
4437
  const preserveN = config.preserveRecentMessages;
4422
4438
  const preserveTokens = config.preserveRecentTokens;
4439
+ const covered = coveredMessageIds(state);
4423
4440
  const result = /* @__PURE__ */ new Set();
4424
4441
  const visible = [];
4425
4442
  for (const msg of messages) {
4426
- if (isSyntheticOrPruned(msg, state)) continue;
4443
+ if (isSyntheticOrPruned(msg, covered)) continue;
4427
4444
  if (isNeverPreserveRecent(
4428
4445
  msg,
4429
4446
  config.neverPreserveRecentTools,
@@ -4449,7 +4466,7 @@ function computeProtectedRefs(messages, state, config, countTokens = estimateTex
4449
4466
  if (preserveN > 0) {
4450
4467
  for (let i = messages.length - 1; i >= 0; i--) {
4451
4468
  const msg = messages[i];
4452
- if (msg.role !== "user" || isSyntheticOrPruned(msg, state)) continue;
4469
+ if (msg.role !== "user" || isSyntheticOrPruned(msg, covered)) continue;
4453
4470
  const ref = state.messageRefs.byRaw[msg.id];
4454
4471
  if (ref && ref !== "BLOCKED") result.add(ref);
4455
4472
  break;
@@ -4460,6 +4477,7 @@ function computeProtectedRefs(messages, state, config, countTokens = estimateTex
4460
4477
  function buildCompressibleRanges(messages, state, config, protectedZoneRefs, countTokens = estimateTextTokens) {
4461
4478
  let compressibleMsgs = [];
4462
4479
  const protectedMsgs = [];
4480
+ const covered = coveredMessageIds(state);
4463
4481
  const protectedCallIds = collectProtectedToolCallIds(messages, config);
4464
4482
  const latest = collectLatestProtected(messages, config);
4465
4483
  for (const id of latest.callIds) protectedCallIds.add(id);
@@ -4470,7 +4488,7 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
4470
4488
  msgIndex++;
4471
4489
  const ref = state.messageRefs.byRaw[msg.id];
4472
4490
  if (!ref || ref === "BLOCKED") continue;
4473
- if (isSyntheticOrPruned(msg, state)) {
4491
+ if (isSyntheticOrPruned(msg, covered)) {
4474
4492
  skipSinceCompressible = true;
4475
4493
  skipSinceProtected = true;
4476
4494
  continue;