@cortexkit/pi-magic-context 0.49.19 → 0.49.21

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 (60) hide show
  1. package/dist/auto-search-worker.js +48 -9
  2. package/dist/chunk-embedding-write-worker.js +29 -22
  3. package/dist/{compaction-marker-candidates-wjzqbspm.js → compaction-marker-candidates-p1kqkqhq.js} +3 -3
  4. package/dist/compaction-marker-candidates-worker.js +2 -2
  5. package/dist/compartment-chunk-embedding-y01m95c2.js +64 -0
  6. package/dist/embedding-backfill-2vh6m3bg.js +24 -0
  7. package/dist/embedding-worker-process.js +2 -2
  8. package/dist/embedding-worker.js +6 -6
  9. package/dist/historian-calibration-extension.js +1 -1
  10. package/dist/{index-e1rza8gp.js → index-29nw7n1r.js} +1 -1
  11. package/dist/{index-rrwv9y2k.js → index-2qtx0q6h.js} +214 -5
  12. package/dist/{index-msqrs4nf.js → index-3c3ztwgc.js} +5 -5
  13. package/dist/index-54wmg4rj.js +82 -0
  14. package/dist/{index-yygsh681.js → index-579m1751.js} +3 -3
  15. package/dist/{index-rc1dez8m.js → index-5j6vwg4z.js} +154 -13
  16. package/dist/{index-qpq6w67c.js → index-6wdwv3a6.js} +2 -2
  17. package/dist/{index-vktahpdj.js → index-at6py2k3.js} +9 -3
  18. package/dist/{index-bxmf4dhr.js → index-ccanzg8p.js} +2367 -1243
  19. package/dist/{index-sqt2haap.js → index-dbgg6hsf.js} +28 -14
  20. package/dist/{index-7bqrfyny.js → index-fgs78jyd.js} +12 -15
  21. package/dist/{index-58mj0dzc.js → index-ftvm2acc.js} +181 -46
  22. package/dist/{index-wveb51es.js → index-gqjxy2p7.js} +74 -9
  23. package/dist/{index-d8gc0112.js → index-gwxaz0z5.js} +4 -6
  24. package/dist/{index-d4dt19md.js → index-hqw0rt9k.js} +1 -1
  25. package/dist/{index-g7p75667.js → index-hxp6q5f8.js} +2 -2
  26. package/dist/{index-svgkv4g2.js → index-j3pz3a1b.js} +2 -2
  27. package/dist/{index-f18ec69t.js → index-jn44h81p.js} +1 -1
  28. package/dist/{index-1kcfwk9c.js → index-my0dn413.js} +1 -1
  29. package/dist/{index-apgwdby5.js → index-n4wyxcgr.js} +1 -1
  30. package/dist/{index-rhprywn6.js → index-n8e5e9fp.js} +28 -7
  31. package/dist/{index-z2rkv0mb.js → index-pe5gz5c4.js} +5 -5
  32. package/dist/{index-dtp1efvf.js → index-st4gwt64.js} +2 -2
  33. package/dist/{index-xnch62s6.js → index-vx6f7wff.js} +314 -127
  34. package/dist/{index-jrap43gc.js → index-w1avzkdt.js} +1 -1
  35. package/dist/{index-vmcgew7x.js → index-w1twp2kp.js} +78 -58
  36. package/dist/{index-ek9zvs4f.js → index-w6r3ggnp.js} +57 -27
  37. package/dist/{index-ym6nh2gk.js → index-wgmhk91m.js} +113 -20
  38. package/dist/{index-2mmy81qt.js → index-wqpjhx1p.js} +501 -20
  39. package/dist/index.js +1178 -417
  40. package/dist/{logger-dygt96rn.js → logger-shetp43v.js} +1 -1
  41. package/dist/{message-fts-rowid-map-cvpy2dmb.js → message-fts-rowid-map-59y476bk.js} +6 -5
  42. package/dist/{message-index-rc2x41k4.js → message-index-3snxf11x.js} +15 -14
  43. package/dist/{message-index-bounded-66saeq5j.js → message-index-bounded-4ngt600v.js} +15 -14
  44. package/dist/{message-time-backfill-ssshbdy8.js → message-time-backfill-e3r8ddh1.js} +3 -3
  45. package/dist/migration-worker.js +12 -11
  46. package/dist/{project-embedding-registry-vf1ncptn.js → project-embedding-registry-hfyzs654.js} +14 -13
  47. package/dist/raw-ordinal-warmup-worker.js +136 -101
  48. package/dist/{read-session-chunk-h5bzj91r.js → read-session-chunk-5dmc77q2.js} +10 -9
  49. package/dist/{read-session-raw-9s3xn7fc.js → read-session-raw-yxv2fv34.js} +4 -3
  50. package/dist/{safe-notification-target-2rkvkmw8.js → safe-notification-target-zcpchea6.js} +2 -2
  51. package/dist/search-archive-3daj5ttc.js +21 -0
  52. package/dist/{search-wh7b9zht.js → search-jhfh3tsj.js} +23 -22
  53. package/dist/{sqlite-fsp0sf3r.js → sqlite-v89bj0yy.js} +7 -1
  54. package/dist/{storage-memory-yxxc5v4n.js → storage-memory-0ndn65fm.js} +2 -2
  55. package/dist/{storage-tags-1kets0q8.js → storage-tags-r48vxthe.js} +7 -5
  56. package/dist/subagent-entry.js +28 -26
  57. package/dist/tag-snapshot-worker-pi.js +22 -14
  58. package/package.json +5 -2
  59. package/dist/embedding-backfill-vwag34t0.js +0 -23
  60. package/dist/search-archive-4817pqev.js +0 -20
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  log2,
19
19
  sessionLog2,
20
20
  flushLogger2
21
- } from "./index-7bqrfyny.js";
21
+ } from "./index-fgs78jyd.js";
22
22
  import {
23
23
  COMPACTION_ENABLED_PATH,
24
24
  isDreamerRunnable,
@@ -249,7 +249,7 @@ import {
249
249
  registerTodoStateLifecycle,
250
250
  syncCtxMemoryToolEnabled,
251
251
  registerMagicContextTools
252
- } from "./index-ek9zvs4f.js";
252
+ } from "./index-w6r3ggnp.js";
253
253
  import"./index-4knyh1kt.js";
254
254
  import {
255
255
  canonicalModelIdentity,
@@ -267,7 +267,7 @@ import {
267
267
  DEFAULT_HISTORIAN_TIMEOUT_MS,
268
268
  DREAM_TASK_PROMOTION_DEFAULTS,
269
269
  LIVE_RELOAD_CONFIG_PATHS
270
- } from "./index-bxmf4dhr.js";
270
+ } from "./index-ccanzg8p.js";
271
271
  import {
272
272
  FAIL_CLOSED_DOCTOR_COMMAND,
273
273
  formatFailClosedBlockingMessage,
@@ -290,7 +290,7 @@ import {
290
290
  openCurrentDatabase,
291
291
  openDatabaseAsync,
292
292
  closeDatabase
293
- } from "./index-sqt2haap.js";
293
+ } from "./index-dbgg6hsf.js";
294
294
  import {
295
295
  pruneMissingProjectIdentities,
296
296
  setHomeProjectPermission,
@@ -302,7 +302,7 @@ import {
302
302
  resolveProjectIdentityForSession,
303
303
  beginBootQuietPeriod,
304
304
  scheduleAfterBootQuiet
305
- } from "./index-g7p75667.js";
305
+ } from "./index-hxp6q5f8.js";
306
306
  import {
307
307
  detectThinkingBindingMismatch,
308
308
  detectLatestTurnThinkingMismatch,
@@ -396,6 +396,7 @@ import {
396
396
  addProcessedImageStrippedIds,
397
397
  getPendingCompactionMarkerState,
398
398
  getCompactionMarkerHealth,
399
+ loadPostprocessReplaySnapshot,
399
400
  clearPendingCompactionMarkerStateIf,
400
401
  getPendingPiCompactionMarkerState,
401
402
  setPendingPiCompactionMarkerState,
@@ -462,7 +463,7 @@ import {
462
463
  getRawSessionTagKeysThrough2,
463
464
  getLegacyProtectedTailStartOrdinal2,
464
465
  readSessionChunk2
465
- } from "./index-wveb51es.js";
466
+ } from "./index-gqjxy2p7.js";
466
467
  import {
467
468
  UNKNOWN_FIT_RATIO,
468
469
  hasMeasuredDecisionCalibration,
@@ -549,7 +550,7 @@ import {
549
550
  getToolTagNumberByOwner2,
550
551
  getNullOwnerToolTag2,
551
552
  adoptNullOwnerToolTag2
552
- } from "./index-rhprywn6.js";
553
+ } from "./index-n8e5e9fp.js";
553
554
  import {
554
555
  textMentionsRecentCommit,
555
556
  hasMeaningfulUserText2,
@@ -561,11 +562,12 @@ import {
561
562
  estimateTokens,
562
563
  estimateFixedPromptTokens,
563
564
  normalizeText
564
- } from "./index-1kcfwk9c.js";
565
+ } from "./index-my0dn413.js";
565
566
  import {
566
567
  inRootAsyncContext2,
567
568
  Database2,
568
569
  getSqliteDatabasePath2,
570
+ withSqliteTurnDeadline2,
569
571
  withSqliteBackgroundWriter2,
570
572
  withSqliteTransformPass2,
571
573
  withoutSqliteTransformPass2,
@@ -574,7 +576,7 @@ import {
574
576
  isTransientSqliteError2,
575
577
  withAsyncPrivilegedWriter2,
576
578
  indexCoordinationInput2
577
- } from "./index-rrwv9y2k.js";
579
+ } from "./index-2qtx0q6h.js";
578
580
  import {
579
581
  stableStringify,
580
582
  closeQuietly,
@@ -582,14 +584,15 @@ import {
582
584
  observeTemporalDecisions,
583
585
  freezeTemporalDecisions,
584
586
  tagIdentityRevisionKey
585
- } from "./index-jrap43gc.js";
587
+ } from "./index-w1avzkdt.js";
586
588
  import {
587
589
  piHarnessKindFromExecutable
588
- } from "./index-apgwdby5.js";
590
+ } from "./index-n4wyxcgr.js";
589
591
  import {
590
592
  BoundedSessionMap,
591
593
  LkgRecoveryFenceError,
592
594
  clearLkgFenceProcessState,
595
+ takeLkgRecoveryLockSweepPage,
593
596
  lkgFenceRequiresRebuild,
594
597
  lkgRecoveryFenceUnclean,
595
598
  ownsLkgDirtyFence,
@@ -611,7 +614,7 @@ import {
611
614
  indexSingleMessage2,
612
615
  indexMessagesAfterOrdinal2,
613
616
  sweepOrphanedOpenCodeMessageIndexesCooperatively2
614
- } from "./index-ym6nh2gk.js";
617
+ } from "./index-wgmhk91m.js";
615
618
  import {
616
619
  resolveOpenCodeDbPath,
617
620
  assertOpenCodeStoreGeneration,
@@ -621,24 +624,27 @@ import {
621
624
  claimOpenCodeDbDiagnosticOnce
622
625
  } from "./index-8976mezv.js";
623
626
  import"./index-399p688g.js";
627
+ import {
628
+ createWorkerShutdown
629
+ } from "./index-54wmg4rj.js";
624
630
  import {
625
631
  runSessionWarmupWorker,
626
632
  RAW_SUMMARY_TEXT_MAX_CHARS2
627
- } from "./index-vktahpdj.js";
633
+ } from "./index-at6py2k3.js";
628
634
  import {
629
635
  formatSynapseLaneDescriptor
630
- } from "./index-d8gc0112.js";
631
- import"./index-yygsh681.js";
636
+ } from "./index-gwxaz0z5.js";
637
+ import"./index-579m1751.js";
632
638
  import {
633
- buildCanonicalChunkTextFromFts,
634
- buildCompartmentSummaryFallbackText,
635
- canonicalizeInMemoryChunkTextForEmbedding,
636
- chunkCanonicalText,
637
- chunkEmbeddingWindowsAreCurrent,
638
- replaceCompartmentChunkEmbeddings,
639
- deleteChunkEmbedBackoffForSession,
640
- chunkWindowSourceKey
641
- } from "./index-xnch62s6.js";
639
+ buildCanonicalChunkTextFromFts2,
640
+ buildCompartmentSummaryFallbackText2,
641
+ canonicalizeInMemoryChunkTextForEmbedding2,
642
+ chunkCanonicalText2,
643
+ chunkEmbeddingWindowsAreCurrent2,
644
+ replaceCompartmentChunkEmbeddings2,
645
+ deleteChunkEmbedBackoffForSession2,
646
+ chunkWindowSourceKey2
647
+ } from "./index-vx6f7wff.js";
642
648
  import {
643
649
  recordSessionProjectIdentity,
644
650
  GIT_SWEEP_LEASE_RENEWAL_MS,
@@ -647,7 +653,7 @@ import {
647
653
  markGitSweepSuccessAndRelease,
648
654
  parkGitSweepNonIndexable,
649
655
  releaseGitSweepLease
650
- } from "./index-svgkv4g2.js";
656
+ } from "./index-j3pz3a1b.js";
651
657
  import {
652
658
  embedPauseBySession,
653
659
  embedRunStateBySession,
@@ -673,7 +679,7 @@ import {
673
679
  embedSessionCompartmentChunks2,
674
680
  getEmbeddingCoverageStatus2,
675
681
  getAutoEmbeddingSessionCoverage2
676
- } from "./index-vmcgew7x.js";
682
+ } from "./index-w1twp2kp.js";
677
683
  import {
678
684
  rememberV1HiddenRun
679
685
  } from "./index-6x556c2q.js";
@@ -688,7 +694,7 @@ import {
688
694
  expandWorkspaceIdentitySetWithAliases,
689
695
  sourceNameForMemory,
690
696
  computeWorkspaceEpochFingerprint
691
- } from "./index-msqrs4nf.js";
697
+ } from "./index-3c3ztwgc.js";
692
698
  import {
693
699
  configureContextDatabasePragmas2
694
700
  } from "./index-fapenpch.js";
@@ -738,7 +744,7 @@ import {
738
744
  normalizeVerificationFiles,
739
745
  indexCommitsForProject,
740
746
  embedUnembeddedCommits
741
- } from "./index-58mj0dzc.js";
747
+ } from "./index-ftvm2acc.js";
742
748
  import {
743
749
  setEmbeddingSessionBusy2,
744
750
  isEmbeddingHostBusy2
@@ -762,18 +768,20 @@ import {
762
768
  setMemoryClassification2,
763
769
  archiveMemory2,
764
770
  getMemoryCountsByStatus2
765
- } from "./index-e1rza8gp.js";
771
+ } from "./index-29nw7n1r.js";
766
772
  import {
767
773
  invalidateMemory2
768
774
  } from "./index-yhzhdp3m.js";
769
775
  import {
770
776
  pushNotification2
771
777
  } from "./index-q1yc6bs0.js";
772
- import"./index-2mmy81qt.js";
778
+ import {
779
+ getCachedLocalEmbeddingPooling
780
+ } from "./index-wqpjhx1p.js";
773
781
  import {
774
782
  cosineSimilarity
775
- } from "./index-z2rkv0mb.js";
776
- import"./index-qpq6w67c.js";
783
+ } from "./index-pe5gz5c4.js";
784
+ import"./index-6wdwv3a6.js";
777
785
  import {
778
786
  DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS,
779
787
  buildHiddenAgentRegistrations,
@@ -786,6 +794,10 @@ import {
786
794
  SUBAGENT_OUTPUT_CEILING_ENV2
787
795
  } from "./index-fa485mqs.js";
788
796
  import {
797
+ PI_CONTEXT_BUDGET,
798
+ PiContextDeadlineError,
799
+ PiContextSupersededError,
800
+ PiContextBudget,
789
801
  PiTagHydrationError,
790
802
  getPiTagSnapshotView,
791
803
  getPiActiveTagSnapshotView,
@@ -795,10 +807,10 @@ import {
795
807
  drainPiTagSnapshotSession,
796
808
  assertPiTagSnapshotReady,
797
809
  ensurePiTagSnapshotReady
798
- } from "./index-rc1dez8m.js";
799
- import"./index-f18ec69t.js";
810
+ } from "./index-5j6vwg4z.js";
811
+ import"./index-jn44h81p.js";
800
812
  import"./index-1cvyaw9a.js";
801
- import"./index-dtp1efvf.js";
813
+ import"./index-st4gwt64.js";
802
814
  import {
803
815
  __toESM
804
816
  } from "./index-22jkk6wg.js";
@@ -814,7 +826,7 @@ import {
814
826
  import {
815
827
  logSlowWriteTransaction,
816
828
  WriteTransactionSteps
817
- } from "./index-d4dt19md.js";
829
+ } from "./index-hqw0rt9k.js";
818
830
  import {
819
831
  setStoragePrivatePermissionEnforcement,
820
832
  ensureStorageDirectorySync,
@@ -1207,6 +1219,9 @@ function resolveHarnessBlock(container, harness) {
1207
1219
  const selected = harness === "omp" ? container?.omp ?? container?.pi : container?.[harness];
1208
1220
  return asRecord(selected);
1209
1221
  }
1222
+ function sourceHarness(container, harness) {
1223
+ return harness === "omp" && container?.omp == null ? "pi" : harness;
1224
+ }
1210
1225
  function normalizeModelEntry(entry, harness) {
1211
1226
  if (typeof entry === "string") {
1212
1227
  const model = readString(entry);
@@ -1253,13 +1268,19 @@ function resolveHistorianModel(config, harness) {
1253
1268
  const block = resolveHarnessBlock(historian, harness);
1254
1269
  if (!block)
1255
1270
  return { fallbacks: [] };
1271
+ const source = `historian.${sourceHarness(historian, harness)}`;
1272
+ const primary = resolvePrimaryEntry({
1273
+ entry: block.model,
1274
+ defaultQualifier: block[harness === "opencode" ? "variant" : "thinking_level"],
1275
+ harness
1276
+ });
1277
+ const fallbacks = resolveFallbackEntries(block.fallback_models, harness);
1256
1278
  return {
1257
- primary: resolvePrimaryEntry({
1258
- entry: block.model,
1259
- defaultQualifier: block[harness === "opencode" ? "variant" : "thinking_level"],
1260
- harness
1261
- }),
1262
- fallbacks: resolveFallbackEntries(block.fallback_models, harness)
1279
+ primary: primary ? { ...primary, sourceConfigKey: `${source}.model` } : undefined,
1280
+ fallbacks: fallbacks.map((entry) => ({
1281
+ ...entry,
1282
+ sourceConfigKey: `${source}.fallback_models`
1283
+ }))
1263
1284
  };
1264
1285
  }
1265
1286
  function resolveDreamerTaskModel(args) {
@@ -1278,15 +1299,25 @@ function resolveDreamerTaskModel(args) {
1278
1299
  const taskQualifier = taskBlock?.[args.harness === "opencode" ? "variant" : "thinking_level"];
1279
1300
  const harnessQualifier = harnessBlock[args.harness === "opencode" ? "variant" : "thinking_level"] ?? normalizeModelEntry(harnessBlock.model, args.harness)?.qualifier;
1280
1301
  const taskHasModel = taskBlock !== undefined && hasOwn(taskBlock, "model");
1302
+ const taskHasFallbacks = taskBlock !== undefined && hasOwn(taskBlock, "fallback_models");
1281
1303
  const primarySource = taskHasModel ? taskBlock?.model : harnessBlock.model;
1282
- const fallbackSource = taskBlock !== undefined && hasOwn(taskBlock, "fallback_models") ? taskBlock.fallback_models : harnessBlock.fallback_models;
1304
+ const fallbackSource = taskHasFallbacks ? taskBlock?.fallback_models : harnessBlock.fallback_models;
1305
+ const source = `dreamer.${sourceHarness(dreamer, args.harness)}`;
1306
+ const primary = resolvePrimaryEntry({
1307
+ entry: primarySource,
1308
+ defaultQualifier: taskQualifier ?? harnessQualifier,
1309
+ harness: args.harness
1310
+ });
1311
+ const fallbacks = resolveFallbackEntries(fallbackSource, args.harness);
1283
1312
  return {
1284
- primary: resolvePrimaryEntry({
1285
- entry: primarySource,
1286
- defaultQualifier: taskQualifier ?? harnessQualifier,
1287
- harness: args.harness
1288
- }),
1289
- fallbacks: resolveFallbackEntries(fallbackSource, args.harness),
1313
+ primary: primary ? {
1314
+ ...primary,
1315
+ sourceConfigKey: taskHasModel ? `${source}.tasks.${args.task}.model` : `${source}.model`
1316
+ } : undefined,
1317
+ fallbacks: fallbacks.map((entry) => ({
1318
+ ...entry,
1319
+ sourceConfigKey: taskHasFallbacks ? `${source}.tasks.${args.task}.fallback_models` : `${source}.fallback_models`
1320
+ })),
1290
1321
  schedule: readString(schedulingTask?.schedule),
1291
1322
  timeoutMinutes: typeof taskBlock?.timeout_minutes === "number" ? taskBlock.timeout_minutes : undefined,
1292
1323
  promotionThreshold: typeof schedulingTask?.promotion_threshold === "number" ? schedulingTask.promotion_threshold : undefined
@@ -1306,6 +1337,7 @@ function buildDreamTaskRuntimeConfigs(dreamer, harness, language, smartNotesEnab
1306
1337
  schedule: resolved.schedule ?? "",
1307
1338
  model: resolved.primary,
1308
1339
  fallbackModels: resolved.fallbacks,
1340
+ modelConfigKey: resolved.primary?.sourceConfigKey ?? resolved.fallbacks[0]?.sourceConfigKey,
1309
1341
  thinkingLevel: harness === "pi" ? resolved.primary?.qualifier : undefined,
1310
1342
  language,
1311
1343
  timeoutMinutes: resolved.timeoutMinutes ?? 20,
@@ -3520,7 +3552,7 @@ function startHostStallProfilerSwitch() {
3520
3552
  // package.json
3521
3553
  var package_default = {
3522
3554
  name: "@cortexkit/pi-magic-context",
3523
- version: "0.49.19",
3555
+ version: "0.49.21",
3524
3556
  type: "module",
3525
3557
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
3526
3558
  main: "dist/index.js",
@@ -3569,7 +3601,7 @@ var package_default = {
3569
3601
  "comment-json": "^5.0.0",
3570
3602
  "onnxruntime-web": "1.26.0-dev.20260416-b7804b056c",
3571
3603
  "quickjs-emscripten": "^0.32.0",
3572
- zod: "^4.1.8"
3604
+ zod: "^4.6.6"
3573
3605
  },
3574
3606
  optionalDependencies: {
3575
3607
  "onnxruntime-node": "1.30.0",
@@ -3585,9 +3617,12 @@ var package_default = {
3585
3617
  "@types/bun": "^1.3.10",
3586
3618
  "@types/node": "^22.20.0",
3587
3619
  "omp-coding-agent-1812": "npm:@oh-my-pi/pi-coding-agent@18.12.3",
3620
+ "omp-coding-agent-18126": "npm:@oh-my-pi/pi-coding-agent@18.12.6",
3621
+ "omp-pi-ai-171": "npm:@oh-my-pi/pi-ai@17.1.7",
3588
3622
  "omp-pi-ai-1889": "npm:@oh-my-pi/pi-ai@18.8.9",
3589
3623
  "omp-pi-ai-1811": "npm:@oh-my-pi/pi-ai@18.11.3",
3590
3624
  "omp-pi-ai-1812": "npm:@oh-my-pi/pi-ai@18.12.3",
3625
+ "omp-pi-ai-18126": "npm:@oh-my-pi/pi-ai@18.12.6",
3591
3626
  "pi-agent-core-087": "npm:@earendil-works/pi-agent-core@0.87.1",
3592
3627
  "pi-ai-086": "npm:@earendil-works/pi-ai@0.86.0",
3593
3628
  "pi-ai-087": "npm:@earendil-works/pi-ai@0.87.1",
@@ -4961,7 +4996,7 @@ async function promptWithTimeout(client, args, timeoutMs, signal, transport, fir
4961
4996
  if (!activity.monitored || activity.received)
4962
4997
  return;
4963
4998
  silent = true;
4964
- controller.abort();
4999
+ controller.abort(new ModelProducedNoOutputError(firstOutputTimeoutMs));
4965
5000
  }, firstOutputTimeoutMs) : undefined;
4966
5001
  const timeoutError = () => silent && firstOutputTimeoutMs !== undefined ? new ModelProducedNoOutputError(firstOutputTimeoutMs) : new Error(`prompt timed out after ${timeoutMs}ms`);
4967
5002
  const onExternalAbort = () => controller.abort();
@@ -5301,7 +5336,7 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
5301
5336
  throwWithPromptFailure(failure.error, failedAttempts, args, timeoutMs, options.transport);
5302
5337
  }
5303
5338
  if (!cooledPrimary && !quota)
5304
- log2(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(failure.error)}; trying ${fallbacks.length} fallback(s)`);
5339
+ log2(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(failure.error)}; ${fallbacks.length} fallback(s) configured, subject to remaining budget`);
5305
5340
  }
5306
5341
  for (let i = 0;i < fallbacks.length; i += 1) {
5307
5342
  const fallback = toModelEntry(fallbacks[i]);
@@ -5374,6 +5409,152 @@ function normalizeSDKResponse(response, fallback, options) {
5374
5409
  return fallback;
5375
5410
  }
5376
5411
  // ../plugin/src/features/magic-context/subagent-token-capture.ts
5412
+ var warnedUnknownModels = new Set;
5413
+ var loggedModelReroutes = new Set;
5414
+ var MAX_SUBAGENT_INVOCATION_ERROR_CHARS = 1000;
5415
+ var invocationErrorDetails = new WeakMap;
5416
+ function annotateSubagentInvocationError(error, details) {
5417
+ if (error && typeof error === "object") {
5418
+ const previous = invocationErrorDetails.get(error) ?? {};
5419
+ invocationErrorDetails.set(error, {
5420
+ ...previous,
5421
+ ...details,
5422
+ hostError: details.hostError ?? previous.hostError
5423
+ });
5424
+ }
5425
+ return error;
5426
+ }
5427
+ function errorDetailsOf(error) {
5428
+ const seen = new Set;
5429
+ const visit = (value, depth) => {
5430
+ if (!value || typeof value !== "object" || depth > 4 || seen.has(value))
5431
+ return {};
5432
+ seen.add(value);
5433
+ const direct = invocationErrorDetails.get(value) ?? {};
5434
+ const record = value;
5435
+ const nested = visit(record.hostError, depth + 1);
5436
+ const cause = visit(record.cause, depth + 1);
5437
+ return {
5438
+ ...cause,
5439
+ ...nested,
5440
+ ...direct,
5441
+ hostError: direct.hostError ?? nested.hostError ?? cause.hostError ?? record.hostError
5442
+ };
5443
+ };
5444
+ return visit(error, 0);
5445
+ }
5446
+ function modelRef(value) {
5447
+ const reference = typeof value === "string" ? value : value?.model;
5448
+ return typeof reference === "string" && reference.trim().length > 0 ? reference.trim() : undefined;
5449
+ }
5450
+ function splitModelRef(value) {
5451
+ if (!value)
5452
+ return { providerId: null, modelId: null };
5453
+ const slash = value.indexOf("/");
5454
+ return slash > 0 && slash < value.length - 1 ? { providerId: value.slice(0, slash), modelId: value.slice(slash + 1) } : { providerId: null, modelId: value };
5455
+ }
5456
+ function cleanOneLine(value) {
5457
+ const oneLine = sanitizeDiagnosticText(value).replaceAll("\r", " ").replaceAll(`
5458
+ `, " ").replaceAll("\t", " ").replace(/\s+/g, " ").trim();
5459
+ return oneLine.length <= MAX_SUBAGENT_INVOCATION_ERROR_CHARS ? oneLine : `${oneLine.slice(0, MAX_SUBAGENT_INVOCATION_ERROR_CHARS - 1)}…`;
5460
+ }
5461
+ function recordMessage(error) {
5462
+ if (typeof error === "string")
5463
+ return error;
5464
+ if (!error || typeof error !== "object")
5465
+ return String(error ?? "");
5466
+ const record = error;
5467
+ const data = record.data && typeof record.data === "object" ? record.data : undefined;
5468
+ const message = typeof data?.message === "string" ? data.message : typeof record.message === "string" ? record.message : typeof record.description === "string" ? record.description : "";
5469
+ const name = typeof record.name === "string" ? record.name : typeof record.type === "string" ? record.type : "";
5470
+ return [name, message].filter(Boolean).join(": ") || "The host reported an error without a message.";
5471
+ }
5472
+ function modelNotFoundDetail(error, attemptedModel) {
5473
+ const seen = new Set;
5474
+ const visit = (value, depth) => {
5475
+ if (typeof value === "string") {
5476
+ const modelMatch = value.match(/model not found:\s*(.+?)(?=(?:\.?\s*did you mean|$))/i);
5477
+ if (!modelMatch)
5478
+ return null;
5479
+ const model = modelMatch[1].trim().replace(/[.,;(]+$/, "");
5480
+ const suggestion = value.match(/did you mean:?\s*\(?\s*([^?);]+)/i)?.[1]?.trim();
5481
+ const message = `Model not found: ${model}${suggestion ? ` (did you mean ${suggestion}?)` : ""}`;
5482
+ return { model, ...suggestion ? { suggestion } : {}, message };
5483
+ }
5484
+ if (!value || typeof value !== "object" || depth > 4 || seen.has(value))
5485
+ return null;
5486
+ seen.add(value);
5487
+ const record = value;
5488
+ const data = record.data && typeof record.data === "object" ? record.data : undefined;
5489
+ const modelRecord = data?.model ?? record.model;
5490
+ const modelId = (typeof data?.modelID === "string" ? data.modelID : undefined) ?? (typeof modelRecord?.modelID === "string" ? modelRecord.modelID : undefined) ?? (typeof modelRecord?.id === "string" ? modelRecord.id : undefined);
5491
+ const providerId = (typeof data?.providerID === "string" ? data.providerID : undefined) ?? (typeof modelRecord?.providerID === "string" ? modelRecord.providerID : undefined);
5492
+ const suggestions = data?.suggestions;
5493
+ const suggestion = Array.isArray(suggestions) && typeof suggestions[0] === "string" ? suggestions[0] : typeof data?.suggestion === "string" ? data.suggestion : undefined;
5494
+ const rawMessage = recordMessage(value);
5495
+ const fromMessage = visit(rawMessage, depth + 1);
5496
+ if (fromMessage)
5497
+ return fromMessage.suggestion || !suggestion ? fromMessage : {
5498
+ ...fromMessage,
5499
+ suggestion,
5500
+ message: `Model not found: ${fromMessage.model} (did you mean ${suggestion}?)`
5501
+ };
5502
+ const name = `${String(record.name ?? "")} ${String(record.type ?? "")}`;
5503
+ if (/ProviderModelNotFoundError|model not found/i.test(name) && modelId) {
5504
+ const model = providerId ? `${providerId}/${modelId}` : modelId;
5505
+ const detail = `Model not found: ${model}${suggestion ? ` (did you mean ${suggestion}?)` : ""}`;
5506
+ return { model, ...suggestion ? { suggestion } : {}, message: detail };
5507
+ }
5508
+ for (const key of ["data", "error", "cause", "hostError"]) {
5509
+ const match = visit(record[key], depth + 1);
5510
+ if (match)
5511
+ return match;
5512
+ }
5513
+ return null;
5514
+ };
5515
+ const found = visit(error, 0);
5516
+ if (!found && attemptedModel && (typeof error === "string" && /ProviderModelNotFoundError/i.test(error) || error !== null && typeof error === "object" && /ProviderModelNotFoundError/i.test(`${String(error.name ?? "")} ${String(error.type ?? "")}`))) {
5517
+ return { model: attemptedModel, message: `Model not found: ${attemptedModel}` };
5518
+ }
5519
+ return found;
5520
+ }
5521
+ function hostLabel(harness) {
5522
+ switch (harness) {
5523
+ case "opencode2":
5524
+ return "OpenCode 2";
5525
+ case "opencode":
5526
+ return "OpenCode";
5527
+ case "pi":
5528
+ return "Pi";
5529
+ case "omp":
5530
+ return "Oh My Pi";
5531
+ }
5532
+ }
5533
+ function invocationErrorText(input, details, attemptedModel) {
5534
+ if (input.error == null && input.hostError == null && details.hostError == null)
5535
+ return null;
5536
+ const rawHostError = input.hostError ?? details.hostError;
5537
+ const modelError = modelNotFoundDetail(rawHostError ?? input.error, attemptedModel);
5538
+ if (modelError) {
5539
+ return cleanOneLine(`No reply: ${hostLabel(input.harness)} refused the model: ${modelError.message}`);
5540
+ }
5541
+ if (rawHostError != null) {
5542
+ return cleanOneLine(`No reply: ${hostLabel(input.harness)} reported a child-session error: ${recordMessage(rawHostError)}`);
5543
+ }
5544
+ return cleanOneLine(describeError(input.error).brief);
5545
+ }
5546
+ function warnUnknownModel(input, details, attemptedModel, modelConfigKey) {
5547
+ if (!attemptedModel)
5548
+ return;
5549
+ const issue = modelNotFoundDetail(input.hostError ?? details.hostError ?? input.error, attemptedModel);
5550
+ if (!issue || warnedUnknownModels.has(attemptedModel))
5551
+ return;
5552
+ if (!modelConfigKey)
5553
+ return;
5554
+ warnedUnknownModels.add(attemptedModel);
5555
+ const suggestion = issue.suggestion ? `provider suggests ${cleanOneLine(issue.suggestion)}` : "provider gave no model suggestion";
5556
+ log2(`[magic-context] WARNING: ${modelConfigKey} configured ${attemptedModel}, but ${hostLabel(input.harness)} does not know that model; ${suggestion}`);
5557
+ }
5377
5558
  function asNumber(value) {
5378
5559
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
5379
5560
  }
@@ -5444,8 +5625,11 @@ function sumTokensFromChildMessages(messages) {
5444
5625
  function findLastAssistantModel(messages) {
5445
5626
  for (let index = messages.length - 1;index >= 0; index -= 1) {
5446
5627
  const message = messages[index];
5447
- if (isAssistantMessage(message))
5448
- return modelFromMessage(message);
5628
+ if (isAssistantMessage(message)) {
5629
+ const model = modelFromMessage(message);
5630
+ if (model.providerId || model.modelId)
5631
+ return model;
5632
+ }
5449
5633
  }
5450
5634
  return { providerId: null, modelId: null };
5451
5635
  }
@@ -5454,10 +5638,25 @@ function recordChildInvocation(input) {
5454
5638
  return null;
5455
5639
  const tokens = input.tokens ?? sumTokensFromChildMessages(input.messages ?? []);
5456
5640
  const observedModel = findLastAssistantModel(input.messages ?? []);
5641
+ const details = errorDetailsOf(input.error);
5642
+ const attemptedModel = details.attemptedModel ?? modelRef(input.attemptedModel);
5643
+ const attemptConfig = [input.attemptedModel, ...input.configuredModels ?? []].find((candidate) => modelRef(candidate) === attemptedModel);
5644
+ const modelConfigKey = details.modelConfigKey ?? input.modelConfigKey ?? (typeof attemptConfig === "object" ? attemptConfig?.sourceConfigKey : undefined);
5645
+ const attemptedParts = splitModelRef(attemptedModel);
5457
5646
  const model = {
5458
- providerId: input.providerId ?? observedModel.providerId,
5459
- modelId: input.modelId ?? observedModel.modelId
5647
+ providerId: observedModel.providerId ?? input.providerId ?? attemptedParts.providerId,
5648
+ modelId: observedModel.modelId ?? input.modelId ?? attemptedParts.modelId
5460
5649
  };
5650
+ const reportedModelRef = observedModel.providerId && observedModel.modelId ? `${observedModel.providerId}/${observedModel.modelId}` : input.providerId && input.modelId ? `${input.providerId}/${input.modelId}` : undefined;
5651
+ if (attemptedModel && reportedModelRef && attemptedModel !== reportedModelRef && (observedModel.providerId !== null || input.providerId !== undefined)) {
5652
+ const rerouteKey = `${input.harness}\x00${attemptedModel}\x00${reportedModelRef}`;
5653
+ if (!loggedModelReroutes.has(rerouteKey)) {
5654
+ loggedModelReroutes.add(rerouteKey);
5655
+ sessionLog2(input.parentSessionId, `subagent model rerouted by host: attempted=${attemptedModel} reported=${reportedModelRef}`);
5656
+ }
5657
+ }
5658
+ warnUnknownModel(input, details, attemptedModel, modelConfigKey);
5659
+ const errorText = invocationErrorText(input, details, attemptedModel);
5461
5660
  try {
5462
5661
  return recordSubagentInvocation(input.db, {
5463
5662
  sessionId: input.parentSessionId,
@@ -5473,7 +5672,7 @@ function recordChildInvocation(input) {
5473
5672
  outputTokens: tokens.output,
5474
5673
  cacheReadTokens: tokens.cacheRead,
5475
5674
  cacheWriteTokens: tokens.cacheWrite,
5476
- error: input.error ? describeError(input.error).brief : null,
5675
+ error: errorText,
5477
5676
  parentInvocationId: input.parentInvocationId ?? null
5478
5677
  });
5479
5678
  } catch (error) {
@@ -5501,6 +5700,17 @@ var HOST_SESSION_ERROR = Symbol("promptAsyncHostSessionError");
5501
5700
  function isHostSessionError(error) {
5502
5701
  return error !== null && typeof error === "object" && error[HOST_SESSION_ERROR] === true;
5503
5702
  }
5703
+ function hostSessionErrorOf(error) {
5704
+ if (!isHostSessionError(error))
5705
+ return;
5706
+ return error.hostError;
5707
+ }
5708
+ function requestModelRef(request) {
5709
+ const model = request.body?.model;
5710
+ if (model && typeof model.providerID === "string" && typeof model.modelID === "string")
5711
+ return `${model.providerID}/${model.modelID}`;
5712
+ return;
5713
+ }
5504
5714
  function supportsPromptAsync(client) {
5505
5715
  const session = sessionApi(client);
5506
5716
  return typeof session?.promptAsync === "function" && typeof session?.status === "function" && typeof session?.messages === "function";
@@ -5655,11 +5865,29 @@ async function promptAsyncAndWaitForIdle(client, request, options = {}) {
5655
5865
  const initialBaseline = new Set(completionBaseline);
5656
5866
  activeSessionErrors.set(sessionId, undefined);
5657
5867
  try {
5658
- const sent = await session.promptAsync?.(request);
5868
+ let sent;
5869
+ try {
5870
+ sent = await session.promptAsync?.(request);
5871
+ } catch (error) {
5872
+ annotateSubagentInvocationError(error, {
5873
+ attemptedModel: requestModelRef(request),
5874
+ modelConfigKey: options.modelConfigKey,
5875
+ hostError: error
5876
+ });
5877
+ throw error;
5878
+ }
5659
5879
  if (sent && typeof sent === "object" && "error" in sent) {
5660
5880
  const rejection = sent.error;
5661
5881
  if (rejection) {
5662
- throw new Error(`prompt_async was rejected: ${describeRejection(rejection)}`);
5882
+ const error = new Error(`prompt_async was rejected: ${describeRejection(rejection)}`, {
5883
+ cause: rejection
5884
+ });
5885
+ annotateSubagentInvocationError(error, {
5886
+ attemptedModel: requestModelRef(request),
5887
+ modelConfigKey: options.modelConfigKey,
5888
+ hostError: rejection
5889
+ });
5890
+ throw error;
5663
5891
  }
5664
5892
  }
5665
5893
  let sentAt = Date.now();
@@ -5674,7 +5902,13 @@ async function promptAsyncAndWaitForIdle(client, request, options = {}) {
5674
5902
  Object.assign(error, {
5675
5903
  name: "DreamerProviderOutputFailureError",
5676
5904
  transient: true,
5677
- [HOST_SESSION_ERROR]: true
5905
+ [HOST_SESSION_ERROR]: true,
5906
+ hostError
5907
+ });
5908
+ annotateSubagentInvocationError(error, {
5909
+ attemptedModel: requestModelRef(request),
5910
+ modelConfigKey: options.modelConfigKey,
5911
+ hostError
5678
5912
  });
5679
5913
  throw error;
5680
5914
  }
@@ -9238,6 +9472,8 @@ function resolveHiddenCompletionExecutor(executor, client, db, directory, entryP
9238
9472
  }
9239
9473
  function createV1HiddenCompletionExecutor(client, db, directory) {
9240
9474
  const historianChildren = new Set;
9475
+ const hostErrors = new Map;
9476
+ const runIdentities = new Map;
9241
9477
  return {
9242
9478
  capabilities: { tools: true, harness: "opencode" },
9243
9479
  async open(run) {
@@ -9254,23 +9490,49 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
9254
9490
  preferResponseOnMissingData: true
9255
9491
  });
9256
9492
  const id = typeof created?.id === "string" ? created.id : "";
9257
- if (id)
9493
+ if (id) {
9258
9494
  rememberV1HiddenRun(id, run);
9495
+ runIdentities.set(id, run);
9496
+ }
9259
9497
  if (id && run.kind !== "dreamer-task") {
9260
9498
  historianChildren.add(id);
9261
9499
  rememberHistorianOutputCap(id, run.maxOutputTokens);
9262
9500
  }
9263
- return { id, childSessionId: id || undefined };
9501
+ const configured = toModelEntry(run.model);
9502
+ return {
9503
+ id,
9504
+ childSessionId: id || undefined,
9505
+ ...configured ? { attemptedModel: configured.model } : {},
9506
+ ...configured?.sourceConfigKey ? { modelConfigKey: configured.sourceConfigKey } : {}
9507
+ };
9264
9508
  },
9265
9509
  async attempt(handle, request) {
9266
9510
  if (!client)
9267
9511
  throw new Error("Hidden completion client is unavailable");
9512
+ const identity = runIdentities.get(handle.id);
9513
+ const requestedModel = request.body?.model;
9514
+ const requestedRef = requestedModel && typeof requestedModel.providerID === "string" && typeof requestedModel.modelID === "string" ? `${requestedModel.providerID}/${requestedModel.modelID}` : undefined;
9515
+ const matchingConfigured = (identity?.configuredModels ?? []).map(toModelEntry).find((entry) => entry?.model === requestedRef);
9516
+ const configured = matchingConfigured ?? (requestedRef && identity?.model && toModelEntry(identity.model)?.model === requestedRef ? toModelEntry(identity.model) : toModelEntry(identity?.model));
9517
+ handle.attemptedModel = requestedRef ?? configured?.model ?? handle.attemptedModel;
9518
+ handle.modelConfigKey = configured?.sourceConfigKey ?? handle.modelConfigKey;
9268
9519
  if (supportsPromptAsync(client)) {
9269
9520
  try {
9270
- await promptAsyncAndWaitForIdle(client, request);
9521
+ await promptAsyncAndWaitForIdle(client, request, {
9522
+ modelConfigKey: handle.modelConfigKey
9523
+ });
9271
9524
  } catch (error) {
9272
- if (historianChildren.has(handle.id) && isHostSessionError(error))
9273
- return;
9525
+ if (isHostSessionError(error)) {
9526
+ const hostError = hostSessionErrorOf(error);
9527
+ hostErrors.set(handle.id, hostError);
9528
+ annotateSubagentInvocationError(error, {
9529
+ attemptedModel: handle.attemptedModel,
9530
+ modelConfigKey: handle.modelConfigKey,
9531
+ hostError
9532
+ });
9533
+ if (historianChildren.has(handle.id))
9534
+ return;
9535
+ }
9274
9536
  throw error;
9275
9537
  }
9276
9538
  return;
@@ -9288,9 +9550,16 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
9288
9550
  preferResponseOnMissingData: true
9289
9551
  });
9290
9552
  const assistantFailure = extractLatestAssistantFailure(messages);
9553
+ const hostError = hostErrors.get(handle.id);
9291
9554
  if (assistantFailure) {
9292
9555
  const finish = assistantFailure.finish ? ` (finish=${assistantFailure.finish})` : "";
9293
- throw new Error(`Historian host recorded an assistant error${finish}: ${describeAssistantFailure(assistantFailure.error)}`);
9556
+ const error = new Error(`Historian host recorded an assistant error${finish}: ${describeAssistantFailure(assistantFailure.error)}`, hostError === undefined ? undefined : { cause: hostError });
9557
+ annotateSubagentInvocationError(error, {
9558
+ attemptedModel: handle.attemptedModel,
9559
+ modelConfigKey: handle.modelConfigKey,
9560
+ hostError
9561
+ });
9562
+ throw error;
9294
9563
  }
9295
9564
  const text = extractLatestAssistantText(messages);
9296
9565
  const latest = Array.isArray(messages) ? messages.filter((message) => isRecord(message) && isRecord(message.info) && message.info.role === "assistant").sort((left, right) => historianMessageCreatedAt(right) - historianMessageCreatedAt(left))[0] : undefined;
@@ -9301,13 +9570,18 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
9301
9570
  reasoning: text ? null : extractLatestHistorianReasoning(messages),
9302
9571
  lengthCapped: hasLengthCappedOutput(messages),
9303
9572
  usage: sumTokensFromChildMessages(messages),
9304
- tokenLog: runTokenLog(info.tokens, undefined, info.finish ?? info.finish_reason ?? info.finishReason)
9573
+ tokenLog: runTokenLog(info.tokens, undefined, info.finish ?? info.finish_reason ?? info.finishReason),
9574
+ attemptedModel: handle.attemptedModel,
9575
+ modelConfigKey: handle.modelConfigKey,
9576
+ ...hostError === undefined ? {} : { hostError }
9305
9577
  };
9306
9578
  },
9307
9579
  async close(handle, settlement) {
9308
9580
  if (handle?.id) {
9309
9581
  rememberV1HiddenRun(handle.id, undefined);
9310
9582
  historianChildren.delete(handle.id);
9583
+ hostErrors.delete(handle.id);
9584
+ runIdentities.delete(handle.id);
9311
9585
  forgetHistorianOutputCap(handle.id);
9312
9586
  }
9313
9587
  if (!client)
@@ -9462,7 +9736,8 @@ async function runHistorianPrompt(args) {
9462
9736
  if (invocationRecorded)
9463
9737
  return null;
9464
9738
  invocationRecorded = true;
9465
- const actualModelRef = completion?.providerId && completion.modelId ? `${completion.providerId}/${completion.modelId}` : null;
9739
+ const configuredModel = toModelEntry(modelOverride);
9740
+ const actualModelRef = completion?.providerId && completion.modelId ? `${completion.providerId}/${completion.modelId}` : handle?.attemptedModel ?? configuredModel?.model ?? null;
9466
9741
  const usedConfiguredFallback = actualModelRef !== null && (fallbackModels ?? []).some((candidate) => toModelEntry(candidate)?.model === actualModelRef);
9467
9742
  return recordChildInvocation({
9468
9743
  db: openDatabase(),
@@ -9478,6 +9753,10 @@ async function runHistorianPrompt(args) {
9478
9753
  providerId: completion.providerId,
9479
9754
  modelId: completion.modelId
9480
9755
  } : {},
9756
+ attemptedModel: handle?.attemptedModel ?? modelOverride,
9757
+ configuredModels: fallbackModels,
9758
+ modelConfigKey: handle?.modelConfigKey ?? configuredModel?.sourceConfigKey,
9759
+ hostError: params.hostError ?? completion?.hostError,
9481
9760
  error: params.error,
9482
9761
  parentInvocationId: agentId === HISTORIAN_EDITOR_AGENT ? parentInvocationId ?? null : null
9483
9762
  });
@@ -9591,7 +9870,8 @@ async function runHistorianPrompt(args) {
9591
9870
  const invocationId = recordInvocation({
9592
9871
  status: emptyError ? "empty" : "completed",
9593
9872
  messages: completion.messages,
9594
- error: emptyError
9873
+ error: emptyError,
9874
+ hostError: completion.hostError
9595
9875
  });
9596
9876
  if (emptyError && (!reasoningResult || lengthCapped)) {
9597
9877
  return {
@@ -10414,7 +10694,9 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
10414
10694
  status: "completed",
10415
10695
  tokens: run.output.usage,
10416
10696
  providerId: run.output.providerId,
10417
- modelId: run.output.modelId
10697
+ modelId: run.output.modelId,
10698
+ attemptedModel: args.model,
10699
+ configuredModels: args.fallbackModels
10418
10700
  });
10419
10701
  }
10420
10702
  stage = "apply";
@@ -10606,6 +10888,7 @@ async function runHiddenSingleShotPrompt(args) {
10606
10888
  });
10607
10889
  }).catch(() => {});
10608
10890
  const handle = await raceWithSignal(opening, args.signal);
10891
+ let completion;
10609
10892
  args.onOpened?.(handle.id);
10610
10893
  let promptSettled = false;
10611
10894
  try {
@@ -10627,7 +10910,10 @@ async function runHiddenSingleShotPrompt(args) {
10627
10910
  ...args.signal ? { signal: args.signal } : {},
10628
10911
  fallbackModels: args.fallbackModels,
10629
10912
  callContext: args.callContext,
10630
- fetchOutput: () => args.executor.collect(handle, 50),
10913
+ fetchOutput: async () => {
10914
+ completion = await args.executor.collect(handle, 50);
10915
+ return completion;
10916
+ },
10631
10917
  validateOutput: (completion) => {
10632
10918
  const tokens = completion.tokenLog ?? runTokenLog(undefined);
10633
10919
  sessionLog2(args.parentSessionId ?? "dreamer", `${args.callContext} response_chars=${(completion.text ?? completion.reasoning ?? "").length} ${formatRunTokenLog(tokens)}`);
@@ -10643,6 +10929,12 @@ async function runHiddenSingleShotPrompt(args) {
10643
10929
  promptSettled = true;
10644
10930
  return { validated: run.validated, completion: run.output, childSessionId: handle.id };
10645
10931
  } catch (error) {
10932
+ const configuredModel = toModelEntry(args.model);
10933
+ annotateSubagentInvocationError(error, {
10934
+ attemptedModel: completion?.attemptedModel ?? handle.attemptedModel ?? configuredModel?.model,
10935
+ modelConfigKey: completion?.modelConfigKey ?? handle.modelConfigKey ?? configuredModel?.sourceConfigKey,
10936
+ ...completion?.hostError === undefined ? {} : { hostError: completion.hostError }
10937
+ });
10646
10938
  if (args.onFailureOutput) {
10647
10939
  let timer;
10648
10940
  try {
@@ -10970,6 +11262,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
10970
11262
  startedAt,
10971
11263
  status: params.status,
10972
11264
  messages: params.messages,
11265
+ attemptedModel: args.model,
11266
+ configuredModels: args.fallbackModels,
10973
11267
  error: params.error
10974
11268
  });
10975
11269
  };
@@ -11757,6 +12051,8 @@ function recordInvocation(args, startedAt, params) {
11757
12051
  startedAt,
11758
12052
  status: params.status,
11759
12053
  messages: params.messages,
12054
+ attemptedModel: args.model,
12055
+ configuredModels: args.fallbackModels,
11760
12056
  ...params.completion && !params.completion.messages ? {
11761
12057
  tokens: params.completion.usage,
11762
12058
  providerId: params.completion.providerId,
@@ -11997,28 +12293,35 @@ function diff(name, before, after) {
11997
12293
  rmSync(dir, { recursive: true, force: true });
11998
12294
  }
11999
12295
  }
12000
- function validateDocsProposal(projectDir, output, budget, expected) {
12001
- if (Object.entries(expected).some(([name, value]) => docsBaseHashes(projectDir)[name] !== value))
12002
- throw new Error("base drifted");
12296
+ function parseDocsProposalOutput(output) {
12003
12297
  const match = output.match(/```json\s*([\s\S]*?)```/);
12004
12298
  const parsed = JSON.parse(match?.[1] ?? output);
12005
12299
  if (!Array.isArray(parsed))
12006
12300
  throw new Error("proposal must be a JSON array");
12007
12301
  const changes = parsed;
12008
- if (!changes.length)
12009
- throw new Error("empty proposal");
12010
12302
  if (changes.some((item) => !item || !FILES.includes(item.file)))
12011
12303
  throw new Error("unknown proposal file");
12304
+ const seen = new Set;
12305
+ for (const change of changes) {
12306
+ const key = `${change.file}:${change.heading}`;
12307
+ if (!["replace", "add", "remove"].includes(change.action) || typeof change.heading !== "string" || !/^#{1,6} [^\r\n]+$/.test(change.heading) || typeof change.text !== "string" || typeof change.reason !== "string" || !change.reason.trim() || /[\r\n]/.test(change.reason) || seen.has(key))
12308
+ throw new Error(`invalid section change in ${change.file}`);
12309
+ seen.add(key);
12310
+ }
12311
+ return changes;
12312
+ }
12313
+ function validateDocsProposal(projectDir, output, budget, expected) {
12314
+ if (Object.entries(expected).some(([name, value]) => docsBaseHashes(projectDir)[name] !== value))
12315
+ throw new Error("base drifted");
12316
+ const changes = parseDocsProposalOutput(output);
12317
+ if (!changes.length)
12318
+ throw new Error("empty proposal");
12012
12319
  let tokens = 0;
12013
12320
  let diffs = "";
12014
12321
  for (const file of FILES) {
12015
12322
  const before = existsSync6(join8(projectDir, file)) ? readFileSync6(join8(projectDir, file), "utf8") : "";
12016
12323
  let after = before;
12017
- const seen = new Set;
12018
12324
  for (const change of changes.filter((item) => item.file === file)) {
12019
- if (!["replace", "add", "remove"].includes(change.action) || typeof change.heading !== "string" || !/^#{1,6} [^\r\n]+$/.test(change.heading) || typeof change.text !== "string" || typeof change.reason !== "string" || !change.reason.trim() || /[\r\n]/.test(change.reason) || seen.has(change.heading))
12020
- throw new Error(`invalid section change in ${file}`);
12021
- seen.add(change.heading);
12022
12325
  const section = sections(after).find((item) => item.heading === change.heading);
12023
12326
  if (change.action === "add") {
12024
12327
  if (section || !change.text.startsWith(`${change.heading}
@@ -13292,6 +13595,8 @@ Remember: output only the JSON object described by the system prompt.`;
13292
13595
  startedAt,
13293
13596
  status: params.status,
13294
13597
  messages: params.messages,
13598
+ attemptedModel: args.model,
13599
+ configuredModels: args.fallbackModels,
13295
13600
  error: params.error
13296
13601
  });
13297
13602
  };
@@ -14039,6 +14344,8 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
14039
14344
  startedAt,
14040
14345
  status: params.status,
14041
14346
  messages: params.messages,
14347
+ attemptedModel: args.model,
14348
+ configuredModels: args.fallbackModels,
14042
14349
  error: params.error
14043
14350
  });
14044
14351
  };
@@ -14953,12 +15260,14 @@ function recordInvocation2(args, startedAt, params) {
14953
15260
  recordChildInvocation({
14954
15261
  db: args.db,
14955
15262
  parentSessionId: args.parentSessionId,
14956
- harness: "opencode",
15263
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
14957
15264
  subagent: "dreamer",
14958
15265
  task: "map-memories",
14959
15266
  startedAt,
14960
15267
  status: params.status,
14961
15268
  messages: params.messages,
15269
+ attemptedModel: args.model,
15270
+ configuredModels: args.fallbackModels,
14962
15271
  error: params.error
14963
15272
  });
14964
15273
  }
@@ -15583,12 +15892,14 @@ function recordInvocation3(args, startedAt, params) {
15583
15892
  recordChildInvocation({
15584
15893
  db: args.db,
15585
15894
  parentSessionId: args.parentSessionId,
15586
- harness: "opencode",
15895
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
15587
15896
  subagent: "dreamer",
15588
15897
  task: "refresh-primers",
15589
15898
  startedAt,
15590
15899
  status: params.status,
15591
15900
  messages: params.messages,
15901
+ attemptedModel: args.model,
15902
+ configuredModels: args.fallbackModels,
15592
15903
  error: params.error
15593
15904
  });
15594
15905
  }
@@ -17162,12 +17473,14 @@ function recordInvocation4(args, startedAt, params) {
17162
17473
  recordChildInvocation({
17163
17474
  db: args.db,
17164
17475
  parentSessionId: args.parentSessionId,
17165
- harness: "opencode",
17476
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
17166
17477
  subagent: "dreamer",
17167
17478
  task: args.forceBroad ? "verify-broad" : "verify",
17168
17479
  startedAt,
17169
17480
  status: params.status,
17170
17481
  messages: params.messages,
17482
+ attemptedModel: args.model,
17483
+ configuredModels: args.fallbackModels,
17171
17484
  error: params.error
17172
17485
  });
17173
17486
  }
@@ -18043,6 +18356,25 @@ async function runRetrospectiveTask(config, ctx, helpers) {
18043
18356
  let childSessionId = null;
18044
18357
  let hiddenHandle = null;
18045
18358
  let promptSettled = false;
18359
+ let invocationRecorded = false;
18360
+ const recordInvocation = (status, messages, error) => {
18361
+ if (!parent || !childSessionId || invocationRecorded)
18362
+ return;
18363
+ invocationRecorded = true;
18364
+ recordChildInvocation({
18365
+ db,
18366
+ parentSessionId: parent,
18367
+ harness: deps.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
18368
+ subagent: "dreamer",
18369
+ task: config.task,
18370
+ startedAt: helpers.invocationStartedAt,
18371
+ status,
18372
+ messages,
18373
+ attemptedModel: config.model,
18374
+ configuredModels: config.fallbackModels,
18375
+ error
18376
+ });
18377
+ };
18046
18378
  try {
18047
18379
  if (deps.hiddenCompletionExecutor) {
18048
18380
  hiddenHandle = await deps.hiddenCompletionExecutor.open({
@@ -18127,18 +18459,8 @@ async function runRetrospectiveTask(config, ctx, helpers) {
18127
18459
  return { ...run, output };
18128
18460
  };
18129
18461
  const finish = (run, watermark) => {
18130
- if (parent && run) {
18131
- recordChildInvocation({
18132
- db,
18133
- parentSessionId: parent,
18134
- harness: "opencode",
18135
- subagent: "dreamer",
18136
- task: config.task,
18137
- startedAt: helpers.invocationStartedAt,
18138
- status: "completed",
18139
- messages: run.output
18140
- });
18141
- }
18462
+ if (run)
18463
+ recordInvocation("completed", run.output);
18142
18464
  return completedWindow(watermark);
18143
18465
  };
18144
18466
  const userLines = renderGateUserLines(messages);
@@ -18231,6 +18553,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
18231
18553
  log2(`[dreamer] retrospective: flagged=${flagged.length} learnings=${learnings.length} memory=${applied.memoryWritten} observations=${applied.observationsInserted} dropped=${applied.observationsDropped} rejected=${applied.rejected.length}`);
18232
18554
  return finish(deepenRun, scan.maxScannedTs);
18233
18555
  } catch (error) {
18556
+ recordInvocation(abortController.signal.aborted ? "aborted" : failedInvocationStatus(error), undefined, error);
18234
18557
  if (!detectOverflow(error).isOverflow)
18235
18558
  throw error;
18236
18559
  const failures = (activeOverflow?.failures ?? 0) + 1;
@@ -18302,6 +18625,25 @@ async function runAgenticTask(config, ctx, helpers) {
18302
18625
  let childSessionId = null;
18303
18626
  let promptSettled = false;
18304
18627
  let expiredArchived = 0;
18628
+ let invocationRecorded = false;
18629
+ const recordInvocation = (status, messages, error) => {
18630
+ if (!parent || !childSessionId || invocationRecorded)
18631
+ return;
18632
+ invocationRecorded = true;
18633
+ recordChildInvocation({
18634
+ db,
18635
+ parentSessionId: parent,
18636
+ harness: deps.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
18637
+ subagent: "dreamer",
18638
+ task,
18639
+ startedAt: invocationStartedAt,
18640
+ status,
18641
+ messages,
18642
+ attemptedModel: config.model,
18643
+ configuredModels: config.fallbackModels,
18644
+ error
18645
+ });
18646
+ };
18305
18647
  try {
18306
18648
  let curateMemories;
18307
18649
  let curateCategory;
@@ -18390,12 +18732,17 @@ async function runAgenticTask(config, ctx, helpers) {
18390
18732
  callContext: `dreamer:${task}`,
18391
18733
  metadata: { tokenBudget: config.tokenBudget, onBudgetUpdate },
18392
18734
  allowEmpty: task === "curate",
18735
+ onOpened: (sessionId) => {
18736
+ childSessionId = sessionId;
18737
+ },
18393
18738
  model: config.model,
18394
18739
  fallbackModels: config.fallbackModels,
18395
18740
  language: task === "curate" ? config.language ?? deps.language : undefined,
18396
18741
  timeoutMs: Math.min(Math.max(0, deadline - Date.now()), config.timeoutMinutes * 60 * 1000),
18397
18742
  signal: abortController.signal,
18398
18743
  parse: (text, completion) => {
18744
+ if (task === "maintain-docs")
18745
+ parseDocsProposalOutput(text);
18399
18746
  if (task !== "curate")
18400
18747
  return text;
18401
18748
  const memoryOperations = inspectCurateMemoryOperations(completion.messages);
@@ -18459,6 +18806,8 @@ async function runAgenticTask(config, ctx, helpers) {
18459
18806
  if (task !== "curate") {
18460
18807
  if (!text)
18461
18808
  throw new Error("Dreamer returned no assistant output.");
18809
+ if (task === "maintain-docs")
18810
+ parseDocsProposalOutput(text);
18462
18811
  return text;
18463
18812
  }
18464
18813
  const memoryOperations = inspectCurateMemoryOperations(messages);
@@ -18505,21 +18854,10 @@ async function runAgenticTask(config, ctx, helpers) {
18505
18854
  helpers.reportProgress(curateRefused, curateRefused);
18506
18855
  log2(`[dreamer] curate safety summary: refused=${curateRefused}`);
18507
18856
  }
18508
- if (parent) {
18509
- recordChildInvocation({
18510
- db,
18511
- parentSessionId: parent,
18512
- harness: "opencode",
18513
- subagent: "dreamer",
18514
- task,
18515
- startedAt: invocationStartedAt,
18516
- status: "completed",
18517
- messages: run.output
18518
- });
18519
- }
18857
+ recordInvocation("completed", run.output);
18520
18858
  if (task === "maintain-docs" && docsHashes && changes) {
18521
18859
  try {
18522
- if (run.validated === "[]") {
18860
+ if (parseDocsProposalOutput(String(run.validated)).length === 0) {
18523
18861
  helpers.recordRun("completed", null, { progress: "no corrections proposed" });
18524
18862
  return {
18525
18863
  status: "completed",
@@ -18570,6 +18908,9 @@ async function runAgenticTask(config, ctx, helpers) {
18570
18908
  }
18571
18909
  } : {}
18572
18910
  };
18911
+ } catch (error) {
18912
+ recordInvocation(abortController.signal.aborted ? "aborted" : failedInvocationStatus(error), undefined, error);
18913
+ throw error;
18573
18914
  } finally {
18574
18915
  heartbeat.stop();
18575
18916
  if (childSessionId)
@@ -19157,6 +19498,8 @@ var RECONCILIATION_BATCH_SIZE = 100;
19157
19498
 
19158
19499
  class MagicContextMessageIndexHeapHolder {
19159
19500
  reconciledSessions = new Set;
19501
+ reconciledSnapshots = new Map;
19502
+ stalledSessions = new Set;
19160
19503
  reconciliationScheduledSessions = new Set;
19161
19504
  clearAndReindexScheduledSessions = new Map;
19162
19505
  sessionLocks = new Map;
@@ -19207,18 +19550,28 @@ function logIndexingError(sessionId, action, error) {
19207
19550
  sessionLog2(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
19208
19551
  log2(`[message-index-async] ${action} failed for ${sessionId}:`, error);
19209
19552
  }
19553
+ function logReconciliationStall(sessionId, reason) {
19554
+ if (heapHolder.stalledSessions.has(sessionId))
19555
+ return;
19556
+ heapHolder.stalledSessions.add(sessionId);
19557
+ sessionLog2(sessionId, `message FTS reconciliation stalled: ${reason}; will retry`);
19558
+ }
19210
19559
  async function reconcileSessionIndex(db, sessionId, readMessages) {
19211
- if (!await sourceReady(readMessages, sessionId))
19560
+ if (!await sourceReady(readMessages, sessionId)) {
19561
+ logReconciliationStall(sessionId, "raw message reader is not ready");
19212
19562
  return false;
19563
+ }
19213
19564
  await runWithSessionLock(sessionId, async () => {
19214
- if (heapHolder.reconciledSessions.has(sessionId))
19565
+ if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId))
19215
19566
  return;
19216
19567
  let fallbackSnapshot = null;
19217
19568
  try {
19218
19569
  const fullReader = typeof readMessages === "function" ? readMessages : null;
19219
- const finalWatermark = readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
19570
+ const revision = readMessages.getRevision?.(sessionId);
19571
+ const previous = heapHolder.reconciledSnapshots.get(sessionId);
19572
+ const finalWatermark = previous && revision === previous.revision ? previous.count : revision !== undefined && readMessages.getCountAfterRevision ? previous && revision > previous.revision ? previous.count + readMessages.getCountAfterRevision(sessionId, previous.revision, revision) : readMessages.getCountAfterRevision(sessionId, -1, revision) : readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
19220
19573
  let cursor = getMessageIndexReconciliationStartOrdinal2(db, sessionId);
19221
- let after;
19574
+ let after = cursor === previous?.count ? previous.after : undefined;
19222
19575
  while (cursor < finalWatermark) {
19223
19576
  const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
19224
19577
  const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
@@ -19237,6 +19590,20 @@ async function reconcileSessionIndex(db, sessionId, readMessages) {
19237
19590
  }
19238
19591
  if (isMessageIndexReconciledThrough2(db, sessionId, finalWatermark)) {
19239
19592
  heapHolder.reconciledSessions.add(sessionId);
19593
+ if (revision !== undefined) {
19594
+ if (!after && finalWatermark > 0 && readMessages.readPage) {
19595
+ const last = readMessages.readPage(sessionId, finalWatermark - 1, 1, finalWatermark).at(-1);
19596
+ if (last?.ordinal === finalWatermark && typeof last.createdAt === "number")
19597
+ after = { timeCreated: last.createdAt, id: last.id };
19598
+ }
19599
+ heapHolder.reconciledSnapshots.set(sessionId, {
19600
+ revision,
19601
+ count: finalWatermark,
19602
+ after
19603
+ });
19604
+ }
19605
+ } else {
19606
+ logReconciliationStall(sessionId, `gap after ordinal ${cursor} (store count ${finalWatermark})`);
19240
19607
  }
19241
19608
  } finally {
19242
19609
  heapHolder.activeReconcilerBuffers.delete(sessionId);
@@ -19245,25 +19612,32 @@ async function reconcileSessionIndex(db, sessionId, readMessages) {
19245
19612
  return true;
19246
19613
  }
19247
19614
  function scheduleReconciliation(db, sessionId, readMessages) {
19248
- if (heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
19615
+ if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
19249
19616
  return;
19250
19617
  }
19251
19618
  heapHolder.reconciliationScheduledSessions.add(sessionId);
19252
19619
  scheduleAfterBootQuiet(() => {
19253
19620
  defer(() => {
19621
+ let appendedDuringReconciliation = false;
19622
+ const previousSnapshot = heapHolder.reconciledSnapshots.get(sessionId);
19254
19623
  reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
19255
- if (ran)
19624
+ if (ran) {
19625
+ const snapshot = heapHolder.reconciledSnapshots.get(sessionId);
19626
+ appendedDuringReconciliation = snapshot !== undefined && snapshot !== previousSnapshot && readMessages.getRevision !== undefined && readMessages.getRevision(sessionId) !== snapshot.revision;
19256
19627
  return;
19628
+ }
19257
19629
  inRootAsyncContext2(() => setTimeout(() => {
19258
19630
  heapHolder.reconciliationScheduledSessions.delete(sessionId);
19259
19631
  scheduleReconciliation(db, sessionId, readMessages);
19260
19632
  }, PREPARE_RETRY_MS)).unref?.();
19261
19633
  }).catch((error) => {
19262
- logIndexingError(sessionId, "reconciliation", error);
19634
+ logReconciliationStall(sessionId, error instanceof Error ? error.message : String(error));
19263
19635
  if (isDatabaseLockedError(error))
19264
19636
  inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
19265
19637
  }).finally(() => {
19266
19638
  heapHolder.reconciliationScheduledSessions.delete(sessionId);
19639
+ if (appendedDuringReconciliation)
19640
+ scheduleReconciliation(db, sessionId, readMessages);
19267
19641
  });
19268
19642
  });
19269
19643
  });
@@ -19355,6 +19729,11 @@ async function indexSingleMessageOffThread(db, sessionId, message) {
19355
19729
  return result.inserted;
19356
19730
  }
19357
19731
  async function sweepOrphanedOpenCodeMessageIndexesOffThread(db, openSource, options = {}) {
19732
+ if (getHarness2() === "opencode" || getHarness2() === "opencode2")
19733
+ options = {
19734
+ ...options,
19735
+ fenceLockNames: options.fenceLockNames ?? takeLkgRecoveryLockSweepPage()
19736
+ };
19358
19737
  if (getHarness2() === "opencode2")
19359
19738
  openSource = () => new Database2(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"), {
19360
19739
  readonly: true,
@@ -19391,6 +19770,8 @@ function clearSessionTracking(sessionId) {
19391
19770
  Atomics.store(cancellation, 0, 1);
19392
19771
  heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
19393
19772
  heapHolder.reconciledSessions.delete(sessionId);
19773
+ heapHolder.reconciledSnapshots.delete(sessionId);
19774
+ heapHolder.stalledSessions.delete(sessionId);
19394
19775
  heapHolder.reconciliationScheduledSessions.delete(sessionId);
19395
19776
  heapHolder.sessionLocks.delete(sessionId);
19396
19777
  heapHolder.activeReconcilerBuffers.delete(sessionId);
@@ -20580,7 +20961,8 @@ class PiSubagentRunner {
20580
20961
  ...options,
20581
20962
  model: attempt?.model,
20582
20963
  thinkingLevel: attempt?.qualifier,
20583
- fallbackModels: undefined
20964
+ fallbackModels: undefined,
20965
+ accountingModelConfigKey: typeof attempt === "object" ? attempt.sourceConfigKey ?? options.accountingModelConfigKey : options.accountingModelConfigKey
20584
20966
  };
20585
20967
  const result = await this.runOnce(attemptOptions, runMode, index === 0 ? primaryModelRef : undefined);
20586
20968
  if (result.ok)
@@ -20635,6 +21017,8 @@ class PiSubagentRunner {
20635
21017
  subagent: options.accountingSubagent ?? inferAccountingSubagent(options.agent),
20636
21018
  task: options.accountingTask ?? null,
20637
21019
  startedAt: startTime,
21020
+ attemptedModel: modelRef,
21021
+ modelConfigKey: options.accountingModelConfigKey,
20638
21022
  status: result.ok ? "completed" : result.meta?.failureClass === ZEN_FREE_TIER_FAILURE ? "failed" : result.reason === "abort" ? "aborted" : result.reason === "timeout" ? "timed_out" : result.reason === "no_assistant" || result.reason === "truncated" ? "empty" : "failed",
20639
21023
  messages,
20640
21024
  providerId: hasProvider ? modelRef?.slice(0, providerSeparator) : undefined,
@@ -21184,10 +21568,11 @@ class PiSubagentRunner {
21184
21568
  if (settled)
21185
21569
  return;
21186
21570
  terminateChild(child);
21571
+ const silentCut = options.signal?.reason instanceof ModelProducedNoOutputError ? options.signal.reason : undefined;
21187
21572
  settle({
21188
21573
  ok: false,
21189
- reason: "abort",
21190
- error: "pi subagent aborted by caller",
21574
+ reason: silentCut ? "timeout" : "abort",
21575
+ error: silentCut?.message ?? "pi subagent aborted by caller",
21191
21576
  durationMs: Date.now() - startTime
21192
21577
  });
21193
21578
  };
@@ -21593,6 +21978,28 @@ function terminateChild(child) {
21593
21978
  }
21594
21979
  }
21595
21980
 
21981
+ // src/dreamer/model-activity.ts
21982
+ function piEventShowsModelOutput(event) {
21983
+ if (!isRecord(event))
21984
+ return false;
21985
+ if (event.type !== "message_update" && event.type !== "message_end")
21986
+ return false;
21987
+ const update = event.assistantMessageEvent;
21988
+ if (event.type === "message_update" && isRecord(update)) {
21989
+ if (update.type === "toolcall_start")
21990
+ return true;
21991
+ if (["text_delta", "thinking_delta", "toolcall_delta"].includes(String(update.type)) && typeof update.delta === "string" && update.delta.length > 0)
21992
+ return true;
21993
+ }
21994
+ const message = event.message;
21995
+ if (!isRecord(message) || message.role !== "assistant")
21996
+ return false;
21997
+ if (Array.isArray(message.content) && message.content.some((part) => isRecord(part) && (part.type === "toolCall" || part.type === "text" && typeof part.text === "string" && part.text.length > 0 || part.type === "thinking" && typeof part.thinking === "string" && part.thinking.length > 0)))
21998
+ return true;
21999
+ const usage = message.usage;
22000
+ return isRecord(usage) && ["input", "output", "cacheRead", "cacheWrite"].some((key) => typeof usage[key] === "number" && usage[key] > 0);
22001
+ }
22002
+
21596
22003
  // src/dreamer/primer-raw-provider-pi.ts
21597
22004
  import { join as join13 } from "node:path";
21598
22005
 
@@ -22275,7 +22682,7 @@ function extractPiTextContent(content) {
22275
22682
  }
22276
22683
 
22277
22684
  // src/dreamer/index.ts
22278
- var warnedUnknownModels = new Set;
22685
+ var warnedUnknownModels2 = new Set;
22279
22686
  var modelAvailability = new WeakMap;
22280
22687
  function validatePiDreamerModels(tasks, registry, harness = "pi") {
22281
22688
  let resolved = modelAvailability.get(registry);
@@ -22297,9 +22704,9 @@ function validatePiDreamerModels(tasks, registry, harness = "pi") {
22297
22704
  }
22298
22705
  if (available)
22299
22706
  return true;
22300
- if (!warnedUnknownModels.has(model)) {
22707
+ if (!warnedUnknownModels2.has(model)) {
22301
22708
  log2(`[dreamer] WARNING: dropping Pi model not found: ${model}`);
22302
- warnedUnknownModels.add(model);
22709
+ warnedUnknownModels2.add(model);
22303
22710
  }
22304
22711
  return false;
22305
22712
  });
@@ -22531,6 +22938,8 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
22531
22938
  const systemPrompt = extractSystemPrompt(args);
22532
22939
  const perTaskModel = extractBodyModel(args);
22533
22940
  const requestedAgent = extractBodyAgent(args) ?? "magic-context-dreamer";
22941
+ const accountingTask = accountingTaskFromTitle(dreamSession.title);
22942
+ const taskConfig = accountingTask ? buildDreamTaskRuntimeConfigs(getDreamerConfig(), opts.harness).find((entry) => entry.task === accountingTask) : undefined;
22534
22943
  const controller = new AbortController;
22535
22944
  let controllers = dreamAbortControllers.get(opts.registrationOwner);
22536
22945
  if (!controllers) {
@@ -22538,7 +22947,12 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
22538
22947
  dreamAbortControllers.set(opts.registrationOwner, controllers);
22539
22948
  }
22540
22949
  controllers.add(controller);
22950
+ noteModelActivityMonitored(args.signal ?? undefined);
22541
22951
  const runPromise = runner.run({
22952
+ onProgress: (progress) => {
22953
+ if (progress.type === "raw_event" && piEventShowsModelOutput(progress.event))
22954
+ noteModelOutputReceived(args.signal ?? undefined);
22955
+ },
22542
22956
  agent: requestedAgent,
22543
22957
  systemPrompt,
22544
22958
  userMessage,
@@ -22551,15 +22965,9 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
22551
22965
  maxOutputTokens: getMaxOutputTokens(),
22552
22966
  accountingSessionId: opts.projectIdentity,
22553
22967
  accountingSubagent: "dreamer",
22554
- accountingTask: accountingTaskFromTitle(dreamSession.title),
22555
- tokenBudget: (() => {
22556
- if (args.tokenBudget !== undefined)
22557
- return args.tokenBudget;
22558
- const task = accountingTaskFromTitle(dreamSession.title);
22559
- if (!task)
22560
- return;
22561
- return buildDreamTaskRuntimeConfigs(getDreamerConfig(), opts.harness).find((entry) => entry.task === task)?.tokenBudget;
22562
- })()
22968
+ accountingTask,
22969
+ accountingModelConfigKey: taskConfig?.modelConfigKey,
22970
+ tokenBudget: args.tokenBudget ?? taskConfig?.tokenBudget
22563
22971
  });
22564
22972
  inFlightDreams.set(runPromise, opts.registrationOwner);
22565
22973
  try {
@@ -23007,6 +23415,13 @@ Unknown task "${requested}".`,
23007
23415
  }
23008
23416
 
23009
23417
  // ../plugin/src/hooks/magic-context/auto-embed-session.ts
23418
+ function localPoolingPreflightPending(projectIdentity) {
23419
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
23420
+ if (snapshot?.provider !== "local")
23421
+ return false;
23422
+ const metadata = getCachedLocalEmbeddingPooling(snapshot.model);
23423
+ return !metadata || metadata.status === "unresolved";
23424
+ }
23010
23425
  function embeddingIdentity(projectIdentity) {
23011
23426
  const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
23012
23427
  return JSON.stringify([
@@ -23027,7 +23442,8 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
23027
23442
  invalidateAutoEmbedSession(sessionId);
23028
23443
  autoEmbedIdentityBySession.set(sessionId, identity);
23029
23444
  }
23030
- if (autoEmbedAttemptedBySession.has(sessionId) || embedPauseBySession.has(sessionId) || embedRunStateBySession.has(sessionId) || Date.now() < (autoEmbedRetryAfterBySession.get(sessionId) ?? 0))
23445
+ const poolingPreflightPending = localPoolingPreflightPending(deps.projectIdentity);
23446
+ if (embedPauseBySession.has(sessionId) || embedRunStateBySession.has(sessionId) || Date.now() < (autoEmbedRetryAfterBySession.get(sessionId) ?? 0) || autoEmbedAttemptedBySession.has(sessionId) && !poolingPreflightPending)
23031
23447
  return;
23032
23448
  const controller = new AbortController;
23033
23449
  embedRunStateBySession.set(sessionId, controller);
@@ -23037,6 +23453,7 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
23037
23453
  let started = false;
23038
23454
  let reason = "error";
23039
23455
  let registeredIdentity = identity;
23456
+ let poolingPendingAfterRegistration = poolingPreflightPending;
23040
23457
  try {
23041
23458
  await new Promise((resolve) => setTimeout(resolve, 0));
23042
23459
  if (controller.signal.aborted)
@@ -23044,6 +23461,7 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
23044
23461
  await deps.ensureRegistered();
23045
23462
  if (controller.signal.aborted)
23046
23463
  return;
23464
+ poolingPendingAfterRegistration = localPoolingPreflightPending(deps.projectIdentity);
23047
23465
  markActive();
23048
23466
  registeredIdentity = embeddingIdentity(deps.projectIdentity);
23049
23467
  autoEmbedIdentityBySession.set(sessionId, registeredIdentity);
@@ -23051,7 +23469,9 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
23051
23469
  if (controller.signal.aborted || !coverage.enabled)
23052
23470
  return;
23053
23471
  if (coverage.embedded === coverage.total) {
23054
- complete = true;
23472
+ complete = !poolingPendingAfterRegistration;
23473
+ if (!complete)
23474
+ retryDelay = 60000;
23055
23475
  return;
23056
23476
  }
23057
23477
  const model = getProjectEmbeddingSnapshot2(deps.projectIdentity)?.model;
@@ -23060,8 +23480,11 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
23060
23480
  const outcome = await embedSessionCompartmentChunks2(deps.db, deps.projectIdentity, sessionId, { signal: controller.signal, automatic: true });
23061
23481
  reason = outcome.status;
23062
23482
  const after = await getAutoEmbeddingSessionCoverage2(deps.db, deps.projectIdentity, sessionId);
23063
- complete = after.enabled && after.embedded === after.total;
23064
- if (!complete && outcome.status !== "busy" && outcome.status !== "aborted") {
23483
+ complete = after.enabled && after.embedded === after.total && !poolingPendingAfterRegistration;
23484
+ if (poolingPendingAfterRegistration) {
23485
+ retryDelay = 60000;
23486
+ reason = "pooling metadata unavailable";
23487
+ } else if (!complete && outcome.status !== "busy" && outcome.status !== "aborted") {
23065
23488
  retryDelay = 60000;
23066
23489
  if (outcome.status === "nothing" || outcome.status === "done")
23067
23490
  reason = "deferred";
@@ -23334,7 +23757,9 @@ function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity) {
23334
23757
  maybeAutoEmbedSessionBackfill({
23335
23758
  db: deps.db,
23336
23759
  projectIdentity,
23337
- ensureRegistered: () => ensureProjectRegisteredFromPiDirectory(projectDir, deps.db)
23760
+ ensureRegistered: () => ensureProjectRegisteredFromPiDirectory(projectDir, deps.db, {
23761
+ preflightLocalPooling: true
23762
+ })
23338
23763
  }, sessionId);
23339
23764
  }
23340
23765
 
@@ -24348,7 +24773,8 @@ function capturePendingDropEligibility(targets, protectedTagIds) {
24348
24773
  eligible.add(number);
24349
24774
  } else {
24350
24775
  const content = target.getContent?.();
24351
- if (typeof content === "string" && content.length > `[dropped §${number}§]`.length)
24776
+ const replacement = `[dropped §${number}§]`;
24777
+ if (typeof content === "string" && content.length > replacement.length && target.canSetContent?.(replacement) !== false)
24352
24778
  eligible.add(number);
24353
24779
  }
24354
24780
  }
@@ -24635,12 +25061,16 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
24635
25061
  }
24636
25062
  } else if (target) {
24637
25063
  const replacement = buildReplacementContent(pendingOp.tagId);
25064
+ if (target.canSetContent?.(replacement) === false) {
25065
+ reject("content_unchanged");
25066
+ continue;
25067
+ }
24638
25068
  persistDrop();
24639
25069
  mutations.push(() => {
24640
25070
  const priorContent = target.getContent?.();
24641
25071
  const changed = target.setContent(replacement);
24642
- record(changed);
24643
25072
  if (changed) {
25073
+ record(true);
24644
25074
  const originalCharacters = typeof priorContent === "string" ? priorContent.length : tagById.get(pendingOp.tagId)?.byteSize ?? replacement.length;
24645
25075
  onTagReduced?.({
24646
25076
  tagNumber: pendingOp.tagId,
@@ -24731,7 +25161,7 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
24731
25161
 
24732
25162
  // ../plugin/src/hooks/magic-context/cache-busting-signals.ts
24733
25163
  function hasReclaimRide(signals) {
24734
- return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory || signals.subagentExecute === true;
25164
+ return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory || signals.subagentExecute === true || signals.executeReclaim === true || signals.servedShapeRepair === true;
24735
25165
  }
24736
25166
  function prefixMutationPermitted(gate) {
24737
25167
  return !gate.signedThinkingHold || gate.firstRender || gate.idleExpiry || gate.emergency;
@@ -24744,7 +25174,9 @@ var RECLAIM_RIDE_NAMES = [
24744
25174
  "force",
24745
25175
  "explicitFlush",
24746
25176
  "publishedHistory",
24747
- "subagentExecute"
25177
+ "subagentExecute",
25178
+ "executeReclaim",
25179
+ "servedShapeRepair"
24748
25180
  ];
24749
25181
  function reclaimRideLabel(signals) {
24750
25182
  const active = RECLAIM_RIDE_NAMES.filter((name) => signals[name]);
@@ -24977,6 +25409,140 @@ function rearmChannel2AfterMeasuredCollapse(input) {
24977
25409
  return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
24978
25410
  }
24979
25411
 
25412
+ // ../plugin/src/hooks/magic-context/postprocess-read-cache.ts
25413
+ var connections = new WeakMap;
25414
+ function snapshot(db, sessionId) {
25415
+ const transaction = db;
25416
+ try {
25417
+ if (transaction.inTransaction || transaction.isTransaction) {
25418
+ connections.delete(db);
25419
+ return { version: -1, changes: -1 };
25420
+ }
25421
+ } catch {
25422
+ connections.delete(db);
25423
+ return { version: -1, changes: -1 };
25424
+ }
25425
+ let connection = connections.get(db);
25426
+ if (!connection) {
25427
+ connection = {
25428
+ stamp: db.prepare("SELECT total_changes() AS changes, data_version AS version FROM pragma_data_version"),
25429
+ sessions: new BoundedSessionMap(100)
25430
+ };
25431
+ connections.set(db, connection);
25432
+ }
25433
+ const stamp = connection.stamp.get();
25434
+ const previous = connection.sessions.get(sessionId);
25435
+ if (previous?.version === stamp.version && previous.changes === stamp.changes) {
25436
+ return previous;
25437
+ }
25438
+ const value = { ...stamp };
25439
+ connection.sessions.set(sessionId, value);
25440
+ return value;
25441
+ }
25442
+ function postprocessReplaySnapshot(db, sessionId) {
25443
+ const state = snapshot(db, sessionId);
25444
+ const replay = state.replay ??= loadPostprocessReplaySnapshot(db, sessionId);
25445
+ return {
25446
+ ...replay,
25447
+ staleReduceStrippedIds: new Set(replay.staleReduceStrippedIds),
25448
+ processedImageStrippedIds: new Set(replay.processedImageStrippedIds),
25449
+ processedImageMarkers: new Map(replay.processedImageMarkers),
25450
+ strippedPlaceholderIds: new Set(replay.strippedPlaceholderIds),
25451
+ hiddenSeamPlaceholderIds: new Set(replay.hiddenSeamPlaceholderIds),
25452
+ mergedReasoningStrippedIds: new Set(replay.mergedReasoningStrippedIds),
25453
+ trailingBlankDecisions: new Map(replay.trailingBlankDecisions),
25454
+ noteNudgeAnchors: structuredClone(replay.noteNudgeAnchors),
25455
+ autoSearchHintDecisions: structuredClone(replay.autoSearchHintDecisions),
25456
+ todoSyntheticAnchor: structuredClone(replay.todoSyntheticAnchor),
25457
+ pendingCompactionMarker: structuredClone(replay.pendingCompactionMarker),
25458
+ compactionMarker: structuredClone(replay.compactionMarker)
25459
+ };
25460
+ }
25461
+
25462
+ // ../plugin/src/hooks/magic-context/execute-reclaim.ts
25463
+ var NAMESPACE2 = "executeReclaim";
25464
+ var failedWrites = new WeakMap;
25465
+ function readExecuteReclaimState(db, sessionId) {
25466
+ return parseState2(postprocessReplaySnapshot(db, sessionId).executeReclaim);
25467
+ }
25468
+ function parseState2(lane) {
25469
+ const value = lane;
25470
+ return {
25471
+ heldPasses: typeof value?.heldPasses === "number" ? Math.max(0, value.heldPasses) : 0,
25472
+ floorOrdinal: typeof value?.floorOrdinal === "number" ? value.floorOrdinal : null,
25473
+ floorPromptId: typeof value?.floorPromptId === "string" ? value.floorPromptId : null
25474
+ };
25475
+ }
25476
+ function writeExecuteReclaimState(db, sessionId, patch) {
25477
+ if (failedWrites.get(db)?.has(sessionId))
25478
+ return false;
25479
+ try {
25480
+ const current = readExecuteReclaimState(db, sessionId);
25481
+ if (JSON.stringify(current) === JSON.stringify({ ...current, ...patch }))
25482
+ return true;
25483
+ if (!updateReplayDocument(db, sessionId, (doc) => {
25484
+ const previous = parseState2(doc[NAMESPACE2]);
25485
+ const state = { ...previous, ...patch };
25486
+ if (JSON.stringify(previous) === JSON.stringify(state))
25487
+ return false;
25488
+ doc.version = 2;
25489
+ doc[NAMESPACE2] = state;
25490
+ return true;
25491
+ }))
25492
+ throw new Error("Could not persist execute reclaim state");
25493
+ return true;
25494
+ } catch (error) {
25495
+ let failed = failedWrites.get(db);
25496
+ if (!failed)
25497
+ failedWrites.set(db, failed = new Set);
25498
+ failed.add(sessionId);
25499
+ sessionLog2(sessionId, `execute reclaim state persistence failed; retaining existing policy: ${String(error)}`);
25500
+ return false;
25501
+ }
25502
+ }
25503
+ function clearExecuteReclaimState(db, sessionId) {
25504
+ writeExecuteReclaimState(db, sessionId, {
25505
+ heldPasses: 0,
25506
+ floorOrdinal: null,
25507
+ floorPromptId: null
25508
+ });
25509
+ }
25510
+ function maintainExecuteFloorMark(db, sessionId, promptId, belowExecute) {
25511
+ failedWrites.get(db)?.delete(sessionId);
25512
+ const state = readExecuteReclaimState(db, sessionId);
25513
+ if (state.floorOrdinal !== null && (belowExecute || promptId !== null && promptId !== state.floorPromptId)) {
25514
+ writeExecuteReclaimState(db, sessionId, { floorOrdinal: null, floorPromptId: null });
25515
+ }
25516
+ }
25517
+ function estimateExecuteReclaimTokens(args) {
25518
+ const eligible = capturePendingDropEligibility(args.targets, args.protectedTagIds);
25519
+ const queued = new Set(args.pendingOps.filter((op) => op.operation === "drop").map((op) => op.tagId));
25520
+ const candidates = args.tags.filter((tag) => tag.status === "active" && queued.has(tag.tagNumber) && eligible.has(tag.tagNumber));
25521
+ const preparationTargets = new Map;
25522
+ for (const tag of candidates) {
25523
+ const target = args.targets.get(tag.tagNumber);
25524
+ if (target?.prepareDrop)
25525
+ preparationTargets.set(tag.tagNumber, target);
25526
+ }
25527
+ const prepared = preparationTargets.size === 0 ? new Set : args.probePreparation?.(preparationTargets) ?? new Set([...preparationTargets].filter(([, target]) => target.prepareDrop?.() !== false).map(([number]) => number));
25528
+ const seed = sessionDecisionCalibration(args.db, args.sessionId);
25529
+ return candidates.reduce((total, tag) => {
25530
+ if (preparationTargets.has(tag.tagNumber) && !prepared.has(tag.tagNumber))
25531
+ return total;
25532
+ const ratio = tag.type === "tool" ? seed.toolsRatio : seed.proseRatio;
25533
+ return total + Math.max(0, (tag.tokenCount ?? Math.ceil(tag.byteSize / 4)) * ratio);
25534
+ }, 0);
25535
+ }
25536
+ function originateExecuteReclaim(args) {
25537
+ if (failedWrites.get(args.db)?.has(args.sessionId))
25538
+ return false;
25539
+ const state = readExecuteReclaimState(args.db, args.sessionId);
25540
+ const heldPasses = args.primaryExecute && args.reclaimableTokens > 0 && !args.alreadyBusting ? state.heldPasses + 1 : 0;
25541
+ if (!writeExecuteReclaimState(args.db, args.sessionId, { heldPasses }))
25542
+ return false;
25543
+ return args.primaryExecute && !args.alreadyBusting && !args.summaryCanCome && args.reclaimableTokens > 0 && (args.usableWindow > 0 && args.reclaimableTokens >= args.usableWindow * 0.02 || heldPasses >= 3);
25544
+ }
25545
+
24980
25546
  // ../plugin/src/hooks/magic-context/file-token-coverage.ts
24981
25547
  function omitIncompleteFileTokenTotals(db, sessionId, messages, totals) {
24982
25548
  const filesByMessage = new Map;
@@ -25364,7 +25930,8 @@ function resolveProtectedTailBoundary(ctx) {
25364
25930
  break;
25365
25931
  }
25366
25932
  livePromptFloor.ordinal = lastMeaningfulUserOrdinal || null;
25367
- if (lastMeaningfulUserOrdinal >= offset) {
25933
+ livePromptFloor.messageId = boundaryMessageId(index, lastMeaningfulUserOrdinal);
25934
+ if (!ctx.liftLivePromptFloor && lastMeaningfulUserOrdinal >= offset) {
25368
25935
  protectedTailStart = Math.min(protectedTailStart, lastMeaningfulUserOrdinal);
25369
25936
  }
25370
25937
  }
@@ -25492,6 +26059,7 @@ function resolveBoundaryContext(args) {
25492
26059
  protectedTailPolicyVersion: meta.protectedTailPolicyVersion,
25493
26060
  migrationFloorActive,
25494
26061
  emergencyTailScale: args.emergencyTailScale,
26062
+ liftLivePromptFloor: args.liftLivePromptFloor,
25495
26063
  providerShapeVersion: args.providerShapeVersion ?? "opencode-v1",
25496
26064
  cacheNamespace: args.cacheNamespace ?? `opencode:${args.sessionId}`,
25497
26065
  storedTokenTotalsForMessages,
@@ -25873,7 +26441,7 @@ function resolveBoundaryContextLimit(usage, fallbackContextLimit) {
25873
26441
  }
25874
26442
  return 128000;
25875
26443
  }
25876
- function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor = 0) {
26444
+ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor = 0, liftLivePromptFloor = false) {
25877
26445
  return withRawSessionMessageCache2(() => {
25878
26446
  try {
25879
26447
  const memoryPrimed = inMemoryTail ? primeInMemoryTailRawMessageCache2({
@@ -25903,7 +26471,8 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
25903
26471
  executeThresholdPercentage,
25904
26472
  usage,
25905
26473
  usageSource: "live",
25906
- taggerFloor
26474
+ taggerFloor,
26475
+ liftLivePromptFloor
25907
26476
  });
25908
26477
  const hasProtectedEligibleHead = boundary.offset < Math.min(boundary.protectedTailStart, boundary.eligibleEndOrdinal);
25909
26478
  if (!hasProtectedEligibleHead) {
@@ -25939,7 +26508,10 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
25939
26508
  function formatProjectedPostDropPercentage(value) {
25940
26509
  return value === null ? "none" : `${value.toFixed(1)}%`;
25941
26510
  }
25942
- function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, keepReasoningTokens, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection, reclaimRide, eligiblePendingDropTagIds) {
26511
+ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, keepReasoningTokens, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection, reclaimRide, eligiblePendingDropTagIds, primaryExecute = false) {
26512
+ if (usage.percentage < executeThresholdPercentage) {
26513
+ writeExecuteReclaimState(db, sessionId, { floorOrdinal: null, floorPromptId: null });
26514
+ }
25943
26515
  if (sessionMeta.compartmentInProgress) {
25944
26516
  sessionLog2(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
25945
26517
  return { shouldFire: false };
@@ -25992,7 +26564,22 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
25992
26564
  resolvedInMemoryTail = undefined;
25993
26565
  }
25994
26566
  }
25995
- const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor);
26567
+ let tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor);
26568
+ const markState = readExecuteReclaimState(db, sessionId);
26569
+ const mark = markState.floorOrdinal;
26570
+ const livePromptOrdinal = tailInfo.boundarySnapshot?.diagnostics?.livePromptFloor.ordinal;
26571
+ let consumedFloorMark = false;
26572
+ if (mark !== null) {
26573
+ const consumed = writeExecuteReclaimState(db, sessionId, {
26574
+ floorOrdinal: null,
26575
+ floorPromptId: null
26576
+ });
26577
+ if (consumed && mark === livePromptOrdinal && markState.floorPromptId === tailInfo.boundarySnapshot?.diagnostics?.livePromptFloor.messageId && usage.percentage >= executeThresholdPercentage) {
26578
+ consumedFloorMark = true;
26579
+ sessionLog2(sessionId, `compartment trigger: live-prompt floor mark consumed at ${mark}`);
26580
+ tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor, true);
26581
+ }
26582
+ }
25996
26583
  if (!tailInfo.hasNewRawHistory) {
25997
26584
  try {
25998
26585
  const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
@@ -26076,7 +26663,21 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
26076
26663
  return { shouldFire: false };
26077
26664
  }
26078
26665
  if (!tailInfo.hasProtectedEligibleHead || !tailInfo.isMeaningful) {
26079
- sessionLog2(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% because unsummarized tail from ${tailInfo.nextStartOrdinal} is too small`);
26666
+ let floorOnly = false;
26667
+ const boundary = tailInfo.boundarySnapshot;
26668
+ const floor = boundary?.diagnostics?.livePromptFloor;
26669
+ if (!consumedFloorMark && floor?.ordinal && floor.from > floor.to) {
26670
+ const withoutFloor = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor, true);
26671
+ floorOnly = withoutFloor.hasProtectedEligibleHead && withoutFloor.isMeaningful;
26672
+ if (floorOnly && primaryExecute && usage.percentage >= executeThresholdPercentage && writeExecuteReclaimState(db, sessionId, {
26673
+ floorOrdinal: floor.ordinal,
26674
+ floorPromptId: floor.messageId ?? null
26675
+ })) {
26676
+ sessionLog2(sessionId, `compartment trigger: live-prompt floor mark set at ${floor.ordinal}`);
26677
+ }
26678
+ }
26679
+ const refusal = floorOnly ? `no eligible head (live-prompt floor at ${floor?.ordinal})` : tailInfo.hasProtectedEligibleHead ? "below meaningfulness" : "no eligible head";
26680
+ sessionLog2(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% — ${refusal}; offset=${tailInfo.nextStartOrdinal} protectedStart=${boundary?.protectedTailStart ?? "none"} eligibleEnd=${boundary?.eligibleEndOrdinal ?? "none"} rawTokens=${tailInfo.trueRawEligibleTokens} chunkTokens=${tailInfo.tokenEstimate}`);
26080
26681
  return { shouldFire: false };
26081
26682
  }
26082
26683
  sessionLog2(sessionId, `compartment trigger: proactive fire at ${usage.percentage.toFixed(1)}% (floor=${proactiveTriggerPercentage}% projected post-drop=${formatProjectedPostDropPercentage(projectedPostDropPercentage)} target=${relativePostDropTarget.toFixed(1)}%)`);
@@ -26245,6 +26846,9 @@ function latestAssistantTurnStart(messages) {
26245
26846
  function latestAssistantTurnMessages(messages) {
26246
26847
  return new Set(messages.slice(latestAssistantTurnStart(messages)));
26247
26848
  }
26849
+ function isAnthropicThinkingPart(part, familyRoute) {
26850
+ return isRecord(part) && THINKING_TYPES.has(String(part.type ?? part.kind)) && (familyRoute || isRecord(part.metadata) && isRecord(part.metadata.anthropic));
26851
+ }
26248
26852
  function hasActiveAnthropicThinkingTurn(messages, provider, model) {
26249
26853
  const familyRoute = isAnthropicFamilyRoute(provider, model);
26250
26854
  for (const message of messages.slice(latestAssistantTurnStart(messages))) {
@@ -26253,7 +26857,7 @@ function hasActiveAnthropicThinkingTurn(messages, provider, model) {
26253
26857
  const parts = content(message);
26254
26858
  if (!Array.isArray(parts))
26255
26859
  continue;
26256
- if (parts.some((part) => isRecord(part) && THINKING_TYPES.has(String(part.type ?? part.kind)) && (familyRoute || isRecord(part.metadata) && isRecord(part.metadata.anthropic))))
26860
+ if (parts.some((part) => isAnthropicThinkingPart(part, familyRoute)))
26257
26861
  return true;
26258
26862
  }
26259
26863
  return false;
@@ -27141,6 +27745,7 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
27141
27745
  db,
27142
27746
  targets,
27143
27747
  skipPrefixInjection,
27748
+ preserveTagOnlyAssistantText: options.preserveTagOnlyAssistantText,
27144
27749
  entryFingerprint: options.entryFingerprintByMessageId?.get(messageId) ?? null,
27145
27750
  reuseIdentity: reuseIdentity || contentDerivedTextIds !== undefined,
27146
27751
  timing,
@@ -27532,7 +28137,7 @@ function isRecord2(value) {
27532
28137
  function tagTextPart(args) {
27533
28138
  const identityStart = args.timing ? performance.now() : 0;
27534
28139
  const text = args.part.getText() ?? "";
27535
- if (args.message.info.role === "assistant" && stripWellFormedLeadingTagPrefix(text).trim().length === 0) {
28140
+ if (args.message.info.role === "assistant" && (stripWellFormedLeadingTagPrefix(text).trim().length === 0 || args.preserveTagOnlyAssistantText && text.includes("§") && stripPersistedAssistantText(text).length === 0)) {
27536
28141
  if (args.timing)
27537
28142
  args.timing.identity += performance.now() - identityStart;
27538
28143
  return;
@@ -28022,7 +28627,8 @@ ${trimmedBody}…
28022
28627
  return wrapped;
28023
28628
  }
28024
28629
  function selectAutoSearchResults(results, threshold) {
28025
- return results.filter((result) => (result.relevanceScore ?? result.score) >= threshold);
28630
+ const relevance = (result) => result.relevanceScore ?? result.score;
28631
+ return results.filter((result) => relevance(result) >= threshold).sort((left, right) => relevance(right) - relevance(left));
28026
28632
  }
28027
28633
 
28028
28634
  // ../plugin/src/hooks/magic-context/auto-search-worker-client.ts
@@ -28115,22 +28721,42 @@ function retryUnpublishedAutoSearchNoHint(db, sessionId, messageId, startedAt) {
28115
28721
  }
28116
28722
  return true;
28117
28723
  }
28724
+
28725
+ class AutoSearchBusyError extends Error {
28726
+ constructor() {
28727
+ super("an earlier auto-search of this session is still running");
28728
+ this.name = "AutoSearchBusyError";
28729
+ }
28730
+ }
28118
28731
  async function searchAutoHint(db, sessionId, projectPath, query, options, entry = new URL(new URL(import.meta.url).pathname.endsWith(".ts") ? "./auto-search-worker.ts" : "./auto-search-worker.js", import.meta.url)) {
28119
- return executeAutoSearchWorker(db, sessionId, projectPath, query, options, entry, "search");
28732
+ const {
28733
+ rerankConfig: _rerankConfig,
28734
+ rerankClient: _rerankClient,
28735
+ rerankConnectionFile: _rerankConnectionFile,
28736
+ onRerankSkipped: _onRerankSkipped,
28737
+ captureRerankLanes: _captureRerankLanes,
28738
+ ...hintOptions
28739
+ } = options;
28740
+ return executeAutoSearchWorker(db, sessionId, projectPath, query, { ...hintOptions, explicitSearch: false, rerank: false }, entry, "search");
28120
28741
  }
28121
28742
  var pendingBackfills = new WeakMap;
28122
28743
  var searchWorkers = new WeakMap;
28123
28744
  var liveSearchWorkers = new Set;
28124
28745
  var MAX_IDLE_SEARCH_WORKERS = 4;
28125
28746
  var SEARCH_WORKER_IDLE_MS = 5 * 60000;
28747
+ var DETACHED_SEARCH_LIMIT_MS = 30000;
28748
+ var AUTO_SEARCH_WORKER_CLOSE_DEADLINE_MS = 2000;
28126
28749
  var workersCreated = 0;
28127
28750
  var workersReused = 0;
28751
+ var searchesSkippedBusy = 0;
28128
28752
  async function acquireSearchWorker(db, key, entry, input, signal) {
28129
28753
  const pool = searchWorkers.get(db) ?? new Map;
28130
28754
  searchWorkers.set(db, pool);
28131
28755
  while (!signal.aborted) {
28132
28756
  let slot = pool.get(key);
28133
28757
  if (slot?.busy) {
28758
+ if (input.job === "search" && (slot.detached || slot.busySessionId === input.sessionId))
28759
+ return "busy";
28134
28760
  const current = slot;
28135
28761
  await new Promise((resolve) => {
28136
28762
  const done = () => {
@@ -28139,6 +28765,8 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28139
28765
  };
28140
28766
  signal.addEventListener("abort", done, { once: true });
28141
28767
  current.busy?.then(done);
28768
+ if (!current.detached)
28769
+ current.detachedSignal?.then(done);
28142
28770
  if (signal.aborted)
28143
28771
  done();
28144
28772
  });
@@ -28147,14 +28775,16 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28147
28775
  const fresh = !slot;
28148
28776
  if (!slot) {
28149
28777
  const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: { ...input, persistent: true } }));
28778
+ const shutdown = createWorkerShutdown(worker, "auto-search", AUTO_SEARCH_WORKER_CLOSE_DEADLINE_MS);
28150
28779
  slot = {
28151
28780
  worker,
28152
28781
  dispose() {
28782
+ this.disposed = true;
28153
28783
  clearTimeout(this.idleTimer);
28154
28784
  if (pool.get(key) === this)
28155
28785
  pool.delete(key);
28156
28786
  liveSearchWorkers.delete(this);
28157
- worker.terminate();
28787
+ shutdown.close();
28158
28788
  worker.unref();
28159
28789
  }
28160
28790
  };
@@ -28168,9 +28798,14 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28168
28798
  workersReused++;
28169
28799
  clearTimeout(slot.idleTimer);
28170
28800
  const current = slot;
28801
+ current.busySessionId = input.sessionId;
28802
+ current.detached = false;
28171
28803
  current.busy = new Promise((resolve) => {
28172
28804
  current.release = resolve;
28173
28805
  });
28806
+ current.detachedSignal = new Promise((resolve) => {
28807
+ current.markDetached = resolve;
28808
+ });
28174
28809
  current.worker.ref();
28175
28810
  return { slot: current, fresh };
28176
28811
  }
@@ -28179,6 +28814,9 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28179
28814
  function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
28180
28815
  if (isEmbeddingHostBusy2())
28181
28816
  return Promise.resolve();
28817
+ const snapshot = getProjectEmbeddingSnapshot2(projectPath);
28818
+ if (!snapshot?.enabled || !snapshot.features.memoryEnabled)
28819
+ return Promise.resolve();
28182
28820
  const key = `${sessionId}\x00${projectPath}`;
28183
28821
  const pending = pendingBackfills.get(db) ?? new Map;
28184
28822
  pendingBackfills.set(db, pending);
@@ -28226,6 +28864,7 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28226
28864
  signal: deadlineSignal,
28227
28865
  readMessages: _readMessages,
28228
28866
  searchMessageHistory: _searchMessageHistory,
28867
+ stepTimings: _stepTimings,
28229
28868
  ...serializable
28230
28869
  } = options;
28231
28870
  const lifecycle = registerAutoSearchWork(sessionId);
@@ -28261,30 +28900,55 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28261
28900
  lifecycle.done();
28262
28901
  return [];
28263
28902
  }
28903
+ if (lease === "busy") {
28904
+ lifecycle.done();
28905
+ searchesSkippedBusy++;
28906
+ throw new AutoSearchBusyError;
28907
+ }
28264
28908
  const { slot, fresh } = lease;
28265
28909
  const worker = slot.worker;
28910
+ const detachable = job === "search" && entry.href === defaultAutoSearchWorkerEntry().href;
28911
+ const startedAt = performance.now();
28912
+ let detachedAt;
28913
+ let ownerVectorMs;
28914
+ let abandonTimer;
28266
28915
  return new Promise((resolve, reject) => {
28267
28916
  let settled = false;
28268
- const finish = (results, error) => {
28917
+ let released = false;
28918
+ const settle = (results, error) => {
28269
28919
  if (settled)
28270
28920
  return;
28271
28921
  settled = true;
28922
+ if (error)
28923
+ reject(error);
28924
+ else
28925
+ resolve(results);
28926
+ };
28927
+ const release = (dispose) => {
28928
+ if (released)
28929
+ return;
28930
+ released = true;
28931
+ clearTimeout(abandonTimer);
28272
28932
  signal?.removeEventListener("abort", abort);
28273
28933
  lifecycle.signal.removeEventListener("abort", abort);
28274
28934
  lifecycle.done();
28275
28935
  worker.off("message", onMessage);
28276
28936
  worker.off("error", onError);
28277
28937
  worker.off("exit", onExit);
28278
- if (error || signal.aborted || entry.href !== defaultAutoSearchWorkerEntry().href)
28938
+ if (dispose || !detachable)
28279
28939
  slot.dispose();
28280
- else {
28940
+ else if (!slot.disposed) {
28281
28941
  slot.idleTimer = setTimeout(() => slot.dispose(), SEARCH_WORKER_IDLE_MS);
28282
28942
  slot.idleTimer.unref?.();
28283
28943
  }
28284
- const release = slot.release;
28944
+ const free = slot.release;
28285
28945
  slot.busy = undefined;
28286
28946
  slot.release = undefined;
28287
- release?.();
28947
+ slot.busySessionId = undefined;
28948
+ slot.detached = false;
28949
+ slot.detachedSignal = undefined;
28950
+ slot.markDetached = undefined;
28951
+ free?.();
28288
28952
  const reusable = liveSearchWorkers.delete(slot);
28289
28953
  if (reusable)
28290
28954
  liveSearchWorkers.add(slot);
@@ -28292,51 +28956,82 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28292
28956
  for (const prior of idle.slice(0, Math.max(0, idle.length - MAX_IDLE_SEARCH_WORKERS)))
28293
28957
  prior.dispose();
28294
28958
  worker.unref();
28295
- if (error)
28296
- reject(error);
28297
- else
28298
- resolve(results);
28299
28959
  };
28300
- const abort = () => finish([]);
28960
+ const finish = (results, error) => {
28961
+ settle(results, error);
28962
+ release(Boolean(error) || signal.aborted);
28963
+ };
28964
+ const abort = () => {
28965
+ if (lifecycle.signal.aborted || !detachable) {
28966
+ finish([]);
28967
+ return;
28968
+ }
28969
+ if (settled)
28970
+ return;
28971
+ detachedAt = performance.now();
28972
+ slot.detached = true;
28973
+ slot.markDetached?.();
28974
+ settle([]);
28975
+ abandonTimer = setTimeout(() => {
28976
+ log2(`[auto-search] session ${sessionId}: search still running ${DETACHED_SEARCH_LIMIT_MS} ms after its deadline; disposing its worker (owner vector wait ${formatMs(ownerVectorMs)})`);
28977
+ release(true);
28978
+ }, DETACHED_SEARCH_LIMIT_MS);
28979
+ abandonTimer.unref?.();
28980
+ };
28301
28981
  signal?.addEventListener("abort", abort, { once: true });
28302
28982
  lifecycle.signal.addEventListener("abort", abort, { once: true });
28303
28983
  const onError = (error) => finish([], error);
28304
28984
  const onExit = (code) => finish([], new Error(`auto-search worker exited (${code})`));
28305
28985
  const onMessage = async (reply) => {
28306
- if (settled)
28986
+ if (released)
28307
28987
  return;
28308
- if (reply.kind === "result") {
28988
+ if (reply.kind === "result" || reply.kind === "error") {
28989
+ if (detachedAt !== undefined) {
28990
+ logLateSearch(sessionId, performance.now() - detachedAt, detachedAt - startedAt, ownerVectorMs, reply.kind === "result" ? reply.timings : undefined, reply.kind === "error");
28991
+ release(reply.kind === "error");
28992
+ return;
28993
+ }
28994
+ if (reply.kind === "error") {
28995
+ finish([], new Error(reply.error));
28996
+ return;
28997
+ }
28309
28998
  if (snapshot && getProjectEmbeddingSnapshot2(projectPath)?.generation !== snapshot.generation)
28310
28999
  finish([]);
28311
29000
  else
28312
29001
  finish(reply.results);
28313
29002
  return;
28314
29003
  }
28315
- if (reply.kind === "error") {
28316
- finish([], new Error(reply.error));
28317
- return;
28318
- }
28319
29004
  if (reply.kind === "messages" || reply.kind === "accepted")
28320
29005
  return;
28321
29006
  const response = { id: reply.id };
28322
- try {
29007
+ if (!signal.aborted) {
29008
+ const requestedAt = performance.now();
29009
+ try {
29010
+ if (reply.kind === "query")
29011
+ response.result = await (job === "backfill" ? embedTextForProject2(projectPath, reply.text, signal, "query") : boundedHintEmbedding(embedQuery, reply.text, signal)) ?? null;
29012
+ else {
29013
+ const passage = await embedBatchForProject2(projectPath, reply.texts, signal, reply.purpose);
29014
+ const current = getProjectEmbeddingSnapshot2(projectPath);
29015
+ response.passage = passage && current ? {
29016
+ ...passage,
29017
+ providerIdentity: current.providerIdentity,
29018
+ runtimeFingerprint: current.runtimeFingerprint,
29019
+ dimensions: passage.vectors.find((vector) => vector !== null)?.length ?? null
29020
+ } : null;
29021
+ }
29022
+ } catch (error) {
29023
+ response.error = error instanceof Error ? error.message : String(error);
29024
+ }
28323
29025
  if (reply.kind === "query")
28324
- response.result = await (job === "backfill" ? embedTextForProject2(projectPath, reply.text, signal, "query") : boundedHintEmbedding(embedQuery, reply.text, signal)) ?? null;
28325
- else {
28326
- const passage = await embedBatchForProject2(projectPath, reply.texts, signal, reply.purpose);
28327
- const current = getProjectEmbeddingSnapshot2(projectPath);
28328
- response.passage = passage && current ? {
28329
- ...passage,
28330
- providerIdentity: current.providerIdentity,
28331
- runtimeFingerprint: current.runtimeFingerprint,
28332
- dimensions: passage.vectors.find((vector) => vector !== null)?.length ?? null
28333
- } : null;
29026
+ ownerVectorMs = performance.now() - requestedAt;
29027
+ if (signal.aborted) {
29028
+ response.result = undefined;
29029
+ response.passage = undefined;
29030
+ response.error = undefined;
28334
29031
  }
28335
- } catch (error) {
28336
- response.error = error instanceof Error ? error.message : String(error);
28337
29032
  }
28338
29033
  response.embeddingHostBusy = isEmbeddingHostBusy2();
28339
- if (!settled && !signal?.aborted) {
29034
+ if (!released) {
28340
29035
  try {
28341
29036
  worker.postMessage(response);
28342
29037
  } catch (error) {
@@ -28358,6 +29053,15 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28358
29053
  }
28359
29054
  });
28360
29055
  }
29056
+ function formatMs(value) {
29057
+ return value === undefined ? "n/a" : `${Math.round(value)} ms`;
29058
+ }
29059
+ function logLateSearch(sessionId, lateMs, waitedMs, ownerVectorMs, timings, failed) {
29060
+ const steps = timings?.steps;
29061
+ const warm = timings?.lastPoolWarm;
29062
+ const pool = warm ? `last pool refresh ${warm.outcome} in ${formatMs(warm.totalMs)} (probe ${formatMs(warm.probeMs)}, read ${formatMs(warm.readMs)}, decode ${formatMs(warm.decodeMs)}, ${warm.probedRows} rows probed, ${warm.decodedRows} decoded)` : "no pool refresh yet";
29063
+ log2(`[auto-search] session ${sessionId}: deadline passed after ${formatMs(waitedMs)}; the search ${failed ? "failed" : "finished"} ${formatMs(lateMs)} later. Steps: message FTS ${formatMs(steps?.messageMs)}, vector wait ${formatMs(steps?.vectorWaitMs)} (owner embedding ${formatMs(ownerVectorMs)}), chunk lane ${formatMs(steps?.chunkMs)} (pool ${steps?.chunkPool ?? "n/a"}), other lanes ${formatMs(steps?.otherLanesMs)}, job ${formatMs(timings?.jobMs)}; ${pool}`);
29064
+ }
28361
29065
  async function boundedHintEmbedding(embed, text, signal) {
28362
29066
  const controller = new AbortController;
28363
29067
  const combined = AbortSignal.any([signal, controller.signal]);
@@ -28581,7 +29285,8 @@ async function runAutoSearchHintForPi(args) {
28581
29285
  },
28582
29286
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
28583
29287
  visibleMemoryIds: options.visibleMemoryIds ?? null,
28584
- sources: ["memory", "message", "git_commit"]
29288
+ sources: ["memory", "message", "git_commit"],
29289
+ chunkPoolWarmOnly: true
28585
29290
  };
28586
29291
  return searchAutoHint(db, sessionId, options.projectPath, rawPrompt, {
28587
29292
  ...searchOptions,
@@ -28593,6 +29298,11 @@ async function runAutoSearchHintForPi(args) {
28593
29298
  args.passGuard?.assert();
28594
29299
  if (lifecycleSignal.aborted)
28595
29300
  return messages;
29301
+ if (error instanceof AutoSearchBusyError) {
29302
+ sessionLog2(sessionId, "auto-search: an earlier search of this session is still running, skipping hint for this turn");
29303
+ persistAutoSearchSkip(db, sessionId, userMsgId);
29304
+ return messages;
29305
+ }
28596
29306
  log2(`[auto-search] unified search failed for session ${sessionId} (no-hint frozen for this turn): ${error instanceof Error ? error.message : String(error)}`);
28597
29307
  await writeNoHintAndReconcile("error");
28598
29308
  return messages;
@@ -28644,7 +29354,7 @@ ${hintText}`;
28644
29354
  if (outcome.decision.decision === "hint") {
28645
29355
  appendHintToUserMessage(userMsg, outcome.decision.text);
28646
29356
  }
28647
- sessionLog2(sessionId, `auto-search: attached hint to ${userMsgId} (${results.length} fragments, top score ${results[0].score.toFixed(3)})`);
29357
+ sessionLog2(sessionId, `auto-search: attached hint to ${userMsgId} (${results.length} fragments, top relevance ${(results[0].relevanceScore ?? results[0].score).toFixed(3)})`);
28648
29358
  return messages;
28649
29359
  } finally {
28650
29360
  if (!lifecycleSignal.aborted && results !== null) {
@@ -28680,19 +29390,19 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
28680
29390
  const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectPath);
28681
29391
  for (const compartment of compartments) {
28682
29392
  try {
28683
- const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
28684
- const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
29393
+ const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding2(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
29394
+ const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts2(db, sessionId, compartment.startMessage, compartment.endMessage);
28685
29395
  if (mappedText === null)
28686
29396
  continue;
28687
- const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, compartment.id);
29397
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText2(db, compartment.id);
28688
29398
  if (canonicalText.length === 0)
28689
29399
  continue;
28690
- const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
29400
+ const windows = chunkCanonicalText2(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
28691
29401
  if (windows.length === 0)
28692
29402
  continue;
28693
- const windowSourceKey = chunkWindowSourceKey(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
29403
+ const windowSourceKey = chunkWindowSourceKey2(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
28694
29404
  const currentModelId = getProjectChunkEmbeddingModelId2(projectPath);
28695
- if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
29405
+ if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent2(db, compartment.id, currentModelId, windows, projectPath)) {
28696
29406
  continue;
28697
29407
  }
28698
29408
  const result = await embedItemsForProject2(projectPath, windows.map((window) => ({
@@ -28702,7 +29412,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
28702
29412
  })), undefined, db, sessionId);
28703
29413
  if (!result)
28704
29414
  continue;
28705
- if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
29415
+ if (chunkEmbeddingWindowsAreCurrent2(db, compartment.id, currentModelId, windows, projectPath)) {
28706
29416
  continue;
28707
29417
  }
28708
29418
  const rows = [];
@@ -28720,7 +29430,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
28720
29430
  });
28721
29431
  }
28722
29432
  if (rows.length === windows.length) {
28723
- replaceCompartmentChunkEmbeddings(db, rows, windowSourceKey);
29433
+ replaceCompartmentChunkEmbeddings2(db, rows, windowSourceKey);
28724
29434
  enqueueShadowEmbeddingItems2(projectPath, "chunk", [String(compartment.id)]);
28725
29435
  }
28726
29436
  } catch (error) {
@@ -29489,7 +30199,8 @@ ${chunkText}`,
29489
30199
  maxOutputTokens,
29490
30200
  onProgress: buildProgressLogger("first"),
29491
30201
  accountingSessionId: sessionId,
29492
- accountingSubagent: "historian"
30202
+ accountingSubagent: "historian",
30203
+ accountingModelConfigKey: deps.modelConfigKey
29493
30204
  }
29494
30205
  });
29495
30206
  let validatedPass = await validateHistorianResult(firstResult, sessionId, chunk, priorCompartments, sequenceOffset);
@@ -29549,6 +30260,7 @@ ${chunkText}`,
29549
30260
  onProgress: buildProgressLogger("fallback"),
29550
30261
  accountingSessionId: sessionId,
29551
30262
  accountingSubagent: "historian",
30263
+ accountingModelConfigKey: candidate.sourceConfigKey ?? deps.modelConfigKey,
29552
30264
  accountingTask: "fallback"
29553
30265
  }
29554
30266
  });
@@ -29600,7 +30312,8 @@ ${chunkText}`,
29600
30312
  maxOutputTokens,
29601
30313
  onProgress: buildProgressLogger("editor"),
29602
30314
  accountingSessionId: sessionId,
29603
- accountingSubagent: "historian_editor"
30315
+ accountingSubagent: "historian_editor",
30316
+ accountingModelConfigKey: deps.modelConfigKey
29604
30317
  }
29605
30318
  });
29606
30319
  const editorPass = await validateHistorianResult(editorResult, sessionId, chunk, priorCompartments, sequenceOffset);
@@ -31655,7 +32368,7 @@ function promoteRecompStagingWithM0Mutation(db, sessionId, holderId) {
31655
32368
  finished = true;
31656
32369
  return null;
31657
32370
  }
31658
- deleteChunkEmbedBackoffForSession(db, sessionId);
32371
+ deleteChunkEmbedBackoffForSession2(db, sessionId);
31659
32372
  db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
31660
32373
  db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
31661
32374
  insertRecompCompartmentRows(db, sessionId, staging.compartments, now);
@@ -32563,7 +33276,7 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = f
32563
33276
  if (marker && clearPendingPiCompactionMarkerStateIf(db, sessionId, marker, null))
32564
33277
  clearedMarker = marker;
32565
33278
  }
32566
- deleteChunkEmbedBackoffForSession(db, sessionId);
33279
+ deleteChunkEmbedBackoffForSession2(db, sessionId);
32567
33280
  queueM0Mutation(db, { sessionId, mutationType: "recomp_boundary_change" });
32568
33281
  clearCachedM0M1(db, sessionId);
32569
33282
  db.exec("COMMIT");
@@ -34521,7 +35234,7 @@ function isSentinelPart(part) {
34521
35234
 
34522
35235
  // src/pi-append-compaction.ts
34523
35236
  var loggedIncompatibleHost = false;
34524
- var failedWrites = new WeakMap;
35237
+ var failedWrites2 = new WeakMap;
34525
35238
  function adaptPiAppendCompaction(sessionManager) {
34526
35239
  if (!sessionManager || typeof sessionManager !== "object")
34527
35240
  return;
@@ -34529,7 +35242,7 @@ function adaptPiAppendCompaction(sessionManager) {
34529
35242
  const append = host.appendCompaction;
34530
35243
  if (typeof append !== "function")
34531
35244
  return;
34532
- if (failedWrites.has(host))
35245
+ if (failedWrites2.has(host))
34533
35246
  return;
34534
35247
  const harness = resolvePiHarnessKind();
34535
35248
  if ((harness === "omp" ? append.length !== 4 && append.length !== 7 : append.length !== 5 && append.length !== 6) || typeof host.getEntry !== "function") {
@@ -34541,7 +35254,7 @@ function adaptPiAppendCompaction(sessionManager) {
34541
35254
  }
34542
35255
  const getEntry = host.getEntry.bind(host);
34543
35256
  return (summary, firstKeptEntryId, tokensBefore, details, fromHook) => {
34544
- const previousFailure = failedWrites.get(host);
35257
+ const previousFailure = failedWrites2.get(host);
34545
35258
  if (previousFailure)
34546
35259
  throw previousFailure;
34547
35260
  let id;
@@ -34559,7 +35272,7 @@ function adaptPiAppendCompaction(sessionManager) {
34559
35272
  }
34560
35273
  } catch {
34561
35274
  const error = new Error("Compaction marker read-back failed; writes disabled for this session manager until restart");
34562
- failedWrites.set(host, error);
35275
+ failedWrites2.set(host, error);
34563
35276
  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`);
34564
35277
  throw error;
34565
35278
  }
@@ -34567,123 +35280,6 @@ function adaptPiAppendCompaction(sessionManager) {
34567
35280
  };
34568
35281
  }
34569
35282
 
34570
- // src/pi-context-budget.ts
34571
- var PI_CONTEXT_BUDGET = {
34572
- hostDeadlineMs: 30000,
34573
- hostMarginMs: 5000,
34574
- outcomeMs: 25000,
34575
- fallbackObservedMs: 4,
34576
- workMs: 21000,
34577
- writerMs: 16500,
34578
- completionReserveMs: 2000,
34579
- searchMs: 3000
34580
- };
34581
-
34582
- class PiContextDeadlineError extends Error {
34583
- }
34584
-
34585
- class PiContextSupersededError extends Error {
34586
- origin;
34587
- constructor(message, origin = "context ownership") {
34588
- super(message);
34589
- this.origin = origin;
34590
- }
34591
- }
34592
-
34593
- class PiContextBudget {
34594
- startedAt;
34595
- now;
34596
- sideTurn = false;
34597
- stage = "entry";
34598
- recovery = "not attempted";
34599
- abandoned = false;
34600
- completed = false;
34601
- failureReason;
34602
- signal;
34603
- cancelled = false;
34604
- isCancelled(error) {
34605
- return this.cancelled || this.signal?.aborted === true || !this.signal && typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
34606
- }
34607
- cancel() {
34608
- this.cancelled = true;
34609
- this.abandoned = true;
34610
- this.completed = false;
34611
- this.failureReason = undefined;
34612
- }
34613
- assertOwner = () => {};
34614
- constructor(startedAt = performance.now(), now = () => performance.now()) {
34615
- this.startedAt = startedAt;
34616
- this.now = now;
34617
- }
34618
- elapsed() {
34619
- return this.now() - this.startedAt;
34620
- }
34621
- remainingWork = () => {
34622
- return Math.max(0, PI_CONTEXT_BUDGET.workMs - this.elapsed());
34623
- };
34624
- remainingOutcome = () => Math.max(0, PI_CONTEXT_BUDGET.outcomeMs - this.elapsed());
34625
- writerAllowance() {
34626
- return Math.max(0, Math.min(PI_CONTEXT_BUDGET.writerMs, this.remainingWork() - PI_CONTEXT_BUDGET.completionReserveMs));
34627
- }
34628
- hydrationAllowance() {
34629
- return Math.max(0, Math.min(this.remainingWork() - PI_CONTEXT_BUDGET.completionReserveMs, this.remainingOutcome() - PI_CONTEXT_BUDGET.completionReserveMs));
34630
- }
34631
- assertOutcome = () => {
34632
- this.assertOwner();
34633
- this.signal?.throwIfAborted();
34634
- if (this.abandoned || this.elapsed() >= PI_CONTEXT_BUDGET.outcomeMs)
34635
- throw new PiContextDeadlineError(this.diagnostic());
34636
- };
34637
- assert = () => {
34638
- this.assertOutcome();
34639
- if (this.elapsed() >= PI_CONTEXT_BUDGET.workMs)
34640
- throw new PiContextDeadlineError(this.diagnostic());
34641
- };
34642
- assertDecisionPublication = () => {
34643
- this.signal?.throwIfAborted();
34644
- if (!this.completed)
34645
- this.assertOwner();
34646
- if (this.abandoned || !this.completed && this.elapsed() >= PI_CONTEXT_BUDGET.outcomeMs)
34647
- throw new PiContextDeadlineError(this.diagnostic());
34648
- };
34649
- diagnostic() {
34650
- return `stage=${this.stage} elapsed=${Math.round(this.elapsed())}ms recovery=${this.recovery}`;
34651
- }
34652
- waitUntil = async (pending, assert, remaining) => {
34653
- try {
34654
- assert();
34655
- } catch (error) {
34656
- pending.catch(() => {});
34657
- throw error;
34658
- }
34659
- let timer;
34660
- let onAbort;
34661
- try {
34662
- return await Promise.race([
34663
- pending,
34664
- ...this.signal ? [
34665
- new Promise((_, reject) => {
34666
- onAbort = () => reject(this.signal?.reason);
34667
- this.signal?.addEventListener("abort", onAbort, {
34668
- once: true
34669
- });
34670
- })
34671
- ] : [],
34672
- new Promise((_, reject) => {
34673
- timer = setTimeout(() => reject(new PiContextDeadlineError(this.diagnostic())), remaining());
34674
- })
34675
- ]);
34676
- } finally {
34677
- clearTimeout(timer);
34678
- if (onAbort)
34679
- this.signal?.removeEventListener("abort", onAbort);
34680
- assert();
34681
- }
34682
- };
34683
- wait = (pending) => this.waitUntil(pending, this.assert, () => this.remainingWork());
34684
- waitMandatory = (pending) => this.waitUntil(pending, this.assertOutcome, this.remainingOutcome);
34685
- }
34686
-
34687
35283
  // src/pi-context-limit.ts
34688
35284
  var MIN_SANE_LIMIT = 16000;
34689
35285
  var MAX_SANE_LIMIT = 1e7;
@@ -35376,6 +35972,11 @@ function piHasManagedSignature(payload, signature) {
35376
35972
  return false;
35377
35973
  }
35378
35974
 
35975
+ // src/pi-dispatch-assistant-history.ts
35976
+ function piOmitsTruncatedAssistant(message) {
35977
+ return (message.stopReason === "length" || message.stopReason === "error" || message.stopReason === "aborted") && Array.isArray(message.content) && !message.content.some((block) => block?.type === "text" || block?.type === "toolCall");
35978
+ }
35979
+
35379
35980
  // src/pi-dispatch-tool-pairing.ts
35380
35981
  var RESPONSES_APIS = new Set([
35381
35982
  "openai-responses",
@@ -35425,14 +36026,14 @@ function object5(value) {
35425
36026
  function omitsAssistant(message, model, compat) {
35426
36027
  if (!Array.isArray(message.content))
35427
36028
  return false;
36029
+ if (piOmitsTruncatedAssistant(message))
36030
+ return true;
35428
36031
  let thinking = false;
35429
- let hasTextBlock = false;
35430
36032
  for (const value of message.content) {
35431
36033
  const block = object5(value);
35432
36034
  if (!block)
35433
36035
  return false;
35434
36036
  if (block.type === "text") {
35435
- hasTextBlock = true;
35436
36037
  if (typeof block.text !== "string" || block.text.trim())
35437
36038
  return false;
35438
36039
  } else if (block.type === "thinking") {
@@ -35442,8 +36043,6 @@ function omitsAssistant(message, model, compat) {
35442
36043
  } else
35443
36044
  return false;
35444
36045
  }
35445
- if (!hasTextBlock && ["length", "error", "aborted"].includes(String(message.stopReason)))
35446
- return true;
35447
36046
  if (compat.requiresReasoningContentForAllAssistantTurns === true)
35448
36047
  return false;
35449
36048
  if (!thinking)
@@ -35748,11 +36347,25 @@ ${wellFormed(text)}
35748
36347
  </think>`;
35749
36348
  return;
35750
36349
  }
35751
- function piResponsesAssistantTexts(value, model) {
36350
+ function coldReplayable(items) {
36351
+ let reasoning = false;
36352
+ for (const value of items) {
36353
+ const item = object7(value);
36354
+ if (typeof item?.encrypted_content === "string")
36355
+ return false;
36356
+ if (item?.type !== "reasoning")
36357
+ continue;
36358
+ if (!Array.isArray(item.content) || !item.content.some((part) => object7(part)?.type === "reasoning_text"))
36359
+ return false;
36360
+ reasoning = true;
36361
+ }
36362
+ return reasoning;
36363
+ }
36364
+ function piResponsesAssistantTexts(value, model, host, alternatives) {
35752
36365
  const message = object7(value);
35753
36366
  if (!message || !Array.isArray(message.content))
35754
36367
  return;
35755
- if (["length", "error", "aborted"].includes(String(message.stopReason)) && !message.content.some((value) => ["text", "toolCall"].includes(String(object7(value)?.type))))
36368
+ if (piOmitsTruncatedAssistant(message))
35756
36369
  return [];
35757
36370
  const texts = [];
35758
36371
  const blocks = [];
@@ -35795,6 +36408,13 @@ function piResponsesAssistantTexts(value, model) {
35795
36408
  const replay = [];
35796
36409
  let bound = 0;
35797
36410
  let output = false;
36411
+ const allowUnsigned = host === "omp" && message.role === "assistant" && [
36412
+ "openai-responses",
36413
+ "azure-openai-responses",
36414
+ "openai-codex-responses"
36415
+ ].includes(model?.api ?? "");
36416
+ let unsigned = false;
36417
+ let rewrittenText = false;
35798
36418
  for (const value of payload.items) {
35799
36419
  const item = object7(value);
35800
36420
  if (item?.type === "reasoning")
@@ -35818,8 +36438,14 @@ function piResponsesAssistantTexts(value, model) {
35818
36438
  } catch {
35819
36439
  return texts;
35820
36440
  }
35821
- if (signature?.v !== 1 || typeof signature.id !== "string" || item.id !== signature.id || item.phase !== signature.phase || part.text !== block.text.replace(/^§\d+§ /u, ""))
35822
- return texts;
36441
+ const signed = signature?.v === 1 && typeof signature.id === "string" && item.id === signature.id && item.phase === signature.phase && part.text === block.text.replace(/^§\d+§ /u, "");
36442
+ if (!signed) {
36443
+ const stripped = stripPersistedAssistantText(part.text);
36444
+ if (!allowUnsigned || "textSignature" in block || stripped !== block.text.replace(/^§\d+§ /u, ""))
36445
+ return texts;
36446
+ unsigned = true;
36447
+ rewrittenText ||= part.text !== stripped && part.text !== block.text;
36448
+ }
35823
36449
  bound++;
35824
36450
  itemTexts.push(part.text);
35825
36451
  }
@@ -35829,7 +36455,13 @@ function piResponsesAssistantTexts(value, model) {
35829
36455
  for (const text of itemTexts)
35830
36456
  replay.push(textIdentity2(wellFormed(text), item.phase));
35831
36457
  }
35832
- return output && bound === blocks.length ? replay : texts;
36458
+ if (!output || bound !== blocks.length || unsigned && !rewrittenText)
36459
+ return texts;
36460
+ if (unsigned && alternatives) {
36461
+ alternatives.fallback = texts;
36462
+ alternatives.cold = coldReplayable(payload.items) ? replay : texts;
36463
+ }
36464
+ return replay;
35833
36465
  }
35834
36466
  function piResponsesWireTexts(value, phase) {
35835
36467
  if (phase !== undefined && phase !== null && phase !== "commentary" && phase !== "final_answer")
@@ -36071,11 +36703,10 @@ function projectMissingToolResults(messages, model, host = "omp") {
36071
36703
  const message = object8(value);
36072
36704
  if (message?.role === "assistant") {
36073
36705
  flush(message.timestamp);
36706
+ if (piOmitsTruncatedAssistant(message))
36707
+ continue;
36074
36708
  projected.push(value);
36075
36709
  const calls = windowCalls(message);
36076
- const truncated = ["length", "error", "aborted"].includes(String(message.stopReason));
36077
- if (truncated && Array.isArray(message.content) && !message.content.some((part) => ["toolCall", "text"].includes(String(object8(part)?.type))))
36078
- continue;
36079
36710
  if (message.stopReason === "aborted" || message.stopReason === "error") {
36080
36711
  aborted = new Map(calls.map((call) => [pairingId(call.id), call]));
36081
36712
  abortedTimestamp = message.timestamp;
@@ -36369,31 +37000,43 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
36369
37000
  }
36370
37001
  const responsesApi = responsesLane(model?.api);
36371
37002
  let responsesMessages = responsesApi ? [] : undefined;
37003
+ const fallbackMessages = [];
37004
+ const coldMessages = [];
37005
+ let unsignedAlternatives = false;
37006
+ const appendResponse = (output, row, texts) => {
37007
+ if (!texts.length && !row.calls.length)
37008
+ return;
37009
+ const previous = output.at(-1);
37010
+ if (previous?.role === "assistant") {
37011
+ previous.calls.push(...row.calls);
37012
+ previous.wireCalls?.push(...row.wireCalls ?? []);
37013
+ previous.responseTexts?.push(...texts);
37014
+ } else
37015
+ output.push({
37016
+ ...row,
37017
+ calls: [...row.calls],
37018
+ ...row.wireCalls ? { wireCalls: [...row.wireCalls] } : {},
37019
+ responseTexts: [...texts]
37020
+ });
37021
+ };
36372
37022
  if (responsesMessages) {
36373
37023
  for (const [index, row] of byIndex) {
36374
37024
  if (row.role !== "assistant") {
36375
37025
  responsesMessages.push(row);
37026
+ fallbackMessages.push(row);
37027
+ coldMessages.push(row);
36376
37028
  continue;
36377
37029
  }
36378
- const texts = piResponsesAssistantTexts(projectedMessages[index], model);
37030
+ const alternatives = {};
37031
+ const texts = piResponsesAssistantTexts(projectedMessages[index], model, host, alternatives);
36379
37032
  if (!texts) {
36380
37033
  responsesMessages = undefined;
36381
37034
  break;
36382
37035
  }
36383
- if (!texts.length && !row.calls.length)
36384
- continue;
36385
- const previous = responsesMessages.at(-1);
36386
- if (previous?.role === "assistant") {
36387
- previous.calls.push(...row.calls);
36388
- previous.wireCalls?.push(...row.wireCalls ?? []);
36389
- previous.responseTexts?.push(...texts);
36390
- } else
36391
- responsesMessages.push({
36392
- ...row,
36393
- calls: [...row.calls],
36394
- ...row.wireCalls ? { wireCalls: [...row.wireCalls] } : {},
36395
- responseTexts: [...texts]
36396
- });
37036
+ unsignedAlternatives ||= alternatives.fallback !== undefined;
37037
+ appendResponse(responsesMessages, row, texts);
37038
+ appendResponse(fallbackMessages, row, alternatives.fallback ?? texts);
37039
+ appendResponse(coldMessages, row, alternatives.cold ?? texts);
36397
37040
  }
36398
37041
  }
36399
37042
  const plan = piChatHistoryPlan(projectedMessages, model);
@@ -36428,6 +37071,7 @@ function buildPiPreparedStructure(messages, model, prepareUser, host = "omp") {
36428
37071
  ...responsesApi && !responsesMessages ? { structuralSkipReason: "Responses history transform is not modeled" } : model?.api === "openai-completions" && !chatMessages ? { structuralSkipReason: "Chat history transform is not modeled" } : {},
36429
37072
  ...chatMessages ? { chatMessages } : {},
36430
37073
  ...responsesMessages ? { responsesMessages } : {},
37074
+ ...responsesMessages && unsignedAlternatives ? { responsesAlternatives: [fallbackMessages, coldMessages] } : {},
36431
37075
  ...model?.api ? { api: model.api } : {},
36432
37076
  ...model?.api?.startsWith("google-") ? {
36433
37077
  googleFunctionIds: object8(model.compat)?.supportsFunctionPartId === true
@@ -36744,6 +37388,10 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
36744
37388
  const chat = !!body && Array.isArray(body.messages) && (prepared?.api === "openai-completions" || body.system === undefined) && body.input === undefined && body.inferenceConfig === undefined;
36745
37389
  stage = "prepared rows";
36746
37390
  expectedRows = responses && prepared?.responsesMessages ? prepared.responsesMessages : chat && prepared?.chatMessages ? prepared.chatMessages : prepared?.messages;
37391
+ if (responses && rows && prepared?.responsesAlternatives) {
37392
+ const actual = rows;
37393
+ expectedRows = [prepared.responsesMessages, ...prepared.responsesAlternatives].find((candidate) => candidate?.length === actual.length && candidate.every((expected, index) => JSON.stringify(expected.responseTexts) === JSON.stringify(actual[index].responseTexts))) ?? expectedRows;
37394
+ }
36747
37395
  if (expectedRows && imageProjection && imageBudget)
36748
37396
  expectedRows = trimPreparedImageRows(expectedRows, imageBudget, trimmed);
36749
37397
  if (!rows || !expectedRows)
@@ -38520,7 +39168,7 @@ function registerPiGuardedContext(pi, handler, options = {}) {
38520
39168
  inputs = messageSnapshots(event.messages);
38521
39169
  active.inputMessages = inputs;
38522
39170
  }
38523
- const result = await budget.waitMandatory(Promise.resolve(withSqliteTransformPass2(() => handler(event, ctx, budget))));
39171
+ const result = await budget.waitMandatory(Promise.resolve(withSqliteTurnDeadline2(() => Math.max(0, budget.remainingOutcome() - PI_CONTEXT_BUDGET.completionReserveMs), () => withSqliteTransformPass2(() => handler(event, ctx, budget)))));
38524
39172
  if (result?.messages) {
38525
39173
  const prepared = preparePiDispatch(result.messages, fenceEnabled ? ctx.model : undefined, fenceEnabled);
38526
39174
  if (prepared.messages !== result.messages)
@@ -38788,13 +39436,15 @@ function recordPiUpperEstimateReclaim(db, cursor, reservation) {
38788
39436
  pendingInput.delete(cursor.sessionId);
38789
39437
  }
38790
39438
  function releasePiUpperEstimateReclaim(db, cursor, reservation) {
38791
- if (!updateReplayDocument(db, cursor.sessionId, (doc) => {
38792
- if (claimFrom(doc[KEY2], cursor.sessionId)?.reservation !== reservation)
38793
- return false;
38794
- delete doc[KEY2];
38795
- return true;
38796
- }))
38797
- throw new Error("Could not release upper-estimate reclaim");
39439
+ withoutSqliteTransformPass2(() => withSqliteTurnDeadline2(() => 0, () => {
39440
+ if (!updateReplayDocument(db, cursor.sessionId, (doc) => {
39441
+ if (claimFrom(doc[KEY2], cursor.sessionId)?.reservation !== reservation)
39442
+ return false;
39443
+ delete doc[KEY2];
39444
+ return true;
39445
+ }))
39446
+ throw new Error("Could not release upper-estimate reclaim");
39447
+ }));
38798
39448
  }
38799
39449
  function resetPiUpperEstimateReclaim(db, sessionId) {
38800
39450
  if (!claimFrom(readReplayEnvelope(db, sessionId)[KEY2], sessionId))
@@ -38806,6 +39456,21 @@ function resetPiUpperEstimateReclaim(db, sessionId) {
38806
39456
  throw new Error("Could not clear upper-estimate reclaim cursor");
38807
39457
  }
38808
39458
 
39459
+ // src/pi-historian-turn-wait.ts
39460
+ var foregroundWaits = new Map;
39461
+ function inPiHistorianRootContext(sessionId, operation) {
39462
+ return inRootAsyncContext2(() => withSqliteTurnDeadline2(() => foregroundWaits.get(sessionId)?.() ?? Infinity, operation));
39463
+ }
39464
+ async function waitForPiHistorianInTurn(sessionId, remainingMs, wait) {
39465
+ foregroundWaits.set(sessionId, remainingMs);
39466
+ try {
39467
+ return await wait();
39468
+ } finally {
39469
+ if (foregroundWaits.get(sessionId) === remainingMs)
39470
+ foregroundWaits.delete(sessionId);
39471
+ }
39472
+ }
39473
+
38809
39474
  // src/pi-lkg-fit-envelope.ts
38810
39475
  import { createHash as createHash13 } from "node:crypto";
38811
39476
  function readPiLkgFitEnvelope(ctx, pi, modelKey, frozen, wireSchema) {
@@ -44124,6 +44789,20 @@ function registerPiContextHandler(pi, baseOptions) {
44124
44789
  elapsedMs: performance.now() - fitInputStart,
44125
44790
  extra: inputForFitReclaim ? "snapshot" : "no-snapshot"
44126
44791
  });
44792
+ if (!options.compactionOff && !sessionMeta.isSubagent) {
44793
+ let promptId = null;
44794
+ for (let i = event.messages.length - 1;i >= 0; i--) {
44795
+ const message = event.messages[i];
44796
+ if (message?.role !== "user")
44797
+ continue;
44798
+ const parts = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
44799
+ if (!hasMeaningfulUserText2(parts))
44800
+ continue;
44801
+ promptId = entryIds?.[i] ?? null;
44802
+ break;
44803
+ }
44804
+ maintainExecuteFloorMark(options.db, sessionId, promptId, usagePercentage < effectiveExecuteThresholdPercentage);
44805
+ }
44127
44806
  const pipelineArgs = {
44128
44807
  recoveryPrefix: recovery.prefix,
44129
44808
  recoveryRebuildReason: recovery.rebuildReason,
@@ -44225,6 +44904,65 @@ function registerPiContextHandler(pi, baseOptions) {
44225
44904
  };
44226
44905
  if (!options.compactionOff)
44227
44906
  assertPiTagSnapshotReady(options.db, sessionId);
44907
+ let historianEvaluatedThisPass = false;
44908
+ const historian = options.historian;
44909
+ const scheduleHistorian = (result) => {
44910
+ if (historianEvaluatedThisPass)
44911
+ return;
44912
+ historianEvaluatedThisPass = true;
44913
+ const tHistorianScheduling = performance.now();
44914
+ budget.stage = "historian scheduling";
44915
+ if (historian && !options.compactionOff && budget.remainingWork() > 0) {
44916
+ guardSqliteTransformPass2({
44917
+ assert: budget.assert,
44918
+ remainingMs: budget.remainingWork
44919
+ });
44920
+ try {
44921
+ budget.assert();
44922
+ maybeFireHistorian({
44923
+ startGuard: () => {
44924
+ if (!budget.completed)
44925
+ budget.assertOwner();
44926
+ if (budget.abandoned || budget.remainingWork() === 0)
44927
+ throw new PiContextDeadlineError(budget.diagnostic());
44928
+ },
44929
+ pi,
44930
+ ctx,
44931
+ sessionId,
44932
+ db: options.db,
44933
+ historian,
44934
+ isFirstContextPassForSession,
44935
+ activeTags: result.activeTags,
44936
+ eligiblePendingDropTagIds: result.eligiblePendingDropTagIds,
44937
+ rawMessageProvider,
44938
+ ordinalAlignment: ordinalAlignment(),
44939
+ taggerFloor,
44940
+ sessionMeta,
44941
+ piUsage,
44942
+ pressureSnapshot: {
44943
+ percentage: usagePercentage,
44944
+ inputTokens: usageInputTokens
44945
+ },
44946
+ minimumPercentage: usagePercentage,
44947
+ liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
44948
+ historianStateSnapshot: historianStateForPass,
44949
+ publishedHistoryRide: isCacheBusting,
44950
+ primaryExecute: schedulerDecision === "execute" && !sessionMeta.isSubagent,
44951
+ signedThinkingHeld: result.strictThinkingKept
44952
+ });
44953
+ } catch (error) {
44954
+ budget.assertOutcome();
44955
+ sessionLog2(sessionId, `historian scheduling skipped: ${String(error)}`);
44956
+ } finally {
44957
+ guardSqliteTransformPass2({
44958
+ assert: budget.assertOutcome,
44959
+ remainingMs: budget.remainingOutcome
44960
+ });
44961
+ }
44962
+ }
44963
+ logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
44964
+ };
44965
+ pipelineArgs.evaluateHistorianBeforeReclaim = scheduleHistorian;
44228
44966
  let result = await budget.waitMandatory(runPipeline(pipelineArgs));
44229
44967
  observePipelineResultForTests(sessionId, result);
44230
44968
  logTransformTiming(sessionId, "runPipeline", tRunPipeline);
@@ -44256,57 +44994,7 @@ function registerPiContextHandler(pi, baseOptions) {
44256
44994
  }, piDecisionSnapshotNewestAssistant, budget.assertDecisionPublication);
44257
44995
  } : undefined;
44258
44996
  logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
44259
- const tHistorianScheduling = performance.now();
44260
- const historian = options.historian;
44261
- budget.stage = "historian scheduling";
44262
- if (historian && !options.compactionOff && budget.remainingWork() > 0) {
44263
- guardSqliteTransformPass2({
44264
- assert: budget.assert,
44265
- remainingMs: budget.remainingWork
44266
- });
44267
- try {
44268
- budget.assert();
44269
- maybeFireHistorian({
44270
- startGuard: () => {
44271
- if (!budget.completed)
44272
- budget.assertOwner();
44273
- if (budget.abandoned || budget.remainingWork() === 0)
44274
- throw new PiContextDeadlineError(budget.diagnostic());
44275
- },
44276
- pi,
44277
- ctx,
44278
- sessionId,
44279
- db: options.db,
44280
- historian,
44281
- isFirstContextPassForSession,
44282
- activeTags: result.activeTags,
44283
- eligiblePendingDropTagIds: result.eligiblePendingDropTagIds,
44284
- rawMessageProvider,
44285
- ordinalAlignment: ordinalAlignment(),
44286
- taggerFloor,
44287
- sessionMeta,
44288
- piUsage,
44289
- pressureSnapshot: {
44290
- percentage: usagePercentage,
44291
- inputTokens: usageInputTokens
44292
- },
44293
- minimumPercentage: usagePercentage,
44294
- liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
44295
- historianStateSnapshot: historianStateForPass,
44296
- publishedHistoryRide: isCacheBusting,
44297
- signedThinkingHeld: result.strictThinkingKept
44298
- });
44299
- } catch (error) {
44300
- budget.assertOutcome();
44301
- sessionLog2(sessionId, `historian scheduling skipped: ${String(error)}`);
44302
- } finally {
44303
- guardSqliteTransformPass2({
44304
- assert: budget.assertOutcome,
44305
- remainingMs: budget.remainingOutcome
44306
- });
44307
- }
44308
- }
44309
- logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
44997
+ scheduleHistorian(result);
44310
44998
  const tPostTransform = performance.now();
44311
44999
  let outputMessages = result.messages;
44312
45000
  let assertTailHygieneLastWriter;
@@ -44693,7 +45381,7 @@ function registerPiContextHandler(pi, baseOptions) {
44693
45381
  const pending = inFlightHistorian.get(sessionId);
44694
45382
  if (pending) {
44695
45383
  budget.stage = "headless fit historian";
44696
- await budget.wait(pending);
45384
+ await waitForPiHistorianInTurn(sessionId, () => Math.max(0, budget.remainingOutcome() - PI_CONTEXT_BUDGET.completionReserveMs), () => budget.wait(pending));
44697
45385
  }
44698
45386
  }
44699
45387
  budget.stage = "outgoing fit reclaim";
@@ -44738,7 +45426,7 @@ function registerPiContextHandler(pi, baseOptions) {
44738
45426
  estimate = estimatePiOutgoingInputTokens(outputMessages, envelope, undefined, outgoingFitLimit);
44739
45427
  } finally {
44740
45428
  if (!reclaimCompleted && upperCursor && reservation)
44741
- withoutSqliteTransformPass2(() => releasePiUpperEstimateReclaim(options.db, upperCursor, reservation));
45429
+ releasePiUpperEstimateReclaim(options.db, upperCursor, reservation);
44742
45430
  }
44743
45431
  }
44744
45432
  }
@@ -45105,7 +45793,7 @@ function spawnPiHistorianRun(args) {
45105
45793
  const holderId = crypto3.randomUUID();
45106
45794
  const controller = new AbortController;
45107
45795
  historianAbortControllers.set(sessionId, controller);
45108
- const runPromise = inRootAsyncContext2(() => (async () => {
45796
+ const runPromise = inPiHistorianRootContext(sessionId, () => (async () => {
45109
45797
  await new Promise((resolve) => setTimeout(resolve, 0));
45110
45798
  if (controller.signal.aborted)
45111
45799
  return;
@@ -45135,6 +45823,7 @@ function spawnPiHistorianRun(args) {
45135
45823
  runner: historian.runner,
45136
45824
  signal: controller.signal,
45137
45825
  historianModel: historian.model,
45826
+ modelConfigKey: historian.modelConfigKey,
45138
45827
  fallbackModels: historian.fallbackModels,
45139
45828
  fallbackModelId,
45140
45829
  historianChunkTokens: historian.historianChunkTokens,
@@ -45457,7 +46146,7 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
45457
46146
  idleExpiry: false,
45458
46147
  emergency: usage.percentage >= historianForceMaterializationPercentage
45459
46148
  }
45460
- }, args.eligiblePendingDropTagIds);
46149
+ }, args.eligiblePendingDropTagIds, args.primaryExecute === true);
45461
46150
  if (!trigger.shouldFire) {
45462
46151
  sessionLog2(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
45463
46152
  try {
@@ -45557,7 +46246,7 @@ function captureReasoningMutationRollback(messages) {
45557
46246
  async function runCompactionOffPipeline(args) {
45558
46247
  let injectionResult = null;
45559
46248
  const transcript = [...args.messages];
45560
- let headChangedUnderSignedTurn = false;
46249
+ let headChangedUnderSignedThinking = false;
45561
46250
  if (args.injection) {
45562
46251
  const state = {
45563
46252
  sessionId: args.sessionId,
@@ -45579,10 +46268,16 @@ async function runCompactionOffPipeline(args) {
45579
46268
  if (servedBeforeFirstRender !== undefined) {
45580
46269
  const headCount = injectionResult?.syntheticLeadingCount ?? 0;
45581
46270
  const head = JSON.stringify(args.messages.slice(0, headCount));
45582
- headChangedUnderSignedTurn = servedBeforeFirstRender === null || JSON.stringify(servedBeforeFirstRender.slice(0, headCount)) !== head;
46271
+ headChangedUnderSignedThinking = servedBeforeFirstRender === null || JSON.stringify(servedBeforeFirstRender.slice(0, headCount)) !== head;
46272
+ } else if (!signedTurnHoldsHead && args.reasoningClearing?.prefixBound === true && (injectionResult?.m0Materialized === true || injectionResult?.m1RenderedCoverage != null)) {
46273
+ const served = args.readLastServedMessages?.() ?? null;
46274
+ const headCount = injectionResult?.syntheticLeadingCount ?? 0;
46275
+ headChangedUnderSignedThinking = served === null || JSON.stringify(served.slice(0, headCount)) !== JSON.stringify(args.messages.slice(0, headCount));
46276
+ if (headChangedUnderSignedThinking)
46277
+ sessionLog2(args.sessionId, "compaction-off fold changed the head: stripping signed thinking");
45583
46278
  }
45584
46279
  }
45585
- if (headChangedUnderSignedTurn)
46280
+ if (headChangedUnderSignedThinking)
45586
46281
  applyPiProactiveThinkingStrip({
45587
46282
  db: args.db,
45588
46283
  sessionId: args.sessionId,
@@ -45896,6 +46591,7 @@ async function runPipeline(args) {
45896
46591
  logTransformTiming(args.sessionId, "injectTemporalMarkers", tTemporal);
45897
46592
  }
45898
46593
  let nativeRemovalInputs;
46594
+ let probingExecuteRemoval = false;
45899
46595
  try {
45900
46596
  nativeRemovalInputs = getNativeReplayState(args.db, args.sessionId).toolInputs;
45901
46597
  } catch {}
@@ -45907,7 +46603,7 @@ async function runPipeline(args) {
45907
46603
  sessionId: args.sessionId,
45908
46604
  callId,
45909
46605
  saved: nativeRemovalInputs,
45910
- canApply: isCacheBustingPass
46606
+ canApply: isCacheBustingPass || probingExecuteRemoval
45911
46607
  }),
45912
46608
  authorizeToolRemovals: (callIds) => preparePiToolRemovalMeasurements({
45913
46609
  db: args.db,
@@ -45939,6 +46635,7 @@ async function runPipeline(args) {
45939
46635
  const heldIdleExpiryRebuild = protectedSignedPrefix && piHardSignals?.cacheExpired === true;
45940
46636
  const systemPrefixChangedThisPass = !prefixPreflightContended && effectiveSystemChangedThisPass;
45941
46637
  const rideSignals = {
46638
+ executeReclaim: false,
45942
46639
  subagentExecute: args.sessionMeta.isSubagent && args.schedulerDecision === "execute",
45943
46640
  hardFold: foldBustsServedPrefixThisPass || systemPrefixChangedThisPass || firstRenderBust || heldIdleExpiryRebuild || isCacheBustingPass,
45944
46641
  force: (args.forceMaterialization === true || emergencyDropEligible) && (args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0),
@@ -46051,11 +46748,14 @@ async function runPipeline(args) {
46051
46748
  }
46052
46749
  }
46053
46750
  }
46054
- if (args.temporalAwareness && isCacheBustingPass && !protectedSignedPrefix) {
46751
+ const applyTemporalOnRide = () => {
46752
+ if (!args.temporalAwareness || !isCacheBustingPass || protectedSignedPrefix)
46753
+ return;
46055
46754
  temporalDecisions = freezeTemporalDecisions(args.db, args.sessionId, temporalCandidates);
46056
46755
  if (injectPiTemporalMarkers(args.messages, temporalDecisions, stableIdResolver) > 0)
46057
46756
  recordFirstApplicationWireEdit(true);
46058
- }
46757
+ };
46758
+ applyTemporalOnRide();
46059
46759
  logPiUnresolvedIdentities(args.sessionId, [
46060
46760
  ...guardPiToolAllocations(args.db, args.sessionId, args.messages, stableIdResolver, args.tagger, fallbackIndex.guardIndexes),
46061
46761
  ...guardPiMessageAllocations(args.db, args.sessionId, entryFingerprintByMessageId)
@@ -46084,6 +46784,7 @@ async function runPipeline(args) {
46084
46784
  args.assertCurrentPass?.();
46085
46785
  return tagTranscript(args.sessionId, { ...transcript, messages: taggingView }, args.tagger, args.db, {
46086
46786
  skipPrefixInjection: !ctxReduceCallable,
46787
+ preserveTagOnlyAssistantText: true,
46087
46788
  entryFingerprintByMessageId,
46088
46789
  reuseMessageIds: textIdentityPlan.reusableMessageIds,
46089
46790
  textIdentityDriftMessageIds: textIdentityPlan.driftedMessageIds,
@@ -46205,6 +46906,62 @@ async function runPipeline(args) {
46205
46906
  const protectionWindowForPass = getProtectionWindowForSession(args.db, args.sessionId, protectionFloorResolution.floor);
46206
46907
  const protectedTagNumbersForPass = usesTokenProtection ? protectionWindowForPass.protectedTagNumbers : newestActiveTagNumbersByCount(getActiveTagsBySession2(args.db, args.sessionId), args.protectedTags);
46207
46908
  const pendingOperationTags = pendingOps.length > 0 ? getTagsForPendingOperations2(args.db, args.sessionId, pendingOps.map((operation) => operation.tagId), usesTokenProtection ? 0 : args.protectedTags, RECENT_TOOL_SKELETON_WINDOW) : [];
46909
+ if (!args.sessionMeta.isSubagent && args.schedulerDecision === "execute") {
46910
+ args.evaluateHistorianBeforeReclaim?.({
46911
+ activeTags: getActiveTagsBySession2(args.db, args.sessionId),
46912
+ eligiblePendingDropTagIds,
46913
+ strictThinkingKept: protectedSignedPrefix
46914
+ });
46915
+ }
46916
+ rideSignals.executeReclaim = originateExecuteReclaim({
46917
+ db: args.db,
46918
+ sessionId: args.sessionId,
46919
+ primaryExecute: !args.sessionMeta.isSubagent && args.schedulerDecision === "execute" && args.contextUsage.percentage < forceMaterializationPercentage,
46920
+ alreadyBusting: isCacheBustingPass || identityRebuild,
46921
+ summaryCanCome: args.sessionMeta.compartmentInProgress || inFlightHistorian.has(args.sessionId) || (prefixPreflightContended || protectedSignedPrefix) && (deferredHistoryRefreshSessions.has(args.sessionId) || deferredMaterializationSessions.has(args.sessionId) || historyRefreshSessions.has(args.sessionId)) || readExecuteReclaimState(args.db, args.sessionId).floorOrdinal !== null,
46922
+ reclaimableTokens: estimateExecuteReclaimTokens({
46923
+ db: args.db,
46924
+ sessionId: args.sessionId,
46925
+ pendingOps,
46926
+ tags: pendingOperationTags,
46927
+ targets: newTargets,
46928
+ protectedTagIds: new Set([
46929
+ ...protectedTagNumbersForPass,
46930
+ ...protectedToolTags
46931
+ ]),
46932
+ probePreparation: (targets) => {
46933
+ const saved = nativeRemovalInputs;
46934
+ const rollback = Symbol("execute removal probe");
46935
+ const allowed = new Set;
46936
+ try {
46937
+ nativeRemovalInputs = saved && new Map(saved);
46938
+ probingExecuteRemoval = true;
46939
+ args.db.transaction(() => {
46940
+ for (const [number, target] of targets) {
46941
+ if (target.prepareDrop?.() !== false)
46942
+ allowed.add(number);
46943
+ }
46944
+ throw rollback;
46945
+ }).immediate();
46946
+ } catch (error) {
46947
+ if (error !== rollback)
46948
+ allowed.clear();
46949
+ } finally {
46950
+ nativeRemovalInputs = saved;
46951
+ probingExecuteRemoval = false;
46952
+ }
46953
+ return allowed;
46954
+ }
46955
+ }),
46956
+ usableWindow: args.usableSoft ?? args.contextUsage.inputTokens / (args.contextUsage.percentage / 100)
46957
+ });
46958
+ if (rideSignals.executeReclaim) {
46959
+ isCacheBustingPass = reclaimRidePermitted(rideSignals, ridePermissionGate);
46960
+ publishedWorkDrainAllowed = isCacheBustingPass;
46961
+ shouldRunHeuristics ||= isCacheBustingPass && args.heuristics !== undefined;
46962
+ stripUnheldSignedTurnOnBust();
46963
+ applyTemporalOnRide();
46964
+ }
46208
46965
  const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
46209
46966
  const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
46210
46967
  const shouldApplyPendingOps = publishedWorkDrainAllowed;
@@ -46937,6 +47694,8 @@ async function runPipeline(args) {
46937
47694
  servedTagNumbers.add(tag.tagNumber);
46938
47695
  }
46939
47696
  }
47697
+ if (bustedThisPass)
47698
+ clearExecuteReclaimState(args.db, args.sessionId);
46940
47699
  return {
46941
47700
  messages: outputMessages,
46942
47701
  recoveryNormalized,
@@ -50592,7 +51351,7 @@ function stripTagPrefixFromAssistantMessage(message) {
50592
51351
  const textPart = part;
50593
51352
  if (typeof textPart.text !== "string")
50594
51353
  continue;
50595
- const stripped = stripPersistedAssistantText(textPart.text);
51354
+ const stripped = stripPersistedAssistantText(textPart.text, message.provider === "anthropic");
50596
51355
  if (stripped !== textPart.text) {
50597
51356
  textPart.text = stripped;
50598
51357
  mutated = true;
@@ -50600,7 +51359,7 @@ function stripTagPrefixFromAssistantMessage(message) {
50600
51359
  }
50601
51360
  return mutated;
50602
51361
  }
50603
- function strippedAssistantContent(content) {
51362
+ function strippedAssistantContent(content, provider = "anthropic") {
50604
51363
  if (!Array.isArray(content))
50605
51364
  return;
50606
51365
  let copy;
@@ -50611,7 +51370,7 @@ function strippedAssistantContent(content) {
50611
51370
  }
50612
51371
  if (typeof part.text !== "string")
50613
51372
  continue;
50614
- const stripped = stripPersistedAssistantText(part.text);
51373
+ const stripped = stripPersistedAssistantText(part.text, provider === "anthropic");
50615
51374
  if (stripped === part.text)
50616
51375
  continue;
50617
51376
  copy ??= content.slice();
@@ -50628,7 +51387,7 @@ function registerOmpAssistantMessageStrip(pi, isActive) {
50628
51387
  const message = event?.message;
50629
51388
  if (message?.role !== "assistant")
50630
51389
  return;
50631
- const content = strippedAssistantContent(message.content);
51390
+ const content = strippedAssistantContent(message.content, message.provider ?? "unknown");
50632
51391
  return content === undefined ? undefined : { content };
50633
51392
  } catch {
50634
51393
  return;
@@ -51097,6 +51856,7 @@ function resolveHistorianFromConfig(config, harness = PI_HARNESS_KIND, modelRegi
51097
51856
  return {
51098
51857
  runner: new PiSubagentRunner,
51099
51858
  model,
51859
+ modelConfigKey: resolved.primary?.sourceConfigKey,
51100
51860
  fallbackModels,
51101
51861
  historianChunkTokens,
51102
51862
  historianContextLimit: resolveKnownHistorianContextLimit(model),
@@ -51174,7 +51934,7 @@ async function src_default(pi) {
51174
51934
  let openFailureCause = null;
51175
51935
  const openStorage = async () => {
51176
51936
  try {
51177
- return await openDatabaseAsync();
51937
+ return await openDatabaseAsync({ nativeTurnDeadlines: true });
51178
51938
  } catch (error) {
51179
51939
  openFailureCause = error instanceof Error ? error.message : String(error);
51180
51940
  return null;
@@ -51575,6 +52335,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
51575
52335
  const todowriteOverlayEnabled = todowriteEnabled && bootProjectDeps.config.todowrite.overlay;
51576
52336
  registerMagicContextTools(pi, {
51577
52337
  rerankConnectionFile: config.subc?.connection_file,
52338
+ rerankConfig: config.rerank,
51578
52339
  expandTools: config.historian?.expand_tools,
51579
52340
  db,
51580
52341
  ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,