@cortexkit/opencode-magic-context 0.49.25 → 0.49.27

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 (124) hide show
  1. package/dist/auto-search-worker.js +4 -4
  2. package/dist/chunk-embedding-write-worker.js +7 -7
  3. package/dist/{compartment-chunk-embedding-eypvn607.js → compartment-chunk-embedding-qgp0tbf7.js} +3 -3
  4. package/dist/config/schema/magic-context.d.ts +393 -393
  5. package/dist/{conflict-warning-hook-a27bhggg.js → conflict-warning-hook-tgnw019g.js} +4 -4
  6. package/dist/{context-keb00be8.js → context-t2k97d6v.js} +116 -116
  7. package/dist/{embedding-backfill-vddgmem3.js → embedding-backfill-cwnyr4fj.js} +5 -5
  8. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  9. package/dist/features/magic-context/message-index-async.d.ts +1 -4
  10. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  11. package/dist/features/magic-context/message-index.d.ts +1 -28
  12. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  13. package/dist/features/magic-context/session-retention.fixture.d.ts +4 -0
  14. package/dist/features/magic-context/session-retention.fixture.d.ts.map +1 -0
  15. package/dist/features/magic-context/storage-session-tables.d.ts +5 -12
  16. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  17. package/dist/hooks/magic-context/caveman-cleanup.d.ts +14 -0
  18. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  19. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +11 -0
  20. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  21. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/foreign-text-parts.d.ts +47 -0
  23. package/dist/hooks/magic-context/foreign-text-parts.d.ts.map +1 -0
  24. package/dist/hooks/magic-context/historian-history-wait.d.ts +10 -0
  25. package/dist/hooks/magic-context/historian-history-wait.d.ts.map +1 -0
  26. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +0 -5
  28. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +0 -10
  30. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/read-session-chunk.d.ts +21 -0
  32. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/read-session-raw.d.ts +20 -0
  34. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/tag-messages.d.ts +15 -0
  36. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/todo-view.d.ts +2 -2
  38. package/dist/hooks/magic-context/transform.d.ts +7 -0
  39. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  40. package/dist/{index-jcr6pe7z.js → index-077ht5cq.js} +1 -1
  41. package/dist/{index-ebsvmc5s.js → index-31y1mznz.js} +4 -4
  42. package/dist/{index-q7ywt6xt.js → index-4cpc59jv.js} +5 -5
  43. package/dist/{index-t6j3qxnd.js → index-4ypqzvhf.js} +1 -1
  44. package/dist/index-7gbcg8xv.js +559 -0
  45. package/dist/{index-9q1g3c5q.js → index-7kkphb6c.js} +1 -1
  46. package/dist/{index-bhyksfyy.js → index-89k1w6x2.js} +3 -3
  47. package/dist/{index-z05n7702.js → index-a2fz9hpa.js} +1 -1
  48. package/dist/{index-0s8454t2.js → index-dcqk0y27.js} +1560 -91
  49. package/dist/{index-n18sch77.js → index-dzfevacx.js} +9 -9
  50. package/dist/{index-axjgxeww.js → index-fq2p158w.js} +169 -13
  51. package/dist/{index-3d5wnkq7.js → index-mm93m7y6.js} +1 -1
  52. package/dist/{index-zzrzjnx5.js → index-n8qmmd7f.js} +3 -3
  53. package/dist/{index-whcgcfrv.js → index-np3rgfw4.js} +1 -1
  54. package/dist/{index-y6xpzjzr.js → index-qzbpbnqt.js} +585 -602
  55. package/dist/{index-7tdtpqrg.js → index-rverk2vz.js} +39 -8
  56. package/dist/{index-cfaet9cg.js → index-s1n8dd2n.js} +1 -1
  57. package/dist/{index-z928hmnp.js → index-t3rbb8wr.js} +2 -2
  58. package/dist/{index-2haxh8h3.js → index-tvzvjggy.js} +1 -1
  59. package/dist/{index-c9zrgcnt.js → index-v0dhhxsq.js} +1 -1
  60. package/dist/{index-szf8r0ba.js → index-v15ne3a3.js} +2 -5
  61. package/dist/{index-x9k3mqrf.js → index-xrnsygfq.js} +1 -1
  62. package/dist/{index-yrrsp47d.js → index-yzjhx10y.js} +20 -6
  63. package/dist/index.js +40 -38
  64. package/dist/{message-fts-rowid-map-9e1getgs.js → message-fts-rowid-map-va36knh4.js} +2 -4
  65. package/dist/{message-index-bounded-vaeqhp9w.js → message-index-bounded-7ayzb2ah.js} +22 -25
  66. package/dist/migration-worker.js +6 -6
  67. package/dist/plugin/dream-timer.d.ts.map +1 -1
  68. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  69. package/dist/{project-embedding-registry-rstzmb60.js → project-embedding-registry-94nncs5g.js} +4 -4
  70. package/dist/raw-ordinal-warmup-worker.js +7 -30
  71. package/dist/{read-session-chunk-z5gnc0zb.js → read-session-chunk-jzb6w9w5.js} +8 -6
  72. package/dist/{read-session-raw-s4amywnh.js → read-session-raw-b2sd67v4.js} +3 -1
  73. package/dist/{recomp-orchestrator-qwqeskhq.js → recomp-orchestrator-02sa2ngr.js} +17 -17
  74. package/dist/{search-archive-mfabzyn2.js → search-archive-q1vw7zg4.js} +7 -7
  75. package/dist/{search-84zfqeky.js → search-spq6nfyf.js} +14 -15
  76. package/dist/{send-session-notification-ygj4mja0.js → send-session-notification-afzzqy5b.js} +3 -3
  77. package/dist/{storage-tags-a77q4v77.js → storage-tags-6hvkk01c.js} +2 -2
  78. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  79. package/dist/{transform-postprocess-phase-hr1ntmjj.js → transform-postprocess-phase-6menyyxc.js} +17 -17
  80. package/dist/v2/auto-search-worker.js +4 -4
  81. package/dist/v2/chunk-embedding-write-worker.js +7 -7
  82. package/dist/v2/{compartment-chunk-embedding-tk6g4q80.js → compartment-chunk-embedding-63dzs31c.js} +3 -3
  83. package/dist/v2/{context-y7wfvdve.js → context-na0esngr.js} +342 -218
  84. package/dist/v2/{embedding-backfill-w5qp7t28.js → embedding-backfill-rh5dgsva.js} +5 -5
  85. package/dist/v2/hooks/context.d.ts.map +1 -1
  86. package/dist/v2/{message-fts-rowid-map-pqk3a55v.js → message-fts-rowid-map-78awh03v.js} +2 -4
  87. package/dist/v2/{message-index-bounded-te303atj.js → message-index-bounded-n09b74vr.js} +21 -24
  88. package/dist/v2/migration-worker.js +6 -6
  89. package/dist/v2/{project-embedding-registry-e7zftfvj.js → project-embedding-registry-6pak822h.js} +4 -4
  90. package/dist/v2/raw-ordinal-warmup-worker.js +7 -30
  91. package/dist/v2/{read-session-chunk-knvkq1hf.js → read-session-chunk-vpt69tw9.js} +7 -5
  92. package/dist/v2/{read-session-raw-ppjxnqk4.js → read-session-raw-5x088amc.js} +3 -1
  93. package/dist/v2/{recomp-orchestrator-e8a4jpvr.js → recomp-orchestrator-txsmbnvw.js} +14 -14
  94. package/dist/v2/{search-archive-vrwgxv6z.js → search-archive-t9bcz4ht.js} +6 -6
  95. package/dist/v2/{search-hav4dggf.js → search-dcy9b6gd.js} +13 -14
  96. package/dist/v2/{send-session-notification-f8scq6ae.js → send-session-notification-vdsgnf4c.js} +1 -1
  97. package/dist/v2/{server-pw21ypwb.js → server-4sn3at8p.js} +1 -1
  98. package/dist/v2/{server-8j2e7t31.js → server-6avtp9jp.js} +1 -1
  99. package/dist/v2/{server-wwaw5npa.js → server-6g98c227.js} +1 -1
  100. package/dist/v2/{server-swvhxhxz.js → server-6vd2n183.js} +39 -8
  101. package/dist/v2/{server-wxrdher8.js → server-awr8qa4c.js} +2 -5
  102. package/dist/v2/{server-7d6m1p2b.js → server-cqjvxyrp.js} +1 -1
  103. package/dist/v2/{server-e75vag9d.js → server-e3hc93wk.js} +5 -5
  104. package/dist/v2/{server-7weh65vd.js → server-jj9qye8y.js} +1520 -79
  105. package/dist/v2/{server-fa7vtp40.js → server-nxas8v1d.js} +1 -1
  106. package/dist/v2/{server-tfawsj08.js → server-txbc3czn.js} +9 -9
  107. package/dist/v2/{server-rqebawx1.js → server-v77xa5wj.js} +1 -1
  108. package/dist/v2/{server-5brp2rfn.js → server-xkvxss5g.js} +19 -5
  109. package/dist/v2/{server-q5z0gag0.js → server-yqek3s4k.js} +1 -1
  110. package/dist/v2/server-z2n2xaeh.js +538 -0
  111. package/dist/v2/{server-9xbbaekh.js → server-z3mk9jdc.js} +2 -2
  112. package/dist/v2/{server-m6yyn961.js → server-zmcrvpm3.js} +2 -2
  113. package/dist/v2/server.js +2 -2
  114. package/dist/v2/{storage-tags-q71rnr9f.js → storage-tags-18nbaanf.js} +2 -2
  115. package/dist/v2/store-reader.d.ts +0 -2
  116. package/dist/v2/store-reader.d.ts.map +1 -1
  117. package/dist/v2/{wrapup-orchestrator-ycs8y6n4.js → wrapup-orchestrator-gjkszser.js} +14 -14
  118. package/dist/{wrapup-orchestrator-f642w8n3.js → wrapup-orchestrator-n5h5sr1x.js} +18 -18
  119. package/package.json +1 -1
  120. package/src/shared/write-transaction-attribution.test.ts +1 -6
  121. package/dist/index-awcftgmx.js +0 -2251
  122. package/dist/message-index-3g966xn7.js +0 -61
  123. package/dist/v2/message-index-fz6b4jeh.js +0 -60
  124. package/dist/v2/server-6a8pxpxg.js +0 -2220
@@ -144,11 +144,11 @@ import {
144
144
  getDroppedTagsByNumbers2,
145
145
  getMaxDroppedTagNumber2,
146
146
  getTagById2
147
- } from "./index-whcgcfrv.js";
147
+ } from "./index-np3rgfw4.js";
148
148
  import {
149
149
  observeTemporalDecisions,
150
150
  stableStringify
151
- } from "./index-x9k3mqrf.js";
151
+ } from "./index-xrnsygfq.js";
152
152
  import {
153
153
  withContentLanguageDirective,
154
154
  parseCron,
@@ -169,7 +169,7 @@ import {
169
169
  buildInMemoryTailRawMessages2,
170
170
  RawOrdinalsNotReady2,
171
171
  runSessionWarmupWorker
172
- } from "./index-7tdtpqrg.js";
172
+ } from "./index-rverk2vz.js";
173
173
  import {
174
174
  openCodeDbExists,
175
175
  withReadOnlySessionDb,
@@ -177,7 +177,7 @@ import {
177
177
  latestPersistedMessageForRecovery,
178
178
  latestRealUserTurnIdFromOpenCodeDb,
179
179
  findLastAssistantModelFromOpenCodeDb
180
- } from "./index-c9zrgcnt.js";
180
+ } from "./index-v0dhhxsq.js";
181
181
  import {
182
182
  expandToolPart,
183
183
  askAnswerLines,
@@ -302,11 +302,11 @@ import {
302
302
  readRawSessionMessageById2,
303
303
  readSessionChunk2,
304
304
  readRawSessionSeedTail2
305
- } from "./index-yrrsp47d.js";
305
+ } from "./index-yzjhx10y.js";
306
306
  import {
307
307
  BoundedSessionMap,
308
308
  getMeasuredToolDefinitionTokens
309
- } from "./index-cfaet9cg.js";
309
+ } from "./index-s1n8dd2n.js";
310
310
  import {
311
311
  isFailClosedBlockingError,
312
312
  shouldBypassFailClosedBlock,
@@ -320,7 +320,7 @@ import {
320
320
  runSqliteOptimize,
321
321
  openDatabase,
322
322
  openCurrentDatabase
323
- } from "./index-q7ywt6xt.js";
323
+ } from "./index-4cpc59jv.js";
324
324
  import {
325
325
  registerOwnRpcServerInstance,
326
326
  rpcPortDir,
@@ -339,7 +339,7 @@ import {
339
339
  resolveStoredPathWorkspaceIdentity,
340
340
  storedPathBelongsToWorkspace,
341
341
  computeWorkspaceEpochFingerprint
342
- } from "./index-9q1g3c5q.js";
342
+ } from "./index-7kkphb6c.js";
343
343
  import {
344
344
  V2_MEMORY_CATEGORIES,
345
345
  CATEGORY_PRIORITY
@@ -368,6 +368,15 @@ import {
368
368
  getLastCompartmentEndMessage,
369
369
  getLastCompartmentEndMessageId,
370
370
  providerResponseFailed,
371
+ LkgRecoveryFenceError,
372
+ lkgServedArrayDigest,
373
+ hasCleanLkgRecoveryFence,
374
+ dirtyLkgRecoveryRevision,
375
+ ownsLkgDirtyFence,
376
+ invalidateCleanLkgRecoveryFence,
377
+ prepareLkgCaptureFence,
378
+ certifyCommittedLkgCapture,
379
+ markLkgRecoveryDirty,
371
380
  getOrCreateSessionMeta,
372
381
  updateSessionMeta,
373
382
  retryPendingSessionCleanups,
@@ -495,6 +504,7 @@ import {
495
504
  readCoordinateRebaseNotice,
496
505
  formatCoordinateRebaseNotice,
497
506
  rebaseSessionCoordinatesAsync,
507
+ shouldWaitForNewHistorianHistory,
498
508
  EMPTY_READ_REPLY,
499
509
  noteTouchedAt,
500
510
  renderGlance,
@@ -515,7 +525,7 @@ import {
515
525
  snapRangeToCompartments,
516
526
  getActiveCompartmentRun,
517
527
  startCompartmentAgent
518
- } from "./index-0s8454t2.js";
528
+ } from "./index-dcqk0y27.js";
519
529
  import {
520
530
  embedPauseBySession,
521
531
  embedRunStateBySession,
@@ -543,7 +553,7 @@ import {
543
553
  embedSessionCompartmentChunks2,
544
554
  getEmbeddingCoverageStatus2,
545
555
  getAutoEmbeddingSessionCoverage2
546
- } from "./index-z05n7702.js";
556
+ } from "./index-a2fz9hpa.js";
547
557
  import {
548
558
  SubcClient,
549
559
  connectionFileExists,
@@ -553,27 +563,15 @@ import {
553
563
  SynapseEmbeddingProvider
554
564
  } from "./index-wfybj1dw.js";
555
565
  import {
556
- LkgRecoveryFenceError,
557
- lkgServedArrayDigest,
558
- takeLkgRecoveryLockSweepPage,
559
- hasCleanLkgRecoveryFence,
560
- dirtyLkgRecoveryRevision,
561
- ownsLkgDirtyFence,
562
- invalidateCleanLkgRecoveryFence,
563
- prepareLkgCaptureFence,
564
- certifyCommittedLkgCapture,
565
- markLkgRecoveryDirty,
566
- gaDatabasePath,
567
- getMessageIndexSourceIdentity2,
568
- isMessageIndexSourceCurrent2,
569
- getLastIndexedOrdinal2,
570
- getMessageIndexReconciliationStartOrdinal2,
571
- isMessageIndexReconciledThrough2,
572
- clearIndexedMessages2,
573
- indexSingleMessage2,
574
- indexMessagesAfterOrdinal2,
575
- sweepOrphanedOpenCodeMessageIndexesCooperatively2
576
- } from "./index-awcftgmx.js";
566
+ getMessageIndexSourceIdentity,
567
+ isMessageIndexSourceCurrent,
568
+ getLastIndexedOrdinal,
569
+ getMessageIndexReconciliationStartOrdinal,
570
+ isMessageIndexReconciledThrough,
571
+ clearIndexedMessages,
572
+ indexSingleMessage,
573
+ indexMessagesAfterOrdinal
574
+ } from "./index-7gbcg8xv.js";
577
575
  import {
578
576
  renderUserFacingFailure,
579
577
  userFacingFailureCode,
@@ -617,7 +615,7 @@ import {
617
615
  readGitFileChangeTimesSince,
618
616
  verificationFileExists,
619
617
  normalizeVerificationFiles
620
- } from "./index-z928hmnp.js";
618
+ } from "./index-t3rbb8wr.js";
621
619
  import {
622
620
  registerNotificationSink2,
623
621
  pushNotification2,
@@ -637,7 +635,7 @@ import {
637
635
  } from "./index-4dhv7mqz.js";
638
636
  import {
639
637
  cosineSimilarity
640
- } from "./index-t6j3qxnd.js";
638
+ } from "./index-4ypqzvhf.js";
641
639
  import {
642
640
  computeCueContentHash,
643
641
  hasMuralCueColumns,
@@ -683,17 +681,17 @@ import {
683
681
  resolveMemoriesByIdsForSearch2,
684
682
  unifiedSearch2,
685
683
  formatSearchResults2
686
- } from "./index-n18sch77.js";
684
+ } from "./index-dzfevacx.js";
687
685
  import {
688
686
  flushIgnoredMessages2,
689
687
  clearIgnoredMessages2,
690
688
  observeIgnoredNotificationEvent2,
691
689
  sendStatusNotification2
692
- } from "./index-jcr6pe7z.js";
690
+ } from "./index-077ht5cq.js";
693
691
  import {
694
692
  setRecompStarting2,
695
693
  setRecompTerminal2
696
- } from "./index-zzrzjnx5.js";
694
+ } from "./index-n8qmmd7f.js";
697
695
  import {
698
696
  makeToolCompositeKey,
699
697
  searchMessageHistoryOffThread,
@@ -741,6 +739,7 @@ import {
741
739
  prewarmTagOwners,
742
740
  waitForTagOwners,
743
741
  stripStructuralNoise,
742
+ isLegacyForeignTextTag,
744
743
  withTransformTimingSummary,
745
744
  logTransformTiming,
746
745
  hasRecentAssistantCommit,
@@ -754,7 +753,7 @@ import {
754
753
  abortSessionFailClosed2,
755
754
  evaluateEmergencyFailClosed2,
756
755
  runPostTransformPhase2
757
- } from "./index-axjgxeww.js";
756
+ } from "./index-fq2p158w.js";
758
757
  import {
759
758
  ANNOUNCEMENT_VERSION2,
760
759
  ANNOUNCEMENT_FEATURES2,
@@ -767,7 +766,7 @@ import {
767
766
  } from "./index-fmsr7v69.js";
768
767
  import {
769
768
  renderSearchArchiveOffThread2
770
- } from "./index-bhyksfyy.js";
769
+ } from "./index-89k1w6x2.js";
771
770
  import {
772
771
  COMPACTION_ENABLED_PATH,
773
772
  isDreamerRunnable,
@@ -9064,6 +9063,21 @@ function verifyAssistantText(messages) {
9064
9063
  const start = text.lastIndexOf("<verify>");
9065
9064
  return start >= 0 ? text.slice(start) : text;
9066
9065
  }
9066
+ function validateVerifyCompletion(messages, text, expectedIds, responseText = text) {
9067
+ let parsed;
9068
+ try {
9069
+ parsed = validateVerifyManifest(text, expectedIds);
9070
+ } catch (error) {
9071
+ throw providerOutputFailureFromInvalidManifest(messages, responseText) ?? error;
9072
+ }
9073
+ const ids = [...parsed.verified, ...parsed.updated, ...parsed.archived, ...parsed.skipped].map((entry) => entry.id);
9074
+ if (ids.length !== expectedIds.size || ids.some((id) => !expectedIds.has(id))) {
9075
+ const providerFailure = providerOutputFailureFromInvalidManifest(messages, responseText);
9076
+ if (providerFailure)
9077
+ throw providerFailure;
9078
+ }
9079
+ return parsed;
9080
+ }
9067
9081
  var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
9068
9082
  var VERIFY_BATCH_FLOOR_MS = 30000;
9069
9083
  function computeVerifyBatchSliceMs(remainingMs, _batchesRemaining) {
@@ -9222,6 +9236,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9222
9236
  const timer = setTimeout(() => batchController.abort(new Error(`verify slice timed out after ${sliceMs}ms`)), sliceMs);
9223
9237
  const batchSignal = batchController.signal;
9224
9238
  const tokenBudget = verifyBatchTokenBudget(batch.length, args.tokenBudget);
9239
+ const expectedIds = new Set(batch.map((memory) => memory.id));
9225
9240
  let agentSessionId = null;
9226
9241
  let hiddenSessionId = null;
9227
9242
  let promptSettled = false;
@@ -9274,13 +9289,10 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9274
9289
  onBudgetUpdate({ spent: 0, finalizeFired: false, sessionId });
9275
9290
  },
9276
9291
  parse: (text, completion) => {
9277
- const providerFailure = providerOutputFailureFromInvalidManifest(completion.messages ?? [], text);
9278
- if (providerFailure)
9279
- throw providerFailure;
9280
9292
  const manifest = verifyAssistantText(completion.messages ?? []) ?? (text.trim() ? text : null);
9281
9293
  if (!manifest)
9282
9294
  throw new Error("verify returned no output");
9283
- return validateVerifyManifest(manifest, new Set(batch.map((memory) => memory.id)));
9295
+ return validateVerifyCompletion(completion.messages ?? [], manifest, expectedIds, text);
9284
9296
  }
9285
9297
  });
9286
9298
  recordInvocation4(args, startedAt, {
@@ -9342,10 +9354,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9342
9354
  const text = verifyAssistantText(messages);
9343
9355
  if (!text)
9344
9356
  throw new Error("verify returned no output");
9345
- const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
9346
- if (providerFailure)
9347
- throw providerFailure;
9348
- return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
9357
+ return validateVerifyCompletion(messages, text, expectedIds);
9349
9358
  }
9350
9359
  });
9351
9360
  promptSettled = true;
@@ -11468,471 +11477,92 @@ function clearDreamerTickFailure(db) {
11468
11477
  db.prepare("DELETE FROM schema_migrations_meta WHERE key = ?").run(DREAMER_TICK_FAILURE_KEY);
11469
11478
  }
11470
11479
 
11471
- // src/features/magic-context/message-index-async.ts
11472
- var indexCancellations = new Map;
11473
- var sessionEpochs = new Map;
11474
- var workerMeasurements = new WeakMap;
11475
- function isDatabaseLockedError(error) {
11476
- if (!error || typeof error !== "object")
11480
+ // src/plugin/dream-timer.ts
11481
+ var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
11482
+ var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
11483
+ var BOOT_PROJECT_JITTER_SLOT_MS = 1000;
11484
+ var activeTimer = null;
11485
+ var tickInFlight = false;
11486
+ var startupTickTimer = null;
11487
+ var startupTimers = new Map;
11488
+ var startupJitters = new Map;
11489
+ var nextStartupJitterSlot = 0;
11490
+ function directoryStillExists(directory) {
11491
+ try {
11492
+ return statSync2(directory).isDirectory();
11493
+ } catch {
11477
11494
  return false;
11478
- const e = error;
11479
- if (typeof e.code === "string") {
11480
- if (e.code === "SQLITE_BUSY" || e.code === "SQLITE_LOCKED")
11481
- return true;
11482
- }
11483
- if (typeof e.message === "string") {
11484
- if (/database is locked/i.test(e.message))
11485
- return true;
11486
- if (/sqlite_(busy|locked)/i.test(e.message))
11487
- return true;
11488
11495
  }
11489
- return false;
11490
- }
11491
- var INCREMENTAL_DEBOUNCE_MS = 100;
11492
- var RECONCILIATION_BATCH_SIZE = 100;
11493
-
11494
- class MagicContextMessageIndexHeapHolder {
11495
- reconciledSessions = new Set;
11496
- reconciledSnapshots = new Map;
11497
- stalledSessions = new Set;
11498
- reconciliationScheduledSessions = new Set;
11499
- clearAndReindexScheduledSessions = new Map;
11500
- sessionLocks = new Map;
11501
- incrementalTimers = new Map;
11502
- pendingIncrementalKeys = new Set;
11503
- completedIncrementalKeys = new Set;
11504
- activeReconcilerBuffers = new Map;
11505
11496
  }
11506
- var heapHolder = new MagicContextMessageIndexHeapHolder;
11507
- function clearCompletedIncrementalKeys(sessionId) {
11508
- const prefix = `${sessionId}\x00`;
11509
- for (const key of heapHolder.completedIncrementalKeys) {
11510
- if (key.startsWith(prefix))
11511
- heapHolder.completedIncrementalKeys.delete(key);
11497
+ function openTimerDatabaseOrNull(context) {
11498
+ let db;
11499
+ try {
11500
+ db = openCurrentDatabase();
11501
+ } catch (error) {
11502
+ log2(`[dreamer] storage fatal; skipping ${context}: ${getErrorMessage(error)}`);
11503
+ return null;
11512
11504
  }
11513
- }
11514
- var PREPARE_RETRY_MS = 60000;
11515
- async function sourceReady(source, sessionId) {
11516
- const prepare = source?.prepare;
11517
- return typeof prepare === "function" ? prepare(sessionId) : true;
11518
- }
11519
- function defer(fn) {
11520
- const immediate = globalThis.setImmediate;
11521
- if (typeof immediate === "function") {
11522
- inRootAsyncContext2(() => immediate(fn));
11523
- return;
11505
+ if (!db) {
11506
+ log2(`[dreamer] storage unavailable; skipping ${context} (the cache schema is newer than this binary supports — restart/upgrade OpenCode/Pi/Magic Context to recover)`);
11507
+ return null;
11524
11508
  }
11525
- inRootAsyncContext2(() => setTimeout(fn, 0));
11526
- }
11527
- function yieldToEventLoop() {
11528
- return new Promise((resolve) => defer(resolve));
11509
+ return db;
11529
11510
  }
11530
- function runWithSessionLock(sessionId, operation) {
11531
- const previous = heapHolder.sessionLocks.get(sessionId) ?? Promise.resolve();
11532
- const run = previous.catch(() => {
11533
- return;
11534
- }).then(async () => {
11535
- await operation();
11536
- });
11537
- heapHolder.sessionLocks.set(sessionId, run);
11538
- run.finally(() => {
11539
- if (heapHolder.sessionLocks.get(sessionId) === run) {
11540
- heapHolder.sessionLocks.delete(sessionId);
11541
- }
11542
- }).catch(() => {
11511
+ var refusedEmptyIdentityDirectories = new Set;
11512
+ function logEmptyIdentityRefusalOnce(directory) {
11513
+ if (refusedEmptyIdentityDirectories.has(directory))
11543
11514
  return;
11544
- });
11545
- return run;
11515
+ refusedEmptyIdentityDirectories.add(directory);
11516
+ log2(`[dreamer] not registering ${directory}: it has no project identity, so no project-scoped work runs for it`);
11546
11517
  }
11547
- function logIndexingError(sessionId, action, error) {
11548
- if (isDatabaseLockedError(error)) {
11549
- sessionLog2(sessionId, `message FTS async ${action} skipped (database busy; will retry on next reconciliation)`);
11518
+ var registeredProjects = new Map;
11519
+ function stopDreamScheduleTimerIfIdle() {
11520
+ if (registeredProjects.size !== 0)
11550
11521
  return;
11522
+ const stopped = activeTimer !== null || startupTickTimer !== null;
11523
+ if (activeTimer) {
11524
+ clearInterval(activeTimer);
11525
+ activeTimer = null;
11551
11526
  }
11552
- sessionLog2(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
11553
- log2(`[message-index-async] ${action} failed for ${sessionId}:`, error);
11554
- }
11555
- function serializedMessageBytes(messages) {
11556
- try {
11557
- return Buffer.byteLength(JSON.stringify(messages));
11558
- } catch {
11559
- return 0;
11527
+ if (startupTickTimer) {
11528
+ clearTimeout(startupTickTimer);
11529
+ startupTickTimer = null;
11560
11530
  }
11531
+ startupJitters.clear();
11532
+ nextStartupJitterSlot = 0;
11533
+ if (stopped)
11534
+ log2("[dreamer] stopped dream schedule timer (no projects left)");
11561
11535
  }
11562
- function logReconciliationStall(sessionId, reason) {
11563
- if (heapHolder.stalledSessions.has(sessionId))
11536
+ async function startDreamScheduleTimer(args) {
11537
+ if (!isUsableProjectIdentity(args.projectIdentity)) {
11538
+ logEmptyIdentityRefusalOnce(args.directory);
11564
11539
  return;
11565
- heapHolder.stalledSessions.add(sessionId);
11566
- sessionLog2(sessionId, `message FTS reconciliation stalled: ${reason}; will retry`);
11567
- }
11568
- async function reconcileSessionIndex(db, sessionId, readMessages) {
11569
- if (!await sourceReady(readMessages, sessionId)) {
11570
- logReconciliationStall(sessionId, "raw message reader is not ready");
11571
- return false;
11572
11540
  }
11573
- await runWithSessionLock(sessionId, async () => {
11574
- if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId))
11575
- return;
11576
- let fallbackSnapshot = null;
11577
- try {
11578
- const fullReader = typeof readMessages === "function" ? readMessages : null;
11579
- const revision = readMessages.getRevision?.(sessionId);
11580
- const previous = heapHolder.reconciledSnapshots.get(sessionId);
11581
- 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;
11582
- let cursor = getMessageIndexReconciliationStartOrdinal2(db, sessionId);
11583
- let after = cursor === previous?.count ? previous.after : undefined;
11584
- while (cursor < finalWatermark) {
11585
- const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
11586
- const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
11587
- const retainedMessages = fallbackSnapshot ?? messages;
11588
- heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
11589
- withSqliteBackgroundWriter2(() => indexMessagesAfterOrdinal2(db, sessionId, messages, cursor, pageEnd));
11590
- const nextCursor = getMessageIndexReconciliationStartOrdinal2(db, sessionId);
11591
- if (nextCursor <= cursor)
11592
- break;
11593
- cursor = nextCursor;
11594
- const last = messages.at(-1);
11595
- after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
11596
- if (cursor < finalWatermark) {
11597
- await yieldToEventLoop();
11598
- }
11599
- }
11600
- if (isMessageIndexReconciledThrough2(db, sessionId, finalWatermark)) {
11601
- heapHolder.reconciledSessions.add(sessionId);
11602
- if (revision !== undefined) {
11603
- if (!after && finalWatermark > 0 && readMessages.readPage) {
11604
- const last = readMessages.readPage(sessionId, finalWatermark - 1, 1, finalWatermark).at(-1);
11605
- if (last?.ordinal === finalWatermark && typeof last.createdAt === "number")
11606
- after = { timeCreated: last.createdAt, id: last.id };
11607
- }
11608
- heapHolder.reconciledSnapshots.set(sessionId, {
11609
- revision,
11610
- count: finalWatermark,
11611
- after
11612
- });
11613
- }
11614
- } else {
11615
- logReconciliationStall(sessionId, `gap after ordinal ${cursor} (store count ${finalWatermark})`);
11616
- }
11617
- } finally {
11618
- heapHolder.activeReconcilerBuffers.delete(sessionId);
11619
- }
11620
- });
11621
- return true;
11622
- }
11623
- function scheduleReconciliation(db, sessionId, readMessages) {
11624
- if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
11541
+ beginBootQuietPeriod();
11542
+ const db = openTimerDatabaseOrNull("schedule timer registration");
11543
+ if (!db)
11625
11544
  return;
11545
+ const dreamingEnabled = Boolean(args.dreamerConfig && args.dreamerConfig.disable !== true);
11546
+ const embeddingSweepEnabled = args.memoryEnabled === true;
11547
+ const commitIndexingEnabled = args.gitCommitIndexing?.enabled === true;
11548
+ const previousRegistration = registeredProjects.get(args.directory);
11549
+ const isNewRegistration = previousRegistration === undefined;
11550
+ if (previousRegistration && previousRegistration !== args) {
11551
+ const pendingStartup = startupTimers.get(args.directory);
11552
+ if (pendingStartup) {
11553
+ clearTimeout(pendingStartup);
11554
+ startupTimers.delete(args.directory);
11555
+ }
11626
11556
  }
11627
- heapHolder.reconciliationScheduledSessions.add(sessionId);
11628
- scheduleAfterBootQuiet(() => {
11629
- defer(() => {
11630
- let appendedDuringReconciliation = false;
11631
- const previousSnapshot = heapHolder.reconciledSnapshots.get(sessionId);
11632
- reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
11633
- if (ran) {
11634
- const snapshot = heapHolder.reconciledSnapshots.get(sessionId);
11635
- appendedDuringReconciliation = snapshot !== undefined && snapshot !== previousSnapshot && readMessages.getRevision !== undefined && readMessages.getRevision(sessionId) !== snapshot.revision;
11636
- return;
11637
- }
11638
- inRootAsyncContext2(() => setTimeout(() => {
11639
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
11640
- scheduleReconciliation(db, sessionId, readMessages);
11641
- }, PREPARE_RETRY_MS)).unref?.();
11642
- }).catch((error) => {
11643
- logReconciliationStall(sessionId, error instanceof Error ? error.message : String(error));
11644
- if (isDatabaseLockedError(error))
11645
- inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
11646
- }).finally(() => {
11647
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
11648
- if (appendedDuringReconciliation)
11649
- scheduleReconciliation(db, sessionId, readMessages);
11650
- });
11651
- });
11652
- });
11653
- }
11654
- function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
11655
- const schedulingKey = `${sessionId}\x00${messageId}`;
11656
- const epoch = sessionEpochs.get(sessionId) ?? 0;
11657
- if (heapHolder.pendingIncrementalKeys.has(schedulingKey))
11658
- return;
11659
- const activeTimer = heapHolder.incrementalTimers.get(schedulingKey);
11660
- if (activeTimer)
11661
- clearTimeout(activeTimer);
11662
- const timer = inRootAsyncContext2(() => setTimeout(() => {
11663
- heapHolder.incrementalTimers.delete(schedulingKey);
11664
- heapHolder.pendingIncrementalKeys.add(schedulingKey);
11665
- const indexMessage = async () => {
11666
- if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
11667
- return;
11668
- const message = typeof messageSource === "function" ? messageSource(sessionId, messageId) : messageSource;
11669
- if (!message)
11670
- return;
11671
- const revisionKey = `${schedulingKey}\x00${getMessageIndexSourceIdentity2(message)}`;
11672
- if (heapHolder.completedIncrementalKeys.has(revisionKey))
11673
- return;
11674
- const currentWatermark = getLastIndexedOrdinal2(db, sessionId);
11675
- if (message.ordinal <= currentWatermark && isMessageIndexSourceCurrent2(db, sessionId, message)) {
11676
- heapHolder.completedIncrementalKeys.add(revisionKey);
11677
- return;
11678
- }
11679
- const wasReconciled = heapHolder.reconciledSessions.delete(sessionId);
11680
- await indexSingleMessageOffThread(db, sessionId, message);
11681
- if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
11682
- return;
11683
- const finalWatermark = getLastIndexedOrdinal2(db, sessionId);
11684
- if (wasReconciled && isMessageIndexReconciledThrough2(db, sessionId, finalWatermark)) {
11685
- heapHolder.reconciledSessions.add(sessionId);
11686
- }
11687
- heapHolder.completedIncrementalKeys.add(revisionKey);
11688
- };
11689
- sourceReady(messageSource, sessionId).then((ready) => {
11690
- if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
11691
- return;
11692
- if (ready)
11693
- return runWithSessionLock(sessionId, indexMessage);
11694
- setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), PREPARE_RETRY_MS).unref?.();
11695
- }).catch((error) => {
11696
- if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
11697
- return;
11698
- heapHolder.reconciledSessions.delete(sessionId);
11699
- logIndexingError(sessionId, `incremental index for ${messageId}`, error);
11700
- if (isDatabaseLockedError(error))
11701
- setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), 1000).unref();
11702
- }).finally(() => {
11703
- if ((sessionEpochs.get(sessionId) ?? 0) === epoch)
11704
- heapHolder.pendingIncrementalKeys.delete(schedulingKey);
11705
- });
11706
- }, INCREMENTAL_DEBOUNCE_MS));
11707
- heapHolder.incrementalTimers.set(schedulingKey, timer);
11708
- }
11709
- async function indexSingleMessageOffThread(db, sessionId, message) {
11710
- const path = getSqliteDatabasePath2(db);
11711
- if (!path)
11712
- return withSqliteBackgroundWriter2(() => indexSingleMessage2(db, sessionId, message));
11713
- const cancellation = new Int32Array(new SharedArrayBuffer(4));
11714
- const active = indexCancellations.get(sessionId) ?? new Set;
11715
- active.add(cancellation);
11716
- indexCancellations.set(sessionId, active);
11717
- const result = await runSessionWarmupWorker({
11718
- path,
11719
- sessionId,
11720
- indexMessage: message,
11721
- harness: getHarness2(),
11722
- indexCancellation: cancellation.buffer,
11723
- ...indexCoordinationInput2()
11724
- }, {}).finally(() => {
11725
- active.delete(cancellation);
11726
- if (active.size === 0)
11727
- indexCancellations.delete(sessionId);
11728
- });
11729
- if (!("inserted" in result))
11730
- throw new Error("failure" in result ? result.detail : "unexpected indexing worker reply");
11731
- if (result.measurements) {
11732
- const sessions = workerMeasurements.get(db) ?? new Map;
11733
- sessions.set(sessionId, result.measurements);
11734
- workerMeasurements.set(db, sessions);
11735
- if (result.measurements.skipped)
11736
- log2(`[magic-context] incremental FTS skipped oversized source ${message.id} (${result.measurements.sourceBytes} bytes); identity and progress persisted`);
11737
- }
11738
- return result.inserted;
11739
- }
11740
- async function sweepOrphanedOpenCodeMessageIndexesOffThread(db, openSource, options = {}) {
11741
- if (getHarness2() === "opencode" || getHarness2() === "opencode2")
11742
- options = {
11743
- ...options,
11744
- fenceLockNames: options.fenceLockNames ?? takeLkgRecoveryLockSweepPage()
11745
- };
11746
- if (getHarness2() === "opencode2")
11747
- openSource = () => new Database2(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"), {
11748
- readonly: true,
11749
- fileMustExist: true
11750
- });
11751
- const path = getSqliteDatabasePath2(db);
11752
- if (!path || getHarness2() !== "opencode" && getHarness2() !== "opencode2")
11753
- return sweepOrphanedOpenCodeMessageIndexesCooperatively2(db, openSource, options);
11754
- let source = null;
11755
- let sourcePath = null;
11756
- try {
11757
- source = openSource();
11758
- if (source)
11759
- sourcePath = getSqliteDatabasePath2(source);
11760
- } catch {} finally {
11761
- if (sourcePath)
11762
- source?.close();
11763
- }
11764
- if (!sourcePath)
11765
- return sweepOrphanedOpenCodeMessageIndexesCooperatively2(db, () => source, options);
11766
- const reply = await runSessionWarmupWorker({
11767
- path,
11768
- sessionId: "",
11769
- harness: getHarness2(),
11770
- orphanSweep: { sourcePath, options }
11771
- }, {});
11772
- if (!("orphanSweep" in reply))
11773
- throw new Error("message history orphan sweep worker failed");
11774
- return reply.orphanSweep;
11775
- }
11776
- function scheduleClearAndReindex(db, sessionId, readMessages) {
11777
- heapHolder.reconciledSessions.delete(sessionId);
11778
- heapHolder.reconciledSnapshots.delete(sessionId);
11779
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
11780
- clearCompletedIncrementalKeys(sessionId);
11781
- const existing = heapHolder.clearAndReindexScheduledSessions.get(sessionId);
11782
- if (existing) {
11783
- existing.source = readMessages;
11784
- return;
11785
- }
11786
- const pending = { source: readMessages };
11787
- heapHolder.clearAndReindexScheduledSessions.set(sessionId, pending);
11788
- scheduleAfterBootQuiet(() => {
11789
- defer(() => {
11790
- let cleared = false;
11791
- runWithSessionLock(sessionId, () => {
11792
- if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) !== pending)
11793
- return;
11794
- heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
11795
- heapHolder.reconciledSessions.delete(sessionId);
11796
- heapHolder.reconciledSnapshots.delete(sessionId);
11797
- clearCompletedIncrementalKeys(sessionId);
11798
- clearIndexedMessages2(db, sessionId);
11799
- cleared = true;
11800
- }).then(() => cleared ? reconcileSessionIndex(db, sessionId, pending.source) : undefined).catch((error) => {
11801
- heapHolder.reconciledSessions.delete(sessionId);
11802
- if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) === pending)
11803
- heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
11804
- logIndexingError(sessionId, "clear and reindex", error);
11805
- });
11806
- });
11807
- });
11808
- }
11809
- function getMessageIndexQueueHeapStats() {
11810
- return {
11811
- queueLength: heapHolder.reconciliationScheduledSessions.size + heapHolder.incrementalTimers.size + heapHolder.pendingIncrementalKeys.size,
11812
- reconciliationScheduled: heapHolder.reconciliationScheduledSessions.size,
11813
- incrementalTimers: heapHolder.incrementalTimers.size,
11814
- pendingIncremental: heapHolder.pendingIncrementalKeys.size,
11815
- activeSessionLocks: heapHolder.sessionLocks.size,
11816
- completedIncrementalKeys: heapHolder.completedIncrementalKeys.size,
11817
- activeBufferMessages: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + messages.length, 0),
11818
- activeBufferBytes: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + serializedMessageBytes(messages), 0)
11819
- };
11820
- }
11821
- function clearSessionTracking(sessionId) {
11822
- sessionEpochs.set(sessionId, (sessionEpochs.get(sessionId) ?? 0) + 1);
11823
- for (const cancellation of indexCancellations.get(sessionId) ?? [])
11824
- Atomics.store(cancellation, 0, 1);
11825
- heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
11826
- heapHolder.reconciledSessions.delete(sessionId);
11827
- heapHolder.reconciledSnapshots.delete(sessionId);
11828
- heapHolder.stalledSessions.delete(sessionId);
11829
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
11830
- heapHolder.sessionLocks.delete(sessionId);
11831
- heapHolder.activeReconcilerBuffers.delete(sessionId);
11832
- const prefix = `${sessionId}\x00`;
11833
- for (const [key, timer] of heapHolder.incrementalTimers) {
11834
- if (key.startsWith(prefix)) {
11835
- clearTimeout(timer);
11836
- heapHolder.incrementalTimers.delete(key);
11837
- }
11838
- }
11839
- for (const key of heapHolder.pendingIncrementalKeys) {
11840
- if (key.startsWith(prefix)) {
11841
- heapHolder.pendingIncrementalKeys.delete(key);
11842
- }
11843
- }
11844
- for (const key of heapHolder.completedIncrementalKeys) {
11845
- if (key.startsWith(prefix))
11846
- heapHolder.completedIncrementalKeys.delete(key);
11847
- }
11848
- }
11849
-
11850
- // src/plugin/dream-timer.ts
11851
- var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
11852
- var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
11853
- var BOOT_PROJECT_JITTER_SLOT_MS = 1000;
11854
- var activeTimer = null;
11855
- var tickInFlight = false;
11856
- var startupTickTimer = null;
11857
- var startupTimers = new Map;
11858
- var startupJitters = new Map;
11859
- var nextStartupJitterSlot = 0;
11860
- function directoryStillExists(directory) {
11861
- try {
11862
- return statSync2(directory).isDirectory();
11863
- } catch {
11864
- return false;
11865
- }
11866
- }
11867
- function openTimerDatabaseOrNull(context) {
11868
- let db;
11869
- try {
11870
- db = openCurrentDatabase();
11871
- } catch (error) {
11872
- log2(`[dreamer] storage fatal; skipping ${context}: ${getErrorMessage(error)}`);
11873
- return null;
11874
- }
11875
- if (!db) {
11876
- log2(`[dreamer] storage unavailable; skipping ${context} (the cache schema is newer than this binary supports — restart/upgrade OpenCode/Pi/Magic Context to recover)`);
11877
- return null;
11878
- }
11879
- return db;
11880
- }
11881
- var refusedEmptyIdentityDirectories = new Set;
11882
- function logEmptyIdentityRefusalOnce(directory) {
11883
- if (refusedEmptyIdentityDirectories.has(directory))
11884
- return;
11885
- refusedEmptyIdentityDirectories.add(directory);
11886
- log2(`[dreamer] not registering ${directory}: it has no project identity, so no project-scoped work runs for it`);
11887
- }
11888
- var registeredProjects = new Map;
11889
- function stopDreamScheduleTimerIfIdle() {
11890
- if (registeredProjects.size !== 0)
11891
- return;
11892
- const stopped = activeTimer !== null || startupTickTimer !== null;
11893
- if (activeTimer) {
11894
- clearInterval(activeTimer);
11895
- activeTimer = null;
11896
- }
11897
- if (startupTickTimer) {
11898
- clearTimeout(startupTickTimer);
11899
- startupTickTimer = null;
11900
- }
11901
- startupJitters.clear();
11902
- nextStartupJitterSlot = 0;
11903
- if (stopped)
11904
- log2("[dreamer] stopped dream schedule timer (no projects left)");
11905
- }
11906
- async function startDreamScheduleTimer(args) {
11907
- if (!isUsableProjectIdentity(args.projectIdentity)) {
11908
- logEmptyIdentityRefusalOnce(args.directory);
11909
- return;
11910
- }
11911
- beginBootQuietPeriod();
11912
- const db = openTimerDatabaseOrNull("schedule timer registration");
11913
- if (!db)
11914
- return;
11915
- const dreamingEnabled = Boolean(args.dreamerConfig && args.dreamerConfig.disable !== true);
11916
- const embeddingSweepEnabled = args.memoryEnabled === true;
11917
- const commitIndexingEnabled = args.gitCommitIndexing?.enabled === true;
11918
- const previousRegistration = registeredProjects.get(args.directory);
11919
- const isNewRegistration = previousRegistration === undefined;
11920
- if (previousRegistration && previousRegistration !== args) {
11921
- const pendingStartup = startupTimers.get(args.directory);
11922
- if (pendingStartup) {
11923
- clearTimeout(pendingStartup);
11924
- startupTimers.delete(args.directory);
11925
- }
11926
- }
11927
- registeredProjects.set(args.directory, args);
11928
- if (isNewRegistration) {
11929
- log2(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
11930
- }
11931
- if (!activeTimer) {
11932
- log2(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
11933
- startupTickTimer = scheduleAfterBootQuiet(() => {
11934
- startupTickTimer = null;
11935
- runTick("startup");
11557
+ registeredProjects.set(args.directory, args);
11558
+ if (isNewRegistration) {
11559
+ log2(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
11560
+ }
11561
+ if (!activeTimer) {
11562
+ log2(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
11563
+ startupTickTimer = scheduleAfterBootQuiet(() => {
11564
+ startupTickTimer = null;
11565
+ runTick("startup");
11936
11566
  });
11937
11567
  const timer = inRootAsyncContext2(() => setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS));
11938
11568
  if (typeof timer === "object" && "unref" in timer) {
@@ -12042,12 +11672,6 @@ async function runMessageHistoryMaintenance(db) {
12042
11672
  log2(`[message-index] pending Rust session cleanup: cleared=${rustCleanup.cleared} failed=${rustCleanup.failedSessionIds.length}`);
12043
11673
  }
12044
11674
  }
12045
- const sweep = await sweepOrphanedOpenCodeMessageIndexesOffThread(db, openOpenCodeDb);
12046
- if (sweep.reason)
12047
- log2(`[message-index] orphan sweep parked: ${sweep.reason}`);
12048
- if (sweep.deleted > 0) {
12049
- log2(`[message-index] orphan sweep: scanned=${sweep.scanned} deleted=${sweep.deleted} cursor=${sweep.cursor || "<complete>"}`);
12050
- }
12051
11675
  }
12052
11676
  function startupJitterMs(directory) {
12053
11677
  const existing = startupJitters.get(directory);
@@ -13040,104 +12664,447 @@ function createScheduler(config) {
13040
12664
  } else {
13041
12665
  log2(`[magic-context] invalid cache_ttl "${sessionMeta.cacheTtl}"; falling back to default 5m`, error);
13042
12666
  }
13043
- ttlMs = parseCacheTtl("5m");
12667
+ ttlMs = parseCacheTtl("5m");
12668
+ }
12669
+ const elapsedTime = currentTime - sessionMeta.lastResponseTime;
12670
+ if (elapsedTime > ttlMs) {
12671
+ return "execute";
12672
+ }
12673
+ return "defer";
12674
+ }
12675
+ };
12676
+ }
12677
+ function computeHardCacheExpired(cacheTtl, lastResponseTime, now, onInvalid) {
12678
+ let ttlMs;
12679
+ try {
12680
+ ttlMs = parseCacheTtl(cacheTtl);
12681
+ } catch (error) {
12682
+ onInvalid?.(error);
12683
+ ttlMs = 5 * 60 * 1000;
12684
+ }
12685
+ return lastResponseTime > 0 && now - lastResponseTime > ttlMs;
12686
+ }
12687
+
12688
+ // src/features/magic-context/storage-unavailable-reason.ts
12689
+ function describeStorageUnavailability(fallbackCause) {
12690
+ const migration = getMigrationOnOpenRefusal();
12691
+ const blockingProcesses = migration?.blockingProcesses ?? migration?.serverPids.map((pid) => ({ kind: "process", pid })) ?? [];
12692
+ if (migration && (blockingProcesses.length > 0 || migration.unreadableFile)) {
12693
+ return {
12694
+ kind: "migration_guard",
12695
+ persistedVersion: migration.persistedVersion,
12696
+ supportedVersion: migration.supportedVersion,
12697
+ blockingProcesses,
12698
+ ...migration.unreadableFile ? { unreadableFile: migration.unreadableFile } : {},
12699
+ ...migration.unreadableArm ? { unreadableArm: migration.unreadableArm } : {}
12700
+ };
12701
+ }
12702
+ const fence = getSchemaFenceRejection();
12703
+ if (fence) {
12704
+ return {
12705
+ kind: "schema_fence",
12706
+ persistedVersion: fence.persistedVersion,
12707
+ supportedVersion: fence.supportedVersion
12708
+ };
12709
+ }
12710
+ return { kind: "storage_failure", cause: fallbackCause };
12711
+ }
12712
+
12713
+ // src/plugin/rpc-handlers.ts
12714
+ import { randomUUID as randomUUID3 } from "node:crypto";
12715
+ import { once } from "node:events";
12716
+ import { rmSync as rmSync2 } from "node:fs";
12717
+ import { join as join5 } from "node:path";
12718
+
12719
+ // src/features/magic-context/memory/memory-diagnostics.ts
12720
+ function emptyMemoryImportanceHistogram() {
12721
+ return {
12722
+ total: 0,
12723
+ unclassified: 0,
12724
+ bands: {
12725
+ "0-19": 0,
12726
+ "20-39": 0,
12727
+ "40-59": 0,
12728
+ "60-79": 0,
12729
+ "80-100": 0
12730
+ }
12731
+ };
12732
+ }
12733
+ function readHistogramRow(db, projectPath, classifiedColumn) {
12734
+ const unclassified = classifiedColumn ? "SUM(CASE WHEN classified_at IS NULL THEN 1 ELSE 0 END)" : "COUNT(*)";
12735
+ return db.prepare(`SELECT COUNT(*) AS total,
12736
+ ${unclassified} AS unclassified,
12737
+ SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 0 AND 19 THEN 1 ELSE 0 END) AS band_0_19,
12738
+ SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 20 AND 39 THEN 1 ELSE 0 END) AS band_20_39,
12739
+ SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 40 AND 59 THEN 1 ELSE 0 END) AS band_40_59,
12740
+ SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 60 AND 79 THEN 1 ELSE 0 END) AS band_60_79,
12741
+ SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 80 AND 100 THEN 1 ELSE 0 END) AS band_80_100
12742
+ FROM memories
12743
+ WHERE project_path = ? AND status = 'active'`).get(projectPath);
12744
+ }
12745
+ function getActiveMemoryImportanceHistogram(db, projectPath) {
12746
+ let row;
12747
+ try {
12748
+ row = readHistogramRow(db, projectPath, true);
12749
+ } catch (error) {
12750
+ if (!String(error).includes("no such column: classified_at"))
12751
+ throw error;
12752
+ row = readHistogramRow(db, projectPath, false);
12753
+ }
12754
+ return {
12755
+ total: Number(row.total ?? 0),
12756
+ unclassified: Number(row.unclassified ?? 0),
12757
+ bands: {
12758
+ "0-19": Number(row.band_0_19 ?? 0),
12759
+ "20-39": Number(row.band_20_39 ?? 0),
12760
+ "40-59": Number(row.band_40_59 ?? 0),
12761
+ "60-79": Number(row.band_60_79 ?? 0),
12762
+ "80-100": Number(row.band_80_100 ?? 0)
12763
+ }
12764
+ };
12765
+ }
12766
+
12767
+ // src/features/magic-context/message-index-async.ts
12768
+ var indexCancellations = new Map;
12769
+ var sessionEpochs = new Map;
12770
+ var workerMeasurements = new WeakMap;
12771
+ function isDatabaseLockedError(error) {
12772
+ if (!error || typeof error !== "object")
12773
+ return false;
12774
+ const e = error;
12775
+ if (typeof e.code === "string") {
12776
+ if (e.code === "SQLITE_BUSY" || e.code === "SQLITE_LOCKED")
12777
+ return true;
12778
+ }
12779
+ if (typeof e.message === "string") {
12780
+ if (/database is locked/i.test(e.message))
12781
+ return true;
12782
+ if (/sqlite_(busy|locked)/i.test(e.message))
12783
+ return true;
12784
+ }
12785
+ return false;
12786
+ }
12787
+ var INCREMENTAL_DEBOUNCE_MS = 100;
12788
+ var RECONCILIATION_BATCH_SIZE = 100;
12789
+
12790
+ class MagicContextMessageIndexHeapHolder {
12791
+ reconciledSessions = new Set;
12792
+ reconciledSnapshots = new Map;
12793
+ stalledSessions = new Set;
12794
+ reconciliationScheduledSessions = new Set;
12795
+ clearAndReindexScheduledSessions = new Map;
12796
+ sessionLocks = new Map;
12797
+ incrementalTimers = new Map;
12798
+ pendingIncrementalKeys = new Set;
12799
+ completedIncrementalKeys = new Set;
12800
+ activeReconcilerBuffers = new Map;
12801
+ }
12802
+ var heapHolder = new MagicContextMessageIndexHeapHolder;
12803
+ function clearCompletedIncrementalKeys(sessionId) {
12804
+ const prefix = `${sessionId}\x00`;
12805
+ for (const key of heapHolder.completedIncrementalKeys) {
12806
+ if (key.startsWith(prefix))
12807
+ heapHolder.completedIncrementalKeys.delete(key);
12808
+ }
12809
+ }
12810
+ var PREPARE_RETRY_MS = 60000;
12811
+ async function sourceReady(source, sessionId) {
12812
+ const prepare = source?.prepare;
12813
+ return typeof prepare === "function" ? prepare(sessionId) : true;
12814
+ }
12815
+ function defer(fn) {
12816
+ const immediate = globalThis.setImmediate;
12817
+ if (typeof immediate === "function") {
12818
+ inRootAsyncContext2(() => immediate(fn));
12819
+ return;
12820
+ }
12821
+ inRootAsyncContext2(() => setTimeout(fn, 0));
12822
+ }
12823
+ function yieldToEventLoop() {
12824
+ return new Promise((resolve) => defer(resolve));
12825
+ }
12826
+ function runWithSessionLock(sessionId, operation) {
12827
+ const previous = heapHolder.sessionLocks.get(sessionId) ?? Promise.resolve();
12828
+ const run = previous.catch(() => {
12829
+ return;
12830
+ }).then(async () => {
12831
+ await operation();
12832
+ });
12833
+ heapHolder.sessionLocks.set(sessionId, run);
12834
+ run.finally(() => {
12835
+ if (heapHolder.sessionLocks.get(sessionId) === run) {
12836
+ heapHolder.sessionLocks.delete(sessionId);
12837
+ }
12838
+ }).catch(() => {
12839
+ return;
12840
+ });
12841
+ return run;
12842
+ }
12843
+ function logIndexingError(sessionId, action, error) {
12844
+ if (isDatabaseLockedError(error)) {
12845
+ sessionLog2(sessionId, `message FTS async ${action} skipped (database busy; will retry on next reconciliation)`);
12846
+ return;
12847
+ }
12848
+ sessionLog2(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
12849
+ log2(`[message-index-async] ${action} failed for ${sessionId}:`, error);
12850
+ }
12851
+ function serializedMessageBytes(messages) {
12852
+ try {
12853
+ return Buffer.byteLength(JSON.stringify(messages));
12854
+ } catch {
12855
+ return 0;
12856
+ }
12857
+ }
12858
+ function logReconciliationStall(sessionId, reason) {
12859
+ if (heapHolder.stalledSessions.has(sessionId))
12860
+ return;
12861
+ heapHolder.stalledSessions.add(sessionId);
12862
+ sessionLog2(sessionId, `message FTS reconciliation stalled: ${reason}; will retry`);
12863
+ }
12864
+ async function reconcileSessionIndex(db, sessionId, readMessages) {
12865
+ if (!await sourceReady(readMessages, sessionId)) {
12866
+ logReconciliationStall(sessionId, "raw message reader is not ready");
12867
+ return false;
12868
+ }
12869
+ await runWithSessionLock(sessionId, async () => {
12870
+ if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId))
12871
+ return;
12872
+ let fallbackSnapshot = null;
12873
+ try {
12874
+ const fullReader = typeof readMessages === "function" ? readMessages : null;
12875
+ const revision = readMessages.getRevision?.(sessionId);
12876
+ const previous = heapHolder.reconciledSnapshots.get(sessionId);
12877
+ 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;
12878
+ let cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
12879
+ let after = cursor === previous?.count ? previous.after : undefined;
12880
+ while (cursor < finalWatermark) {
12881
+ const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
12882
+ const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
12883
+ const retainedMessages = fallbackSnapshot ?? messages;
12884
+ heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
12885
+ withSqliteBackgroundWriter2(() => indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd));
12886
+ const nextCursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
12887
+ if (nextCursor <= cursor)
12888
+ break;
12889
+ cursor = nextCursor;
12890
+ const last = messages.at(-1);
12891
+ after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
12892
+ if (cursor < finalWatermark) {
12893
+ await yieldToEventLoop();
12894
+ }
12895
+ }
12896
+ if (isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
12897
+ heapHolder.reconciledSessions.add(sessionId);
12898
+ if (revision !== undefined) {
12899
+ if (!after && finalWatermark > 0 && readMessages.readPage) {
12900
+ const last = readMessages.readPage(sessionId, finalWatermark - 1, 1, finalWatermark).at(-1);
12901
+ if (last?.ordinal === finalWatermark && typeof last.createdAt === "number")
12902
+ after = { timeCreated: last.createdAt, id: last.id };
12903
+ }
12904
+ heapHolder.reconciledSnapshots.set(sessionId, {
12905
+ revision,
12906
+ count: finalWatermark,
12907
+ after
12908
+ });
12909
+ }
12910
+ } else {
12911
+ logReconciliationStall(sessionId, `gap after ordinal ${cursor} (store count ${finalWatermark})`);
12912
+ }
12913
+ } finally {
12914
+ heapHolder.activeReconcilerBuffers.delete(sessionId);
12915
+ }
12916
+ });
12917
+ return true;
12918
+ }
12919
+ function scheduleReconciliation(db, sessionId, readMessages) {
12920
+ if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
12921
+ return;
12922
+ }
12923
+ heapHolder.reconciliationScheduledSessions.add(sessionId);
12924
+ scheduleAfterBootQuiet(() => {
12925
+ defer(() => {
12926
+ let appendedDuringReconciliation = false;
12927
+ const previousSnapshot = heapHolder.reconciledSnapshots.get(sessionId);
12928
+ reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
12929
+ if (ran) {
12930
+ const snapshot = heapHolder.reconciledSnapshots.get(sessionId);
12931
+ appendedDuringReconciliation = snapshot !== undefined && snapshot !== previousSnapshot && readMessages.getRevision !== undefined && readMessages.getRevision(sessionId) !== snapshot.revision;
12932
+ return;
12933
+ }
12934
+ inRootAsyncContext2(() => setTimeout(() => {
12935
+ heapHolder.reconciliationScheduledSessions.delete(sessionId);
12936
+ scheduleReconciliation(db, sessionId, readMessages);
12937
+ }, PREPARE_RETRY_MS)).unref?.();
12938
+ }).catch((error) => {
12939
+ logReconciliationStall(sessionId, error instanceof Error ? error.message : String(error));
12940
+ if (isDatabaseLockedError(error))
12941
+ inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
12942
+ }).finally(() => {
12943
+ heapHolder.reconciliationScheduledSessions.delete(sessionId);
12944
+ if (appendedDuringReconciliation)
12945
+ scheduleReconciliation(db, sessionId, readMessages);
12946
+ });
12947
+ });
12948
+ });
12949
+ }
12950
+ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
12951
+ const schedulingKey = `${sessionId}\x00${messageId}`;
12952
+ const epoch = sessionEpochs.get(sessionId) ?? 0;
12953
+ if (heapHolder.pendingIncrementalKeys.has(schedulingKey))
12954
+ return;
12955
+ const activeTimer = heapHolder.incrementalTimers.get(schedulingKey);
12956
+ if (activeTimer)
12957
+ clearTimeout(activeTimer);
12958
+ const timer = inRootAsyncContext2(() => setTimeout(() => {
12959
+ heapHolder.incrementalTimers.delete(schedulingKey);
12960
+ heapHolder.pendingIncrementalKeys.add(schedulingKey);
12961
+ const indexMessage = async () => {
12962
+ if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
12963
+ return;
12964
+ const message = typeof messageSource === "function" ? messageSource(sessionId, messageId) : messageSource;
12965
+ if (!message)
12966
+ return;
12967
+ const revisionKey = `${schedulingKey}\x00${getMessageIndexSourceIdentity(message)}`;
12968
+ if (heapHolder.completedIncrementalKeys.has(revisionKey))
12969
+ return;
12970
+ const currentWatermark = getLastIndexedOrdinal(db, sessionId);
12971
+ if (message.ordinal <= currentWatermark && isMessageIndexSourceCurrent(db, sessionId, message)) {
12972
+ heapHolder.completedIncrementalKeys.add(revisionKey);
12973
+ return;
13044
12974
  }
13045
- const elapsedTime = currentTime - sessionMeta.lastResponseTime;
13046
- if (elapsedTime > ttlMs) {
13047
- return "execute";
12975
+ const wasReconciled = heapHolder.reconciledSessions.delete(sessionId);
12976
+ await indexSingleMessageOffThread(db, sessionId, message);
12977
+ if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
12978
+ return;
12979
+ const finalWatermark = getLastIndexedOrdinal(db, sessionId);
12980
+ if (wasReconciled && isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
12981
+ heapHolder.reconciledSessions.add(sessionId);
13048
12982
  }
13049
- return "defer";
13050
- }
13051
- };
12983
+ heapHolder.completedIncrementalKeys.add(revisionKey);
12984
+ };
12985
+ sourceReady(messageSource, sessionId).then((ready) => {
12986
+ if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
12987
+ return;
12988
+ if (ready)
12989
+ return runWithSessionLock(sessionId, indexMessage);
12990
+ setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), PREPARE_RETRY_MS).unref?.();
12991
+ }).catch((error) => {
12992
+ if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
12993
+ return;
12994
+ heapHolder.reconciledSessions.delete(sessionId);
12995
+ logIndexingError(sessionId, `incremental index for ${messageId}`, error);
12996
+ if (isDatabaseLockedError(error))
12997
+ setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), 1000).unref();
12998
+ }).finally(() => {
12999
+ if ((sessionEpochs.get(sessionId) ?? 0) === epoch)
13000
+ heapHolder.pendingIncrementalKeys.delete(schedulingKey);
13001
+ });
13002
+ }, INCREMENTAL_DEBOUNCE_MS));
13003
+ heapHolder.incrementalTimers.set(schedulingKey, timer);
13052
13004
  }
13053
- function computeHardCacheExpired(cacheTtl, lastResponseTime, now, onInvalid) {
13054
- let ttlMs;
13055
- try {
13056
- ttlMs = parseCacheTtl(cacheTtl);
13057
- } catch (error) {
13058
- onInvalid?.(error);
13059
- ttlMs = 5 * 60 * 1000;
13005
+ async function indexSingleMessageOffThread(db, sessionId, message) {
13006
+ const path = getSqliteDatabasePath2(db);
13007
+ if (!path)
13008
+ return withSqliteBackgroundWriter2(() => indexSingleMessage(db, sessionId, message));
13009
+ const cancellation = new Int32Array(new SharedArrayBuffer(4));
13010
+ const active = indexCancellations.get(sessionId) ?? new Set;
13011
+ active.add(cancellation);
13012
+ indexCancellations.set(sessionId, active);
13013
+ const result = await runSessionWarmupWorker({
13014
+ path,
13015
+ sessionId,
13016
+ indexMessage: message,
13017
+ harness: getHarness2(),
13018
+ indexCancellation: cancellation.buffer,
13019
+ ...indexCoordinationInput2()
13020
+ }, {}).finally(() => {
13021
+ active.delete(cancellation);
13022
+ if (active.size === 0)
13023
+ indexCancellations.delete(sessionId);
13024
+ });
13025
+ if (!("inserted" in result))
13026
+ throw new Error("failure" in result ? result.detail : "unexpected indexing worker reply");
13027
+ if (result.measurements) {
13028
+ const sessions = workerMeasurements.get(db) ?? new Map;
13029
+ sessions.set(sessionId, result.measurements);
13030
+ workerMeasurements.set(db, sessions);
13031
+ if (result.measurements.skipped)
13032
+ log2(`[magic-context] incremental FTS skipped oversized source ${message.id} (${result.measurements.sourceBytes} bytes); identity and progress persisted`);
13060
13033
  }
13061
- return lastResponseTime > 0 && now - lastResponseTime > ttlMs;
13034
+ return result.inserted;
13062
13035
  }
13063
-
13064
- // src/features/magic-context/storage-unavailable-reason.ts
13065
- function describeStorageUnavailability(fallbackCause) {
13066
- const migration = getMigrationOnOpenRefusal();
13067
- const blockingProcesses = migration?.blockingProcesses ?? migration?.serverPids.map((pid) => ({ kind: "process", pid })) ?? [];
13068
- if (migration && (blockingProcesses.length > 0 || migration.unreadableFile)) {
13069
- return {
13070
- kind: "migration_guard",
13071
- persistedVersion: migration.persistedVersion,
13072
- supportedVersion: migration.supportedVersion,
13073
- blockingProcesses,
13074
- ...migration.unreadableFile ? { unreadableFile: migration.unreadableFile } : {},
13075
- ...migration.unreadableArm ? { unreadableArm: migration.unreadableArm } : {}
13076
- };
13077
- }
13078
- const fence = getSchemaFenceRejection();
13079
- if (fence) {
13080
- return {
13081
- kind: "schema_fence",
13082
- persistedVersion: fence.persistedVersion,
13083
- supportedVersion: fence.supportedVersion
13084
- };
13036
+ function scheduleClearAndReindex(db, sessionId, readMessages) {
13037
+ heapHolder.reconciledSessions.delete(sessionId);
13038
+ heapHolder.reconciledSnapshots.delete(sessionId);
13039
+ heapHolder.reconciliationScheduledSessions.delete(sessionId);
13040
+ clearCompletedIncrementalKeys(sessionId);
13041
+ const existing = heapHolder.clearAndReindexScheduledSessions.get(sessionId);
13042
+ if (existing) {
13043
+ existing.source = readMessages;
13044
+ return;
13085
13045
  }
13086
- return { kind: "storage_failure", cause: fallbackCause };
13046
+ const pending = { source: readMessages };
13047
+ heapHolder.clearAndReindexScheduledSessions.set(sessionId, pending);
13048
+ scheduleAfterBootQuiet(() => {
13049
+ defer(() => {
13050
+ let cleared = false;
13051
+ runWithSessionLock(sessionId, () => {
13052
+ if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) !== pending)
13053
+ return;
13054
+ heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
13055
+ heapHolder.reconciledSessions.delete(sessionId);
13056
+ heapHolder.reconciledSnapshots.delete(sessionId);
13057
+ clearCompletedIncrementalKeys(sessionId);
13058
+ clearIndexedMessages(db, sessionId);
13059
+ cleared = true;
13060
+ }).then(() => cleared ? reconcileSessionIndex(db, sessionId, pending.source) : undefined).catch((error) => {
13061
+ heapHolder.reconciledSessions.delete(sessionId);
13062
+ if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) === pending)
13063
+ heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
13064
+ logIndexingError(sessionId, "clear and reindex", error);
13065
+ });
13066
+ });
13067
+ });
13087
13068
  }
13088
-
13089
- // src/plugin/rpc-handlers.ts
13090
- import { randomUUID as randomUUID3 } from "node:crypto";
13091
- import { once } from "node:events";
13092
- import { rmSync as rmSync2 } from "node:fs";
13093
- import { join as join5 } from "node:path";
13094
-
13095
- // src/features/magic-context/memory/memory-diagnostics.ts
13096
- function emptyMemoryImportanceHistogram() {
13069
+ function getMessageIndexQueueHeapStats() {
13097
13070
  return {
13098
- total: 0,
13099
- unclassified: 0,
13100
- bands: {
13101
- "0-19": 0,
13102
- "20-39": 0,
13103
- "40-59": 0,
13104
- "60-79": 0,
13105
- "80-100": 0
13106
- }
13071
+ queueLength: heapHolder.reconciliationScheduledSessions.size + heapHolder.incrementalTimers.size + heapHolder.pendingIncrementalKeys.size,
13072
+ reconciliationScheduled: heapHolder.reconciliationScheduledSessions.size,
13073
+ incrementalTimers: heapHolder.incrementalTimers.size,
13074
+ pendingIncremental: heapHolder.pendingIncrementalKeys.size,
13075
+ activeSessionLocks: heapHolder.sessionLocks.size,
13076
+ completedIncrementalKeys: heapHolder.completedIncrementalKeys.size,
13077
+ activeBufferMessages: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + messages.length, 0),
13078
+ activeBufferBytes: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + serializedMessageBytes(messages), 0)
13107
13079
  };
13108
13080
  }
13109
- function readHistogramRow(db, projectPath, classifiedColumn) {
13110
- const unclassified = classifiedColumn ? "SUM(CASE WHEN classified_at IS NULL THEN 1 ELSE 0 END)" : "COUNT(*)";
13111
- return db.prepare(`SELECT COUNT(*) AS total,
13112
- ${unclassified} AS unclassified,
13113
- SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 0 AND 19 THEN 1 ELSE 0 END) AS band_0_19,
13114
- SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 20 AND 39 THEN 1 ELSE 0 END) AS band_20_39,
13115
- SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 40 AND 59 THEN 1 ELSE 0 END) AS band_40_59,
13116
- SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 60 AND 79 THEN 1 ELSE 0 END) AS band_60_79,
13117
- SUM(CASE WHEN COALESCE(importance, 50) BETWEEN 80 AND 100 THEN 1 ELSE 0 END) AS band_80_100
13118
- FROM memories
13119
- WHERE project_path = ? AND status = 'active'`).get(projectPath);
13120
- }
13121
- function getActiveMemoryImportanceHistogram(db, projectPath) {
13122
- let row;
13123
- try {
13124
- row = readHistogramRow(db, projectPath, true);
13125
- } catch (error) {
13126
- if (!String(error).includes("no such column: classified_at"))
13127
- throw error;
13128
- row = readHistogramRow(db, projectPath, false);
13081
+ function clearSessionTracking(sessionId) {
13082
+ sessionEpochs.set(sessionId, (sessionEpochs.get(sessionId) ?? 0) + 1);
13083
+ for (const cancellation of indexCancellations.get(sessionId) ?? [])
13084
+ Atomics.store(cancellation, 0, 1);
13085
+ heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
13086
+ heapHolder.reconciledSessions.delete(sessionId);
13087
+ heapHolder.reconciledSnapshots.delete(sessionId);
13088
+ heapHolder.stalledSessions.delete(sessionId);
13089
+ heapHolder.reconciliationScheduledSessions.delete(sessionId);
13090
+ heapHolder.sessionLocks.delete(sessionId);
13091
+ heapHolder.activeReconcilerBuffers.delete(sessionId);
13092
+ const prefix = `${sessionId}\x00`;
13093
+ for (const [key, timer] of heapHolder.incrementalTimers) {
13094
+ if (key.startsWith(prefix)) {
13095
+ clearTimeout(timer);
13096
+ heapHolder.incrementalTimers.delete(key);
13097
+ }
13129
13098
  }
13130
- return {
13131
- total: Number(row.total ?? 0),
13132
- unclassified: Number(row.unclassified ?? 0),
13133
- bands: {
13134
- "0-19": Number(row.band_0_19 ?? 0),
13135
- "20-39": Number(row.band_20_39 ?? 0),
13136
- "40-59": Number(row.band_40_59 ?? 0),
13137
- "60-79": Number(row.band_60_79 ?? 0),
13138
- "80-100": Number(row.band_80_100 ?? 0)
13099
+ for (const key of heapHolder.pendingIncrementalKeys) {
13100
+ if (key.startsWith(prefix)) {
13101
+ heapHolder.pendingIncrementalKeys.delete(key);
13139
13102
  }
13140
- };
13103
+ }
13104
+ for (const key of heapHolder.completedIncrementalKeys) {
13105
+ if (key.startsWith(prefix))
13106
+ heapHolder.completedIncrementalKeys.delete(key);
13107
+ }
13141
13108
  }
13142
13109
 
13143
13110
  // src/features/magic-context/session-cache-ttl.ts
@@ -14237,6 +14204,13 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
14237
14204
  }
14238
14205
  return { shouldFire: false };
14239
14206
  }
14207
+ if (tailInfo.boundarySnapshot && shouldWaitForNewHistorianHistory(tailInfo.boundarySnapshot, {
14208
+ usagePercentage: usage.percentage,
14209
+ emergency: getOverflowState(db, sessionId).needsEmergencyRecovery
14210
+ })) {
14211
+ sessionLog2(sessionId, "compartment trigger: waiting for new history after no forward progress");
14212
+ return { shouldFire: false };
14213
+ }
14240
14214
  const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
14241
14215
  const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession2(db, sessionId), keepReasoningTokens, sessionMeta.clearedReasoningThroughTag, canClearReasoning, reasoningProjection?.budgetCutoff, eligiblePendingDropTagIds);
14242
14216
  const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
@@ -16480,8 +16454,8 @@ function registerRpcHandlers(rpcServer, args) {
16480
16454
  const db = readDatabase();
16481
16455
  if (!db)
16482
16456
  return { ok: false, error: "db unavailable" };
16483
- const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-qwqeskhq.js"));
16484
- const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-ygj4mja0.js"));
16457
+ const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-02sa2ngr.js"));
16458
+ const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-afzzqy5b.js"));
16485
16459
  log2(`[rpc] recomp requested for session ${sessionId}`);
16486
16460
  if (!args.client && !args.hiddenCompletionExecutor) {
16487
16461
  return {
@@ -16565,7 +16539,7 @@ function registerRpcHandlers(rpcServer, args) {
16565
16539
  const db = readDatabase();
16566
16540
  if (!db)
16567
16541
  return { ok: false, error: "db unavailable" };
16568
- const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-f642w8n3.js"));
16542
+ const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-n5h5sr1x.js"));
16569
16543
  const model = liveSessionState.liveModelBySession.get(sessionId);
16570
16544
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
16571
16545
  const ctx = {
@@ -24400,6 +24374,7 @@ function createTransform(deps) {
24400
24374
  const startTime = performance.now();
24401
24375
  const historianRun = deps.resolveHistorianRun?.();
24402
24376
  const messages = output.messages;
24377
+ const foreignTextParts = deps.transformMode === "rust" ? undefined : deps.collectForeignTextParts?.(messages);
24403
24378
  const entryOrderForThinkingFit = messages.slice();
24404
24379
  const coveredHostInstructions = takeCoveredInstructionRows(messages);
24405
24380
  const passOutcome = createPassOutcome();
@@ -25064,6 +25039,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
25064
25039
  }
25065
25040
  logTransformTiming(sessionId, "injectTemporalMarkers", tTemporal);
25066
25041
  }
25042
+ const replaysCaveman = !reducedMode && !compactionOff && deps.cavemanTextCompression?.enabled === true;
25067
25043
  let taggingSucceeded = false;
25068
25044
  let recoveryBatch = null;
25069
25045
  let recoveryNormalized = false;
@@ -25076,7 +25052,9 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
25076
25052
  skipPrefixInjection: !ctxReduceCallable,
25077
25053
  servedMessages: messages,
25078
25054
  normalizeRestoredAssistantText: deps.normalizeRestoredAssistantText,
25079
- refreshSourceContents: deps.refreshSourceContents?.(sessionId)
25055
+ refreshSourceContents: deps.refreshSourceContents?.(sessionId),
25056
+ foreignTextParts,
25057
+ replaysCaveman
25080
25058
  });
25081
25059
  for (const [number, target] of tagged.targets)
25082
25060
  targets.set(number, target);
@@ -25102,7 +25080,9 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
25102
25080
  scopedToolSweep,
25103
25081
  servedMessages: messages,
25104
25082
  normalizeRestoredAssistantText: deps.normalizeRestoredAssistantText,
25105
- refreshSourceContents: deps.refreshSourceContents?.(sessionId)
25083
+ refreshSourceContents: deps.refreshSourceContents?.(sessionId),
25084
+ foreignTextParts,
25085
+ replaysCaveman
25106
25086
  });
25107
25087
  targets = result.targets;
25108
25088
  if (thinkingRecovery.restore)
@@ -25158,7 +25138,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
25158
25138
  const t3 = performance.now();
25159
25139
  const strippedStructuralNoise = canUseEmptySentinels && !compactionOff ? stripStructuralNoise(messages) : 0;
25160
25140
  logTransformTiming(sessionId, "stripStructuralNoise", t3, `strippedParts=${strippedStructuralNoise}`);
25161
- if (!reducedMode && !compactionOff && deps.cavemanTextCompression?.enabled) {
25141
+ if (replaysCaveman) {
25162
25142
  const tCavemanReplay = performance.now();
25163
25143
  const replayedCaveman = replayCavemanCompression(sessionId, db, targets, activeTags);
25164
25144
  if (replayedCaveman > 0) {
@@ -28607,7 +28587,7 @@ function singleLine(value) {
28607
28587
  // src/tools/ctx-note/tools.ts
28608
28588
  function captureAnchorOrdinal(db, sessionId) {
28609
28589
  try {
28610
- const ordinal = getLastIndexedOrdinal2(db, sessionId);
28590
+ const ordinal = getLastIndexedOrdinal(db, sessionId);
28611
28591
  return ordinal > 0 ? ordinal : null;
28612
28592
  } catch {
28613
28593
  return null;
@@ -29005,23 +28985,26 @@ function createCtxReduceTool(deps) {
29005
28985
  dropIds = dropIds.filter((id) => !ctxReduceSelfStampIds.has(id));
29006
28986
  const tagStatusMap = new Map(allTags.map((tag) => [tag.tagNumber, tag.status]));
29007
28987
  const inertWhitespaceTagNumbers = new Set(getInertWhitespaceAssistantTagsByNumbers2(deps.db, sessionId, dropIds).map((tag) => tag.tagNumber));
29008
- const inertDropIds = [
29009
- ...new Set(dropIds.filter((id) => inertWhitespaceTagNumbers.has(id)))
29010
- ];
29011
- const inertNote = inertDropIds.length > 0 ? `Skipped: ${inertDropIds.map((id) => `§${id}§ is provider framing, nothing to reclaim`).join("; ")}.` : "";
28988
+ const foreignTextTagNumbers = new Set(dropIds.filter((id) => isLegacyForeignTextTag(sessionId, id)));
28989
+ const skippedTagNumbers = new Set([
28990
+ ...inertWhitespaceTagNumbers,
28991
+ ...foreignTextTagNumbers
28992
+ ]);
28993
+ const skippedDropIds = [...new Set(dropIds.filter((id) => skippedTagNumbers.has(id)))];
28994
+ const inertNote = skippedDropIds.length > 0 ? `Skipped: ${skippedDropIds.map((id) => inertWhitespaceTagNumbers.has(id) ? `§${id}§ is provider framing, nothing to reclaim` : `§${id}§ is another plugin's text, nothing to reclaim`).join("; ")}.` : "";
29012
28995
  const pendingOps = getPendingOps(deps.db, sessionId);
29013
28996
  const pendingMap = new Map(pendingOps.map((op) => [op.tagId, op.operation]));
29014
28997
  const conflicts = [];
29015
28998
  for (const id of dropIds) {
29016
- if (tagStatusMap.get(id) === "compacted" && !inertWhitespaceTagNumbers.has(id)) {
28999
+ if (tagStatusMap.get(id) === "compacted" && !skippedTagNumbers.has(id)) {
29017
29000
  conflicts.push(`§${id}§ is from before compaction`);
29018
29001
  }
29019
29002
  }
29020
29003
  if (conflicts.length > 0) {
29021
29004
  return `Error: Conflicting operations — ${conflicts.join("; ")}.`;
29022
29005
  }
29023
- const stampedCount = new Set(dropIds.filter((id) => !inertWhitespaceTagNumbers.has(id))).size;
29024
- dropIds = dropIds.filter((id) => !inertWhitespaceTagNumbers.has(id) && tagStatusMap.get(id) !== "dropped" && pendingMap.get(id) !== "drop");
29006
+ const stampedCount = new Set(dropIds.filter((id) => !skippedTagNumbers.has(id))).size;
29007
+ dropIds = dropIds.filter((id) => !skippedTagNumbers.has(id) && tagStatusMap.get(id) !== "dropped" && pendingMap.get(id) !== "drop");
29025
29008
  if (dropIds.length === 0) {
29026
29009
  const reply = formatCtxReduceReply(stampedCount, ctxReduceSelfStampCount);
29027
29010
  if (reply)
@@ -29788,4 +29771,4 @@ function applyHiddenSubagentTemperature(input, output, log) {
29788
29771
  output.temperature = temperature;
29789
29772
  }
29790
29773
 
29791
- export { logConfigDependencyNotesOnce, openOpenCodeDb, DREAMER_SYSTEM_PROMPT, runSessionProjectBackfill, SMART_NOTE_COMPILER_SYSTEM_PROMPT, createLiveSessionState, RETROSPECTIVE_MAX_USER_MESSAGE_CHARS, RETROSPECTIVE_MESSAGE_TRUNCATION_MARKER, OpenCodeRetrospectiveRawProvider, createDreamTaskExecutor, runManualDream, runDueTasksForProject, scheduleClearAndReindex, startDreamScheduleTimer, createDreamTimerModuleClient, ensureProjectRegisteredFromOpenCodeDirectory, recordOpenCodeProvenInputFloor, resolveOpenCodeProvenInputFloor, resolveContextWindowGeometry, resolveContextLimit, resolveExecuteThresholdDetail, resolveModelKey, resolveSessionId, createScheduler, describeStorageUnavailability, resolveSessionCacheTtl, runEmbedHistoryDrain, pauseEmbedHistoryDrain, formatEmbedStatusText, getSessionProperties, getSessionCreatedInfo, getMessageUpdatedAssistantInfo, getMessageUpdatedInfo, getSessionErrorInfo, getMessageRemovedInfo, summarizeManualDream, createMagicContextCommandHandler, getLiveNotificationParams, createChatMessageHook, createEventHook, createCommandExecuteBeforeHook, createToolExecuteAfterHook, recordHiddenVariantWarning, buildStatusDetail, isDebugRpcEnabled, registerRpcHandlers, maybeAutoEmbedSessionBackfill, clearTransformDecisionSession, scheduleOpenCodeTransformDecisionWrite, stageOpenCodeV2TransformDecision, bindOpenCodeV2TransformDecision, maybeDeliverChannel2, armLatestThinkingRecovery, armBindingRecoverySafely, armLatestThinkingRecoveryFromError, createM0RenderOptions, lkgReplayLimit, measureLkgReplay, STORAGE_BUSY_MESSAGE, StorageBusyRefusalError, bindSystemDateRequestIdentity, bindSystemDateOutput, registerSystemDateRefresh, rustWrapupHistorianFields, UnmanagedOverWindowError, UnresolvedHistoryBoundaryError, clearMessageTokensCache, createTransform, createSubcModuleClient, createModuleToolBackends, createRustRefusalRecovery, createSystemPromptHashHandler, tryMessagesTransformLkgReplay, createMessagesTransformHandler, primaryOnlyToolIds, subagentToolRefusal, guardSubagentTools, hideSubagentTools, removePrimaryOnlyTools, storedSubagentMode, createCtxExpandTools, CTX_MEMORY_LIST_TOOL_NAME, CTX_MEMORY_ACTIONS, createCtxMemoryTools, createCtxMemoryListTools, CTX_NOTE_DESCRIPTION, withoutSmartNoteText, createCtxNoteTools, createCtxReduceTools, createCtxSearchTools, parameterDescriptionsFor, applyJsonSchemaParameterDescriptions, MagicContextRpcServer, subagentTemperature, applyHiddenSubagentTemperature };
29774
+ export { logConfigDependencyNotesOnce, openOpenCodeDb, DREAMER_SYSTEM_PROMPT, runSessionProjectBackfill, SMART_NOTE_COMPILER_SYSTEM_PROMPT, createLiveSessionState, RETROSPECTIVE_MAX_USER_MESSAGE_CHARS, RETROSPECTIVE_MESSAGE_TRUNCATION_MARKER, OpenCodeRetrospectiveRawProvider, createDreamTaskExecutor, runManualDream, runDueTasksForProject, startDreamScheduleTimer, createDreamTimerModuleClient, ensureProjectRegisteredFromOpenCodeDirectory, recordOpenCodeProvenInputFloor, resolveOpenCodeProvenInputFloor, resolveContextWindowGeometry, resolveContextLimit, resolveExecuteThresholdDetail, resolveModelKey, resolveSessionId, createScheduler, describeStorageUnavailability, scheduleClearAndReindex, resolveSessionCacheTtl, runEmbedHistoryDrain, pauseEmbedHistoryDrain, formatEmbedStatusText, getSessionProperties, getSessionCreatedInfo, getMessageUpdatedAssistantInfo, getMessageUpdatedInfo, getSessionErrorInfo, getMessageRemovedInfo, summarizeManualDream, createMagicContextCommandHandler, getLiveNotificationParams, createChatMessageHook, createEventHook, createCommandExecuteBeforeHook, createToolExecuteAfterHook, recordHiddenVariantWarning, buildStatusDetail, isDebugRpcEnabled, registerRpcHandlers, maybeAutoEmbedSessionBackfill, clearTransformDecisionSession, scheduleOpenCodeTransformDecisionWrite, stageOpenCodeV2TransformDecision, bindOpenCodeV2TransformDecision, maybeDeliverChannel2, armLatestThinkingRecovery, armBindingRecoverySafely, armLatestThinkingRecoveryFromError, createM0RenderOptions, lkgReplayLimit, measureLkgReplay, STORAGE_BUSY_MESSAGE, StorageBusyRefusalError, bindSystemDateRequestIdentity, bindSystemDateOutput, registerSystemDateRefresh, rustWrapupHistorianFields, UnmanagedOverWindowError, UnresolvedHistoryBoundaryError, clearMessageTokensCache, createTransform, createSubcModuleClient, createModuleToolBackends, createRustRefusalRecovery, createSystemPromptHashHandler, tryMessagesTransformLkgReplay, createMessagesTransformHandler, primaryOnlyToolIds, subagentToolRefusal, guardSubagentTools, hideSubagentTools, removePrimaryOnlyTools, storedSubagentMode, createCtxExpandTools, CTX_MEMORY_LIST_TOOL_NAME, CTX_MEMORY_ACTIONS, createCtxMemoryTools, createCtxMemoryListTools, CTX_NOTE_DESCRIPTION, withoutSmartNoteText, createCtxNoteTools, createCtxReduceTools, createCtxSearchTools, parameterDescriptionsFor, applyJsonSchemaParameterDescriptions, MagicContextRpcServer, subagentTemperature, applyHiddenSubagentTemperature };