@cortexkit/opencode-magic-context 0.41.0 → 0.41.2

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 (143) hide show
  1. package/dist/config/schema/magic-context.d.ts +15 -0
  2. package/dist/config/schema/magic-context.d.ts.map +1 -1
  3. package/dist/{conflict-warning-hook-xj1r88a7.js → conflict-warning-hook-rf17b6et.js} +3 -3
  4. package/dist/{derive-budgets-3xfyphvk.js → derive-budgets-9q2d3r93.js} +2 -2
  5. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +16 -17
  6. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  7. package/dist/features/magic-context/compartment-embedding.d.ts.map +1 -1
  8. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/curate-memory-safety.d.ts +21 -0
  10. package/dist/features/magic-context/dreamer/curate-memory-safety.d.ts.map +1 -0
  11. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/task-prompts.d.ts +1 -6
  13. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  14. package/dist/features/magic-context/memory/embedding-failure.d.ts +10 -2
  15. package/dist/features/magic-context/memory/embedding-failure.d.ts.map +1 -1
  16. package/dist/features/magic-context/memory/embedding-local.d.ts +19 -2
  17. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  18. package/dist/features/magic-context/memory/embedding-synapse.d.ts +10 -1
  19. package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
  20. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  21. package/dist/features/magic-context/memory/onnxruntime-node-wasm-shim.d.ts +3 -0
  22. package/dist/features/magic-context/memory/onnxruntime-node-wasm-shim.d.ts.map +1 -0
  23. package/dist/features/magic-context/memory/project-identity.d.ts +4 -0
  24. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  25. package/dist/features/magic-context/memory/sharp-wasm-shim.d.ts +2 -0
  26. package/dist/features/magic-context/memory/sharp-wasm-shim.d.ts.map +1 -0
  27. package/dist/features/magic-context/memory/transformers-node-wasm-entry.d.ts +3 -0
  28. package/dist/features/magic-context/memory/transformers-node-wasm-entry.d.ts.map +1 -0
  29. package/dist/features/magic-context/memory/transformers-web-entry.d.ts +2 -0
  30. package/dist/features/magic-context/memory/transformers-web-entry.d.ts.map +1 -0
  31. package/dist/features/magic-context/message-fts-rowid-map.d.ts +28 -0
  32. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -0
  33. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  34. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  35. package/dist/features/magic-context/overflow-detection.d.ts +15 -2
  36. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  37. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  38. package/dist/features/magic-context/search.d.ts +18 -0
  39. package/dist/features/magic-context/search.d.ts.map +1 -1
  40. package/dist/features/magic-context/storage-db.d.ts +2 -1
  41. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  42. package/dist/features/magic-context/storage-meta-persisted.d.ts +19 -2
  43. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  44. package/dist/features/magic-context/storage-meta-session.d.ts +3 -2
  45. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  46. package/dist/features/magic-context/storage-meta.d.ts +2 -2
  47. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-ops.d.ts +2 -0
  49. package/dist/features/magic-context/storage-ops.d.ts.map +1 -1
  50. package/dist/features/magic-context/storage-schema-helpers.d.ts.map +1 -1
  51. package/dist/features/magic-context/storage-session-tables.d.ts +9 -1
  52. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  53. package/dist/features/magic-context/storage-tags.d.ts +13 -0
  54. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  55. package/dist/features/magic-context/storage.d.ts +2 -2
  56. package/dist/features/magic-context/storage.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/boundary-execution.d.ts +3 -0
  58. package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/event-handler.d.ts +4 -1
  60. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/format-embed-failure.d.ts.map +1 -1
  62. package/dist/hooks/magic-context/hook-handlers.d.ts +3 -0
  63. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/hook.d.ts +1 -1
  65. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/live-session-state.d.ts +3 -1
  67. package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/rust-mode-transform.d.ts +9 -1
  69. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/sentinel.d.ts +13 -37
  71. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/strip-content.d.ts +12 -5
  73. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/tag-id-fallback.d.ts +3 -1
  75. package/dist/hooks/magic-context/tag-id-fallback.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +28 -2
  78. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/transform.d.ts +1 -1
  80. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  81. package/dist/{index-b4gv9f7g.js → index-4x691bz5.js} +87 -2
  82. package/dist/{index-knna83k0.js → index-9j3tx8hy.js} +1 -1
  83. package/dist/{index-jmwq2wxr.js → index-b9j85d29.js} +1 -1
  84. package/dist/{index-2bykz3bx.js → index-cvda5jb3.js} +7 -2
  85. package/dist/{index-bf799gbq.js → index-d1mxrd3p.js} +0 -1
  86. package/dist/{index-dmgbar7r.js → index-eq9wr75c.js} +2 -2
  87. package/dist/{index-w8rkbhn6.js → index-j8r0ejb3.js} +1232 -261
  88. package/dist/{index-26ds03jd.js → index-vnz6jvdc.js} +1 -1
  89. package/dist/{index-x9dmzyp5.js → index-y1yr57fw.js} +81 -17
  90. package/dist/{index-88za3sz8.js → index-zwjhba2r.js} +3 -3
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +1771 -1109
  93. package/dist/{model-resolution-jgrkt0z2.js → model-resolution-6w6wzw18.js} +1 -1
  94. package/dist/plugin/dream-timer.d.ts +4 -0
  95. package/dist/plugin/dream-timer.d.ts.map +1 -1
  96. package/dist/plugin/embedding-routing.d.ts.map +1 -1
  97. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
  98. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  99. package/dist/{recomp-orchestrator-1w4xj6jt.js → recomp-orchestrator-m37p3fq6.js} +6 -6
  100. package/dist/{safe-notification-target-p0c0csxw.js → safe-notification-target-2a8py95v.js} +2 -2
  101. package/dist/{send-session-notification-kn34g7mx.js → send-session-notification-bw7eex6w.js} +3 -3
  102. package/dist/shared/index.d.ts +1 -0
  103. package/dist/shared/index.d.ts.map +1 -1
  104. package/dist/shared/logger.d.ts.map +1 -1
  105. package/dist/shared/model-resolution.d.ts.map +1 -1
  106. package/dist/shared/rpc-utils.d.ts +3 -1
  107. package/dist/shared/rpc-utils.d.ts.map +1 -1
  108. package/dist/shared/summarize-child-stderr.d.ts +2 -0
  109. package/dist/shared/summarize-child-stderr.d.ts.map +1 -0
  110. package/dist/shared/test-temp-dir.d.ts +40 -0
  111. package/dist/shared/test-temp-dir.d.ts.map +1 -0
  112. package/dist/shared/window-geometry.d.ts +2 -0
  113. package/dist/shared/window-geometry.d.ts.map +1 -1
  114. package/dist/{storage-meta-session-snbzd26z.js → storage-meta-session-dse3qv6s.js} +5 -3
  115. package/dist/{task-config-ty08ptc2.js → task-config-gv6s04fp.js} +2 -2
  116. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  117. package/dist/tools/ctx-memory/types.d.ts +2 -0
  118. package/dist/tools/ctx-memory/types.d.ts.map +1 -1
  119. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  120. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  121. package/dist/transformers-node-wasm.js +25676 -0
  122. package/dist/transformers-web.js +24570 -0
  123. package/dist/transformers.node-b1wa0hgx.js +28808 -0
  124. package/package.json +8 -3
  125. package/src/config/index.test.ts +50 -4
  126. package/src/config/latch-permanence-guard.test.ts +5 -0
  127. package/src/config/schema/magic-context.test.ts +20 -0
  128. package/src/config/schema/magic-context.ts +8 -0
  129. package/src/shared/conflict-detector.test.ts +6 -19
  130. package/src/shared/conflict-fixer.test.ts +5 -8
  131. package/src/shared/index.ts +1 -0
  132. package/src/shared/logger.test.ts +135 -40
  133. package/src/shared/logger.ts +115 -2
  134. package/src/shared/model-resolution.test.ts +21 -19
  135. package/src/shared/model-resolution.ts +0 -1
  136. package/src/shared/rpc-utils.test.ts +246 -5
  137. package/src/shared/rpc-utils.ts +340 -49
  138. package/src/shared/summarize-child-stderr.test.ts +55 -0
  139. package/src/shared/summarize-child-stderr.ts +33 -0
  140. package/src/shared/test-temp-dir.test.ts +57 -0
  141. package/src/shared/test-temp-dir.ts +165 -0
  142. package/src/shared/window-geometry.ts +9 -0
  143. /package/dist/{index-rpgg35ms.js → index-8sseka65.js} +0 -0
@@ -2,20 +2,21 @@ import {
2
2
  deriveTriggerBudget,
3
3
  modelSupportsVision,
4
4
  shouldEnforcePrivateStoragePermissions
5
- } from "./index-2bykz3bx.js";
5
+ } from "./index-cvda5jb3.js";
6
6
  import {
7
7
  describeError,
8
8
  getErrorMessage,
9
9
  sendIgnoredMessage
10
- } from "./index-88za3sz8.js";
10
+ } from "./index-zwjhba2r.js";
11
11
  import {
12
+ SESSION_SCOPED_TABLES,
12
13
  clearCachedM0M1,
13
14
  deleteSessionScopedRows,
14
15
  ensureSessionMetaRow,
15
16
  logSlowWriteTransaction,
16
17
  persistCachedM0,
17
18
  updateSessionMeta
18
- } from "./index-x9dmzyp5.js";
19
+ } from "./index-y1yr57fw.js";
19
20
  import {
20
21
  modelRefLookupOrder,
21
22
  piModelRefToCanonical
@@ -28,7 +29,7 @@ import {
28
29
  openCodeDbExists,
29
30
  withPrivilegedWriter,
30
31
  withReadOnlySessionDb
31
- } from "./index-jmwq2wxr.js";
32
+ } from "./index-b9j85d29.js";
32
33
  import {
33
34
  detectConfigFile
34
35
  } from "./index-8mtsfhyg.js";
@@ -39,7 +40,7 @@ import {
39
40
  log,
40
41
  sanitizeDiagnosticText,
41
42
  sessionLog
42
- } from "./index-b4gv9f7g.js";
43
+ } from "./index-4x691bz5.js";
43
44
  import {
44
45
  ensureCortexKitArtifactGitignore,
45
46
  getDataDir,
@@ -538,8 +539,8 @@ function formatFailClosedBlockingMessage(reason) {
538
539
  ].join(" ");
539
540
  }
540
541
  return [
541
- `Magic Context cannot migrate the shared database because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
542
- "Restart the blocking process (it will pick up the new build and migrate on start), or shut it down and retry.",
542
+ `Magic Context cannot migrate the shared database (one database serves every project on this machine) because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
543
+ "Restart the blocking process — even one from a different project — and it will pick up the new build and migrate on start; or shut it down and retry.",
543
544
  `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
544
545
  ].join(" ");
545
546
  }
@@ -704,8 +705,19 @@ function isPidAlive(pid) {
704
705
  var RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000;
705
706
  var LINUX_CLOCK_TICKS_PER_SECOND = 100;
706
707
  var PS_PROBE_TIMEOUT_MS = 1000;
708
+ var WINDOWS_CIM_PROBE_TIMEOUT_MS = 5000;
709
+ var MAX_ANCESTOR_WALK_DEPTH = 16;
707
710
  var OPEN_CODE_COMMAND_MARKERS = ["opencode", "node", "bun", "electron"];
708
711
  var TASKLIST_NO_TASKS_PATTERN = /^INFO:\s+No tasks are running which match the specified criteria\.?$/im;
712
+ var WINDOWS_CIM_COMMAND = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine,CreationDate | ConvertTo-Json -Compress";
713
+ var PI_HARNESS_ARC_MARKERS = [
714
+ "pi-coding-agent",
715
+ "oh-my-pi",
716
+ "@oh-my-pi",
717
+ "cljs/dist",
718
+ "dist/bundle/cli"
719
+ ];
720
+ var PI_IMAGE_NAMES = new Set(["pi", "pi.cmd", "omp", "oh-my-pi"]);
709
721
  var rpcIdentityReadFileSync = readFileSync;
710
722
  var rpcIdentityExecFileSync = execFileSync;
711
723
  var rpcIdentityProcessKill = process.kill;
@@ -750,7 +762,7 @@ function readPsProcessStartTime(pid) {
750
762
  function readProcessStartTime(pid) {
751
763
  if (!Number.isInteger(pid) || pid <= 0)
752
764
  return null;
753
- return rpcIdentityPlatform === "linux" ? readLinuxProcessStartTime(pid) : rpcIdentityPlatform === "win32" ? null : readPsProcessStartTime(pid);
765
+ return rpcIdentityPlatform === "linux" ? readLinuxProcessStartTime(pid) : rpcIdentityPlatform === "win32" ? readWindowsProcessStartTime(pid) : readPsProcessStartTime(pid);
754
766
  }
755
767
  function readProcessProbeEvidence(pid) {
756
768
  return {
@@ -758,6 +770,10 @@ function readProcessProbeEvidence(pid) {
758
770
  commandLine: readProcessCommand(pid)
759
771
  };
760
772
  }
773
+ var windowsProcessFactsCache = null;
774
+ function rememberWindowsProcessFacts(facts) {
775
+ windowsProcessFactsCache = new Map(facts.map((fact) => [fact.pid, fact]));
776
+ }
761
777
  function parseCsvLine(line) {
762
778
  const fields = [];
763
779
  let field = "";
@@ -822,6 +838,16 @@ function readWindowsProcess(pid) {
822
838
  return { state: "inconclusive" };
823
839
  }
824
840
  }
841
+ function readWindowsProcessStartTime(pid) {
842
+ const cached = windowsProcessFactsCache?.get(pid);
843
+ if (cached)
844
+ return cached.startTime;
845
+ const snapshot = tryReadWindowsCimSnapshot(rpcIdentityExecFileSync);
846
+ if (!snapshot)
847
+ return null;
848
+ rememberWindowsProcessFacts(snapshot.facts);
849
+ return windowsProcessFactsCache?.get(pid)?.startTime ?? null;
850
+ }
825
851
  function readLinuxProcessCommand(pid) {
826
852
  try {
827
853
  return String(rpcIdentityReadFileSync(`/proc/${pid}/cmdline`, "utf8"));
@@ -844,7 +870,15 @@ function readPsProcessCommand(pid) {
844
870
  function readProcessCommand(pid) {
845
871
  if (!Number.isInteger(pid) || pid <= 0)
846
872
  return null;
847
- return rpcIdentityPlatform === "linux" ? readLinuxProcessCommand(pid) : rpcIdentityPlatform === "win32" ? readWindowsProcess(pid).command ?? null : readPsProcessCommand(pid);
873
+ if (rpcIdentityPlatform === "linux")
874
+ return readLinuxProcessCommand(pid);
875
+ if (rpcIdentityPlatform === "win32") {
876
+ const cached = windowsProcessFactsCache?.get(pid);
877
+ if (cached?.commandLine)
878
+ return cached.commandLine;
879
+ return readWindowsProcess(pid).command ?? null;
880
+ }
881
+ return readPsProcessCommand(pid);
848
882
  }
849
883
  function executableName(token) {
850
884
  return (token ?? "").replace(/^['"]|['"]$/g, "").split("/").at(-1) ?? "";
@@ -904,57 +938,262 @@ function isPidIdentityPlausible(record, evidence) {
904
938
  return "inconclusive";
905
939
  return commandLooksLikeOpenCode(command) ? "plausible" : "implausible";
906
940
  }
907
- function commandLooksLikePi(command) {
908
- const normalized = command.trim().toLowerCase().replaceAll("\\", "/");
909
- const tokens = normalized.split(/\s+/).filter(Boolean);
910
- const executableName2 = (token) => (token ?? "").split("/").at(-1) ?? "";
911
- const first = executableName2(tokens[0]).replace(/\.exe$/, "");
912
- if (["pi", "pi.cmd", "omp", "oh-my-pi"].includes(first))
941
+ function commandLooksLikePiImage(command) {
942
+ const tokens = commandTokens(command);
943
+ const first = executableName(tokens[0]).replace(/\.(?:exe|cmd)$/, "");
944
+ return PI_IMAGE_NAMES.has(first);
945
+ }
946
+ function commandHasPiHarnessArc(command) {
947
+ const normalized = command.trim().toLowerCase().replaceAll("\\", "/").replaceAll("\x00", " ");
948
+ if (!normalized)
949
+ return false;
950
+ const tokens = commandTokens(command);
951
+ if (tokens.length === 0)
952
+ return false;
953
+ const hasArc = PI_HARNESS_ARC_MARKERS.some((marker) => normalized.includes(marker));
954
+ const first = executableName(tokens[0]).replace(/\.(?:exe|cmd)$/, "");
955
+ if (hasArc && ["pi", "omp", "oh-my-pi", "node", "bun", "deno", "cmd"].includes(first)) {
913
956
  return true;
957
+ }
958
+ if (hasArc && PI_HARNESS_ARC_MARKERS.some((marker) => tokens[0].includes(marker))) {
959
+ return true;
960
+ }
914
961
  if (["node", "bun", "deno"].includes(first)) {
915
- const script = executableName2(tokens[1]);
916
- return ["pi", "pi.js", "pi.mjs", "pi.cjs"].includes(script) || normalized.includes("pi-coding-agent");
962
+ const script = executableName(tokens[1]).replace(/\.(?:exe|cmd)$/, "");
963
+ if (["pi", "pi.js", "pi.mjs", "pi.cjs"].includes(script))
964
+ return true;
965
+ if (hasArc)
966
+ return true;
917
967
  }
918
968
  return false;
919
969
  }
970
+ function execProcessList(exec, file, args, timeout = PS_PROBE_TIMEOUT_MS) {
971
+ return String(exec(file, [...args], {
972
+ encoding: "utf8",
973
+ timeout,
974
+ stdio: ["ignore", "pipe", "pipe"]
975
+ }));
976
+ }
977
+ function parseWindowsCreationDate(value) {
978
+ if (typeof value === "number" && Number.isFinite(value)) {
979
+ return value > 1000000000000 ? value : value * 1000;
980
+ }
981
+ if (typeof value !== "string")
982
+ return null;
983
+ const trimmed = value.trim();
984
+ if (!trimmed)
985
+ return null;
986
+ const wmi = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+-])(\d{3})$/.exec(trimmed);
987
+ if (wmi) {
988
+ const utcMs = Date.UTC(Number(wmi[1]), Number(wmi[2]) - 1, Number(wmi[3]), Number(wmi[4]), Number(wmi[5]), Number(wmi[6]), Number(wmi[7]) / 1000);
989
+ if (!Number.isFinite(utcMs))
990
+ return null;
991
+ const offsetMinutes = Number(wmi[9]);
992
+ const sign = wmi[8] === "+" ? 1 : -1;
993
+ return utcMs - sign * offsetMinutes * 60000;
994
+ }
995
+ const dotNet = /^\/Date\((-?\d+)\)\/$/.exec(trimmed);
996
+ if (dotNet) {
997
+ const milliseconds = Number(dotNet[1]);
998
+ return Number.isFinite(milliseconds) ? milliseconds : null;
999
+ }
1000
+ const parsed = Date.parse(trimmed);
1001
+ return Number.isFinite(parsed) ? parsed : null;
1002
+ }
1003
+ function parseWindowsCimOutput(output) {
1004
+ const trimmed = output.trim();
1005
+ if (!trimmed)
1006
+ return null;
1007
+ const bracket = trimmed.indexOf("[");
1008
+ const brace = trimmed.indexOf("{");
1009
+ const start = Math.min(bracket === -1 ? Number.POSITIVE_INFINITY : bracket, brace === -1 ? Number.POSITIVE_INFINITY : brace);
1010
+ if (!Number.isFinite(start))
1011
+ return null;
1012
+ let parsed;
1013
+ try {
1014
+ parsed = JSON.parse(trimmed.slice(start));
1015
+ } catch {
1016
+ return null;
1017
+ }
1018
+ if (parsed == null)
1019
+ return null;
1020
+ const rows = Array.isArray(parsed) ? parsed : [parsed];
1021
+ const facts = [];
1022
+ for (const row of rows) {
1023
+ if (!row || typeof row !== "object")
1024
+ continue;
1025
+ const record = row;
1026
+ const pid = Number(record.ProcessId);
1027
+ if (!Number.isInteger(pid) || pid <= 0)
1028
+ continue;
1029
+ const parentRaw = record.ParentProcessId;
1030
+ const parentPid = parentRaw == null || parentRaw === "" ? Number.NaN : Number(parentRaw);
1031
+ const commandLine = typeof record.CommandLine === "string" ? record.CommandLine : null;
1032
+ facts.push({
1033
+ pid,
1034
+ parentPid: Number.isInteger(parentPid) && parentPid > 0 ? parentPid : null,
1035
+ commandLine,
1036
+ imageName: commandLine ? executableName(commandTokens(commandLine)[0]) : null,
1037
+ startTime: parseWindowsCreationDate(record.CreationDate)
1038
+ });
1039
+ }
1040
+ return facts.length > 0 ? facts : null;
1041
+ }
1042
+ function snapshotFromFacts(facts, source) {
1043
+ const parentByPid = new Map;
1044
+ for (const fact of facts) {
1045
+ if (fact.parentPid != null)
1046
+ parentByPid.set(fact.pid, fact.parentPid);
1047
+ }
1048
+ return { facts, parentByPid, source };
1049
+ }
1050
+ function tryReadWindowsCimSnapshot(exec) {
1051
+ try {
1052
+ const output = execProcessList(exec, "powershell", ["-NoProfile", "-Command", WINDOWS_CIM_COMMAND], WINDOWS_CIM_PROBE_TIMEOUT_MS);
1053
+ const facts = parseWindowsCimOutput(output);
1054
+ return facts ? snapshotFromFacts(facts, "cim") : null;
1055
+ } catch {
1056
+ return null;
1057
+ }
1058
+ }
1059
+ function tryReadWindowsTasklistSnapshot() {
1060
+ try {
1061
+ const output = execProcessList(rpcProcessListExecFileSync, "tasklist", ["/FO", "CSV"]);
1062
+ const entries = parseTasklistOutput(output);
1063
+ if (entries === null)
1064
+ return null;
1065
+ const facts = entries.map((entry) => ({
1066
+ pid: entry.pid,
1067
+ parentPid: null,
1068
+ commandLine: null,
1069
+ imageName: entry.command,
1070
+ startTime: null
1071
+ }));
1072
+ return snapshotFromFacts(facts, "tasklist");
1073
+ } catch {
1074
+ return null;
1075
+ }
1076
+ }
1077
+ function readPosixProcessSnapshot() {
1078
+ const output = execProcessList(rpcProcessListExecFileSync, "ps", ["-axo", "pid=,command="]);
1079
+ const facts = [];
1080
+ for (const line of output.split(/\r?\n/)) {
1081
+ const match = /^\s*(\d+)\s+(.+)$/.exec(line);
1082
+ if (!match)
1083
+ continue;
1084
+ const pid = Number(match[1]);
1085
+ if (!Number.isInteger(pid) || pid <= 0)
1086
+ continue;
1087
+ facts.push({
1088
+ pid,
1089
+ parentPid: null,
1090
+ commandLine: match[2],
1091
+ imageName: executableName(commandTokens(match[2])[0]),
1092
+ startTime: null
1093
+ });
1094
+ }
1095
+ return snapshotFromFacts(facts, "ps");
1096
+ }
1097
+ function readPosixParentPid(pid) {
1098
+ try {
1099
+ const output = execProcessList(rpcProcessListExecFileSync, "ps", [
1100
+ "-o",
1101
+ "ppid=",
1102
+ "-p",
1103
+ String(pid)
1104
+ ]);
1105
+ const match = /^\s*(\d+)\s*$/.exec(output);
1106
+ if (!match)
1107
+ return null;
1108
+ const ppid = Number(match[1]);
1109
+ return Number.isInteger(ppid) && ppid > 0 ? ppid : null;
1110
+ } catch {
1111
+ return null;
1112
+ }
1113
+ }
1114
+ function collectAncestorPids(selfPid, parentByPid) {
1115
+ const ancestors = new Set;
1116
+ let current = selfPid;
1117
+ for (let depth = 0;depth < MAX_ANCESTOR_WALK_DEPTH; depth += 1) {
1118
+ let ppid = null;
1119
+ if (parentByPid.has(current)) {
1120
+ ppid = parentByPid.get(current) ?? null;
1121
+ } else if (rpcIdentityPlatform !== "win32") {
1122
+ ppid = readPosixParentPid(current);
1123
+ if (ppid == null && current === process.pid && process.ppid > 0) {
1124
+ ppid = process.ppid;
1125
+ }
1126
+ } else if (current === process.pid && process.ppid > 0) {
1127
+ ppid = process.ppid;
1128
+ } else {
1129
+ break;
1130
+ }
1131
+ if (ppid == null || ppid <= 0 || ppid === current || ancestors.has(ppid))
1132
+ break;
1133
+ ancestors.add(ppid);
1134
+ current = ppid;
1135
+ }
1136
+ return ancestors;
1137
+ }
1138
+ function classifyLivePiSnapshot(snapshot) {
1139
+ const ancestors = collectAncestorPids(process.pid, snapshot.parentByPid);
1140
+ const processIds = new Set;
1141
+ const inconclusivePids = new Set;
1142
+ const skippedAncestorPids = [];
1143
+ for (const fact of snapshot.facts) {
1144
+ if (fact.pid === process.pid)
1145
+ continue;
1146
+ const command = fact.commandLine ?? fact.imageName ?? "";
1147
+ const looksLikeHarness = commandHasPiHarnessArc(command) || commandLooksLikePiImage(command);
1148
+ if (!looksLikeHarness)
1149
+ continue;
1150
+ if (ancestors.has(fact.pid)) {
1151
+ skippedAncestorPids.push(fact.pid);
1152
+ log(`[magic-context] Pi process scan: skipping ancestor PID ${fact.pid} (session launcher shim)`);
1153
+ continue;
1154
+ }
1155
+ if (commandHasPiHarnessArc(command)) {
1156
+ processIds.add(fact.pid);
1157
+ continue;
1158
+ }
1159
+ inconclusivePids.add(fact.pid);
1160
+ log(`[magic-context] Pi process scan: PID ${fact.pid} command line is ambiguous (image-name or missing Pi/OMP arc); treating as inconclusive`);
1161
+ }
1162
+ skippedAncestorPids.sort((left, right) => left - right);
1163
+ const verified = [...processIds].sort((left, right) => left - right);
1164
+ const inconclusive = [...inconclusivePids].sort((left, right) => left - right);
1165
+ if (verified.length === 0 && inconclusive.length > 0) {
1166
+ return {
1167
+ state: "inconclusive",
1168
+ processIds: [],
1169
+ inconclusivePids: inconclusive,
1170
+ ...skippedAncestorPids.length > 0 ? { skippedAncestorPids } : {}
1171
+ };
1172
+ }
1173
+ return {
1174
+ state: "known",
1175
+ processIds: verified,
1176
+ ...inconclusive.length > 0 ? { inconclusivePids: inconclusive } : {},
1177
+ ...skippedAncestorPids.length > 0 ? { skippedAncestorPids } : {}
1178
+ };
1179
+ }
920
1180
  function inspectLivePiProcesses() {
921
1181
  if (false) {}
922
1182
  try {
923
- const isWindows = rpcIdentityPlatform === "win32";
924
- const output = String(rpcProcessListExecFileSync(isWindows ? "tasklist" : "ps", isWindows ? ["/FO", "CSV"] : ["-axo", "pid=,command="], {
925
- encoding: "utf8",
926
- timeout: PS_PROBE_TIMEOUT_MS,
927
- stdio: ["ignore", "pipe", "pipe"]
928
- }));
929
- const pids = new Set;
930
- if (isWindows) {
931
- const entries = parseTasklistOutput(output);
932
- if (entries === null) {
1183
+ if (rpcIdentityPlatform === "win32") {
1184
+ const cim = tryReadWindowsCimSnapshot(rpcProcessListExecFileSync);
1185
+ const snapshot = cim ?? tryReadWindowsTasklistSnapshot();
1186
+ if (!snapshot) {
933
1187
  return {
934
1188
  state: "unreadable",
935
1189
  processIds: [],
936
- error: "tasklist output unavailable"
1190
+ error: "process list unavailable"
937
1191
  };
938
1192
  }
939
- for (const entry of entries) {
940
- if (entry.pid === process.pid)
941
- continue;
942
- if (commandLooksLikePi(entry.command))
943
- pids.add(entry.pid);
944
- }
945
- } else {
946
- for (const line of output.split(/\r?\n/)) {
947
- const match = /^\s*(\d+)\s+(.+)$/.exec(line);
948
- if (!match)
949
- continue;
950
- const pid = Number(match[1]);
951
- if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid)
952
- continue;
953
- if (commandLooksLikePi(match[2]))
954
- pids.add(pid);
955
- }
1193
+ rememberWindowsProcessFacts(snapshot.facts);
1194
+ return classifyLivePiSnapshot(snapshot);
956
1195
  }
957
- return { state: "known", processIds: [...pids].sort((left, right) => left - right) };
1196
+ return classifyLivePiSnapshot(readPosixProcessSnapshot());
958
1197
  } catch (error) {
959
1198
  return {
960
1199
  state: "unreadable",
@@ -1241,7 +1480,7 @@ async function prepareAuthority(args) {
1241
1480
  if (identities.length > 0) {
1242
1481
  args.db.transaction(() => {
1243
1482
  for (const identity of identities) {
1244
- rememberIdentity(args.db, domain, args.projectPath, identity.moduleRowId, identity.sourceRowId);
1483
+ rememberIdentity(args.db, domain, args.projectPath, identity.moduleRowId, identity.sourceRowId, undefined, true);
1245
1484
  }
1246
1485
  }).immediate();
1247
1486
  }
@@ -1880,11 +2119,16 @@ function applyMirroredNoteCompileFields(args) {
1880
2119
  return result.changes === 1;
1881
2120
  });
1882
2121
  }
1883
- function rememberIdentity(db, domain, moduleProject, moduleRowId, contextRowId, statements) {
2122
+ function rememberIdentity(db, domain, moduleProject, moduleRowId, contextRowId, statements, replaceContextIdentity = domain === "notes") {
1884
2123
  const existing = mirrorIdentity(db, domain, moduleProject, moduleRowId, statements);
1885
- if (existing)
2124
+ if (existing?.context_row_id === contextRowId)
1886
2125
  return;
1887
- if (domain === "notes") {
2126
+ if (existing) {
2127
+ if (!replaceContextIdentity)
2128
+ return;
2129
+ (statements?.deleteIdentity ?? db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND module_project = ? AND module_row_id = ?")).run(domain, moduleProject, moduleRowId);
2130
+ }
2131
+ if (replaceContextIdentity) {
1888
2132
  (statements?.deleteIdentityByContext ?? db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND context_row_id = ?")).run(domain, contextRowId);
1889
2133
  }
1890
2134
  (statements?.insertIdentity ?? db.prepare("INSERT OR IGNORE INTO mirror_identity(domain, module_project, module_row_id, context_row_id) VALUES (?, ?, ?, ?)")).run(domain, moduleProject, moduleRowId, contextRowId);
@@ -1899,7 +2143,7 @@ function contextMemoryId(db, domain, moduleProject, row, moduleRowId, statements
1899
2143
  if (sourceUuid && sourceUuid === localStoreUuid && sourceId >= 0) {
1900
2144
  const existing = (statements?.memoryIdByStoreId ?? db.prepare("SELECT id FROM memories WHERE id = ? AND project_path = ?")).get(sourceId, moduleProject);
1901
2145
  if (existing?.id !== undefined) {
1902
- rememberIdentity(db, domain, moduleProject, moduleRowId, existing.id, statements);
2146
+ rememberIdentity(db, domain, moduleProject, moduleRowId, existing.id, statements, true);
1903
2147
  return existing.id;
1904
2148
  }
1905
2149
  }
@@ -2128,6 +2372,24 @@ function applyMirrorPage(args) {
2128
2372
  if (page.domain === "memories" && resnapshotStatus !== "complete" && page.rows.some((feed) => feed.op === "tombstone")) {
2129
2373
  throw new Error("memory mirror resnapshot must complete before tombstones");
2130
2374
  }
2375
+ if (page.domain === "memories") {
2376
+ for (const feed of page.rows) {
2377
+ if (feed.domain !== "memories" || feed.op === "tombstone" || feed.feed_seq <= durableCursor) {
2378
+ continue;
2379
+ }
2380
+ const row = feed.full_row_snapshot;
2381
+ const moduleProject = rowString(row, "project_path");
2382
+ const sourceUuid = rowNullableString(row, "context_store_uuid");
2383
+ const sourceId = rowNumber(row, "context_row_id", -1);
2384
+ if (!moduleProject || !sourceUuid || sourceUuid !== statements.contextStoreUuid || sourceId < 0) {
2385
+ continue;
2386
+ }
2387
+ const existing = statements.memoryIdByStoreId.get(sourceId, moduleProject);
2388
+ if (existing?.id === undefined)
2389
+ continue;
2390
+ rememberIdentity(db, "memories", moduleProject, feed.module_row_id, existing.id, statements, true);
2391
+ }
2392
+ }
2131
2393
  const touchedProjects = new Set;
2132
2394
  for (const feed of page.rows) {
2133
2395
  if (feed.domain !== page.domain || feed.feed_seq <= nextCursor)
@@ -2270,6 +2532,135 @@ function pullMemoryMirrorOnce(args) {
2270
2532
  return flight;
2271
2533
  }
2272
2534
 
2535
+ // src/features/magic-context/message-fts-rowid-map.ts
2536
+ import { createHash as createHash3 } from "node:crypto";
2537
+ var MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE = 500;
2538
+ var BACKFILL_STATE_ID = 1;
2539
+ var EMPTY_INDEX_CONTENT_HASH = createHash3("sha256").update("").digest("hex");
2540
+ var upsertMapStatements = new WeakMap;
2541
+ var rangeReadyStatements = new WeakMap;
2542
+ var activeBackfills = new WeakMap;
2543
+ function getUpsertMapStatement(db) {
2544
+ let statement = upsertMapStatements.get(db);
2545
+ if (!statement) {
2546
+ statement = db.prepare(`INSERT INTO message_fts_rowid_map (session_id, message_ordinal, fts_rowid)
2547
+ VALUES (?, ?, ?)
2548
+ ON CONFLICT(session_id, message_ordinal) DO UPDATE SET
2549
+ fts_rowid = excluded.fts_rowid`);
2550
+ upsertMapStatements.set(db, statement);
2551
+ }
2552
+ return statement;
2553
+ }
2554
+ function getBackfillState(db) {
2555
+ const row = db.prepare(`SELECT watermark_rowid AS watermarkRowid, completed
2556
+ FROM message_fts_rowid_map_backfill_state
2557
+ WHERE id = ?`).get(BACKFILL_STATE_ID);
2558
+ return {
2559
+ processed: 0,
2560
+ watermarkRowid: typeof row?.watermarkRowid === "number" && Number.isSafeInteger(row.watermarkRowid) ? row.watermarkRowid : 0,
2561
+ completed: row?.completed === 1
2562
+ };
2563
+ }
2564
+ function recordMessageFtsRowid(db, sessionId, messageOrdinal, ftsRowid) {
2565
+ const numericRowid = Number(ftsRowid);
2566
+ if (!Number.isSafeInteger(numericRowid) || numericRowid <= 0) {
2567
+ throw new Error(`invalid message FTS rowid: ${String(ftsRowid)}`);
2568
+ }
2569
+ getUpsertMapStatement(db).run(sessionId, messageOrdinal, numericRowid);
2570
+ }
2571
+ function backfillMessageFtsRowidMapBatch(db, batchSize = MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE) {
2572
+ const boundedBatchSize = Math.max(1, Math.floor(batchSize));
2573
+ let progress = {
2574
+ processed: 0,
2575
+ watermarkRowid: 0,
2576
+ completed: false
2577
+ };
2578
+ db.transaction(() => {
2579
+ const state = getBackfillState(db);
2580
+ if (state.completed) {
2581
+ progress = state;
2582
+ return;
2583
+ }
2584
+ const rows = db.prepare(`SELECT rowid AS ftsRowid,
2585
+ session_id AS sessionId,
2586
+ message_ordinal AS messageOrdinal
2587
+ FROM message_history_fts
2588
+ WHERE rowid > ?
2589
+ ORDER BY rowid ASC
2590
+ LIMIT ?`).all(state.watermarkRowid, boundedBatchSize);
2591
+ let watermarkRowid = state.watermarkRowid;
2592
+ for (const row of rows) {
2593
+ const ftsRowid = Number(row.ftsRowid);
2594
+ const messageOrdinal = Number(row.messageOrdinal);
2595
+ if (Number.isSafeInteger(ftsRowid) && ftsRowid > watermarkRowid) {
2596
+ watermarkRowid = ftsRowid;
2597
+ }
2598
+ if (typeof row.sessionId === "string" && Number.isSafeInteger(messageOrdinal) && messageOrdinal >= 0 && Number.isSafeInteger(ftsRowid) && ftsRowid > 0) {
2599
+ recordMessageFtsRowid(db, row.sessionId, messageOrdinal, ftsRowid);
2600
+ }
2601
+ }
2602
+ const completed = rows.length < boundedBatchSize;
2603
+ db.prepare(`UPDATE message_fts_rowid_map_backfill_state
2604
+ SET watermark_rowid = ?, completed = ?, updated_at = ?
2605
+ WHERE id = ?`).run(watermarkRowid, completed ? 1 : 0, Date.now(), BACKFILL_STATE_ID);
2606
+ progress = {
2607
+ processed: rows.length,
2608
+ watermarkRowid,
2609
+ completed
2610
+ };
2611
+ })();
2612
+ return progress;
2613
+ }
2614
+ async function runMessageFtsRowidMapBackfill(db) {
2615
+ for (;; ) {
2616
+ const progress = backfillMessageFtsRowidMapBatch(db);
2617
+ if (progress.completed)
2618
+ return;
2619
+ await new Promise((resolve) => setTimeout(resolve, 0));
2620
+ }
2621
+ }
2622
+ function startMessageFtsRowidMapBackfill(db) {
2623
+ const active = activeBackfills.get(db);
2624
+ if (active)
2625
+ return active;
2626
+ const run = runMessageFtsRowidMapBackfill(db).finally(() => {
2627
+ activeBackfills.delete(db);
2628
+ });
2629
+ activeBackfills.set(db, run);
2630
+ return run;
2631
+ }
2632
+ function messageFtsOrdinalRangeIsMapped(db, sessionId, startOrdinal, endOrdinal) {
2633
+ if (endOrdinal < startOrdinal)
2634
+ return true;
2635
+ if (getBackfillState(db).completed)
2636
+ return true;
2637
+ let statement = rangeReadyStatements.get(db);
2638
+ if (!statement) {
2639
+ statement = db.prepare(`SELECT COUNT(DISTINCT source.message_ordinal) AS sourceOrdinalCount,
2640
+ COUNT(DISTINCT CASE
2641
+ WHEN source.role IN ('user', 'assistant')
2642
+ AND source.normalized_content_hash != ?
2643
+ THEN source.message_ordinal
2644
+ END) AS expectedMapCount,
2645
+ COUNT(DISTINCT CASE
2646
+ WHEN source.role IN ('user', 'assistant')
2647
+ AND source.normalized_content_hash != ?
2648
+ AND map.fts_rowid IS NOT NULL
2649
+ THEN source.message_ordinal
2650
+ END) AS mappedCount
2651
+ FROM message_history_source AS source
2652
+ LEFT JOIN message_fts_rowid_map AS map
2653
+ ON map.session_id = source.session_id
2654
+ AND map.message_ordinal = source.message_ordinal
2655
+ WHERE source.session_id = ?
2656
+ AND source.message_ordinal BETWEEN ? AND ?`);
2657
+ rangeReadyStatements.set(db, statement);
2658
+ }
2659
+ const row = statement.get(EMPTY_INDEX_CONTENT_HASH, EMPTY_INDEX_CONTENT_HASH, sessionId, startOrdinal, endOrdinal);
2660
+ const ordinalCount = endOrdinal - startOrdinal + 1;
2661
+ return row?.sourceOrdinalCount === ordinalCount && row.expectedMapCount === row.mappedCount;
2662
+ }
2663
+
2273
2664
  // src/hooks/magic-context/compartment-parser.ts
2274
2665
  var COMPARTMENT_REGEX = /<compartment\s+([^>]*?)\s*>(.*?)<\/compartment>/gs;
2275
2666
  var ATTR_START_REGEX = /\bstart="(\d+)"/;
@@ -2491,6 +2882,7 @@ function healAllNullColumns(db) {
2491
2882
  ["stale_reduce_stripped_ids", ""],
2492
2883
  ["processed_image_stripped_ids", ""],
2493
2884
  ["merged_reasoning_stripped_ids", ""],
2885
+ ["thinking_binding_recovery_target", ""],
2494
2886
  ["trailing_blank_decisions", ""],
2495
2887
  ["memory_block_cache", ""],
2496
2888
  ["memory_block_ids", ""],
@@ -2542,7 +2934,7 @@ function healMissingMemoryBlockIds(db, columns) {
2542
2934
  }
2543
2935
 
2544
2936
  // src/features/magic-context/workspaces.ts
2545
- import { createHash as createHash4 } from "node:crypto";
2937
+ import { createHash as createHash5 } from "node:crypto";
2546
2938
 
2547
2939
  // src/features/magic-context/memory/constants.ts
2548
2940
  var V2_MEMORY_CATEGORIES = [
@@ -2596,7 +2988,7 @@ var CATEGORY_DEFAULT_TTL = {
2596
2988
 
2597
2989
  // src/features/magic-context/memory/project-identity.ts
2598
2990
  import { execFileSync as execFileSync2 } from "node:child_process";
2599
- import { createHash as createHash3 } from "node:crypto";
2991
+ import { createHash as createHash4 } from "node:crypto";
2600
2992
  import { existsSync, realpathSync, statSync } from "node:fs";
2601
2993
  import { homedir } from "node:os";
2602
2994
  import path from "node:path";
@@ -2666,7 +3058,7 @@ function getErrorStderr(error) {
2666
3058
  }
2667
3059
  function directoryFallback(directory) {
2668
3060
  const canonical = path.resolve(directory);
2669
- const hash = createHash3("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
3061
+ const hash = createHash4("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
2670
3062
  return `dir:${hash}`;
2671
3063
  }
2672
3064
  function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
@@ -2927,6 +3319,9 @@ function gitRootDirectory(canonical) {
2927
3319
  return null;
2928
3320
  }
2929
3321
  }
3322
+ function directoryHasGitMetadata(directory) {
3323
+ return gitRootDirectory(path.resolve(directory)) !== null;
3324
+ }
2930
3325
  function resolveProjectIdentityForSession(directory, allowHomeProject = false) {
2931
3326
  const canonicalHome = canonicalUserHomeDirectory();
2932
3327
  const canonicalDirectory = (() => {
@@ -3164,7 +3559,7 @@ function computeWorkspaceEpochFingerprint(db, identities) {
3164
3559
  const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
3165
3560
  const epochs = getEpochMap(db, canonical);
3166
3561
  const shareCategories = selectWorkspaceShareCategories(db, canonical);
3167
- const hash = createHash4("sha256");
3562
+ const hash = createHash5("sha256");
3168
3563
  hash.update("share_categories", "utf8");
3169
3564
  hash.update("\x00");
3170
3565
  hash.update(shareCategories === null ? "NO_WORKSPACE" : JSON.stringify(shareCategories), "utf8");
@@ -5389,6 +5784,30 @@ var MIGRATIONS = [
5389
5784
  return;
5390
5785
  ensureColumn(db, "memory_verifications", "mapping_origin", "TEXT NOT NULL DEFAULT 'mapper'");
5391
5786
  }
5787
+ },
5788
+ {
5789
+ version: 83,
5790
+ description: "add indexed rowid access for message FTS content",
5791
+ up(db) {
5792
+ db.exec(`
5793
+ CREATE TABLE IF NOT EXISTS message_fts_rowid_map (
5794
+ session_id TEXT NOT NULL,
5795
+ message_ordinal INTEGER NOT NULL,
5796
+ fts_rowid INTEGER NOT NULL,
5797
+ PRIMARY KEY(session_id, message_ordinal)
5798
+ );
5799
+
5800
+ CREATE TABLE IF NOT EXISTS message_fts_rowid_map_backfill_state (
5801
+ id INTEGER PRIMARY KEY CHECK(id = 1),
5802
+ watermark_rowid INTEGER NOT NULL DEFAULT 0,
5803
+ completed INTEGER NOT NULL DEFAULT 0 CHECK(completed IN (0, 1)),
5804
+ updated_at INTEGER NOT NULL DEFAULT 0
5805
+ );
5806
+ INSERT OR IGNORE INTO message_fts_rowid_map_backfill_state
5807
+ (id, watermark_rowid, completed, updated_at)
5808
+ VALUES (1, 0, 0, 0);
5809
+ `);
5810
+ }
5392
5811
  }
5393
5812
  ];
5394
5813
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -5507,7 +5926,7 @@ async function runMigrationsWithRetry(db, options = {}) {
5507
5926
  }
5508
5927
 
5509
5928
  // src/features/magic-context/tool-definition-tokens.ts
5510
- import { createHash as createHash5 } from "node:crypto";
5929
+ import { createHash as createHash6 } from "node:crypto";
5511
5930
 
5512
5931
  // src/hooks/magic-context/read-session-formatting.ts
5513
5932
  import { existsSync as existsSync2, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "node:fs";
@@ -5846,7 +6265,7 @@ function keyFor(providerID, modelID, agentName) {
5846
6265
  return `${providerID}/${modelID}/${agent}`;
5847
6266
  }
5848
6267
  function fingerprintFor(description, parameters) {
5849
- return createHash5("sha256").update(description).update("\x00").update(stableStringify(parameters)).digest("hex");
6268
+ return createHash6("sha256").update(description).update("\x00").update(stableStringify(parameters)).digest("hex");
5850
6269
  }
5851
6270
  function getCurrentToolSetHash(providerID, modelID, agentName) {
5852
6271
  if (!providerID || !modelID)
@@ -5854,7 +6273,7 @@ function getCurrentToolSetHash(providerID, modelID, agentName) {
5854
6273
  const toolIds = measurements.get(keyFor(providerID, modelID, agentName));
5855
6274
  if (!toolIds || toolIds.size === 0)
5856
6275
  return "";
5857
- return createHash5("sha256").update(Array.from(toolIds.keys()).sort().join("\x00")).digest("hex");
6276
+ return createHash6("sha256").update(Array.from(toolIds.keys()).sort().join("\x00")).digest("hex");
5858
6277
  }
5859
6278
  function setDatabase(db) {
5860
6279
  persistenceDb = db;
@@ -6197,7 +6616,7 @@ function getSchemaFenceRejection() {
6197
6616
  function getMigrationOnOpenRefusal() {
6198
6617
  return lastMigrationOnOpenRefusal;
6199
6618
  }
6200
- var LATEST_SUPPORTED_VERSION = 82;
6619
+ var LATEST_SUPPORTED_VERSION = 83;
6201
6620
  var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
6202
6621
  var defaultStoragePermissionFs = { chmodSync, mkdirSync };
6203
6622
  var storagePermissionFs = defaultStoragePermissionFs;
@@ -6496,13 +6915,18 @@ function createPiBlockingProcess(pid) {
6496
6915
  function formatInconclusiveOpenCodeMigrationWarning(dbPath, pids) {
6497
6916
  return `[magic-context] storage warning: continuing migration for ${dbPath}; OpenCode server PID ${pids.join(", ")} was not confirmed because its liveness or identity check could not run. This commonly means an OS sandbox denied kill(0) or ps. No live OpenCode server was confirmed.`;
6498
6917
  }
6499
- function logInconclusiveMigrationProbes(dbPath, discovery, piProbeState) {
6918
+ function formatInconclusivePiMigrationWarning(dbPath, pids) {
6919
+ return `[magic-context] storage warning: continuing migration for ${dbPath}; Pi/OMP PID ${pids.join(", ")} was not confirmed as a live harness because the process image or command line was ambiguous. No live Pi harness was confirmed.`;
6920
+ }
6921
+ function logInconclusiveMigrationProbes(dbPath, discovery, piDiscovery) {
6500
6922
  const uncertainPids = discovery.inconclusivePids ?? [];
6501
6923
  if (uncertainPids.length > 0) {
6502
6924
  log(formatInconclusiveOpenCodeMigrationWarning(dbPath, uncertainPids));
6503
6925
  }
6504
- if (piProbeState === "unreadable") {
6926
+ if (piDiscovery.state === "unreadable") {
6505
6927
  log(`[magic-context] storage warning: continuing migration for ${dbPath}; the Pi/OMP process-list probe could not run, which commonly means an OS sandbox denied ps. No live Pi harness was confirmed.`);
6928
+ } else if ((piDiscovery.inconclusivePids?.length ?? 0) > 0) {
6929
+ log(formatInconclusivePiMigrationWarning(dbPath, piDiscovery.inconclusivePids ?? []));
6506
6930
  }
6507
6931
  }
6508
6932
  function isDefaultSharedDatabasePath(dbPath) {
@@ -6537,7 +6961,7 @@ function enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion)
6537
6961
  const blockingProcesses = [...serverProcesses, ...piPids.map(createPiBlockingProcess)];
6538
6962
  if ((discovery.state === "absent" || discovery.state === "stale" || discovery.state === "inconclusive") && piPids.length === 0) {
6539
6963
  lastMigrationOnOpenRefusal = null;
6540
- logInconclusiveMigrationProbes(dbPath, discovery, piDiscovery.state);
6964
+ logInconclusiveMigrationProbes(dbPath, discovery, piDiscovery);
6541
6965
  return true;
6542
6966
  }
6543
6967
  const blockingPids = [...new Set([...discovery.serverPids, ...piPids])].sort((left, right) => left - right);
@@ -6584,17 +7008,20 @@ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion)
6584
7008
  }
6585
7009
  healWedgedChannel2Claims(db);
6586
7010
  if (!explicitDbPath) {
6587
- const runBackfill = () => {
7011
+ const runBackfills = () => {
6588
7012
  try {
6589
7013
  runToolOwnerBackfill(db);
6590
7014
  } catch (error) {
6591
7015
  log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error)}`);
6592
7016
  }
7017
+ startMessageFtsRowidMapBackfill(db).catch((error) => {
7018
+ log(`[magic-context] message FTS rowid-map backfill failed (will resume next startup): ${getErrorMessage(error)}`);
7019
+ });
6593
7020
  };
6594
7021
  if (bootQuietRemainingMs() > 0)
6595
- scheduleAfterBootQuiet(runBackfill);
7022
+ scheduleAfterBootQuiet(runBackfills);
6596
7023
  else
6597
- runBackfill();
7024
+ runBackfills();
6598
7025
  }
6599
7026
  setDatabase(db);
6600
7027
  loadToolDefinitionMeasurements(db);
@@ -7134,6 +7561,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
7134
7561
  tokenize='porter unicode61'
7135
7562
  );
7136
7563
 
7564
+ CREATE TABLE IF NOT EXISTS message_fts_rowid_map (
7565
+ session_id TEXT NOT NULL,
7566
+ message_ordinal INTEGER NOT NULL,
7567
+ fts_rowid INTEGER NOT NULL,
7568
+ PRIMARY KEY(session_id, message_ordinal)
7569
+ );
7570
+
7571
+ CREATE TABLE IF NOT EXISTS message_fts_rowid_map_backfill_state (
7572
+ id INTEGER PRIMARY KEY CHECK(id = 1),
7573
+ watermark_rowid INTEGER NOT NULL DEFAULT 0,
7574
+ completed INTEGER NOT NULL DEFAULT 0 CHECK(completed IN (0, 1)),
7575
+ updated_at INTEGER NOT NULL DEFAULT 0
7576
+ );
7577
+ INSERT OR IGNORE INTO message_fts_rowid_map_backfill_state
7578
+ (id, watermark_rowid, completed, updated_at)
7579
+ VALUES (1, 0, 0, 0);
7580
+
7137
7581
  CREATE TABLE IF NOT EXISTS message_history_index (
7138
7582
  session_id TEXT PRIMARY KEY,
7139
7583
  last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
@@ -7277,8 +7721,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
7277
7721
  cached_m0_system_hash TEXT,
7278
7722
  cached_m0_tool_set_hash TEXT,
7279
7723
  cached_m0_model_key TEXT,
7280
- cached_m0_project_identity TEXT,
7281
- cached_m0_last_baseline_end_message_id TEXT,
7724
+ cached_m0_project_identity TEXT,
7725
+ cached_m0_last_baseline_end_message_id TEXT,
7726
+ thinking_binding_recovery_target TEXT NOT NULL DEFAULT '',
7282
7727
  upgrade_reminded_at INTEGER,
7283
7728
  pi_stable_id_scheme INTEGER
7284
7729
  );
@@ -7500,6 +7945,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
7500
7945
  ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
7501
7946
  ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
7502
7947
  ensureColumn(db, "session_meta", "merged_reasoning_stripped_ids", "TEXT DEFAULT ''");
7948
+ ensureColumn(db, "session_meta", "thinking_binding_recovery_target", "TEXT DEFAULT ''");
7503
7949
  ensureColumn(db, "session_meta", "trailing_blank_decisions", "TEXT DEFAULT ''");
7504
7950
  ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
7505
7951
  ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
@@ -7899,7 +8345,7 @@ function probeChildSpawnFence(db) {
7899
8345
  return { allowSpawn: true };
7900
8346
  }
7901
8347
  // src/features/magic-context/message-index.ts
7902
- import { createHash as createHash6 } from "node:crypto";
8348
+ import { createHash as createHash7 } from "node:crypto";
7903
8349
 
7904
8350
  // src/hooks/magic-context/read-session-raw.ts
7905
8351
  function isRawMessageRow(row) {
@@ -9668,6 +10114,9 @@ var upsertMessageSourceStatements = new WeakMap;
9668
10114
  var deleteMessageSourceStatements = new WeakMap;
9669
10115
  var deleteMessageSourceRangeStatements = new WeakMap;
9670
10116
  var deleteMessageFtsStatements = new WeakMap;
10117
+ var deleteFtsMapStatements = new WeakMap;
10118
+ var deleteFtsMapRangeStatements = new WeakMap;
10119
+ var deleteMessageFtsMapStatements = new WeakMap;
9671
10120
  function normalizeIndexText(text) {
9672
10121
  return text.replace(/\s+/g, " ").trim();
9673
10122
  }
@@ -9706,7 +10155,10 @@ function getUpsertDirtyFloorStatement(db) {
9706
10155
  function getDeleteFtsStatement(db) {
9707
10156
  let stmt = deleteFtsStatements.get(db);
9708
10157
  if (!stmt) {
9709
- stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ?");
10158
+ stmt = db.prepare(`DELETE FROM message_history_fts
10159
+ WHERE rowid IN (
10160
+ SELECT fts_rowid FROM message_fts_rowid_map WHERE session_id = ?
10161
+ )`);
9710
10162
  deleteFtsStatements.set(db, stmt);
9711
10163
  }
9712
10164
  return stmt;
@@ -9714,7 +10166,12 @@ function getDeleteFtsStatement(db) {
9714
10166
  function getDeleteFtsRangeStatement(db) {
9715
10167
  let stmt = deleteFtsRangeStatements.get(db);
9716
10168
  if (!stmt) {
9717
- stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ? AND CAST(message_ordinal AS INTEGER) BETWEEN ? AND ?");
10169
+ stmt = db.prepare(`DELETE FROM message_history_fts
10170
+ WHERE rowid IN (
10171
+ SELECT fts_rowid
10172
+ FROM message_fts_rowid_map
10173
+ WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?
10174
+ )`);
9718
10175
  deleteFtsRangeStatements.set(db, stmt);
9719
10176
  }
9720
10177
  return stmt;
@@ -9730,7 +10187,12 @@ function getDeleteIndexStatement(db) {
9730
10187
  function getCountIndexedMessageStatement(db) {
9731
10188
  let stmt = countIndexedMessageStatements.get(db);
9732
10189
  if (!stmt) {
9733
- stmt = db.prepare("SELECT COUNT(*) AS count FROM message_history_fts WHERE session_id = ? AND message_id = ?");
10190
+ stmt = db.prepare(`SELECT COUNT(*) AS count
10191
+ FROM message_history_source AS source
10192
+ JOIN message_fts_rowid_map AS map
10193
+ ON map.session_id = source.session_id
10194
+ AND map.message_ordinal = source.message_ordinal
10195
+ WHERE source.session_id = ? AND source.message_id = ?`);
9734
10196
  countIndexedMessageStatements.set(db, stmt);
9735
10197
  }
9736
10198
  return stmt;
@@ -9780,11 +10242,53 @@ function getDeleteMessageSourceRangeStatement(db) {
9780
10242
  function getDeleteMessageFtsStatement(db) {
9781
10243
  let stmt = deleteMessageFtsStatements.get(db);
9782
10244
  if (!stmt) {
9783
- stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ? AND message_id = ?");
10245
+ stmt = db.prepare(`DELETE FROM message_history_fts
10246
+ WHERE rowid IN (
10247
+ SELECT map.fts_rowid
10248
+ FROM message_history_source AS source
10249
+ JOIN message_fts_rowid_map AS map
10250
+ ON map.session_id = source.session_id
10251
+ AND map.message_ordinal = source.message_ordinal
10252
+ WHERE source.session_id = ? AND source.message_id = ?
10253
+ )`);
9784
10254
  deleteMessageFtsStatements.set(db, stmt);
9785
10255
  }
9786
10256
  return stmt;
9787
10257
  }
10258
+ function getDeleteFtsMapStatement(db) {
10259
+ let stmt = deleteFtsMapStatements.get(db);
10260
+ if (!stmt) {
10261
+ stmt = db.prepare("DELETE FROM message_fts_rowid_map WHERE session_id = ?");
10262
+ deleteFtsMapStatements.set(db, stmt);
10263
+ }
10264
+ return stmt;
10265
+ }
10266
+ function getDeleteFtsMapRangeStatement(db) {
10267
+ let stmt = deleteFtsMapRangeStatements.get(db);
10268
+ if (!stmt) {
10269
+ stmt = db.prepare("DELETE FROM message_fts_rowid_map WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?");
10270
+ deleteFtsMapRangeStatements.set(db, stmt);
10271
+ }
10272
+ return stmt;
10273
+ }
10274
+ function getDeleteMessageFtsMapStatement(db) {
10275
+ let stmt = deleteMessageFtsMapStatements.get(db);
10276
+ if (!stmt) {
10277
+ stmt = db.prepare(`DELETE FROM message_fts_rowid_map
10278
+ WHERE session_id = ?
10279
+ AND message_ordinal = (
10280
+ SELECT message_ordinal
10281
+ FROM message_history_source
10282
+ WHERE session_id = ? AND message_id = ?
10283
+ )`);
10284
+ deleteMessageFtsMapStatements.set(db, stmt);
10285
+ }
10286
+ return stmt;
10287
+ }
10288
+ function insertMessageFtsRow(db, sessionId, messageOrdinal, messageId, role, content) {
10289
+ const result = getInsertMessageStatement(db).run(sessionId, messageOrdinal, messageId, role, content);
10290
+ recordMessageFtsRowid(db, sessionId, messageOrdinal, result.lastInsertRowid);
10291
+ }
9788
10292
  function normalizeSourceVersion(version) {
9789
10293
  if (typeof version === "number")
9790
10294
  return `number:${version}`;
@@ -9797,7 +10301,7 @@ function getMessageSourceSnapshot(message) {
9797
10301
  return {
9798
10302
  ordinal: message.ordinal,
9799
10303
  sourceVersion: normalizeSourceVersion(message.version),
9800
- contentHash: createHash6("sha256").update(content).digest("hex"),
10304
+ contentHash: createHash7("sha256").update(content).digest("hex"),
9801
10305
  role: message.role,
9802
10306
  content
9803
10307
  };
@@ -9857,6 +10361,7 @@ function deleteIndexedMessage(db, sessionId, messageId) {
9857
10361
  function clearIndexedMessages(db, sessionId) {
9858
10362
  db.transaction(() => {
9859
10363
  getDeleteFtsStatement(db).run(sessionId);
10364
+ getDeleteFtsMapStatement(db).run(sessionId);
9860
10365
  getDeleteMessageSourceStatement(db).run(sessionId);
9861
10366
  getDeleteIndexStatement(db).run(sessionId);
9862
10367
  clearCompressionDepth(db, sessionId);
@@ -9881,10 +10386,14 @@ function indexSingleMessageInTransaction(db, sessionId, message, now, dirtyFloor
9881
10386
  if (isMessageIndexSourceCurrent(db, sessionId, message)) {
9882
10387
  return false;
9883
10388
  }
10389
+ if (!messageFtsOrdinalRangeIsMapped(db, sessionId, message.ordinal, message.ordinal)) {
10390
+ return false;
10391
+ }
9884
10392
  getDeleteMessageFtsStatement(db).run(sessionId, message.id);
10393
+ getDeleteMessageFtsMapStatement(db).run(sessionId, sessionId, message.id);
9885
10394
  const content2 = setMessageSource(db, sessionId, message, now);
9886
10395
  if (content2.length > 0 && (message.role === "user" || message.role === "assistant")) {
9887
- getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content2);
10396
+ insertMessageFtsRow(db, sessionId, message.ordinal, message.id, message.role, content2);
9888
10397
  }
9889
10398
  setIndexProgress(db, sessionId, currentWatermark, dirtyFloorBeforeAttempt === message.ordinal ? null : dirtyFloorBeforeAttempt, now);
9890
10399
  return true;
@@ -9895,7 +10404,7 @@ function indexSingleMessageInTransaction(db, sessionId, message, now, dirtyFloor
9895
10404
  const content = setMessageSource(db, sessionId, message, now);
9896
10405
  let inserted = false;
9897
10406
  if (content.length > 0 && (message.role === "user" || message.role === "assistant") && !isMessageAlreadyIndexed(db, sessionId, message.id)) {
9898
- getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content);
10407
+ insertMessageFtsRow(db, sessionId, message.ordinal, message.id, message.role, content);
9899
10408
  inserted = true;
9900
10409
  }
9901
10410
  setIndexProgress(db, sessionId, message.ordinal, dirtyFloorBeforeAttempt === message.ordinal ? null : dirtyFloorBeforeAttempt, now);
@@ -9932,8 +10441,14 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, _lastIndexedOrdinal,
9932
10441
  const currentWatermark = getLastIndexedOrdinal(db, sessionId);
9933
10442
  const dirtyFloor = getDirtyIndexFloor(db, sessionId);
9934
10443
  const effectiveWatermark = dirtyFloor === null ? currentWatermark : Math.min(currentWatermark, Math.max(0, dirtyFloor - 1));
10444
+ if (dirtyFloor !== null && dirtyFloor <= currentWatermark && !messageFtsOrdinalRangeIsMapped(db, sessionId, dirtyFloor, Math.min(currentWatermark, finalWatermark))) {
10445
+ db.exec("COMMIT");
10446
+ committed = true;
10447
+ return 0;
10448
+ }
9935
10449
  if (dirtyFloor !== null && dirtyFloor <= finalWatermark) {
9936
10450
  getDeleteFtsRangeStatement(db).run(sessionId, dirtyFloor, finalWatermark);
10451
+ getDeleteFtsMapRangeStatement(db).run(sessionId, dirtyFloor, finalWatermark);
9937
10452
  getDeleteMessageSourceRangeStatement(db).run(sessionId, dirtyFloor, finalWatermark);
9938
10453
  }
9939
10454
  const messagesByOrdinal = new Map;
@@ -9954,7 +10469,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, _lastIndexedOrdinal,
9954
10469
  if (content.length === 0 || message.role !== "user" && message.role !== "assistant" || isMessageAlreadyIndexed(db, sessionId, message.id)) {
9955
10470
  continue;
9956
10471
  }
9957
- getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content);
10472
+ insertMessageFtsRow(db, sessionId, message.ordinal, message.id, message.role, content);
9958
10473
  inserted += 1;
9959
10474
  }
9960
10475
  const missingFloor = coveredWatermark < finalWatermark ? coveredWatermark + 1 : null;
@@ -9982,6 +10497,16 @@ function persistMessageHistoryOrphanSweepState(db, cursor, lastSweptAt) {
9982
10497
  cursor_session_id = excluded.cursor_session_id,
9983
10498
  last_swept_at = excluded.last_swept_at`).run(cursor, lastSweptAt);
9984
10499
  }
10500
+ function getOpenCodeSessionScopedCandidateSourceSql() {
10501
+ return SESSION_SCOPED_TABLES.filter((definition) => definition.harnessScoped === true).map((definition) => {
10502
+ const predicates = ["session_id IS NOT NULL", "harness = 'opencode'"];
10503
+ if (definition.extraPredicate)
10504
+ predicates.push(definition.extraPredicate);
10505
+ return `SELECT session_id FROM ${definition.table} WHERE ${predicates.join(" AND ")}`;
10506
+ }).join(`
10507
+ UNION
10508
+ `);
10509
+ }
9985
10510
  function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options = {}) {
9986
10511
  const now = options.now ?? Date.now();
9987
10512
  const batchSize = Math.max(1, Math.floor(options.batchSize ?? MESSAGE_HISTORY_ORPHAN_SWEEP_BATCH_SIZE));
@@ -10005,13 +10530,19 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
10005
10530
  }
10006
10531
  try {
10007
10532
  const cutoff = now - safetyAgeMs;
10533
+ const candidateSourceSql = getOpenCodeSessionScopedCandidateSourceSql();
10008
10534
  const candidates = db.prepare(`SELECT session_id
10009
- FROM message_history_index
10010
- WHERE harness = 'opencode'
10011
- AND updated_at <= ?
10012
- AND session_id > ?
10535
+ FROM (${candidateSourceSql}) AS session_candidates
10536
+ WHERE session_id > ?
10537
+ AND NOT EXISTS (
10538
+ SELECT 1
10539
+ FROM message_history_index
10540
+ WHERE message_history_index.session_id = session_candidates.session_id
10541
+ AND message_history_index.harness = 'opencode'
10542
+ AND message_history_index.updated_at > ?
10543
+ )
10013
10544
  ORDER BY session_id ASC
10014
- LIMIT ?`).all(cutoff, cursor, batchSize);
10545
+ LIMIT ?`).all(cursor, cutoff, batchSize);
10015
10546
  const sessionExists = openCodeDb.prepare("SELECT 1 FROM session WHERE id = ? LIMIT 1");
10016
10547
  const missingSessionIds = candidates.filter((candidate) => !sessionExists.get(candidate.session_id)).map((candidate) => candidate.session_id);
10017
10548
  const nextCursor = candidates.length < batchSize ? "" : candidates[candidates.length - 1]?.session_id ?? cursor;
@@ -10020,10 +10551,19 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
10020
10551
  let committed = false;
10021
10552
  let deleted = 0;
10022
10553
  try {
10023
- const stillEligible = db.prepare("SELECT 1 FROM message_history_index WHERE session_id = ? AND harness = 'opencode' AND updated_at <= ?");
10554
+ const stillEligible = db.prepare(`SELECT 1
10555
+ FROM (${candidateSourceSql}) AS session_candidates
10556
+ WHERE session_id = ?
10557
+ AND NOT EXISTS (
10558
+ SELECT 1
10559
+ FROM message_history_index
10560
+ WHERE message_history_index.session_id = session_candidates.session_id
10561
+ AND message_history_index.harness = 'opencode'
10562
+ AND message_history_index.updated_at > ?
10563
+ )
10564
+ LIMIT 1`);
10024
10565
  const eligibleSessionIds = missingSessionIds.filter((sessionId) => stillEligible.get(sessionId, cutoff));
10025
- deleteSessionScopedRows(db, eligibleSessionIds, "opencode");
10026
- deleted = eligibleSessionIds.length;
10566
+ deleted = deleteSessionScopedRows(db, eligibleSessionIds, "opencode");
10027
10567
  persistMessageHistoryOrphanSweepState(db, nextCursor, completedAt);
10028
10568
  db.exec("COMMIT");
10029
10569
  committed = true;
@@ -10045,7 +10585,7 @@ function sweepOrphanedOpenCodeMessageIndexes(db, openReadableOpenCodeDb, options
10045
10585
  }
10046
10586
  }
10047
10587
  // src/features/magic-context/project-docs-hash.ts
10048
- import { createHash as createHash7 } from "node:crypto";
10588
+ import { createHash as createHash8 } from "node:crypto";
10049
10589
  import { lstatSync, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
10050
10590
  import path2 from "node:path";
10051
10591
  var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
@@ -10143,7 +10683,7 @@ function hashCanonicalPieces(hashPieces) {
10143
10683
  if (hashPieces.length === 0) {
10144
10684
  return "";
10145
10685
  }
10146
- return createHash7("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
10686
+ return createHash8("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
10147
10687
  }
10148
10688
  function readProjectDocsCanonical(projectDirectory) {
10149
10689
  const canonicalDirectory = path2.resolve(projectDirectory);
@@ -10171,10 +10711,10 @@ function computeProjectDocsHash(projectDirectory) {
10171
10711
  return readProjectDocsCanonical(projectDirectory).canonicalHash;
10172
10712
  }
10173
10713
  // src/features/magic-context/storage-embedding-measurements.ts
10174
- import { createHash as createHash8 } from "node:crypto";
10714
+ import { createHash as createHash9 } from "node:crypto";
10175
10715
  function normalizedQueryHash(query) {
10176
10716
  const normalized = query.trim().replace(/\s+/g, " ").toLowerCase();
10177
- return createHash8("sha256").update(normalized).digest("hex");
10717
+ return createHash9("sha256").update(normalized).digest("hex");
10178
10718
  }
10179
10719
  var MEASUREMENT_CORPUS_SESSION_ROW_CAP = 2000;
10180
10720
  function recordEmbeddingMeasurement(db, input, cap = MEASUREMENT_CORPUS_SESSION_ROW_CAP) {
@@ -11516,6 +12056,29 @@ function removeStrippedPlaceholderId(db, sessionId, messageId) {
11516
12056
  applyStrippedPlaceholderDelta(db, sessionId, { remove: [messageId] });
11517
12057
  return true;
11518
12058
  }
12059
+ var NEWEST_REASONING_BEARING_ASSISTANT = "newest_reasoning_bearing_assistant";
12060
+ var THINKING_BINDING_RECOVERY_FROZEN_PREFIX = "binding_mismatch:";
12061
+ function thinkingBindingRecoveryFrozenId(messageId) {
12062
+ return `${THINKING_BINDING_RECOVERY_FROZEN_PREFIX}${messageId}`;
12063
+ }
12064
+ function getThinkingBindingRecoveryTarget(db, sessionId) {
12065
+ const row = db.prepare("SELECT thinking_binding_recovery_target FROM session_meta WHERE session_id = ?").get(sessionId);
12066
+ const target = row?.thinking_binding_recovery_target;
12067
+ return typeof target === "string" && target.length > 0 ? target : null;
12068
+ }
12069
+ function armThinkingBindingRecovery(db, sessionId, messageId) {
12070
+ ensureSessionMetaRow(db, sessionId);
12071
+ const target = typeof messageId === "string" && messageId.length > 0 ? messageId : NEWEST_REASONING_BEARING_ASSISTANT;
12072
+ if (target === NEWEST_REASONING_BEARING_ASSISTANT) {
12073
+ db.prepare("UPDATE session_meta SET thinking_binding_recovery_target = ? WHERE session_id = ? AND COALESCE(thinking_binding_recovery_target, '') = ''").run(target, sessionId);
12074
+ return;
12075
+ }
12076
+ db.prepare("UPDATE session_meta SET thinking_binding_recovery_target = ? WHERE session_id = ?").run(target, sessionId);
12077
+ }
12078
+ function clearThinkingBindingRecoveryIf(db, sessionId, expectedTarget) {
12079
+ const result = db.prepare("UPDATE session_meta SET thinking_binding_recovery_target = '' WHERE session_id = ? AND thinking_binding_recovery_target = ?").run(sessionId, expectedTarget);
12080
+ return result.changes > 0;
12081
+ }
11519
12082
  function getMergedReasoningStrippedIds(db, sessionId) {
11520
12083
  const row = db.prepare("SELECT merged_reasoning_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
11521
12084
  return new Set(parseStrippedBlob(row?.merged_reasoning_stripped_ids));
@@ -11591,7 +12154,7 @@ function addTrailingBlankDecisions(db, sessionId, additions, options) {
11591
12154
  let changed = false;
11592
12155
  for (const [id, decision] of add) {
11593
12156
  const currentDecision = current.get(id);
11594
- if (currentDecision === undefined || id === options?.overwriteMessageId && currentDecision !== decision) {
12157
+ if (currentDecision === undefined || id === options?.overwriteMessageId && currentDecision !== decision && currentDecision !== "strip") {
11595
12158
  current.set(id, decision);
11596
12159
  changed = true;
11597
12160
  }
@@ -11975,6 +12538,7 @@ function markNoteChecked(db, noteId) {
11975
12538
  // src/features/magic-context/storage-ops.ts
11976
12539
  var queuePendingOpStatements = new WeakMap;
11977
12540
  var getPendingOpsStatements = new WeakMap;
12541
+ var getPendingOpsCountStatements = new WeakMap;
11978
12542
  var clearPendingOpsStatements = new WeakMap;
11979
12543
  var removePendingOpStatements = new WeakMap;
11980
12544
  function getQueuePendingOpStatement(db) {
@@ -12035,6 +12599,19 @@ function getPendingOps(db, sessionId) {
12035
12599
  const rows = getPendingOpsStatement(db).all(sessionId).filter(isPendingOpRow);
12036
12600
  return rows.map(toPendingOp).filter((op) => op !== null);
12037
12601
  }
12602
+ function getPendingOpsCount(db, sessionId) {
12603
+ try {
12604
+ let statement = getPendingOpsCountStatements.get(db);
12605
+ if (!statement) {
12606
+ statement = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?");
12607
+ getPendingOpsCountStatements.set(db, statement);
12608
+ }
12609
+ const row = statement.get(sessionId);
12610
+ return typeof row?.count === "number" && Number.isFinite(row.count) ? row.count : null;
12611
+ } catch {
12612
+ return null;
12613
+ }
12614
+ }
12038
12615
  function clearPendingOps(db, sessionId) {
12039
12616
  getClearPendingOpsStatement(db).run(sessionId);
12040
12617
  }
@@ -12551,7 +13128,7 @@ function readUint32BE(b, offset) {
12551
13128
  }
12552
13129
 
12553
13130
  // src/hooks/magic-context/todo-view.ts
12554
- import { createHash as createHash9 } from "node:crypto";
13131
+ import { createHash as createHash10 } from "node:crypto";
12555
13132
  var TODO_STATUS_PENDING = "pending";
12556
13133
  var TODO_STATUS_IN_PROGRESS = "in_progress";
12557
13134
  var TODO_STATUS_COMPLETED = "completed";
@@ -12619,7 +13196,7 @@ function buildSyntheticTodoPart(stateJson) {
12619
13196
  };
12620
13197
  }
12621
13198
  function computeSyntheticCallId(stateJson) {
12622
- const hash = createHash9("sha256").update(stateJson).digest("hex").slice(0, 16);
13199
+ const hash = createHash10("sha256").update(stateJson).digest("hex").slice(0, 16);
12623
13200
  return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
12624
13201
  }
12625
13202
  function isSyntheticTodoPart(part) {
@@ -13571,7 +14148,10 @@ var getTagNumbersByMessageIdStatements = new WeakMap;
13571
14148
  var deleteTagsByMessageIdStatements = new WeakMap;
13572
14149
  var getMaxTagNumberBySessionStatements = new WeakMap;
13573
14150
  var getTagNumberByMessageIdStatements = new WeakMap;
14151
+ var getAssignableTagNumberByMessageIdStatements = new WeakMap;
13574
14152
  var hasPiFallbackMessageTagStatements = new WeakMap;
14153
+ var WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX = "__mc_whitespace_assistant_inert__:";
14154
+ var WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX = "mc:whitespace-assistant:";
13575
14155
  function getInsertTagStatement(db) {
13576
14156
  let stmt = insertTagStatements.get(db);
13577
14157
  if (!stmt) {
@@ -13791,7 +14371,10 @@ function backfillTagTokenCounts(db, sessionId, tagNumber, counts) {
13791
14371
  function getUpdateTagMessageIdStatement(db) {
13792
14372
  let stmt = updateTagMessageIdStatements.get(db);
13793
14373
  if (!stmt) {
13794
- stmt = db.prepare("UPDATE tags SET message_id = ? WHERE session_id = ? AND tag_number = ?");
14374
+ stmt = db.prepare(`UPDATE tags SET message_id = ?
14375
+ WHERE session_id = ?
14376
+ AND tag_number = ?
14377
+ AND message_id NOT LIKE '${WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX}%'`);
13795
14378
  updateTagMessageIdStatements.set(db, stmt);
13796
14379
  }
13797
14380
  return stmt;
@@ -13828,6 +14411,25 @@ function getTagNumberByMessageIdStatement(db) {
13828
14411
  }
13829
14412
  return stmt;
13830
14413
  }
14414
+ function getAssignableTagNumberByMessageIdStatement(db) {
14415
+ let stmt = getAssignableTagNumberByMessageIdStatements.get(db);
14416
+ if (!stmt) {
14417
+ stmt = db.prepare(`SELECT tag_number FROM tags
14418
+ WHERE session_id = ?
14419
+ AND message_id = ?
14420
+ AND NOT (
14421
+ status = 'compacted'
14422
+ AND COALESCE(
14423
+ entry_fingerprint LIKE '${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%',
14424
+ 0
14425
+ ) = 1
14426
+ )
14427
+ ORDER BY tag_number ASC
14428
+ LIMIT 1`);
14429
+ getAssignableTagNumberByMessageIdStatements.set(db, stmt);
14430
+ }
14431
+ return stmt;
14432
+ }
13831
14433
  function isTagRow(row) {
13832
14434
  if (row === null || typeof row !== "object")
13833
14435
  return false;
@@ -13874,6 +14476,25 @@ function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoni
13874
14476
  function updateTagStatus(db, sessionId, tagId, status) {
13875
14477
  getUpdateTagStatusStatement(db).run(status, sessionId, tagId);
13876
14478
  }
14479
+ function markWhitespaceAssistantTagInert(db, sessionId, tagNumber, contentId) {
14480
+ db.prepare(`UPDATE tags
14481
+ SET status = 'compacted',
14482
+ message_id = ?,
14483
+ entry_fingerprint = ?
14484
+ WHERE session_id = ? AND tag_number = ? AND type = 'message'`).run(`${WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX}${tagNumber}`, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}${contentId}`, sessionId, tagNumber);
14485
+ }
14486
+ function getInertWhitespaceAssistantTags(db, sessionId) {
14487
+ const rows = db.prepare(`SELECT tag_number AS tagNumber, entry_fingerprint AS entryFingerprint
14488
+ FROM tags
14489
+ WHERE session_id = ?
14490
+ AND type = 'message'
14491
+ AND status = 'compacted'
14492
+ AND entry_fingerprint LIKE ?`).all(sessionId, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%`);
14493
+ return rows.flatMap((row) => {
14494
+ const contentId = row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length);
14495
+ return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
14496
+ });
14497
+ }
13877
14498
  function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
13878
14499
  getUpdateTagDropModeStatement(db).run(dropMode, sessionId, tagNumber);
13879
14500
  }
@@ -13921,6 +14542,10 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
13921
14542
  const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
13922
14543
  return isTagNumberRow(row) ? row.tag_number : null;
13923
14544
  }
14545
+ function getAssignableTagNumberByMessageId(db, sessionId, messageId) {
14546
+ const row = getAssignableTagNumberByMessageIdStatement(db).get(sessionId, messageId);
14547
+ return isTagNumberRow(row) ? row.tag_number : null;
14548
+ }
13924
14549
  var getMinMessageTagNumberForRawIdStatements = new WeakMap;
13925
14550
  function isMinTagNumberRow(row) {
13926
14551
  return row !== null && typeof row === "object" && "m" in row;
@@ -14044,6 +14669,13 @@ function getMaxDroppedTagNumber(db, sessionId) {
14044
14669
  const row = getMaxDroppedTagNumberStatement(db).get(sessionId);
14045
14670
  return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
14046
14671
  }
14672
+ function getTagById(db, sessionId, tagId) {
14673
+ const result = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number = ?`).get(sessionId, tagId);
14674
+ if (!isTagRow(result)) {
14675
+ return null;
14676
+ }
14677
+ return toTagEntry(result);
14678
+ }
14047
14679
  var getToolTagNumberByOwnerStatements = new WeakMap;
14048
14680
  var getNullOwnerToolTagStatements = new WeakMap;
14049
14681
  var adoptNullOwnerToolTagStatements = new WeakMap;
@@ -14250,6 +14882,7 @@ var LIMIT_EXTRACTION_PATTERNS = [
14250
14882
  ];
14251
14883
  var MIN_PLAUSIBLE_LIMIT = 1024;
14252
14884
  var MAX_PLAUSIBLE_LIMIT = 1e7;
14885
+ var THINKING_BINDING_MISMATCH_PATTERN = /bound to a different conversation/i;
14253
14886
  function extractErrorMessage(error) {
14254
14887
  if (!error)
14255
14888
  return "";
@@ -14278,6 +14911,70 @@ function extractErrorMessage(error) {
14278
14911
  }
14279
14912
  return String(error);
14280
14913
  }
14914
+ function extractThinkingBindingMessageId(error) {
14915
+ if (!error || typeof error !== "object")
14916
+ return;
14917
+ const seen = new Set;
14918
+ const queue = [error];
14919
+ while (queue.length > 0) {
14920
+ const current = queue.shift();
14921
+ if (!current || seen.has(current))
14922
+ continue;
14923
+ seen.add(current);
14924
+ const record = current;
14925
+ for (const key of ["message_id", "messageID", "messageId"]) {
14926
+ const value = record[key];
14927
+ if (typeof value === "string" && value.length > 0)
14928
+ return value;
14929
+ }
14930
+ for (const value of Object.values(record)) {
14931
+ if (value && typeof value === "object")
14932
+ queue.push(value);
14933
+ }
14934
+ }
14935
+ return;
14936
+ }
14937
+ function extractExplicitHttpStatus(error) {
14938
+ if (!error || typeof error !== "object")
14939
+ return;
14940
+ const seen = new Set;
14941
+ const queue = [error];
14942
+ while (queue.length > 0) {
14943
+ const current = queue.shift();
14944
+ if (!current || seen.has(current))
14945
+ continue;
14946
+ seen.add(current);
14947
+ const record = current;
14948
+ for (const key of ["status", "statusCode", "status_code"]) {
14949
+ const value = record[key];
14950
+ if (typeof value === "number")
14951
+ return value;
14952
+ }
14953
+ for (const value of Object.values(record)) {
14954
+ if (value && typeof value === "object")
14955
+ queue.push(value);
14956
+ }
14957
+ }
14958
+ return;
14959
+ }
14960
+ function detectThinkingBindingMismatch(error) {
14961
+ const message = extractErrorMessage(error);
14962
+ const explicitStatus = extractExplicitHttpStatus(error);
14963
+ if (explicitStatus !== undefined && explicitStatus !== 400 || !THINKING_BINDING_MISMATCH_PATTERN.test(message)) {
14964
+ return { isBindingMismatch: false };
14965
+ }
14966
+ const messageId = extractThinkingBindingMessageId(error);
14967
+ return {
14968
+ isBindingMismatch: true,
14969
+ matchedPattern: "bound to a different conversation",
14970
+ ...messageId ? { messageId } : {}
14971
+ };
14972
+ }
14973
+ function isFable51ThinkingBindingModel(providerID, modelID) {
14974
+ if (providerID?.toLowerCase() !== "anthropic" || !modelID)
14975
+ return false;
14976
+ return /(?:^|[-_.])fable[-_.]?5[-_.]1(?:$|[-_.])/i.test(modelID);
14977
+ }
14281
14978
  function detectOverflow(error) {
14282
14979
  const message = extractErrorMessage(error);
14283
14980
  if (!message) {
@@ -15456,9 +16153,9 @@ function parseUserMemoryRow(row) {
15456
16153
  }
15457
16154
 
15458
16155
  // src/features/magic-context/mural/storage-mural-cues.ts
15459
- import { createHash as createHash10 } from "node:crypto";
16156
+ import { createHash as createHash11 } from "node:crypto";
15460
16157
  function computeCueContentHash(content) {
15461
- return createHash10("sha256").update(content).digest("hex");
16158
+ return createHash11("sha256").update(content).digest("hex");
15462
16159
  }
15463
16160
  var muralCueColumnCache = new WeakMap;
15464
16161
  var muralCueRejectionColumnCache = new WeakMap;
@@ -15656,13 +16353,13 @@ function invalidateMemory(projectPath, memoryId) {
15656
16353
  }
15657
16354
 
15658
16355
  // src/features/magic-context/memory/normalize-hash.ts
15659
- import { createHash as createHash11 } from "node:crypto";
16356
+ import { createHash as createHash12 } from "node:crypto";
15660
16357
  function normalizeMemoryContent(content) {
15661
16358
  return content.toLowerCase().replace(/\s+/g, " ").trim();
15662
16359
  }
15663
16360
  function computeNormalizedHash(content) {
15664
16361
  const normalized = normalizeMemoryContent(content);
15665
- return createHash11("md5").update(normalized).digest("hex");
16362
+ return createHash12("md5").update(normalized).digest("hex");
15666
16363
  }
15667
16364
 
15668
16365
  // src/features/magic-context/memory/visibility.ts
@@ -16635,7 +17332,7 @@ async function runMemoryMigration(deps) {
16635
17332
  }
16636
17333
 
16637
17334
  // src/features/magic-context/compartment-chunk-embedding.ts
16638
- import { createHash as createHash12 } from "node:crypto";
17335
+ import { createHash as createHash13 } from "node:crypto";
16639
17336
 
16640
17337
  // src/features/magic-context/recursive-text-splitter.ts
16641
17338
  var DEFAULT_SEPARATORS = [`
@@ -16725,6 +17422,14 @@ function recursiveCharacterSplit(text, options) {
16725
17422
  // src/features/magic-context/compartment-chunk-embedding.ts
16726
17423
  var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512;
16727
17424
  var CHUNK_WINDOW_SAFETY_RATIO = 0.9;
17425
+ var MESSAGE_FTS_CHUNK_LOAD_SQL = `SELECT map.message_ordinal AS messageOrdinal, fts.role, fts.content
17426
+ FROM message_fts_rowid_map AS map
17427
+ CROSS JOIN message_history_fts AS fts
17428
+ ON fts.rowid = map.fts_rowid
17429
+ WHERE map.session_id = ?
17430
+ AND map.message_ordinal BETWEEN ? AND ?
17431
+ AND fts.role IN ('user', 'assistant')
17432
+ ORDER BY map.message_ordinal ASC`;
16728
17433
  var loadFtsRowsStatements = new WeakMap;
16729
17434
  var existingHashStatements = new WeakMap;
16730
17435
  var existingHashByProjectStatements = new WeakMap;
@@ -16741,13 +17446,7 @@ var decodedSearchPoolBytes = 0;
16741
17446
  function getLoadFtsRowsStatement(db) {
16742
17447
  let stmt = loadFtsRowsStatements.get(db);
16743
17448
  if (!stmt) {
16744
- stmt = db.prepare(`SELECT message_ordinal AS messageOrdinal, role, content
16745
- FROM message_history_fts
16746
- WHERE session_id = ?
16747
- AND message_ordinal >= ?
16748
- AND message_ordinal <= ?
16749
- AND role IN ('user', 'assistant')
16750
- ORDER BY message_ordinal ASC`);
17449
+ stmt = db.prepare(MESSAGE_FTS_CHUNK_LOAD_SQL);
16751
17450
  loadFtsRowsStatements.set(db, stmt);
16752
17451
  }
16753
17452
  return stmt;
@@ -16920,7 +17619,7 @@ function parseCanonicalLineRange(line) {
16920
17619
  return { start, end };
16921
17620
  }
16922
17621
  function hashChunkText(text) {
16923
- return createHash12("sha256").update(text).digest("hex");
17622
+ return createHash13("sha256").update(text).digest("hex");
16924
17623
  }
16925
17624
  function vectorBlob2(vector) {
16926
17625
  return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
@@ -16935,6 +17634,8 @@ function toFloat32Array2(blob) {
16935
17634
  function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal) {
16936
17635
  if (endOrdinal < startOrdinal)
16937
17636
  return "";
17637
+ if (!messageFtsOrdinalRangeIsMapped(db, sessionId, startOrdinal, endOrdinal))
17638
+ return null;
16938
17639
  const rows = getLoadFtsRowsStatement(db).all(sessionId, startOrdinal, endOrdinal).map((row) => row);
16939
17640
  const lines = [];
16940
17641
  let current = null;
@@ -17209,39 +17910,79 @@ function mapBackfillCandidateRows(rows) {
17209
17910
  title: row.title
17210
17911
  }));
17211
17912
  }
17212
- var sessionBackfillCandidateStatements = new WeakMap;
17213
- function loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelId, limit, excludeIds) {
17214
- if (excludeIds && excludeIds.length > 0) {
17215
- const placeholders3 = excludeIds.map(() => "?").join(", ");
17216
- const stmt2 = db.prepare(`SELECT c.id AS id,
17217
- c.session_id AS sessionId,
17218
- c.start_message AS startMessage,
17219
- c.end_message AS endMessage,
17220
- c.title AS title
17221
- FROM compartments c
17222
- JOIN session_projects sp
17223
- ON sp.session_id = c.session_id
17224
- AND sp.harness = c.harness
17225
- AND sp.project_path = ?
17226
- WHERE c.session_id = ?
17227
- AND c.start_message IS NOT NULL
17228
- AND c.end_message IS NOT NULL
17229
- AND c.id NOT IN (${placeholders3})
17230
- AND NOT EXISTS (
17231
- SELECT 1
17232
- FROM compartment_chunk_embeddings current
17233
- WHERE current.compartment_id = c.id
17234
- AND current.project_path = ?
17235
- AND current.model_id = ?
17236
- )
17237
- ORDER BY c.start_message ASC, c.id ASC
17238
- LIMIT ?`);
17239
- const rows2 = stmt2.all(projectPath, sessionId, ...excludeIds, projectPath, modelId, Math.max(1, limit));
17240
- return mapBackfillCandidateRows(rows2);
17913
+ function classifyChunkCoverageDefect(db, projectPath, modelId, candidate, maxInputTokens) {
17914
+ const mappedText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
17915
+ if (mappedText === null)
17916
+ return "deferred";
17917
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, candidate.id);
17918
+ const windows = chunkCanonicalText(canonicalText, candidate.startMessage, candidate.endMessage, maxInputTokens);
17919
+ const existing = getExistingChunkHashes(db, candidate.id, modelId, projectPath);
17920
+ if (windows.some((window) => !existing.has(window.windowIndex)))
17921
+ return "missing";
17922
+ if (existing.size !== windows.length || windows.some((window) => existing.get(window.windowIndex) !== window.chunkHash)) {
17923
+ return "stale";
17241
17924
  }
17242
- let stmt = sessionBackfillCandidateStatements.get(db);
17243
- if (!stmt) {
17244
- stmt = db.prepare(`SELECT c.id AS id,
17925
+ return null;
17926
+ }
17927
+ function selectHashIncompleteChunkCandidates(db, projectPath, modelId, candidates, limit, maxInputTokens) {
17928
+ const missing = [];
17929
+ const stale = [];
17930
+ for (const candidate of candidates) {
17931
+ const defect = classifyChunkCoverageDefect(db, projectPath, modelId, candidate, maxInputTokens);
17932
+ if (defect === "missing")
17933
+ missing.push(candidate);
17934
+ else if (defect === "stale")
17935
+ stale.push(candidate);
17936
+ }
17937
+ return [...missing, ...stale].slice(0, limit);
17938
+ }
17939
+ var sessionBackfillCandidateStatements = new WeakMap;
17940
+ function loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelId, limit, excludeIds, maxInputTokens = DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS) {
17941
+ const exclusions = excludeIds && excludeIds.length > 0 ? excludeIds : [];
17942
+ const exclusionSql = exclusions.length > 0 ? `AND c.id NOT IN (${exclusions.map(() => "?").join(", ")})` : "";
17943
+ const stmt = exclusions.length > 0 ? db.prepare(`SELECT c.id AS id,
17944
+ c.session_id AS sessionId,
17945
+ c.start_message AS startMessage,
17946
+ c.end_message AS endMessage,
17947
+ c.title AS title
17948
+ FROM compartments c
17949
+ JOIN session_projects sp
17950
+ ON sp.session_id = c.session_id
17951
+ AND sp.harness = c.harness
17952
+ AND sp.project_path = ?
17953
+ WHERE c.session_id = ?
17954
+ AND c.start_message IS NOT NULL
17955
+ AND c.end_message IS NOT NULL
17956
+ ${exclusionSql}
17957
+ ORDER BY c.start_message ASC, c.id ASC`) : (() => {
17958
+ let cached = sessionBackfillCandidateStatements.get(db);
17959
+ if (!cached) {
17960
+ cached = db.prepare(`SELECT c.id AS id,
17961
+ c.session_id AS sessionId,
17962
+ c.start_message AS startMessage,
17963
+ c.end_message AS endMessage,
17964
+ c.title AS title
17965
+ FROM compartments c
17966
+ JOIN session_projects sp
17967
+ ON sp.session_id = c.session_id
17968
+ AND sp.harness = c.harness
17969
+ AND sp.project_path = ?
17970
+ WHERE c.session_id = ?
17971
+ AND c.start_message IS NOT NULL
17972
+ AND c.end_message IS NOT NULL
17973
+ ORDER BY c.start_message ASC, c.id ASC`);
17974
+ sessionBackfillCandidateStatements.set(db, cached);
17975
+ }
17976
+ return cached;
17977
+ })();
17978
+ const rows = stmt.all(projectPath, sessionId, ...exclusions);
17979
+ return selectHashIncompleteChunkCandidates(db, projectPath, modelId, mapBackfillCandidateRows(rows), Math.max(1, limit), maxInputTokens);
17980
+ }
17981
+ function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId, maxInputTokens = DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS) {
17982
+ return loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelId, Number.MAX_SAFE_INTEGER, undefined, maxInputTokens).length;
17983
+ }
17984
+ function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelId, maxInputTokens = DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS) {
17985
+ const rows = db.prepare(`SELECT c.id AS id,
17245
17986
  c.session_id AS sessionId,
17246
17987
  c.start_message AS startMessage,
17247
17988
  c.end_message AS endMessage,
@@ -17254,64 +17995,19 @@ function loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelI
17254
17995
  WHERE c.session_id = ?
17255
17996
  AND c.start_message IS NOT NULL
17256
17997
  AND c.end_message IS NOT NULL
17257
- AND NOT EXISTS (
17258
- SELECT 1
17259
- FROM compartment_chunk_embeddings current
17260
- WHERE current.compartment_id = c.id
17261
- AND current.project_path = ?
17262
- AND current.model_id = ?
17263
- )
17264
- ORDER BY c.start_message ASC, c.id ASC
17265
- LIMIT ?`);
17266
- sessionBackfillCandidateStatements.set(db, stmt);
17998
+ ORDER BY c.start_message ASC, c.id ASC`).all(projectPath, sessionId);
17999
+ const candidates = mapBackfillCandidateRows(rows);
18000
+ let embedded = 0;
18001
+ for (const candidate of candidates) {
18002
+ if (classifyChunkCoverageDefect(db, projectPath, modelId, candidate, maxInputTokens) === null) {
18003
+ embedded += 1;
18004
+ }
17267
18005
  }
17268
- const rows = stmt.all(projectPath, sessionId, projectPath, modelId, Math.max(1, limit));
17269
- return mapBackfillCandidateRows(rows);
17270
- }
17271
- function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId) {
17272
- const row = db.prepare(`SELECT COUNT(*) AS n
17273
- FROM compartments c
17274
- JOIN session_projects sp
17275
- ON sp.session_id = c.session_id
17276
- AND sp.harness = c.harness
17277
- AND sp.project_path = ?
17278
- WHERE c.session_id = ?
17279
- AND c.start_message IS NOT NULL
17280
- AND c.end_message IS NOT NULL
17281
- AND NOT EXISTS (
17282
- SELECT 1
17283
- FROM compartment_chunk_embeddings current
17284
- WHERE current.compartment_id = c.id
17285
- AND current.project_path = ?
17286
- AND current.model_id = ?
17287
- )`).get(projectPath, sessionId, projectPath, modelId);
17288
- return typeof row?.n === "number" ? row.n : 0;
17289
- }
17290
- function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelId) {
17291
- const row = db.prepare(`SELECT
17292
- COUNT(*) AS total,
17293
- SUM(CASE WHEN EXISTS (
17294
- SELECT 1 FROM compartment_chunk_embeddings e
17295
- WHERE e.compartment_id = c.id
17296
- AND e.project_path = ?
17297
- AND e.model_id = ?
17298
- ) THEN 1 ELSE 0 END) AS embedded
17299
- FROM compartments c
17300
- JOIN session_projects sp
17301
- ON sp.session_id = c.session_id
17302
- AND sp.harness = c.harness
17303
- AND sp.project_path = ?
17304
- WHERE c.session_id = ?
17305
- AND c.start_message IS NOT NULL
17306
- AND c.end_message IS NOT NULL`).get(projectPath, modelId, projectPath, sessionId);
17307
- return {
17308
- total: typeof row?.total === "number" ? row.total : 0,
17309
- embedded: typeof row?.embedded === "number" ? row.embedded : 0
17310
- };
18006
+ return { embedded, total: candidates.length };
17311
18007
  }
17312
18008
 
17313
18009
  // src/features/magic-context/project-embedding-registry.ts
17314
- import { createHash as createHash14, randomUUID as randomUUID2 } from "node:crypto";
18010
+ import { createHash as createHash15, randomUUID as randomUUID2 } from "node:crypto";
17315
18011
 
17316
18012
  // src/config/schema/magic-context.ts
17317
18013
  import { homedir as homedir4 } from "node:os";
@@ -32012,6 +32708,7 @@ var BaseEmbeddingConfigSchema = exports_external.object({
32012
32708
  query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
32013
32709
  truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
32014
32710
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted."),
32711
+ local_runtime: exports_external.enum(["auto", "native", "wasm"]).default("auto").describe("Local provider only: ONNX runtime selection. 'auto' uses native under Node and uses WASM under Bun versions before 1.4.0, where Bun's NAPI teardown race can panic on quit; native is restored automatically on Bun 1.4.0+. Set 'native' only to prefer speed while accepting that pre-1.4.0 Bun crash risk, or 'wasm' to avoid loading the native addon."),
32015
32712
  local_dtype: exports_external.enum([
32016
32713
  "auto",
32017
32714
  "fp32",
@@ -32068,6 +32765,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
32068
32765
  return {
32069
32766
  provider: "local",
32070
32767
  model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
32768
+ local_runtime: data.local_runtime,
32071
32769
  ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {},
32072
32770
  ...data.local_dtype ? { local_dtype: data.local_dtype } : {}
32073
32771
  };
@@ -32148,7 +32846,8 @@ var MagicContextConfigSchema = exports_external.object({
32148
32846
  }).default({ enforce_private_permissions: true }).describe("Storage permission policy. The default keeps session content and memories owner-private. Disabling enforcement is for trusted shared-group storage managed externally; every group member able to read the storage can read all stored session content and memories."),
32149
32847
  embedding: EmbeddingConfigSchema.default({
32150
32848
  provider: "local",
32151
- model: DEFAULT_LOCAL_EMBEDDING_MODEL
32849
+ model: DEFAULT_LOCAL_EMBEDDING_MODEL,
32850
+ local_runtime: "auto"
32152
32851
  }).describe("Embedding provider configuration"),
32153
32852
  subc: exports_external.object({
32154
32853
  connection_file: exports_external.string().trim().min(1).transform(expandConfigPath).describe("Path to the owner-only subc connection file.")
@@ -32519,6 +33218,82 @@ function releaseGitSweepLease(db, projectPath, holderId) {
32519
33218
  }
32520
33219
 
32521
33220
  // src/features/magic-context/memory/embedding-failure.ts
33221
+ function errorMessage(error51) {
33222
+ return error51 instanceof Error ? error51.message : String(error51 ?? "unknown error");
33223
+ }
33224
+ function nestedMessages(error51) {
33225
+ const messages = [errorMessage(error51)];
33226
+ if (error51 && typeof error51 === "object" && "cause" in error51) {
33227
+ const cause = error51.cause;
33228
+ if (cause !== undefined)
33229
+ messages.push(...nestedMessages(cause));
33230
+ }
33231
+ return messages;
33232
+ }
33233
+ function safeErrorDetail(message) {
33234
+ return message.replace(/https?:\/\/[^\s"']+/gi, "<remote URL>").replace(/\/(?:Users|home)\/[^/\s]+/g, "~").replace(/\s+/g, " ").trim().slice(0, 240);
33235
+ }
33236
+ function hasAny(messages, patterns) {
33237
+ return messages.some((message) => {
33238
+ const lower = message.toLowerCase();
33239
+ return patterns.some((pattern) => lower.includes(pattern));
33240
+ });
33241
+ }
33242
+ function classifyLocalEmbeddingFailure(error51, context = {}) {
33243
+ const primaryMessages = nestedMessages(error51);
33244
+ const nativeMessages = context.nativeError === undefined ? [] : nestedMessages(context.nativeError);
33245
+ if (hasAny(primaryMessages, [
33246
+ "mc_embedding_fs_unavailable",
33247
+ "file system cache is not available"
33248
+ ]) || context.usesWasm && hasAny(primaryMessages, ["unable to get model file path or buffer"])) {
33249
+ return {
33250
+ class: "local_fs_unavailable",
33251
+ reason: "the WASM model cache cannot access the Node filesystem",
33252
+ retryable: false
33253
+ };
33254
+ }
33255
+ if (hasAny(primaryMessages, [
33256
+ "failed to fetch",
33257
+ "fetch failed",
33258
+ "network error",
33259
+ "enotfound",
33260
+ "econnreset",
33261
+ "econnrefused",
33262
+ "certificate",
33263
+ "unable to load file",
33264
+ "unauthorized access to file",
33265
+ "forbidden access to file",
33266
+ "not found at"
33267
+ ]) || primaryMessages.some((message) => /\bHTTP\s+[45]\d\d\b/i.test(message))) {
33268
+ return {
33269
+ class: "local_download_failure",
33270
+ reason: `the embedding model download failed: ${safeErrorDetail(primaryMessages[0])}`,
33271
+ retryable: true
33272
+ };
33273
+ }
33274
+ const bindingMessages = [...primaryMessages, ...nativeMessages];
33275
+ if (hasAny(bindingMessages, [
33276
+ "onnxruntime_binding.node",
33277
+ "cannot find package 'onnxruntime-node'",
33278
+ 'cannot find package "onnxruntime-node"',
33279
+ "cannot find module 'onnxruntime-node'",
33280
+ 'cannot find module "onnxruntime-node"',
33281
+ "could not resolve: onnxruntime-node"
33282
+ ])) {
33283
+ const platform = context.platform ?? process.platform;
33284
+ const arch = context.arch ?? process.arch;
33285
+ return {
33286
+ class: "local_binding_missing",
33287
+ reason: platform === "darwin" && arch === "x64" ? "onnxruntime-node has no darwin/x64 native binding and the WASM fallback could not complete" : `onnxruntime-node has no usable native binding for ${platform}/${arch} and the WASM fallback could not complete`,
33288
+ retryable: false
33289
+ };
33290
+ }
33291
+ return {
33292
+ class: "local_runtime_error",
33293
+ reason: `the local embedding runtime failed: ${safeErrorDetail(primaryMessages[0])}`,
33294
+ retryable: false
33295
+ };
33296
+ }
32522
33297
  function dominantEmbeddingFailure(failures) {
32523
33298
  const counts = new Map;
32524
33299
  for (const failure of failures) {
@@ -32538,7 +33313,7 @@ function dominantEmbeddingFailure(failures) {
32538
33313
  }
32539
33314
 
32540
33315
  // src/features/magic-context/memory/embedding-synapse.ts
32541
- import { createHash as createHash13 } from "node:crypto";
33316
+ import { createHash as createHash14 } from "node:crypto";
32542
33317
 
32543
33318
  // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
32544
33319
  import { promises as fs2 } from "node:fs";
@@ -33890,21 +34665,28 @@ var SYNAPSE_DEFAULT_MODEL = "gte-modernbert-base-f16";
33890
34665
  var SYNAPSE_MAX_INPUT_TOKENS = 8192;
33891
34666
  var SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS = 3000;
33892
34667
  var SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS = 120000;
34668
+ var SYNAPSE_CERTIFICATION_REFUSAL_REASONS = new Set([
34669
+ "not_certified",
34670
+ "probe_required",
34671
+ "migration_required"
34672
+ ]);
33893
34673
 
33894
34674
  class SynapseEmbeddingError extends Error {
33895
34675
  code;
33896
34676
  retryAfterMs;
33897
34677
  permanent;
34678
+ refusalReason;
33898
34679
  constructor(code, message, options) {
33899
34680
  super(message, options?.cause === undefined ? undefined : { cause: options.cause });
33900
34681
  this.name = "SynapseEmbeddingError";
33901
34682
  this.code = code;
33902
34683
  this.permanent = options?.permanent ?? isPermanentSynapseCode(code);
33903
34684
  this.retryAfterMs = options?.retryAfterMs ?? (this.permanent ? undefined : 100);
34685
+ this.refusalReason = options?.refusalReason;
33904
34686
  }
33905
34687
  }
33906
34688
  function isPermanentSynapseCode(code) {
33907
- return code === "artifact_invalid" || code === "substitution_rejected" || code === "not_certified" || code === "probe_required" || code === "idempotency_conflict" || code === "schema_violation";
34689
+ return code === "artifact_invalid" || code === "substitution_rejected" || code === "not_certified" || code === "probe_required" || code === "idempotency_conflict" || code === "schema_violation" || code === "certification_refused" || code === "needs_reauth";
33908
34690
  }
33909
34691
  function asRecord(value) {
33910
34692
  return value !== null && typeof value === "object" ? value : null;
@@ -33930,11 +34712,21 @@ function readErrorCode(value) {
33930
34712
  }
33931
34713
  return;
33932
34714
  }
34715
+ function readCertificationRefusalReason(value) {
34716
+ if (!(value instanceof SubcCallError))
34717
+ return;
34718
+ const detail = value.detail;
34719
+ if (typeof detail === "string")
34720
+ return detail;
34721
+ const record2 = asRecord(detail);
34722
+ return typeof record2?.reason === "string" ? record2.reason : undefined;
34723
+ }
33933
34724
  function classifyError(value) {
33934
34725
  if (value instanceof SynapseEmbeddingError)
33935
34726
  return value;
33936
34727
  const code = readErrorCode(value) ?? (value instanceof Error ? value.name : "transport");
33937
34728
  const normalized = code.toLowerCase();
34729
+ const refusalReason = readCertificationRefusalReason(value);
33938
34730
  let mapped = "transport";
33939
34731
  if (normalized.includes("queue_full"))
33940
34732
  mapped = "queue_full";
@@ -33946,12 +34738,16 @@ function classifyError(value) {
33946
34738
  mapped = "artifact_invalid";
33947
34739
  else if (normalized.includes("substitution"))
33948
34740
  mapped = "substitution_rejected";
34741
+ else if (normalized === "certification_refused")
34742
+ mapped = "certification_refused";
33949
34743
  else if (normalized.includes("not_certified"))
33950
34744
  mapped = "not_certified";
33951
34745
  else if (normalized.includes("probe_required"))
33952
34746
  mapped = "probe_required";
33953
34747
  else if (normalized.includes("idempotency_conflict"))
33954
34748
  mapped = "idempotency_conflict";
34749
+ else if (normalized.includes("needs_reauth"))
34750
+ mapped = "needs_reauth";
33955
34751
  else if (normalized.includes("schema"))
33956
34752
  mapped = "schema_violation";
33957
34753
  else if (normalized.includes("module_restarted") || normalized.includes("module restarted"))
@@ -33959,14 +34755,46 @@ function classifyError(value) {
33959
34755
  const message = value instanceof Error ? value.message : String(value);
33960
34756
  return new SynapseEmbeddingError(mapped, message, {
33961
34757
  retryAfterMs: readRetryAfter(value) ?? (isPermanentSynapseCode(mapped) ? undefined : 100),
33962
- cause: value
34758
+ cause: value,
34759
+ refusalReason
33963
34760
  });
33964
34761
  }
34762
+ function embeddingFailureFor(error51) {
34763
+ const typedReason = error51.refusalReason;
34764
+ if (typedReason !== undefined && SYNAPSE_CERTIFICATION_REFUSAL_REASONS.has(typedReason) || error51.code === "not_certified" || error51.code === "probe_required") {
34765
+ return {
34766
+ class: "certification_refusal",
34767
+ reason: `SYNAPSE certification refused embedding: ${typedReason ?? error51.code}`,
34768
+ retryable: false
34769
+ };
34770
+ }
34771
+ if (error51.code === "certification_refused") {
34772
+ return {
34773
+ class: "certification_refusal",
34774
+ reason: `SYNAPSE certification refused embedding: ${typedReason ?? "unknown reason"}`,
34775
+ retryable: false
34776
+ };
34777
+ }
34778
+ if (typedReason === "needs_reauth" || typedReason === "needs_reauth_expired") {
34779
+ return {
34780
+ class: "credential_required",
34781
+ reason: "SYNAPSE requires reauthentication",
34782
+ retryable: false
34783
+ };
34784
+ }
34785
+ if (error51.code === "substitution_rejected") {
34786
+ return { class: "substitution_rejected", reason: error51.message, retryable: false };
34787
+ }
34788
+ if (error51.code === "schema_violation" || error51.code === "artifact_invalid") {
34789
+ return { class: "invalid_envelope", reason: error51.message, retryable: false };
34790
+ }
34791
+ return { class: "transport_error", reason: error51.message, retryable: !error51.permanent };
34792
+ }
33965
34793
  function wait(ms) {
33966
34794
  return new Promise((resolve4) => setTimeout(resolve4, ms));
33967
34795
  }
33968
34796
  function sha256(value) {
33969
- return createHash13("sha256").update(value).digest("hex");
34797
+ return createHash14("sha256").update(value).digest("hex");
33970
34798
  }
33971
34799
  function stableJson(value) {
33972
34800
  if (Array.isArray(value))
@@ -34081,6 +34909,7 @@ class SynapseEmbeddingProvider {
34081
34909
  initialized = false;
34082
34910
  initializing = null;
34083
34911
  permanentFailure = false;
34912
+ lastFailureReason = null;
34084
34913
  batchLimit = 16;
34085
34914
  tokenBudget = null;
34086
34915
  constructor(options) {
@@ -34155,9 +34984,11 @@ class SynapseEmbeddingProvider {
34155
34984
  this.tokenBudget = metadata.recommended_token_budget ?? this.tokenBudget;
34156
34985
  }
34157
34986
  this.initialized = true;
34987
+ this.recordSuccess();
34158
34988
  return true;
34159
34989
  } catch (error51) {
34160
34990
  const classified = classifyError(error51);
34991
+ this.recordFailure(classified);
34161
34992
  if (classified.permanent) {
34162
34993
  this.permanentFailure = true;
34163
34994
  log(`[magic-context] Synapse lane disabled: ${classified.code}: ${classified.message}`);
@@ -34184,6 +35015,7 @@ class SynapseEmbeddingProvider {
34184
35015
  if (!extracted)
34185
35016
  throw new SynapseEmbeddingError("schema_violation", "Synapse query returned no vector");
34186
35017
  this.validateResponse(extracted.metadata, extracted.vector.length);
35018
+ this.recordSuccess();
34187
35019
  return extracted.vector;
34188
35020
  } catch (error51) {
34189
35021
  this.logCallFailure(error51, "embed.query");
@@ -34247,6 +35079,7 @@ class SynapseEmbeddingProvider {
34247
35079
  const vectorArray = Float32Array.from(vector);
34248
35080
  this.validateResponse({ ...batchEnvelope, ...item }, vectorArray.length);
34249
35081
  output.set(id, vectorArray);
35082
+ this.recordSuccess();
34250
35083
  }
34251
35084
  } catch (error51) {
34252
35085
  const classified = classifyError(error51);
@@ -34269,6 +35102,9 @@ class SynapseEmbeddingProvider {
34269
35102
  isLoaded() {
34270
35103
  return this.initialized;
34271
35104
  }
35105
+ getLastFailureReason() {
35106
+ return this.lastFailureReason;
35107
+ }
34272
35108
  requestConstraints(extra) {
34273
35109
  const metadata = this.metadata;
34274
35110
  if (!metadata)
@@ -34386,11 +35222,18 @@ class SynapseEmbeddingProvider {
34386
35222
  }
34387
35223
  logCallFailure(error51, operation) {
34388
35224
  const classified = classifyError(error51);
35225
+ this.recordFailure(classified);
34389
35226
  if (classified.permanent)
34390
35227
  this.permanentFailure = true;
34391
35228
  const suffix = classified.retryAfterMs === undefined ? "" : ` retry_after_ms=${classified.retryAfterMs}`;
34392
35229
  log(`[magic-context] Synapse ${operation} failed: ${classified.code}${suffix}: ${classified.message}`);
34393
35230
  }
35231
+ recordFailure(error51) {
35232
+ this.lastFailureReason = embeddingFailureFor(error51);
35233
+ }
35234
+ recordSuccess() {
35235
+ this.lastFailureReason = null;
35236
+ }
34394
35237
  }
34395
35238
 
34396
35239
  // src/features/magic-context/memory/embedding-identity.ts
@@ -34434,6 +35277,34 @@ import { chmodSync as chmodSync2, mkdirSync as mkdirSync3 } from "node:fs";
34434
35277
  import { open, stat, unlink, writeFile } from "node:fs/promises";
34435
35278
  import { dirname as dirname5, join as join6 } from "node:path";
34436
35279
  import { pathToFileURL as pathToFileURL2 } from "node:url";
35280
+ var BUN_NAPI_TEARDOWN_FIX_VERSION = [1, 4, 0];
35281
+ function currentLocalEmbeddingHost() {
35282
+ const bun = globalThis.Bun;
35283
+ const hasProcess = typeof process !== "undefined";
35284
+ const bunVersion = hasProcess && typeof process.versions?.bun === "string" ? process.versions.bun : undefined;
35285
+ return {
35286
+ isElectron: hasProcess && Boolean(process.versions?.electron),
35287
+ isBun: Boolean(bun) || Boolean(bunVersion),
35288
+ bunVersion,
35289
+ hasNodeFilesystem: hasProcess && (typeof process.versions?.node === "string" || typeof bunVersion === "string")
35290
+ };
35291
+ }
35292
+ function bunHasNapiTeardownFix(version2) {
35293
+ const match = version2?.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/);
35294
+ if (!match || match[4])
35295
+ return false;
35296
+ const parsed = [Number(match[1]), Number(match[2]), Number(match[3])];
35297
+ return parsed.some((part) => !Number.isSafeInteger(part)) ? false : parsed[0] > BUN_NAPI_TEARDOWN_FIX_VERSION[0] || parsed[0] === BUN_NAPI_TEARDOWN_FIX_VERSION[0] && (parsed[1] > BUN_NAPI_TEARDOWN_FIX_VERSION[1] || parsed[1] === BUN_NAPI_TEARDOWN_FIX_VERSION[1] && parsed[2] >= BUN_NAPI_TEARDOWN_FIX_VERSION[2]);
35298
+ }
35299
+ function resolveLocalEmbeddingRuntime(preference = "auto", host = currentLocalEmbeddingHost()) {
35300
+ if (preference === "native" || preference === "wasm")
35301
+ return preference;
35302
+ if (host.isElectron)
35303
+ return "electron";
35304
+ if (host.isBun && !bunHasNapiTeardownFix(host.bunVersion))
35305
+ return "wasm";
35306
+ return "native";
35307
+ }
34437
35308
  var LOCK_POLL_MS = 150;
34438
35309
  var STALE_LOCK_MS = 3 * 60000;
34439
35310
  var MAX_LOCK_WAIT_MS = 5 * 60000;
@@ -34486,23 +35357,29 @@ function startLockHeartbeat(lockPath) {
34486
35357
  return () => clearInterval(timer);
34487
35358
  }
34488
35359
  var localEmbeddingRuntimeMode = "native";
35360
+ var localEmbeddingProcessFailure = null;
34489
35361
  var wasmRuntimeInjected = false;
34490
- var isElectronForRuntime = () => typeof process !== "undefined" && Boolean(process.versions?.electron);
35362
+ var localEmbeddingHostForRuntime = currentLocalEmbeddingHost;
34491
35363
  var importWasmOrtForRuntime = async () => {
34492
- const ortWebSpec = `onnxruntime-${"web"}`;
34493
- return await import(ortWebSpec);
35364
+ const { createRequire: createRequireFn } = await import("node:module");
35365
+ const requireFn = createRequireFn(import.meta.url);
35366
+ const ortEntry = requireFn.resolve("onnxruntime-web");
35367
+ return {
35368
+ module: await import("onnxruntime-web"),
35369
+ entryPath: ortEntry
35370
+ };
34494
35371
  };
34495
35372
  var importTransformersForRuntime = async () => {
34496
- const transformersSpec = "@huggingface/transformers";
34497
- return await import(transformersSpec);
35373
+ return await import("./transformers.node-b1wa0hgx.js");
34498
35374
  };
34499
35375
  var importTransformersWasmFallbackForRuntime = async () => {
34500
- const { createRequire: createRequireFn } = await import("node:module");
34501
- const requireFn = createRequireFn(import.meta.url);
34502
- const nodeEntry = requireFn.resolve("@huggingface/transformers");
34503
- const webEntry = pathToFileURL2(join6(dirname5(nodeEntry), "transformers.web.js")).href;
35376
+ const webEntry = new URL("./transformers-web.js", import.meta.url).href;
34504
35377
  return await import(webEntry);
34505
35378
  };
35379
+ var importTransformersNodeWasmFallbackForRuntime = async () => {
35380
+ const nodeWasmEntry = new URL("./transformers-node-wasm.js", import.meta.url).href;
35381
+ return await import(nodeWasmEntry);
35382
+ };
34506
35383
  var modelCacheDirForRuntime = () => join6(getMagicContextStorageDir(), "models");
34507
35384
  var logForRuntime = log;
34508
35385
  var injectWasmOrtForRuntime = injectWasmOrt;
@@ -34518,17 +35395,9 @@ async function injectWasmOrt() {
34518
35395
  if (wasmRuntimeInjected)
34519
35396
  return true;
34520
35397
  try {
34521
- const ortWeb = await importWasmOrtForRuntime();
34522
- try {
34523
- const { createRequire: createRequireFn } = await import("node:module");
34524
- const requireFn = createRequireFn(import.meta.url);
34525
- const mainEntry = requireFn.resolve("onnxruntime-web");
34526
- const distDir = dirname5(mainEntry);
34527
- if (ortWeb.env?.wasm) {
34528
- ortWeb.env.wasm.wasmPaths = `${pathToFileURL2(distDir).href}/`;
34529
- }
34530
- } catch (pathError) {
34531
- log("[magic-context] could not resolve local onnxruntime-web/dist, falling back to default WASM paths:", pathError instanceof Error ? pathError.message : String(pathError));
35398
+ const { module: ortWeb, entryPath } = await importWasmOrtForRuntime();
35399
+ if (ortWeb.env?.wasm) {
35400
+ ortWeb.env.wasm.wasmPaths = `${pathToFileURL2(dirname5(entryPath)).href}/`;
34532
35401
  }
34533
35402
  globalThis[Symbol.for("onnxruntime")] = ortWeb;
34534
35403
  wasmRuntimeInjected = true;
@@ -34551,27 +35420,61 @@ function likelyMuslHint() {
34551
35420
  function localEmbeddingRuntimeIsDisabled() {
34552
35421
  return localEmbeddingRuntimeMode === "disabled";
34553
35422
  }
35423
+
35424
+ class LocalEmbeddingFallbackError extends Error {
35425
+ nativeError;
35426
+ constructor(nativeError, wasmError) {
35427
+ super("the native local embedding runtime and its WASM fallback both failed", {
35428
+ cause: wasmError
35429
+ });
35430
+ this.name = "LocalEmbeddingFallbackError";
35431
+ this.nativeError = nativeError;
35432
+ }
35433
+ }
35434
+
35435
+ class LocalEmbeddingFsUnavailableError extends Error {
35436
+ code = "MC_EMBEDDING_FS_UNAVAILABLE";
35437
+ constructor() {
35438
+ super("MC_EMBEDDING_FS_UNAVAILABLE: Node WASM bundle has no filesystem cache");
35439
+ this.name = "LocalEmbeddingFsUnavailableError";
35440
+ }
35441
+ }
35442
+ async function importWasmTransformersForHost() {
35443
+ const host = localEmbeddingHostForRuntime();
35444
+ if (host.isElectron) {
35445
+ return importTransformersForRuntime();
35446
+ }
35447
+ return host.hasNodeFilesystem ? importTransformersNodeWasmFallbackForRuntime() : importTransformersWasmFallbackForRuntime();
35448
+ }
34554
35449
  function disableLocalEmbeddingsAfterRuntimeFailure(detail) {
34555
35450
  localEmbeddingRuntimeMode = "disabled";
34556
- logForRuntime(`[magic-context] local embeddings are disabled because both the onnxruntime-node native binding and the onnxruntime-web (WASM) fallback failed to load. Native failure: ${detail}. Run \`npx @cortexkit/magic-context@latest doctor\` for repair guidance (use \`doctor --force\` to reinstall cached plugin packages), or configure an \`openai-compatible\` embedding HTTP endpoint. Existing memories are unaffected.`);
35451
+ logForRuntime(`[magic-context] local embeddings are disabled because both the onnxruntime-node native binding and the onnxruntime-web (WASM) fallback failed to load. Native failure: ${detail}. Run \`npx @cortexkit/magic-context@latest doctor\` for diagnostics; reinstalling repairs missing package files but cannot add a native binding that upstream does not ship. Alternatively, configure an \`openai-compatible\` embedding HTTP endpoint. Existing memories are unaffected.`);
34557
35452
  }
34558
- async function loadTransformersForLocalEmbedding() {
35453
+ async function loadTransformersForLocalEmbedding(runtimePreference) {
34559
35454
  if (localEmbeddingRuntimeMode === "disabled") {
34560
35455
  throw new Error("local embedding runtime is disabled");
34561
35456
  }
35457
+ const resolvedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, localEmbeddingHostForRuntime());
35458
+ if (resolvedRuntime === "wasm") {
35459
+ if (!await ensureWasmOrtInjected()) {
35460
+ disableLocalEmbeddingsAfterRuntimeFailure("the selected WASM runtime is unavailable");
35461
+ throw new Error("onnxruntime-web failed to load");
35462
+ }
35463
+ return { module: await importWasmTransformersForHost(), usesWasm: true };
35464
+ }
34562
35465
  if (localEmbeddingRuntimeMode === "wasm") {
34563
35466
  if (!await ensureWasmOrtInjected()) {
34564
35467
  disableLocalEmbeddingsAfterRuntimeFailure("the previously selected WASM runtime is unavailable");
34565
35468
  throw new Error("onnxruntime-web failed to load");
34566
35469
  }
34567
35470
  try {
34568
- return { module: await importTransformersWasmFallbackForRuntime(), usesWasm: true };
35471
+ return { module: await importWasmTransformersForHost(), usesWasm: true };
34569
35472
  } catch (wasmError) {
34570
35473
  disableLocalEmbeddingsAfterRuntimeFailure("the previously selected WASM runtime failed to load");
34571
35474
  throw wasmError;
34572
35475
  }
34573
35476
  }
34574
- const electron = isElectronForRuntime();
35477
+ const electron = resolvedRuntime === "electron";
34575
35478
  if (electron) {
34576
35479
  const wasInjected = wasmRuntimeInjected;
34577
35480
  if (await ensureWasmOrtInjected()) {
@@ -34593,12 +35496,12 @@ async function loadTransformersForLocalEmbedding() {
34593
35496
  }
34594
35497
  localEmbeddingRuntimeMode = "wasm";
34595
35498
  try {
34596
- const module = await importTransformersWasmFallbackForRuntime();
35499
+ const module = await importWasmTransformersForHost();
34597
35500
  logForRuntime("[magic-context] onnxruntime-node failed to load; using onnxruntime-web (WASM) for local embeddings. WASM inference is slower than native; a remote `openai-compatible` provider may be faster." + likelyMuslHint());
34598
35501
  return { module, usesWasm: true };
34599
35502
  } catch (wasmError) {
34600
35503
  disableLocalEmbeddingsAfterRuntimeFailure(nativeError instanceof Error ? nativeError.message : String(nativeError));
34601
- throw wasmError;
35504
+ throw new LocalEmbeddingFallbackError(nativeError, wasmError);
34602
35505
  }
34603
35506
  }
34604
35507
  }
@@ -34627,6 +35530,8 @@ function isNativeRuntimeMissingError(error51) {
34627
35530
  if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
34628
35531
  return true;
34629
35532
  }
35533
+ if (lower.includes('could not load the "sharp" module'))
35534
+ return true;
34630
35535
  const mentionsNativeRuntime = lower.includes("onnxruntime-node") || lower.includes("onnxruntime_binding");
34631
35536
  if (!mentionsNativeRuntime)
34632
35537
  return false;
@@ -34679,19 +35584,24 @@ class LocalEmbeddingProvider {
34679
35584
  maxInputTokens;
34680
35585
  model;
34681
35586
  dtype;
35587
+ runtimePreference;
34682
35588
  pipeline = null;
34683
35589
  initPromise = null;
35590
+ lastFailureReason = null;
35591
+ usesWasm = false;
34684
35592
  inFlight = 0;
34685
35593
  disposing = false;
34686
35594
  disposePromise = null;
34687
35595
  inFlightWaiters = [];
34688
- constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512, dtype = DEFAULT_LOCAL_DTYPE) {
35596
+ constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512, dtype = DEFAULT_LOCAL_DTYPE, runtimePreference = "auto") {
34689
35597
  this.model = model;
34690
35598
  this.maxInputTokens = maxInputTokens;
34691
35599
  this.dtype = dtype || DEFAULT_LOCAL_DTYPE;
35600
+ this.runtimePreference = runtimePreference;
34692
35601
  this.modelId = getEmbeddingProviderIdentity({
34693
35602
  provider: "local",
34694
35603
  model,
35604
+ local_runtime: runtimePreference,
34695
35605
  ...dtype && dtype !== DEFAULT_LOCAL_DTYPE ? { local_dtype: dtype } : {}
34696
35606
  });
34697
35607
  }
@@ -34703,6 +35613,7 @@ class LocalEmbeddingProvider {
34703
35613
  return true;
34704
35614
  }
34705
35615
  if (localEmbeddingRuntimeMode === "disabled") {
35616
+ this.lastFailureReason = localEmbeddingProcessFailure ?? classifyLocalEmbeddingFailure(new Error("local embedding runtime is disabled"));
34706
35617
  return false;
34707
35618
  }
34708
35619
  if (this.initPromise) {
@@ -34714,12 +35625,17 @@ class LocalEmbeddingProvider {
34714
35625
  if (this.disposing) {
34715
35626
  return;
34716
35627
  }
34717
- const { module: transformersModule, usesWasm } = await loadTransformersForLocalEmbedding();
35628
+ const { module: transformersModule, usesWasm } = await loadTransformersForLocalEmbedding(this.runtimePreference);
35629
+ this.usesWasm = usesWasm;
34718
35630
  const env = transformersModule.env;
34719
35631
  const LogLevel = transformersModule.LogLevel;
34720
35632
  if (LogLevel && "ERROR" in LogLevel) {
34721
35633
  env.logLevel = LogLevel.ERROR;
34722
35634
  }
35635
+ const host = localEmbeddingHostForRuntime();
35636
+ if (usesWasm && host.hasNodeFilesystem && !host.isElectron && (env.useFS !== true || env.useFSCache !== true)) {
35637
+ throw new LocalEmbeddingFsUnavailableError;
35638
+ }
34723
35639
  const modelCacheDir = modelCacheDirForRuntime();
34724
35640
  try {
34725
35641
  if (shouldEnforcePrivateStoragePermissions()) {
@@ -34768,6 +35684,8 @@ class LocalEmbeddingProvider {
34768
35684
  }
34769
35685
  }
34770
35686
  if (this.pipeline) {
35687
+ this.lastFailureReason = null;
35688
+ localEmbeddingProcessFailure = null;
34771
35689
  log(`[magic-context] embedding model loaded: ${this.model}`);
34772
35690
  } else if (this.disposing) {
34773
35691
  return;
@@ -34779,11 +35697,19 @@ class LocalEmbeddingProvider {
34779
35697
  await releaseLock();
34780
35698
  }
34781
35699
  } catch (error51) {
35700
+ const nativeError = error51 instanceof LocalEmbeddingFallbackError ? error51.nativeError : undefined;
35701
+ const failure = classifyLocalEmbeddingFailure(error51, {
35702
+ platform: process.platform,
35703
+ arch: process.arch,
35704
+ usesWasm: this.usesWasm,
35705
+ nativeError
35706
+ });
35707
+ this.lastFailureReason = failure;
35708
+ localEmbeddingProcessFailure = failure;
34782
35709
  if (!localEmbeddingRuntimeIsDisabled() && isNativeRuntimeMissingError(error51)) {
34783
35710
  disableLocalEmbeddingsAfterRuntimeFailure(error51 instanceof Error ? error51.message : String(error51));
34784
- } else if (!localEmbeddingRuntimeIsDisabled()) {
34785
- log("[magic-context] embedding model failed to load:", error51);
34786
35711
  }
35712
+ logForRuntime(`[magic-context] embedding model failed to load (${failure.class}: ${failure.reason}):`, error51);
34787
35713
  this.pipeline = null;
34788
35714
  } finally {
34789
35715
  this.initPromise = null;
@@ -34827,9 +35753,17 @@ class LocalEmbeddingProvider {
34827
35753
  pooling: "mean",
34828
35754
  normalize: true
34829
35755
  }));
34830
- return extractBatchEmbeddings(result, 1)[0] ?? null;
35756
+ const embedding = extractBatchEmbeddings(result, 1)[0] ?? null;
35757
+ if (!embedding) {
35758
+ this.lastFailureReason = classifyLocalEmbeddingFailure(new Error("local embedding pipeline returned no vector"), { usesWasm: this.usesWasm });
35759
+ } else {
35760
+ this.lastFailureReason = null;
35761
+ }
35762
+ return embedding;
34831
35763
  } catch (error51) {
34832
- log("[magic-context] embedding failed:", error51);
35764
+ const failure = classifyLocalEmbeddingFailure(error51, { usesWasm: this.usesWasm });
35765
+ this.lastFailureReason = failure;
35766
+ logForRuntime(`[magic-context] embedding failed (${failure.class}: ${failure.reason}):`, error51);
34833
35767
  return null;
34834
35768
  } finally {
34835
35769
  this.finishInFlight();
@@ -34858,9 +35792,17 @@ class LocalEmbeddingProvider {
34858
35792
  pooling: "mean",
34859
35793
  normalize: true
34860
35794
  }));
34861
- return extractBatchEmbeddings(result, texts.length);
35795
+ const embeddings = extractBatchEmbeddings(result, texts.length);
35796
+ if (embeddings.every((embedding) => embedding === null)) {
35797
+ this.lastFailureReason = classifyLocalEmbeddingFailure(new Error("local embedding pipeline returned no vectors"), { usesWasm: this.usesWasm });
35798
+ } else {
35799
+ this.lastFailureReason = null;
35800
+ }
35801
+ return embeddings;
34862
35802
  } catch (error51) {
34863
- log("[magic-context] embedding batch failed:", error51);
35803
+ const failure = classifyLocalEmbeddingFailure(error51, { usesWasm: this.usesWasm });
35804
+ this.lastFailureReason = failure;
35805
+ logForRuntime(`[magic-context] embedding batch failed (${failure.class}: ${failure.reason}):`, error51);
34864
35806
  return Array.from({ length: texts.length }, () => null);
34865
35807
  } finally {
34866
35808
  this.finishInFlight();
@@ -34893,6 +35835,9 @@ class LocalEmbeddingProvider {
34893
35835
  isLoaded() {
34894
35836
  return this.pipeline !== null;
34895
35837
  }
35838
+ getLastFailureReason() {
35839
+ return this.lastFailureReason;
35840
+ }
34896
35841
  }
34897
35842
 
34898
35843
  // src/features/magic-context/memory/embedding-ssrf.ts
@@ -35452,6 +36397,7 @@ function resolveEmbeddingConfig(config2) {
35452
36397
  return {
35453
36398
  provider: "local",
35454
36399
  model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
36400
+ local_runtime: config2?.local_runtime ?? "auto",
35455
36401
  ...config2?.max_input_tokens ? {
35456
36402
  max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
35457
36403
  } : {},
@@ -35517,7 +36463,7 @@ function createProvider(config2, context) {
35517
36463
  });
35518
36464
  }
35519
36465
  if (config2.provider === "local") {
35520
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype);
36466
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype, config2.local_runtime);
35521
36467
  }
35522
36468
  if (config2.provider === "synapse") {
35523
36469
  const synapse = config2;
@@ -35546,10 +36492,10 @@ function stableStringify2(value) {
35546
36492
  return JSON.stringify(value);
35547
36493
  }
35548
36494
  function sha256Prefix(value, length = 16) {
35549
- return createHash14("sha256").update(value).digest("hex").slice(0, length);
36495
+ return createHash15("sha256").update(value).digest("hex").slice(0, length);
35550
36496
  }
35551
36497
  function contentSha256(value) {
35552
- return createHash14("sha256").update(value).digest("hex");
36498
+ return createHash15("sha256").update(value).digest("hex");
35553
36499
  }
35554
36500
  function getRuntimeFingerprint(config2) {
35555
36501
  if (config2.provider === "off") {
@@ -36004,15 +36950,25 @@ function shadowBackfillMissingBase(scope, primaryModelId, shadowModelId, project
36004
36950
  };
36005
36951
  }
36006
36952
  return {
36007
- sql: `SELECT DISTINCT cp.compartment_id AS id
36953
+ sql: `SELECT cp.compartment_id AS id,
36954
+ MIN(CASE WHEN NOT EXISTS (
36955
+ SELECT 1 FROM compartment_chunk_embeddings same_key
36956
+ WHERE same_key.compartment_id = cp.compartment_id
36957
+ AND same_key.window_index = cp.window_index
36958
+ AND same_key.model_id = ?
36959
+ ) THEN 0 ELSE 1 END) AS defect_order
36008
36960
  FROM compartment_chunk_embeddings cp
36009
36961
  WHERE cp.project_path = ? AND cp.model_id = ?
36010
36962
  AND NOT EXISTS (
36011
- SELECT 1 FROM compartment_chunk_embeddings cs
36012
- WHERE cs.compartment_id = cp.compartment_id AND cs.model_id = ?
36013
- )`,
36014
- params: [projectIdentity, primaryModelId, shadowModelId],
36015
- orderBy: " ORDER BY cp.compartment_id"
36963
+ SELECT 1 FROM compartment_chunk_embeddings current
36964
+ WHERE current.compartment_id = cp.compartment_id
36965
+ AND current.window_index = cp.window_index
36966
+ AND current.chunk_hash = cp.chunk_hash
36967
+ AND current.model_id = ?
36968
+ )
36969
+ GROUP BY cp.compartment_id`,
36970
+ params: [shadowModelId, projectIdentity, primaryModelId, shadowModelId],
36971
+ orderBy: " ORDER BY defect_order ASC, cp.compartment_id ASC"
36016
36972
  };
36017
36973
  }
36018
36974
  function shadowBackfillMissingIds(db, projectIdentity, scope, primaryModelId, shadowModelId, limit) {
@@ -36178,13 +37134,17 @@ async function processShadowQueueItem(item) {
36178
37134
  const placeholders3 = boundedIds.map(() => "?").join(",");
36179
37135
  const candidates = db.prepare(`SELECT id, session_id, start_message, end_message
36180
37136
  FROM compartments WHERE id IN (${placeholders3})`).all(...boundedIds.map((id) => Number(id)));
36181
- const prepared = candidates.flatMap((candidate) => {
36182
- const text = buildCanonicalChunkTextFromFts(db, candidate.session_id, candidate.start_message, candidate.end_message) || buildCompartmentSummaryFallbackText(db, candidate.id);
36183
- if (!text)
36184
- return [];
36185
- const windows = chunkCanonicalText(text, candidate.start_message, candidate.end_message, SYNAPSE_MAX_INPUT_TOKENS);
36186
- return windows.length > 0 ? [{ candidate, windows }] : [];
36187
- });
37137
+ const prepared = [];
37138
+ for (const candidate of candidates) {
37139
+ const mappedText = buildCanonicalChunkTextFromFts(db, candidate.session_id, candidate.start_message, candidate.end_message);
37140
+ if (mappedText !== null) {
37141
+ const text = mappedText || buildCompartmentSummaryFallbackText(db, candidate.id);
37142
+ const windows = chunkCanonicalText(text, candidate.start_message, candidate.end_message, SYNAPSE_MAX_INPUT_TOKENS);
37143
+ if (windows.length > 0)
37144
+ prepared.push({ candidate, windows });
37145
+ }
37146
+ await new Promise((resolve4) => setTimeout(resolve4, 0));
37147
+ }
36188
37148
  const items = prepared.flatMap((item2) => item2.windows.map((window) => ({
36189
37149
  id: `chunk:${item2.candidate.id}:${window.windowIndex}`,
36190
37150
  text: window.text,
@@ -36529,7 +37489,11 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
36529
37489
  const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
36530
37490
  const prepared = [];
36531
37491
  for (const candidate of candidates) {
36532
- const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage) || buildCompartmentSummaryFallbackText(db, candidate.id);
37492
+ await new Promise((resolve4) => setTimeout(resolve4, 0));
37493
+ const mappedText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
37494
+ if (mappedText === null)
37495
+ continue;
37496
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, candidate.id);
36533
37497
  if (canonicalText.length === 0) {
36534
37498
  noWork.push(candidate.id);
36535
37499
  continue;
@@ -36628,7 +37592,8 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
36628
37592
  return { status: "disabled", embedded: 0, total: 0 };
36629
37593
  }
36630
37594
  recordSessionProjectIdentity(db, sessionId, projectIdentity);
36631
- const total = countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot2.chunkModelId);
37595
+ const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
37596
+ const total = countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot2.chunkModelId, maxInputTokens);
36632
37597
  if (total === 0)
36633
37598
  return { status: "nothing", embedded: 0, total: 0 };
36634
37599
  const holderId = `session-embed-${randomUUID2()}`;
@@ -36666,7 +37631,7 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
36666
37631
  aborted2 = true;
36667
37632
  break;
36668
37633
  }
36669
- const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot2.chunkModelId, batchSize, [...skipIds, ...failedIds]);
37634
+ const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot2.chunkModelId, batchSize, [...skipIds, ...failedIds], maxInputTokens);
36670
37635
  if (candidates.length === 0)
36671
37636
  break;
36672
37637
  const {
@@ -36711,7 +37676,7 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
36711
37676
  if (aborted2)
36712
37677
  return { status: "aborted", embedded, total, failed: failedIds.length };
36713
37678
  if (providerDown || failedIds.length > 0) {
36714
- const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot2.chunkModelId) - skipIds.length);
37679
+ const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot2.chunkModelId, maxInputTokens) - skipIds.length);
36715
37680
  if (remaining > 0) {
36716
37681
  return {
36717
37682
  status: "stalled",
@@ -36737,7 +37702,7 @@ function getEmbeddingCoverageStatus(db, projectIdentity, sessionId) {
36737
37702
  commits: { embedded: 0, total: 0, gitEnabled: false }
36738
37703
  };
36739
37704
  }
36740
- const session = countSessionCompartmentEmbedCoverage(db, projectIdentity, sessionId, snapshot2.chunkModelId);
37705
+ const session = countSessionCompartmentEmbedCoverage(db, projectIdentity, sessionId, snapshot2.chunkModelId, getProjectEmbeddingMaxInputTokens(projectIdentity));
36741
37706
  const memories = getMemoryEmbedCoverage(db, projectIdentity, snapshot2.modelId);
36742
37707
  const gitEnabled = snapshot2.gitCommitEnabled;
36743
37708
  const commits = gitEnabled ? {
@@ -36763,7 +37728,10 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
36763
37728
  for (const compartment of compartments) {
36764
37729
  try {
36765
37730
  const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
36766
- const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage) || buildCompartmentSummaryFallbackText(db, compartment.id);
37731
+ const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
37732
+ if (mappedText === null)
37733
+ continue;
37734
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, compartment.id);
36767
37735
  if (canonicalText.length === 0)
36768
37736
  continue;
36769
37737
  const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
@@ -36803,6 +37771,8 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
36803
37771
  }
36804
37772
  } catch (error51) {
36805
37773
  sessionLog(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error51);
37774
+ } finally {
37775
+ await new Promise((resolve4) => setTimeout(resolve4, 0));
36806
37776
  }
36807
37777
  }
36808
37778
  }
@@ -36876,7 +37846,8 @@ function cosineSimilarity(a, b) {
36876
37846
  // src/features/magic-context/memory/embedding.ts
36877
37847
  var DEFAULT_EMBEDDING_CONFIG = {
36878
37848
  provider: "local",
36879
- model: DEFAULT_LOCAL_EMBEDDING_MODEL
37849
+ model: DEFAULT_LOCAL_EMBEDDING_MODEL,
37850
+ local_runtime: "auto"
36880
37851
  };
36881
37852
  var embeddingConfig = DEFAULT_EMBEDDING_CONFIG;
36882
37853
  var provider = null;
@@ -36896,7 +37867,7 @@ function createProvider2(config2) {
36896
37867
  });
36897
37868
  }
36898
37869
  if (config2.provider === "local") {
36899
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype);
37870
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype, config2.local_runtime);
36900
37871
  }
36901
37872
  if (config2.provider === "synapse") {
36902
37873
  const synapse = config2;
@@ -37413,7 +38384,7 @@ function tallyFactsByCategory(facts) {
37413
38384
  import { join as join8 } from "node:path";
37414
38385
 
37415
38386
  // src/features/magic-context/compaction-marker.ts
37416
- import { createHash as createHash15 } from "node:crypto";
38387
+ import { createHash as createHash16 } from "node:crypto";
37417
38388
  import { existsSync as existsSync8 } from "node:fs";
37418
38389
  import { join as join7 } from "node:path";
37419
38390
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@@ -37421,7 +38392,7 @@ var ID_PREFIX_HEX_LENGTH = 12;
37421
38392
  var ID_SUFFIX_LENGTH = 14;
37422
38393
  var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
37423
38394
  function deterministicBase62(seed, length) {
37424
- let value = BigInt(`0x${createHash15("sha256").update(seed).digest("hex")}`);
38395
+ let value = BigInt(`0x${createHash16("sha256").update(seed).digest("hex")}`);
37425
38396
  const chars = Array(length);
37426
38397
  for (let index = length - 1;index >= 0; index -= 1) {
37427
38398
  chars[index] = BASE62_CHARS[Number(value % 62n)];
@@ -39800,7 +40771,7 @@ function sanitizeDumpName(value) {
39800
40771
  import { Buffer as Buffer2 } from "node:buffer";
39801
40772
 
39802
40773
  // src/features/magic-context/mural/render-trigger.ts
39803
- import { createHash as createHash16 } from "node:crypto";
40774
+ import { createHash as createHash17 } from "node:crypto";
39804
40775
 
39805
40776
  // src/features/magic-context/mural/mural-selection.ts
39806
40777
  var DEFAULT_MURAL_MEMORY_BUDGET = 8000;
@@ -40426,7 +41397,7 @@ function ensureMuralRendered(db, projectIdentity, budgetTokens = DEFAULT_MURAL_M
40426
41397
  return { hasMural: false, rerendered: false };
40427
41398
  }
40428
41399
  const rendered = renderMural(entries);
40429
- const textHash = createHash16("sha256").update(rendered.sha256Input).digest("hex");
41400
+ const textHash = createHash17("sha256").update(rendered.sha256Input).digest("hex");
40430
41401
  const existing = getMural(db, projectIdentity);
40431
41402
  if (existing && existing.contentHash === textHash && existing.width === rendered.width && existing.height === rendered.height) {
40432
41403
  return {
@@ -46599,7 +47570,7 @@ async function executeContextRecomp(deps, options = {}) {
46599
47570
  }
46600
47571
 
46601
47572
  // src/hooks/magic-context/lkg-slot.ts
46602
- import { createHash as createHash17 } from "node:crypto";
47573
+ import { createHash as createHash18 } from "node:crypto";
46603
47574
  var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
46604
47575
  var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
46605
47576
  var LKG_METADATA_BYTES = 256;
@@ -46665,7 +47636,7 @@ function lkgContentFields(value) {
46665
47636
  }
46666
47637
  }
46667
47638
  function lkgContentDigestFromFields(fields) {
46668
- const hash2 = createHash17("sha256");
47639
+ const hash2 = createHash18("sha256");
46669
47640
  for (const field of fields) {
46670
47641
  const value = typeof field === "symbol" ? field.description ?? "" : String(field);
46671
47642
  hash2.update(`${typeof field}:${value.length}:`).update(value).update("\x00");
@@ -47089,4 +48060,4 @@ async function runUpgradeMemoryMigration(ctx, sessionId, migrationDirectory) {
47089
48060
  }
47090
48061
  }
47091
48062
 
47092
- export { withContentLanguageDirective, buildPrimaryLanguageDirective, cortexKitUserConfigBasePath, cortexKitProjectConfigBasePath, resolveLegacyConfigSources, resolveLegacyConfigSourcesForHarness, migrateMagicContextConfigLocations, exports_external, DEFAULT_PROTECTED_TAGS, parseCron, nextOccurrence, nextDueAtMs, promptSurfaceConfigIdentity, resolvePromptSurface, resolveModelConfigOrDefault, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, DEFAULT_LOCAL_EMBEDDING_MODEL, PER_HARNESS_MIGRATION_INVENTORY, ConfigProfilesSchema, MagicContextConfigSchema, getOpenCodeDbPath, removeMcOwnedCompactionMarkers, isFailClosedBlockingError, shouldBypassFailClosedBlock, resolveAgentNameFromMessages, createFailClosedController, recordHookInitFailure, clearHookInitFailure, getLastHookInitFailure, ProjectIdentityError, resolveProjectIdentityStrict, takeDubiousOwnershipProjectIdentityWarning, resolveProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, isLinkedGitWorktree, recordSessionProjectIdentity, beginBootQuietPeriod, bootQuietRemainingMs, scheduleAfterBootQuiet, rpcPortDir, rpcPortFilePath, isPidAlive, parseRpcPortFile, observeAuthorityRouting, registerModuleNoteEvaluationBridge, getModuleNoteEvaluationBridge, getContextStoreUuid, ensureContextStoreUuid, getAuthorityManagedMarker, reconcileAuthorityProject, checksumAuthoritySeedRows, prepareAuthority, drainAuthority, getMirrorCursor, applyMirroredNoteCompileFields, applyMirrorPage, pullMemoryMirrorOnce, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, computeWorkspaceEpochFingerprint, textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, getCurrentToolSetHash, recordToolDefinition, getMeasuredToolDefinitionTokens, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getDatabasePath, getPersistedSchemaVersion, setSqlitePragmaConfig, runSqliteOptimize, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, clearRecompStaging, isRawCompactionSummaryInfo, extractInMemoryMessageViews, buildInMemoryTailRawMessages, isRecord, estimateTrueRawMessageTokens, invalidateTrueRawTokenCache, stripPersistedAssistantText, byteSize, stripTagPrefix, prependTag, isThinkingPart, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, isEditTool, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, setRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, primeInMemoryTailRawMessageCache, readRawSessionMessageOrdinalPage, getRawSessionStoredMessageCount, readRawSessionMessagePartsById, readRawSessionMessageOrdinalById, readRawSessionMessageById, readSessionChunk, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, deleteIndexedMessage, clearIndexedMessages, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, recordEmbeddingMeasurement, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationIdForProjects, MAX_EXECUTE_THRESHOLD, escalationBands, isEmergencyRecoveryArmed, isProviderOverflowReconfirmed, getEmergencyRecoveryArmedAt, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, getPersistedReasoningWatermark, setPersistedReasoningWatermark, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, getNoteNudgeAnchors, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, removeNoteNudgeAnchorByMessageId, removeAutoSearchHintDecisionByMessageId, getPersistedTodoPermissionDenied, setPersistedTodoPermissionDenied, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, setNoteLastReadAt, getHistorianFailureState, clearHistorianFailureState, getOverflowState, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, setPersistedCompactionMarkerState, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, removeStrippedPlaceholderId, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getTrailingBlankDecisions, addTrailingBlankDecisions, demoteTrailingBlankKeepDecisions, getStaleReduceStrippedIds, addStaleReduceStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, peekDeferredExecutePending, setDeferredExecutePendingIfAbsent, clearDeferredExecutePendingIfMatches, getSessionsWithPendingMarker, setSessionWorkMetrics, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNote, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectMemoryEpoch, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, CTX_REDUCE_KEEP, estimateImageTokensFromDataUrl, normalizeTodoStateJson, buildSyntheticTodoPart, computeSyntheticCallId, isSyntheticTodoPart, countRealUserMessages, tailHygieneStructuralSignature, sameTailHygieneStructuralSignature, refreshTailHygieneBaseline, effectiveTailHygiene, assertTailHygieneContentUnchanged, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, toolOutputTokens, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, estimateEmergencyDropReclaimTokens, planEmergencyDrop, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, updateTagDropMode, updateCavemanDepth, updateTagMessageId, deleteTagsByMessageId, getMaxTagNumberBySession, getTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getTailHygieneTags, getDroppedTagsBySession, getTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, createChildSessionWithFence, detectOverflow, resolveFallbackChain, modelBodyField, toModelEntry, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, extractLatestAssistantText, hasLengthCappedOutput, setKeepSubagents, shouldKeepSubagents, recordChildInvocation, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, Priority, AdmissionClass, StaleRouteHandleError, SocketClosedError, SocketTimeoutError, SubcClient, isConsumerReconnectTransient, connectionFileExists, getCompartmentEvents, loadCompartmentChunkEmbeddingsForSearch, cosineSimilarity, SYNAPSE_DEFAULT_MODEL, SynapseEmbeddingProvider, computeNormalizedHash, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitTimeMs, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, saveEmbeddingIfHashMatches, getProjectEmbeddings, peekProjectEmbeddings, invalidateProject, invalidateMemory, markProjectLoadUntrusted, contentSha256, sweepStaleEmbeddingIdentitiesForProject, registerProjectEmbedding, registerProjectShadowEmbedding, getShadowEmbeddingMeasurementCohort, getPrimaryEmbeddingMeasurementCohort, embedShadowTextForProject, enqueueShadowEmbeddingItems, registerProjectInObservationMode, getProjectEmbeddingSnapshot, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, isEmbeddingEnabled, embedText, ensureMemoryEmbeddings, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, recordMuralCueRejection, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, buildWorkspaceMemorySqlFilter, getMemoriesByProjects, getMaxMemoryIdForProjects, readNewMemoriesForM1Union, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, setMemoryClassification, supersededMemory, mergeMemoryStats, archiveMemory, getMemoryCountsByStatus, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getMural, BoundedSessionMap, registerLkgPersistence, LKG_SNAPSHOT_ARRAY, LKG_SNAPSHOT_OBJECT, LKG_SNAPSHOT_KEY, LKG_SNAPSHOT_STRING, LKG_SNAPSHOT_NUMBER, LKG_SNAPSHOT_BOOLEAN, LKG_SNAPSHOT_NULL, LKG_SNAPSHOT_UNDEFINED, incrementalLkgContentDigests, lkgContentDigest, captureSlot, getSlot, dropSlot, noteEntry, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, resolveMuralWire, extractM0Block, formatDate, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, prepareCompartmentInjection, renderCompartmentInjection, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, injectM0M1, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure, isRecompSkip, isRecompComplete, extractRecompReason, contextualizeUpgradeReason, setRecompStarting, setRecompNote, setRecompTerminal, runManagedRecomp, runManagedUpgrade };
48063
+ export { withContentLanguageDirective, buildPrimaryLanguageDirective, cortexKitUserConfigBasePath, cortexKitProjectConfigBasePath, resolveLegacyConfigSources, resolveLegacyConfigSourcesForHarness, migrateMagicContextConfigLocations, exports_external, DEFAULT_PROTECTED_TAGS, parseCron, nextOccurrence, nextDueAtMs, promptSurfaceConfigIdentity, resolvePromptSurface, resolveModelConfigOrDefault, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, DEFAULT_LOCAL_EMBEDDING_MODEL, PER_HARNESS_MIGRATION_INVENTORY, ConfigProfilesSchema, MagicContextConfigSchema, getOpenCodeDbPath, removeMcOwnedCompactionMarkers, isFailClosedBlockingError, shouldBypassFailClosedBlock, resolveAgentNameFromMessages, createFailClosedController, recordHookInitFailure, clearHookInitFailure, getLastHookInitFailure, ProjectIdentityError, resolveProjectIdentityStrict, takeDubiousOwnershipProjectIdentityWarning, resolveProjectIdentity, directoryHasGitMetadata, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, isLinkedGitWorktree, recordSessionProjectIdentity, beginBootQuietPeriod, bootQuietRemainingMs, scheduleAfterBootQuiet, rpcPortDir, rpcPortFilePath, isPidAlive, parseRpcPortFile, observeAuthorityRouting, registerModuleNoteEvaluationBridge, getModuleNoteEvaluationBridge, getContextStoreUuid, ensureContextStoreUuid, getAuthorityManagedMarker, reconcileAuthorityProject, checksumAuthoritySeedRows, prepareAuthority, drainAuthority, getMirrorCursor, applyMirroredNoteCompileFields, applyMirrorPage, pullMemoryMirrorOnce, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, computeWorkspaceEpochFingerprint, textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, getCurrentToolSetHash, recordToolDefinition, getMeasuredToolDefinitionTokens, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getDatabasePath, getPersistedSchemaVersion, setSqlitePragmaConfig, runSqliteOptimize, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, clearRecompStaging, isRawCompactionSummaryInfo, extractInMemoryMessageViews, buildInMemoryTailRawMessages, isRecord, estimateTrueRawMessageTokens, invalidateTrueRawTokenCache, stripPersistedAssistantText, byteSize, stripTagPrefix, prependTag, isThinkingPart, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, isEditTool, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, setRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, primeInMemoryTailRawMessageCache, readRawSessionMessageOrdinalPage, getRawSessionStoredMessageCount, readRawSessionMessagePartsById, readRawSessionMessageOrdinalById, readRawSessionMessageById, readSessionChunk, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, deleteIndexedMessage, clearIndexedMessages, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, recordEmbeddingMeasurement, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationIdForProjects, MAX_EXECUTE_THRESHOLD, escalationBands, isEmergencyRecoveryArmed, isProviderOverflowReconfirmed, getEmergencyRecoveryArmedAt, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, getPersistedReasoningWatermark, setPersistedReasoningWatermark, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, getNoteNudgeAnchors, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, removeNoteNudgeAnchorByMessageId, removeAutoSearchHintDecisionByMessageId, getPersistedTodoPermissionDenied, setPersistedTodoPermissionDenied, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, setNoteLastReadAt, getHistorianFailureState, clearHistorianFailureState, getOverflowState, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, setPersistedCompactionMarkerState, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, removeStrippedPlaceholderId, NEWEST_REASONING_BEARING_ASSISTANT, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, thinkingBindingRecoveryFrozenId, getThinkingBindingRecoveryTarget, armThinkingBindingRecovery, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getTrailingBlankDecisions, addTrailingBlankDecisions, demoteTrailingBlankKeepDecisions, getStaleReduceStrippedIds, addStaleReduceStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, peekDeferredExecutePending, setDeferredExecutePendingIfAbsent, clearDeferredExecutePendingIfMatches, getSessionsWithPendingMarker, setSessionWorkMetrics, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNote, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectMemoryEpoch, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, CTX_REDUCE_KEEP, estimateImageTokensFromDataUrl, normalizeTodoStateJson, buildSyntheticTodoPart, computeSyntheticCallId, isSyntheticTodoPart, countRealUserMessages, tailHygieneStructuralSignature, sameTailHygieneStructuralSignature, refreshTailHygieneBaseline, effectiveTailHygiene, assertTailHygieneContentUnchanged, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, toolOutputTokens, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, estimateEmergencyDropReclaimTokens, planEmergencyDrop, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, markWhitespaceAssistantTagInert, getInertWhitespaceAssistantTags, updateTagDropMode, updateCavemanDepth, updateTagMessageId, deleteTagsByMessageId, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getTailHygieneTags, getDroppedTagsBySession, getTagsByNumbers, getMaxDroppedTagNumber, getTagById, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, createChildSessionWithFence, detectThinkingBindingMismatch, isFable51ThinkingBindingModel, detectOverflow, resolveFallbackChain, modelBodyField, toModelEntry, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, extractLatestAssistantText, hasLengthCappedOutput, setKeepSubagents, shouldKeepSubagents, recordChildInvocation, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, Priority, AdmissionClass, StaleRouteHandleError, SocketClosedError, SocketTimeoutError, SubcClient, isConsumerReconnectTransient, connectionFileExists, getCompartmentEvents, loadCompartmentChunkEmbeddingsForSearch, cosineSimilarity, SYNAPSE_DEFAULT_MODEL, SynapseEmbeddingProvider, computeNormalizedHash, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitTimeMs, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, saveEmbeddingIfHashMatches, getProjectEmbeddings, peekProjectEmbeddings, invalidateProject, invalidateMemory, markProjectLoadUntrusted, contentSha256, sweepStaleEmbeddingIdentitiesForProject, registerProjectEmbedding, registerProjectShadowEmbedding, getShadowEmbeddingMeasurementCohort, getPrimaryEmbeddingMeasurementCohort, embedShadowTextForProject, enqueueShadowEmbeddingItems, registerProjectInObservationMode, getProjectEmbeddingSnapshot, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, isEmbeddingEnabled, embedText, ensureMemoryEmbeddings, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, recordMuralCueRejection, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, buildWorkspaceMemorySqlFilter, getMemoriesByProjects, getMaxMemoryIdForProjects, readNewMemoriesForM1Union, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, setMemoryClassification, supersededMemory, mergeMemoryStats, archiveMemory, getMemoryCountsByStatus, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getMural, BoundedSessionMap, registerLkgPersistence, LKG_SNAPSHOT_ARRAY, LKG_SNAPSHOT_OBJECT, LKG_SNAPSHOT_KEY, LKG_SNAPSHOT_STRING, LKG_SNAPSHOT_NUMBER, LKG_SNAPSHOT_BOOLEAN, LKG_SNAPSHOT_NULL, LKG_SNAPSHOT_UNDEFINED, incrementalLkgContentDigests, lkgContentDigest, captureSlot, getSlot, dropSlot, noteEntry, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, resolveMuralWire, extractM0Block, formatDate, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, prepareCompartmentInjection, renderCompartmentInjection, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, injectM0M1, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure, isRecompSkip, isRecompComplete, extractRecompReason, contextualizeUpgradeReason, setRecompStarting, setRecompNote, setRecompTerminal, runManagedRecomp, runManagedUpgrade };