@cortexkit/pi-magic-context 0.49.29 → 0.49.31

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
@@ -139,6 +139,7 @@ import {
139
139
  decodePiContentDecision,
140
140
  getPiContentDecisions,
141
141
  freezePiContentDecision,
142
+ withNativeReplayWriteBarrier,
142
143
  getNativeReplayState,
143
144
  saveNativeToolInputs,
144
145
  addNativeReasoningIds,
@@ -262,7 +263,7 @@ import {
262
263
  registerTodoStateLifecycle,
263
264
  syncCtxMemoryToolEnabled,
264
265
  registerMagicContextTools
265
- } from "./index-00p6t4nd.js";
266
+ } from "./index-2nryd8ye.js";
266
267
  import"./index-4knyh1kt.js";
267
268
  import {
268
269
  canonicalModelIdentity,
@@ -304,7 +305,7 @@ import {
304
305
  openCurrentDatabase,
305
306
  openDatabaseAsync,
306
307
  closeDatabase
307
- } from "./index-9pfffeqj.js";
308
+ } from "./index-xvqcqg0r.js";
308
309
  import {
309
310
  sameProjectDirectory,
310
311
  pruneMissingProjectIdentities,
@@ -329,6 +330,7 @@ import {
329
330
  HYGIENE_PROVIDER_UNITS_VERSION,
330
331
  sessionDecisionCalibration,
331
332
  transitionSessionHygieneUnits,
333
+ rowWindowMass,
332
334
  computeProtectionWindow,
333
335
  readEpochFloorSnapshot,
334
336
  getProtectionWindowForSession,
@@ -450,6 +452,7 @@ import {
450
452
  isInActiveAnthropicTurn,
451
453
  activeAnthropicTurnStart,
452
454
  hasAnthropicReasoning,
455
+ isMarkerOnlyText,
453
456
  findLatestAssistantReasoningMutationExemptMessage,
454
457
  DEFAULT_KEEP_REASONING_TOKENS,
455
458
  resolveKeepReasoningTokens,
@@ -480,7 +483,7 @@ import {
480
483
  getRawSessionTagKeysThrough2,
481
484
  getLegacyProtectedTailStartOrdinal2,
482
485
  readSessionChunk2
483
- } from "./index-yvb1cz6b.js";
486
+ } from "./index-34e3mm36.js";
484
487
  import {
485
488
  UNKNOWN_FIT_RATIO,
486
489
  hasMeasuredDecisionCalibration,
@@ -598,6 +601,7 @@ import {
598
601
  stableStringify,
599
602
  closeQuietly,
600
603
  isKnownAutocommit,
604
+ getTableColumnNames,
601
605
  observeTemporalDecisions,
602
606
  freezeTemporalDecisions,
603
607
  tagIdentityRevisionKey
@@ -680,7 +684,7 @@ import {
680
684
  isMessageIndexReconciledThrough,
681
685
  indexSingleMessage,
682
686
  indexMessagesAfterOrdinal
683
- } from "./index-vppykq05.js";
687
+ } from "./index-yddeb86g.js";
684
688
  import {
685
689
  rememberV1HiddenRun
686
690
  } from "./index-6x556c2q.js";
@@ -745,7 +749,7 @@ import {
745
749
  normalizeVerificationFiles,
746
750
  indexCommitsForProject,
747
751
  embedUnembeddedCommits
748
- } from "./index-wcma874r.js";
752
+ } from "./index-bpd654bz.js";
749
753
  import {
750
754
  setEmbeddingSessionBusy2,
751
755
  isEmbeddingHostBusy2
@@ -801,7 +805,7 @@ import {
801
805
  PiContextSupersededError,
802
806
  PiContextBudget,
803
807
  PiTagHydrationError,
804
- getPiTagSnapshotView,
808
+ getPiPassTagSnapshotView,
805
809
  getPiActiveTagSnapshotView,
806
810
  readPiFallbackTagRows,
807
811
  prewarmPiTagSnapshot,
@@ -809,10 +813,10 @@ import {
809
813
  drainPiTagSnapshotSession,
810
814
  assertPiTagSnapshotReady,
811
815
  ensurePiTagSnapshotReady
812
- } from "./index-f1pcnedq.js";
816
+ } from "./index-v40sm8q6.js";
813
817
  import"./index-jn44h81p.js";
814
818
  import"./index-1cvyaw9a.js";
815
- import"./index-fp40yrsy.js";
819
+ import"./index-sr1ss4f8.js";
816
820
  import {
817
821
  __toESM
818
822
  } from "./index-22jkk6wg.js";
@@ -3557,7 +3561,7 @@ function startHostStallProfilerSwitch() {
3557
3561
  // package.json
3558
3562
  var package_default = {
3559
3563
  name: "@cortexkit/pi-magic-context",
3560
- version: "0.49.29",
3564
+ version: "0.49.31",
3561
3565
  type: "module",
3562
3566
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
3563
3567
  main: "dist/index.js",
@@ -3623,12 +3627,14 @@ var package_default = {
3623
3627
  "@types/node": "^22.20.0",
3624
3628
  "omp-coding-agent-1812": "npm:@oh-my-pi/pi-coding-agent@18.12.3",
3625
3629
  "omp-coding-agent-18126": "npm:@oh-my-pi/pi-coding-agent@18.12.6",
3630
+ "omp-coding-agent-18132": "npm:@oh-my-pi/pi-coding-agent@18.13.2",
3626
3631
  "omp-pi-ai-171": "npm:@oh-my-pi/pi-ai@17.1.7",
3627
3632
  "omp-pi-ai-1889": "npm:@oh-my-pi/pi-ai@18.8.9",
3628
3633
  "omp-pi-ai-1811": "npm:@oh-my-pi/pi-ai@18.11.3",
3629
3634
  "omp-pi-ai-1812": "npm:@oh-my-pi/pi-ai@18.12.3",
3630
3635
  "omp-pi-ai-18126": "npm:@oh-my-pi/pi-ai@18.12.6",
3631
3636
  "omp-pi-ai-1813": "npm:@oh-my-pi/pi-ai@18.13.0",
3637
+ "omp-pi-ai-18132": "npm:@oh-my-pi/pi-ai@18.13.2",
3632
3638
  "pi-agent-core-087": "npm:@earendil-works/pi-agent-core@0.87.1",
3633
3639
  "pi-ai-086": "npm:@earendil-works/pi-ai@0.86.0",
3634
3640
  "pi-ai-087": "npm:@earendil-works/pi-ai@0.87.1",
@@ -14760,7 +14766,6 @@ function parseMapMemoriesManifest(text) {
14760
14766
  }
14761
14767
  function validateMapMemoriesManifest(text, expectedIds) {
14762
14768
  const parsed = parseMapMemoriesManifest(text);
14763
- assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "mappings", "memory");
14764
14769
  assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
14765
14770
  return parsed;
14766
14771
  }
@@ -16947,8 +16952,7 @@ function parsePartialVerifyManifest(text, expectedIds) {
16947
16952
  var VERIFY_BATCH_SIZE = 5;
16948
16953
  var VERIFY_TOKENS_PER_MEMORY = 1e5;
16949
16954
  var VERIFY_RUN_TOKEN_BUDGET = 2500000;
16950
- var VERIFY_RUN_SLICE_MS = 240000;
16951
- var VERIFY_IN_FLIGHT_GRACE_MS = 120000;
16955
+ var VERIFY_BATCH_DEFAULT_MS = 240000;
16952
16956
  function verifyBatchTokenBudget(size, configured) {
16953
16957
  return Math.min(configured ?? Number.MAX_SAFE_INTEGER, size * VERIFY_TOKENS_PER_MEMORY);
16954
16958
  }
@@ -16978,8 +16982,8 @@ function validateVerifyCompletion(messages, text, expectedIds, responseText = te
16978
16982
  }
16979
16983
  var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
16980
16984
  var VERIFY_BATCH_FLOOR_MS = 30000;
16981
- function computeVerifyBatchSliceMs(remainingMs, _batchesRemaining) {
16982
- return Math.min(remainingMs, VERIFY_RUN_SLICE_MS);
16985
+ function computeVerifyBatchSliceMs(remainingMs, batchesRemaining) {
16986
+ return Math.min(remainingMs, Math.max(VERIFY_BATCH_DEFAULT_MS, remainingMs / Math.max(1, batchesRemaining)));
16983
16987
  }
16984
16988
  function closeBroadCycle(args, cycleStartAt) {
16985
16989
  if (!args.forceBroad || cycleStartAt === undefined)
@@ -17003,7 +17007,6 @@ async function runVerify(args) {
17003
17007
  }
17004
17008
  async function runVerifyWithCooldown(args) {
17005
17009
  const runStartedAt = Date.now();
17006
- const sliceDeadline = runStartedAt + VERIFY_RUN_SLICE_MS;
17007
17010
  const result = {
17008
17011
  verified: 0,
17009
17012
  updated: 0,
@@ -17051,12 +17054,10 @@ async function runVerifyWithCooldown(args) {
17051
17054
  try {
17052
17055
  for (let i = 0;i < batches.length; i += 1) {
17053
17056
  const now = Date.now();
17054
- const startCutoff = Math.min(args.deadline, sliceDeadline);
17055
- const hardStop = Math.min(args.deadline, sliceDeadline + VERIFY_IN_FLIGHT_GRACE_MS);
17056
- const remainingMs = Math.max(0, hardStop - now);
17057
- if (now >= startCutoff) {
17057
+ const remainingMs = Math.max(0, args.deadline - now);
17058
+ if (now >= args.deadline) {
17058
17059
  result.stopReason = "deadline";
17059
- log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — the run deadline passed ${now - startCutoff}ms ago`);
17060
+ log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — the run deadline passed ${now - args.deadline}ms ago`);
17060
17061
  break;
17061
17062
  }
17062
17063
  if (remainingMs < VERIFY_BATCH_FLOOR_MS) {
@@ -17995,7 +17996,7 @@ function createDreamTaskExecutor(deps) {
17995
17996
  return { status: "failed", transient: true, error };
17996
17997
  }
17997
17998
  const processed = result.mapped + result.independent;
17998
- if (processed > 0) {
17999
+ if (processed > 0 || result.failure === undefined) {
17999
18000
  const progress = `map-memories: committed ${processed} mapping(s) (mapped ${result.mapped}, independent ${result.independent}); ${result.remaining} remain`;
18000
18001
  recordRun("completed", null, { progress });
18001
18002
  return { status: "completed" };
@@ -22425,7 +22426,7 @@ function normalizePiUserEntry(entry, sessionId, ordinal, followsAssistantReply)
22425
22426
  return null;
22426
22427
  if (message.role !== "user" || typeof message.timestamp !== "number")
22427
22428
  return null;
22428
- const text = extractPiTextContent(message.content).trim();
22429
+ const text = cleanUserText2(extractPiTextContent(message.content));
22429
22430
  if (!text)
22430
22431
  return null;
22431
22432
  return {
@@ -22459,7 +22460,7 @@ function extractPiTextContent(content) {
22459
22460
  if (part === null || typeof part !== "object")
22460
22461
  return [];
22461
22462
  const record = part;
22462
- return record.type === "text" && typeof record.text === "string" ? [record.text] : [];
22463
+ return record.synthetic !== true && record.type === "text" && typeof record.text === "string" ? [record.text] : [];
22463
22464
  }).join(`
22464
22465
  `);
22465
22466
  }
@@ -24955,6 +24956,7 @@ function prepareLegacyToolSkeletonConversions(db, sessionId, targets, options =
24955
24956
  });
24956
24957
  };
24957
24958
  const rows = readRows(db);
24959
+ options.prepareRemovals?.(rows);
24958
24960
  const converted = new Map;
24959
24961
  for (const row of rows) {
24960
24962
  const target = targets.get(row.tagNumber);
@@ -25186,6 +25188,15 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
25186
25188
  }
25187
25189
  return didMutateMessage;
25188
25190
  }
25191
+ function prepareFlushedToolRemovals(targets, tags) {
25192
+ for (const tag of tags) {
25193
+ if (tag.status !== "dropped" || tag.type !== "tool")
25194
+ continue;
25195
+ if (tag.dropMode != null && tag.dropMode !== "full")
25196
+ continue;
25197
+ targets.get(tag.tagNumber)?.prepareReplayDrop?.();
25198
+ }
25199
+ }
25189
25200
  function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
25190
25201
  let didMutateMessage = false;
25191
25202
  const tags = preloadedTags ?? getDroppedTagsByNumbers2(db, sessionId, [...targets.keys()]);
@@ -27882,7 +27893,7 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
27882
27893
  skipPrefixInjection,
27883
27894
  preserveTagOnlyAssistantText: options.preserveTagOnlyAssistantText,
27884
27895
  entryFingerprint: options.entryFingerprintByMessageId?.get(messageId) ?? null,
27885
- reuseIdentity: reuseIdentity || contentDerivedTextIds !== undefined,
27896
+ reuseIdentity: reuseIdentity || options.reuseTextMessageIds?.has(messageId) === true || contentDerivedTextIds !== undefined,
27886
27897
  timing,
27887
27898
  textIdentitySourceCache: options.textIdentitySourceCache,
27888
27899
  textTokenCache: options.textTokenCache
@@ -27951,7 +27962,11 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
27951
27962
  if (timing)
27952
27963
  timing.identity += performance.now() - identityStart;
27953
27964
  } else {
27954
- const accounting = readAggregateToolAccounting(part, timing, options.toolTokenCache, tokenCacheKey);
27965
+ const accounting = readAggregateToolAccounting(part, timing, options.toolTokenCache, tokenCacheKey, {
27966
+ byteSize: existing.maxByteSize,
27967
+ tokenCount: existing.maxTokenCount,
27968
+ inputTokenCount: existing.inputTokenCount
27969
+ });
27955
27970
  text = accounting.text;
27956
27971
  if (part.kind === "tool_result") {
27957
27972
  applyGrownToolResultAccounting({
@@ -28033,7 +28048,7 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
28033
28048
  if (timing)
28034
28049
  timing.identity += performance.now() - identityStart;
28035
28050
  } else {
28036
- const accounting = readAggregateToolAccounting(part, timing, options.toolTokenCache, tokenCacheKey);
28051
+ const accounting = readAggregateToolAccounting(part, timing, options.toolTokenCache, tokenCacheKey, tagger.getToolTagAccounting(sessionId, callId, messageId));
28037
28052
  text = accounting.text;
28038
28053
  const outputByteSize = part.kind === "tool_result" ? accounting.byteSize : 0;
28039
28054
  const outputTokenCount = part.kind === "tool_result" ? accounting.tokenCount : 0;
@@ -28129,12 +28144,14 @@ function applyGrownToolResultAccounting(args) {
28129
28144
  updateTagTokenCount2(args.db, args.sessionId, args.aggregate.tagId, tokenCount);
28130
28145
  syncToolAggregateAccounting(args.tagger, args.sessionId, args.aggregate);
28131
28146
  }
28132
- function readAggregateToolAccounting(part, timing, tokenCache, tokenCacheKey) {
28147
+ function readAggregateToolAccounting(part, timing, tokenCache, tokenCacheKey, persisted) {
28133
28148
  const text = part.getText() ?? "";
28134
28149
  const byteSize = getToolPartByteSize(part, text);
28135
- const metadata = part.getToolMetadata();
28150
+ const metadata = part.getToolMetadata({
28151
+ skipInputTokenCount: persisted?.inputTokenCount != null
28152
+ });
28136
28153
  let tokenCount = 0;
28137
- if (part.kind === "tool_result") {
28154
+ if (part.kind === "tool_result" && (!persisted || persisted.tokenCount === null || byteSize > persisted.byteSize)) {
28138
28155
  const tokenStart = timing ? performance.now() : 0;
28139
28156
  tokenCount = getCachedToolPartTokenCount(part, text, tokenCache, tokenCacheKey);
28140
28157
  if (timing)
@@ -28521,6 +28538,12 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
28521
28538
  return any ? "truncated" : "absent";
28522
28539
  },
28523
28540
  prepareDrop: () => !occurrences.some((occ) => occ.part.canRemove?.() === "defer"),
28541
+ prepareReplayDrop: () => {
28542
+ if (complete() && !requiresToolArcSkeleton) {
28543
+ for (const occ of occurrences)
28544
+ occ.part.canRemove?.();
28545
+ }
28546
+ },
28524
28547
  canDrop: () => complete() && !occurrences.some((occ) => occ.part.hasUserAnswer?.()),
28525
28548
  requiresToolArcSkeleton,
28526
28549
  readInput() {
@@ -31357,7 +31380,8 @@ function tagAttribution(input) {
31357
31380
  if (!cached) {
31358
31381
  removed.length = 0;
31359
31382
  added.length = 0;
31360
- added.push(...input.tags);
31383
+ for (const tag of input.tags)
31384
+ added.push(tag);
31361
31385
  cached = {
31362
31386
  tags: input.tags,
31363
31387
  messageTags: new Map,
@@ -31446,7 +31470,10 @@ function attributeTags(input, arcs, messageIds) {
31446
31470
  exactToolTags,
31447
31471
  orphanTagsByCall,
31448
31472
  boundsByOwner
31449
- } = tagAttribution(input);
31473
+ } = tagAttribution({
31474
+ ...input,
31475
+ tags: attributionProjection(input, arcs, messageIds)
31476
+ });
31450
31477
  const messageIndexById = new Map;
31451
31478
  for (let index = 0;index < messageIds.length; index += 1) {
31452
31479
  const id = input.stableId?.(input.messages[index], index);
@@ -31509,6 +31536,61 @@ function attributeTags(input, arcs, messageIds) {
31509
31536
  }
31510
31537
  return { messageTags, tagsByNumber };
31511
31538
  }
31539
+ var attributionProjections = new WeakMap;
31540
+ function attributionProjection(input, arcs, messageIds) {
31541
+ const owners = new Set(messageIds);
31542
+ const calls = new Set;
31543
+ const numbers = new Set;
31544
+ for (const arc of arcs) {
31545
+ owners.add(arc.ownerId);
31546
+ calls.add(arc.callId);
31547
+ }
31548
+ const notePrefix = (text) => {
31549
+ for (const candidate of [text, stripChannel1ReminderSpans(text)]) {
31550
+ const match = candidate.trimStart().match(TAG_PREFIX);
31551
+ if (match)
31552
+ numbers.add(Number(match[1]));
31553
+ }
31554
+ };
31555
+ for (let index = 0;index < input.messages.length; index++) {
31556
+ const id = input.stableId?.(input.messages[index], index);
31557
+ if (id)
31558
+ owners.add(id);
31559
+ const message = input.messages[index];
31560
+ if (!isRecord5(message))
31561
+ continue;
31562
+ if (typeof message.content === "string")
31563
+ notePrefix(message.content);
31564
+ else if (Array.isArray(message.content)) {
31565
+ for (const part of message.content)
31566
+ if (isRecord5(part) && typeof part.text === "string")
31567
+ notePrefix(part.text);
31568
+ }
31569
+ }
31570
+ const cacheable = input.tagCacheKey !== undefined;
31571
+ const cached = cacheable ? attributionProjections.get(input.tags) : undefined;
31572
+ const content = cacheable ? input.messages.map(safeStableStringify) : undefined;
31573
+ if (cached && cached.messageIds.length === messageIds.length && messageIds.every((id, index) => id === cached.messageIds[index]) && content?.length === cached.content.length && content.every((value, index) => value === cached.content[index]) && owners.size === cached.owners.size && [...owners].every((owner) => cached.owners.has(owner)) && calls.size === cached.calls.size && [...calls].every((call) => cached.calls.has(call)) && numbers.size === cached.numbers.size && [...numbers].every((number) => cached.numbers.has(number)))
31574
+ return cached.projection;
31575
+ const projection = input.tags.filter((tag) => {
31576
+ if (numbers.has(tag.tagNumber))
31577
+ return true;
31578
+ const owner = messageIdForTag(tag);
31579
+ if (owner !== null && owners.has(owner))
31580
+ return true;
31581
+ return tag.type === "tool" && tag.toolOwnerMessageId === null && calls.has(tag.messageId);
31582
+ });
31583
+ if (cacheable && content)
31584
+ attributionProjections.set(input.tags, {
31585
+ messageIds,
31586
+ content,
31587
+ owners,
31588
+ calls,
31589
+ numbers,
31590
+ projection
31591
+ });
31592
+ return projection;
31593
+ }
31512
31594
  var partJsonMemo = new TailHygieneJsonMemo;
31513
31595
  var excludedViews = new WeakMap;
31514
31596
  function excludedDraftForApi(key, value, providerApi) {
@@ -33380,6 +33462,26 @@ async function executeContextRecompWithResult(deps, options = {}) {
33380
33462
  }
33381
33463
 
33382
33464
  // ../plugin/src/hooks/magic-context/history-boundary-repair.ts
33465
+ function readStoreBoundaries(db, sessionId) {
33466
+ const columns = getTableColumnNames(db, "compartments");
33467
+ const numbers = ["id", "sequence", "start_message", "end_message", "created_at"];
33468
+ const strings = ["session_id", "start_message_id", "end_message_id", "title", "content"];
33469
+ const predicates = [...numbers, ...strings].every((column) => columns.has(column)) ? [
33470
+ ...numbers.map((column) => `typeof(${column}) IN ('integer', 'real')`),
33471
+ ...strings.map((column) => `typeof(${column}) = 'text'`)
33472
+ ] : ["0"];
33473
+ for (const column of ["p1", "p2", "p3", "p4", "episode_type"]) {
33474
+ if (columns.has(column))
33475
+ predicates.push(`typeof(${column}) IN ('text', 'null')`);
33476
+ }
33477
+ for (const column of ["importance", "legacy"]) {
33478
+ if (columns.has(column))
33479
+ predicates.push(`typeof(${column}) IN ('integer', 'real', 'null')`);
33480
+ }
33481
+ return db.prepare(`SELECT sequence, ${columns.has("end_message_id") ? "end_message_id" : "NULL"} AS endMessageId
33482
+ FROM compartments WHERE session_id = ? AND ${predicates.join(" AND ")}
33483
+ ORDER BY sequence ASC`).all(sessionId);
33484
+ }
33383
33485
  function readBaseline(db, sessionId) {
33384
33486
  const row = db.prepare("SELECT cached_m0_bytes IS NOT NULL AS hasM0, cached_m0_last_baseline_end_message_id AS boundary FROM session_meta WHERE session_id = ?").get(sessionId);
33385
33487
  return {
@@ -33446,7 +33548,7 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = f
33446
33548
  }
33447
33549
  function repairMissingHistoryBoundary(args) {
33448
33550
  const { db, sessionId, isInHostStore, scope = "store" } = args;
33449
- const compartments = scope === "active-branch" ? db.prepare("SELECT sequence, COALESCE(end_message_id, '') AS endMessageId FROM compartments WHERE session_id = ? ORDER BY sequence").all(sessionId) : getCompartments(db, sessionId);
33551
+ const compartments = scope === "active-branch" ? db.prepare("SELECT sequence, COALESCE(end_message_id, '') AS endMessageId FROM compartments WHERE session_id = ? ORDER BY sequence").all(sessionId) : readStoreBoundaries(db, sessionId);
33450
33552
  let latestIndex = compartments.length - 1;
33451
33553
  while (latestIndex >= 0 && !compartments[latestIndex]?.endMessageId)
33452
33554
  latestIndex -= 1;
@@ -33490,7 +33592,7 @@ function repairMissingHistoryBoundary(args) {
33490
33592
  let dropped;
33491
33593
  let anchorForDrop = anchor;
33492
33594
  try {
33493
- if (scope === "active-branch" && anchor) {
33595
+ if (anchor) {
33494
33596
  const row = db.prepare("SELECT end_message AS endMessage FROM compartments WHERE session_id = ? AND sequence = ?").get(sessionId, anchor.sequence);
33495
33597
  if (!row)
33496
33598
  return { kind: "unresolved", reason: "busy", missingEndMessageId: missing };
@@ -35199,6 +35301,76 @@ function canRemoveNativeToolCall(message, toolCallId) {
35199
35301
  var NATIVE_TOOL_REMOVAL_MARKER = '{"__magic_context_remove_tool_arc__":true}';
35200
35302
 
35201
35303
  // src/native-replay-state-pi.ts
35304
+ var removalBatches = new WeakMap;
35305
+
35306
+ class PiToolRemovalBatchError extends Error {
35307
+ constructor(cause) {
35308
+ super("Native tool removal batch could not be persisted", { cause });
35309
+ }
35310
+ }
35311
+ function withPiToolRemovalBatch(args, edit) {
35312
+ let sessions = removalBatches.get(args.db);
35313
+ const enclosing = sessions?.get(args.sessionId);
35314
+ if (enclosing)
35315
+ return edit(enclosing.flush);
35316
+ if (!sessions) {
35317
+ sessions = new Map;
35318
+ removalBatches.set(args.db, sessions);
35319
+ }
35320
+ let publishing = false;
35321
+ const batch = {
35322
+ saved: args.saved,
35323
+ planned: new Map(args.saved),
35324
+ requested: new Map,
35325
+ pending: new Map,
35326
+ flushed: false,
35327
+ flush() {
35328
+ if (batch.flushed)
35329
+ return;
35330
+ batch.persistPending();
35331
+ batch.flushed = true;
35332
+ },
35333
+ persistPending() {
35334
+ if (publishing || batch.pending.size === 0)
35335
+ return;
35336
+ const connection = args.db;
35337
+ if (connection.inTransaction !== true && connection.isTransaction !== true)
35338
+ throw new Error("Native removal publication requires a caller-owned transaction");
35339
+ try {
35340
+ publishing = true;
35341
+ saveNativeToolInputs(args.db, args.sessionId, batch.pending);
35342
+ batch.pending.clear();
35343
+ } catch (cause) {
35344
+ throw new PiToolRemovalBatchError(cause);
35345
+ } finally {
35346
+ publishing = false;
35347
+ }
35348
+ }
35349
+ };
35350
+ sessions.set(args.sessionId, batch);
35351
+ try {
35352
+ const result = withNativeReplayWriteBarrier(args.db, args.sessionId, batch.persistPending, () => edit(batch.flush));
35353
+ if (batch.requested.size > 0 && !batch.flushed)
35354
+ throw new Error("Native removal markers were not flushed in the caller's transaction");
35355
+ const saved = args.saved;
35356
+ if (saved && batch.requested.size > 0) {
35357
+ const prior = new Map([...batch.requested.keys()].map((id) => [id, saved.get(id)]));
35358
+ args.rollbackObservations?.push(() => {
35359
+ for (const [id, value] of prior) {
35360
+ if (value === undefined)
35361
+ saved.delete(id);
35362
+ else
35363
+ saved.set(id, value);
35364
+ }
35365
+ });
35366
+ for (const [id, marker] of batch.requested)
35367
+ saved.set(id, marker);
35368
+ }
35369
+ return result;
35370
+ } finally {
35371
+ sessions.delete(args.sessionId);
35372
+ }
35373
+ }
35202
35374
  function applyNativeToolInputReplayPi(args, saved) {
35203
35375
  if (saved.size === 0 && (!args.canApply || args.changes.size === 0))
35204
35376
  return 0;
@@ -35310,6 +35482,12 @@ function applyNativeReasoningReplayPi(args, saved) {
35310
35482
  function preparePiToolRemovalMeasurements(args) {
35311
35483
  if (!args.saved || !args.canApply)
35312
35484
  return;
35485
+ const batch = removalBatches.get(args.db)?.get(args.sessionId);
35486
+ if (batch?.saved === args.saved) {
35487
+ for (const callId of args.callIds)
35488
+ authorizePiToolRemoval({ ...args, callId });
35489
+ return;
35490
+ }
35313
35491
  const requested = new Map;
35314
35492
  for (const callId of args.callIds) {
35315
35493
  if (args.saved.get(callId) !== NATIVE_TOOL_REMOVAL_MARKER)
@@ -35325,9 +35503,54 @@ function preparePiToolRemovalMeasurements(args) {
35325
35503
  args.saved.set(callId, marker);
35326
35504
  } catch {}
35327
35505
  }
35506
+ function preparePiToolRemovalChecks(args) {
35507
+ if (!args.db?.inTransaction || args.rows.length === 0)
35508
+ return;
35509
+ const occurrences = new Map;
35510
+ for (const raw of args.messages) {
35511
+ if (!raw || typeof raw !== "object")
35512
+ continue;
35513
+ const message = raw;
35514
+ if (message.role !== "assistant" || !Array.isArray(message.content))
35515
+ continue;
35516
+ for (const rawPart of message.content) {
35517
+ if (!rawPart || typeof rawPart !== "object")
35518
+ continue;
35519
+ const part = rawPart;
35520
+ if (part.type === "toolCall" && typeof part.id === "string")
35521
+ occurrences.set(part.id, (occurrences.get(part.id) ?? 0) + 1);
35522
+ }
35523
+ }
35524
+ const requested = [];
35525
+ for (const row of args.rows) {
35526
+ if (row.callId === null || occurrences.get(row.callId) !== 1)
35527
+ continue;
35528
+ const target = args.targets.get(row.tagNumber);
35529
+ if (target?.requiresToolArcSkeleton || target?.canDrop?.() !== true)
35530
+ continue;
35531
+ if (!target.mutationParts?.some(({ part }) => part !== null && typeof part === "object" && ("kind" in part) && part.kind === "tool_use" && ("id" in part) && part.id === row.callId))
35532
+ continue;
35533
+ requested.push(row.callId);
35534
+ }
35535
+ if (requested.length)
35536
+ args.prepare(requested);
35537
+ }
35328
35538
  function authorizePiToolRemoval(args) {
35329
35539
  if (!args.saved)
35330
35540
  return false;
35541
+ const batch = removalBatches.get(args.db)?.get(args.sessionId);
35542
+ if (batch?.saved === args.saved) {
35543
+ if (batch.planned.get(args.callId) === NATIVE_TOOL_REMOVAL_MARKER)
35544
+ return true;
35545
+ if (!args.canApply)
35546
+ return false;
35547
+ if (batch.flushed)
35548
+ throw new Error("Tool removal requested after lane publication");
35549
+ batch.planned.set(args.callId, NATIVE_TOOL_REMOVAL_MARKER);
35550
+ batch.requested.set(args.callId, NATIVE_TOOL_REMOVAL_MARKER);
35551
+ batch.pending.set(args.callId, NATIVE_TOOL_REMOVAL_MARKER);
35552
+ return true;
35553
+ }
35331
35554
  if (args.saved.get(args.callId) === NATIVE_TOOL_REMOVAL_MARKER)
35332
35555
  return true;
35333
35556
  if (!args.canApply)
@@ -35384,6 +35607,57 @@ function isSentinelPart(part) {
35384
35607
  return p.type === "text" && typeof p.text === "string" && (p.text === "" || p.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT);
35385
35608
  }
35386
35609
 
35610
+ // src/pass-tag-projection-pi.ts
35611
+ function projectPiReplayDrops(transcript, metadata) {
35612
+ const owners = new Set;
35613
+ const addresses = new Set;
35614
+ const calls = new Set;
35615
+ const prefixes = new Set;
35616
+ for (const message of transcript.messages) {
35617
+ owners.add(message.info.id ?? "");
35618
+ let ordinal = 0;
35619
+ for (const part of message.parts) {
35620
+ if (part.kind === "text") {
35621
+ addresses.add(`${message.info.id}:p${ordinal++}`);
35622
+ const prefix = /^§(\d+)§\s/.exec(part.getText() ?? "");
35623
+ if (prefix)
35624
+ prefixes.add(Number(prefix[1]));
35625
+ } else if ((part.kind === "tool_use" || part.kind === "tool_result") && part.id)
35626
+ calls.add(part.id);
35627
+ }
35628
+ }
35629
+ const numbers = new Set;
35630
+ for (const tag of metadata) {
35631
+ if (tag.status !== "dropped")
35632
+ continue;
35633
+ if (prefixes.has(tag.tagNumber) || (tag.type === "tool" ? calls.has(tag.messageId) && (tag.toolOwnerMessageId === null || tag.toolOwnerMessageId === "" || owners.has(tag.toolOwnerMessageId)) : addresses.has(tag.messageId)))
35634
+ numbers.add(tag.tagNumber);
35635
+ }
35636
+ return metadata.filter((tag) => tag.status === "dropped" && numbers.has(tag.tagNumber));
35637
+ }
35638
+ function protectedPiPassTagNumbers(rows, floor, toolsRatio = 1) {
35639
+ if (!(toolsRatio >= 0) || rows.some((row) => !Number.isFinite(row.tagNumber)))
35640
+ return computeProtectionWindow(rows, floor, toolsRatio).protectedTagNumbers;
35641
+ const numbers = [];
35642
+ let group;
35643
+ let groups = 0;
35644
+ let mass = 0;
35645
+ for (let index = rows.length - 1;index >= 0; index--) {
35646
+ const row = rows[index];
35647
+ if (row?.type !== "tool")
35648
+ continue;
35649
+ if (row.tagNumber !== group) {
35650
+ if (groups >= 3 && Math.ceil(mass * toolsRatio) >= floor)
35651
+ break;
35652
+ group = row.tagNumber;
35653
+ groups++;
35654
+ numbers.push(row.tagNumber);
35655
+ }
35656
+ mass += rowWindowMass(row);
35657
+ }
35658
+ return new Set(numbers.reverse());
35659
+ }
35660
+
35387
35661
  // src/pi-append-compaction.ts
35388
35662
  var loggedIncompatibleHost = false;
35389
35663
  var failedWrites2 = new WeakMap;
@@ -36540,23 +36814,113 @@ function piMatchesChatImages(content, urls) {
36540
36814
  return true;
36541
36815
  }
36542
36816
 
36543
- // src/pi-dispatch-image-budget.ts
36817
+ // src/pi-dispatch-date-reminder.ts
36544
36818
  function object8(value) {
36545
36819
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
36546
36820
  }
36821
+ function piDateReminderText(value, cwd) {
36822
+ if (typeof value !== "string")
36823
+ return false;
36824
+ const match = /^<system-reminder>\nToday: (\d{4}-\d{2}-\d{2}); current working directory: '([^\r\n<>§]+)'\. Do not repeat this information in your reply\.\n<\/system-reminder>$/u.exec(value);
36825
+ if (!match)
36826
+ return false;
36827
+ const [, date, path] = match;
36828
+ if ([...path].some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127))
36829
+ return false;
36830
+ const parsed = new Date(`${date}T00:00:00Z`);
36831
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString().slice(0, 10) !== date)
36832
+ return false;
36833
+ if (!/^(?:\/|[A-Za-z]:\/)/u.test(path) || path.includes("\\"))
36834
+ return false;
36835
+ return cwd === undefined || path === cwd.replace(/\\/gu, "/");
36836
+ }
36837
+ function piDateReminderWireText(content, cwd) {
36838
+ if (typeof content === "string")
36839
+ return piDateReminderText(content, cwd) ? content : undefined;
36840
+ if (!Array.isArray(content) || content.length !== 1)
36841
+ return;
36842
+ const block = object8(content[0]);
36843
+ const cache = object8(block?.cache_control);
36844
+ if (block?.type !== "text" || !cache || cache.type !== "ephemeral" || Object.keys(block).some((key) => !["type", "text", "cache_control"].includes(key)) || Object.keys(cache).some((key) => !["type", "ttl", "scope"].includes(key)) || cache.ttl !== undefined && cache.ttl !== "5m" && cache.ttl !== "1h" || cache.scope !== undefined && cache.scope !== "global")
36845
+ return;
36846
+ return piDateReminderText(block.text, cwd) ? block.text : undefined;
36847
+ }
36848
+ var PI_DATE_REMINDER_APIS = new Set([
36849
+ "anthropic-messages",
36850
+ "openai-completions",
36851
+ "openai-responses",
36852
+ "azure-openai-responses",
36853
+ "openai-codex-responses",
36854
+ "bedrock-converse-stream",
36855
+ "google-generative-ai",
36856
+ "google-vertex",
36857
+ "google-gemini-cli",
36858
+ "ollama-chat"
36859
+ ]);
36860
+ function singleText(value, type) {
36861
+ if (!Array.isArray(value) || value.length !== 1)
36862
+ return;
36863
+ const part = object8(value[0]);
36864
+ return part && (type === undefined ? Object.keys(part).length === 1 : part.type === type && Object.keys(part).length === 2) ? part.text : undefined;
36865
+ }
36866
+ function piWithoutDateReminders(payload, api, cwd, developerRole, includesPreparedFirstUser) {
36867
+ const body = object8(payload);
36868
+ if (!body)
36869
+ return;
36870
+ const google = api.startsWith("google-");
36871
+ const envelope = google ? object8(body.request) ?? body : body;
36872
+ const field = google ? "contents" : api.endsWith("responses") ? "input" : "messages";
36873
+ const messages = envelope[field];
36874
+ if (!Array.isArray(messages))
36875
+ return;
36876
+ let firstUser = false;
36877
+ let removed = false;
36878
+ const kept = [];
36879
+ for (const value of messages) {
36880
+ const row = object8(value);
36881
+ if (!row)
36882
+ return;
36883
+ const text = google ? singleText(row.parts) : api === "bedrock-converse-stream" ? singleText(row.content) : api.endsWith("responses") ? singleText(row.content, "input_text") ?? (api === "openai-codex-responses" ? row.content : undefined) : row.content;
36884
+ if (piDateReminderText(text, cwd)) {
36885
+ const keys = google ? ["role", "parts"] : api.endsWith("responses") ? ["role", "content", "type"] : ["role", "content"];
36886
+ const role = api === "ollama-chat" ? "system" : api === "openai-completions" && developerRole ? "developer" : "user";
36887
+ if (!firstUser || row.role !== role || Object.keys(row).some((key) => !keys.includes(key)) || row.type !== undefined && row.type !== "message")
36888
+ return;
36889
+ if (!removed) {
36890
+ const prefix = { ...envelope, [field]: kept };
36891
+ if (!includesPreparedFirstUser(google && body.request !== undefined ? { ...body, request: prefix } : prefix))
36892
+ return;
36893
+ }
36894
+ removed = true;
36895
+ continue;
36896
+ }
36897
+ if (row.role === "user" && (typeof row.content === "string" || Array.isArray(row.content) && row.content.some((part) => object8(part)?.type === "input_text" || object8(part)?.type === "text" || typeof object8(part)?.text === "string") || Array.isArray(row.parts) && row.parts.some((part) => typeof object8(part)?.text === "string")))
36898
+ firstUser = true;
36899
+ kept.push(value);
36900
+ }
36901
+ if (!removed)
36902
+ return;
36903
+ const filtered = { ...envelope, [field]: kept };
36904
+ return google && body.request !== undefined ? { ...body, request: filtered } : filtered;
36905
+ }
36906
+
36907
+ // src/pi-dispatch-image-budget.ts
36908
+ function object9(value) {
36909
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
36910
+ }
36547
36911
  function piImageBudgetPlan(model) {
36548
- if (!model?.input?.includes("image") || object8(model.compat)?.stripImageInput === true)
36912
+ if (!model?.input?.includes("image") || object9(model.compat)?.stripImageInput === true)
36549
36913
  return;
36550
36914
  return {
36551
36915
  count: 0,
36552
36916
  api: model.api,
36553
36917
  rows: new Map,
36554
- hoistToolImages: model.api?.startsWith("google-") === true && object8(model.compat)?.multimodalFunctionResponse !== true || model.api === "bedrock-converse-stream" && model.requiresToolResultImageHoisting === true,
36918
+ hoistToolImages: model.api?.startsWith("google-") === true && object9(model.compat)?.multimodalFunctionResponse !== true || model.api === "bedrock-converse-stream" && model.requiresToolResultImageHoisting === true,
36555
36919
  hoistErrorImages: model.api === "anthropic-messages" || model.api === "bedrock-converse-stream"
36556
36920
  };
36557
36921
  }
36558
36922
  function inputImage(block, api) {
36559
- const file = object8(block.providerFile);
36923
+ const file = object9(block.providerFile);
36560
36924
  if (api === "ollama-chat")
36561
36925
  return { kind: "bytes", value: String(block.data ?? "") };
36562
36926
  if ((api?.endsWith("responses") && file?.provider === "openai" || api === "anthropic-messages" && file?.provider === "anthropic") && typeof file?.id === "string")
@@ -36576,7 +36940,7 @@ function piRecordImages(plan, row, source) {
36576
36940
  return;
36577
36941
  const images = [];
36578
36942
  for (const value of source.content) {
36579
- const block = object8(value);
36943
+ const block = object9(value);
36580
36944
  if (block?.type === "image")
36581
36945
  images.push(inputImage(block, plan.api));
36582
36946
  }
@@ -36602,20 +36966,20 @@ function piWireImages(content, ollamaImages) {
36602
36966
  return [];
36603
36967
  const images = [];
36604
36968
  for (const value of content) {
36605
- const block = object8(value);
36969
+ const block = object9(value);
36606
36970
  if (!block)
36607
36971
  continue;
36608
- const source = object8(block.source);
36609
- const inline = object8(block.inlineData);
36610
- const file = object8(block.fileData);
36611
- const bedrock = object8(block.image);
36972
+ const source = object9(block.source);
36973
+ const inline = object9(block.inlineData);
36974
+ const file = object9(block.fileData);
36975
+ const bedrock = object9(block.image);
36612
36976
  if (block.type === "image_url" || block.type === "input_image") {
36613
36977
  if (typeof block.file_id === "string")
36614
36978
  images.push({ kind: "file", value: block.file_id });
36615
36979
  else
36616
36980
  images.push({
36617
36981
  kind: "url",
36618
- value: String(typeof block.image_url === "string" ? block.image_url : object8(block.image_url)?.url)
36982
+ value: String(typeof block.image_url === "string" ? block.image_url : object9(block.image_url)?.url)
36619
36983
  });
36620
36984
  } else if (block.type === "image") {
36621
36985
  if (source?.type === "file")
@@ -36639,7 +37003,7 @@ function piWireImages(content, ollamaImages) {
36639
37003
  else if (bedrock)
36640
37004
  images.push({
36641
37005
  kind: "data",
36642
- value: String(object8(bedrock.source)?.bytes),
37006
+ value: String(object9(bedrock.source)?.bytes),
36643
37007
  mime: `image/${bedrock.format}`
36644
37008
  });
36645
37009
  }
@@ -36661,11 +37025,11 @@ function piMatchesImages(actual, expected) {
36661
37025
  return true;
36662
37026
  }
36663
37027
  function piWireImageCount(payload) {
36664
- const body = object8(payload);
37028
+ const body = object9(payload);
36665
37029
  const visit = (value) => {
36666
37030
  if (Array.isArray(value))
36667
37031
  return value.reduce((n, item) => n + visit(item), 0);
36668
- const block = object8(value);
37032
+ const block = object9(value);
36669
37033
  if (!block)
36670
37034
  return 0;
36671
37035
  if (["image", "image_url", "input_image"].includes(String(block.type)) || block.inlineData || block.fileData || block.image)
@@ -36679,12 +37043,12 @@ function piWireImageCount(payload) {
36679
37043
  block.response
36680
37044
  ].reduce((n, item) => n + visit(item), Array.isArray(block.images) ? block.images.length : 0);
36681
37045
  };
36682
- return visit(body?.messages ?? body?.input ?? body?.contents ?? object8(body?.request)?.contents);
37046
+ return visit(body?.messages ?? body?.input ?? body?.contents ?? object9(body?.request)?.contents);
36683
37047
  }
36684
37048
 
36685
37049
  // src/pi-dispatch-responses-history.ts
36686
37050
  var MAX_TEXT_UNITS = 32 * 1024 * 1024;
36687
- function object9(value) {
37051
+ function object10(value) {
36688
37052
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
36689
37053
  }
36690
37054
  function wellFormed2(text) {
@@ -36699,7 +37063,7 @@ function textIdentity2(text, phase) {
36699
37063
  function signaturePhase(block) {
36700
37064
  try {
36701
37065
  if (typeof block.textSignature === "string") {
36702
- const signature = object9(JSON.parse(block.textSignature));
37066
+ const signature = object10(JSON.parse(block.textSignature));
36703
37067
  if (signature?.v === 1 && typeof signature.id === "string")
36704
37068
  return signature.phase;
36705
37069
  }
@@ -36721,19 +37085,19 @@ ${wellFormed2(text)}
36721
37085
  function coldReplayable(items) {
36722
37086
  let reasoning = false;
36723
37087
  for (const value of items) {
36724
- const item = object9(value);
37088
+ const item = object10(value);
36725
37089
  if (typeof item?.encrypted_content === "string")
36726
37090
  return false;
36727
37091
  if (item?.type !== "reasoning")
36728
37092
  continue;
36729
- if (!Array.isArray(item.content) || !item.content.some((part) => object9(part)?.type === "reasoning_text"))
37093
+ if (!Array.isArray(item.content) || !item.content.some((part) => object10(part)?.type === "reasoning_text"))
36730
37094
  return false;
36731
37095
  reasoning = true;
36732
37096
  }
36733
37097
  return reasoning;
36734
37098
  }
36735
37099
  function piResponsesAssistantTexts(value, model, host, alternatives) {
36736
- const message = object9(value);
37100
+ const message = object10(value);
36737
37101
  if (!message || !Array.isArray(message.content))
36738
37102
  return;
36739
37103
  if (piOmitsTruncatedAssistant(message))
@@ -36743,7 +37107,7 @@ function piResponsesAssistantTexts(value, model, host, alternatives) {
36743
37107
  const sameModel = model !== undefined && typeof model.api === "string" && typeof model.id === "string" && typeof model.provider === "string" && message.api === model.api && message.model === model.id && message.provider === model.provider;
36744
37108
  let units = 0;
36745
37109
  for (const value of message.content) {
36746
- const block = object9(value);
37110
+ const block = object10(value);
36747
37111
  if (block?.type === "toolCall")
36748
37112
  continue;
36749
37113
  if (block?.type === "thinking") {
@@ -36753,7 +37117,7 @@ function piResponsesAssistantTexts(value, model, host, alternatives) {
36753
37117
  return;
36754
37118
  if (!block.thinking.trim())
36755
37119
  continue;
36756
- const compat = object9(model.compat);
37120
+ const compat = object10(model.compat);
36757
37121
  if (block.summary === false && (compat?.requiresReasoningContentForToolCalls === true || compat?.requiresReasoningContentForAllAssistantTurns === true))
36758
37122
  return;
36759
37123
  const text = demotedThinking(block.thinking, model);
@@ -36773,7 +37137,7 @@ function piResponsesAssistantTexts(value, model, host, alternatives) {
36773
37137
  texts.push(textIdentity2(wellFormed2(block.text), sameModel ? signaturePhase(block) : undefined));
36774
37138
  blocks.push(block);
36775
37139
  }
36776
- const payload = object9(message.providerPayload);
37140
+ const payload = object10(message.providerPayload);
36777
37141
  if (message.api !== model?.api || typeof model?.id !== "string" || typeof model?.provider !== "string" || message.model !== model?.id || (payload?.provider ?? message.provider) !== model?.provider || payload?.type !== "openaiResponsesHistory" || payload.dt !== true || !Array.isArray(payload.items))
36778
37142
  return texts;
36779
37143
  const replay = [];
@@ -36787,7 +37151,7 @@ function piResponsesAssistantTexts(value, model, host, alternatives) {
36787
37151
  let unsigned = false;
36788
37152
  let rewrittenText = false;
36789
37153
  for (const value of payload.items) {
36790
- const item = object9(value);
37154
+ const item = object10(value);
36791
37155
  if (item?.type === "reasoning")
36792
37156
  continue;
36793
37157
  if (item?.type === "function_call" || item?.type === "custom_tool_call") {
@@ -36798,14 +37162,14 @@ function piResponsesAssistantTexts(value, model, host, alternatives) {
36798
37162
  return texts;
36799
37163
  const itemTexts = [];
36800
37164
  for (const value of item.content) {
36801
- const part = object9(value);
37165
+ const part = object10(value);
36802
37166
  const block = blocks[bound];
36803
37167
  if (!block || part?.type !== "output_text" || typeof part.text !== "string")
36804
37168
  return texts;
36805
37169
  let signature;
36806
37170
  try {
36807
37171
  if (typeof block.textSignature === "string")
36808
- signature = object9(JSON.parse(block.textSignature));
37172
+ signature = object10(JSON.parse(block.textSignature));
36809
37173
  } catch {
36810
37174
  return texts;
36811
37175
  }
@@ -36815,7 +37179,7 @@ function piResponsesAssistantTexts(value, model, host, alternatives) {
36815
37179
  if (!allowUnsigned || "textSignature" in block || stripped !== block.text.replace(/^§\d+§ /u, ""))
36816
37180
  return texts;
36817
37181
  unsigned = true;
36818
- rewrittenText ||= part.text !== stripped && part.text !== block.text;
37182
+ rewrittenText ||= part.text !== stripped;
36819
37183
  }
36820
37184
  bound++;
36821
37185
  itemTexts.push(part.text);
@@ -36844,7 +37208,7 @@ function piResponsesWireTexts(value, phase) {
36844
37208
  const texts = [];
36845
37209
  let units = 0;
36846
37210
  for (const partValue of value) {
36847
- const part = object9(partValue);
37211
+ const part = object10(partValue);
36848
37212
  if (part?.type !== "output_text" || typeof part.text !== "string")
36849
37213
  return;
36850
37214
  units += part.text.length;
@@ -36856,6 +37220,7 @@ function piResponsesWireTexts(value, phase) {
36856
37220
  }
36857
37221
 
36858
37222
  // src/pi-dispatch-structure.ts
37223
+ var dateReminderPlans = new WeakMap;
36859
37224
  var MAX_MESSAGES = 1e5;
36860
37225
  var ORPHAN_NOTE = Symbol("prepared orphan tool result");
36861
37226
  var ANTHROPIC_CONTINUE_PAD_TEXT = "Continue.";
@@ -36882,11 +37247,11 @@ var TRANSFORM_MESSAGES_APIS = new Set([
36882
37247
  "devin-agent",
36883
37248
  "apple-foundation-models"
36884
37249
  ]);
36885
- function object10(value) {
37250
+ function object11(value) {
36886
37251
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
36887
37252
  }
36888
37253
  function messageStructure(value) {
36889
- const message = object10(value);
37254
+ const message = object11(value);
36890
37255
  if (!message)
36891
37256
  return;
36892
37257
  const role = [
@@ -36915,7 +37280,7 @@ function messageStructure(value) {
36915
37280
  }
36916
37281
  if (role === "assistant" && Array.isArray(message.content)) {
36917
37282
  for (const value of message.content) {
36918
- const block = object10(value);
37283
+ const block = object11(value);
36919
37284
  if (block?.type !== "toolCall" && block?.type !== "tool_use")
36920
37285
  continue;
36921
37286
  if (typeof block.id !== "string")
@@ -36931,7 +37296,7 @@ function windowCalls(message) {
36931
37296
  if (!Array.isArray(message.content))
36932
37297
  return [];
36933
37298
  return message.content.flatMap((value) => {
36934
- const block = object10(value);
37299
+ const block = object11(value);
36935
37300
  return block?.type === "toolCall" && typeof block.id === "string" ? [
36936
37301
  {
36937
37302
  id: block.id,
@@ -36941,7 +37306,7 @@ function windowCalls(message) {
36941
37306
  });
36942
37307
  }
36943
37308
  function duplicateSuffix(model) {
36944
- const compat = object10(model?.compat);
37309
+ const compat = object11(model?.compat);
36945
37310
  if (model?.api === "openai-completions") {
36946
37311
  if (compat?.requiresMistralToolIds === true)
36947
37312
  return { prefix: "dup", max: 9 };
@@ -36958,7 +37323,7 @@ function appendDuplicateSuffix(id, suffix, max) {
36958
37323
  }
36959
37324
  function projectMissingToolResults(messages, model, host = "omp") {
36960
37325
  const input = messages.filter((value) => {
36961
- const message = object10(value);
37326
+ const message = object11(value);
36962
37327
  return !((message?.role === "bashExecution" || message?.role === "pythonExecution") && message.excludeFromContext === true);
36963
37328
  });
36964
37329
  if (host === "pi")
@@ -36973,7 +37338,7 @@ function projectMissingToolResults(messages, model, host = "omp") {
36973
37338
  const realResults = new Map;
36974
37339
  const validToolUseIds = new Set;
36975
37340
  const deduplicated = input.map((value, index) => {
36976
- const message = object10(value);
37341
+ const message = object11(value);
36977
37342
  if (message?.role === "toolResult" && typeof message.toolCallId === "string") {
36978
37343
  let key = pairingId(message.toolCallId);
36979
37344
  let output = value;
@@ -37000,7 +37365,7 @@ function projectMissingToolResults(messages, model, host = "omp") {
37000
37365
  const touched = new Set;
37001
37366
  let changed = false;
37002
37367
  const content = message.content.map((part) => {
37003
- const block = object10(part);
37368
+ const block = object11(part);
37004
37369
  if (block?.type !== "toolCall" || typeof block.id !== "string")
37005
37370
  return part;
37006
37371
  const key = pairingId(block.id);
@@ -37079,7 +37444,7 @@ function projectMissingToolResults(messages, model, host = "omp") {
37079
37444
  };
37080
37445
  for (let index = 0;index < deduplicated.length; index++) {
37081
37446
  const value = deduplicated[index];
37082
- const message = object10(value);
37447
+ const message = object11(value);
37083
37448
  if (message?.role === "assistant") {
37084
37449
  flush(message.timestamp);
37085
37450
  if (piOmitsTruncatedAssistant(message))
@@ -37120,7 +37485,7 @@ function projectMissingToolResults(messages, model, host = "omp") {
37120
37485
  if (pending.some((call) => !answered.has(pairingId(call.id))) || aborted.size > 0)
37121
37486
  continue;
37122
37487
  const parts = message.content.flatMap((value) => {
37123
- const part = object10(value);
37488
+ const part = object11(value);
37124
37489
  return part?.type === "text" && typeof part.text === "string" && part.text.trim() ? [part.text] : [];
37125
37490
  });
37126
37491
  if (!parts.length)
@@ -37148,11 +37513,11 @@ function projectUnmodeledToolResults(messages) {
37148
37513
  return pipe > 0 ? id.slice(0, pipe) : id;
37149
37514
  };
37150
37515
  for (const value of messages) {
37151
- const message = object10(value);
37516
+ const message = object11(value);
37152
37517
  if (message?.role !== "assistant" || !Array.isArray(message.content))
37153
37518
  continue;
37154
37519
  for (const value of message.content) {
37155
- const block = object10(value);
37520
+ const block = object11(value);
37156
37521
  if (block?.type !== "toolCall" || typeof block.id !== "string")
37157
37522
  continue;
37158
37523
  if ([
@@ -37168,7 +37533,7 @@ function projectUnmodeledToolResults(messages) {
37168
37533
  const pairingId = (id) => !opaqueIds.has(id) && responsesComponents.has(component(id)) ? component(id) : id;
37169
37534
  const lastResult = new Map;
37170
37535
  messages.forEach((value, index) => {
37171
- const message = object10(value);
37536
+ const message = object11(value);
37172
37537
  if (message?.role === "toolResult" && typeof message.toolCallId === "string")
37173
37538
  lastResult.set(pairingId(message.toolCallId), index);
37174
37539
  });
@@ -37199,7 +37564,7 @@ function projectUnmodeledToolResults(messages) {
37199
37564
  };
37200
37565
  for (let index = 0;index < messages.length; index++) {
37201
37566
  const value = messages[index];
37202
- const message = object10(value);
37567
+ const message = object11(value);
37203
37568
  if ((message?.role === "bashExecution" || message?.role === "pythonExecution") && message.excludeFromContext === true)
37204
37569
  continue;
37205
37570
  if (message?.role !== "toolResult")
@@ -37241,7 +37606,7 @@ function projectPiToolResults(messages) {
37241
37606
  held.length = 0;
37242
37607
  };
37243
37608
  for (const value of messages) {
37244
- const message = object10(value);
37609
+ const message = object11(value);
37245
37610
  const role = message?.role;
37246
37611
  if (role === "assistant") {
37247
37612
  close(message?.timestamp);
@@ -37269,23 +37634,26 @@ function projectPiToolResults(messages) {
37269
37634
  close();
37270
37635
  return projected;
37271
37636
  }
37272
- function preparePiDispatch(messages, model, omp) {
37637
+ function preparePiDispatch(messages, model, omp, cwd) {
37273
37638
  let output = messages;
37274
37639
  const structure = buildPiPreparedStructure(messages, model, omp ? (index, source) => {
37275
- if (object10(source.providerPayload)?.type !== "openaiResponsesHistory")
37640
+ if (object11(source.providerPayload)?.type !== "openaiResponsesHistory")
37276
37641
  return;
37277
37642
  if (output === messages)
37278
37643
  output = messages.slice();
37279
37644
  const { providerPayload: _payload, ...copy } = source;
37280
37645
  output[index] = copy;
37281
37646
  } : undefined, omp ? "omp" : "pi");
37647
+ const reminders = structure && dateReminderPlans.get(structure);
37648
+ if (reminders)
37649
+ reminders.cwd = cwd;
37282
37650
  return { messages: output, structure };
37283
37651
  }
37284
37652
  function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37285
37653
  if (!messages.length || messages.length > MAX_MESSAGES)
37286
37654
  return;
37287
37655
  for (let index = 0;index < messages.length; index++) {
37288
- const source = object10(messages[index]);
37656
+ const source = object11(messages[index]);
37289
37657
  if (source?.role === "user" || source?.role === "compactionSummary")
37290
37658
  prepareUser?.(index, source);
37291
37659
  }
@@ -37297,11 +37665,12 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37297
37665
  const toolIds = new Map;
37298
37666
  const responsesToolIds = new Map;
37299
37667
  const byIndex = new Map;
37668
+ let firstUserRow;
37300
37669
  const imageBudget = piImageBudgetPlan(model);
37301
37670
  let valid = true;
37302
37671
  for (let index = 0;index < projectedMessages.length; index++) {
37303
37672
  const message = projectedMessages[index];
37304
- const source = object10(message);
37673
+ const source = object11(message);
37305
37674
  if (rows.length === 0 && (source?.role === "system" || source?.role === "developer"))
37306
37675
  continue;
37307
37676
  if ((source?.role === "bashExecution" || source?.role === "pythonExecution") && source.excludeFromContext === true)
@@ -37325,7 +37694,7 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37325
37694
  "azure-openai-responses",
37326
37695
  "openai-codex-responses"
37327
37696
  ].includes(model?.api ?? "") && (source?.role === "user" || source?.role === "developer") && (typeof source.content === "string" ? !source.content.trim() : Array.isArray(source.content) && !source.content.some((value) => {
37328
- const block = object10(value);
37697
+ const block = object11(value);
37329
37698
  return block?.type === "image" || block?.type === "text" && typeof block.text === "string" && block.text.trim();
37330
37699
  })))
37331
37700
  continue;
@@ -37357,6 +37726,8 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37357
37726
  row.wireResults = row.results.map((id) => toolIds.has(id) ? toolIds.get(id) : responsesToolIds.get(id.split("|", 1)[0]));
37358
37727
  }
37359
37728
  rows.push(row);
37729
+ if (source?.role === "user")
37730
+ firstUserRow ??= row;
37360
37731
  byIndex.set(index, row);
37361
37732
  piRecordImages(imageBudget, row, source);
37362
37733
  }
@@ -37367,12 +37738,12 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37367
37738
  const positionedRows = [...byIndex];
37368
37739
  for (let position = positionedRows.length - 1;position >= 0; position--) {
37369
37740
  const [index, row] = positionedRows[position];
37370
- const source = object10(projectedMessages[index]);
37741
+ const source = object11(projectedMessages[index]);
37371
37742
  if (!source)
37372
37743
  return;
37373
37744
  const content = source.content;
37374
37745
  const parts = typeof content === "string" ? [{ type: "text", text: content }] : content;
37375
- const textOnly = Array.isArray(parts) && parts.every((part) => object10(part)?.type === "text" && typeof object10(part)?.text === "string");
37746
+ const textOnly = Array.isArray(parts) && parts.every((part) => object11(part)?.type === "text" && typeof object11(part)?.text === "string");
37376
37747
  const systemTexts = () => {
37377
37748
  const texts = parts.map((part) => part.text);
37378
37749
  return model?.api === "anthropic-messages" ? texts.filter((text) => text.trim()).map((text) => new TextDecoder().decode(new TextEncoder().encode(text))) : texts;
@@ -37380,7 +37751,7 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37380
37751
  if (piIsDeveloperHistory(source) && source.attribution !== "user") {
37381
37752
  const previous = rows[position - 1];
37382
37753
  const next = rows[position + 1];
37383
- const anthropicPromotable = model?.api === "anthropic-messages" && object10(model.compat)?.supportsMidConversationSystem === true && textOnly;
37754
+ const anthropicPromotable = model?.api === "anthropic-messages" && object11(model.compat)?.supportsMidConversationSystem === true && textOnly;
37384
37755
  if (anthropicPromotable)
37385
37756
  promotable.set(row, systemTexts());
37386
37757
  if (model?.api === "ollama-chat" || anthropicPromotable && (previous?.role === "user" || previous?.role === "toolResult") && (!next || next.role === "assistant"))
@@ -37471,7 +37842,7 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37471
37842
  }
37472
37843
  return [row];
37473
37844
  });
37474
- return {
37845
+ const prepared = {
37475
37846
  messages: rows,
37476
37847
  ...imageBudget?.count ? { imageBudget } : {},
37477
37848
  ...responsesApi && !responsesMessages ? { structuralSkipReason: "Responses history transform is not modeled" } : model?.api === "openai-completions" && !chatMessages ? { structuralSkipReason: "Chat history transform is not modeled" } : {},
@@ -37482,9 +37853,17 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
37482
37853
  ...modelsContinuePad ? { anthropicContinuePad: true } : {},
37483
37854
  ...modelsContinuePad && baseRows.some((row) => row.optionalThinking) ? { anthropicOptional: { rows: baseRows, promotable } } : {},
37484
37855
  ...model?.api?.startsWith("google-") ? {
37485
- googleFunctionIds: object10(model.compat)?.supportsFunctionPartId === true
37856
+ googleFunctionIds: object11(model.compat)?.supportsFunctionPartId === true
37486
37857
  } : {}
37487
37858
  };
37859
+ if (host === "omp" && PI_DATE_REMINDER_APIS.has(model?.api ?? ""))
37860
+ dateReminderPlans.set(prepared, {
37861
+ ...modelsContinuePad ? { plan: { rows: baseRows, promotable } } : {},
37862
+ firstUser: firstUserRow ? baseRows.indexOf(firstUserRow) : -1,
37863
+ midConversationSystem: object11(model?.compat)?.supportsMidConversationSystem === true,
37864
+ developerRole: object11(model?.compat)?.supportsDeveloperRole === true
37865
+ });
37866
+ return prepared;
37488
37867
  }
37489
37868
  function responsesLane(api) {
37490
37869
  return [
@@ -37494,7 +37873,7 @@ function responsesLane(api) {
37494
37873
  ].includes(api ?? "");
37495
37874
  }
37496
37875
  function payloadStructure(payload, ollama = false, responsesItems = false, imageProjection = false) {
37497
- const body = object10(payload);
37876
+ const body = object11(payload);
37498
37877
  if (!body)
37499
37878
  return;
37500
37879
  const google = piGoogleConversation(payload);
@@ -37509,12 +37888,12 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
37509
37888
  return;
37510
37889
  const rows = [];
37511
37890
  for (const value of messages) {
37512
- const message = object10(value);
37891
+ const message = object11(value);
37513
37892
  if (!message)
37514
37893
  return;
37515
37894
  if (rows.length === 0 && (message.role === "system" || message.role === "developer"))
37516
37895
  continue;
37517
- if (message.role === "system" && Array.isArray(message.content) && message.content.every((block) => ["tool_addition", "tool_removal"].includes(String(object10(block)?.type))))
37896
+ if (message.role === "system" && Array.isArray(message.content) && message.content.every((block) => ["tool_addition", "tool_removal"].includes(String(object11(block)?.type))))
37518
37897
  continue;
37519
37898
  if (responses && message.type === "reasoning")
37520
37899
  continue;
@@ -37571,7 +37950,7 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
37571
37950
  continue;
37572
37951
  }
37573
37952
  if (message.role === "user" && Array.isArray(message.content)) {
37574
- const results = message.content.filter((block) => object10(block)?.type === "tool_result" || bedrock && object10(block)?.toolResult);
37953
+ const results = message.content.filter((block) => object11(block)?.type === "tool_result" || bedrock && object11(block)?.toolResult);
37575
37954
  if (results.length) {
37576
37955
  for (const block of results) {
37577
37956
  const id = bedrock ? block.toolResult?.toolUseId : block.tool_use_id;
@@ -37618,11 +37997,11 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
37618
37997
  }
37619
37998
  if (Array.isArray(message.tool_calls)) {
37620
37999
  for (const call of message.tool_calls) {
37621
- const source = object10(call);
38000
+ const source = object11(call);
37622
38001
  if (!source)
37623
38002
  return;
37624
38003
  if (source.id === undefined && ollama) {
37625
- const fn = object10(source.function);
38004
+ const fn = object11(source.function);
37626
38005
  if (typeof fn?.name !== "string")
37627
38006
  return;
37628
38007
  row.calls.push("");
@@ -37658,7 +38037,7 @@ function googleStructure(contents, imageProjection = false) {
37658
38037
  return;
37659
38038
  const rows = [];
37660
38039
  for (const value of contents) {
37661
- const message = object10(value);
38040
+ const message = object11(value);
37662
38041
  if (!message || !Array.isArray(message.parts))
37663
38042
  return;
37664
38043
  if (message.role !== "user" && message.role !== "model")
@@ -37673,11 +38052,11 @@ function googleStructure(contents, imageProjection = false) {
37673
38052
  };
37674
38053
  const results = [];
37675
38054
  for (const value of message.parts) {
37676
- const part = object10(value);
38055
+ const part = object11(value);
37677
38056
  if (!part)
37678
38057
  return;
37679
38058
  if (part.functionCall) {
37680
- const call = object10(part.functionCall);
38059
+ const call = object11(part.functionCall);
37681
38060
  if (row.role !== "assistant" || typeof call?.name !== "string" || call.id !== undefined && typeof call.id !== "string")
37682
38061
  return;
37683
38062
  row.calls.push(call.id ?? "");
@@ -37685,7 +38064,7 @@ function googleStructure(contents, imageProjection = false) {
37685
38064
  row.callNames.push(call.name);
37686
38065
  }
37687
38066
  if (part.functionResponse) {
37688
- const result = object10(part.functionResponse);
38067
+ const result = object11(part.functionResponse);
37689
38068
  if (row.role !== "user" || typeof result?.name !== "string" || result.id !== undefined && typeof result.id !== "string")
37690
38069
  return;
37691
38070
  results.push({
@@ -37719,11 +38098,11 @@ function matchesUserText(content, text, api, responses, googleOrBedrock) {
37719
38098
  if (responses || googleOrBedrock) {
37720
38099
  if (!Array.isArray(content) || content.length !== 1)
37721
38100
  return false;
37722
- const block = object10(content[0]);
38101
+ const block = object11(content[0]);
37723
38102
  return !!block && block.text === text && (responses ? block.type === "input_text" : Object.keys(block).length === 1);
37724
38103
  }
37725
38104
  if ((api === "anthropic-messages" || api === "factory-droid-agent") && Array.isArray(content)) {
37726
- const block = content.length === 1 ? object10(content[0]) : undefined;
38105
+ const block = content.length === 1 ? object11(content[0]) : undefined;
37727
38106
  return block?.type === "text" && block.text === text;
37728
38107
  }
37729
38108
  return content === text;
@@ -37776,7 +38155,7 @@ function trimPreparedImageRows(rows, budget, drops) {
37776
38155
  flush();
37777
38156
  return projected;
37778
38157
  }
37779
- function countAnthropicOptionalAlignments(plan, base, wire, compare) {
38158
+ function countAnthropicOptionalAlignments(plan, base, wire, compare, reminders, firstUser = -1) {
37780
38159
  const pad = {
37781
38160
  role: "user",
37782
38161
  calls: [],
@@ -37808,11 +38187,16 @@ function countAnthropicOptionalAlignments(plan, base, wire, compare) {
37808
38187
  const place = (next) => {
37809
38188
  if (current < 0)
37810
38189
  return at;
37811
- const nextRole = next === undefined ? undefined : role(next);
38190
+ let after = at + 1;
38191
+ while (after < wire.length && reminders?.has(wire[after]))
38192
+ after++;
38193
+ const controls = after > at + 1;
38194
+ if (controls && (firstUser < 0 || current < firstUser))
38195
+ return;
38196
+ const nextRole = controls ? wire[at + 1].role : next === undefined ? undefined : role(next);
37812
38197
  if (!matches(final(current, previous, nextRole), at))
37813
38198
  return;
37814
- let after = at + 1;
37815
- if (role(current) === "assistant" && nextRole === "assistant") {
38199
+ if (!controls && role(current) === "assistant" && nextRole === "assistant") {
37816
38200
  if (!matches(pad, after))
37817
38201
  return;
37818
38202
  after++;
@@ -37822,7 +38206,7 @@ function countAnthropicOptionalAlignments(plan, base, wire, compare) {
37822
38206
  for (let next = current + 1;next < base.length; next++) {
37823
38207
  const after = place(next);
37824
38208
  if (after !== undefined)
37825
- add(next, current < 0 ? undefined : role(current), after, count);
38209
+ add(next, current < 0 ? undefined : wire[after - 1]?.role, after, count);
37826
38210
  if (!base[next].optionalThinking)
37827
38211
  return;
37828
38212
  }
@@ -37832,7 +38216,7 @@ function countAnthropicOptionalAlignments(plan, base, wire, compare) {
37832
38216
  return;
37833
38217
  }
37834
38218
  const after = place(undefined);
37835
- if (after === wire.length || after === wire.length - 1 && role(current) === "assistant" && isAnthropicContinuePadRow(wire[after]))
38219
+ if (after === wire.length || after === wire.length - 1 && wire[after - 1]?.role === "assistant" && isAnthropicContinuePadRow(wire[after]))
37836
38220
  complete = Math.min(2, complete + count);
37837
38221
  };
37838
38222
  advance(-1, undefined, 0, 1);
@@ -37850,6 +38234,70 @@ function countAnthropicOptionalAlignments(plan, base, wire, compare) {
37850
38234
  return complete;
37851
38235
  }
37852
38236
  function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
38237
+ const plan = prepared && dateReminderPlans.get(prepared);
38238
+ try {
38239
+ const messages = plan ? object11(payload)?.messages : undefined;
38240
+ if (Array.isArray(messages)) {
38241
+ for (const value of messages) {
38242
+ const message = object11(value);
38243
+ if (message?.role !== "system" && message?.role !== "developer")
38244
+ break;
38245
+ if (piDateReminderWireText(message.content, plan?.cwd) !== undefined)
38246
+ return "comparison=role";
38247
+ }
38248
+ }
38249
+ } catch {}
38250
+ const mismatch = preparedStructureMismatch(payload, prepared, onImageTrim);
38251
+ if (!mismatch)
38252
+ return mismatch;
38253
+ try {
38254
+ if (!prepared || !plan)
38255
+ return mismatch;
38256
+ if (!plan.plan) {
38257
+ if (plan.firstUser < 0)
38258
+ return mismatch;
38259
+ const root = prepared.messages[plan.firstUser];
38260
+ const body = object11(payload);
38261
+ const routeRows = Array.isArray(body?.input) ? prepared.responsesMessages ?? prepared.messages : prepared.api === "openai-completions" ? prepared.chatMessages ?? prepared.messages : prepared.messages;
38262
+ const firstUser = routeRows.indexOf(root);
38263
+ if (firstUser < 0)
38264
+ return mismatch;
38265
+ const filtered = piWithoutDateReminders(payload, prepared.api ?? "", plan.cwd, plan.developerRole, (prefix) => {
38266
+ const rows = payloadStructure(prefix, prepared.api === "ollama-chat", !!prepared.responsesMessages);
38267
+ return !!rows && rows.length > firstUser;
38268
+ });
38269
+ return filtered === undefined ? mismatch : preparedStructureMismatch(filtered, prepared, onImageTrim);
38270
+ }
38271
+ const messages = object11(payload)?.messages;
38272
+ if (!Array.isArray(messages))
38273
+ return mismatch;
38274
+ for (const value of messages) {
38275
+ const message = object11(value);
38276
+ if (piDateReminderWireText(message?.content, plan.cwd) !== undefined && Object.keys(message ?? {}).some((key) => !["role", "content"].includes(key)))
38277
+ return mismatch;
38278
+ }
38279
+ const wire = payloadStructure(payload, false, false, !!prepared.imageBudget && piWireImageCount(payload) < prepared.imageBudget.count);
38280
+ if (!wire)
38281
+ return mismatch;
38282
+ const reminders = new Set(wire.filter((row) => piDateReminderWireText(row.wireContent, plan.cwd) !== undefined));
38283
+ if (!reminders.size)
38284
+ return mismatch;
38285
+ for (let index = 0;index < wire.length; index++) {
38286
+ const row = wire[index];
38287
+ if (!reminders.has(row))
38288
+ continue;
38289
+ const previous = wire[index - 1];
38290
+ const next = wire[index + 1];
38291
+ const promoted = plan.midConversationSystem && (previous?.role === "user" || previous?.role === "toolResult") && (!next || next.role === "assistant");
38292
+ if (row.wireRole !== (promoted ? "system" : "user") || row.calls.length || row.results.length)
38293
+ return mismatch;
38294
+ }
38295
+ return preparedStructureMismatch(payload, { ...prepared, anthropicOptional: plan.plan }, onImageTrim, reminders, wire, plan.firstUser);
38296
+ } catch {
38297
+ return mismatch;
38298
+ }
38299
+ }
38300
+ function preparedStructureMismatch(payload, prepared, onImageTrim, reminders, reminderWire, firstUser) {
37853
38301
  let stage = "image count";
37854
38302
  let row = 0;
37855
38303
  let expectedRows;
@@ -37864,10 +38312,10 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
37864
38312
  return "comparison=image count";
37865
38313
  const imageProjection = trimmed > 0;
37866
38314
  stage = "wire rows";
37867
- const body = object10(payload);
38315
+ const body = object11(payload);
37868
38316
  const ollama = prepared?.api === "ollama-chat" && !!body && Array.isArray(body.messages) && body.input === undefined && body.system === undefined && body.inferenceConfig === undefined;
37869
38317
  const responses = body?.messages === undefined && Array.isArray(body?.input);
37870
- rows = payloadStructure(payload, ollama, responses && !!prepared?.responsesMessages, imageProjection);
38318
+ rows = reminderWire ?? payloadStructure(payload, ollama, responses && !!prepared?.responsesMessages, imageProjection);
37871
38319
  const chat = !!body && Array.isArray(body.messages) && (prepared?.api === "openai-completions" || body.system === undefined) && body.input === undefined && body.inferenceConfig === undefined;
37872
38320
  stage = "prepared rows";
37873
38321
  expectedRows = responses && prepared?.responsesMessages ? prepared.responsesMessages : chat && prepared?.chatMessages ? prepared.chatMessages : prepared?.messages;
@@ -37891,7 +38339,7 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
37891
38339
  if (expected.systemText !== undefined) {
37892
38340
  const texts = expected.systemText;
37893
38341
  const content = actual.wireContent;
37894
- const actualTexts = typeof content === "string" ? [content] : Array.isArray(content) && content.every((part) => object10(part)?.type === "text" && typeof object10(part)?.text === "string") ? content.map((part) => part.text) : undefined;
38342
+ const actualTexts = typeof content === "string" ? [content] : Array.isArray(content) && content.every((part) => object11(part)?.type === "text" && typeof object11(part)?.text === "string") ? content.map((part) => part.text) : undefined;
37895
38343
  if (!actualTexts || (typeof content === "string" ? content !== texts.join(`
37896
38344
  `) : JSON.stringify(actualTexts) !== JSON.stringify(texts)))
37897
38345
  return "content";
@@ -37922,7 +38370,7 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
37922
38370
  };
37923
38371
  if (optionalPlan) {
37924
38372
  stage = "optional assistants";
37925
- const alignments = countAnthropicOptionalAlignments(optionalPlan, imageProjection && imageBudget ? trimPreparedImageRows(optionalPlan.rows, imageBudget, trimmed) : optionalPlan.rows, rows, compareRow);
38373
+ const alignments = countAnthropicOptionalAlignments(optionalPlan, imageProjection && imageBudget ? trimPreparedImageRows(optionalPlan.rows, imageBudget, trimmed) : optionalPlan.rows, rows, compareRow, reminders, firstUser);
37926
38374
  if (alignments > 1)
37927
38375
  return structureDetail(0, expectedRows, rows, "alignment");
37928
38376
  if (alignments === 1) {
@@ -39682,7 +40130,7 @@ function registerPiGuardedContext(pi, handler, options = {}) {
39682
40130
  }
39683
40131
  const result = await budget.waitMandatory(Promise.resolve(withSqliteTurnDeadline2(() => Math.max(0, budget.remainingOutcome() - PI_CONTEXT_BUDGET.completionReserveMs), () => withSqliteTransformPass2(() => handler(event, ctx, budget)))));
39684
40132
  if (result?.messages) {
39685
- const prepared = preparePiDispatch(result.messages, fenceEnabled ? ctx.model : undefined, fenceEnabled);
40133
+ const prepared = preparePiDispatch(result.messages, fenceEnabled ? ctx.model : undefined, fenceEnabled, ctx.cwd);
39686
40134
  if (prepared.messages !== result.messages)
39687
40135
  result.messages = prepared.messages;
39688
40136
  active.managedSignature = piManagedSignature(result.messages);
@@ -42017,11 +42465,6 @@ function replayPiReminderStrips(args) {
42017
42465
  }
42018
42466
 
42019
42467
  // src/strip-placeholders-pi.ts
42020
- var MARKER_ONLY_PATTERN = /^(?:(?:§\d+§|\[dropped(?: §\d+§)?\]|\[cleared\])\s*)+$/;
42021
- function isPiMarkerOnlyText(text) {
42022
- const trimmed = text.trim();
42023
- return trimmed.length > 0 && MARKER_ONLY_PATTERN.test(trimmed);
42024
- }
42025
42468
  function messageIsPlaceholderOnly(message) {
42026
42469
  if (!message || typeof message !== "object")
42027
42470
  return false;
@@ -42029,7 +42472,7 @@ function messageIsPlaceholderOnly(message) {
42029
42472
  if (msg.role !== "assistant")
42030
42473
  return false;
42031
42474
  if (typeof msg.content === "string")
42032
- return msg.content.trim().length === 0 || isPiMarkerOnlyText(msg.content);
42475
+ return msg.content.trim().length === 0 || isMarkerOnlyText(msg.content);
42033
42476
  if (!Array.isArray(msg.content))
42034
42477
  return false;
42035
42478
  if (msg.content.length === 0)
@@ -42043,7 +42486,7 @@ function messageIsPlaceholderOnly(message) {
42043
42486
  if (typeof text !== "string")
42044
42487
  return false;
42045
42488
  sawVisibleContent = true;
42046
- if (text.trim().length > 0 && !isPiMarkerOnlyText(text))
42489
+ if (text.trim().length > 0 && !isMarkerOnlyText(text))
42047
42490
  return false;
42048
42491
  }
42049
42492
  return sawVisibleContent;
@@ -42866,7 +43309,7 @@ function createPiAssistantPart(working, messageIndex, partIndex, markDirty) {
42866
43309
  setToolOutput() {
42867
43310
  throw new Error("setToolOutput on assistant part");
42868
43311
  },
42869
- getToolMetadata() {
43312
+ getToolMetadata(options) {
42870
43313
  const current = working[messageIndex].content;
42871
43314
  const p = current[partIndex];
42872
43315
  if (p?.type !== "toolCall") {
@@ -42877,7 +43320,7 @@ function createPiAssistantPart(working, messageIndex, partIndex, markDirty) {
42877
43320
  try {
42878
43321
  const serialized = JSON.stringify(p.arguments);
42879
43322
  inputByteSize = serialized.length;
42880
- inputTokenCount = serialized ? estimateTokens(serialized) : 0;
43323
+ inputTokenCount = serialized && !options?.skipInputTokenCount ? estimateTokens(serialized) : 0;
42881
43324
  } catch {
42882
43325
  inputByteSize = 0;
42883
43326
  inputTokenCount = 0;
@@ -43238,6 +43681,7 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
43238
43681
  sourceCache.set(tagId, source);
43239
43682
  }
43240
43683
  const driftedMessageIds = new Set;
43684
+ const reusableTextMessageIds = new Set;
43241
43685
  const legacyReminderTagNumbers = new Set;
43242
43686
  for (const [messageId, currentSources] of currentSourcesByMessageId) {
43243
43687
  const legacyRows = legacyRowsByMessageId.get(messageId) ?? [];
@@ -43265,6 +43709,8 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
43265
43709
  });
43266
43710
  if (!vectorMatches)
43267
43711
  driftedMessageIds.add(messageId);
43712
+ else if (!messageId.startsWith("pi-msg-") && legacyRows.every((row) => sourceCache.has(row.tagId) && !legacyReminderTagNumbers.has(row.tagId)))
43713
+ reusableTextMessageIds.add(messageId);
43268
43714
  }
43269
43715
  const reusableMessageIds = new Set;
43270
43716
  for (const messageId of reuseCandidates) {
@@ -43275,7 +43721,8 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
43275
43721
  driftedMessageIds,
43276
43722
  legacyReminderTagNumbers,
43277
43723
  reusableMessageIds,
43278
- sourceCache
43724
+ sourceCache,
43725
+ reusableTextMessageIds
43279
43726
  };
43280
43727
  }
43281
43728
  var piBranchProjectionBySession = new Map;
@@ -44822,7 +45269,7 @@ function registerPiContextHandler(pi, baseOptions) {
44822
45269
  withoutSqliteTransformPass2(() => options.maybeAutoEmbedSession?.(sessionId, projectDirectory, projectIdentity));
44823
45270
  if (!options.compactionOff) {
44824
45271
  budget.stage = "tag snapshot hydration";
44825
- const hydration = ensurePiTagSnapshotReady(options.db, sessionId, budget);
45272
+ const hydration = ensurePiTagSnapshotReady(options.db, sessionId, budget, "pass");
44826
45273
  if (hydration)
44827
45274
  await guardAwait(hydration);
44828
45275
  }
@@ -46054,7 +46501,7 @@ function registerPiContextHandler(pi, baseOptions) {
46054
46501
  budget.failureReason = err.message;
46055
46502
  if (sessionIdForError) {
46056
46503
  try {
46057
- prewarmPiTagSnapshot(lkgOptions.db, sessionIdForError);
46504
+ prewarmPiTagSnapshot(lkgOptions.db, sessionIdForError, "pass");
46058
46505
  } catch {}
46059
46506
  }
46060
46507
  throw err;
@@ -46120,7 +46567,7 @@ function registerPiContextHandler(pi, baseOptions) {
46120
46567
  })
46121
46568
  });
46122
46569
  assertPiTagSnapshotReady(lkgOptions.db, sessionIdForError);
46123
- const drops = getPiTagSnapshotView(lkgOptions.db, sessionIdForError).filter((tag) => tag.status === "dropped");
46570
+ const drops = projectPiReplayDrops(recoveryTranscript, getPiPassTagSnapshotView(lkgOptions.db, sessionIdForError));
46124
46571
  const changed = applyFlushedStatuses(sessionIdForError, lkgOptions.db, buildPersistedDropTargets(recoveryTranscript, drops, {
46125
46572
  allowReasoningPrefixRewrite: true
46126
46573
  }), drops);
@@ -47119,6 +47566,21 @@ async function runPipeline(args) {
47119
47566
  try {
47120
47567
  nativeRemovalInputs = getNativeReplayState(args.db, args.sessionId).toolInputs;
47121
47568
  } catch {}
47569
+ const removalBatch = (edit) => withPiToolRemovalBatch({ db: args.db, sessionId: args.sessionId, saved: nativeRemovalInputs }, edit);
47570
+ const applyToolRemovalGroup = (edit) => {
47571
+ const savedRemovalInputs = nativeRemovalInputs;
47572
+ nativeRemovalInputs = savedRemovalInputs && new Map(savedRemovalInputs);
47573
+ try {
47574
+ return args.db.transaction(() => removalBatch((flush) => {
47575
+ const result = edit();
47576
+ flush();
47577
+ return result;
47578
+ })).immediate();
47579
+ } catch (cause) {
47580
+ nativeRemovalInputs = savedRemovalInputs;
47581
+ throw cause instanceof PiToolRemovalBatchError ? cause : new PiToolRemovalBatchError(cause);
47582
+ }
47583
+ };
47122
47584
  const tTranscriptBuild = performance.now();
47123
47585
  const transcript = createPiTranscript(args.messages, args.sessionId, args.messages.map(stableIdResolver), {
47124
47586
  preserveReasoningToolArcs: args.reasoningClearing?.preserveReasoningToolArcs,
@@ -47311,6 +47773,7 @@ async function runPipeline(args) {
47311
47773
  preserveTagOnlyAssistantText: true,
47312
47774
  entryFingerprintByMessageId,
47313
47775
  reuseMessageIds: textIdentityPlan.reusableMessageIds,
47776
+ reuseTextMessageIds: textIdentityPlan.reusableTextMessageIds,
47314
47777
  textIdentityDriftMessageIds: textIdentityPlan.driftedMessageIds,
47315
47778
  textIdentitySourceCache: textIdentityPlan.sourceCache,
47316
47779
  textTokenCache: tagTextTokenCache,
@@ -47391,21 +47854,40 @@ async function runPipeline(args) {
47391
47854
  message.content = content;
47392
47855
  });
47393
47856
  }
47857
+ const tLegacyToolConversion = performance.now();
47394
47858
  if (foldBustsServedPrefixThisPass) {
47859
+ const savedRemovalInputs = nativeRemovalInputs;
47395
47860
  try {
47861
+ nativeRemovalInputs = savedRemovalInputs && new Map(savedRemovalInputs);
47396
47862
  let converted = 0;
47397
- args.db.transaction(() => {
47863
+ args.db.transaction(() => removalBatch((flush) => {
47398
47864
  converted = convertLegacyToolSkeletons(args.db, args.sessionId, targets, {
47399
- keepFullDrop: (callId) => nativeRemovalInputs === undefined || callId !== null && nativeRemovalInputs.get(callId) === NATIVE_TOOL_REMOVAL_MARKER
47865
+ prepareRemovals: (rows) => preparePiToolRemovalChecks({
47866
+ db: args.db,
47867
+ rows,
47868
+ targets,
47869
+ messages: args.messages,
47870
+ prepare: transcript.prepareToolRemovalMeasurements
47871
+ }),
47872
+ keepFullDrop: (callId) => nativeRemovalInputs === undefined || callId !== null && authorizePiToolRemoval({
47873
+ db: args.db,
47874
+ sessionId: args.sessionId,
47875
+ callId,
47876
+ saved: nativeRemovalInputs,
47877
+ canApply: false
47878
+ }) === true
47400
47879
  }).size;
47401
- }).immediate();
47880
+ flush();
47881
+ })).immediate();
47402
47882
  if (converted > 0) {
47403
47883
  sessionLog2(args.sessionId, `pi HARD fold converted ${converted} legacy dropped-tool skeleton(s) to real-or-absent`);
47404
47884
  }
47405
47885
  } catch (error) {
47886
+ nativeRemovalInputs = savedRemovalInputs;
47406
47887
  sessionLog2(args.sessionId, `pi legacy dropped-tool skeleton conversion failed (kept legacy bytes): ${error instanceof Error ? error.message : String(error)}`);
47407
47888
  }
47408
47889
  }
47890
+ logTransformTiming(args.sessionId, "convertLegacyToolSkeletons", tLegacyToolConversion);
47409
47891
  try {
47410
47892
  if (!args.sessionMeta.isSubagent) {
47411
47893
  const hasRecentCommit = detectRecentCommit(args.messages);
@@ -47423,7 +47905,9 @@ async function runPipeline(args) {
47423
47905
  const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
47424
47906
  const shouldReadPendingOps = !args.compactionOff && (publishedWorkDrainAllowed || args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || foldExecutedThisPass || firstRenderBust);
47425
47907
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
47908
+ const tReclaimDistance = performance.now();
47426
47909
  const reclaimDistance = isCacheBustingPass ? toolReclaimDistanceEntries(mutationView, targets) : [];
47910
+ logTransformTiming(args.sessionId, "toolReclaimDistanceEntries", tReclaimDistance);
47427
47911
  const protectedToolTags = protectedToolTagNumbers(getActiveTagsBySession2(args.db, args.sessionId), args.protectedTools);
47428
47912
  for (const number of identityAdoption.protectedTagNumbers)
47429
47913
  protectedToolTags.add(number);
@@ -47460,13 +47944,14 @@ async function runPipeline(args) {
47460
47944
  try {
47461
47945
  nativeRemovalInputs = saved && new Map(saved);
47462
47946
  probingExecuteRemoval = true;
47463
- args.db.transaction(() => {
47947
+ args.db.transaction(() => removalBatch((flush) => {
47464
47948
  for (const [number, target] of targets) {
47465
47949
  if (target.prepareDrop?.() !== false)
47466
47950
  allowed.add(number);
47467
47951
  }
47952
+ flush();
47468
47953
  throw rollback;
47469
- }).immediate();
47954
+ })).immediate();
47470
47955
  } catch (error) {
47471
47956
  if (error !== rollback)
47472
47957
  allowed.clear();
@@ -47505,13 +47990,13 @@ async function runPipeline(args) {
47505
47990
  pendingDecisionLogObserverForTests?.(pendingDecisionLog);
47506
47991
  try {
47507
47992
  const tApplyPending = performance.now();
47508
- pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, new Set([
47993
+ pendingOpsDidMutate = applyToolRemovalGroup(() => applyPendingOperations(args.sessionId, args.db, newTargets, new Set([
47509
47994
  ...args.contextUsage.percentage >= 95 ? [] : protectedTagNumbersForPass,
47510
47995
  ...protectedToolTags,
47511
47996
  ...identityAdoption.protectedTagNumbers
47512
47997
  ]), pendingOperationTags, pendingOps, [], new Set, (reduction) => droppedTokenReductions.push(reduction), undefined, (eligible) => {
47513
47998
  eligiblePendingDropTagIds = eligible;
47514
- });
47999
+ }));
47515
48000
  if (pendingOpsDidMutate) {
47516
48001
  droppedCount += pendingOps.length;
47517
48002
  }
@@ -47541,7 +48026,26 @@ async function runPipeline(args) {
47541
48026
  const flushedDroppedTags = getDroppedTagsByNumbers2(args.db, args.sessionId, targetTagNumbers);
47542
48027
  logTransformTiming(args.sessionId, "getDroppedTagsByNumbers", tGetTags, `targets=${targetTagNumbers.length} fetched=${flushedDroppedTags.length}`);
47543
48028
  const tFlushed = performance.now();
47544
- runPersistedReplayStage("flushed-status-failure", undefined, () => applyFlushedStatuses(args.sessionId, args.db, targets, flushedDroppedTags));
48029
+ runPersistedReplayStage("flushed-status-failure", undefined, () => {
48030
+ const render = () => applyFlushedStatuses(args.sessionId, args.db, targets, flushedDroppedTags);
48031
+ const savedRemovalInputs = nativeRemovalInputs;
48032
+ const needsRemovalPreparation = savedRemovalInputs !== undefined && flushedDroppedTags.some((tag) => tag.type === "tool" && tag.dropMode === "full" && savedRemovalInputs.get(tag.messageId) !== NATIVE_TOOL_REMOVAL_MARKER);
48033
+ if (!isCacheBustingPass || !needsRemovalPreparation)
48034
+ return render();
48035
+ try {
48036
+ nativeRemovalInputs = savedRemovalInputs && new Map(savedRemovalInputs);
48037
+ return args.db.transaction(() => removalBatch((flush) => {
48038
+ prepareFlushedToolRemovals(targets, flushedDroppedTags);
48039
+ flush();
48040
+ return render();
48041
+ })).immediate();
48042
+ } catch (error) {
48043
+ nativeRemovalInputs = savedRemovalInputs;
48044
+ if (error instanceof PiToolRemovalBatchError)
48045
+ return render();
48046
+ throw error;
48047
+ }
48048
+ });
47545
48049
  logTransformTiming(args.sessionId, "applyFlushedStatuses", tFlushed);
47546
48050
  logTransformTiming(args.sessionId, "batchFinalize:flushed", tFlushed);
47547
48051
  const messageIdToMaxTag = buildMessageIdToMaxTag(targets);
@@ -47590,7 +48094,7 @@ async function runPipeline(args) {
47590
48094
  let routineCleanupApplied = false;
47591
48095
  let heuristicsResult = null;
47592
48096
  const tActiveTags = performance.now();
47593
- const allTagsForPass = getPiTagSnapshotView(args.db, args.sessionId);
48097
+ const allTagsForPass = getPiPassTagSnapshotView(args.db, args.sessionId);
47594
48098
  const activeTags = getPiActiveTagSnapshotView(args.db, args.sessionId, allTagsForPass);
47595
48099
  logTransformTiming(args.sessionId, "getTagsBySessionSnapshot", tActiveTags, `all=${allTagsForPass.length} active=${activeTags.length}`);
47596
48100
  if (shouldRunHeuristics) {
@@ -47612,7 +48116,7 @@ async function runPipeline(args) {
47612
48116
  clearEmergencyDropSample(args.db, args.sessionId);
47613
48117
  }
47614
48118
  routineCleanupApplied = (emergencyDropEligible ? args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0 : args.sessionMeta.isSubagent || !routinePressureAlreadyApplied) || hasPendingMaterializeSignal || rideSignals.explicitFlush || deferredMaterialize || independentMutationBeforeHeuristics;
47615
- heuristicsResult = applyPiHeuristicCleanup(args.sessionId, args.db, newTargets, args.messages, {
48119
+ heuristicsResult = applyToolRemovalGroup(() => applyPiHeuristicCleanup(args.sessionId, args.db, newTargets, args.messages, {
47616
48120
  protectedTags: args.protectedTags,
47617
48121
  prepareToolRemovalMeasurements: transcript.prepareToolRemovalMeasurements,
47618
48122
  protectedToolTags,
@@ -47626,18 +48130,18 @@ async function runPipeline(args) {
47626
48130
  usagePercentage: args.contextUsage.percentage,
47627
48131
  passAlreadyPriced: independentMutationBeforeHeuristics
47628
48132
  } : undefined,
47629
- caveman: args.isSubagent ? undefined : args.heuristics.caveman
47630
- }, activeTags, stableIdResolver);
48133
+ caveman: args.isSubagent ? undefined : args.heuristics?.caveman
48134
+ }, activeTags, stableIdResolver));
47631
48135
  if (!routineCleanupApplied && heuristicsResult.emergencyDroppedTools > 0) {
47632
- const ridingCleanup = applyPiHeuristicCleanup(args.sessionId, args.db, newTargets, args.messages, {
48136
+ const ridingCleanup = applyToolRemovalGroup(() => applyPiHeuristicCleanup(args.sessionId, args.db, newTargets, args.messages, {
47633
48137
  protectedTags: args.protectedTags,
47634
48138
  protectedToolTags,
47635
48139
  protectedCutoff: usesTokenProtection ? protectionWindowForPass.cutoff : undefined,
47636
48140
  routine: true,
47637
48141
  staleReduceStripEnabled: true,
47638
48142
  onStaleReduceEdit: recordStaleReduceEdit,
47639
- caveman: args.isSubagent ? undefined : args.heuristics.caveman
47640
- }, getActiveTagsBySession2(args.db, args.sessionId), stableIdResolver);
48143
+ caveman: args.isSubagent ? undefined : args.heuristics?.caveman
48144
+ }, getActiveTagsBySession2(args.db, args.sessionId), stableIdResolver));
47641
48145
  heuristicsResult = {
47642
48146
  droppedTools: heuristicsResult.droppedTools + ridingCleanup.droppedTools,
47643
48147
  deduplicatedTools: heuristicsResult.deduplicatedTools + ridingCleanup.deduplicatedTools,
@@ -47676,6 +48180,8 @@ async function runPipeline(args) {
47676
48180
  }
47677
48181
  logTransformTiming(args.sessionId, "applyHeuristicCleanup", tHeuristic, `droppedTools=${heuristicsResult.droppedTools} deduplicatedTools=${heuristicsResult.deduplicatedTools} droppedInjections=${heuristicsResult.droppedInjections} staleReduce=${heuristicsResult.droppedStaleReduceCalls} compressedTextTags=${heuristicsResult.compressedTextTags} mutatedTextTags=${heuristicsResult.mutatedTextTags}`);
47678
48182
  } catch (err) {
48183
+ if (err instanceof PiToolRemovalBatchError)
48184
+ throw err;
47679
48185
  sessionLog2(args.sessionId, `heuristic cleanup failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
47680
48186
  }
47681
48187
  }
@@ -47814,7 +48320,7 @@ async function runPipeline(args) {
47814
48320
  }
47815
48321
  autoReclaimTargetCount = syntheticPendingOps.length;
47816
48322
  if (syntheticPendingOps.length > 0) {
47817
- autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, protectedTagNumbersForPass, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
48323
+ autoReclaimDidMutate = applyToolRemovalGroup(() => applyPendingOperations(args.sessionId, args.db, newTargets, protectedTagNumbersForPass, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction)));
47818
48324
  if (autoReclaimDidMutate) {
47819
48325
  droppedCount += syntheticPendingOps.length;
47820
48326
  autoReclaimDidMutateThisPass = true;
@@ -47835,10 +48341,7 @@ async function runPipeline(args) {
47835
48341
  noteImagePosition(message.info.id, tagNumber);
47836
48342
  }
47837
48343
  }
47838
- const imageToolTags = new Map(allTagsForPass.filter((tag) => tag.type === "tool").map((tag) => [
47839
- `${tag.toolOwnerMessageId ?? ""}\x00${tag.messageId}`,
47840
- tag.tagNumber
47841
- ]));
48344
+ const imageToolCoordinates = [];
47842
48345
  const imageToolOwners = new Map;
47843
48346
  for (let index = 0;index < workingMessages.length; index++) {
47844
48347
  const message = workingMessages[index];
@@ -47848,12 +48351,26 @@ async function runPipeline(args) {
47848
48351
  if (part.type !== "toolCall")
47849
48352
  continue;
47850
48353
  imageToolOwners.set(part.id, id ?? "");
47851
- noteImagePosition(id, imageToolTags.get(`${id ?? ""}\x00${part.id}`) ?? 0);
48354
+ imageToolCoordinates.push({ id, key: `${id ?? ""}\x00${part.id}` });
47852
48355
  }
47853
48356
  } else if (message.role === "toolResult") {
47854
- noteImagePosition(id, imageToolTags.get(`${imageToolOwners.get(message.toolCallId) ?? ""}\x00${message.toolCallId}`) ?? 0);
48357
+ imageToolCoordinates.push({
48358
+ id,
48359
+ key: `${imageToolOwners.get(message.toolCallId) ?? ""}\x00${message.toolCallId}`
48360
+ });
47855
48361
  }
47856
48362
  }
48363
+ const imageToolKeys = new Set(imageToolCoordinates.map(({ key }) => key));
48364
+ const imageToolTags = new Map;
48365
+ for (const tag of allTagsForPass) {
48366
+ if (tag.type !== "tool")
48367
+ continue;
48368
+ const key = `${tag.toolOwnerMessageId ?? ""}\x00${tag.messageId}`;
48369
+ if (imageToolKeys.has(key))
48370
+ imageToolTags.set(key, tag.tagNumber);
48371
+ }
48372
+ for (const { id, key } of imageToolCoordinates)
48373
+ noteImagePosition(id, imageToolTags.get(key) ?? 0);
47857
48374
  const protectedImageToolKeys = new Set(activeTags.filter((tag) => tag.type === "tool" && protectedToolTags.has(tag.tagNumber)).map((tag) => tag.toolOwnerMessageId ? `${tag.toolOwnerMessageId}\x00${tag.messageId}` : tag.messageId));
47858
48375
  const imageResult = stripPiProcessedImages({
47859
48376
  db: args.db,
@@ -48188,7 +48705,7 @@ async function runPipeline(args) {
48188
48705
  onAdopt: (message) => sessionLog2(args.sessionId, message)
48189
48706
  });
48190
48707
  protectionFloorResolution = resolveProtectionFloor();
48191
- const protectedTagNumbers = usesTokenProtection ? computeProtectionWindow(allTagsForPass, protectionFloorResolution.floor, activeCalibration.toolsRatio).protectedTagNumbers : newestActiveTagNumbersByCount(activeTags, args.protectedTags);
48708
+ const protectedTagNumbers = usesTokenProtection ? protectedPiPassTagNumbers(allTagsForPass, protectionFloorResolution.floor, activeCalibration.toolsRatio) : newestActiveTagNumbersByCount(activeTags, args.protectedTags);
48192
48709
  const channelPendingOps = shouldApplyPendingOps ? getPendingOps(args.db, args.sessionId) : shouldReadPendingOps ? pendingOps : getPendingOps(args.db, args.sessionId);
48193
48710
  const channelBaselineSnapshot = {
48194
48711
  tagCacheKey: fallbackCache.index,
@@ -52758,7 +53275,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
52758
53275
  return;
52759
53276
  }
52760
53277
  const emptyHistorian = empty.find((chain) => chain.owner === "historian");
52761
- const historianLine = historian ? `registered historian trigger (model=${historian.model}${historian.fallbackModels?.length ? `, fallbacks=${historian.fallbackModels.join(",")}` : ""}, executeThreshold=${formatExecuteThresholdForLog(historian.executeThresholdPercentage)})` : emptyHistorian ? `registered historian trigger: DISABLED (no configured model is registered in Pi: ${formatEmptyPiModelChain(emptyHistorian)})` : undefined;
53278
+ const historianLine = historian ? `registered historian trigger (model=${historian.model}${historian.fallbackModels?.length ? `, fallbacks=${historian.fallbackModels.map(formatPiModelForLog).join(",")}` : ""}, executeThreshold=${formatExecuteThresholdForLog(historian.executeThresholdPercentage)})` : emptyHistorian ? `registered historian trigger: DISABLED (no configured model is registered in Pi: ${formatEmptyPiModelChain(emptyHistorian)})` : undefined;
52762
53279
  if (historianLine && !loggedPiModelChainLines.has(historianLine)) {
52763
53280
  loggedPiModelChainLines.add(historianLine);
52764
53281
  info(historianLine);
@@ -52882,7 +53399,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
52882
53399
  registerPiCloneSessionTransitions(pi.on.bind(pi), {
52883
53400
  db,
52884
53401
  signalPendingMarker: signalPiDeferredCompactionMarkerDrain,
52885
- onInherited: (sessionId) => prewarmPiTagSnapshot(db, sessionId)
53402
+ onInherited: (sessionId) => prewarmPiTagSnapshot(db, sessionId, "pass")
52886
53403
  });
52887
53404
  pi.on("session_start", async (event, ctx) => {
52888
53405
  bindStaleBuildNotice(ctx, import.meta.url);
@@ -52904,7 +53421,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
52904
53421
  await handlePiCloneSessionStart(event, ctx, {
52905
53422
  db,
52906
53423
  signalPendingMarker: signalPiDeferredCompactionMarkerDrain,
52907
- onInherited: (sessionId) => prewarmPiTagSnapshot(db, sessionId)
53424
+ onInherited: (sessionId) => prewarmPiTagSnapshot(db, sessionId, "pass")
52908
53425
  });
52909
53426
  const sessionId = resolveSessionId(ctx);
52910
53427
  if (!piMarkerRehydrationLogged && pendingPiMarkerSessions.length > 0 && sessionId) {
@@ -52921,7 +53438,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
52921
53438
  });
52922
53439
  }
52923
53440
  if (sessionId)
52924
- prewarmPiTagSnapshot(db, sessionId);
53441
+ prewarmPiTagSnapshot(db, sessionId, "pass");
52925
53442
  });
52926
53443
  pi.on("agent_start", (_event, ctx) => {
52927
53444
  setEmbeddingSessionBusy2(ctx.sessionManager.getSessionId(), true);
@@ -53497,7 +54014,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
53497
54014
  try {
53498
54015
  const incomingSessionId = readSessionId(ctx);
53499
54016
  if (incomingSessionId && _event?.reason !== "fork")
53500
- prewarmPiTagSnapshot(db, incomingSessionId);
54017
+ prewarmPiTagSnapshot(db, incomingSessionId, "pass");
53501
54018
  if (!outgoingSessionId || outgoingSessionId === readSessionId(ctx))
53502
54019
  return;
53503
54020
  clearPiSystemPromptSession(outgoingSessionId);
@@ -53518,6 +54035,11 @@ function formatExecuteThresholdForLog(value) {
53518
54035
  const base = `${value.default}%`;
53519
54036
  return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
53520
54037
  }
54038
+ function formatPiModelForLog(entry) {
54039
+ if (typeof entry === "string")
54040
+ return entry;
54041
+ return `${entry.model}${entry.qualifier ? ` (thinking_level=${entry.qualifier})` : ""}`;
54042
+ }
53521
54043
  export {
53522
54044
  __test,
53523
54045
  canonicalPiModelKey,