@cortexkit/pi-magic-context 0.49.16 → 0.49.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/auto-search-worker.js +76 -63
  2. package/dist/chunk-embedding-write-worker.js +10 -10
  3. package/dist/{compaction-marker-candidates-k4tqg4jb.js → compaction-marker-candidates-wjzqbspm.js} +2 -2
  4. package/dist/compaction-marker-candidates-worker.js +2 -2
  5. package/dist/embedding-backfill-vwag34t0.js +23 -0
  6. package/dist/embedding-worker-process.js +1 -1
  7. package/dist/embedding-worker.js +4 -4
  8. package/dist/historian-calibration-extension.js +4 -1
  9. package/dist/{index-g4jf772p.js → index-1kcfwk9c.js} +22 -2
  10. package/dist/{index-657xh9w4.js → index-2mmy81qt.js} +2 -2
  11. package/dist/{index-x3k1530z.js → index-4bv5bttd.js} +3 -3
  12. package/dist/index-4knyh1kt.js +1387 -0
  13. package/dist/{index-ja1c33qa.js → index-d21pdr8v.js} +2 -2
  14. package/dist/{index-xmzhrht0.js → index-d43hmn31.js} +29 -18
  15. package/dist/{index-6dz2ed1v.js → index-d8gc0112.js} +2 -2
  16. package/dist/{index-hy44m6jc.js → index-e1rza8gp.js} +1 -1
  17. package/dist/{index-ajfpyk0x.js → index-fa485mqs.js} +59 -1
  18. package/dist/{index-fhyy4ave.js → index-fvjthct0.js} +851 -73
  19. package/dist/{index-y5c73caa.js → index-g7p75667.js} +32 -3
  20. package/dist/{index-tympym62.js → index-gdjv1nnd.js} +2 -2
  21. package/dist/{index-v8d4vgam.js → index-gp928w10.js} +6 -6
  22. package/dist/{index-46q4e104.js → index-qpq6w67c.js} +1 -1
  23. package/dist/{index-44h64qza.js → index-r9f4f6s1.js} +14 -10
  24. package/dist/{index-dne4ja7a.js → index-rhprywn6.js} +4 -4
  25. package/dist/{index-asrxgdt4.js → index-rrwv9y2k.js} +8 -0
  26. package/dist/{index-mx59cve4.js → index-svgkv4g2.js} +1 -1
  27. package/dist/{index-qqxqwqhp.js → index-vktahpdj.js} +1 -1
  28. package/dist/{index-n3r2d2pr.js → index-vmcgew7x.js} +10 -7
  29. package/dist/{index-afy3dzf9.js → index-xnch62s6.js} +12 -6
  30. package/dist/{index-4178cbfw.js → index-xxn1tpnv.js} +124 -2039
  31. package/dist/{index-s1xn8qfw.js → index-yygsh681.js} +6 -3
  32. package/dist/{index-p3evwech.js → index-z2rkv0mb.js} +3 -3
  33. package/dist/index.js +1109 -355
  34. package/dist/{message-fts-rowid-map-mbanfkt1.js → message-fts-rowid-map-cvpy2dmb.js} +5 -3
  35. package/dist/{message-index-easvmz22.js → message-index-74qdqmq7.js} +11 -11
  36. package/dist/{message-index-bounded-xzerjxmp.js → message-index-bounded-g9hgresf.js} +15 -15
  37. package/dist/{message-time-backfill-3q4kemfc.js → message-time-backfill-ssshbdy8.js} +1 -1
  38. package/dist/migration-worker.js +7 -7
  39. package/dist/{project-embedding-registry-xwnmqmx8.js → project-embedding-registry-vf1ncptn.js} +10 -10
  40. package/dist/raw-ordinal-warmup-worker.js +10 -10
  41. package/dist/{read-session-chunk-1sb5n7zs.js → read-session-chunk-chepqmw5.js} +5 -5
  42. package/dist/{read-session-raw-jz5e9jz0.js → read-session-raw-9s3xn7fc.js} +2 -2
  43. package/dist/{search-x3fa0561.js → search-6ztbx25v.js} +17 -17
  44. package/dist/{search-archive-3ma5n0wr.js → search-archive-jg4a1kcx.js} +6 -6
  45. package/dist/{sqlite-adjpy399.js → sqlite-fsp0sf3r.js} +1 -1
  46. package/dist/{storage-memory-axnsk5t1.js → storage-memory-yxxc5v4n.js} +2 -2
  47. package/dist/{storage-tags-jtessrec.js → storage-tags-1kets0q8.js} +3 -3
  48. package/dist/subagent-entry.js +22 -21
  49. package/dist/tag-snapshot-worker-pi.js +9 -9
  50. package/package.json +6 -1
  51. package/dist/embedding-backfill-c4bdw8pp.js +0 -23
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  harnessOwnsOpenCodeStore2
5
5
  } from "./index-0h2mkab2.js";
6
6
  import {
7
+ getDataDir,
7
8
  ensureCortexKitArtifactGitignore,
8
9
  getProjectMagicContextHistorianDir,
9
10
  getMagicContextStorageDir,
@@ -248,7 +249,8 @@ import {
248
249
  registerTodoStateLifecycle,
249
250
  syncCtxMemoryToolEnabled,
250
251
  registerMagicContextTools
251
- } from "./index-4178cbfw.js";
252
+ } from "./index-xxn1tpnv.js";
253
+ import"./index-4knyh1kt.js";
252
254
  import {
253
255
  canonicalModelIdentity,
254
256
  piModelRefToCanonical,
@@ -288,8 +290,9 @@ import {
288
290
  openCurrentDatabase,
289
291
  openDatabaseAsync,
290
292
  closeDatabase
291
- } from "./index-v8d4vgam.js";
293
+ } from "./index-gp928w10.js";
292
294
  import {
295
+ pruneMissingProjectIdentities,
293
296
  setHomeProjectPermission,
294
297
  ProjectIdentityError,
295
298
  resolveProjectIdentityStrict,
@@ -299,7 +302,7 @@ import {
299
302
  resolveProjectIdentityForSession,
300
303
  beginBootQuietPeriod,
301
304
  scheduleAfterBootQuiet
302
- } from "./index-y5c73caa.js";
305
+ } from "./index-g7p75667.js";
303
306
  import {
304
307
  detectThinkingBindingMismatch,
305
308
  detectLatestTurnThinkingMismatch,
@@ -412,6 +415,7 @@ import {
412
415
  computeRawRangeFingerprint,
413
416
  invalidateTrueRawTokenCache,
414
417
  stripSystemInjection,
418
+ isFilePart,
415
419
  hasUserAnswerMetadata,
416
420
  DreamTokenBudgetExceeded,
417
421
  TOKEN_BUDGET_FINALIZE_MESSAGE,
@@ -458,7 +462,7 @@ import {
458
462
  getRawSessionTagKeysThrough2,
459
463
  getLegacyProtectedTailStartOrdinal2,
460
464
  readSessionChunk2
461
- } from "./index-44h64qza.js";
465
+ } from "./index-r9f4f6s1.js";
462
466
  import {
463
467
  UNKNOWN_FIT_RATIO,
464
468
  hasMeasuredDecisionCalibration,
@@ -545,7 +549,7 @@ import {
545
549
  getToolTagNumberByOwner2,
546
550
  getNullOwnerToolTag2,
547
551
  adoptNullOwnerToolTag2
548
- } from "./index-dne4ja7a.js";
552
+ } from "./index-rhprywn6.js";
549
553
  import {
550
554
  textMentionsRecentCommit,
551
555
  hasMeaningfulUserText2,
@@ -557,7 +561,7 @@ import {
557
561
  estimateTokens,
558
562
  estimateFixedPromptTokens,
559
563
  normalizeText
560
- } from "./index-g4jf772p.js";
564
+ } from "./index-1kcfwk9c.js";
561
565
  import {
562
566
  inRootAsyncContext2,
563
567
  Database2,
@@ -570,7 +574,7 @@ import {
570
574
  isTransientSqliteError2,
571
575
  withAsyncPrivilegedWriter2,
572
576
  indexCoordinationInput2
573
- } from "./index-asrxgdt4.js";
577
+ } from "./index-rrwv9y2k.js";
574
578
  import {
575
579
  stableStringify,
576
580
  closeQuietly,
@@ -579,19 +583,6 @@ import {
579
583
  freezeTemporalDecisions,
580
584
  tagIdentityRevisionKey
581
585
  } from "./index-jrap43gc.js";
582
- import {
583
- resolveOpenCodeDbPath,
584
- assertOpenCodeStoreGeneration,
585
- openCodeDbPathExists,
586
- recordOpenCodeDbReadFailure,
587
- clearOpenCodeDbReadFailure,
588
- claimOpenCodeDbDiagnosticOnce
589
- } from "./index-8976mezv.js";
590
- import"./index-399p688g.js";
591
- import {
592
- runSessionWarmupWorker,
593
- RAW_SUMMARY_TEXT_MAX_CHARS2
594
- } from "./index-qqxqwqhp.js";
595
586
  import {
596
587
  piHarnessKindFromExecutable
597
588
  } from "./index-apgwdby5.js";
@@ -604,11 +595,14 @@ import {
604
595
  ownsLkgDirtyFence,
605
596
  invalidateCleanLkgRecoveryFence,
606
597
  markLkgRecoveryDirty,
598
+ gaDatabasePath,
607
599
  readSessionActivity,
608
600
  observeSessionActivity,
609
601
  backfillSessionActivity,
610
602
  clearCompressionDepth,
611
603
  clearCompressionDepthRange,
604
+ cleanSearchText,
605
+ matchedSearchSnippet,
612
606
  getMessageIndexSourceIdentity2,
613
607
  isMessageIndexSourceCurrent2,
614
608
  getLastIndexedOrdinal2,
@@ -616,12 +610,25 @@ import {
616
610
  isMessageIndexReconciledThrough2,
617
611
  indexSingleMessage2,
618
612
  indexMessagesAfterOrdinal2,
619
- sweepOrphanedOpenCodeMessageIndexes2
620
- } from "./index-fhyy4ave.js";
613
+ sweepOrphanedOpenCodeMessageIndexesCooperatively2
614
+ } from "./index-fvjthct0.js";
615
+ import {
616
+ resolveOpenCodeDbPath,
617
+ assertOpenCodeStoreGeneration,
618
+ openCodeDbPathExists,
619
+ recordOpenCodeDbReadFailure,
620
+ clearOpenCodeDbReadFailure,
621
+ claimOpenCodeDbDiagnosticOnce
622
+ } from "./index-8976mezv.js";
623
+ import"./index-399p688g.js";
624
+ import {
625
+ runSessionWarmupWorker,
626
+ RAW_SUMMARY_TEXT_MAX_CHARS2
627
+ } from "./index-vktahpdj.js";
621
628
  import {
622
629
  formatSynapseLaneDescriptor
623
- } from "./index-6dz2ed1v.js";
624
- import"./index-s1xn8qfw.js";
630
+ } from "./index-d8gc0112.js";
631
+ import"./index-yygsh681.js";
625
632
  import {
626
633
  buildCanonicalChunkTextFromFts,
627
634
  buildCompartmentSummaryFallbackText,
@@ -631,7 +638,7 @@ import {
631
638
  replaceCompartmentChunkEmbeddings,
632
639
  deleteChunkEmbedBackoffForSession,
633
640
  chunkWindowSourceKey
634
- } from "./index-afy3dzf9.js";
641
+ } from "./index-xnch62s6.js";
635
642
  import {
636
643
  recordSessionProjectIdentity,
637
644
  GIT_SWEEP_LEASE_RENEWAL_MS,
@@ -640,7 +647,7 @@ import {
640
647
  markGitSweepSuccessAndRelease,
641
648
  parkGitSweepNonIndexable,
642
649
  releaseGitSweepLease
643
- } from "./index-mx59cve4.js";
650
+ } from "./index-svgkv4g2.js";
644
651
  import {
645
652
  embedPauseBySession,
646
653
  embedRunStateBySession,
@@ -666,7 +673,7 @@ import {
666
673
  embedSessionCompartmentChunks2,
667
674
  getEmbeddingCoverageStatus2,
668
675
  getAutoEmbeddingSessionCoverage2
669
- } from "./index-n3r2d2pr.js";
676
+ } from "./index-vmcgew7x.js";
670
677
  import {
671
678
  rememberV1HiddenRun
672
679
  } from "./index-6x556c2q.js";
@@ -681,7 +688,7 @@ import {
681
688
  expandWorkspaceIdentitySetWithAliases,
682
689
  sourceNameForMemory,
683
690
  computeWorkspaceEpochFingerprint
684
- } from "./index-tympym62.js";
691
+ } from "./index-gdjv1nnd.js";
685
692
  import {
686
693
  configureContextDatabasePragmas2
687
694
  } from "./index-fapenpch.js";
@@ -731,7 +738,7 @@ import {
731
738
  normalizeVerificationFiles,
732
739
  indexCommitsForProject,
733
740
  embedUnembeddedCommits
734
- } from "./index-xmzhrht0.js";
741
+ } from "./index-d43hmn31.js";
735
742
  import {
736
743
  setEmbeddingSessionBusy2,
737
744
  isEmbeddingHostBusy2
@@ -755,18 +762,18 @@ import {
755
762
  setMemoryClassification2,
756
763
  archiveMemory2,
757
764
  getMemoryCountsByStatus2
758
- } from "./index-hy44m6jc.js";
765
+ } from "./index-e1rza8gp.js";
759
766
  import {
760
767
  invalidateMemory2
761
768
  } from "./index-yhzhdp3m.js";
762
769
  import {
763
770
  pushNotification2
764
771
  } from "./index-q1yc6bs0.js";
765
- import"./index-657xh9w4.js";
772
+ import"./index-2mmy81qt.js";
766
773
  import {
767
774
  cosineSimilarity
768
- } from "./index-p3evwech.js";
769
- import"./index-46q4e104.js";
775
+ } from "./index-z2rkv0mb.js";
776
+ import"./index-qpq6w67c.js";
770
777
  import {
771
778
  DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS,
772
779
  buildHiddenAgentRegistrations,
@@ -774,9 +781,10 @@ import {
774
781
  readHostSystemPrompt,
775
782
  subagentStepCap,
776
783
  SubagentTelemetry,
784
+ HISTORIAN_CACHE_TAIL_ENV2,
777
785
  HISTORIAN_MAX_OUTPUT_TOKENS_ENV2,
778
786
  SUBAGENT_OUTPUT_CEILING_ENV2
779
- } from "./index-ajfpyk0x.js";
787
+ } from "./index-fa485mqs.js";
780
788
  import {
781
789
  PiTagHydrationError,
782
790
  getPiTagSnapshotView,
@@ -787,10 +795,10 @@ import {
787
795
  drainPiTagSnapshotSession,
788
796
  assertPiTagSnapshotReady,
789
797
  ensurePiTagSnapshotReady
790
- } from "./index-x3k1530z.js";
798
+ } from "./index-4bv5bttd.js";
791
799
  import"./index-f18ec69t.js";
792
800
  import"./index-1cvyaw9a.js";
793
- import"./index-ja1c33qa.js";
801
+ import"./index-d21pdr8v.js";
794
802
  import {
795
803
  __toESM
796
804
  } from "./index-22jkk6wg.js";
@@ -815,7 +823,7 @@ import {
815
823
  } from "./index-81nthk8j.js";
816
824
 
817
825
  // src/index.ts
818
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
826
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
819
827
  import { createRequire as createRequire2 } from "node:module";
820
828
  import { join as join16, resolve as resolve3 } from "node:path";
821
829
 
@@ -3512,7 +3520,7 @@ function startHostStallProfilerSwitch() {
3512
3520
  // package.json
3513
3521
  var package_default = {
3514
3522
  name: "@cortexkit/pi-magic-context",
3515
- version: "0.49.16",
3523
+ version: "0.49.18",
3516
3524
  type: "module",
3517
3525
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
3518
3526
  main: "dist/index.js",
@@ -3577,8 +3585,13 @@ var package_default = {
3577
3585
  "@types/bun": "^1.3.10",
3578
3586
  "@types/node": "^22.20.0",
3579
3587
  "omp-coding-agent-1812": "npm:@oh-my-pi/pi-coding-agent@18.12.3",
3588
+ "omp-pi-ai-1889": "npm:@oh-my-pi/pi-ai@18.8.9",
3589
+ "omp-pi-ai-1811": "npm:@oh-my-pi/pi-ai@18.11.3",
3590
+ "omp-pi-ai-1812": "npm:@oh-my-pi/pi-ai@18.12.3",
3580
3591
  "pi-agent-core-087": "npm:@earendil-works/pi-agent-core@0.87.1",
3581
3592
  "pi-ai-086": "npm:@earendil-works/pi-ai@0.86.0",
3593
+ "pi-ai-087": "npm:@earendil-works/pi-ai@0.87.1",
3594
+ "pi-ai-130": "npm:@earendil-works/pi-ai@1.3.0",
3582
3595
  "pi-coding-agent-086": "npm:@earendil-works/pi-coding-agent@0.86.0",
3583
3596
  "pi-coding-agent-087": "npm:@earendil-works/pi-coding-agent@0.87.1",
3584
3597
  "pi-coding-agent-130": "npm:@earendil-works/pi-coding-agent@1.3.0",
@@ -9340,6 +9353,7 @@ async function runHistorianPrompt(args) {
9340
9353
  let handle = null;
9341
9354
  let completion;
9342
9355
  const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, client, db, sessionDirectory, "historian");
9356
+ const cacheTail = args.cacheTail ?? (executor.capabilities.harness === "opencode2" ? "skip" : undefined);
9343
9357
  let promptSettled = false;
9344
9358
  let hadUnsettledPrompt = false;
9345
9359
  const startedAt = Date.now();
@@ -9421,6 +9435,7 @@ async function runHistorianPrompt(args) {
9421
9435
  try {
9422
9436
  await promptSyncWithModelSuggestionRetry(client, {
9423
9437
  path: { id: agentSessionId },
9438
+ ...cacheTail !== undefined ? { cacheTail: retryIndex > 0 ? "write" : cacheTail } : {},
9424
9439
  query: { directory: sessionDirectory },
9425
9440
  body: {
9426
9441
  agent: agentId,
@@ -19233,9 +19248,14 @@ async function indexSingleMessageOffThread(db, sessionId, message) {
19233
19248
  return result.inserted;
19234
19249
  }
19235
19250
  async function sweepOrphanedOpenCodeMessageIndexesOffThread(db, openSource, options = {}) {
19251
+ if (getHarness2() === "opencode2")
19252
+ openSource = () => new Database2(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"), {
19253
+ readonly: true,
19254
+ fileMustExist: true
19255
+ });
19236
19256
  const path = getSqliteDatabasePath2(db);
19237
- if (!path || getHarness2() !== "opencode")
19238
- return sweepOrphanedOpenCodeMessageIndexes2(db, openSource, options);
19257
+ if (!path || getHarness2() !== "opencode" && getHarness2() !== "opencode2")
19258
+ return sweepOrphanedOpenCodeMessageIndexesCooperatively2(db, openSource, options);
19239
19259
  let source = null;
19240
19260
  let sourcePath = null;
19241
19261
  try {
@@ -19247,7 +19267,7 @@ async function sweepOrphanedOpenCodeMessageIndexesOffThread(db, openSource, opti
19247
19267
  source?.close();
19248
19268
  }
19249
19269
  if (!sourcePath)
19250
- return sweepOrphanedOpenCodeMessageIndexes2(db, () => source, options);
19270
+ return sweepOrphanedOpenCodeMessageIndexesCooperatively2(db, () => source, options);
19251
19271
  const reply = await runSessionWarmupWorker({
19252
19272
  path,
19253
19273
  sessionId: "",
@@ -19403,7 +19423,7 @@ function runTick(origin) {
19403
19423
  if (tickInFlight)
19404
19424
  return;
19405
19425
  tickInFlight = true;
19406
- log2(`[dreamer] timer tick (${origin}) — projects=${registeredProjects.size}`);
19426
+ log2(`[magic-context] maintenance tick (${origin}) — projects=${registeredProjects.size}`);
19407
19427
  (async () => {
19408
19428
  try {
19409
19429
  const db = openTimerDatabaseOrNull("maintenance tick");
@@ -19453,6 +19473,9 @@ function persistTickOutcome(db, failure) {
19453
19473
  }
19454
19474
  }
19455
19475
  async function runMessageHistoryMaintenance(db) {
19476
+ const prunedIdentities = await pruneMissingProjectIdentities();
19477
+ if (prunedIdentities > 0)
19478
+ log2(`[magic-context] pruned ${prunedIdentities} missing project identities`);
19456
19479
  try {
19457
19480
  await drainStaleLkgSlots(db);
19458
19481
  } catch (error) {
@@ -19686,10 +19709,20 @@ async function sweepGitCommits(args) {
19686
19709
  const holderId = crypto.randomUUID();
19687
19710
  const lease = acquireGitSweepLease(db, projectIdentity, holderId);
19688
19711
  if (!lease.acquired) {
19689
- const reason = lease.reason === "cooldown_active" ? `cooldown active until ${lease.nextAllowedAt}` : `lease held by ${lease.leaseHolder ?? "another holder"} until ${lease.leaseExpiresAt ?? "unknown"}`;
19712
+ if (lease.reason === "cooldown_active")
19713
+ return;
19714
+ const reason = `lease held by ${lease.leaseHolder ?? "another holder"} until ${lease.leaseExpiresAt ?? "unknown"}`;
19690
19715
  log2(`[git-commits] sweep skipped for ${projectIdentity}: ${reason}`);
19691
19716
  return;
19692
19717
  }
19718
+ if (projectIdentity.startsWith("dir:")) {
19719
+ if (parkGitSweepNonIndexable(db, projectIdentity, holderId)) {
19720
+ log2(`[git-commits] sweep parked for ${projectIdentity}: directory identity has no commits`);
19721
+ } else {
19722
+ releaseGitSweepLease(db, projectIdentity, holderId);
19723
+ }
19724
+ return;
19725
+ }
19693
19726
  const startedAt = Date.now();
19694
19727
  const stopRenewal = startGitSweepLeaseRenewal(db, projectIdentity, holderId);
19695
19728
  log2(`[git-commits] sweep starting for ${projectIdentity} (sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
@@ -20658,6 +20691,7 @@ class PiSubagentRunner {
20658
20691
  delete parentEnv.MAGIC_CONTEXT_HISTORIAN_TEMPERATURE;
20659
20692
  delete parentEnv[HISTORIAN_MAX_OUTPUT_TOKENS_ENV2];
20660
20693
  delete parentEnv[SUBAGENT_OUTPUT_CEILING_ENV2];
20694
+ delete parentEnv[HISTORIAN_CACHE_TAIL_ENV2];
20661
20695
  try {
20662
20696
  child = inRootAsyncContext2(() => this.spawnImpl(this.invocation.command, [...this.invocation.prefixArgs, ...this.extraArgs, ...args], {
20663
20697
  windowsHide: true,
@@ -20666,6 +20700,7 @@ class PiSubagentRunner {
20666
20700
  ...parentEnv,
20667
20701
  [MAGIC_CONTEXT_PI_SUBAGENT_ENV]: "1",
20668
20702
  MAGIC_CONTEXT_SUBAGENT_PROMPT_FILE: systemPromptPath,
20703
+ [HISTORIAN_CACHE_TAIL_ENV2]: /^(magic-context-)?historian(?:-recomp)?$/.test(options.agent) && options.accountingSubagent !== "historian_editor" ? options.cacheTail : undefined,
20669
20704
  MAGIC_CONTEXT_SUBAGENT_BUDGET_GUARD_FILE: budgetGuardFile,
20670
20705
  MAGIC_CONTEXT_SUBAGENT_PROVENANCE_ONLY: /^(magic-context-)?historian(?:-recomp|-editor)?$/.test(options.agent) ? undefined : "1",
20671
20706
  ...options.temperature !== undefined ? {
@@ -24219,27 +24254,43 @@ function buildReplacementContent(tagId) {
24219
24254
  return `[dropped §${tagId}§]`;
24220
24255
  }
24221
24256
  function applyNewToolDrop(target, options) {
24222
- if (options.persist && (target?.prepareDrop?.() ?? target?.canDrop?.()) === false) {
24257
+ const plan = planNewToolDrop(target, options, !!options.persist);
24258
+ if (!plan)
24223
24259
  return { result: "incomplete", mode: "full" };
24260
+ options.persist?.(plan.mode);
24261
+ return plan.apply();
24262
+ }
24263
+ function planNewToolDrop(target, options, prepare, plannedRemovals) {
24264
+ if (prepare && (target?.prepareDrop?.() ?? target?.canDrop?.()) === false) {
24265
+ return;
24224
24266
  }
24225
24267
  if (!target) {
24226
- options.persist?.("full");
24227
- return { result: "absent", mode: "full" };
24268
+ return { mode: "full", apply: () => ({ result: "absent", mode: "full" }) };
24228
24269
  }
24229
- if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true || target.wouldStrandConversationEnd?.() === true) {
24270
+ if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true || target.wouldStrandConversationEnd?.(plannedRemovals) === true) {
24230
24271
  const strip = target.hasAttachments?.() === true;
24231
- options.persist?.(strip ? "skeleton_stripped" : "skeleton_real");
24272
+ const mode = strip ? "skeleton_stripped" : "skeleton_real";
24232
24273
  return {
24233
- result: (strip ? target.skeletonStripped?.() : target.skeletonReal?.()) ?? "absent",
24234
- mode: strip ? "skeleton_stripped" : "skeleton_real"
24274
+ mode,
24275
+ apply: () => ({
24276
+ result: (strip ? target.skeletonStripped?.() : target.skeletonReal?.()) ?? "absent",
24277
+ mode
24278
+ })
24235
24279
  };
24236
24280
  }
24237
- options.persist?.("full");
24238
- const result = target.drop?.() ?? "absent";
24239
- if (result === "truncated" && target.hasAttachments?.() === true) {
24240
- return { result: target.skeletonStripped?.() ?? "absent", mode: "skeleton_stripped" };
24241
- }
24242
- return { result, mode: result === "truncated" ? "skeleton_real" : "full" };
24281
+ return {
24282
+ mode: "full",
24283
+ apply: () => {
24284
+ const result = target.drop?.() ?? "absent";
24285
+ if (result === "truncated" && target.hasAttachments?.() === true) {
24286
+ return {
24287
+ result: target.skeletonStripped?.() ?? "absent",
24288
+ mode: "skeleton_stripped"
24289
+ };
24290
+ }
24291
+ return { result, mode: result === "truncated" ? "skeleton_real" : "full" };
24292
+ }
24293
+ };
24243
24294
  }
24244
24295
  function applyPersistedToolDrop(db, sessionId, tagNumber, target, options, afterWrite) {
24245
24296
  return applyNewToolDrop(target, {
@@ -24328,6 +24379,7 @@ function prepareLegacyToolSkeletonConversions(db, sessionId, targets, options =
24328
24379
  }
24329
24380
  };
24330
24381
  }
24382
+ var PENDING_OPERATION_CHUNK_SIZE = 64;
24331
24383
  function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set, onTagReduced, onBatchComplete, onEligibilitySnapshot) {
24332
24384
  let didMutateMessage = false;
24333
24385
  let diagnostics;
@@ -24337,153 +24389,184 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
24337
24389
  diagnostics.reasons[reason] = (diagnostics.reasons[reason] ?? 0) + 1;
24338
24390
  };
24339
24391
  let admitted = false;
24340
- try {
24341
- db.transaction(() => {
24342
- admitted = true;
24343
- }).immediate();
24344
- {
24345
- const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
24346
- onEligibilitySnapshot?.(capturePendingDropEligibility(targets, protectedTagIds));
24347
- const tags = preloadedTags ?? getTagsByNumbers2(db, sessionId, [
24348
- ...new Set([
24349
- ...pendingOps.map((op) => op.tagId),
24350
- ...syntheticPendingOps.map((op) => op.tagId)
24351
- ])
24352
- ]);
24353
- const tagById = new Map(tags.map((tag) => [tag.tagNumber, tag]));
24354
- const tagStatusById = new Map(tags.map((tag) => [tag.tagNumber, tag.status]));
24355
- const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
24356
- const opsToApply = [
24357
- ...pendingOps.map((op) => ({ op, synthetic: false })),
24358
- ...syntheticPendingOps.map((op) => ({ op, synthetic: true }))
24359
- ];
24360
- diagnostics = {
24361
- source: pendingOps.length > 0 && syntheticPendingOps.length > 0 ? "mixed" : syntheticPendingOps.length > 0 ? "synthetic" : "pending",
24362
- total: opsToApply.length,
24363
- mutated: 0,
24364
- persistedWithoutMutation: 0,
24365
- reasons: {}
24366
- };
24367
- const skeletonWindow = new Set(preloadedTags ? tags.filter((tag) => tag.type === "tool").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, RECENT_TOOL_SKELETON_WINDOW) : getNewestToolTagNumbers2(db, sessionId, RECENT_TOOL_SKELETON_WINDOW));
24368
- for (const { op: pendingOp, synthetic } of opsToApply) {
24369
- let operationMutated = false;
24370
- const tagStatus = tagStatusById.get(pendingOp.tagId);
24371
- if (tagStatus === "compacted" || tagStatus === "dropped") {
24372
- reject("already_reduced");
24373
- if (!synthetic)
24374
- removePendingOp(db, sessionId, pendingOp.tagId);
24375
- continue;
24376
- }
24377
- const target = targets.get(pendingOp.tagId);
24378
- const veto = pendingDropVeto(pendingOp.tagId, target, protectedTagIds);
24379
- if (veto) {
24380
- reject(veto);
24381
- continue;
24382
- }
24383
- const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
24384
- if (synthetic) {
24385
- if (!isToolTag) {
24386
- reject("synthetic_non_tool");
24387
- continue;
24388
- }
24389
- if (target?.canDrop?.() !== true) {
24390
- reject("synthetic_target_not_droppable");
24391
- continue;
24392
- }
24392
+ let startedAt = 0;
24393
+ const mutations = [];
24394
+ let drainChunk;
24395
+ let hasMore = false;
24396
+ do {
24397
+ admitted = false;
24398
+ startedAt = 0;
24399
+ try {
24400
+ db.transaction(() => {
24401
+ admitted = true;
24402
+ startedAt = performance.now();
24403
+ if (drainChunk) {
24404
+ drainChunk();
24405
+ return;
24393
24406
  }
24394
- const persistDrop = (mode) => {
24395
- let startedAt = 0;
24396
- try {
24397
- db.transaction(() => {
24398
- startedAt = performance.now();
24399
- markTagDropped2(db, sessionId, pendingOp.tagId, mode);
24407
+ const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
24408
+ onEligibilitySnapshot?.(capturePendingDropEligibility(targets, protectedTagIds));
24409
+ const tags = preloadedTags ?? getTagsByNumbers2(db, sessionId, [
24410
+ ...new Set([
24411
+ ...pendingOps.map((op) => op.tagId),
24412
+ ...syntheticPendingOps.map((op) => op.tagId)
24413
+ ])
24414
+ ]);
24415
+ const tagById = new Map(tags.map((tag) => [tag.tagNumber, tag]));
24416
+ const tagStatusById = new Map(tags.map((tag) => [tag.tagNumber, tag.status]));
24417
+ const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
24418
+ const opsToApply = [
24419
+ ...pendingOps.map((op) => ({ op, synthetic: false })),
24420
+ ...syntheticPendingOps.map((op) => ({ op, synthetic: true }))
24421
+ ];
24422
+ diagnostics = {
24423
+ source: pendingOps.length > 0 && syntheticPendingOps.length > 0 ? "mixed" : syntheticPendingOps.length > 0 ? "synthetic" : "pending",
24424
+ total: opsToApply.length,
24425
+ mutated: 0,
24426
+ persistedWithoutMutation: 0,
24427
+ reasons: {}
24428
+ };
24429
+ const skeletonWindow = new Set(preloadedTags ? tags.filter((tag) => tag.type === "tool").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, RECENT_TOOL_SKELETON_WINDOW) : getNewestToolTagNumbers2(db, sessionId, RECENT_TOOL_SKELETON_WINDOW));
24430
+ const plannedRemovals = new Set;
24431
+ const removedTagIds = new Set;
24432
+ const record = (mutated) => {
24433
+ if (!diagnostics)
24434
+ return;
24435
+ if (mutated) {
24436
+ didMutateMessage = true;
24437
+ diagnostics.mutated += 1;
24438
+ } else
24439
+ diagnostics.persistedWithoutMutation += 1;
24440
+ };
24441
+ let cursor = 0;
24442
+ drainChunk = () => {
24443
+ const chunk = opsToApply.slice(cursor, cursor + PENDING_OPERATION_CHUNK_SIZE);
24444
+ cursor += chunk.length;
24445
+ hasMore = cursor < opsToApply.length;
24446
+ for (const { op: pendingOp, synthetic } of chunk) {
24447
+ const tagStatus = tagStatusById.get(pendingOp.tagId);
24448
+ if (tagStatus === "compacted" || tagStatus === "dropped") {
24449
+ reject("already_reduced");
24400
24450
  if (!synthetic)
24401
24451
  removePendingOp(db, sessionId, pendingOp.tagId);
24402
- }).immediate();
24403
- } finally {
24404
- if (startedAt)
24405
- logSlowWriteTransaction("apply_pending_operation", startedAt);
24406
- }
24407
- };
24408
- let shouldPersistDrop = false;
24409
- if (isToolTag) {
24410
- if (editMarkerTagIds.has(pendingOp.tagId)) {
24411
- const strip = target?.hasAttachments?.() === true;
24412
- if (target?.canDrop?.() === false || target?.prepareDrop?.() === false || !target) {
24413
- reject("edit_marker_incomplete");
24414
24452
  continue;
24415
24453
  }
24416
- persistDrop(strip ? "edit_marker_stripped" : "edit_marker");
24417
- const markResult = (strip ? target?.editMarkerStripped?.() : target?.editMarker?.()) ?? "absent";
24418
- if (markResult === "incomplete" || markResult === "absent") {
24419
- reject(`edit_marker_${markResult}`);
24454
+ if (removedTagIds.has(pendingOp.tagId)) {
24455
+ reject("drop_incomplete");
24420
24456
  continue;
24421
24457
  }
24422
- didMutateMessage = true;
24423
- operationMutated = true;
24424
- onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
24425
- shouldPersistDrop = true;
24426
- } else {
24427
- const { result: dropResult, mode: appliedMode } = applyNewToolDrop(target, {
24428
- inWindow: skeletonWindow.has(pendingOp.tagId),
24429
- persist: persistDrop
24430
- });
24431
- if (dropResult === "incomplete" || synthetic && dropResult !== "removed" && dropResult !== "truncated") {
24432
- reject(`drop_${dropResult}`);
24458
+ const target = targets.get(pendingOp.tagId);
24459
+ const veto = pendingDropVeto(pendingOp.tagId, target, protectedTagIds);
24460
+ if (veto) {
24461
+ reject(veto);
24433
24462
  continue;
24434
24463
  }
24435
- if (dropResult === "removed" || dropResult === "truncated") {
24436
- didMutateMessage = true;
24437
- operationMutated = true;
24438
- onTagReduced?.({
24439
- tagNumber: pendingOp.tagId,
24440
- mode: appliedMode === "full" ? "full" : "truncated"
24464
+ const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
24465
+ if (synthetic) {
24466
+ if (!isToolTag) {
24467
+ reject("synthetic_non_tool");
24468
+ continue;
24469
+ }
24470
+ if (target?.canDrop?.() !== true) {
24471
+ reject("synthetic_target_not_droppable");
24472
+ continue;
24473
+ }
24474
+ }
24475
+ const persistDrop = (mode) => {
24476
+ markTagDropped2(db, sessionId, pendingOp.tagId, mode);
24477
+ if (!synthetic)
24478
+ removePendingOp(db, sessionId, pendingOp.tagId);
24479
+ };
24480
+ if (isToolTag) {
24481
+ if (editMarkerTagIds.has(pendingOp.tagId)) {
24482
+ const strip = target?.hasAttachments?.() === true;
24483
+ if (target?.canDrop?.() === false || target?.prepareDrop?.() === false || !target) {
24484
+ reject("edit_marker_incomplete");
24485
+ continue;
24486
+ }
24487
+ persistDrop(strip ? "edit_marker_stripped" : "edit_marker");
24488
+ mutations.push(() => {
24489
+ const markResult = (strip ? target?.editMarkerStripped?.() : target?.editMarker?.()) ?? "absent";
24490
+ if (markResult === "incomplete" || markResult === "absent") {
24491
+ reject(`edit_marker_${markResult}`);
24492
+ return;
24493
+ }
24494
+ record(true);
24495
+ onTagReduced?.({
24496
+ tagNumber: pendingOp.tagId,
24497
+ mode: "edit_marker"
24498
+ });
24499
+ });
24500
+ } else {
24501
+ const plan = planNewToolDrop(target, { inWindow: skeletonWindow.has(pendingOp.tagId) }, true, plannedRemovals);
24502
+ if (!plan) {
24503
+ reject("drop_incomplete");
24504
+ continue;
24505
+ }
24506
+ persistDrop(plan.mode);
24507
+ if (plan.mode === "full" && target?.drop) {
24508
+ target.notePlannedRemoval?.(plannedRemovals);
24509
+ removedTagIds.add(pendingOp.tagId);
24510
+ }
24511
+ mutations.push(() => {
24512
+ const { result: dropResult, mode: appliedMode } = plan.apply();
24513
+ if (dropResult === "incomplete" || synthetic && dropResult !== "removed" && dropResult !== "truncated") {
24514
+ reject(`drop_${dropResult}`);
24515
+ return;
24516
+ }
24517
+ if (dropResult === "removed" || dropResult === "truncated") {
24518
+ record(true);
24519
+ onTagReduced?.({
24520
+ tagNumber: pendingOp.tagId,
24521
+ mode: appliedMode === "full" ? "full" : "truncated"
24522
+ });
24523
+ } else {
24524
+ reject(`drop_${dropResult}`);
24525
+ record(false);
24526
+ }
24527
+ });
24528
+ }
24529
+ } else if (target) {
24530
+ const replacement = buildReplacementContent(pendingOp.tagId);
24531
+ persistDrop();
24532
+ mutations.push(() => {
24533
+ const priorContent = target.getContent?.();
24534
+ const changed = target.setContent(replacement);
24535
+ record(changed);
24536
+ if (changed) {
24537
+ const originalCharacters = typeof priorContent === "string" ? priorContent.length : tagById.get(pendingOp.tagId)?.byteSize ?? replacement.length;
24538
+ onTagReduced?.({
24539
+ tagNumber: pendingOp.tagId,
24540
+ mode: "partial",
24541
+ removedCharacters: Math.max(0, originalCharacters - replacement.length)
24542
+ });
24543
+ } else {
24544
+ reject("content_unchanged");
24545
+ }
24441
24546
  });
24442
- } else {
24443
- reject(`drop_${dropResult}`);
24547
+ } else if (!synthetic) {
24548
+ reject("target_absent");
24549
+ persistDrop();
24550
+ mutations.push(() => record(false));
24444
24551
  }
24445
- shouldPersistDrop = true;
24446
- }
24447
- } else if (target) {
24448
- const replacement = buildReplacementContent(pendingOp.tagId);
24449
- const priorContent = target.getContent?.();
24450
- persistDrop();
24451
- const changed = target.setContent(replacement);
24452
- if (changed) {
24453
- didMutateMessage = true;
24454
- operationMutated = true;
24455
- const originalCharacters = typeof priorContent === "string" ? priorContent.length : tagById.get(pendingOp.tagId)?.byteSize ?? replacement.length;
24456
- onTagReduced?.({
24457
- tagNumber: pendingOp.tagId,
24458
- mode: "partial",
24459
- removedCharacters: Math.max(0, originalCharacters - replacement.length)
24460
- });
24461
- } else {
24462
- reject("content_unchanged");
24463
24552
  }
24464
- shouldPersistDrop = true;
24465
- } else if (!synthetic) {
24466
- reject("target_absent");
24467
- persistDrop();
24468
- shouldPersistDrop = true;
24469
- }
24470
- if (!shouldPersistDrop) {
24471
- reject("not_persisted");
24472
- continue;
24473
- }
24474
- if (operationMutated)
24475
- diagnostics.mutated += 1;
24476
- else
24477
- diagnostics.persistedWithoutMutation += 1;
24553
+ };
24554
+ drainChunk();
24555
+ }).immediate();
24556
+ } catch (error) {
24557
+ if (!admitted && /database (?:table )?is locked|sqlite_(busy|locked)/i.test(String(error))) {
24558
+ sessionLog2(sessionId, "pending operations write admission busy; retaining remaining operations for retry");
24559
+ hasMore = false;
24560
+ } else {
24561
+ throw error;
24478
24562
  }
24563
+ } finally {
24564
+ if (startedAt)
24565
+ logSlowWriteTransaction("apply_pending_operations", startedAt);
24479
24566
  }
24480
- } catch (error) {
24481
- if (!admitted && /database (?:table )?is locked|sqlite_(busy|locked)/i.test(String(error))) {
24482
- sessionLog2(sessionId, "pending operations write admission busy; retaining prior bytes for retry");
24483
- return false;
24484
- }
24485
- throw error;
24486
- }
24567
+ for (const mutate of mutations.splice(0))
24568
+ mutate();
24569
+ } while (hasMore);
24487
24570
  if (diagnostics) {
24488
24571
  onBatchComplete?.(diagnostics);
24489
24572
  if (diagnostics.total > 0 && diagnostics.mutated === 0) {
@@ -24543,6 +24626,12 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
24543
24626
  function hasReclaimRide(signals) {
24544
24627
  return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory || signals.subagentExecute === true;
24545
24628
  }
24629
+ function prefixMutationPermitted(gate) {
24630
+ return !gate.signedThinkingHold || gate.firstRender || gate.idleExpiry || gate.emergency;
24631
+ }
24632
+ function reclaimRidePermitted(signals, gate) {
24633
+ return prefixMutationPermitted(gate) && hasReclaimRide(signals);
24634
+ }
24546
24635
  var RECLAIM_RIDE_NAMES = [
24547
24636
  "hardFold",
24548
24637
  "force",
@@ -24781,6 +24870,31 @@ function rearmChannel2AfterMeasuredCollapse(input) {
24781
24870
  return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
24782
24871
  }
24783
24872
 
24873
+ // ../plugin/src/hooks/magic-context/file-token-coverage.ts
24874
+ function omitIncompleteFileTokenTotals(db, sessionId, messages, totals) {
24875
+ const filesByMessage = new Map;
24876
+ for (const message of messages) {
24877
+ const count = message.parts.filter(isFilePart).length;
24878
+ if (count > 0 && totals.has(message.id))
24879
+ filesByMessage.set(message.id, count);
24880
+ }
24881
+ if (filesByMessage.size === 0)
24882
+ return totals;
24883
+ const rows = db.prepare(`
24884
+ SELECT o.value AS owner, COUNT(t.id) AS count
24885
+ FROM json_each(?) o LEFT JOIN tags t
24886
+ ON t.session_id = ? AND t.type = 'file'
24887
+ AND t.message_id >= o.value || ':file'
24888
+ AND t.message_id < o.value || ':file;'
24889
+ GROUP BY o.value
24890
+ `).all(JSON.stringify([...filesByMessage.keys()]), sessionId);
24891
+ for (const row of rows) {
24892
+ if (row.count < (filesByMessage.get(row.owner) ?? 0))
24893
+ totals.delete(row.owner);
24894
+ }
24895
+ return totals;
24896
+ }
24897
+
24784
24898
  // ../plugin/src/hooks/magic-context/protected-tail-boundary.ts
24785
24899
  function describeBoundaryDiagnostics(snapshot) {
24786
24900
  return `boundaryDiagnostics=${JSON.stringify(snapshot.diagnostics ?? { unavailable: true, boundaryReason: snapshot.boundaryReason })}`;
@@ -25005,7 +25119,7 @@ function resolveProtectedTailBoundary(ctx) {
25005
25119
  const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
25006
25120
  const absoluteMessageCount = getCachedAbsoluteMessageCount2(ctx.sessionId) ?? getRawSessionMessageOrdinalCount2(ctx.sessionId);
25007
25121
  const messages = readRawSessionMessageRange2(ctx.sessionId, Math.max(1, offset - 1), absoluteMessageCount);
25008
- const storedTotals = ctx.storedTokenTotalsForMessages?.(messages.map((m) => m.id)) ?? ctx.storedTokenTotals;
25122
+ const storedTotals = ctx.storedTokenTotalsForMessages?.(messages.map((m) => m.id), messages) ?? ctx.storedTokenTotals;
25009
25123
  const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
25010
25124
  providerShapeVersion: ctx.providerShapeVersion,
25011
25125
  cacheNamespace: ctx.cacheNamespace,
@@ -25248,9 +25362,10 @@ function resolveBoundaryContext(args) {
25248
25362
  migrationFloorActive = seedResult.seeded;
25249
25363
  }
25250
25364
  const calibration = sessionDecisionCalibration(args.db, args.sessionId);
25251
- const storedTokenTotalsForMessages = (messageIds) => {
25365
+ const storedTokenTotalsForMessages = (messageIds, messages = []) => {
25252
25366
  try {
25253
- return getAllStatusTagTokenTotalsFlat2(args.db, args.sessionId, args.taggerFloor ?? 0, calibration, messageIds).totals;
25367
+ const totals = getAllStatusTagTokenTotalsFlat2(args.db, args.sessionId, args.taggerFloor ?? 0, calibration, messageIds).totals;
25368
+ return omitIncompleteFileTokenTotals(args.db, args.sessionId, messages, totals);
25254
25369
  } catch (error) {
25255
25370
  sessionLog2(args.sessionId, "protected-tail stored-token map unavailable (live fallback):", error);
25256
25371
  return;
@@ -25285,7 +25400,7 @@ function resolveWrapupProtectedTailBoundary(args) {
25285
25400
  const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
25286
25401
  const absoluteMessageCount = getCachedAbsoluteMessageCount2(ctx.sessionId) ?? getRawSessionMessageOrdinalCount2(ctx.sessionId);
25287
25402
  const messages = readRawSessionMessageRange2(ctx.sessionId, Math.max(1, offset - 1), absoluteMessageCount);
25288
- const storedTotals = ctx.storedTokenTotalsForMessages?.(messages.map((m) => m.id)) ?? ctx.storedTokenTotals;
25403
+ const storedTotals = ctx.storedTokenTotalsForMessages?.(messages.map((m) => m.id), messages) ?? ctx.storedTokenTotals;
25289
25404
  const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
25290
25405
  providerShapeVersion: ctx.providerShapeVersion,
25291
25406
  cacheNamespace: ctx.cacheNamespace,
@@ -25783,8 +25898,9 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
25783
25898
  const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
25784
25899
  const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession2(db, sessionId), keepReasoningTokens, sessionMeta.clearedReasoningThroughTag, canClearReasoning, reasoningProjection?.budgetCutoff, eligiblePendingDropTagIds);
25785
25900
  const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
25901
+ const ridePermitted = reclaimRide !== undefined && (reclaimRide.permission ? reclaimRidePermitted(reclaimRide, reclaimRide.permission) : hasReclaimRide(reclaimRide));
25786
25902
  const rideLabel = reclaimRide ? reclaimRideLabel(reclaimRide) : "ride=none";
25787
- const dropsCanLand = reclaimRide !== undefined && hasReclaimRide(reclaimRide);
25903
+ const dropsCanLand = ridePermitted;
25788
25904
  const forceMaterializationPercentage = escalationBands(executeThresholdPercentage).forceMaterializationPercentage;
25789
25905
  if (usage.percentage >= forceMaterializationPercentage) {
25790
25906
  if (dropsCanLand && projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
@@ -26278,6 +26394,101 @@ function opencodeReasoningBudgetStatus(messages, budget, prefixBound, proseRatio
26278
26394
  };
26279
26395
  }
26280
26396
 
26397
+ // ../plugin/src/hooks/magic-context/signed-thinking-hold.ts
26398
+ var HEAVY_REASONING_TOKENS = 1500;
26399
+ var HEAVY_REASONING_WINDOW_STEPS = 15;
26400
+ var HOLD_CAP_POINTS = 10;
26401
+ var REASONING_TYPES = new Set(["reasoning", "thinking"]);
26402
+ function role2(message) {
26403
+ if (!isRecord(message))
26404
+ return;
26405
+ return isRecord(message.info) ? message.info.role : message.role;
26406
+ }
26407
+ function parts(message) {
26408
+ if (!isRecord(message))
26409
+ return [];
26410
+ if (Array.isArray(message.parts))
26411
+ return message.parts;
26412
+ return Array.isArray(message.content) ? message.content : [];
26413
+ }
26414
+ function recordedReasoningTokens(message) {
26415
+ if (!isRecord(message))
26416
+ return;
26417
+ const info = isRecord(message.info) ? message.info : undefined;
26418
+ const candidates = [];
26419
+ if (info && isRecord(info.tokens))
26420
+ candidates.push(info.tokens.reasoning);
26421
+ if (isRecord(message.usage)) {
26422
+ candidates.push(message.usage.reasoning, message.usage.reasoningTokens);
26423
+ }
26424
+ for (const value of candidates) {
26425
+ if (typeof value === "number" && Number.isFinite(value) && value > 0)
26426
+ return value;
26427
+ }
26428
+ return;
26429
+ }
26430
+ function stepReasoningTokens(message, estimateTextTokens) {
26431
+ let text = "";
26432
+ let opaque = false;
26433
+ for (const part of parts(message)) {
26434
+ if (!isRecord(part))
26435
+ continue;
26436
+ const type = String(part.type ?? part.kind);
26437
+ if (type === "redacted_thinking" || part.redacted === true) {
26438
+ opaque = true;
26439
+ continue;
26440
+ }
26441
+ if (!REASONING_TYPES.has(type))
26442
+ continue;
26443
+ const body = typeof part.thinking === "string" ? part.thinking : typeof part.text === "string" ? part.text : "";
26444
+ if (body.length > 0)
26445
+ text += body;
26446
+ else
26447
+ opaque = true;
26448
+ }
26449
+ if (!text && !opaque)
26450
+ return 0;
26451
+ return reasoningStepCost(recordedReasoningTokens(message), text ? estimateTextTokens(text) : 0, opaque);
26452
+ }
26453
+ function decideSignedThinkingHold(args) {
26454
+ const capPercentage = args.executeThresholdPercentage + HOLD_CAP_POINTS;
26455
+ let heavyStepsBack = null;
26456
+ let heavyStepTokens = 0;
26457
+ const start = latestAssistantTurnStart(args.messages);
26458
+ let stepsBack = 0;
26459
+ for (let index = args.messages.length - 1;index >= start; index--) {
26460
+ const message = args.messages[index];
26461
+ if (role2(message) !== "assistant" || parts(message).length === 0)
26462
+ continue;
26463
+ stepsBack++;
26464
+ if (stepsBack > HEAVY_REASONING_WINDOW_STEPS)
26465
+ break;
26466
+ const tokens = stepReasoningTokens(message, args.estimateTextTokens);
26467
+ if (tokens > HEAVY_REASONING_TOKENS) {
26468
+ heavyStepsBack = stepsBack;
26469
+ heavyStepTokens = tokens;
26470
+ break;
26471
+ }
26472
+ }
26473
+ if (heavyStepsBack === null)
26474
+ return {
26475
+ held: false,
26476
+ reason: "no_recent_heavy_reasoning",
26477
+ heavyStepsBack,
26478
+ heavyStepTokens,
26479
+ capPercentage
26480
+ };
26481
+ if (!(args.usagePercentage < capPercentage))
26482
+ return { held: false, reason: "above_cap", heavyStepsBack, heavyStepTokens, capPercentage };
26483
+ return {
26484
+ held: true,
26485
+ reason: "heavy_reasoning",
26486
+ heavyStepsBack,
26487
+ heavyStepTokens,
26488
+ capPercentage
26489
+ };
26490
+ }
26491
+
26281
26492
  // ../plugin/src/hooks/magic-context/strict-thinking-prefix.ts
26282
26493
  function servedPrefixMatches(args) {
26283
26494
  const heads = args.messages?.slice(0, 2);
@@ -26625,6 +26836,41 @@ ${typeof state?.output === "string" ? state.output : JSON.stringify(state?.outpu
26625
26836
  };
26626
26837
  }
26627
26838
 
26839
+ // ../plugin/src/hooks/magic-context/transform-stage-logger.ts
26840
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
26841
+ var SLOW_STAGE_MS = 100;
26842
+ var passes = new AsyncLocalStorage2;
26843
+ async function withTransformTimingSummary(run) {
26844
+ const pass = {
26845
+ stages: [],
26846
+ slow: [],
26847
+ closed: false,
26848
+ sessionId: undefined
26849
+ };
26850
+ return passes.run(pass, async () => {
26851
+ try {
26852
+ return await run();
26853
+ } finally {
26854
+ pass.closed = true;
26855
+ if (pass.sessionId)
26856
+ sessionLog2(pass.sessionId, `transform stages: ${pass.stages.join(" ")} slow>=${SLOW_STAGE_MS}ms=[${pass.slow.join(",")}]`);
26857
+ }
26858
+ });
26859
+ }
26860
+ function logTransformElapsed(sessionId, stage, elapsedMs, extra) {
26861
+ const elapsed = elapsedMs.toFixed(1);
26862
+ const suffix = extra ? ` ${extra}` : "";
26863
+ const pass = passes.getStore();
26864
+ if (pass && !pass.closed) {
26865
+ pass.sessionId = sessionId;
26866
+ pass.stages.push(`${stage}=${elapsed}ms${extra ? `(${extra})` : ""}`);
26867
+ if (elapsedMs >= SLOW_STAGE_MS)
26868
+ pass.slow.push(stage);
26869
+ }
26870
+ if (elapsedMs >= SLOW_STAGE_MS)
26871
+ sessionLog2(sessionId, `transform stage: stage=${stage} elapsed=${elapsed}ms${suffix}`);
26872
+ }
26873
+
26628
26874
  // ../plugin/src/shared/recovery-reasoning-prefix.ts
26629
26875
  function recoveryReasoningPrefixes(messages, partsKey) {
26630
26876
  const prefixes = [];
@@ -27070,12 +27316,12 @@ class ConversationEndGuard {
27070
27316
  this.end = message;
27071
27317
  }
27072
27318
  }
27073
- wouldStrand(occurrences) {
27319
+ wouldStrand(occurrences, plannedRemovals) {
27074
27320
  const end = this.end;
27075
27321
  if (!end || !occurrences.some((occ) => occ.message === end))
27076
27322
  return false;
27077
27323
  const leaving = new Set(occurrences.map((occ) => partKey(occ.part)));
27078
- const survives = (part) => !leaving.has(partKey(part)) && !this.removed.has(partKey(part));
27324
+ const survives = (part) => !leaving.has(partKey(part)) && !this.removed.has(partKey(part)) && !plannedRemovals?.has(partKey(part));
27079
27325
  return end.info.role === "assistant" ? !end.parts.some((part) => part.kind === "tool_result" && survives(part)) : !end.parts.some((part) => partHasContent(part) && survives(part));
27080
27326
  }
27081
27327
  noteRemoved(occurrences) {
@@ -27402,8 +27648,12 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
27402
27648
  }
27403
27649
  return null;
27404
27650
  },
27405
- wouldStrandConversationEnd() {
27406
- return conversationEnd?.wouldStrand(occurrences) ?? false;
27651
+ wouldStrandConversationEnd(plannedRemovals) {
27652
+ return conversationEnd?.wouldStrand(occurrences, plannedRemovals) ?? false;
27653
+ },
27654
+ notePlannedRemoval(plannedRemovals) {
27655
+ for (const occ of occurrences)
27656
+ plannedRemovals.add(partKey(occ.part));
27407
27657
  },
27408
27658
  editMarker() {
27409
27659
  const sentinel = `[dropped §${tagId}§]`;
@@ -27491,7 +27741,8 @@ function buildToolTarget(part, message, tagId) {
27491
27741
  }
27492
27742
 
27493
27743
  // ../plugin/src/hooks/magic-context/auto-search-deadline.ts
27494
- var AUTO_SEARCH_TIMEOUT_MS = 3000;
27744
+ var AUTO_SEARCH_TIMEOUT_MS = 1000;
27745
+ var AUTO_SEARCH_VECTOR_TIMEOUT_MS = 200;
27495
27746
  var operationDeadlines = new WeakMap;
27496
27747
  function autoSearchDeadlineUnixMs(signal) {
27497
27748
  const deadline = signal && operationDeadlines.get(signal);
@@ -27604,32 +27855,32 @@ function formatAge(committedAtMs) {
27604
27855
  const years = Math.floor(days / 365);
27605
27856
  return years === 1 ? "1y ago" : `${years}y ago`;
27606
27857
  }
27607
- function renderFragment(result, charCap, wordRules) {
27858
+ function renderFragment(result, charCap, wordRules, query) {
27608
27859
  switch (result.source) {
27609
27860
  case "memory": {
27610
- const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27861
+ const compressed = cavemanCompress(cleanSearchText(result.content), "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27611
27862
  return truncate2(compressed, charCap);
27612
27863
  }
27613
27864
  case "git_commit": {
27614
- const subject = result.content.split(/\r?\n/)[0] ?? result.content;
27865
+ const subject = cleanSearchText(result.content.split(/\r?\n/)[0] ?? result.content);
27615
27866
  const body = truncate2(subject, Math.max(10, charCap - 20));
27616
27867
  return `commit ${result.shortSha} ${formatAge(result.committedAtMs)}: ${body}`;
27617
27868
  }
27618
27869
  case "message": {
27619
- const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27870
+ const compressed = cavemanCompress(query ? matchedSearchSnippet(result.content, query, charCap) : cleanSearchText(result.content), "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27620
27871
  return truncate2(compressed, charCap);
27621
27872
  }
27622
27873
  case "compartment": {
27623
- const source = result.snippet ?? result.title;
27874
+ const source = cleanSearchText(result.title);
27624
27875
  const compressed = cavemanCompress(source, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27625
27876
  return truncate2(compressed, charCap);
27626
27877
  }
27627
27878
  case "primer": {
27628
- const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27879
+ const compressed = cavemanCompress(cleanSearchText(result.content), "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27629
27880
  return truncate2(compressed, charCap);
27630
27881
  }
27631
27882
  case "note": {
27632
- const compressed = cavemanCompress(result.content, "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27883
+ const compressed = cavemanCompress(cleanSearchText(result.content), "ultra", CURRENT_CAVEMAN_RULES, wordRules);
27633
27884
  return truncate2(compressed, charCap);
27634
27885
  }
27635
27886
  }
@@ -27640,7 +27891,7 @@ function buildAutoSearchHint(results, options = {}) {
27640
27891
  const picks = results.slice(0, maxFragments);
27641
27892
  const lines = [];
27642
27893
  for (const result of picks) {
27643
- const fragment = renderFragment(result, fragmentCharCap, options.wordRules ?? "english");
27894
+ const fragment = renderFragment(result, fragmentCharCap, options.wordRules ?? "english", options.query ?? "");
27644
27895
  if (fragment.length === 0)
27645
27896
  continue;
27646
27897
  lines.push(`- ${fragment}`);
@@ -27663,6 +27914,9 @@ ${trimmedBody}…
27663
27914
  }
27664
27915
  return wrapped;
27665
27916
  }
27917
+ function selectAutoSearchResults(results, threshold) {
27918
+ return results.filter((result) => (result.relevanceScore ?? result.score) >= threshold);
27919
+ }
27666
27920
 
27667
27921
  // ../plugin/src/hooks/magic-context/auto-search-worker-client.ts
27668
27922
  import { Worker } from "node:worker_threads";
@@ -27758,6 +28012,63 @@ async function searchAutoHint(db, sessionId, projectPath, query, options, entry
27758
28012
  return executeAutoSearchWorker(db, sessionId, projectPath, query, options, entry, "search");
27759
28013
  }
27760
28014
  var pendingBackfills = new WeakMap;
28015
+ var searchWorkers = new WeakMap;
28016
+ var liveSearchWorkers = new Set;
28017
+ var MAX_IDLE_SEARCH_WORKERS = 4;
28018
+ var SEARCH_WORKER_IDLE_MS = 5 * 60000;
28019
+ var workersCreated = 0;
28020
+ var workersReused = 0;
28021
+ async function acquireSearchWorker(db, key, entry, input, signal) {
28022
+ const pool = searchWorkers.get(db) ?? new Map;
28023
+ searchWorkers.set(db, pool);
28024
+ while (!signal.aborted) {
28025
+ let slot = pool.get(key);
28026
+ if (slot?.busy) {
28027
+ const current = slot;
28028
+ await new Promise((resolve) => {
28029
+ const done = () => {
28030
+ signal.removeEventListener("abort", done);
28031
+ resolve();
28032
+ };
28033
+ signal.addEventListener("abort", done, { once: true });
28034
+ current.busy?.then(done);
28035
+ if (signal.aborted)
28036
+ done();
28037
+ });
28038
+ continue;
28039
+ }
28040
+ const fresh = !slot;
28041
+ if (!slot) {
28042
+ const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: { ...input, persistent: true } }));
28043
+ slot = {
28044
+ worker,
28045
+ dispose() {
28046
+ clearTimeout(this.idleTimer);
28047
+ if (pool.get(key) === this)
28048
+ pool.delete(key);
28049
+ liveSearchWorkers.delete(this);
28050
+ worker.terminate();
28051
+ worker.unref();
28052
+ }
28053
+ };
28054
+ workersCreated++;
28055
+ pool.set(key, slot);
28056
+ liveSearchWorkers.add(slot);
28057
+ const current = slot;
28058
+ worker.on("error", () => current.dispose());
28059
+ worker.on("exit", () => current.dispose());
28060
+ } else
28061
+ workersReused++;
28062
+ clearTimeout(slot.idleTimer);
28063
+ const current = slot;
28064
+ current.busy = new Promise((resolve) => {
28065
+ current.release = resolve;
28066
+ });
28067
+ current.worker.ref();
28068
+ return { slot: current, fresh };
28069
+ }
28070
+ return null;
28071
+ }
27761
28072
  function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
27762
28073
  if (isEmbeddingHostBusy2())
27763
28074
  return Promise.resolve();
@@ -27822,6 +28133,7 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
27822
28133
  query,
27823
28134
  options: {
27824
28135
  ...serializable,
28136
+ autoHint: true,
27825
28137
  backfillMemoryEmbeddings: false,
27826
28138
  countRetrievals: false,
27827
28139
  measurementDisabled: true
@@ -27831,8 +28143,20 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
27831
28143
  snapshot,
27832
28144
  deadlineUnixMs: autoSearchDeadlineUnixMs(deadlineSignal)
27833
28145
  };
28146
+ let lease;
28147
+ try {
28148
+ lease = await acquireSearchWorker(db, `${input.harness}\x00${projectPath}\x00${job}\x00${entry.href}`, entry, input, signal);
28149
+ } catch (error) {
28150
+ lifecycle.done();
28151
+ throw error;
28152
+ }
28153
+ if (!lease) {
28154
+ lifecycle.done();
28155
+ return [];
28156
+ }
28157
+ const { slot, fresh } = lease;
28158
+ const worker = slot.worker;
27834
28159
  return new Promise((resolve, reject) => {
27835
- const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: input }));
27836
28160
  let settled = false;
27837
28161
  const finish = (results, error) => {
27838
28162
  if (settled)
@@ -27841,7 +28165,25 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
27841
28165
  signal?.removeEventListener("abort", abort);
27842
28166
  lifecycle.signal.removeEventListener("abort", abort);
27843
28167
  lifecycle.done();
27844
- worker.terminate();
28168
+ worker.off("message", onMessage);
28169
+ worker.off("error", onError);
28170
+ worker.off("exit", onExit);
28171
+ if (error || signal.aborted || entry.href !== defaultAutoSearchWorkerEntry().href)
28172
+ slot.dispose();
28173
+ else {
28174
+ slot.idleTimer = setTimeout(() => slot.dispose(), SEARCH_WORKER_IDLE_MS);
28175
+ slot.idleTimer.unref?.();
28176
+ }
28177
+ const release = slot.release;
28178
+ slot.busy = undefined;
28179
+ slot.release = undefined;
28180
+ release?.();
28181
+ const reusable = liveSearchWorkers.delete(slot);
28182
+ if (reusable)
28183
+ liveSearchWorkers.add(slot);
28184
+ const idle = [...liveSearchWorkers].filter((candidate) => !candidate.busy);
28185
+ for (const prior of idle.slice(0, Math.max(0, idle.length - MAX_IDLE_SEARCH_WORKERS)))
28186
+ prior.dispose();
27845
28187
  worker.unref();
27846
28188
  if (error)
27847
28189
  reject(error);
@@ -27851,9 +28193,9 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
27851
28193
  const abort = () => finish([]);
27852
28194
  signal?.addEventListener("abort", abort, { once: true });
27853
28195
  lifecycle.signal.addEventListener("abort", abort, { once: true });
27854
- worker.on("error", (error) => finish([], error));
27855
- worker.on("exit", (code) => finish([], new Error(`auto-search worker exited (${code})`)));
27856
- worker.on("message", async (reply) => {
28196
+ const onError = (error) => finish([], error);
28197
+ const onExit = (code) => finish([], new Error(`auto-search worker exited (${code})`));
28198
+ const onMessage = async (reply) => {
27857
28199
  if (settled)
27858
28200
  return;
27859
28201
  if (reply.kind === "result") {
@@ -27872,7 +28214,7 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
27872
28214
  const response = { id: reply.id };
27873
28215
  try {
27874
28216
  if (reply.kind === "query")
27875
- response.result = await (job === "backfill" ? embedTextForProject2(projectPath, reply.text, signal, "query") : embedQuery?.(reply.text, signal)) ?? null;
28217
+ response.result = await (job === "backfill" ? embedTextForProject2(projectPath, reply.text, signal, "query") : boundedHintEmbedding(embedQuery, reply.text, signal)) ?? null;
27876
28218
  else {
27877
28219
  const passage = await embedBatchForProject2(projectPath, reply.texts, signal, reply.purpose);
27878
28220
  const current = getProjectEmbeddingSnapshot2(projectPath);
@@ -27887,13 +28229,49 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
27887
28229
  response.error = error instanceof Error ? error.message : String(error);
27888
28230
  }
27889
28231
  response.embeddingHostBusy = isEmbeddingHostBusy2();
27890
- if (!settled && !signal?.aborted)
27891
- worker.postMessage(response);
27892
- });
28232
+ if (!settled && !signal?.aborted) {
28233
+ try {
28234
+ worker.postMessage(response);
28235
+ } catch (error) {
28236
+ finish([], error instanceof Error ? error : new Error(String(error)));
28237
+ }
28238
+ }
28239
+ };
28240
+ worker.on("error", onError);
28241
+ worker.on("exit", onExit);
28242
+ worker.on("message", onMessage);
27893
28243
  if (signal?.aborted)
27894
28244
  abort();
28245
+ else if (!fresh) {
28246
+ try {
28247
+ worker.postMessage({ kind: "run", input });
28248
+ } catch (error) {
28249
+ finish([], error instanceof Error ? error : new Error(String(error)));
28250
+ }
28251
+ }
27895
28252
  });
27896
28253
  }
28254
+ async function boundedHintEmbedding(embed, text, signal) {
28255
+ const controller = new AbortController;
28256
+ const combined = AbortSignal.any([signal, controller.signal]);
28257
+ let timer;
28258
+ try {
28259
+ return await Promise.race([
28260
+ Promise.resolve().then(() => embed?.(text, combined) ?? null),
28261
+ new Promise((resolve) => {
28262
+ timer = setTimeout(() => {
28263
+ resolve(null);
28264
+ controller.abort();
28265
+ }, AUTO_SEARCH_VECTOR_TIMEOUT_MS);
28266
+ })
28267
+ ]);
28268
+ } finally {
28269
+ clearTimeout(timer);
28270
+ }
28271
+ }
28272
+ function defaultAutoSearchWorkerEntry() {
28273
+ return new URL(new URL(import.meta.url).pathname.endsWith(".ts") ? "./auto-search-worker.ts" : "./auto-search-worker.js", import.meta.url);
28274
+ }
27897
28275
  var messageSearchWorkerFallbacks = new Map;
27898
28276
 
27899
28277
  // src/auto-search-pi.ts
@@ -28083,6 +28461,8 @@ async function runAutoSearchHintForPi(args) {
28083
28461
  const gitCommitsEnabled = snapshot?.gitCommitEnabled ?? false;
28084
28462
  const searchOptions = {
28085
28463
  limit: 10,
28464
+ maxMessageOrdinal: Math.max(0, getLastCompartmentEndMessage(db, sessionId)),
28465
+ excludeMessageId: userMsgId,
28086
28466
  memoryEnabled,
28087
28467
  embeddingEnabled,
28088
28468
  gitCommitsEnabled,
@@ -28124,13 +28504,15 @@ async function runAutoSearchHintForPi(args) {
28124
28504
  return messages;
28125
28505
  }
28126
28506
  const scoreThreshold = options.scoreThreshold ?? DEFAULT_SCORE_THRESHOLD;
28127
- if (results[0].score < scoreThreshold) {
28128
- sessionLog2(sessionId, `auto-search: top score ${results[0].score.toFixed(3)} below threshold ${scoreThreshold}`);
28507
+ results = selectAutoSearchResults(results, scoreThreshold);
28508
+ if (results.length === 0) {
28509
+ sessionLog2(sessionId, `auto-search: no fragment meets relevance threshold ${scoreThreshold}`);
28129
28510
  await writeNoHintAndReconcile("below-threshold");
28130
28511
  return messages;
28131
28512
  }
28132
28513
  const hintText = buildAutoSearchHint(results, {
28133
- wordRules: options.wordRules
28514
+ wordRules: options.wordRules,
28515
+ query: rawPrompt
28134
28516
  });
28135
28517
  if (!hintText) {
28136
28518
  await writeNoHintAndReconcile("empty");
@@ -28563,6 +28945,7 @@ async function runHistorianSubagentWithTransientRetriesGuarded(args) {
28563
28945
  args.onDispatch?.();
28564
28946
  result = await args.runner.run({
28565
28947
  ...args.options,
28948
+ cacheTail: retryIndex > 0 ? "write" : args.options.cacheTail ?? "skip",
28566
28949
  fallbackModels: undefined
28567
28950
  });
28568
28951
  } catch (error) {
@@ -34029,6 +34412,54 @@ function isSentinelPart(part) {
34029
34412
  return p.type === "text" && typeof p.text === "string" && (p.text === "" || p.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT);
34030
34413
  }
34031
34414
 
34415
+ // src/pi-append-compaction.ts
34416
+ var loggedIncompatibleHost = false;
34417
+ var failedWrites = new WeakMap;
34418
+ function adaptPiAppendCompaction(sessionManager) {
34419
+ if (!sessionManager || typeof sessionManager !== "object")
34420
+ return;
34421
+ const host = sessionManager;
34422
+ const append = host.appendCompaction;
34423
+ if (typeof append !== "function")
34424
+ return;
34425
+ if (failedWrites.has(host))
34426
+ return;
34427
+ const harness = resolvePiHarnessKind();
34428
+ if ((harness === "omp" ? append.length !== 4 && append.length !== 7 : append.length !== 5 && append.length !== 6) || typeof host.getEntry !== "function") {
34429
+ if (!loggedIncompatibleHost) {
34430
+ loggedIncompatibleHost = true;
34431
+ log2(`ERROR: compaction marker disabled: incompatible host binding harness=${harness} arity=${append.length} getEntry=${typeof host.getEntry}; leaving marker pending`);
34432
+ }
34433
+ return;
34434
+ }
34435
+ const getEntry = host.getEntry.bind(host);
34436
+ return (summary, firstKeptEntryId, tokensBefore, details, fromHook) => {
34437
+ const previousFailure = failedWrites.get(host);
34438
+ if (previousFailure)
34439
+ throw previousFailure;
34440
+ let id;
34441
+ if (harness === "pi") {
34442
+ id = append.call(host, summary, firstKeptEntryId, tokensBefore, details, fromHook);
34443
+ } else if (append.length === 7) {
34444
+ id = append.call(host, summary, undefined, firstKeptEntryId, tokensBefore, details, fromHook);
34445
+ } else {
34446
+ id = append.call(host, summary, undefined, firstKeptEntryId, tokensBefore, { details, fromExtension: fromHook });
34447
+ }
34448
+ try {
34449
+ const entry = typeof id === "string" && id.length > 0 ? getEntry(id) : undefined;
34450
+ if (entry?.type !== "compaction" || entry.firstKeptEntryId !== firstKeptEntryId || entry.details?.source !== "magic-context") {
34451
+ throw new Error("Compaction marker read-back mismatch");
34452
+ }
34453
+ } catch {
34454
+ const error = new Error("Compaction marker read-back failed; writes disabled for this session manager until restart");
34455
+ failedWrites.set(host, error);
34456
+ log2(`ERROR: compaction marker read-back failed harness=${harness} compactionId=${typeof id === "string" ? id : "<missing>"} expectedFirstKept=${firstKeptEntryId}; further writes disabled for this session manager until restart; leaving marker pending`);
34457
+ throw error;
34458
+ }
34459
+ return id;
34460
+ };
34461
+ }
34462
+
34032
34463
  // src/pi-context-budget.ts
34033
34464
  var PI_CONTEXT_BUDGET = {
34034
34465
  hostDeadlineMs: 30000,
@@ -34838,10 +35269,50 @@ function piHasManagedSignature(payload, signature) {
34838
35269
  return false;
34839
35270
  }
34840
35271
 
35272
+ // src/pi-dispatch-tool-pairing.ts
35273
+ var RESPONSES_APIS = new Set([
35274
+ "openai-responses",
35275
+ "openai-codex-responses",
35276
+ "azure-openai-responses"
35277
+ ]);
35278
+ function object4(value) {
35279
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
35280
+ }
35281
+ function piResponsesCallComponent(id) {
35282
+ const pipe = id.indexOf("|");
35283
+ return pipe <= 0 ? id : id.slice(0, pipe);
35284
+ }
35285
+ function piToolCallPairing(messages) {
35286
+ const responsesComponents = new Set;
35287
+ const opaqueCompositeIds = new Set;
35288
+ for (const value of messages) {
35289
+ const message = object4(value);
35290
+ if (message?.role !== "assistant" || !Array.isArray(message.content))
35291
+ continue;
35292
+ const responses = RESPONSES_APIS.has(String(message.api));
35293
+ for (const part of message.content) {
35294
+ const block = object4(part);
35295
+ if (block?.type !== "toolCall" || typeof block.id !== "string")
35296
+ continue;
35297
+ if (responses)
35298
+ responsesComponents.add(piResponsesCallComponent(block.id));
35299
+ else if (block.id.includes("|"))
35300
+ opaqueCompositeIds.add(block.id);
35301
+ }
35302
+ }
35303
+ return (id) => {
35304
+ const pipe = id.indexOf("|");
35305
+ if (pipe <= 0 || opaqueCompositeIds.has(id))
35306
+ return id;
35307
+ const prefix = id.slice(0, pipe);
35308
+ return responsesComponents.has(prefix) ? prefix : id;
35309
+ };
35310
+ }
35311
+
34841
35312
  // src/pi-dispatch-chat-history.ts
34842
35313
  var MAX_EXACT_UNITS = 32 * 1024 * 1024;
34843
35314
  var IMAGE_CAPTION = "Attached image(s) from tool result:";
34844
- function object4(value) {
35315
+ function object5(value) {
34845
35316
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34846
35317
  }
34847
35318
  function omitsAssistant(message, model, compat) {
@@ -34850,7 +35321,7 @@ function omitsAssistant(message, model, compat) {
34850
35321
  let thinking = false;
34851
35322
  let hasTextBlock = false;
34852
35323
  for (const value of message.content) {
34853
- const block = object4(value);
35324
+ const block = object5(value);
34854
35325
  if (!block)
34855
35326
  return false;
34856
35327
  if (block.type === "text") {
@@ -34875,23 +35346,24 @@ function omitsAssistant(message, model, compat) {
34875
35346
  function piChatHistoryPlan(messages, model) {
34876
35347
  if (model?.api !== "openai-completions")
34877
35348
  return;
34878
- const compat = object4(model.compat) ?? {};
35349
+ const compat = object5(model.compat) ?? {};
35350
+ const pairingId = piToolCallPairing(messages);
34879
35351
  const calls = new Set;
34880
35352
  for (const value of messages) {
34881
- const message = object4(value);
35353
+ const message = object5(value);
34882
35354
  if (message?.role !== "assistant" || !Array.isArray(message.content))
34883
35355
  continue;
34884
35356
  for (const value of message.content) {
34885
- const block = object4(value);
35357
+ const block = object5(value);
34886
35358
  if (block?.type === "toolCall" && typeof block.id === "string")
34887
- calls.add(block.id);
35359
+ calls.add(pairingId(block.id));
34888
35360
  }
34889
35361
  }
34890
35362
  const transformed = [];
34891
35363
  let pending = new Set;
34892
35364
  let exactUnits = 0;
34893
35365
  for (let index = 0;index < messages.length; index++) {
34894
- const message = object4(messages[index]);
35366
+ const message = object5(messages[index]);
34895
35367
  if (!message)
34896
35368
  return;
34897
35369
  if ((message.role === "bashExecution" || message.role === "pythonExecution") && message.excludeFromContext === true)
@@ -34903,19 +35375,19 @@ function piChatHistoryPlan(messages, model) {
34903
35375
  continue;
34904
35376
  if (Array.isArray(message.content))
34905
35377
  for (const value of message.content) {
34906
- const block = object4(value);
35378
+ const block = object5(value);
34907
35379
  if (block?.type === "toolCall" && typeof block.id === "string")
34908
- pending.add(block.id);
35380
+ pending.add(pairingId(block.id));
34909
35381
  }
34910
35382
  }
34911
35383
  if (message.role === "toolResult" && typeof message.toolCallId === "string") {
34912
- pending.delete(message.toolCallId);
34913
- if (!calls.has(message.toolCallId)) {
35384
+ pending.delete(pairingId(message.toolCallId));
35385
+ if (!calls.has(pairingId(message.toolCallId))) {
34914
35386
  if (pending.size || typeof message.toolName !== "string" || !Array.isArray(message.content))
34915
35387
  return;
34916
35388
  const parts = [];
34917
35389
  for (const value of message.content) {
34918
- const part = object4(value);
35390
+ const part = object5(value);
34919
35391
  if (part?.type === "text" && typeof part.text === "string" && part.text.trim())
34920
35392
  parts.push(part.text);
34921
35393
  }
@@ -34948,14 +35420,14 @@ ${parts.join(`
34948
35420
  };
34949
35421
  const vision = model.input?.includes("image") === true && compat.stripImageInput !== true;
34950
35422
  for (const step of transformed) {
34951
- const message = step.kind === "source" ? object4(messages[step.index]) : undefined;
35423
+ const message = step.kind === "source" ? object5(messages[step.index]) : undefined;
34952
35424
  if (message?.role !== "toolResult")
34953
35425
  flushImages();
34954
35426
  steps.push(step);
34955
35427
  if (message?.role !== "toolResult" || !vision || !Array.isArray(message.content))
34956
35428
  continue;
34957
35429
  for (const value of message.content) {
34958
- const block = object4(value);
35430
+ const block = object5(value);
34959
35431
  if (block?.type !== "image")
34960
35432
  continue;
34961
35433
  if (compat.requiresAssistantAfterToolResult === true)
@@ -34979,12 +35451,12 @@ ${parts.join(`
34979
35451
  function piMatchesChatImages(content, urls) {
34980
35452
  if (!Array.isArray(content) || content.length !== urls.length + 1)
34981
35453
  return false;
34982
- const caption = object4(content[0]);
35454
+ const caption = object5(content[0]);
34983
35455
  if (caption?.type !== "text" || caption.text !== IMAGE_CAPTION || Object.keys(caption).length !== 2)
34984
35456
  return false;
34985
35457
  for (let i = 0;i < urls.length; i++) {
34986
- const block = object4(content[i + 1]);
34987
- const image = object4(block?.image_url);
35458
+ const block = object5(content[i + 1]);
35459
+ const image = object5(block?.image_url);
34988
35460
  if (block?.type !== "image_url" || Object.keys(block).length !== 2 || !image || Object.keys(image).length !== 1 || image.url !== urls[i])
34989
35461
  return false;
34990
35462
  }
@@ -34992,22 +35464,22 @@ function piMatchesChatImages(content, urls) {
34992
35464
  }
34993
35465
 
34994
35466
  // src/pi-dispatch-image-budget.ts
34995
- function object5(value) {
35467
+ function object6(value) {
34996
35468
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34997
35469
  }
34998
35470
  function piImageBudgetPlan(model) {
34999
- if (!model?.input?.includes("image") || object5(model.compat)?.stripImageInput === true)
35471
+ if (!model?.input?.includes("image") || object6(model.compat)?.stripImageInput === true)
35000
35472
  return;
35001
35473
  return {
35002
35474
  count: 0,
35003
35475
  api: model.api,
35004
35476
  rows: new Map,
35005
- hoistToolImages: model.api?.startsWith("google-") === true && object5(model.compat)?.multimodalFunctionResponse !== true || model.api === "bedrock-converse-stream" && model.requiresToolResultImageHoisting === true,
35477
+ hoistToolImages: model.api?.startsWith("google-") === true && object6(model.compat)?.multimodalFunctionResponse !== true || model.api === "bedrock-converse-stream" && model.requiresToolResultImageHoisting === true,
35006
35478
  hoistErrorImages: model.api === "anthropic-messages" || model.api === "bedrock-converse-stream"
35007
35479
  };
35008
35480
  }
35009
35481
  function inputImage(block, api) {
35010
- const file = object5(block.providerFile);
35482
+ const file = object6(block.providerFile);
35011
35483
  if (api === "ollama-chat")
35012
35484
  return { kind: "bytes", value: String(block.data ?? "") };
35013
35485
  if ((api?.endsWith("responses") && file?.provider === "openai" || api === "anthropic-messages" && file?.provider === "anthropic") && typeof file?.id === "string")
@@ -35027,7 +35499,7 @@ function piRecordImages(plan, row, source) {
35027
35499
  return;
35028
35500
  const images = [];
35029
35501
  for (const value of source.content) {
35030
- const block = object5(value);
35502
+ const block = object6(value);
35031
35503
  if (block?.type === "image")
35032
35504
  images.push(inputImage(block, plan.api));
35033
35505
  }
@@ -35053,20 +35525,20 @@ function piWireImages(content, ollamaImages) {
35053
35525
  return [];
35054
35526
  const images = [];
35055
35527
  for (const value of content) {
35056
- const block = object5(value);
35528
+ const block = object6(value);
35057
35529
  if (!block)
35058
35530
  continue;
35059
- const source = object5(block.source);
35060
- const inline = object5(block.inlineData);
35061
- const file = object5(block.fileData);
35062
- const bedrock = object5(block.image);
35531
+ const source = object6(block.source);
35532
+ const inline = object6(block.inlineData);
35533
+ const file = object6(block.fileData);
35534
+ const bedrock = object6(block.image);
35063
35535
  if (block.type === "image_url" || block.type === "input_image") {
35064
35536
  if (typeof block.file_id === "string")
35065
35537
  images.push({ kind: "file", value: block.file_id });
35066
35538
  else
35067
35539
  images.push({
35068
35540
  kind: "url",
35069
- value: String(typeof block.image_url === "string" ? block.image_url : object5(block.image_url)?.url)
35541
+ value: String(typeof block.image_url === "string" ? block.image_url : object6(block.image_url)?.url)
35070
35542
  });
35071
35543
  } else if (block.type === "image") {
35072
35544
  if (source?.type === "file")
@@ -35090,7 +35562,7 @@ function piWireImages(content, ollamaImages) {
35090
35562
  else if (bedrock)
35091
35563
  images.push({
35092
35564
  kind: "data",
35093
- value: String(object5(bedrock.source)?.bytes),
35565
+ value: String(object6(bedrock.source)?.bytes),
35094
35566
  mime: `image/${bedrock.format}`
35095
35567
  });
35096
35568
  }
@@ -35112,11 +35584,11 @@ function piMatchesImages(actual, expected) {
35112
35584
  return true;
35113
35585
  }
35114
35586
  function piWireImageCount(payload) {
35115
- const body = object5(payload);
35587
+ const body = object6(payload);
35116
35588
  const visit = (value) => {
35117
35589
  if (Array.isArray(value))
35118
35590
  return value.reduce((n, item) => n + visit(item), 0);
35119
- const block = object5(value);
35591
+ const block = object6(value);
35120
35592
  if (!block)
35121
35593
  return 0;
35122
35594
  if (["image", "image_url", "input_image"].includes(String(block.type)) || block.inlineData || block.fileData || block.image)
@@ -35130,12 +35602,12 @@ function piWireImageCount(payload) {
35130
35602
  block.response
35131
35603
  ].reduce((n, item) => n + visit(item), Array.isArray(block.images) ? block.images.length : 0);
35132
35604
  };
35133
- return visit(body?.messages ?? body?.input ?? body?.contents ?? object5(body?.request)?.contents);
35605
+ return visit(body?.messages ?? body?.input ?? body?.contents ?? object6(body?.request)?.contents);
35134
35606
  }
35135
35607
 
35136
35608
  // src/pi-dispatch-responses-history.ts
35137
35609
  var MAX_TEXT_UNITS = 32 * 1024 * 1024;
35138
- function object6(value) {
35610
+ function object7(value) {
35139
35611
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
35140
35612
  }
35141
35613
  function wellFormed(text) {
@@ -35150,7 +35622,7 @@ function textIdentity2(text, phase) {
35150
35622
  function signaturePhase(block) {
35151
35623
  try {
35152
35624
  if (typeof block.textSignature === "string") {
35153
- const signature = object6(JSON.parse(block.textSignature));
35625
+ const signature = object7(JSON.parse(block.textSignature));
35154
35626
  if (signature?.v === 1 && typeof signature.id === "string")
35155
35627
  return signature.phase;
35156
35628
  }
@@ -35170,17 +35642,17 @@ ${wellFormed(text)}
35170
35642
  return;
35171
35643
  }
35172
35644
  function piResponsesAssistantTexts(value, model) {
35173
- const message = object6(value);
35645
+ const message = object7(value);
35174
35646
  if (!message || !Array.isArray(message.content))
35175
35647
  return;
35176
- if (["length", "error", "aborted"].includes(String(message.stopReason)) && !message.content.some((value) => ["text", "toolCall"].includes(String(object6(value)?.type))))
35648
+ if (["length", "error", "aborted"].includes(String(message.stopReason)) && !message.content.some((value) => ["text", "toolCall"].includes(String(object7(value)?.type))))
35177
35649
  return [];
35178
35650
  const texts = [];
35179
35651
  const blocks = [];
35180
35652
  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;
35181
35653
  let units = 0;
35182
35654
  for (const value of message.content) {
35183
- const block = object6(value);
35655
+ const block = object7(value);
35184
35656
  if (block?.type === "toolCall")
35185
35657
  continue;
35186
35658
  if (block?.type === "thinking") {
@@ -35190,7 +35662,7 @@ function piResponsesAssistantTexts(value, model) {
35190
35662
  return;
35191
35663
  if (!block.thinking.trim())
35192
35664
  continue;
35193
- const compat = object6(model.compat);
35665
+ const compat = object7(model.compat);
35194
35666
  if (block.summary === false && (compat?.requiresReasoningContentForToolCalls === true || compat?.requiresReasoningContentForAllAssistantTurns === true))
35195
35667
  return;
35196
35668
  const text = demotedThinking(block.thinking, model);
@@ -35210,14 +35682,14 @@ function piResponsesAssistantTexts(value, model) {
35210
35682
  texts.push(textIdentity2(wellFormed(block.text), sameModel ? signaturePhase(block) : undefined));
35211
35683
  blocks.push(block);
35212
35684
  }
35213
- const payload = object6(message.providerPayload);
35685
+ const payload = object7(message.providerPayload);
35214
35686
  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))
35215
35687
  return texts;
35216
35688
  const replay = [];
35217
35689
  let bound = 0;
35218
35690
  let output = false;
35219
35691
  for (const value of payload.items) {
35220
- const item = object6(value);
35692
+ const item = object7(value);
35221
35693
  if (item?.type === "reasoning")
35222
35694
  continue;
35223
35695
  if (item?.type === "function_call" || item?.type === "custom_tool_call") {
@@ -35228,14 +35700,14 @@ function piResponsesAssistantTexts(value, model) {
35228
35700
  return texts;
35229
35701
  const itemTexts = [];
35230
35702
  for (const value of item.content) {
35231
- const part = object6(value);
35703
+ const part = object7(value);
35232
35704
  const block = blocks[bound];
35233
35705
  if (!block || part?.type !== "output_text" || typeof part.text !== "string")
35234
35706
  return texts;
35235
35707
  let signature;
35236
35708
  try {
35237
35709
  if (typeof block.textSignature === "string")
35238
- signature = object6(JSON.parse(block.textSignature));
35710
+ signature = object7(JSON.parse(block.textSignature));
35239
35711
  } catch {
35240
35712
  return texts;
35241
35713
  }
@@ -35262,7 +35734,7 @@ function piResponsesWireTexts(value, phase) {
35262
35734
  const texts = [];
35263
35735
  let units = 0;
35264
35736
  for (const partValue of value) {
35265
- const part = object6(partValue);
35737
+ const part = object7(partValue);
35266
35738
  if (part?.type !== "output_text" || typeof part.text !== "string")
35267
35739
  return;
35268
35740
  units += part.text.length;
@@ -35292,11 +35764,11 @@ var TRANSFORM_MESSAGES_APIS = new Set([
35292
35764
  "devin-agent",
35293
35765
  "apple-foundation-models"
35294
35766
  ]);
35295
- function object7(value) {
35767
+ function object8(value) {
35296
35768
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
35297
35769
  }
35298
35770
  function messageStructure(value) {
35299
- const message = object7(value);
35771
+ const message = object8(value);
35300
35772
  if (!message)
35301
35773
  return;
35302
35774
  const role = [
@@ -35325,7 +35797,7 @@ function messageStructure(value) {
35325
35797
  }
35326
35798
  if (role === "assistant" && Array.isArray(message.content)) {
35327
35799
  for (const value of message.content) {
35328
- const block = object7(value);
35800
+ const block = object8(value);
35329
35801
  if (block?.type !== "toolCall" && block?.type !== "tool_use")
35330
35802
  continue;
35331
35803
  if (typeof block.id !== "string")
@@ -35337,41 +35809,249 @@ function messageStructure(value) {
35337
35809
  }
35338
35810
  return row;
35339
35811
  }
35340
- function projectMissingToolResults(messages, api) {
35341
- const projectOrphans = TRANSFORM_MESSAGES_APIS.has(api ?? "");
35812
+ function windowCalls(message) {
35813
+ if (!Array.isArray(message.content))
35814
+ return [];
35815
+ return message.content.flatMap((value) => {
35816
+ const block = object8(value);
35817
+ return block?.type === "toolCall" && typeof block.id === "string" ? [
35818
+ {
35819
+ id: block.id,
35820
+ name: typeof block.name === "string" ? block.name : ""
35821
+ }
35822
+ ] : [];
35823
+ });
35824
+ }
35825
+ function duplicateSuffix(model) {
35826
+ const compat = object8(model?.compat);
35827
+ if (model?.api === "openai-completions") {
35828
+ if (compat?.requiresMistralToolIds === true)
35829
+ return { prefix: "dup", max: 9 };
35830
+ if (compat?.usesOpenAIToolCallIdLimit === true)
35831
+ return { prefix: "_dup", max: 40 };
35832
+ }
35833
+ if (model?.api === "devin-agent")
35834
+ return { prefix: "_dup", max: 40 };
35835
+ return { prefix: "_dup", max: 64 };
35836
+ }
35837
+ function appendDuplicateSuffix(id, suffix, max) {
35838
+ const segment = (part) => part.length + suffix.length <= max ? `${part}${suffix}` : `${part.slice(0, Math.max(0, max - suffix.length))}${suffix}`;
35839
+ return id.includes("|") ? id.split("|").map(segment).join("|") : segment(id);
35840
+ }
35841
+ function projectMissingToolResults(messages, model, host = "omp") {
35842
+ const input = messages.filter((value) => {
35843
+ const message = object8(value);
35844
+ return !((message?.role === "bashExecution" || message?.role === "pythonExecution") && message.excludeFromContext === true);
35845
+ });
35846
+ if (host === "pi")
35847
+ return projectPiToolResults(input);
35848
+ const api = model?.api;
35849
+ if (!TRANSFORM_MESSAGES_APIS.has(api ?? ""))
35850
+ return projectUnmodeledToolResults(messages);
35851
+ const pairingId = piToolCallPairing(input);
35852
+ const { prefix, max } = duplicateSuffix(model);
35853
+ const seen = new Map;
35854
+ const renames = new Map;
35855
+ const realResults = new Map;
35856
+ const validToolUseIds = new Set;
35857
+ const deduplicated = input.map((value, index) => {
35858
+ const message = object8(value);
35859
+ if (message?.role === "toolResult" && typeof message.toolCallId === "string") {
35860
+ let key = pairingId(message.toolCallId);
35861
+ let output = value;
35862
+ const queue = renames.get(key);
35863
+ if (queue?.length) {
35864
+ const replacement = queue.shift();
35865
+ if (!queue.length)
35866
+ renames.delete(key);
35867
+ if (replacement !== undefined) {
35868
+ output = { ...message, toolCallId: replacement };
35869
+ key = pairingId(replacement);
35870
+ }
35871
+ }
35872
+ const entry = { index, message: output, consumed: false };
35873
+ const entries = realResults.get(key);
35874
+ if (entries)
35875
+ entries.push(entry);
35876
+ else
35877
+ realResults.set(key, [entry]);
35878
+ return output;
35879
+ }
35880
+ if (message?.role !== "assistant" || !Array.isArray(message.content))
35881
+ return value;
35882
+ const touched = new Set;
35883
+ let changed = false;
35884
+ const content = message.content.map((part) => {
35885
+ const block = object8(part);
35886
+ if (block?.type !== "toolCall" || typeof block.id !== "string")
35887
+ return part;
35888
+ const key = pairingId(block.id);
35889
+ if (!touched.has(key)) {
35890
+ touched.add(key);
35891
+ renames.delete(key);
35892
+ }
35893
+ const count = seen.get(key) ?? 0;
35894
+ const queue = renames.get(key) ?? [];
35895
+ renames.set(key, queue);
35896
+ if (count === 0) {
35897
+ seen.set(key, 1);
35898
+ queue.push(undefined);
35899
+ return part;
35900
+ }
35901
+ let suffix = count;
35902
+ let replacement = appendDuplicateSuffix(block.id, `${prefix}${suffix}`, max);
35903
+ while (seen.has(pairingId(replacement))) {
35904
+ suffix++;
35905
+ replacement = appendDuplicateSuffix(block.id, `${prefix}${suffix}`, max);
35906
+ }
35907
+ seen.set(key, suffix + 1);
35908
+ seen.set(pairingId(replacement), 1);
35909
+ queue.push(replacement);
35910
+ changed = true;
35911
+ return { ...block, id: replacement };
35912
+ });
35913
+ for (const call of windowCalls({ content }))
35914
+ validToolUseIds.add(pairingId(call.id));
35915
+ return changed ? { ...message, content } : value;
35916
+ });
35917
+ const takeRealResult = (id, afterIndex) => {
35918
+ for (const entry of realResults.get(pairingId(id)) ?? []) {
35919
+ if (entry.consumed || entry.index <= afterIndex)
35920
+ continue;
35921
+ entry.consumed = true;
35922
+ return entry.message;
35923
+ }
35924
+ return;
35925
+ };
35926
+ const projected = [];
35927
+ const answered = new Set;
35928
+ let pending = [];
35929
+ let pendingStart = -1;
35930
+ let aborted = new Map;
35931
+ let abortedTimestamp;
35932
+ let abortedStart = -1;
35933
+ const stub = (call, text, timestamp) => ({
35934
+ role: "toolResult",
35935
+ toolCallId: call.id,
35936
+ toolName: call.name,
35937
+ content: [{ type: "text", text }],
35938
+ isError: true,
35939
+ timestamp
35940
+ });
35941
+ const flush = (boundaryTimestamp) => {
35942
+ for (const call of pending) {
35943
+ const key = pairingId(call.id);
35944
+ if (answered.has(key))
35945
+ continue;
35946
+ projected.push(takeRealResult(call.id, pendingStart) ?? stub(call, "No result provided", boundaryTimestamp));
35947
+ answered.add(key);
35948
+ }
35949
+ pending = [];
35950
+ if (abortedTimestamp === undefined)
35951
+ return;
35952
+ for (const call of aborted.values()) {
35953
+ const key = pairingId(call.id);
35954
+ if (answered.has(key))
35955
+ continue;
35956
+ projected.push(takeRealResult(call.id, abortedStart) ?? stub(call, "aborted", abortedTimestamp));
35957
+ answered.add(key);
35958
+ }
35959
+ aborted = new Map;
35960
+ abortedTimestamp = undefined;
35961
+ };
35962
+ for (let index = 0;index < deduplicated.length; index++) {
35963
+ const value = deduplicated[index];
35964
+ const message = object8(value);
35965
+ if (message?.role === "assistant") {
35966
+ flush(message.timestamp);
35967
+ projected.push(value);
35968
+ const calls = windowCalls(message);
35969
+ const truncated = ["length", "error", "aborted"].includes(String(message.stopReason));
35970
+ if (truncated && Array.isArray(message.content) && !message.content.some((part) => ["toolCall", "text"].includes(String(object8(part)?.type))))
35971
+ continue;
35972
+ if (message.stopReason === "aborted" || message.stopReason === "error") {
35973
+ aborted = new Map(calls.map((call) => [pairingId(call.id), call]));
35974
+ abortedTimestamp = message.timestamp;
35975
+ abortedStart = index;
35976
+ } else if (calls.length) {
35977
+ pending = calls;
35978
+ pendingStart = index;
35979
+ }
35980
+ continue;
35981
+ }
35982
+ if (message?.role !== "toolResult" || typeof message.toolCallId !== "string") {
35983
+ if (message?.role !== "toolResult")
35984
+ flush(message?.timestamp);
35985
+ projected.push(value);
35986
+ continue;
35987
+ }
35988
+ const key = pairingId(message.toolCallId);
35989
+ if (answered.has(key))
35990
+ continue;
35991
+ if (aborted.has(key) || pending.some((call) => pairingId(call.id) === key)) {
35992
+ aborted.delete(key);
35993
+ answered.add(key);
35994
+ projected.push(value);
35995
+ continue;
35996
+ }
35997
+ if (validToolUseIds.has(key))
35998
+ continue;
35999
+ if (typeof message.toolName !== "string" || !Array.isArray(message.content)) {
36000
+ projected.push(value);
36001
+ continue;
36002
+ }
36003
+ if (pending.some((call) => !answered.has(pairingId(call.id))) || aborted.size > 0)
36004
+ continue;
36005
+ const parts = message.content.flatMap((value) => {
36006
+ const part = object8(value);
36007
+ return part?.type === "text" && typeof part.text === "string" && part.text.trim() ? [part.text] : [];
36008
+ });
36009
+ if (!parts.length)
36010
+ continue;
36011
+ const error = message.isError ? ' is-error="true"' : "";
36012
+ const note = `<stale-tool-result tool="${message.toolName}" id="${message.toolCallId}"${error}>
36013
+ ${parts.join(`
36014
+ `)}
36015
+ </stale-tool-result>`;
36016
+ projected.push({
36017
+ role: "user",
36018
+ content: api === "ollama-chat" ? note : new TextDecoder().decode(new TextEncoder().encode(note)),
36019
+ timestamp: message.timestamp,
36020
+ [ORPHAN_NOTE]: true
36021
+ });
36022
+ }
36023
+ flush();
36024
+ return projected;
36025
+ }
36026
+ function projectUnmodeledToolResults(messages) {
35342
36027
  const responsesComponents = new Set;
35343
36028
  const opaqueIds = new Set;
35344
- const validToolUseIds = projectOrphans ? new Set : undefined;
35345
36029
  const component = (id) => {
35346
36030
  const pipe = id.indexOf("|");
35347
36031
  return pipe > 0 ? id.slice(0, pipe) : id;
35348
36032
  };
35349
36033
  for (const value of messages) {
35350
- const message = object7(value);
36034
+ const message = object8(value);
35351
36035
  if (message?.role !== "assistant" || !Array.isArray(message.content))
35352
36036
  continue;
35353
36037
  for (const value of message.content) {
35354
- const block = object7(value);
36038
+ const block = object8(value);
35355
36039
  if (block?.type !== "toolCall" || typeof block.id !== "string")
35356
36040
  continue;
35357
36041
  if ([
35358
36042
  "openai-responses",
35359
36043
  "azure-openai-responses",
35360
36044
  "openai-codex-responses"
35361
- ].includes(String(message.api))) {
36045
+ ].includes(String(message.api)))
35362
36046
  responsesComponents.add(component(block.id));
35363
- validToolUseIds?.add(component(block.id));
35364
- } else {
35365
- if (block.id.includes("|"))
35366
- opaqueIds.add(block.id);
35367
- validToolUseIds?.add(block.id);
35368
- }
36047
+ else if (block.id.includes("|"))
36048
+ opaqueIds.add(block.id);
35369
36049
  }
35370
36050
  }
35371
36051
  const pairingId = (id) => !opaqueIds.has(id) && responsesComponents.has(component(id)) ? component(id) : id;
35372
36052
  const lastResult = new Map;
35373
36053
  messages.forEach((value, index) => {
35374
- const message = object7(value);
36054
+ const message = object8(value);
35375
36055
  if (message?.role === "toolResult" && typeof message.toolCallId === "string")
35376
36056
  lastResult.set(pairingId(message.toolCallId), index);
35377
36057
  });
@@ -35402,35 +36082,13 @@ function projectMissingToolResults(messages, api) {
35402
36082
  };
35403
36083
  for (let index = 0;index < messages.length; index++) {
35404
36084
  const value = messages[index];
35405
- const message = object7(value);
36085
+ const message = object8(value);
35406
36086
  if ((message?.role === "bashExecution" || message?.role === "pythonExecution") && message.excludeFromContext === true)
35407
36087
  continue;
35408
36088
  if (message?.role !== "toolResult")
35409
36089
  flush(message?.timestamp);
35410
36090
  else if (typeof message.toolCallId === "string" && pending.some((call) => pairingId(call.id) === pairingId(String(message.toolCallId))))
35411
36091
  resolved.add(pairingId(message.toolCallId));
35412
- else if (validToolUseIds && message?.role === "toolResult" && typeof message.toolCallId === "string" && typeof message.toolName === "string" && !validToolUseIds.has(pairingId(message.toolCallId)) && Array.isArray(message.content)) {
35413
- if (pending.some((call) => !resolved.has(pairingId(call.id))))
35414
- continue;
35415
- const parts = message.content.flatMap((value) => {
35416
- const part = object7(value);
35417
- return part?.type === "text" && typeof part.text === "string" && part.text.trim() ? [part.text] : [];
35418
- });
35419
- if (parts.length) {
35420
- const error = message.isError ? ' is-error="true"' : "";
35421
- const note = `<stale-tool-result tool="${message.toolName}" id="${message.toolCallId}"${error}>
35422
- ${parts.join(`
35423
- `)}
35424
- </stale-tool-result>`;
35425
- projected.push({
35426
- role: "user",
35427
- content: api === "ollama-chat" ? note : new TextDecoder().decode(new TextEncoder().encode(note)),
35428
- timestamp: message.timestamp,
35429
- [ORPHAN_NOTE]: true
35430
- });
35431
- }
35432
- continue;
35433
- }
35434
36092
  projected.push(value);
35435
36093
  if (message?.role !== "assistant" || !Array.isArray(message.content))
35436
36094
  continue;
@@ -35439,39 +36097,82 @@ ${parts.join(`
35439
36097
  timestamp = message.timestamp;
35440
36098
  if (aborted && typeof timestamp !== "number")
35441
36099
  continue;
35442
- for (const value of message.content) {
35443
- const block = object7(value);
35444
- if (block?.type === "toolCall" && typeof block.id === "string")
35445
- pending.push({
35446
- id: block.id,
35447
- name: typeof block.name === "string" ? block.name : ""
35448
- });
35449
- }
36100
+ pending.push(...windowCalls(message));
35450
36101
  }
35451
36102
  flush();
35452
36103
  return projected;
35453
36104
  }
36105
+ function projectPiToolResults(messages) {
36106
+ const projected = [];
36107
+ let pending = [];
36108
+ let answered = new Set;
36109
+ const held = [];
36110
+ const close = (timestamp) => {
36111
+ for (const call of pending)
36112
+ if (!answered.has(call.id))
36113
+ projected.push({
36114
+ role: "toolResult",
36115
+ toolCallId: call.id,
36116
+ toolName: call.name,
36117
+ content: [{ type: "text", text: "No result provided" }],
36118
+ isError: true,
36119
+ timestamp
36120
+ });
36121
+ pending = [];
36122
+ answered = new Set;
36123
+ projected.push(...held);
36124
+ held.length = 0;
36125
+ };
36126
+ for (const value of messages) {
36127
+ const message = object8(value);
36128
+ const role = message?.role;
36129
+ if (role === "assistant") {
36130
+ close(message?.timestamp);
36131
+ if (message?.stopReason === "error" || message?.stopReason === "aborted")
36132
+ continue;
36133
+ const calls = message ? windowCalls(message) : [];
36134
+ if (calls.length)
36135
+ pending = calls;
36136
+ } else if (role === "toolResult") {
36137
+ if (typeof message?.toolCallId === "string")
36138
+ answered.add(message.toolCallId);
36139
+ } else if (role === "system" && pending.length) {
36140
+ held.push(value);
36141
+ continue;
36142
+ } else if ([
36143
+ "user",
36144
+ "custom",
36145
+ "bashExecution",
36146
+ "branchSummary",
36147
+ "compactionSummary"
36148
+ ].includes(String(role)))
36149
+ close(message?.timestamp);
36150
+ projected.push(value);
36151
+ }
36152
+ close();
36153
+ return projected;
36154
+ }
35454
36155
  function preparePiDispatch(messages, model, omp) {
35455
36156
  let output = messages;
35456
36157
  const structure = buildPiPreparedStructure(messages, model, omp ? (index, source) => {
35457
- if (object7(source.providerPayload)?.type !== "openaiResponsesHistory")
36158
+ if (object8(source.providerPayload)?.type !== "openaiResponsesHistory")
35458
36159
  return;
35459
36160
  if (output === messages)
35460
36161
  output = messages.slice();
35461
36162
  const { providerPayload: _payload, ...copy } = source;
35462
36163
  output[index] = copy;
35463
- } : undefined);
36164
+ } : undefined, omp ? "omp" : "pi");
35464
36165
  return { messages: output, structure };
35465
36166
  }
35466
- function buildPiPreparedStructure(messages, model, prepareUser) {
36167
+ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
35467
36168
  if (!messages.length || messages.length > MAX_MESSAGES)
35468
36169
  return;
35469
36170
  for (let index = 0;index < messages.length; index++) {
35470
- const source = object7(messages[index]);
36171
+ const source = object8(messages[index]);
35471
36172
  if (source?.role === "user" || source?.role === "compactionSummary")
35472
36173
  prepareUser?.(index, source);
35473
36174
  }
35474
- const projectedMessages = projectMissingToolResults(model?.api ? piAgentHistory(messages, model.api) : messages, model?.api);
36175
+ const projectedMessages = projectMissingToolResults(model?.api && host === "omp" ? piAgentHistory(messages, model.api) : messages, model, host);
35475
36176
  if (projectedMessages.length > MAX_MESSAGES)
35476
36177
  return;
35477
36178
  const rows = [];
@@ -35483,7 +36184,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35483
36184
  let valid = true;
35484
36185
  for (let index = 0;index < projectedMessages.length; index++) {
35485
36186
  const message = projectedMessages[index];
35486
- const source = object7(message);
36187
+ const source = object8(message);
35487
36188
  if (rows.length === 0 && (source?.role === "system" || source?.role === "developer"))
35488
36189
  continue;
35489
36190
  if ((source?.role === "bashExecution" || source?.role === "pythonExecution") && source.excludeFromContext === true)
@@ -35507,7 +36208,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35507
36208
  "azure-openai-responses",
35508
36209
  "openai-codex-responses"
35509
36210
  ].includes(model?.api ?? "") && (source?.role === "user" || source?.role === "developer") && (typeof source.content === "string" ? !source.content.trim() : Array.isArray(source.content) && !source.content.some((value) => {
35510
- const block = object7(value);
36211
+ const block = object8(value);
35511
36212
  return block?.type === "image" || block?.type === "text" && typeof block.text === "string" && block.text.trim();
35512
36213
  })))
35513
36214
  continue;
@@ -35540,16 +36241,16 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35540
36241
  const positionedRows = [...byIndex];
35541
36242
  for (let position = positionedRows.length - 1;position >= 0; position--) {
35542
36243
  const [index, row] = positionedRows[position];
35543
- const source = object7(projectedMessages[index]);
36244
+ const source = object8(projectedMessages[index]);
35544
36245
  if (!source)
35545
36246
  return;
35546
36247
  const content = source.content;
35547
36248
  const parts = typeof content === "string" ? [{ type: "text", text: content }] : content;
35548
- const textOnly = Array.isArray(parts) && parts.every((part) => object7(part)?.type === "text" && typeof object7(part)?.text === "string");
36249
+ const textOnly = Array.isArray(parts) && parts.every((part) => object8(part)?.type === "text" && typeof object8(part)?.text === "string");
35549
36250
  if (piIsDeveloperHistory(source) && source.attribution !== "user") {
35550
36251
  const previous = rows[position - 1];
35551
36252
  const next = rows[position + 1];
35552
- if (model?.api === "ollama-chat" || model?.api === "anthropic-messages" && object7(model.compat)?.supportsMidConversationSystem === true && textOnly && (previous?.role === "user" || previous?.role === "toolResult") && (!next || next.role === "assistant"))
36253
+ if (model?.api === "ollama-chat" || model?.api === "anthropic-messages" && object8(model.compat)?.supportsMidConversationSystem === true && textOnly && (previous?.role === "user" || previous?.role === "toolResult") && (!next || next.role === "assistant"))
35553
36254
  row.role = "system";
35554
36255
  }
35555
36256
  if (row.role === "system") {
@@ -35622,7 +36323,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35622
36323
  ...responsesMessages ? { responsesMessages } : {},
35623
36324
  ...model?.api ? { api: model.api } : {},
35624
36325
  ...model?.api?.startsWith("google-") ? {
35625
- googleFunctionIds: object7(model.compat)?.supportsFunctionPartId === true
36326
+ googleFunctionIds: object8(model.compat)?.supportsFunctionPartId === true
35626
36327
  } : {}
35627
36328
  };
35628
36329
  }
@@ -35634,7 +36335,7 @@ function responsesLane(api) {
35634
36335
  ].includes(api ?? "");
35635
36336
  }
35636
36337
  function payloadStructure(payload, ollama = false, responsesItems = false, imageProjection = false) {
35637
- const body = object7(payload);
36338
+ const body = object8(payload);
35638
36339
  if (!body)
35639
36340
  return;
35640
36341
  const google = piGoogleConversation(payload);
@@ -35649,7 +36350,7 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35649
36350
  return;
35650
36351
  const rows = [];
35651
36352
  for (const value of messages) {
35652
- const message = object7(value);
36353
+ const message = object8(value);
35653
36354
  if (!message)
35654
36355
  return;
35655
36356
  if (rows.length === 0 && (message.role === "system" || message.role === "developer"))
@@ -35709,7 +36410,7 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35709
36410
  continue;
35710
36411
  }
35711
36412
  if (message.role === "user" && Array.isArray(message.content)) {
35712
- const results = message.content.filter((block) => object7(block)?.type === "tool_result" || bedrock && object7(block)?.toolResult);
36413
+ const results = message.content.filter((block) => object8(block)?.type === "tool_result" || bedrock && object8(block)?.toolResult);
35713
36414
  if (results.length) {
35714
36415
  for (const block of results) {
35715
36416
  const id = bedrock ? block.toolResult?.toolUseId : block.tool_use_id;
@@ -35756,11 +36457,11 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35756
36457
  }
35757
36458
  if (Array.isArray(message.tool_calls)) {
35758
36459
  for (const call of message.tool_calls) {
35759
- const source = object7(call);
36460
+ const source = object8(call);
35760
36461
  if (!source)
35761
36462
  return;
35762
36463
  if (source.id === undefined && ollama) {
35763
- const fn = object7(source.function);
36464
+ const fn = object8(source.function);
35764
36465
  if (typeof fn?.name !== "string")
35765
36466
  return;
35766
36467
  row.calls.push("");
@@ -35796,7 +36497,7 @@ function googleStructure(contents, imageProjection = false) {
35796
36497
  return;
35797
36498
  const rows = [];
35798
36499
  for (const value of contents) {
35799
- const message = object7(value);
36500
+ const message = object8(value);
35800
36501
  if (!message || !Array.isArray(message.parts))
35801
36502
  return;
35802
36503
  if (message.role !== "user" && message.role !== "model")
@@ -35811,11 +36512,11 @@ function googleStructure(contents, imageProjection = false) {
35811
36512
  };
35812
36513
  const results = [];
35813
36514
  for (const value of message.parts) {
35814
- const part = object7(value);
36515
+ const part = object8(value);
35815
36516
  if (!part)
35816
36517
  return;
35817
36518
  if (part.functionCall) {
35818
- const call = object7(part.functionCall);
36519
+ const call = object8(part.functionCall);
35819
36520
  if (row.role !== "assistant" || typeof call?.name !== "string" || call.id !== undefined && typeof call.id !== "string")
35820
36521
  return;
35821
36522
  row.calls.push(call.id ?? "");
@@ -35823,7 +36524,7 @@ function googleStructure(contents, imageProjection = false) {
35823
36524
  row.callNames.push(call.name);
35824
36525
  }
35825
36526
  if (part.functionResponse) {
35826
- const result = object7(part.functionResponse);
36527
+ const result = object8(part.functionResponse);
35827
36528
  if (row.role !== "user" || typeof result?.name !== "string" || result.id !== undefined && typeof result.id !== "string")
35828
36529
  return;
35829
36530
  results.push({
@@ -35857,11 +36558,11 @@ function matchesUserText(content, text, api, responses, googleOrBedrock) {
35857
36558
  if (responses || googleOrBedrock) {
35858
36559
  if (!Array.isArray(content) || content.length !== 1)
35859
36560
  return false;
35860
- const block = object7(content[0]);
36561
+ const block = object8(content[0]);
35861
36562
  return !!block && block.text === text && (responses ? block.type === "input_text" : Object.keys(block).length === 1);
35862
36563
  }
35863
36564
  if ((api === "anthropic-messages" || api === "factory-droid-agent") && Array.isArray(content)) {
35864
- const block = content.length === 1 ? object7(content[0]) : undefined;
36565
+ const block = content.length === 1 ? object8(content[0]) : undefined;
35865
36566
  return block?.type === "text" && block.text === text;
35866
36567
  }
35867
36568
  return content === text;
@@ -35929,7 +36630,7 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
35929
36630
  return "comparison=image count";
35930
36631
  const imageProjection = trimmed > 0;
35931
36632
  stage = "wire rows";
35932
- const body = object7(payload);
36633
+ const body = object8(payload);
35933
36634
  const ollama = prepared?.api === "ollama-chat" && !!body && Array.isArray(body.messages) && body.input === undefined && body.system === undefined && body.inferenceConfig === undefined;
35934
36635
  const responses = body?.messages === undefined && Array.isArray(body?.input);
35935
36636
  rows = payloadStructure(payload, ollama, responses && !!prepared?.responsesMessages, imageProjection);
@@ -35954,7 +36655,7 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
35954
36655
  if (expected.systemText !== undefined) {
35955
36656
  const texts = expected.systemText;
35956
36657
  const content = actual.wireContent;
35957
- const actualTexts = typeof content === "string" ? [content] : Array.isArray(content) && content.every((part) => object7(part)?.type === "text" && typeof object7(part)?.text === "string") ? content.map((part) => part.text) : undefined;
36658
+ const actualTexts = typeof content === "string" ? [content] : Array.isArray(content) && content.every((part) => object8(part)?.type === "text" && typeof object8(part)?.text === "string") ? content.map((part) => part.text) : undefined;
35958
36659
  if (!actualTexts || (typeof content === "string" ? content !== texts.join(`
35959
36660
  `) : JSON.stringify(actualTexts) !== JSON.stringify(texts)))
35960
36661
  return structureDetail(i, expectedRows, rows, "content");
@@ -41294,13 +41995,12 @@ function buildPiTextIdentityPlan(db, sessionId, tagger, transcript, reuseCandida
41294
41995
  }
41295
41996
  var piBranchProjectionBySession = new Map;
41296
41997
  var piBranchLookupByProjection = new WeakMap;
41297
- function logTransformElapsed(sessionId, stage, elapsedMs, extra) {
41298
- const suffix = extra ? ` ${extra}` : "";
41998
+ function logTransformElapsed2(sessionId, stage, elapsedMs, extra) {
41299
41999
  recordPiTransformTiming({ sessionId, stage, elapsedMs, extra });
41300
- sessionLog2(sessionId, `transform stage: stage=${stage} elapsed=${elapsedMs.toFixed(1)}ms${suffix}`);
42000
+ logTransformElapsed(sessionId, stage, elapsedMs, extra);
41301
42001
  }
41302
42002
  function logTransformTiming(sessionId, stage, start, extra) {
41303
- logTransformElapsed(sessionId, stage, performance.now() - start, extra);
42003
+ logTransformElapsed2(sessionId, stage, performance.now() - start, extra);
41304
42004
  }
41305
42005
  function piVariantChangeBustsProviderCache(providerID, modelID) {
41306
42006
  return variantChangeBustsProviderCache(providerID, modelID);
@@ -41939,7 +42639,7 @@ function stripMcOwnedPiCompactionSummary(messages, entryIds, branchEntries) {
41939
42639
  break;
41940
42640
  }
41941
42641
  }
41942
- if (compaction?.fromHook !== true)
42642
+ if (compaction?.fromHook !== true && compaction?.fromExtension !== true)
41943
42643
  return false;
41944
42644
  const details = compaction.details;
41945
42645
  if (details?.source !== "magic-context")
@@ -42727,7 +43427,7 @@ function loadPiHistorianStateSnapshot(db, sessionId) {
42727
43427
  }
42728
43428
  function registerPiContextHandler(pi, baseOptions) {
42729
43429
  const tagger = createTagger();
42730
- const lkgCoordinator = createPiLkgCoordinator(baseOptions.db, undefined, ({ sessionId, elapsedMs, reusedPrefix }) => logTransformElapsed(sessionId, "lkgCapture", elapsedMs, `reusedPrefix=${reusedPrefix}`));
43430
+ const lkgCoordinator = createPiLkgCoordinator(baseOptions.db, undefined, ({ sessionId, elapsedMs, reusedPrefix }) => logTransformElapsed2(sessionId, "lkgCapture", elapsedMs, `reusedPrefix=${reusedPrefix}`));
42731
43431
  const schedulerCache = new WeakMap;
42732
43432
  const DEFAULT_SCHEDULER_CONFIG = {
42733
43433
  executeThresholdPercentage: 65
@@ -42764,7 +43464,7 @@ function registerPiContextHandler(pi, baseOptions) {
42764
43464
  variantChangeLogObserverForTests?.(message);
42765
43465
  sessionLog2(sessionId, message);
42766
43466
  });
42767
- const contextHandler = async (event, ctx, budget) => {
43467
+ const runHandler = async (event, ctx, budget) => {
42768
43468
  budget.assertOutcome();
42769
43469
  const passSessionId = ctx.sessionManager ? resolveSessionId2(ctx) : undefined;
42770
43470
  const generation = Symbol();
@@ -43362,6 +44062,14 @@ function registerPiContextHandler(pi, baseOptions) {
43362
44062
  schedulerDeferReason,
43363
44063
  forceMaterialization: forceMaterialization || isEmergency,
43364
44064
  forceMaterializationPercentage,
44065
+ signedThinkingHold: resolvePiSignedThinkingHold({
44066
+ sessionId,
44067
+ db: options.db,
44068
+ messages: event.messages,
44069
+ prefixBound: isPrefixBoundThinkingModel(ctx.model?.provider, ctx.model?.id),
44070
+ usagePercentage,
44071
+ executeThresholdPercentage: effectiveExecuteThresholdPercentage
44072
+ }),
43365
44073
  contextUsage: {
43366
44074
  percentage: usagePercentage,
43367
44075
  inputTokens: usageInputTokens
@@ -43478,7 +44186,8 @@ function registerPiContextHandler(pi, baseOptions) {
43478
44186
  minimumPercentage: usagePercentage,
43479
44187
  liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
43480
44188
  historianStateSnapshot: historianStateForPass,
43481
- publishedHistoryRide: isCacheBusting
44189
+ publishedHistoryRide: isCacheBusting,
44190
+ signedThinkingHeld: result.strictThinkingKept
43482
44191
  });
43483
44192
  } catch (error) {
43484
44193
  budget.assertOutcome();
@@ -43871,6 +44580,7 @@ function registerPiContextHandler(pi, baseOptions) {
43871
44580
  },
43872
44581
  minimumPercentage: 95,
43873
44582
  publishedHistoryRide: false,
44583
+ signedThinkingHeld: result.strictThinkingKept,
43874
44584
  historianStateSnapshot: loadPiHistorianStateSnapshot(options.db, sessionId)
43875
44585
  });
43876
44586
  const pending = inFlightHistorian.get(sessionId);
@@ -44148,6 +44858,7 @@ function registerPiContextHandler(pi, baseOptions) {
44148
44858
  return;
44149
44859
  }
44150
44860
  };
44861
+ const contextHandler = (...args) => withTransformTimingSummary(async () => await runHandler(...args) ?? undefined);
44151
44862
  registerPiGuardedContext(pi, contextHandler, {
44152
44863
  compactionOff: (ctx) => (baseOptions.resolveForProject?.(ctx.cwd) ?? baseOptions).compactionOff === true,
44153
44864
  onRefusal: (ctx, budget, message, isCurrent) => {
@@ -44400,10 +45111,7 @@ function spawnPiHistorianRun(args) {
44400
45111
  historian.onStatusChange?.(ctx, sessionId);
44401
45112
  }
44402
45113
  function resolvePiAppendCompaction(ctx) {
44403
- const sm = ctx.sessionManager;
44404
- if (typeof sm?.appendCompaction !== "function")
44405
- return;
44406
- return sm.appendCompaction.bind(sm);
45114
+ return adaptPiAppendCompaction(ctx.sessionManager);
44407
45115
  }
44408
45116
  function guardedPiAppendCompaction(ctx, assertCurrentPass) {
44409
45117
  const append = resolvePiAppendCompaction(ctx);
@@ -44634,8 +45342,14 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
44634
45342
  const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.keepReasoningTokens, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit, () => readPiHistorianTail(db, sessionId, provider), args.taggerFloor, { canClearReasoning: true }, {
44635
45343
  hardFold: false,
44636
45344
  force: usage.percentage >= historianForceMaterializationPercentage && (usage.percentage >= 95 || getEmergencyInputSample(db, sessionId) === 0),
44637
- explicitFlush: hasPendingMaterialization(sessionId),
44638
- publishedHistory: args.publishedHistoryRide
45345
+ explicitFlush: hasPendingMaterializationOrigin(pendingMaterializationSessions, sessionId, "user_flush"),
45346
+ publishedHistory: args.publishedHistoryRide,
45347
+ permission: {
45348
+ signedThinkingHold: args.signedThinkingHeld === true,
45349
+ firstRender: false,
45350
+ idleExpiry: false,
45351
+ emergency: usage.percentage >= historianForceMaterializationPercentage
45352
+ }
44639
45353
  }, args.eligiblePendingDropTagIds);
44640
45354
  if (!trigger.shouldFire) {
44641
45355
  sessionLog2(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
@@ -44736,7 +45450,7 @@ function captureReasoningMutationRollback(messages) {
44736
45450
  async function runCompactionOffPipeline(args) {
44737
45451
  let injectionResult = null;
44738
45452
  if (args.injection) {
44739
- injectionResult = injectM0M1Pi({
45453
+ const state = {
44740
45454
  sessionId: args.sessionId,
44741
45455
  projectIdentity: args.projectIdentity,
44742
45456
  projectDirectory: args.projectDirectory,
@@ -44747,7 +45461,10 @@ async function runCompactionOffPipeline(args) {
44747
45461
  historyBudgetPolicyIdentity: args.injection.historyBudgetPolicyIdentity,
44748
45462
  muralEnabled: args.injection.muralEnabled === true,
44749
45463
  compactionOff: true
44750
- }, args.db, args.messages, args.entryIds, false, args.injectionPassSnapshot);
45464
+ };
45465
+ if (args.reasoningClearing?.prefixBound === true && hasActiveAnthropicThinkingTurn(args.messages, args.resolvedProviderID, args.resolvedModelID))
45466
+ state.preparedPrefix = prepareCachedM0M1PiReplay(state, args.db, args.injectionPassSnapshot?.cachedRow);
45467
+ injectionResult = injectM0M1Pi(state, args.db, args.messages, args.entryIds, false, args.injectionPassSnapshot);
44751
45468
  }
44752
45469
  return {
44753
45470
  messages: args.messages,
@@ -44783,6 +45500,27 @@ async function runCompactionOffPipeline(args) {
44783
45500
  lkgEntryIdByRef: new Map
44784
45501
  };
44785
45502
  }
45503
+ var signedThinkingHoldLogKeys = new Map;
45504
+ function resolvePiSignedThinkingHold(args) {
45505
+ if (!args.prefixBound)
45506
+ return false;
45507
+ let proseRatio;
45508
+ const decision = decideSignedThinkingHold({
45509
+ messages: args.messages,
45510
+ usagePercentage: args.usagePercentage,
45511
+ executeThresholdPercentage: args.executeThresholdPercentage,
45512
+ estimateTextTokens: (text) => {
45513
+ proseRatio ??= sessionDecisionCalibration(args.db, args.sessionId).proseRatio;
45514
+ return estimateTokens(text) * proseRatio;
45515
+ }
45516
+ });
45517
+ const key = `${decision.reason}:${decision.heavyStepsBack ?? "none"}`;
45518
+ if (signedThinkingHoldLogKeys.get(args.sessionId) !== key) {
45519
+ signedThinkingHoldLogKeys.set(args.sessionId, key);
45520
+ sessionLog2(args.sessionId, `signed thinking hold: held=${decision.held} reason=${decision.reason} heavyStepsBack=${decision.heavyStepsBack ?? "none"} heavyStepTokens=${decision.heavyStepTokens} usage=${args.usagePercentage.toFixed(1)}% cap=${decision.capPercentage}%`);
45521
+ }
45522
+ return decision.held;
45523
+ }
44786
45524
  async function runPipeline(args) {
44787
45525
  args.assertCurrentPass?.();
44788
45526
  if (args.compactionOff)
@@ -44798,7 +45536,8 @@ async function runPipeline(args) {
44798
45536
  signalPiPendingMaterialization(args.sessionId, "thinking_hold");
44799
45537
  let restoreOriginals;
44800
45538
  let activeThinkingTurn = hasActiveAnthropicThinkingTurn(args.messages, args.resolvedProviderID, args.resolvedModelID);
44801
- let protectedSignedPrefix = activeThinkingTurn && args.reasoningClearing?.prefixBound === true;
45539
+ const signedTurnOnPrefixBoundModel = args.reasoningClearing?.prefixBound === true && (activeThinkingTurn || activeAnthropicTurnStart(args.messages, true) === undefined && args.messages.some((message) => message.role === "assistant" && Array.isArray(message.content) && message.content.some((part) => part?.type === "thinking" || part?.type === "redacted_thinking")));
45540
+ let protectedSignedPrefix = signedTurnOnPrefixBoundModel && args.signedThinkingHold === true;
44802
45541
  let rewritingSignedPrefix = false;
44803
45542
  let isCacheBustingPass = args.recoveryRebuildReason === "lkg_recovery_input_rebuild" || (!!args.recoveryRebuildReason || args.forceSignedRebuildForFit === true) && hasUnfrozenPiThinking({
44804
45543
  messages: args.messages,
@@ -44829,8 +45568,12 @@ async function runPipeline(args) {
44829
45568
  activeThinkingTurn = false;
44830
45569
  protectedSignedPrefix = false;
44831
45570
  };
44832
- if (args.recoveryRebuildReason || args.forceSignedRebuildForFit && protectedSignedPrefix)
45571
+ if (args.recoveryRebuildReason || args.forceSignedRebuildForFit && signedTurnOnPrefixBoundModel)
44833
45572
  stripForPrefixRewrite(isCacheBustingPass);
45573
+ const stripUnheldSignedTurnOnBust = () => {
45574
+ if (isCacheBustingPass && signedTurnOnPrefixBoundModel && !protectedSignedPrefix && !rewritingSignedPrefix)
45575
+ stripForPrefixRewrite();
45576
+ };
44834
45577
  const realStableId = (msg, index) => resolvePiRealStableId(msg, index, args.entryIds, args.entryIdByRef ?? undefined);
44835
45578
  const passFallbackIds = settlePiFallbackOccurrences(args.db, args.sessionId, piContentFallbackIds(args.messages, realStableId));
44836
45579
  const stableIdResolver = (msg, index) => realStableId(msg, index) ?? passFallbackIds[index] ?? resolvePiStableId(msg, index);
@@ -45073,9 +45816,16 @@ async function runPipeline(args) {
45073
45816
  explicitFlush: !protectedSignedPrefix && (args.userFlushOrigin === true || hasPendingMaterializationOrigin(pendingMaterializationSessions, args.sessionId, "user_flush")),
45074
45817
  publishedHistory: !prefixPreflightContended && publishedM1RefreshedThisPass
45075
45818
  };
45076
- let prefixMutationAllowed = !protectedSignedPrefix || firstRenderBust || heldIdleExpiryRebuild || emergencyDropEligible;
45077
- isCacheBustingPass = prefixMutationAllowed && hasReclaimRide(rideSignals);
45819
+ const ridePermissionGate = {
45820
+ signedThinkingHold: protectedSignedPrefix,
45821
+ firstRender: firstRenderBust,
45822
+ idleExpiry: heldIdleExpiryRebuild,
45823
+ emergency: emergencyDropEligible
45824
+ };
45825
+ let prefixMutationAllowed = prefixMutationPermitted(ridePermissionGate);
45826
+ isCacheBustingPass = reclaimRidePermitted(rideSignals, ridePermissionGate);
45078
45827
  let publishedWorkDrainAllowed = isCacheBustingPass;
45828
+ stripUnheldSignedTurnOnBust();
45079
45829
  const usesTokenProtection = args.protectedTokenTierOverrides !== undefined || args.protectedTokens !== undefined;
45080
45830
  const resolveProtectionFloor = () => resolveEpochFloorForPass(args.db, args.sessionId, {
45081
45831
  configuredOverride: args.protectedTokens,
@@ -45150,6 +45900,7 @@ async function runPipeline(args) {
45150
45900
  deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
45151
45901
  isCacheBustingPass = prefixMutationAllowed;
45152
45902
  publishedWorkDrainAllowed = isCacheBustingPass;
45903
+ stripUnheldSignedTurnOnBust();
45153
45904
  shouldRunHeuristics = args.heuristics !== undefined;
45154
45905
  if (piM0State && prefixMutationAllowed) {
45155
45906
  try {
@@ -46358,6 +47109,7 @@ function clearContextHandlerSession(sessionId) {
46358
47109
  clearPiChannel1State(sessionId);
46359
47110
  lastHeuristicsTurnIdBySession.delete(sessionId);
46360
47111
  routinePressureAppliedBySession.delete(sessionId);
47112
+ signedThinkingHoldLogKeys.delete(sessionId);
46361
47113
  lastSeenProjectIdentityBySession.delete(sessionId);
46362
47114
  persistedProjectIdentityBySession.delete(sessionId);
46363
47115
  sessionProjectBindingFailureLogAtBySession.delete(sessionId);
@@ -46452,10 +47204,12 @@ function createPiHistorianClient(args) {
46452
47204
  }
46453
47205
  const promptText = extractPromptText(body.parts);
46454
47206
  const modelOverride = readBodyModel(body);
47207
+ const cacheTail = input && typeof input === "object" && "cacheTail" in input ? input.cacheTail : undefined;
46455
47208
  const result = await args.runner.run({
46456
47209
  agent: "magic-context-historian",
46457
47210
  systemPrompt: args.systemPrompt,
46458
47211
  userMessage: promptText,
47212
+ ...cacheTail === "write" || cacheTail === "skip" ? { cacheTail } : {},
46459
47213
  model: modelOverride?.model ?? args.model,
46460
47214
  fallbackModels: modelOverride ? undefined : args.fallbackModels,
46461
47215
  timeoutMs: args.timeoutMs,
@@ -49804,9 +50558,9 @@ var PI_STARTUP_MAINTENANCE_SCHEDULED = Symbol.for("magic-context.pi.startup-main
49804
50558
  function getPiChildInitContext() {
49805
50559
  const globals = globalThis;
49806
50560
  const existing = globals[PI_CHILD_INIT_CONTEXT];
49807
- if (existing instanceof AsyncLocalStorage2)
50561
+ if (existing instanceof AsyncLocalStorage3)
49808
50562
  return existing;
49809
- const context = new AsyncLocalStorage2;
50563
+ const context = new AsyncLocalStorage3;
49810
50564
  globals[PI_CHILD_INIT_CONTEXT] = context;
49811
50565
  return context;
49812
50566
  }