@cortexkit/opencode-magic-context 0.47.0 → 0.49.0

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 (425) hide show
  1. package/dist/agents/magic-context-prompt.d.ts +1 -1
  2. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  3. package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
  4. package/dist/auto-search-worker.js +27 -30
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/mural-model-deprecation.d.ts +15 -0
  7. package/dist/config/mural-model-deprecation.d.ts.map +1 -0
  8. package/dist/config/project-security.d.ts +0 -3
  9. package/dist/config/project-security.d.ts.map +1 -1
  10. package/dist/config/schema/magic-context.d.ts +10 -6
  11. package/dist/config/schema/magic-context.d.ts.map +1 -1
  12. package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-kzx4dmk1.js} +12 -10
  13. package/dist/{context-wq4ffwyb.js → context-nj5f293n.js} +2765 -1925
  14. package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-qz5rrr08.js} +4 -3
  15. package/dist/embedding-activity-g1dhes6g.js +10 -0
  16. package/dist/embedding-backfill-aetxv1vt.js +21 -0
  17. package/dist/embedding-cache-mgyr73ef.js +16 -0
  18. package/dist/embedding-worker.js +11 -9
  19. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
  21. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
  23. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
  25. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
  27. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  29. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  30. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  31. package/dist/features/magic-context/message-index-async.d.ts +16 -3
  32. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  33. package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
  34. package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
  35. package/dist/features/magic-context/message-index.d.ts +7 -1
  36. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  37. package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
  38. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  39. package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
  40. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  41. package/dist/features/magic-context/search-rerank.d.ts +35 -0
  42. package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
  43. package/dist/features/magic-context/search.d.ts +40 -0
  44. package/dist/features/magic-context/search.d.ts.map +1 -1
  45. package/dist/features/magic-context/session-activity.d.ts.map +1 -1
  46. package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
  47. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  49. package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
  50. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  51. package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
  52. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  53. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  54. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  55. package/dist/features/magic-context/storage-session-tables.d.ts +2 -0
  56. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  57. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
  58. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
  59. package/dist/features/magic-context/storage-tags.d.ts +153 -4
  60. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  61. package/dist/features/magic-context/storage.d.ts +1 -1
  62. package/dist/features/magic-context/storage.d.ts.map +1 -1
  63. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  64. package/dist/features/magic-context/tagger.d.ts +2 -0
  65. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  66. package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
  67. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  68. package/dist/harness-e4avh192.js +10 -0
  69. package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
  70. package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
  73. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
  74. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  75. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +34 -3
  77. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/command-handler.d.ts +3 -0
  79. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
  84. package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
  87. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/hook.d.ts +3 -2
  89. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
  92. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
  94. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
  96. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
  98. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
  100. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
  101. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
  102. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
  103. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
  104. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
  105. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
  106. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
  107. package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
  108. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  109. package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
  110. package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
  111. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
  112. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
  113. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
  114. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
  115. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
  116. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
  117. package/dist/hooks/magic-context/read-session-chunk.d.ts +19 -1
  118. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  119. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
  121. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  122. package/dist/hooks/magic-context/read-session-raw.d.ts +118 -1
  123. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  124. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
  126. package/dist/hooks/magic-context/rust-mode-transform.d.ts +36 -0
  127. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/sentinel.d.ts +41 -1
  129. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
  131. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
  132. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
  133. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
  134. package/dist/hooks/magic-context/strip-content.d.ts +14 -2
  135. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  136. package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
  137. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  138. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  139. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  140. package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
  141. package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
  142. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  143. package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
  144. package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
  145. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +13 -0
  146. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  147. package/dist/hooks/magic-context/transform.d.ts +9 -2
  148. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  149. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  150. package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
  151. package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
  152. package/dist/{index-5gq3b2ya.js → index-1bt88epp.js} +227 -205
  153. package/dist/{index-cwf6s3ay.js → index-1g30axtz.js} +3279 -2907
  154. package/dist/{index-5a2r0p9f.js → index-1r0k9js3.js} +20 -13
  155. package/dist/index-2bvekkfy.js +11 -0
  156. package/dist/{index-6d9e1m08.js → index-2jcbj7r1.js} +13301 -13225
  157. package/dist/index-2jgwttpt.js +3269 -0
  158. package/dist/index-4dhv7mqz.js +131 -0
  159. package/dist/{index-sj29b3z2.js → index-4mjhqadz.js} +3 -3
  160. package/dist/{index-0c82743p.js → index-57mrqed8.js} +17 -15
  161. package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
  162. package/dist/index-7jzrrxap.js +931 -0
  163. package/dist/index-8ajstryz.js +18 -0
  164. package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
  165. package/dist/{index-6wkcswft.js → index-9qjqq45k.js} +29 -19
  166. package/dist/{index-adwfkpex.js → index-9rt53q79.js} +23 -23
  167. package/dist/index-b7mv1jx3.js +1060 -0
  168. package/dist/index-d9vfe7xq.js +16 -0
  169. package/dist/{index-gg8j07zz.js → index-ezmszwbd.js} +8 -6
  170. package/dist/index-fb3zxn06.js +13 -0
  171. package/dist/index-fr0wbhdn.js +43 -0
  172. package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
  173. package/dist/index-gzcmtmar.js +171 -0
  174. package/dist/{index-w2t4ah5j.js → index-h2py7207.js} +6762 -7400
  175. package/dist/index-h2wc01qk.js +120 -0
  176. package/dist/index-h5zfkjyk.js +1277 -0
  177. package/dist/{index-92bp57hg.js → index-ha87j7a8.js} +1343 -149
  178. package/dist/index-hj2q50k0.js +856 -0
  179. package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
  180. package/dist/index-kmpvemph.js +1314 -0
  181. package/dist/index-kp5qe690.js +3030 -0
  182. package/dist/{index-m5fe6jch.js → index-kq57tdf0.js} +152 -2453
  183. package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
  184. package/dist/{v2/server-njt3np1k.js → index-nm6a8xpd.js} +220 -961
  185. package/dist/{index-hybnrwq0.js → index-nsjyysj0.js} +137 -130
  186. package/dist/index-nydv6g8r.js +3569 -0
  187. package/dist/index-pavzsdc6.js +17 -0
  188. package/dist/index-peshmj6h.js +152 -0
  189. package/dist/index-pxwp2hjk.js +571 -0
  190. package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
  191. package/dist/{v2/server-51dv1pr5.js → index-qx53vezw.js} +301 -27
  192. package/dist/{index-rrrsepyw.js → index-s4j7t92z.js} +90 -85
  193. package/dist/{index-9pk9exrb.js → index-stbr4ce6.js} +18 -18
  194. package/dist/{index-fzbvakh0.js → index-tqf7yg27.js} +3 -3
  195. package/dist/index-vkbqdnkj.js +2307 -0
  196. package/dist/{index-8da2zjhz.js → index-z1tjp257.js} +9 -7
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +608 -349
  199. package/dist/logger-ewak5q1s.js +20 -0
  200. package/dist/message-index-bounded-h0mrd4pr.js +124 -0
  201. package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-8x06r9kx.js} +8 -6
  202. package/dist/migration-worker.js +25 -18
  203. package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  204. package/dist/plugin/dream-timer.d.ts +1 -1
  205. package/dist/plugin/dream-timer.d.ts.map +1 -1
  206. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
  207. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  208. package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
  209. package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
  210. package/dist/plugin/host-stall-profiler.d.ts +2 -95
  211. package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
  212. package/dist/plugin/messages-transform.d.ts +0 -13
  213. package/dist/plugin/messages-transform.d.ts.map +1 -1
  214. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  215. package/dist/plugin/tool-registry.d.ts.map +1 -1
  216. package/dist/project-embedding-registry-rtt0djyb.js +88 -0
  217. package/dist/raw-ordinal-warmup-worker.js +60 -0
  218. package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-ty89v75e.js} +17 -9
  219. package/dist/read-session-raw-8sjbc9h0.js +60 -0
  220. package/dist/recomp-orchestrator-4f1yyd1q.js +57 -0
  221. package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-q0cyrx3x.js} +4 -2
  222. package/dist/search-pz4f4wge.js +45 -0
  223. package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-38cd5dqt.js} +10 -7
  224. package/dist/shared/auto-search-lifecycle.d.ts +14 -0
  225. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
  226. package/dist/shared/conflict-detector.d.ts.map +1 -1
  227. package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
  228. package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
  229. package/dist/shared/host-stall-profiler-common.d.ts +58 -0
  230. package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
  231. package/dist/shared/host-stall-profiler-node.d.ts +36 -0
  232. package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
  233. package/dist/shared/host-stall-profiler-report.d.ts +68 -0
  234. package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
  235. package/dist/shared/host-stall-profiler.d.ts +5 -0
  236. package/dist/shared/host-stall-profiler.d.ts.map +1 -0
  237. package/dist/shared/logger.d.ts.map +1 -1
  238. package/dist/shared/model-resolution.d.ts +2 -3
  239. package/dist/shared/model-resolution.d.ts.map +1 -1
  240. package/dist/shared/models-dev-temperature.d.ts +18 -0
  241. package/dist/shared/models-dev-temperature.d.ts.map +1 -0
  242. package/dist/shared/project-directory-key.d.ts +16 -0
  243. package/dist/shared/project-directory-key.d.ts.map +1 -1
  244. package/dist/shared/sqlite.d.ts +30 -0
  245. package/dist/shared/sqlite.d.ts.map +1 -1
  246. package/dist/shared/stable-json.d.ts.map +1 -1
  247. package/dist/shared/subagent-temperature.d.ts +46 -0
  248. package/dist/shared/subagent-temperature.d.ts.map +1 -0
  249. package/dist/shared/user-facing-codes.d.ts +0 -5
  250. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  251. package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  252. package/dist/sqlite-mhjkerzq.js +46 -0
  253. package/dist/storage-memory-07fx57k6.js +71 -0
  254. package/dist/storage-tags-k0pda32s.js +133 -0
  255. package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
  256. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  257. package/dist/tools/ctx-note/constants.d.ts +4 -0
  258. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  259. package/dist/tools/ctx-note/tools.d.ts +1 -0
  260. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  261. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  262. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  263. package/dist/tools/ctx-search/types.d.ts +1 -0
  264. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  265. package/dist/tools/parameter-descriptions.d.ts +2 -2
  266. package/dist/tools/parameter-descriptions.d.ts.map +1 -1
  267. package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-tck4g20s.js} +35 -20
  268. package/dist/transformers-node-wasm.js +18415 -18415
  269. package/dist/v2/auto-search-worker.js +27 -30
  270. package/dist/v2/{context-14v1hr8b.js → context-crbt6p1y.js} +4708 -4218
  271. package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-fgej9j46.js} +4 -3
  272. package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
  273. package/dist/v2/embedding-backfill-ph1qfyn3.js +21 -0
  274. package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
  275. package/dist/v2/embedding-worker.js +12 -9
  276. package/dist/v2/fold/host-media.d.ts +4 -0
  277. package/dist/v2/fold/host-media.d.ts.map +1 -1
  278. package/dist/v2/fold/memory-cache.d.ts +70 -0
  279. package/dist/v2/fold/memory-cache.d.ts.map +1 -0
  280. package/dist/v2/fold/native-codec.d.ts +10 -0
  281. package/dist/v2/fold/native-codec.d.ts.map +1 -0
  282. package/dist/v2/fold/native-replay.d.ts +58 -0
  283. package/dist/v2/fold/native-replay.d.ts.map +1 -0
  284. package/dist/v2/fold/policy.d.ts +24 -0
  285. package/dist/v2/fold/policy.d.ts.map +1 -0
  286. package/dist/v2/harness-e4avh192.js +10 -0
  287. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  288. package/dist/v2/hidden-completion.d.ts +7 -0
  289. package/dist/v2/hidden-completion.d.ts.map +1 -1
  290. package/dist/v2/hooks/context.d.ts +2 -2
  291. package/dist/v2/hooks/context.d.ts.map +1 -1
  292. package/dist/v2/hooks/dream-manual.d.ts +1 -1
  293. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  294. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  295. package/dist/v2/hooks/dream-trigger.d.ts +5 -3
  296. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  297. package/dist/v2/hooks/generate.d.ts +9 -2
  298. package/dist/v2/hooks/generate.d.ts.map +1 -1
  299. package/dist/v2/hooks/payload.d.ts.map +1 -1
  300. package/dist/v2/hooks/tools.d.ts.map +1 -1
  301. package/dist/v2/hooks/types.d.ts +6 -0
  302. package/dist/v2/hooks/types.d.ts.map +1 -1
  303. package/dist/v2/logger-pj02s7sr.js +19 -0
  304. package/dist/v2/message-index-bounded-xwqdywxg.js +123 -0
  305. package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-cje68egj.js} +7 -7
  306. package/dist/v2/migration-worker.js +24 -17
  307. package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  308. package/dist/v2/project-embedding-registry-d6m7tyxr.js +86 -0
  309. package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
  310. package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-8p5mdryx.js} +16 -8
  311. package/dist/v2/read-session-raw-j8dvp7f4.js +59 -0
  312. package/dist/v2/recomp-orchestrator-ckfgt6wq.js +57 -0
  313. package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-y3p1hce9.js} +3 -3
  314. package/dist/v2/search-ym8rehhz.js +45 -0
  315. package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-5m0yapqx.js} +9 -8
  316. package/dist/v2/{server-rz514f14.js → server-19zjmn02.js} +2044 -2060
  317. package/dist/v2/server-1tk82krw.js +796 -0
  318. package/dist/v2/server-2bvekkfy.js +11 -0
  319. package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
  320. package/dist/v2/server-2s6ayq3t.js +1048 -0
  321. package/dist/v2/{server-fcdehk1s.js → server-2s9qz6n7.js} +4 -4
  322. package/dist/v2/server-3j4d00kf.js +171 -0
  323. package/dist/v2/{server-14vq4kpm.js → server-3t0q2cqx.js} +3 -3
  324. package/dist/v2/server-4dhv7mqz.js +131 -0
  325. package/dist/v2/server-4ez8mntn.js +3213 -0
  326. package/dist/v2/{server-6r257mf5.js → server-676xw7at.js} +3 -3
  327. package/dist/v2/{server-vs5gpnd4.js → server-6byqfbqf.js} +165 -145
  328. package/dist/v2/server-7ekna9zs.js +120 -0
  329. package/dist/v2/server-7h861yms.js +1272 -0
  330. package/dist/v2/server-7jzrrxap.js +931 -0
  331. package/dist/v2/server-8ajstryz.js +18 -0
  332. package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
  333. package/dist/v2/{server-cpepxy2q.js → server-8k2agx29.js} +14 -12
  334. package/dist/v2/server-c5rrgrcd.js +3545 -0
  335. package/dist/v2/server-d9vfe7xq.js +16 -0
  336. package/dist/v2/server-fb3zxn06.js +13 -0
  337. package/dist/v2/server-fr0wbhdn.js +43 -0
  338. package/dist/v2/{server-y10vbq6y.js → server-hb6xhh9q.js} +11 -1053
  339. package/dist/v2/server-jvxzm1jy.js +3023 -0
  340. package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
  341. package/dist/{index-5eqk6z3s.js → v2/server-kzns2hbz.js} +301 -27
  342. package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
  343. package/dist/v2/server-pavzsdc6.js +17 -0
  344. package/dist/v2/{server-vd4e7174.js → server-pj4pjv02.js} +21 -17
  345. package/dist/v2/{server-e0c1b7a7.js → server-q4ph9bwn.js} +1340 -148
  346. package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
  347. package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
  348. package/dist/v2/{server-d0sraw7m.js → server-sa8jvrfc.js} +291 -286
  349. package/dist/v2/server-ss95ky04.js +1048 -0
  350. package/dist/v2/{server-1qbnzc80.js → server-t4k4qexw.js} +142 -150
  351. package/dist/{index-x3kwrmqk.js → v2/server-v4mewb78.js} +35 -792
  352. package/dist/v2/server-w32kmdez.js +154 -0
  353. package/dist/v2/{server-nf82q6pt.js → server-x4hscabv.js} +5547 -5449
  354. package/dist/v2/server-xwz4dqh9.js +569 -0
  355. package/dist/v2/{server-efhwzx05.js → server-ycw9qqcy.js} +23 -23
  356. package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
  357. package/dist/v2/server-zp53y8js.js +1311 -0
  358. package/dist/v2/server.js +16 -14
  359. package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  360. package/dist/v2/sqlite-mhjkerzq.js +46 -0
  361. package/dist/v2/storage-memory-07fx57k6.js +71 -0
  362. package/dist/v2/storage-tags-8vw924zn.js +132 -0
  363. package/dist/v2/store-reader.d.ts +24 -2
  364. package/dist/v2/store-reader.d.ts.map +1 -1
  365. package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
  366. package/dist/v2/transformers-node-wasm.js +18415 -18415
  367. package/dist/v2/tui/index.d.ts.map +1 -1
  368. package/dist/v2/tui/types.d.ts +1 -10
  369. package/dist/v2/tui/types.d.ts.map +1 -1
  370. package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-a7efxaax.js} +51 -30
  371. package/dist/wrapup-orchestrator-barbc6h9.js +44 -0
  372. package/package.json +4 -3
  373. package/src/agents/magic-context-prompt.ts +27 -2
  374. package/src/agents/smart-notes-enabled.test.ts +294 -0
  375. package/src/agents/smart-notes-on.golden.json +70 -0
  376. package/src/config/index.test.ts +67 -1
  377. package/src/config/index.ts +2 -0
  378. package/src/config/latch-permanence-guard.test.ts +4 -0
  379. package/src/config/mural-model-deprecation.ts +24 -0
  380. package/src/config/project-security.hostile-matrix.test.ts +4 -44
  381. package/src/config/project-security.test.ts +9 -14
  382. package/src/config/project-security.ts +13 -55
  383. package/src/config/schema/magic-context.test.ts +2 -2
  384. package/src/config/schema/magic-context.ts +16 -10
  385. package/src/features/magic-context/dreamer/task-registry.ts +6 -0
  386. package/src/shared/auto-search-lifecycle.ts +43 -0
  387. package/src/shared/conflict-detector.test.ts +56 -0
  388. package/src/shared/conflict-detector.ts +16 -5
  389. package/src/shared/host-stall-profiler-bun.ts +358 -0
  390. package/src/shared/host-stall-profiler-common.ts +159 -0
  391. package/src/shared/host-stall-profiler-node.test.ts +234 -0
  392. package/src/shared/host-stall-profiler-node.ts +274 -0
  393. package/src/shared/host-stall-profiler-report.ts +248 -0
  394. package/src/shared/host-stall-profiler.ts +57 -0
  395. package/src/shared/logger.test.ts +38 -0
  396. package/src/shared/logger.ts +10 -2
  397. package/src/shared/model-resolution.test.ts +54 -17
  398. package/src/shared/model-resolution.ts +6 -17
  399. package/src/shared/models-dev-temperature.ts +107 -0
  400. package/src/shared/project-directory-key.test.ts +59 -0
  401. package/src/shared/project-directory-key.ts +20 -0
  402. package/src/shared/sqlite.test.ts +52 -0
  403. package/src/shared/sqlite.ts +339 -23
  404. package/src/shared/stable-json-linear.test.ts +109 -0
  405. package/src/shared/stable-json.ts +37 -7
  406. package/src/shared/subagent-temperature.test.ts +270 -0
  407. package/src/shared/subagent-temperature.ts +110 -0
  408. package/src/shared/user-facing-codes.ts +2 -6
  409. package/src/shared/write-transaction-attribution.test.ts +2 -2
  410. package/src/v2/tui/host-contract.test.ts +41 -67
  411. package/src/v2/tui/index.ts +6 -214
  412. package/src/v2/tui/types.ts +5 -17
  413. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
  414. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
  415. package/dist/features/magic-context/checkout-claim.d.ts +0 -155
  416. package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
  417. package/dist/index-bb36vgr3.js +0 -6608
  418. package/dist/index-fnn5pjtt.js +0 -6554
  419. package/dist/recomp-orchestrator-rervg6q4.js +0 -42
  420. package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
  421. package/dist/v2/server-3trjk1hx.js +0 -6360
  422. package/dist/v2/server-nm9n3aqq.js +0 -6461
  423. package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
  424. /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
  425. /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
@@ -0,0 +1,3023 @@
1
+ import {
2
+ DEFAULT_LOCAL_EMBEDDING_MODEL
3
+ } from "./server-zm570tr2.js";
4
+ import {
5
+ withSqliteBackgroundWriter2,
6
+ withoutSqliteTransformPass2,
7
+ isTransientSqliteError2
8
+ } from "./server-kb9nn0a0.js";
9
+ import {
10
+ isEmbeddingHostBusy2
11
+ } from "./server-qt1qqasc.js";
12
+ import {
13
+ getHarness2
14
+ } from "./server-pavzsdc6.js";
15
+ import {
16
+ sanitizeDiagnosticText,
17
+ log2
18
+ } from "./server-t4k4qexw.js";
19
+ import {
20
+ estimateTokens
21
+ } from "./server-kzns2hbz.js";
22
+ import {
23
+ SYNAPSE_DEFAULT_MODEL,
24
+ isSynapseEmbeddingTruncated,
25
+ getSynapseBatchRequestKey,
26
+ SynapseEmbeddingProvider
27
+ } from "./server-hb6xhh9q.js";
28
+ import {
29
+ CHUNK_WINDOW_SAFETY_RATIO,
30
+ normalizeCompartmentChunkMaxInputTokens,
31
+ buildCanonicalChunkTextFromFts,
32
+ buildCompartmentSummaryFallbackText,
33
+ chunkCanonicalText,
34
+ chunkEmbeddingWindowsAreCurrent,
35
+ replaceCompartmentChunkEmbeddings,
36
+ loadUnembeddedShadowChunkCandidates,
37
+ loadUnembeddedCompartmentChunkCandidatesPolite,
38
+ recordChunkEmbedBackoff,
39
+ chunkWindowSourceKey,
40
+ loadUnembeddedSessionChunkCandidatesPolite,
41
+ countSessionCompartmentEmbedCoverage,
42
+ countUnembeddedSessionCompartmentsPolite
43
+ } from "./server-ss95ky04.js";
44
+ import {
45
+ saveEmbeddingIfHashMatches,
46
+ getMemoryEmbedCoverage,
47
+ invalidateProject2
48
+ } from "./server-4dhv7mqz.js";
49
+ import {
50
+ dominantEmbeddingFailure,
51
+ embeddingModelsMatch,
52
+ resolveEmbeddingTextPrefixes,
53
+ getEmbeddingProviderIdentity,
54
+ LocalEmbeddingProvider
55
+ } from "./server-2s6ayq3t.js";
56
+ import {
57
+ isUserHomeDirectory,
58
+ setBootQuietPeriodForTests
59
+ } from "./server-xwz4dqh9.js";
60
+ import {
61
+ logSlowWriteTransaction
62
+ } from "./server-3t0q2cqx.js";
63
+
64
+ // src/features/magic-context/storage-embedding-measurements.ts
65
+ import { createHash } from "node:crypto";
66
+ function normalizedQueryHash(query) {
67
+ const normalized = query.trim().replace(/\s+/g, " ").toLowerCase();
68
+ return createHash("sha256").update(normalized).digest("hex");
69
+ }
70
+ var MEASUREMENT_CORPUS_SESSION_ROW_CAP = 2000;
71
+ function recordEmbeddingMeasurement(db, input, cap = MEASUREMENT_CORPUS_SESSION_ROW_CAP) {
72
+ const queryTextHash = normalizedQueryHash(input.queryText);
73
+ const dedupKey = queryTextHash;
74
+ const result = db.prepare(`INSERT OR IGNORE INTO embedding_measurement_corpus
75
+ (session_id, project_path, dedup_key, cohort_key, query_text_hash,
76
+ primary_result_ids_json, shadow_result_ids_json, primary_latency_ms, shadow_latency_ms,
77
+ primary_failed, shadow_failed, primary_model_id, shadow_model_id,
78
+ primary_fingerprint, shadow_fingerprint, primary_epoch, shadow_epoch,
79
+ corpus_hash, coverage_json, created_at)
80
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.sessionId, input.projectPath, dedupKey, input.cohortKey, queryTextHash, JSON.stringify(input.primaryResultIds.slice(0, 10)), JSON.stringify(input.shadowResultIds.slice(0, 10)), input.primaryLatencyMs, input.shadowLatencyMs, input.primaryFailed ? 1 : 0, input.shadowFailed ? 1 : 0, input.primaryModelId, input.shadowModelId, input.primaryFingerprint, input.shadowFingerprint, input.primaryEpoch, input.shadowEpoch, input.corpusHash, JSON.stringify(input.coverage), Date.now());
81
+ if (result.changes > 0) {
82
+ const rowCount = db.prepare("SELECT COUNT(*) AS count FROM embedding_measurement_corpus WHERE session_id = ?").get(input.sessionId).count;
83
+ const overflow = rowCount - cap;
84
+ if (overflow > 0) {
85
+ db.prepare(`DELETE FROM embedding_measurement_corpus
86
+ WHERE session_id = ?
87
+ AND id IN (
88
+ SELECT id FROM embedding_measurement_corpus
89
+ WHERE session_id = ?
90
+ ORDER BY id ASC
91
+ LIMIT ?
92
+ )`).run(input.sessionId, input.sessionId, overflow);
93
+ }
94
+ }
95
+ return result.changes > 0;
96
+ }
97
+ function beginSynapseBatchLedger(db, input, now = Date.now()) {
98
+ db.prepare(`INSERT INTO synapse_batch_ledger
99
+ (session_id, project_path, scope, manifest_json, request_key, status, created_at, updated_at)
100
+ VALUES (?, ?, ?, ?, ?, 'pending', ?, ?)
101
+ ON CONFLICT(session_id, request_key) DO UPDATE SET
102
+ manifest_json = excluded.manifest_json,
103
+ updated_at = excluded.updated_at`).run(input.sessionId, input.projectPath, input.scope, JSON.stringify(input.manifest), input.requestKey, now, now);
104
+ }
105
+ function finishSynapseBatchLedger(db, sessionId, requestKey, status, now = Date.now()) {
106
+ db.prepare("UPDATE synapse_batch_ledger SET status = ?, updated_at = ? WHERE session_id = ? AND request_key = ?").run(status, now, sessionId, requestKey);
107
+ }
108
+ var SYNAPSE_BATCH_LEDGER_TTL_MS = 14 * 24 * 60 * 60 * 1000;
109
+ function pruneSynapseBatchLedgerForProject(db, projectIdentity, ttlMs = SYNAPSE_BATCH_LEDGER_TTL_MS) {
110
+ const ledgerTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'synapse_batch_ledger'").get();
111
+ if (!ledgerTable)
112
+ return 0;
113
+ const shadow = `shadow:${projectIdentity}`;
114
+ const cutoff = Date.now() - ttlMs;
115
+ const predicate = "session_id IN (?, ?) AND updated_at < ?";
116
+ if (!db.prepare(`SELECT 1 FROM synapse_batch_ledger WHERE ${predicate} LIMIT 1`).get(projectIdentity, shadow, cutoff))
117
+ return 0;
118
+ return db.prepare(`DELETE FROM synapse_batch_ledger WHERE ${predicate}`).run(projectIdentity, shadow, cutoff).changes;
119
+ }
120
+
121
+ // src/features/magic-context/project-embedding-registry.ts
122
+ import { createHash as createHash2, randomUUID } from "node:crypto";
123
+
124
+ // src/shared/background-batch-drain.ts
125
+ async function drainBackgroundBatches(step, options = {}) {
126
+ const now = options.now ?? (() => performance.now());
127
+ const deadline = now() + (options.budgetMs ?? 2000);
128
+ const yieldFn = options.yieldFn ?? (() => new Promise((resolve) => setTimeout(resolve, 0)));
129
+ let batches = 0;
130
+ while (now() < deadline) {
131
+ try {
132
+ if (!withoutSqliteTransformPass2(() => withSqliteBackgroundWriter2(step)))
133
+ break;
134
+ } catch (error) {
135
+ if (isTransientSqliteError2(error))
136
+ break;
137
+ throw error;
138
+ }
139
+ batches++;
140
+ await yieldFn();
141
+ }
142
+ return batches;
143
+ }
144
+
145
+ // src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
146
+ var saveStatements = new WeakMap;
147
+ var loadProjectStatements = new WeakMap;
148
+ var loadUnembeddedStatements = new WeakMap;
149
+ var countEmbeddedStatements = new WeakMap;
150
+ function getSaveStatement(db) {
151
+ let stmt = saveStatements.get(db);
152
+ if (!stmt) {
153
+ stmt = db.prepare(`INSERT INTO git_commit_embeddings (sha, embedding, model_id, created_at)
154
+ VALUES (?, ?, ?, ?)
155
+ ON CONFLICT(sha, model_id) DO UPDATE SET
156
+ embedding = excluded.embedding,
157
+ created_at = excluded.created_at`);
158
+ saveStatements.set(db, stmt);
159
+ }
160
+ return stmt;
161
+ }
162
+ function getLoadProjectStatement(db) {
163
+ let stmt = loadProjectStatements.get(db);
164
+ if (!stmt) {
165
+ stmt = db.prepare(`SELECT e.sha AS sha, e.embedding AS embedding, e.model_id AS model_id
166
+ FROM git_commit_embeddings e
167
+ JOIN git_commits c ON c.sha = e.sha
168
+ WHERE c.project_path = ? AND e.model_id = ?`);
169
+ loadProjectStatements.set(db, stmt);
170
+ }
171
+ return stmt;
172
+ }
173
+ function getLoadUnembeddedStatement(db) {
174
+ let stmt = loadUnembeddedStatements.get(db);
175
+ if (!stmt) {
176
+ stmt = db.prepare(`SELECT c.sha AS sha, c.message AS message
177
+ FROM git_commits c
178
+ LEFT JOIN git_commit_embeddings e ON c.sha = e.sha AND e.model_id = ?
179
+ WHERE c.project_path = ? AND e.sha IS NULL
180
+ ORDER BY c.committed_at DESC
181
+ LIMIT ?`);
182
+ loadUnembeddedStatements.set(db, stmt);
183
+ }
184
+ return stmt;
185
+ }
186
+ function getCountEmbeddedStatement(db) {
187
+ let stmt = countEmbeddedStatements.get(db);
188
+ if (!stmt) {
189
+ stmt = db.prepare(`SELECT COUNT(*) AS count FROM git_commit_embeddings e
190
+ JOIN git_commits c ON c.sha = e.sha WHERE c.project_path = ? AND e.model_id = ?`);
191
+ countEmbeddedStatements.set(db, stmt);
192
+ }
193
+ return stmt;
194
+ }
195
+ function saveCommitEmbedding(db, sha, embedding, modelId) {
196
+ const bytes = new Uint8Array(embedding.buffer, embedding.byteOffset, embedding.byteLength);
197
+ getSaveStatement(db).run(sha, bytes, modelId, Date.now());
198
+ }
199
+ function loadProjectCommitEmbeddings(db, projectPath, modelId) {
200
+ const rows = getLoadProjectStatement(db).all(projectPath, modelId);
201
+ const map = new Map;
202
+ for (const row of rows) {
203
+ const buffer = row.embedding.buffer.slice(row.embedding.byteOffset, row.embedding.byteOffset + row.embedding.byteLength);
204
+ map.set(row.sha, new Float32Array(buffer));
205
+ }
206
+ return map;
207
+ }
208
+ function loadUnembeddedCommits(db, projectPath, modelId, limit) {
209
+ return getLoadUnembeddedStatement(db).all(modelId, projectPath, limit);
210
+ }
211
+ function countEmbeddedCommits(db, projectPath, modelId) {
212
+ const row = getCountEmbeddedStatement(db).get(projectPath, modelId);
213
+ return row?.count ?? 0;
214
+ }
215
+
216
+ // src/features/magic-context/git-commits/storage-git-commits.ts
217
+ var insertStatements = new WeakMap;
218
+ var existingShasStatements = new WeakMap;
219
+ var projectCountStatements = new WeakMap;
220
+ var evictOverflowStatements = new WeakMap;
221
+ var latestCommitTimeStatements = new WeakMap;
222
+ var latestCommitShaStatements = new WeakMap;
223
+ function getInsertStatement(db) {
224
+ let stmt = insertStatements.get(db);
225
+ if (!stmt) {
226
+ stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
227
+ VALUES (?, ?, ?, ?, ?, ?, ?)
228
+ ON CONFLICT(sha) DO UPDATE SET
229
+ project_path = excluded.project_path,
230
+ short_sha = excluded.short_sha,
231
+ message = excluded.message,
232
+ author = excluded.author,
233
+ committed_at = excluded.committed_at,
234
+ indexed_at = excluded.indexed_at
235
+ WHERE git_commits.message != excluded.message`);
236
+ insertStatements.set(db, stmt);
237
+ }
238
+ return stmt;
239
+ }
240
+ function getExistingShasStatement(db) {
241
+ let stmt = existingShasStatements.get(db);
242
+ if (!stmt) {
243
+ stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
244
+ existingShasStatements.set(db, stmt);
245
+ }
246
+ return stmt;
247
+ }
248
+ function getProjectCountStatement(db) {
249
+ let stmt = projectCountStatements.get(db);
250
+ if (!stmt) {
251
+ stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
252
+ projectCountStatements.set(db, stmt);
253
+ }
254
+ return stmt;
255
+ }
256
+ function getLatestCommitShaStatement(db) {
257
+ let stmt = latestCommitShaStatements.get(db);
258
+ if (!stmt) {
259
+ stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ? ORDER BY committed_at DESC, sha DESC LIMIT 1");
260
+ latestCommitShaStatements.set(db, stmt);
261
+ }
262
+ return stmt;
263
+ }
264
+ function getEvictOverflowStatement(db) {
265
+ let stmt = evictOverflowStatements.get(db);
266
+ if (!stmt) {
267
+ stmt = db.prepare(`DELETE FROM git_commits
268
+ WHERE rowid IN (
269
+ SELECT rowid FROM git_commits
270
+ WHERE project_path = ?
271
+ ORDER BY committed_at DESC, sha DESC
272
+ LIMIT -1 OFFSET ?
273
+ )`);
274
+ evictOverflowStatements.set(db, stmt);
275
+ }
276
+ return stmt;
277
+ }
278
+ function upsertCommits(db, projectPath, commits) {
279
+ if (commits.length === 0)
280
+ return { inserted: 0, updated: 0 };
281
+ const existing = new Set;
282
+ for (const row of getExistingShasStatement(db).all(projectPath)) {
283
+ existing.add(row.sha);
284
+ }
285
+ let inserted = 0;
286
+ let updated = 0;
287
+ const now = Date.now();
288
+ const insertStmt = getInsertStatement(db);
289
+ db.transaction(() => {
290
+ for (const commit of commits) {
291
+ const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
292
+ if (result.changes > 0) {
293
+ if (existing.has(commit.sha)) {
294
+ updated++;
295
+ } else {
296
+ inserted++;
297
+ existing.add(commit.sha);
298
+ }
299
+ }
300
+ }
301
+ }).immediate();
302
+ return { inserted, updated };
303
+ }
304
+ function getCommitCount(db, projectPath) {
305
+ const row = getProjectCountStatement(db).get(projectPath);
306
+ return row?.count ?? 0;
307
+ }
308
+ function getLatestIndexedCommitSha(db, projectPath) {
309
+ const row = getLatestCommitShaStatement(db).get(projectPath);
310
+ return row?.sha ?? null;
311
+ }
312
+ function enforceProjectCap(db, projectPath, maxCommits) {
313
+ if (maxCommits <= 0)
314
+ return 0;
315
+ const count = getCommitCount(db, projectPath);
316
+ if (count <= maxCommits)
317
+ return 0;
318
+ getEvictOverflowStatement(db).run(projectPath, maxCommits);
319
+ const after = getCommitCount(db, projectPath);
320
+ const evicted = Math.max(0, count - after);
321
+ if (evicted > 0) {
322
+ log2(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
323
+ }
324
+ return evicted;
325
+ }
326
+
327
+ // src/features/magic-context/git-commits/sweep-coordinator.ts
328
+ var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
329
+ var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
330
+ var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
331
+ var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
332
+ function runImmediate(db, body) {
333
+ db.exec("BEGIN IMMEDIATE");
334
+ const transactionStartedAt = performance.now();
335
+ let committed = false;
336
+ try {
337
+ const result = body();
338
+ db.exec("COMMIT");
339
+ committed = true;
340
+ logSlowWriteTransaction("git_sweep_lease", transactionStartedAt);
341
+ return result;
342
+ } finally {
343
+ if (!committed) {
344
+ try {
345
+ db.exec("ROLLBACK");
346
+ } catch {}
347
+ }
348
+ }
349
+ }
350
+ function rowToState(row) {
351
+ return {
352
+ projectPath: row.project_path,
353
+ leaseHolder: row.lease_holder,
354
+ leaseExpiresAt: row.lease_expires_at,
355
+ lastSweptAt: row.last_swept_at
356
+ };
357
+ }
358
+ function getGitSweepCoordinatorState(db, projectPath) {
359
+ const row = db.prepare(`SELECT project_path, lease_holder, lease_expires_at, last_swept_at
360
+ FROM git_sweep_coordinator
361
+ WHERE project_path = ?`).get(projectPath);
362
+ return row ? rowToState(row) : null;
363
+ }
364
+ function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
365
+ const cooldownMs = options.cooldownMs ?? GIT_SWEEP_COOLDOWN_MS;
366
+ const leaseTtlMs = options.leaseTtlMs ?? GIT_SWEEP_LEASE_TTL_MS;
367
+ return runImmediate(db, () => {
368
+ const now = Date.now();
369
+ const row = getGitSweepCoordinatorState(db, projectPath);
370
+ if (row?.leaseHolder && row.leaseExpiresAt !== null && row.leaseExpiresAt > now) {
371
+ return {
372
+ acquired: false,
373
+ projectPath,
374
+ reason: "lease_active",
375
+ leaseHolder: row.leaseHolder,
376
+ leaseExpiresAt: row.leaseExpiresAt,
377
+ lastSweptAt: row.lastSweptAt,
378
+ nextAllowedAt: null
379
+ };
380
+ }
381
+ if (!options.ignoreCooldown && row?.lastSweptAt !== null && row?.lastSweptAt !== undefined) {
382
+ const nextAllowedAt = row.lastSweptAt + cooldownMs;
383
+ if (nextAllowedAt > now) {
384
+ return {
385
+ acquired: false,
386
+ projectPath,
387
+ reason: "cooldown_active",
388
+ leaseHolder: row.leaseHolder,
389
+ leaseExpiresAt: row.leaseExpiresAt,
390
+ lastSweptAt: row.lastSweptAt,
391
+ nextAllowedAt
392
+ };
393
+ }
394
+ }
395
+ const leaseExpiresAt = now + leaseTtlMs;
396
+ db.prepare(`INSERT INTO git_sweep_coordinator (
397
+ project_path,
398
+ lease_holder,
399
+ lease_expires_at,
400
+ last_swept_at
401
+ ) VALUES (?, ?, ?, NULL)
402
+ ON CONFLICT(project_path) DO UPDATE SET
403
+ lease_holder = excluded.lease_holder,
404
+ lease_expires_at = excluded.lease_expires_at`).run(projectPath, holderId, leaseExpiresAt);
405
+ return {
406
+ acquired: true,
407
+ projectPath,
408
+ holderId,
409
+ acquiredAt: now,
410
+ leaseExpiresAt
411
+ };
412
+ });
413
+ }
414
+ function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LEASE_TTL_MS) {
415
+ return runImmediate(db, () => {
416
+ const now = Date.now();
417
+ const leaseExpiresAt = now + leaseTtlMs;
418
+ const result = db.prepare(`UPDATE git_sweep_coordinator
419
+ SET lease_expires_at = ?
420
+ WHERE project_path = ?
421
+ AND lease_holder = ?
422
+ AND lease_expires_at > ?`).run(leaseExpiresAt, projectPath, holderId, now);
423
+ return result.changes === 1;
424
+ });
425
+ }
426
+ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
427
+ return runImmediate(db, () => {
428
+ const now = Date.now();
429
+ const result = db.prepare(`UPDATE git_sweep_coordinator
430
+ SET lease_holder = NULL,
431
+ lease_expires_at = NULL,
432
+ last_swept_at = ?
433
+ WHERE project_path = ?
434
+ AND lease_holder = ?
435
+ AND lease_expires_at > ?`).run(now, projectPath, holderId, now);
436
+ return result.changes === 1;
437
+ });
438
+ }
439
+ function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
440
+ return runImmediate(db, () => {
441
+ const now = Date.now();
442
+ const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
443
+ const result = db.prepare(`UPDATE git_sweep_coordinator
444
+ SET lease_holder = NULL,
445
+ lease_expires_at = NULL,
446
+ last_swept_at = ?
447
+ WHERE project_path = ?
448
+ AND lease_holder = ?
449
+ AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
450
+ return result.changes === 1;
451
+ });
452
+ }
453
+ function releaseGitSweepLease(db, projectPath, holderId) {
454
+ runImmediate(db, () => {
455
+ db.prepare(`UPDATE git_sweep_coordinator
456
+ SET lease_holder = NULL,
457
+ lease_expires_at = NULL
458
+ WHERE project_path = ?
459
+ AND lease_holder = ?`).run(projectPath, holderId);
460
+ });
461
+ }
462
+
463
+ // src/features/magic-context/memory/embedding-ssrf.ts
464
+ var METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata.goog"]);
465
+ var IPV6_METADATA_HOSTS = new Set(["fd00:ec2::254"]);
466
+ function isLinkLocalIpv4(host) {
467
+ return /^169\.254\.\d{1,3}\.\d{1,3}$/.test(host);
468
+ }
469
+ function ipv4FromMappedIpv6(host) {
470
+ const m = /^::ffff:(.+)$/.exec(host);
471
+ if (!m)
472
+ return null;
473
+ const tail = m[1];
474
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(tail))
475
+ return tail;
476
+ const hex = /^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(tail);
477
+ if (hex) {
478
+ const hi = Number.parseInt(hex[1], 16);
479
+ const lo = Number.parseInt(hex[2], 16);
480
+ if (Number.isNaN(hi) || Number.isNaN(lo))
481
+ return null;
482
+ return `${hi >> 8 & 255}.${hi & 255}.${lo >> 8 & 255}.${lo & 255}`;
483
+ }
484
+ return null;
485
+ }
486
+ function blockedEmbeddingEndpointReason(endpoint) {
487
+ const trimmed = endpoint.trim();
488
+ if (trimmed.length === 0)
489
+ return null;
490
+ let url;
491
+ try {
492
+ url = new URL(trimmed);
493
+ } catch {
494
+ return `embedding endpoint is not a valid URL: ${trimmed}`;
495
+ }
496
+ const host = url.hostname.toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
497
+ if (METADATA_HOSTNAMES.has(host)) {
498
+ return `embedding endpoint host ${host} is a cloud metadata service (blocked)`;
499
+ }
500
+ if (IPV6_METADATA_HOSTS.has(host)) {
501
+ return `embedding endpoint host ${host} is the AWS IPv6 metadata service (blocked)`;
502
+ }
503
+ if (isLinkLocalIpv4(host)) {
504
+ return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
505
+ }
506
+ const mappedV4 = ipv4FromMappedIpv6(host);
507
+ if (mappedV4 && isLinkLocalIpv4(mappedV4)) {
508
+ return `embedding endpoint host ${host} (IPv4-mapped ${mappedV4}) is link-local / cloud metadata (blocked)`;
509
+ }
510
+ if (host.startsWith("fe80:")) {
511
+ return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
512
+ }
513
+ return null;
514
+ }
515
+
516
+ // src/features/magic-context/memory/embedding-openai.ts
517
+ function responseSlots(items, inputCount) {
518
+ if (items.every((item) => item?.index === undefined)) {
519
+ return items.map((_, position) => position);
520
+ }
521
+ const slots = [];
522
+ const seen = new Set;
523
+ for (const item of items) {
524
+ const index = item?.index;
525
+ if (typeof index !== "number" || !Number.isInteger(index) || index < 0 || index >= inputCount || seen.has(index)) {
526
+ return null;
527
+ }
528
+ seen.add(index);
529
+ slots.push(index);
530
+ }
531
+ return slots;
532
+ }
533
+ function capEmbeddingInput(input, maxInputTokens, purpose) {
534
+ const ratio = purpose === "query" ? CHUNK_WINDOW_SAFETY_RATIO : 1;
535
+ const budget = Math.max(1, Math.floor(maxInputTokens * ratio));
536
+ if (estimateTokens(input) <= budget)
537
+ return input;
538
+ let low = 0;
539
+ let high = input.length;
540
+ while (low < high) {
541
+ const mid = Math.ceil((low + high) / 2);
542
+ if (estimateTokens(input.slice(0, mid)) <= budget)
543
+ low = mid;
544
+ else
545
+ high = mid - 1;
546
+ }
547
+ if (low > 0 && low < input.length) {
548
+ const last = input.charCodeAt(low - 1);
549
+ const next = input.charCodeAt(low);
550
+ if (last >= 55296 && last <= 56319 && next >= 56320 && next <= 57343)
551
+ low -= 1;
552
+ }
553
+ return input.slice(0, low);
554
+ }
555
+ function normalizeEndpoint(endpoint) {
556
+ return endpoint?.trim().replace(/\/+$/, "") ?? "";
557
+ }
558
+ var FAILURE_THRESHOLD = 3;
559
+ var FAILURE_WINDOW_MS = 60000;
560
+ var OPEN_DURATION_MS = 5 * 60000;
561
+ var FETCH_TIMEOUT_MS = 30000;
562
+
563
+ class OpenAICompatibleEmbeddingProvider {
564
+ modelId;
565
+ maxInputTokens;
566
+ endpoint;
567
+ model;
568
+ apiKey;
569
+ inputType;
570
+ queryInputType;
571
+ queryPrefix;
572
+ documentPrefix;
573
+ truncate;
574
+ initialized = false;
575
+ failureTimes = [];
576
+ circuitOpenUntil = 0;
577
+ openLogged = false;
578
+ modelMismatchLogged = false;
579
+ lastFailureReason = null;
580
+ halfOpenProbeInFlight = false;
581
+ queryTruncationLogged = false;
582
+ constructor(options) {
583
+ this.endpoint = normalizeEndpoint(options.endpoint);
584
+ this.model = options.model?.trim() ?? "";
585
+ this.apiKey = options.apiKey?.trim() ?? "";
586
+ this.inputType = options.inputType?.trim() ?? "";
587
+ this.queryInputType = options.queryInputType?.trim() ?? "";
588
+ const prefixes = resolveEmbeddingTextPrefixes(this.model, options.queryInstruction, options.documentPrefix);
589
+ this.queryPrefix = prefixes.queryPrefix;
590
+ this.documentPrefix = prefixes.documentPrefix;
591
+ this.truncate = options.truncate?.trim() ?? "";
592
+ this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
593
+ this.modelId = getEmbeddingProviderIdentity({
594
+ provider: "openai-compatible",
595
+ endpoint: this.endpoint,
596
+ model: this.model,
597
+ ...this.apiKey ? { api_key: this.apiKey } : {},
598
+ ...this.inputType ? { input_type: this.inputType } : {},
599
+ ...options.documentPrefix !== undefined ? { document_prefix: options.documentPrefix } : {},
600
+ ...this.truncate ? { truncate: this.truncate } : {}
601
+ });
602
+ }
603
+ async initialize() {
604
+ if (this.initialized)
605
+ return true;
606
+ if (!this.endpoint || !this.model) {
607
+ log2("[magic-context] openai-compatible embedding provider is missing endpoint or model");
608
+ this.initialized = false;
609
+ return false;
610
+ }
611
+ const blockedReason = blockedEmbeddingEndpointReason(this.endpoint);
612
+ if (blockedReason) {
613
+ log2(`[magic-context] embedding endpoint blocked: ${blockedReason}`);
614
+ this.initialized = false;
615
+ return false;
616
+ }
617
+ this.initialized = true;
618
+ return true;
619
+ }
620
+ resolveInputTypeForPurpose(purpose = "passage") {
621
+ if (purpose === "query") {
622
+ return this.queryInputType || this.inputType;
623
+ }
624
+ return this.inputType;
625
+ }
626
+ async embed(text, signal, purpose) {
627
+ const [embedding] = await this.embedBatch([text], signal, purpose);
628
+ return embedding ?? null;
629
+ }
630
+ async embedBatch(texts, signal, purpose) {
631
+ if (texts.length === 0) {
632
+ return [];
633
+ }
634
+ const textPrefix = purpose === "query" ? this.queryPrefix : this.documentPrefix;
635
+ const requestTexts = texts.map((text) => {
636
+ const input = `${textPrefix}${text.trim().length === 0 ? " " : text}`;
637
+ const capped = capEmbeddingInput(input, this.maxInputTokens, purpose);
638
+ if (purpose === "query" && capped.length < input.length && !this.queryTruncationLogged) {
639
+ log2(`[magic-context] embedding query truncated from ${input.length} to ${capped.length} characters to fit max_input_tokens`);
640
+ this.queryTruncationLogged = true;
641
+ }
642
+ return capped;
643
+ });
644
+ if (!await this.initialize()) {
645
+ return Array.from({ length: texts.length }, () => null);
646
+ }
647
+ if (signal?.aborted) {
648
+ return Array.from({ length: texts.length }, () => null);
649
+ }
650
+ let isProbe = false;
651
+ let internalController;
652
+ let timeoutHandle;
653
+ let onOuterAbort;
654
+ try {
655
+ const claim = this.claimProbeOrShortCircuit();
656
+ if (claim === "short_circuit") {
657
+ return Array.from({ length: texts.length }, () => null);
658
+ }
659
+ isProbe = claim === "probe";
660
+ internalController = new AbortController;
661
+ timeoutHandle = setTimeout(() => internalController?.abort(), FETCH_TIMEOUT_MS);
662
+ onOuterAbort = () => internalController?.abort();
663
+ if (signal) {
664
+ signal.addEventListener("abort", onOuterAbort, { once: true });
665
+ }
666
+ const inputTypeForRequest = this.resolveInputTypeForPurpose(purpose);
667
+ const response = await fetch(`${this.endpoint}/embeddings`, {
668
+ method: "POST",
669
+ headers: {
670
+ "content-type": "application/json",
671
+ ...this.apiKey ? { authorization: `Bearer ${this.apiKey}` } : {}
672
+ },
673
+ body: JSON.stringify({
674
+ model: this.model,
675
+ input: requestTexts,
676
+ ...inputTypeForRequest ? { input_type: inputTypeForRequest } : {},
677
+ ...this.truncate ? { truncate: this.truncate } : {}
678
+ }),
679
+ redirect: "error",
680
+ signal: internalController.signal
681
+ });
682
+ if (!response.ok) {
683
+ const excerpt = await response.text().catch(() => "");
684
+ const failure = this.failure("http_error", `HTTP ${response.status} from endpoint${this.bodyExcerpt(excerpt)}`, response.status >= 500 || response.status === 408 || response.status === 429);
685
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
686
+ this.recordFailure(isProbe, failure);
687
+ return Array.from({ length: texts.length }, () => null);
688
+ }
689
+ const rawBody = await response.text();
690
+ if (rawBody.trim().length === 0) {
691
+ const failure = this.failure("invalid_envelope", "response body was empty", false);
692
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
693
+ this.recordFailure(isProbe, failure);
694
+ return Array.from({ length: texts.length }, () => null);
695
+ }
696
+ let body;
697
+ try {
698
+ body = JSON.parse(rawBody);
699
+ } catch {
700
+ const failure = this.failure("invalid_envelope", `response body was not valid JSON${this.bodyExcerpt(rawBody)}`, false);
701
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
702
+ this.recordFailure(isProbe, failure);
703
+ return Array.from({ length: texts.length }, () => null);
704
+ }
705
+ const servedModel = typeof body.model === "string" ? body.model : "";
706
+ if (this.model && servedModel && !embeddingModelsMatch(servedModel, this.model)) {
707
+ if (!this.modelMismatchLogged) {
708
+ log2(`[magic-context] embedding endpoint served a DIFFERENT model than requested — refusing the substituted vectors (they have the wrong dimensions/space). requested="${sanitizeDiagnosticText(this.model)}" served="${sanitizeDiagnosticText(servedModel)}". Check that the endpoint serves the requested model; variant suffixes and vendor prefixes are matched automatically.`);
709
+ this.modelMismatchLogged = true;
710
+ }
711
+ this.recordFailure(isProbe, this.failure("substitution_rejected", `served model '${sanitizeDiagnosticText(servedModel)}' does not match requested '${sanitizeDiagnosticText(this.model)}' (substitution guard)`, false));
712
+ return Array.from({ length: texts.length }, () => null);
713
+ }
714
+ const responseKeys = Object.keys(body).sort();
715
+ if (!Array.isArray(body.data)) {
716
+ const failure = this.failure("invalid_envelope", `response had keys [${responseKeys.join(", ")}] but data[] was absent`, false);
717
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
718
+ this.recordFailure(isProbe, failure);
719
+ return Array.from({ length: texts.length }, () => null);
720
+ }
721
+ if (body.data.length === 0) {
722
+ const failure = this.failure("empty_result", "response data[] was empty", true);
723
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
724
+ this.recordFailure(isProbe, failure);
725
+ return Array.from({ length: texts.length }, () => null);
726
+ }
727
+ const slots = responseSlots(body.data, texts.length);
728
+ if (!slots) {
729
+ const failure = this.failure("invalid_envelope", "response data[].index values were missing, duplicated or out of range", false);
730
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
731
+ this.recordFailure(isProbe, failure);
732
+ return Array.from({ length: texts.length }, () => null);
733
+ }
734
+ const results = Array.from({ length: texts.length }, () => null);
735
+ body.data.forEach((item, position) => {
736
+ const embedding = item?.embedding;
737
+ const slot = slots[position];
738
+ if (slot !== undefined && slot < results.length && Array.isArray(embedding)) {
739
+ results[slot] = Float32Array.from(embedding);
740
+ }
741
+ });
742
+ if (results.every((r) => r === null)) {
743
+ const failure = this.failure("invalid_envelope", `response had keys [${responseKeys.join(", ")}] but data[].embedding was absent`, false);
744
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
745
+ this.recordFailure(isProbe, failure);
746
+ } else {
747
+ this.recordSuccess();
748
+ }
749
+ return results;
750
+ } catch (error) {
751
+ const isAbort = error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
752
+ if (isAbort) {
753
+ if (signal?.aborted) {} else {
754
+ log2(`[magic-context] openai-compatible embedding request timed out after ${FETCH_TIMEOUT_MS}ms`);
755
+ const failure = this.failure("transport_error", `request timed out after ${FETCH_TIMEOUT_MS}ms`, true);
756
+ this.recordFailure(isProbe, failure);
757
+ }
758
+ } else {
759
+ const detail = error instanceof Error ? error.message : String(error);
760
+ const failure = this.failure("transport_error", `transport error: ${sanitizeDiagnosticText(detail)}`, true);
761
+ log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
762
+ this.recordFailure(isProbe, failure);
763
+ }
764
+ return Array.from({ length: texts.length }, () => null);
765
+ } finally {
766
+ if (timeoutHandle !== undefined) {
767
+ clearTimeout(timeoutHandle);
768
+ }
769
+ if (signal && onOuterAbort) {
770
+ signal.removeEventListener("abort", onOuterAbort);
771
+ }
772
+ if (isProbe) {
773
+ this.halfOpenProbeInFlight = false;
774
+ }
775
+ }
776
+ }
777
+ async dispose() {
778
+ this.initialized = false;
779
+ }
780
+ isLoaded() {
781
+ return this.initialized;
782
+ }
783
+ claimProbeOrShortCircuit() {
784
+ if (this.circuitOpenUntil === 0) {
785
+ return "allow";
786
+ }
787
+ if (Date.now() < this.circuitOpenUntil) {
788
+ return "short_circuit";
789
+ }
790
+ if (this.halfOpenProbeInFlight) {
791
+ return "short_circuit";
792
+ }
793
+ this.halfOpenProbeInFlight = true;
794
+ log2(`[magic-context] openai-compatible embedding: circuit half-open, probing endpoint after ${this.lastFailureReason?.reason ?? "unknown failure"}`);
795
+ return "probe";
796
+ }
797
+ failure(failureClass, reason, retryable) {
798
+ return { class: failureClass, reason, retryable };
799
+ }
800
+ bodyExcerpt(body) {
801
+ const excerpt = sanitizeDiagnosticText(body).replace(/\s+/g, " ").trim().slice(0, 200);
802
+ return excerpt ? `: ${excerpt}` : "";
803
+ }
804
+ recordFailure(isProbe, failure) {
805
+ if (failure)
806
+ this.lastFailureReason = failure;
807
+ if (isProbe) {
808
+ this.circuitOpenUntil = Date.now() + OPEN_DURATION_MS;
809
+ if (!this.openLogged) {
810
+ log2(`[magic-context] openai-compatible embedding: probe failed (${failure?.reason ?? this.lastFailureReason?.reason ?? "unknown failure"}), re-opening circuit for ${OPEN_DURATION_MS / 60000}min`);
811
+ this.openLogged = true;
812
+ }
813
+ this.failureTimes = [];
814
+ return;
815
+ }
816
+ const now = Date.now();
817
+ const cutoff = now - FAILURE_WINDOW_MS;
818
+ this.failureTimes = this.failureTimes.filter((t) => t > cutoff);
819
+ this.failureTimes.push(now);
820
+ if (this.failureTimes.length >= FAILURE_THRESHOLD) {
821
+ this.circuitOpenUntil = now + OPEN_DURATION_MS;
822
+ if (!this.openLogged) {
823
+ log2(`[magic-context] openai-compatible embedding: opening circuit for ${OPEN_DURATION_MS / 60000}min after ${this.failureTimes.length} failures in ${FAILURE_WINDOW_MS / 1000}s (${failure?.reason ?? this.lastFailureReason?.reason ?? "unknown failure"})`);
824
+ this.openLogged = true;
825
+ }
826
+ this.failureTimes = [];
827
+ }
828
+ }
829
+ recordSuccess() {
830
+ if (this.failureTimes.length > 0 || this.circuitOpenUntil > 0 || this.openLogged) {
831
+ log2("[magic-context] openai-compatible embedding: endpoint recovered, circuit closed");
832
+ }
833
+ this.failureTimes = [];
834
+ this.circuitOpenUntil = 0;
835
+ this.openLogged = false;
836
+ this.lastFailureReason = null;
837
+ }
838
+ getLastFailureReason() {
839
+ return this.lastFailureReason;
840
+ }
841
+ _getCircuitState() {
842
+ if (this.circuitOpenUntil === 0)
843
+ return "closed";
844
+ if (Date.now() < this.circuitOpenUntil) {
845
+ return this.halfOpenProbeInFlight ? "half_open" : "open";
846
+ }
847
+ return "half_open";
848
+ }
849
+ _getFailureCount() {
850
+ return this.failureTimes.length;
851
+ }
852
+ _resetCircuit() {
853
+ this.failureTimes = [];
854
+ this.circuitOpenUntil = 0;
855
+ this.openLogged = false;
856
+ this.halfOpenProbeInFlight = false;
857
+ this.lastFailureReason = null;
858
+ }
859
+ }
860
+
861
+ // src/features/magic-context/session-project-storage.ts
862
+ var SESSION_CHUNK_REPAIR_BATCH_SIZE = 100;
863
+ var upsertSessionProjectStatements = new WeakMap;
864
+ var repairSessionChunkProjectStatements = new WeakMap;
865
+ var misScopedProjectChunkStatements = new WeakMap;
866
+ var MIS_SCOPED_PROJECT_CHUNK_IDS_SQL = `
867
+ SELECT e.id FROM compartment_chunk_embeddings e
868
+ JOIN session_projects sp ON sp.session_id = e.session_id AND sp.harness = e.harness
869
+ WHERE e.project_path = ? AND sp.project_path <> e.project_path
870
+ UNION ALL
871
+ SELECT e.id FROM session_projects sp
872
+ JOIN compartment_chunk_embeddings e ON e.session_id = sp.session_id
873
+ WHERE sp.project_path = ? AND e.harness = sp.harness AND e.project_path <> sp.project_path`;
874
+ function getUpsertSessionProjectStatement(db) {
875
+ let stmt = upsertSessionProjectStatements.get(db);
876
+ if (!stmt) {
877
+ stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
878
+ VALUES (?, ?, ?, ?)
879
+ ON CONFLICT(session_id, harness) DO UPDATE SET
880
+ project_path = excluded.project_path,
881
+ updated_at = excluded.updated_at
882
+ WHERE session_projects.project_path <> excluded.project_path`);
883
+ upsertSessionProjectStatements.set(db, stmt);
884
+ }
885
+ return stmt;
886
+ }
887
+ function getRepairSessionChunkProjectStatement(db) {
888
+ let stmt = repairSessionChunkProjectStatements.get(db);
889
+ if (!stmt) {
890
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
891
+ SET project_path = ?
892
+ WHERE id IN (
893
+ SELECT id
894
+ FROM compartment_chunk_embeddings
895
+ WHERE session_id = ?
896
+ AND harness = ?
897
+ AND project_path <> ?
898
+ LIMIT ?
899
+ )`);
900
+ repairSessionChunkProjectStatements.set(db, stmt);
901
+ }
902
+ return stmt;
903
+ }
904
+ function findMisScopedCompartmentChunkEmbeddingIdsForProject(db, projectPath) {
905
+ return db.prepare(`SELECT id FROM (${MIS_SCOPED_PROJECT_CHUNK_IDS_SQL}) LIMIT 25`).all(projectPath, projectPath).map(({ id }) => id);
906
+ }
907
+ function recordSessionProjectIdentity(db, sessionId, projectPath) {
908
+ if (!sessionId || !projectPath)
909
+ return;
910
+ if (!projectPath.startsWith("git:") && !projectPath.startsWith("dir:") && isUserHomeDirectory(projectPath))
911
+ return;
912
+ const harness = getHarness2();
913
+ const now = Date.now();
914
+ let previousProjectPath;
915
+ db.transaction(() => {
916
+ const existing = db.prepare("SELECT project_path FROM session_projects WHERE session_id = ? AND harness = ?").get(sessionId, harness);
917
+ previousProjectPath = existing?.project_path;
918
+ getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
919
+ getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath, SESSION_CHUNK_REPAIR_BATCH_SIZE);
920
+ }).immediate();
921
+ return previousProjectPath === projectPath ? undefined : { previousProjectPath, projectPath };
922
+ }
923
+ function hasRecordedSessionProjectIdentity(db, sessionId) {
924
+ const row = db.prepare("SELECT 1 AS found FROM session_projects WHERE session_id = ? AND harness = ?").get(sessionId, getHarness2());
925
+ return row?.found === 1;
926
+ }
927
+ function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath, ids = findMisScopedCompartmentChunkEmbeddingIdsForProject(db, projectPath)) {
928
+ if (!projectPath || ids.length === 0)
929
+ return 0;
930
+ return db.prepare(`UPDATE compartment_chunk_embeddings
931
+ SET project_path = (SELECT sp.project_path FROM session_projects sp
932
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
933
+ AND sp.harness = compartment_chunk_embeddings.harness)
934
+ WHERE id IN (${ids.map(() => "?").join(",")}) AND EXISTS (
935
+ SELECT 1 FROM session_projects sp
936
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
937
+ AND sp.harness = compartment_chunk_embeddings.harness
938
+ AND sp.project_path <> compartment_chunk_embeddings.project_path
939
+ AND (sp.project_path = ? OR compartment_chunk_embeddings.project_path = ?)
940
+ )`).run(...ids, projectPath, projectPath).changes;
941
+ }
942
+
943
+ // src/features/magic-context/shadow-backfill-state.ts
944
+ var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
945
+ function parseJsonRecord(value) {
946
+ try {
947
+ const parsed = JSON.parse(value);
948
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
949
+ } catch {
950
+ return {};
951
+ }
952
+ }
953
+ function parsePersistedShadowBackfillState(provenanceJson) {
954
+ const raw = parseJsonRecord(provenanceJson)[SHADOW_BACKFILL_PROVENANCE_KEY];
955
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw))
956
+ return;
957
+ const state = raw;
958
+ if (state.version !== 1)
959
+ return;
960
+ return state;
961
+ }
962
+ function hasShadowEmbeddingRegistrationsTable(db) {
963
+ return Boolean(db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'shadow_embedding_registrations'").get());
964
+ }
965
+ function describeShadowBackfillWriteRefusal2(reason) {
966
+ switch (reason) {
967
+ case "provider_returned_no_vectors":
968
+ return "the provider returned no vectors";
969
+ case "memory_hash_guard_rejected":
970
+ return "the memory normalized-hash guard rejected vectors because content changed in flight";
971
+ case "candidate_rows_changed":
972
+ return "the selected source rows changed before the writer loaded them";
973
+ case "registration_retired_during_embed":
974
+ return "the shadow registration was retired or replaced while the provider call was in flight, so the vectors were discarded";
975
+ case "chunk_fts_mapping_incomplete":
976
+ return "the chunk writer refused rows whose transcript ordinals are not fully mapped in FTS";
977
+ case "chunk_empty_canonical_text":
978
+ return "the chunk writer produced no canonical windows";
979
+ case "chunk_partial_vector_set":
980
+ return "the chunk writer refused a partial provider result so it would not replace a compartment incompletely";
981
+ case "chunk_window_contract_mismatch":
982
+ return "written chunk window keys or hashes did not satisfy the selector's window contract";
983
+ case "duplicate_submission_budget":
984
+ return "the same content batch was already submitted within the one-hour provider budget";
985
+ default:
986
+ return "the write completed without satisfying the selected candidate";
987
+ }
988
+ }
989
+ function listShadowBackfillStalls2(db, projectIdentity) {
990
+ if (!hasShadowEmbeddingRegistrationsTable(db))
991
+ return [];
992
+ const rows = db.prepare(`SELECT project_path AS projectIdentity, scope, model_id AS modelId,
993
+ provenance_json AS provenanceJson
994
+ FROM shadow_embedding_registrations
995
+ ${projectIdentity ? "WHERE project_path = ?" : ""}
996
+ ORDER BY updated_at DESC, generation DESC`).all(...projectIdentity ? [projectIdentity] : []);
997
+ const latestScopes = new Set;
998
+ const stalls = [];
999
+ for (const row of rows) {
1000
+ const scopeKey = `${row.projectIdentity}:${row.scope}`;
1001
+ if (latestScopes.has(scopeKey))
1002
+ continue;
1003
+ latestScopes.add(scopeKey);
1004
+ const state = parsePersistedShadowBackfillState(row.provenanceJson);
1005
+ if (state?.stopReason !== "stalled_no_progress")
1006
+ continue;
1007
+ stalls.push({
1008
+ projectIdentity: row.projectIdentity,
1009
+ scope: row.scope,
1010
+ modelId: row.modelId,
1011
+ candidateSignature: state.candidateSignature ?? "unknown",
1012
+ writeRefusalReason: state.writeRefusalReason ?? "unknown_write_rejection",
1013
+ stoppedAt: state.stoppedAt ?? 0
1014
+ });
1015
+ }
1016
+ return stalls;
1017
+ }
1018
+
1019
+ // src/features/magic-context/project-embedding-registry.ts
1020
+ var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
1021
+ var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
1022
+ var SWEEP_MAX_CONSECUTIVE_EMPTY = 3;
1023
+ var COMMIT_DRAIN_BATCH_SIZE = 16;
1024
+ var COMMIT_DRAIN_MAX_PER_SWEEP = 500;
1025
+ var CHUNK_DRAIN_BATCH_SIZE = 8;
1026
+ var CHUNK_DRAIN_MAX_PER_SWEEP = CHUNK_DRAIN_BATCH_SIZE;
1027
+ var EMBEDDING_IDENTITY_GC_GRACE_MS = 14 * 24 * 60 * 60 * 1000;
1028
+ var STALE_EMBEDDING_GC_BATCH_SIZE = 25;
1029
+ var MAX_WINDOWS_PER_EMBED_CALL = 2;
1030
+ var SESSION_EMBED_LEASE_RENEWAL_MS = 60 * 1000;
1031
+ var EMBED_SLICE_RETRY_ATTEMPTS = 3;
1032
+ var EMBED_SLICE_RETRY_BASE_MS = 250;
1033
+ var EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4;
1034
+ var MAX_CONSECUTIVE_FAILED_BATCHES = 3;
1035
+ var projectRegistrations = new Map;
1036
+ var shadowRegistrations = new Map;
1037
+ var shadowQueue = [];
1038
+ var shadowWorker = null;
1039
+ var SHADOW_MAX_ITEMS_PER_TICK = 64;
1040
+ var SHADOW_MAX_BYTES_PER_TICK = 512 * 1024;
1041
+ var SHADOW_MAX_WALL_CLOCK_MS = 2000;
1042
+ var SHADOW_RESUBMIT_WINDOW_MS = 60 * 60 * 1000;
1043
+ var SHADOW_BACKFILL_PROVENANCE_KEY2 = "_magicContextShadowBackfill";
1044
+ var pendingShadowBackfills = new Map;
1045
+ var shadowBackfillLastIds = new Map;
1046
+ var shadowBackfillStopReasons = new Map;
1047
+ var shadowBackfillLastWriteOutcomes = new Map;
1048
+ var shadowBackfillNow = () => Date.now();
1049
+ function getShadowBackfillStopReason2(projectIdentity, scope) {
1050
+ return shadowBackfillStopReasons.get(`${projectIdentity}:${scope}`);
1051
+ }
1052
+ var loadUnembeddedMemoriesStatements = new WeakMap;
1053
+ var upsertActiveIdentityStatements = new WeakMap;
1054
+ var backfillActiveIdentityStatements = new Map;
1055
+ var staleIdentityStatements = new Map;
1056
+ var deleteActiveIdentityStatements = new WeakMap;
1057
+ var globalRegistrationGeneration = 0;
1058
+ var untrustedLoadProjects = new Set;
1059
+ function markProjectLoadUntrusted2(projectIdentity) {
1060
+ untrustedLoadProjects.add(projectIdentity);
1061
+ }
1062
+ var projectSweepInProgress = false;
1063
+ var testProviderFactory = null;
1064
+
1065
+ class TestProviderFactoryRequiredError extends Error {
1066
+ constructor() {
1067
+ super("test constructed a network-capable embedding provider without a test factory — install _setTestProviderFactoryForProject or set embedding.provider off in the fixture");
1068
+ this.name = "TestProviderFactoryRequiredError";
1069
+ }
1070
+ }
1071
+ function synapseDescriptorFromConfig(config) {
1072
+ const raw = config;
1073
+ const candidate = raw.synapse_descriptor;
1074
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
1075
+ return;
1076
+ const descriptor = candidate;
1077
+ if (typeof descriptor.lane !== "string" || descriptor.lane.length === 0 || typeof descriptor.max_tokens !== "number" || !Number.isInteger(descriptor.max_tokens) || descriptor.max_tokens <= 0 || descriptor.max_tokens_source !== "runtime_bucket" && descriptor.max_tokens_source !== "worker_bucket" && descriptor.max_tokens_source !== "catalog" && descriptor.max_tokens_source !== "catalog_unloaded" || typeof descriptor.warm !== "boolean") {
1078
+ return;
1079
+ }
1080
+ return descriptor;
1081
+ }
1082
+ function synapseConfigFields(config) {
1083
+ const raw = config;
1084
+ const descriptor = synapseDescriptorFromConfig(config);
1085
+ const rawProvenance = raw.synapse_provenance;
1086
+ const provenance = descriptor ? {
1087
+ ...rawProvenance && typeof rawProvenance === "object" && !Array.isArray(rawProvenance) ? rawProvenance : rawProvenance === undefined ? {} : { synapse_provenance: rawProvenance },
1088
+ capability_descriptor: descriptor
1089
+ } : rawProvenance;
1090
+ return {
1091
+ ...typeof raw.model === "string" ? { model: raw.model } : {},
1092
+ ...typeof raw.synapse_fingerprint === "string" ? { fingerprint: raw.synapse_fingerprint } : {},
1093
+ ...typeof raw.synapse_table_epoch === "number" ? { tableEpoch: raw.synapse_table_epoch } : {},
1094
+ ...typeof raw.synapse_dims === "number" ? { dims: raw.synapse_dims } : {},
1095
+ ...provenance !== undefined ? { provenance } : {},
1096
+ ...descriptor ? { descriptor } : {}
1097
+ };
1098
+ }
1099
+ function parseJsonRecord2(value) {
1100
+ try {
1101
+ const parsed = JSON.parse(value);
1102
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : { synapse_provenance: parsed };
1103
+ } catch {
1104
+ return {};
1105
+ }
1106
+ }
1107
+ function hasShadowEmbeddingRegistrationsTable2(db) {
1108
+ return Boolean(db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'shadow_embedding_registrations'").get());
1109
+ }
1110
+ function getPersistedShadowBackfillState(db, projectIdentity, scope, modelId) {
1111
+ if (!hasShadowEmbeddingRegistrationsTable2(db))
1112
+ return;
1113
+ const row = db.prepare(`SELECT provenance_json AS provenanceJson
1114
+ FROM shadow_embedding_registrations
1115
+ WHERE project_path = ? AND scope = ? AND model_id = ?`).get(projectIdentity, scope, modelId);
1116
+ return typeof row?.provenanceJson === "string" ? parsePersistedShadowBackfillState(row.provenanceJson) : undefined;
1117
+ }
1118
+ function updatePersistedShadowBackfillState(db, projectIdentity, scope, modelId, update) {
1119
+ if (!hasShadowEmbeddingRegistrationsTable2(db))
1120
+ return;
1121
+ const row = db.prepare(`SELECT provenance_json AS provenanceJson
1122
+ FROM shadow_embedding_registrations
1123
+ WHERE project_path = ? AND scope = ? AND model_id = ?`).get(projectIdentity, scope, modelId);
1124
+ if (typeof row?.provenanceJson !== "string")
1125
+ return;
1126
+ const provenance = parseJsonRecord2(row.provenanceJson);
1127
+ const current = parsePersistedShadowBackfillState(row.provenanceJson) ?? { version: 1 };
1128
+ provenance[SHADOW_BACKFILL_PROVENANCE_KEY2] = update(current);
1129
+ db.prepare(`UPDATE shadow_embedding_registrations
1130
+ SET provenance_json = ?
1131
+ WHERE project_path = ? AND scope = ? AND model_id = ?`).run(JSON.stringify(provenance), projectIdentity, scope, modelId);
1132
+ }
1133
+ function shadowDescriptorProvenanceJson(db, projectIdentity, scope, modelId, synapseProvenance) {
1134
+ const provenance = typeof synapseProvenance === "object" && synapseProvenance !== null && !Array.isArray(synapseProvenance) ? { ...synapseProvenance } : synapseProvenance === undefined ? {} : { synapse_provenance: synapseProvenance };
1135
+ const existing = getPersistedShadowBackfillState(db, projectIdentity, scope, modelId);
1136
+ if (existing)
1137
+ provenance[SHADOW_BACKFILL_PROVENANCE_KEY2] = existing;
1138
+ return JSON.stringify(provenance);
1139
+ }
1140
+ function persistPrimaryDescriptor(db, registration) {
1141
+ const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'embedding_registrations'").get();
1142
+ if (!descriptorTable)
1143
+ return;
1144
+ const fields = synapseConfigFields(registration.config);
1145
+ db.prepare(`INSERT INTO embedding_registrations
1146
+ (project_path, provider_identity, model_id, chunk_model_id, fingerprint, table_epoch, dims, provenance_json, generation, updated_at)
1147
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1148
+ ON CONFLICT(project_path) DO UPDATE SET
1149
+ provider_identity = excluded.provider_identity,
1150
+ model_id = excluded.model_id,
1151
+ chunk_model_id = excluded.chunk_model_id,
1152
+ fingerprint = excluded.fingerprint,
1153
+ table_epoch = excluded.table_epoch,
1154
+ dims = excluded.dims,
1155
+ provenance_json = excluded.provenance_json,
1156
+ generation = excluded.generation,
1157
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, registration.providerIdentity, registration.modelId, registration.chunkModelId, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, JSON.stringify(fields.provenance ?? {}), registration.generation, Date.now());
1158
+ }
1159
+ function persistShadowDescriptor(db, registration) {
1160
+ const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'shadow_embedding_registrations'").get();
1161
+ if (!descriptorTable)
1162
+ return;
1163
+ const fields = synapseConfigFields(registration.config);
1164
+ const now = Date.now();
1165
+ db.prepare(`INSERT INTO shadow_embedding_registrations
1166
+ (project_path, scope, model_id, generation, fingerprint, table_epoch, dims, provenance_json, updated_at)
1167
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1168
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
1169
+ generation = excluded.generation,
1170
+ fingerprint = excluded.fingerprint,
1171
+ table_epoch = excluded.table_epoch,
1172
+ dims = excluded.dims,
1173
+ provenance_json = excluded.provenance_json,
1174
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, "memory", registration.modelId, registration.generation, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, shadowDescriptorProvenanceJson(db, registration.projectIdentity, "memory", registration.modelId, fields.provenance), now);
1175
+ db.prepare(`INSERT INTO shadow_embedding_registrations
1176
+ (project_path, scope, model_id, generation, fingerprint, table_epoch, dims, provenance_json, updated_at)
1177
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1178
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
1179
+ generation = excluded.generation,
1180
+ fingerprint = excluded.fingerprint,
1181
+ table_epoch = excluded.table_epoch,
1182
+ dims = excluded.dims,
1183
+ provenance_json = excluded.provenance_json,
1184
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, "commit", registration.modelId, registration.generation, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, shadowDescriptorProvenanceJson(db, registration.projectIdentity, "commit", registration.modelId, fields.provenance), now);
1185
+ db.prepare(`INSERT INTO shadow_embedding_registrations
1186
+ (project_path, scope, model_id, generation, fingerprint, table_epoch, dims, provenance_json, updated_at)
1187
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1188
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
1189
+ generation = excluded.generation,
1190
+ fingerprint = excluded.fingerprint,
1191
+ table_epoch = excluded.table_epoch,
1192
+ dims = excluded.dims,
1193
+ provenance_json = excluded.provenance_json,
1194
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, "chunk", registration.chunkModelId, registration.generation, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, shadowDescriptorProvenanceJson(db, registration.projectIdentity, "chunk", registration.chunkModelId, fields.provenance), now);
1195
+ }
1196
+ function resolveEmbeddingConfig(config) {
1197
+ if (!config || config.provider === "local") {
1198
+ return {
1199
+ provider: "local",
1200
+ model: config?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
1201
+ local_runtime: config?.local_runtime ?? "auto",
1202
+ ...config?.max_input_tokens ? {
1203
+ max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config.max_input_tokens)
1204
+ } : {},
1205
+ ...config?.local_dtype ? { local_dtype: config.local_dtype } : {}
1206
+ };
1207
+ }
1208
+ if (config.provider === "openai-compatible") {
1209
+ const apiKey = config.api_key?.trim();
1210
+ const inputType = config.input_type?.trim();
1211
+ const queryInputType = config.query_input_type?.trim();
1212
+ const truncate = config.truncate?.trim();
1213
+ return {
1214
+ provider: "openai-compatible",
1215
+ model: config.model.trim(),
1216
+ endpoint: config.endpoint.trim(),
1217
+ ...apiKey ? { api_key: apiKey } : {},
1218
+ ...inputType ? { input_type: inputType } : {},
1219
+ ...queryInputType ? { query_input_type: queryInputType } : {},
1220
+ ...config.query_instruction !== undefined ? { query_instruction: config.query_instruction } : {},
1221
+ ...config.document_prefix !== undefined ? { document_prefix: config.document_prefix } : {},
1222
+ ...truncate ? { truncate } : {},
1223
+ ...config.max_input_tokens ? {
1224
+ max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config.max_input_tokens)
1225
+ } : {}
1226
+ };
1227
+ }
1228
+ if (config.provider === "off") {
1229
+ return { provider: "off" };
1230
+ }
1231
+ if (config.provider === "synapse") {
1232
+ const synapse = config;
1233
+ const descriptor = synapseDescriptorFromConfig(config);
1234
+ return {
1235
+ provider: "synapse",
1236
+ model: synapse.model?.trim() || "gte-modernbert-base-f16",
1237
+ max_input_tokens: normalizeCompartmentChunkMaxInputTokens(descriptor?.max_tokens ?? synapse.max_input_tokens),
1238
+ ...synapse.synapse_connection_file ? { synapse_connection_file: synapse.synapse_connection_file } : {},
1239
+ ...synapse.synapse_fingerprint ? { synapse_fingerprint: synapse.synapse_fingerprint } : {},
1240
+ ...typeof synapse.synapse_table_epoch === "number" ? { synapse_table_epoch: synapse.synapse_table_epoch } : {},
1241
+ ...typeof synapse.synapse_dims === "number" ? { synapse_dims: synapse.synapse_dims } : {},
1242
+ ...typeof synapse.synapse_recommended_batch === "number" ? { synapse_recommended_batch: synapse.synapse_recommended_batch } : {},
1243
+ ...typeof synapse.synapse_recommended_token_budget === "number" ? {
1244
+ synapse_recommended_token_budget: synapse.synapse_recommended_token_budget
1245
+ } : {},
1246
+ ...descriptor ? { synapse_descriptor: descriptor } : {},
1247
+ ...synapse.synapse_provenance !== undefined ? { synapse_provenance: synapse.synapse_provenance } : {}
1248
+ };
1249
+ }
1250
+ throw new Error("Unknown embedding provider");
1251
+ }
1252
+ function createProvider(config, context) {
1253
+ if (config.provider === "off") {
1254
+ return null;
1255
+ }
1256
+ if (testProviderFactory) {
1257
+ return testProviderFactory(config);
1258
+ }
1259
+ if (process.env.MAGIC_CONTEXT_TEST_DATA_DIR?.trim()) {
1260
+ throw new TestProviderFactoryRequiredError;
1261
+ }
1262
+ if (config.provider === "openai-compatible") {
1263
+ return new OpenAICompatibleEmbeddingProvider({
1264
+ endpoint: config.endpoint,
1265
+ model: config.model,
1266
+ apiKey: config.api_key,
1267
+ inputType: config.input_type,
1268
+ queryInputType: config.query_input_type,
1269
+ queryInstruction: config.query_instruction,
1270
+ documentPrefix: config.document_prefix,
1271
+ truncate: config.truncate,
1272
+ maxInputTokens: config.max_input_tokens
1273
+ });
1274
+ }
1275
+ if (config.provider === "local") {
1276
+ return new LocalEmbeddingProvider(config.model, config.max_input_tokens, config.local_dtype, config.local_runtime);
1277
+ }
1278
+ if (config.provider === "synapse") {
1279
+ const synapse = config;
1280
+ return new SynapseEmbeddingProvider({
1281
+ connectionFile: synapse.synapse_connection_file ?? "",
1282
+ projectRoot: context?.projectRoot ?? "",
1283
+ session: context?.session ?? "embedding",
1284
+ model: synapse.model,
1285
+ fingerprint: synapse.synapse_fingerprint,
1286
+ tableEpoch: synapse.synapse_table_epoch,
1287
+ dims: synapse.synapse_dims,
1288
+ recommendedBatch: synapse.synapse_recommended_batch,
1289
+ recommendedTokenBudget: synapse.synapse_recommended_token_budget,
1290
+ descriptor: synapse.synapse_descriptor,
1291
+ provenance: synapse.synapse_provenance
1292
+ });
1293
+ }
1294
+ throw new Error("Unknown embedding provider");
1295
+ }
1296
+ function stableStringify(value) {
1297
+ if (Array.isArray(value)) {
1298
+ return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
1299
+ }
1300
+ if (value && typeof value === "object") {
1301
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
1302
+ return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
1303
+ }
1304
+ return JSON.stringify(value);
1305
+ }
1306
+ function sha256Prefix(value, length = 16) {
1307
+ return createHash2("sha256").update(value).digest("hex").slice(0, length);
1308
+ }
1309
+ function contentSha2562(value) {
1310
+ return createHash2("sha256").update(value).digest("hex");
1311
+ }
1312
+ function getRuntimeFingerprint(config) {
1313
+ if (config.provider === "off") {
1314
+ return OFF_PROVIDER_IDENTITY;
1315
+ }
1316
+ return `${getEmbeddingProviderIdentity(config)}:${sha256Prefix(stableStringify(config))}`;
1317
+ }
1318
+ function getChunkEmbeddingModelId(config, providerIdentity) {
1319
+ if (config.provider === "off") {
1320
+ return OFF_PROVIDER_IDENTITY;
1321
+ }
1322
+ const chunkIdentity = {
1323
+ providerIdentity,
1324
+ chunkerVersion: 2,
1325
+ maxInputTokens: normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in config ? config.max_input_tokens : undefined),
1326
+ truncate: config.provider === "openai-compatible" ? config.truncate ?? "" : ""
1327
+ };
1328
+ return `${providerIdentity}:chunk:${sha256Prefix(stableStringify(chunkIdentity))}`;
1329
+ }
1330
+ function sameFeatures(a, b) {
1331
+ return a.memoryEnabled === b.memoryEnabled && a.gitCommitEnabled === b.gitCommitEnabled;
1332
+ }
1333
+ function snapshotFor(registration) {
1334
+ const providerIsOn = registration.providerIdentity !== OFF_PROVIDER_IDENTITY;
1335
+ const historyEnabled = !registration.observationMode && providerIsOn;
1336
+ const enabled = historyEnabled && registration.features.memoryEnabled;
1337
+ const gitCommitEnabled = !registration.observationMode && providerIsOn && registration.features.gitCommitEnabled;
1338
+ const configuredModel = "model" in registration.config && typeof registration.config.model === "string" ? registration.config.model.trim() : "";
1339
+ const synapseDescriptor = !registration.observationMode && registration.config.provider === "synapse" ? synapseDescriptorFromConfig(registration.config) : undefined;
1340
+ return {
1341
+ projectIdentity: registration.projectIdentity,
1342
+ sourceDirectory: registration.sourceDirectory,
1343
+ providerIdentity: registration.providerIdentity,
1344
+ runtimeFingerprint: registration.runtimeFingerprint,
1345
+ generation: registration.generation,
1346
+ features: { ...registration.features },
1347
+ enabled,
1348
+ historyEnabled,
1349
+ gitCommitEnabled,
1350
+ modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
1351
+ chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
1352
+ model: registration.observationMode || !providerIsOn ? "off" : configuredModel ? configuredModel : registration.modelId,
1353
+ provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local",
1354
+ ...synapseDescriptor ? { synapseDescriptor } : {}
1355
+ };
1356
+ }
1357
+ function disposeProvider(provider) {
1358
+ if (!provider)
1359
+ return;
1360
+ provider.dispose().catch((error) => {
1361
+ log2("[magic-context] embedding provider dispose failed:", error);
1362
+ });
1363
+ }
1364
+ function getUpsertActiveIdentityStatement(db) {
1365
+ let stmt = upsertActiveIdentityStatements.get(db);
1366
+ if (!stmt) {
1367
+ stmt = db.prepare(`INSERT INTO embedding_identity_active (project_path, scope, model_id, last_active_at)
1368
+ VALUES (?, ?, ?, ?)
1369
+ ON CONFLICT(project_path, scope, model_id) DO UPDATE SET
1370
+ last_active_at = excluded.last_active_at`);
1371
+ upsertActiveIdentityStatements.set(db, stmt);
1372
+ }
1373
+ return stmt;
1374
+ }
1375
+ function statementMapFor(maps, key) {
1376
+ let map = maps.get(key);
1377
+ if (!map) {
1378
+ map = new WeakMap;
1379
+ maps.set(key, map);
1380
+ }
1381
+ return map;
1382
+ }
1383
+ function getBackfillActiveIdentityStatement(db, scope) {
1384
+ const map = statementMapFor(backfillActiveIdentityStatements, scope);
1385
+ let stmt = map.get(db);
1386
+ if (!stmt) {
1387
+ const selectByScope = {
1388
+ memory: `SELECT DISTINCT e.model_id AS model_id
1389
+ FROM memory_embeddings e
1390
+ JOIN memories m ON m.id = e.memory_id
1391
+ WHERE m.project_path = ?`,
1392
+ commit: `SELECT DISTINCT e.model_id AS model_id
1393
+ FROM git_commit_embeddings e
1394
+ JOIN git_commits c ON c.sha = e.sha
1395
+ WHERE c.project_path = ?`,
1396
+ chunk: `SELECT DISTINCT e.model_id AS model_id
1397
+ FROM compartment_chunk_embeddings e
1398
+ WHERE e.project_path = ?`
1399
+ };
1400
+ stmt = db.prepare(`SELECT model_id FROM (${selectByScope[scope]}) legacy
1401
+ WHERE model_id IS NOT NULL AND NOT EXISTS (
1402
+ SELECT 1 FROM embedding_identity_active active
1403
+ WHERE active.project_path = ? AND active.scope = ?
1404
+ AND active.model_id = legacy.model_id
1405
+ ) LIMIT 25`);
1406
+ map.set(db, stmt);
1407
+ }
1408
+ return stmt;
1409
+ }
1410
+ function recordScopeActiveIdentity(db, projectIdentity, scope, modelId, now) {
1411
+ getUpsertActiveIdentityStatement(db).run(projectIdentity, scope, modelId, now);
1412
+ }
1413
+ var legacyDiscoveryComplete = new WeakMap;
1414
+ function recordActiveEmbeddingIdentity(db, projectIdentity, currentProviderIdentity, currentChunkIdentity, features) {
1415
+ if (currentProviderIdentity === OFF_PROVIDER_IDENTITY) {
1416
+ return false;
1417
+ }
1418
+ const scopes = [["chunk", currentChunkIdentity]];
1419
+ if (features.memoryEnabled)
1420
+ scopes.push(["memory", currentProviderIdentity]);
1421
+ if (features.gitCommitEnabled)
1422
+ scopes.push(["commit", currentProviderIdentity]);
1423
+ const active = db.prepare("SELECT 1 FROM embedding_identity_active WHERE project_path = ? AND scope = ? AND model_id = ?");
1424
+ let discovered = legacyDiscoveryComplete.get(db);
1425
+ if (!discovered) {
1426
+ discovered = new Set;
1427
+ legacyDiscoveryComplete.set(db, discovered);
1428
+ }
1429
+ const discoveryKey = (scope, model) => JSON.stringify([projectIdentity, scope, model]);
1430
+ const legacy = scopes.filter(([scope, model]) => !discovered.has(discoveryKey(scope, model)) || !active.get(projectIdentity, scope, model)).map(([scope, model]) => ({
1431
+ scope,
1432
+ model,
1433
+ rows: getBackfillActiveIdentityStatement(db, scope).all(projectIdentity, projectIdentity, scope)
1434
+ }));
1435
+ const repairIds = findMisScopedCompartmentChunkEmbeddingIdsForProject(db, projectIdentity);
1436
+ if (legacy.every(({ rows }) => rows.length === 0) && scopes.every(([scope, model]) => active.get(projectIdentity, scope, model)) && repairIds.length === 0) {
1437
+ for (const { scope, model } of legacy)
1438
+ discovered.add(discoveryKey(scope, model));
1439
+ return false;
1440
+ }
1441
+ const now = Date.now();
1442
+ db.exec("BEGIN IMMEDIATE");
1443
+ const transactionStartedAt = performance.now();
1444
+ try {
1445
+ if (features.memoryEnabled) {
1446
+ recordScopeActiveIdentity(db, projectIdentity, "memory", currentProviderIdentity, now);
1447
+ }
1448
+ if (features.gitCommitEnabled) {
1449
+ recordScopeActiveIdentity(db, projectIdentity, "commit", currentProviderIdentity, now);
1450
+ }
1451
+ for (const { scope, rows } of legacy) {
1452
+ for (const { model_id } of rows) {
1453
+ db.prepare(`INSERT OR IGNORE INTO embedding_identity_active
1454
+ (project_path, scope, model_id, last_active_at) VALUES (?, ?, ?, ?)`).run(projectIdentity, scope, model_id, now);
1455
+ }
1456
+ }
1457
+ repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectIdentity, repairIds);
1458
+ recordScopeActiveIdentity(db, projectIdentity, "chunk", currentChunkIdentity, now);
1459
+ db.exec("COMMIT");
1460
+ logSlowWriteTransaction("embedding_identity_record", transactionStartedAt);
1461
+ for (const { scope, model, rows } of legacy) {
1462
+ if (rows.length < 25)
1463
+ discovered.add(discoveryKey(scope, model));
1464
+ }
1465
+ return true;
1466
+ } catch (error) {
1467
+ try {
1468
+ db.exec("ROLLBACK");
1469
+ } catch {}
1470
+ throw error;
1471
+ }
1472
+ }
1473
+ function getStaleIdentityStatement(db, scope) {
1474
+ const map = statementMapFor(staleIdentityStatements, scope);
1475
+ let stmt = map.get(db);
1476
+ if (!stmt) {
1477
+ stmt = db.prepare(`SELECT model_id AS modelId
1478
+ FROM embedding_identity_active
1479
+ WHERE project_path = ?
1480
+ AND scope = ?
1481
+ AND model_id <> ?
1482
+ AND last_active_at < ?`);
1483
+ map.set(db, stmt);
1484
+ }
1485
+ return stmt;
1486
+ }
1487
+ function getDeleteActiveIdentityStatement(db) {
1488
+ let stmt = deleteActiveIdentityStatements.get(db);
1489
+ if (!stmt) {
1490
+ stmt = db.prepare(`DELETE FROM embedding_identity_active
1491
+ WHERE project_path = ? AND scope = ? AND model_id = ?`);
1492
+ deleteActiveIdentityStatements.set(db, stmt);
1493
+ }
1494
+ return stmt;
1495
+ }
1496
+ function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModelIds = new Set([currentModelId])) {
1497
+ const rows = getStaleIdentityStatement(db, scope).all(projectIdentity, scope, currentModelId, cutoff);
1498
+ return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string" && !protectedModelIds.has(modelId));
1499
+ }
1500
+ function deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, limit) {
1501
+ if (scope === "memory") {
1502
+ return db.prepare(`DELETE FROM memory_embeddings
1503
+ WHERE rowid IN (
1504
+ SELECT me.rowid
1505
+ FROM memory_embeddings me
1506
+ WHERE me.memory_id IN (SELECT id FROM memories WHERE project_path = ?)
1507
+ AND me.model_id = ?
1508
+ LIMIT ?
1509
+ )`).run(projectIdentity, modelId, limit).changes;
1510
+ }
1511
+ if (scope === "commit") {
1512
+ return db.prepare(`DELETE FROM git_commit_embeddings
1513
+ WHERE rowid IN (
1514
+ SELECT gce.rowid
1515
+ FROM git_commit_embeddings gce
1516
+ WHERE gce.sha IN (SELECT sha FROM git_commits WHERE project_path = ?)
1517
+ AND gce.model_id = ?
1518
+ LIMIT ?
1519
+ )`).run(projectIdentity, modelId, limit).changes;
1520
+ }
1521
+ return db.prepare(`DELETE FROM compartment_chunk_embeddings
1522
+ WHERE id IN (
1523
+ SELECT id
1524
+ FROM compartment_chunk_embeddings
1525
+ WHERE project_path = ? AND model_id = ?
1526
+ LIMIT ?
1527
+ )`).run(projectIdentity, modelId, limit).changes;
1528
+ }
1529
+ function hasStaleEmbeddingRows(db, scope, projectIdentity, modelId) {
1530
+ if (scope === "memory") {
1531
+ return Boolean(db.prepare(`SELECT 1
1532
+ FROM memory_embeddings me
1533
+ WHERE me.memory_id IN (SELECT id FROM memories WHERE project_path = ?)
1534
+ AND me.model_id = ?
1535
+ LIMIT 1`).get(projectIdentity, modelId));
1536
+ }
1537
+ if (scope === "commit") {
1538
+ return Boolean(db.prepare(`SELECT 1
1539
+ FROM git_commit_embeddings gce
1540
+ WHERE gce.sha IN (SELECT sha FROM git_commits WHERE project_path = ?)
1541
+ AND gce.model_id = ?
1542
+ LIMIT 1`).get(projectIdentity, modelId));
1543
+ }
1544
+ return Boolean(db.prepare(`SELECT 1
1545
+ FROM compartment_chunk_embeddings
1546
+ WHERE project_path = ? AND model_id = ?
1547
+ LIMIT 1`).get(projectIdentity, modelId));
1548
+ }
1549
+ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date.now()) {
1550
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
1551
+ const result = {
1552
+ memoryRowsDeleted: 0,
1553
+ commitRowsDeleted: 0,
1554
+ chunkRowsDeleted: 0,
1555
+ trackingRowsDeleted: 0
1556
+ };
1557
+ if (!snapshot)
1558
+ return result;
1559
+ if (untrustedLoadProjects.has(projectIdentity))
1560
+ return result;
1561
+ const cutoff = now - EMBEDDING_IDENTITY_GC_GRACE_MS;
1562
+ const deleteTracking = getDeleteActiveIdentityStatement(db);
1563
+ const shadow = shadowRegistrations.get(projectIdentity);
1564
+ const protectedModels = {
1565
+ memory: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
1566
+ commit: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
1567
+ chunk: new Set([snapshot.chunkModelId, ...shadow ? [shadow.chunkModelId] : []])
1568
+ };
1569
+ const scopes = [
1570
+ {
1571
+ scope: "memory",
1572
+ enabled: snapshot.enabled && snapshot.modelId !== "off",
1573
+ currentModelId: snapshot.modelId
1574
+ },
1575
+ {
1576
+ scope: "commit",
1577
+ enabled: snapshot.gitCommitEnabled && snapshot.modelId !== "off",
1578
+ currentModelId: snapshot.modelId
1579
+ },
1580
+ {
1581
+ scope: "chunk",
1582
+ enabled: snapshot.historyEnabled && snapshot.chunkModelId !== "off",
1583
+ currentModelId: snapshot.chunkModelId
1584
+ }
1585
+ ];
1586
+ let remainingBudget = STALE_EMBEDDING_GC_BATCH_SIZE;
1587
+ const candidates = scopes.flatMap(({ scope, enabled, currentModelId }) => enabled ? staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModels[scope]).slice(0, STALE_EMBEDDING_GC_BATCH_SIZE).map((modelId) => ({ scope, modelId })) : []).slice(0, STALE_EMBEDDING_GC_BATCH_SIZE);
1588
+ if (candidates.length === 0)
1589
+ return result;
1590
+ db.exec("BEGIN IMMEDIATE");
1591
+ const transactionStartedAt = performance.now();
1592
+ try {
1593
+ for (const { scope, modelId } of candidates) {
1594
+ if (remainingBudget === 0)
1595
+ break;
1596
+ const marker = db.prepare(`SELECT last_active_at FROM embedding_identity_active
1597
+ WHERE project_path = ? AND scope = ? AND model_id = ?`).get(projectIdentity, scope, modelId);
1598
+ if (!marker || marker.last_active_at >= cutoff)
1599
+ continue;
1600
+ const deleted = deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, remainingBudget);
1601
+ remainingBudget -= deleted;
1602
+ if (scope === "memory")
1603
+ result.memoryRowsDeleted += deleted;
1604
+ else if (scope === "commit")
1605
+ result.commitRowsDeleted += deleted;
1606
+ else
1607
+ result.chunkRowsDeleted += deleted;
1608
+ if (!hasStaleEmbeddingRows(db, scope, projectIdentity, modelId)) {
1609
+ result.trackingRowsDeleted += deleteTracking.run(projectIdentity, scope, modelId).changes;
1610
+ } else if (deleted === 0) {
1611
+ remainingBudget = 0;
1612
+ }
1613
+ }
1614
+ db.exec("COMMIT");
1615
+ logSlowWriteTransaction("embedding_stale_gc", transactionStartedAt);
1616
+ } catch (error) {
1617
+ try {
1618
+ db.exec("ROLLBACK");
1619
+ } catch {}
1620
+ throw error;
1621
+ }
1622
+ if (result.memoryRowsDeleted > 0)
1623
+ invalidateProject2(projectIdentity);
1624
+ return result;
1625
+ }
1626
+ async function drainProjectEmbeddingIdentityMaintenance2(db, projectIdentity, budgetMs = 2000) {
1627
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
1628
+ if (!snapshot || untrustedLoadProjects.has(projectIdentity))
1629
+ return 0;
1630
+ return drainBackgroundBatches(() => recordActiveEmbeddingIdentity(db, projectIdentity, snapshot.modelId, snapshot.chunkModelId, { memoryEnabled: snapshot.enabled, gitCommitEnabled: snapshot.gitCommitEnabled }), { budgetMs });
1631
+ }
1632
+ async function drainStaleEmbeddingIdentitiesForProject2(db, projectIdentity, budgetMs = 2000) {
1633
+ const total = {
1634
+ memoryRowsDeleted: 0,
1635
+ commitRowsDeleted: 0,
1636
+ chunkRowsDeleted: 0,
1637
+ trackingRowsDeleted: 0
1638
+ };
1639
+ await drainBackgroundBatches(() => {
1640
+ const result = sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity);
1641
+ total.memoryRowsDeleted += result.memoryRowsDeleted;
1642
+ total.commitRowsDeleted += result.commitRowsDeleted;
1643
+ total.chunkRowsDeleted += result.chunkRowsDeleted;
1644
+ total.trackingRowsDeleted += result.trackingRowsDeleted;
1645
+ return result.memoryRowsDeleted + result.commitRowsDeleted + result.chunkRowsDeleted + result.trackingRowsDeleted > 0;
1646
+ }, { budgetMs });
1647
+ return total;
1648
+ }
1649
+ function registerProjectEmbedding2(db, projectIdentity, config, features, sourceDirectory) {
1650
+ const resolvedConfig = resolveEmbeddingConfig(config);
1651
+ const providerIdentity = getEmbeddingProviderIdentity(resolvedConfig);
1652
+ const runtimeFingerprint = getRuntimeFingerprint(resolvedConfig);
1653
+ const chunkModelId = getChunkEmbeddingModelId(resolvedConfig, providerIdentity);
1654
+ const prior = projectRegistrations.get(projectIdentity);
1655
+ const canReuseProvider = prior !== undefined && !prior.observationMode && prior.runtimeFingerprint === runtimeFingerprint && prior.providerIdentity === providerIdentity;
1656
+ recordActiveEmbeddingIdentity(db, projectIdentity, providerIdentity, chunkModelId, features);
1657
+ pruneSynapseBatchLedgerForProject(db, projectIdentity);
1658
+ untrustedLoadProjects.delete(projectIdentity);
1659
+ const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || prior.chunkModelId !== chunkModelId || !sameFeatures(prior.features, features);
1660
+ const generation = generationChanged ? ++globalRegistrationGeneration : prior.generation;
1661
+ const registration = {
1662
+ projectIdentity,
1663
+ sourceDirectory,
1664
+ config: resolvedConfig,
1665
+ providerIdentity,
1666
+ runtimeFingerprint,
1667
+ provider: canReuseProvider ? prior.provider : null,
1668
+ generation,
1669
+ features: { ...features },
1670
+ modelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : providerIdentity,
1671
+ chunkModelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : chunkModelId,
1672
+ observationMode: false
1673
+ };
1674
+ projectRegistrations.set(projectIdentity, registration);
1675
+ if (generationChanged || !db.prepare("SELECT 1 FROM embedding_registrations WHERE project_path = ? AND provider_identity = ? AND chunk_model_id = ? AND generation = ?").get(projectIdentity, providerIdentity, registration.chunkModelId, generation)) {
1676
+ persistPrimaryDescriptor(db, registration);
1677
+ }
1678
+ if (!canReuseProvider) {
1679
+ disposeProvider(prior?.provider ?? null);
1680
+ }
1681
+ return snapshotFor(registration);
1682
+ }
1683
+ function registerProjectShadowEmbedding2(db, projectIdentity, config, sourceDirectory, options = {}) {
1684
+ const resolvedConfig = resolveEmbeddingConfig(config);
1685
+ if (resolvedConfig.provider !== "synapse") {
1686
+ throw new Error("Shadow embedding registration requires the synapse provider");
1687
+ }
1688
+ const providerIdentity = getEmbeddingProviderIdentity(resolvedConfig);
1689
+ const chunkModelId = getChunkEmbeddingModelId(resolvedConfig, providerIdentity);
1690
+ const provider = createProvider(resolvedConfig, {
1691
+ projectRoot: sourceDirectory,
1692
+ session: `shadow:${projectIdentity}`
1693
+ });
1694
+ if (!provider)
1695
+ return null;
1696
+ const prior = shadowRegistrations.get(projectIdentity);
1697
+ if (prior && prior.providerIdentity === providerIdentity) {
1698
+ provider.dispose();
1699
+ dbForShadowQueue.set(projectIdentity, db);
1700
+ persistShadowDescriptor(db, prior);
1701
+ const backfillAlreadyArmed = hasPendingShadowBackfill(projectIdentity) || shadowQueue.some((item) => item.projectIdentity === projectIdentity);
1702
+ if (!backfillAlreadyArmed || options.manualBackfill === true) {
1703
+ maybeArmShadowBackfill(db, projectIdentity, prior, options.manualBackfill === true);
1704
+ }
1705
+ return {
1706
+ ...snapshotFor({
1707
+ projectIdentity,
1708
+ sourceDirectory,
1709
+ config: prior.config,
1710
+ providerIdentity: prior.providerIdentity,
1711
+ runtimeFingerprint: `shadow:${prior.providerIdentity}`,
1712
+ provider: prior.provider,
1713
+ generation: prior.generation,
1714
+ features: { memoryEnabled: true, gitCommitEnabled: true },
1715
+ modelId: prior.modelId,
1716
+ chunkModelId: prior.chunkModelId,
1717
+ observationMode: false
1718
+ }),
1719
+ provider: "synapse"
1720
+ };
1721
+ }
1722
+ const generation = ++globalRegistrationGeneration;
1723
+ const registration = {
1724
+ projectIdentity,
1725
+ sourceDirectory,
1726
+ config: resolvedConfig,
1727
+ provider,
1728
+ providerIdentity,
1729
+ modelId: providerIdentity,
1730
+ chunkModelId,
1731
+ generation
1732
+ };
1733
+ shadowRegistrations.set(projectIdentity, registration);
1734
+ dbForShadowQueue.set(projectIdentity, db);
1735
+ if (prior) {
1736
+ disposeProvider(prior.provider);
1737
+ for (const scope of ["memory", "commit", "chunk"]) {
1738
+ const scopeKey = `${projectIdentity}:${scope}`;
1739
+ shadowBackfillLastIds.delete(scopeKey);
1740
+ shadowBackfillStopReasons.delete(scopeKey);
1741
+ shadowBackfillLastWriteOutcomes.delete(scopeKey);
1742
+ }
1743
+ }
1744
+ db.transaction(() => {
1745
+ const now = Date.now();
1746
+ recordScopeActiveIdentity(db, projectIdentity, "memory", registration.modelId, now);
1747
+ recordScopeActiveIdentity(db, projectIdentity, "commit", registration.modelId, now);
1748
+ recordScopeActiveIdentity(db, projectIdentity, "chunk", registration.chunkModelId, now);
1749
+ persistShadowDescriptor(db, registration);
1750
+ }).immediate();
1751
+ maybeArmShadowBackfill(db, projectIdentity, registration, options.manualBackfill === true);
1752
+ return {
1753
+ projectIdentity,
1754
+ sourceDirectory,
1755
+ providerIdentity,
1756
+ runtimeFingerprint: `shadow:${providerIdentity}`,
1757
+ generation,
1758
+ features: { memoryEnabled: true, gitCommitEnabled: true },
1759
+ enabled: true,
1760
+ historyEnabled: true,
1761
+ gitCommitEnabled: true,
1762
+ modelId: registration.modelId,
1763
+ chunkModelId: registration.chunkModelId,
1764
+ model: "model" in resolvedConfig && typeof resolvedConfig.model === "string" ? resolvedConfig.model : registration.modelId,
1765
+ provider: "synapse",
1766
+ ...synapseDescriptorFromConfig(resolvedConfig) ? { synapseDescriptor: synapseDescriptorFromConfig(resolvedConfig) } : {}
1767
+ };
1768
+ }
1769
+ function startShadowWorker() {
1770
+ if (shadowWorker)
1771
+ return;
1772
+ shadowWorker = runShadowWorker().finally(() => {
1773
+ shadowWorker = null;
1774
+ if (shadowQueue.length > 0 || hasPendingShadowBackfill())
1775
+ startShadowWorker();
1776
+ });
1777
+ }
1778
+ function getShadowEmbeddingMeasurementCohort2(projectIdentity) {
1779
+ const registration = shadowRegistrations.get(projectIdentity);
1780
+ if (!registration)
1781
+ return null;
1782
+ const fields = synapseConfigFields(registration.config);
1783
+ return {
1784
+ modelId: registration.modelId,
1785
+ chunkModelId: registration.chunkModelId,
1786
+ fingerprint: fields.fingerprint ?? "",
1787
+ epoch: fields.tableEpoch ?? 0,
1788
+ dims: fields.dims ?? 0
1789
+ };
1790
+ }
1791
+ function getPrimaryEmbeddingMeasurementCohort2(projectIdentity) {
1792
+ const registration = projectRegistrations.get(projectIdentity);
1793
+ if (!registration)
1794
+ return null;
1795
+ const fields = synapseConfigFields(registration.config);
1796
+ return {
1797
+ modelId: registration.modelId,
1798
+ chunkModelId: registration.chunkModelId,
1799
+ fingerprint: fields.fingerprint ?? "",
1800
+ epoch: fields.tableEpoch ?? 0,
1801
+ dims: fields.dims ?? 0
1802
+ };
1803
+ }
1804
+ async function embedShadowTextForProject2(projectIdentity, text, signal) {
1805
+ const registration = shadowRegistrations.get(projectIdentity);
1806
+ if (!registration)
1807
+ return null;
1808
+ try {
1809
+ const vector = await registration.provider.embed(text, signal, "query");
1810
+ return vector && !isSynapseEmbeddingTruncated(vector) ? vector : null;
1811
+ } catch (error) {
1812
+ log2("[magic-context] Synapse shadow query failed:", error);
1813
+ return null;
1814
+ }
1815
+ }
1816
+ function enqueueShadowEmbeddingItems2(projectIdentity, scope, ids) {
1817
+ if (ids.length === 0 || !shadowRegistrations.has(projectIdentity))
1818
+ return;
1819
+ shadowQueue.push({ projectIdentity, scope, ids: [...ids] });
1820
+ startShadowWorker();
1821
+ }
1822
+ function shadowBackfillMissingBase(scope, primaryModelId, shadowModelId, projectIdentity) {
1823
+ if (scope === "memory") {
1824
+ return {
1825
+ sql: `SELECT m.id AS id
1826
+ FROM memories m
1827
+ JOIN memory_embeddings mp ON mp.memory_id = m.id AND mp.model_id = ?
1828
+ LEFT JOIN memory_embeddings ms ON ms.memory_id = m.id AND ms.model_id = ?
1829
+ WHERE m.project_path = ? AND m.status = 'active' AND ms.memory_id IS NULL`,
1830
+ params: [primaryModelId, shadowModelId, projectIdentity],
1831
+ orderBy: " ORDER BY m.id"
1832
+ };
1833
+ }
1834
+ return {
1835
+ sql: `SELECT gc.sha AS id
1836
+ FROM git_commits gc
1837
+ JOIN git_commit_embeddings gp ON gp.sha = gc.sha AND gp.model_id = ?
1838
+ LEFT JOIN git_commit_embeddings gs ON gs.sha = gc.sha AND gs.model_id = ?
1839
+ WHERE gc.project_path = ? AND gs.sha IS NULL`,
1840
+ params: [primaryModelId, shadowModelId, projectIdentity],
1841
+ orderBy: " ORDER BY gc.committed_at DESC, gc.sha"
1842
+ };
1843
+ }
1844
+ function shadowBackfillMissingIds(db, projectIdentity, scope, primaryModelId, shadowModelId, limit, shadowMaxInputTokens) {
1845
+ if (scope === "chunk") {
1846
+ return loadUnembeddedShadowChunkCandidates(db, projectIdentity, primaryModelId, shadowModelId, limit, shadowMaxInputTokens).map((candidate) => String(candidate.id));
1847
+ }
1848
+ const { sql, params, orderBy } = shadowBackfillMissingBase(scope, primaryModelId, shadowModelId, projectIdentity);
1849
+ const rows = db.prepare(`${sql}${orderBy} LIMIT ?`).all(...params, limit);
1850
+ return rows.map((row) => String(row.id));
1851
+ }
1852
+ function countShadowBackfillMissing(db, projectIdentity, scope, primaryModelId, shadowModelId, shadowMaxInputTokens) {
1853
+ if (scope === "chunk") {
1854
+ return loadUnembeddedShadowChunkCandidates(db, projectIdentity, primaryModelId, shadowModelId, Number.MAX_SAFE_INTEGER, shadowMaxInputTokens).length;
1855
+ }
1856
+ const { sql, params } = shadowBackfillMissingBase(scope, primaryModelId, shadowModelId, projectIdentity);
1857
+ return db.prepare(`SELECT COUNT(*) AS count FROM (${sql})`).get(...params).count;
1858
+ }
1859
+ function shadowModelIdForScope(registration, scope) {
1860
+ return scope === "chunk" ? registration.chunkModelId : registration.modelId;
1861
+ }
1862
+ function shadowMaxInputTokensFor(registration) {
1863
+ return normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in registration.config ? registration.config.max_input_tokens : undefined);
1864
+ }
1865
+ function shadowBackfillCohortFingerprint(db, projectIdentity, scope, primaryModelId) {
1866
+ if (scope === "memory") {
1867
+ return db.prepare(`SELECT COUNT(*) AS rowCount, MAX(m.id) AS maxId, MAX(m.updated_at) AS maxUpdatedAt
1868
+ FROM memories m
1869
+ JOIN memory_embeddings me ON me.memory_id = m.id AND me.model_id = ?
1870
+ WHERE m.project_path = ? AND m.status = 'active'`).get(primaryModelId, projectIdentity);
1871
+ }
1872
+ if (scope === "commit") {
1873
+ return db.prepare(`SELECT COUNT(*) AS rowCount, MAX(gc.sha) AS maxId, MAX(gc.committed_at) AS maxUpdatedAt
1874
+ FROM git_commits gc
1875
+ JOIN git_commit_embeddings gce ON gce.sha = gc.sha AND gce.model_id = ?
1876
+ WHERE gc.project_path = ?`).get(primaryModelId, projectIdentity);
1877
+ }
1878
+ return db.prepare(`SELECT COUNT(*) AS rowCount,
1879
+ COUNT(DISTINCT compartment_id) AS compartmentCount,
1880
+ MAX(compartment_id) AS maxId,
1881
+ MAX(created_at) AS maxUpdatedAt
1882
+ FROM compartment_chunk_embeddings
1883
+ WHERE project_path = ? AND model_id = ?`).get(projectIdentity, primaryModelId);
1884
+ }
1885
+ function shadowBackfillCandidateBatch(db, projectIdentity, scope, primaryModelId, shadow, limit) {
1886
+ const shadowModelId = shadowModelIdForScope(shadow, scope);
1887
+ const ids = shadowBackfillMissingIds(db, projectIdentity, scope, primaryModelId, shadowModelId, limit, shadowMaxInputTokensFor(shadow));
1888
+ return {
1889
+ ids,
1890
+ signature: sha256Prefix(stableStringify({
1891
+ scope,
1892
+ primaryModelId,
1893
+ shadowModelId,
1894
+ ids,
1895
+ cohort: shadowBackfillCohortFingerprint(db, projectIdentity, scope, primaryModelId)
1896
+ }), 32)
1897
+ };
1898
+ }
1899
+ function hasPendingShadowBackfill(projectIdentity) {
1900
+ if (projectIdentity === undefined)
1901
+ return pendingShadowBackfills.size > 0;
1902
+ const scopes = pendingShadowBackfills.get(projectIdentity);
1903
+ return scopes !== undefined && scopes.size > 0;
1904
+ }
1905
+ function pumpShadowBackfill() {
1906
+ for (const [projectIdentity, scopes] of pendingShadowBackfills) {
1907
+ const db = dbForShadowQueue.get(projectIdentity);
1908
+ const shadow = shadowRegistrations.get(projectIdentity);
1909
+ const primary = projectRegistrations.get(projectIdentity);
1910
+ if (!db || !shadow || !primary) {
1911
+ pendingShadowBackfills.delete(projectIdentity);
1912
+ continue;
1913
+ }
1914
+ for (const scope of [...scopes]) {
1915
+ const primaryModelId = shadowModelIdForScope(primary, scope);
1916
+ const shadowModelId = shadowModelIdForScope(shadow, scope);
1917
+ const stallKey = `${projectIdentity}:${scope}`;
1918
+ if (primaryModelId === "off" || shadowModelId === "off") {
1919
+ scopes.delete(scope);
1920
+ shadowBackfillLastIds.delete(stallKey);
1921
+ shadowBackfillLastWriteOutcomes.delete(stallKey);
1922
+ continue;
1923
+ }
1924
+ const batch = shadowBackfillCandidateBatch(db, projectIdentity, scope, primaryModelId, shadow, SHADOW_MAX_ITEMS_PER_TICK);
1925
+ if (batch.ids.length === 0) {
1926
+ shadowBackfillStopReasons.set(stallKey, "drained");
1927
+ scopes.delete(scope);
1928
+ shadowBackfillLastIds.delete(stallKey);
1929
+ shadowBackfillLastWriteOutcomes.delete(stallKey);
1930
+ updatePersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId, (state) => ({
1931
+ ...state,
1932
+ stopReason: "drained",
1933
+ candidateSignature: undefined,
1934
+ writeRefusalReason: undefined,
1935
+ stoppedAt: shadowBackfillNow()
1936
+ }));
1937
+ continue;
1938
+ }
1939
+ if (shadowBackfillLastIds.get(stallKey) === batch.signature) {
1940
+ const lastOutcome = shadowBackfillLastWriteOutcomes.get(stallKey);
1941
+ const writeRefusalReason = lastOutcome?.refusalReason ?? (lastOutcome && lastOutcome.writes > 0 ? "chunk_window_contract_mismatch" : "unknown_write_rejection");
1942
+ shadowBackfillStopReasons.set(stallKey, "stalled_no_progress");
1943
+ updatePersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId, (state) => ({
1944
+ ...state,
1945
+ stopReason: "stalled_no_progress",
1946
+ candidateSignature: batch.signature,
1947
+ writeRefusalReason,
1948
+ stoppedAt: shadowBackfillNow()
1949
+ }));
1950
+ log2(`[shadow] backfill scope ${scope} for ${projectIdentity} retired without progress — ` + `${describeShadowBackfillWriteRefusal2(writeRefusalReason)}; ` + `${batch.ids.length}+ items remain and automatic registration will not retry unchanged candidates`);
1951
+ scopes.delete(scope);
1952
+ shadowBackfillLastIds.delete(stallKey);
1953
+ shadowBackfillLastWriteOutcomes.delete(stallKey);
1954
+ continue;
1955
+ }
1956
+ shadowBackfillLastIds.set(stallKey, batch.signature);
1957
+ shadowQueue.push({ projectIdentity, scope, ids: batch.ids });
1958
+ }
1959
+ if (scopes.size === 0)
1960
+ pendingShadowBackfills.delete(projectIdentity);
1961
+ }
1962
+ }
1963
+ function maybeArmShadowBackfill(db, projectIdentity, shadow, manualBackfill = false) {
1964
+ if (untrustedLoadProjects.has(projectIdentity))
1965
+ return;
1966
+ const primary = projectRegistrations.get(projectIdentity);
1967
+ if (!primary)
1968
+ return;
1969
+ const pending = new Set;
1970
+ for (const scope of ["memory", "commit", "chunk"]) {
1971
+ const primaryModelId = shadowModelIdForScope(primary, scope);
1972
+ const shadowModelId = shadowModelIdForScope(shadow, scope);
1973
+ const stallKey = `${projectIdentity}:${scope}`;
1974
+ if (primaryModelId === "off" || shadowModelId === "off")
1975
+ continue;
1976
+ if (scope === "memory" && !primary.features.memoryEnabled)
1977
+ continue;
1978
+ const batch = shadowBackfillCandidateBatch(db, projectIdentity, scope, primaryModelId, shadow, SHADOW_MAX_ITEMS_PER_TICK);
1979
+ const persisted = getPersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId);
1980
+ if (batch.ids.length === 0) {
1981
+ if (persisted?.stopReason === "stalled_no_progress") {
1982
+ shadowBackfillStopReasons.set(stallKey, "drained");
1983
+ updatePersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId, (state) => ({
1984
+ ...state,
1985
+ stopReason: "drained",
1986
+ candidateSignature: undefined,
1987
+ writeRefusalReason: undefined,
1988
+ stoppedAt: shadowBackfillNow()
1989
+ }));
1990
+ }
1991
+ continue;
1992
+ }
1993
+ if (!manualBackfill && persisted?.stopReason === "stalled_no_progress" && persisted.candidateSignature === batch.signature) {
1994
+ shadowBackfillStopReasons.set(stallKey, "stalled_no_progress");
1995
+ continue;
1996
+ }
1997
+ shadowBackfillStopReasons.delete(stallKey);
1998
+ shadowBackfillLastIds.delete(stallKey);
1999
+ shadowBackfillLastWriteOutcomes.delete(stallKey);
2000
+ updatePersistedShadowBackfillState(db, projectIdentity, scope, shadowModelId, (state) => ({
2001
+ ...state,
2002
+ stopReason: undefined,
2003
+ candidateSignature: undefined,
2004
+ writeRefusalReason: undefined,
2005
+ stoppedAt: undefined
2006
+ }));
2007
+ pending.add(scope);
2008
+ }
2009
+ if (pending.size === 0)
2010
+ return;
2011
+ pendingShadowBackfills.set(projectIdentity, pending);
2012
+ pumpShadowBackfill();
2013
+ startShadowWorker();
2014
+ }
2015
+ function getShadowBackfillRemaining2(db, projectIdentity) {
2016
+ const remaining = { memory: 0, commit: 0, chunk: 0 };
2017
+ const primary = projectRegistrations.get(projectIdentity);
2018
+ const shadow = shadowRegistrations.get(projectIdentity);
2019
+ if (!primary || !shadow)
2020
+ return remaining;
2021
+ for (const scope of ["memory", "commit", "chunk"]) {
2022
+ const primaryModelId = shadowModelIdForScope(primary, scope);
2023
+ const shadowModelId = shadowModelIdForScope(shadow, scope);
2024
+ if (primaryModelId === "off" || shadowModelId === "off")
2025
+ continue;
2026
+ remaining[scope] = countShadowBackfillMissing(db, projectIdentity, scope, primaryModelId, shadowModelId, shadowMaxInputTokensFor(shadow));
2027
+ }
2028
+ return remaining;
2029
+ }
2030
+ async function flushShadowEmbeddingBacklog2(projectIdentity, onSettled) {
2031
+ if (shadowQueue.length > 0 || hasPendingShadowBackfill(projectIdentity)) {
2032
+ startShadowWorker();
2033
+ }
2034
+ for (;; ) {
2035
+ const worker = shadowWorker;
2036
+ if (worker) {
2037
+ await worker;
2038
+ await onSettled?.();
2039
+ continue;
2040
+ }
2041
+ if (shadowQueue.length === 0 && !hasPendingShadowBackfill(projectIdentity))
2042
+ return;
2043
+ startShadowWorker();
2044
+ if (!shadowWorker)
2045
+ await new Promise((resolve) => setTimeout(resolve, 10));
2046
+ await onSettled?.();
2047
+ }
2048
+ }
2049
+ async function embedShadowItems(registration, items, db, scope) {
2050
+ const raw = registration.config;
2051
+ const fingerprint = typeof raw.synapse_fingerprint === "string" ? raw.synapse_fingerprint : "";
2052
+ const tableEpoch = typeof raw.synapse_table_epoch === "number" ? raw.synapse_table_epoch : 0;
2053
+ const requestKey = getSynapseBatchRequestKey({
2054
+ model: typeof raw.model === "string" ? raw.model : SYNAPSE_DEFAULT_MODEL,
2055
+ fingerprint,
2056
+ tableEpoch,
2057
+ items
2058
+ });
2059
+ const sessionId = `shadow:${registration.projectIdentity}`;
2060
+ const now = shadowBackfillNow();
2061
+ const prior = db.prepare(`SELECT updated_at AS updatedAt
2062
+ FROM synapse_batch_ledger
2063
+ WHERE session_id = ? AND request_key = ?`).get(sessionId, requestKey);
2064
+ if (typeof prior?.updatedAt === "number" && now - prior.updatedAt >= 0 && now - prior.updatedAt < SHADOW_RESUBMIT_WINDOW_MS) {
2065
+ const modelId = shadowModelIdForScope(registration, scope);
2066
+ const state = getPersistedShadowBackfillState(db, registration.projectIdentity, scope, modelId);
2067
+ if (state?.budgetLogRequestKey !== requestKey || typeof state.budgetLoggedAt !== "number" || now - state.budgetLoggedAt >= SHADOW_RESUBMIT_WINDOW_MS) {
2068
+ log2(`[shadow] skipped duplicate ${scope} batch for ${registration.projectIdentity}; ` + "the same content was submitted within the one-hour provider budget");
2069
+ updatePersistedShadowBackfillState(db, registration.projectIdentity, scope, modelId, (current) => ({
2070
+ ...current,
2071
+ budgetLogRequestKey: requestKey,
2072
+ budgetLoggedAt: now
2073
+ }));
2074
+ }
2075
+ return {
2076
+ vectors: new Map,
2077
+ refusalReason: "duplicate_submission_budget"
2078
+ };
2079
+ }
2080
+ beginSynapseBatchLedger(db, {
2081
+ sessionId,
2082
+ projectPath: registration.projectIdentity,
2083
+ scope,
2084
+ manifest: items.map(({ id, contentSha256 }) => ({ id, contentSha256 })),
2085
+ requestKey
2086
+ }, now);
2087
+ try {
2088
+ if (registration.provider.embedItems) {
2089
+ const returned = await registration.provider.embedItems(items);
2090
+ const vectors = new Map([...returned].filter(([, vector]) => !isSynapseEmbeddingTruncated(vector)));
2091
+ finishSynapseBatchLedger(db, sessionId, requestKey, vectors.size === items.length ? "complete" : "partial", shadowBackfillNow());
2092
+ return {
2093
+ vectors,
2094
+ ...vectors.size === 0 ? { refusalReason: "provider_returned_no_vectors" } : {}
2095
+ };
2096
+ }
2097
+ const positional = await registration.provider.embedBatch(items.map((item) => item.text));
2098
+ const vectors = new Map(items.flatMap((item, index) => {
2099
+ const vector = positional[index];
2100
+ return vector && !isSynapseEmbeddingTruncated(vector) ? [[item.id, vector]] : [];
2101
+ }));
2102
+ finishSynapseBatchLedger(db, sessionId, requestKey, vectors.size === items.length ? "complete" : "partial", shadowBackfillNow());
2103
+ return {
2104
+ vectors,
2105
+ ...vectors.size === 0 ? { refusalReason: "provider_returned_no_vectors" } : {}
2106
+ };
2107
+ } catch (error) {
2108
+ finishSynapseBatchLedger(db, sessionId, requestKey, "failed", shadowBackfillNow());
2109
+ throw error;
2110
+ }
2111
+ }
2112
+ async function processShadowQueueItem(item) {
2113
+ const registration = shadowRegistrations.get(item.projectIdentity);
2114
+ if (!registration)
2115
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2116
+ const boundedIds = item.ids.slice(0, SHADOW_MAX_ITEMS_PER_TICK);
2117
+ if (item.scope === "memory") {
2118
+ const db = dbForShadowQueue.get(item.projectIdentity);
2119
+ if (!db)
2120
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2121
+ const placeholders = boundedIds.map(() => "?").join(",");
2122
+ const rows = db.prepare(`SELECT id, content, normalized_hash FROM memories
2123
+ WHERE project_path = ? AND id IN (${placeholders}) AND status = 'active'`).all(item.projectIdentity, ...boundedIds.map((id) => Number(id)));
2124
+ if (rows.length === 0)
2125
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2126
+ const embedded = await embedShadowItems(registration, rows.map((row) => ({
2127
+ id: `memory:${row.id}`,
2128
+ text: row.content,
2129
+ contentSha256: contentSha2562(row.content)
2130
+ })), db, "memory");
2131
+ const live = shadowRegistrations.get(item.projectIdentity);
2132
+ if (!live || live.generation !== registration.generation) {
2133
+ return { writes: 0, refusalReason: "registration_retired_during_embed" };
2134
+ }
2135
+ let writes = 0;
2136
+ let hashGuardRejected = false;
2137
+ db.transaction(() => {
2138
+ for (const row of rows) {
2139
+ const vector = embedded.vectors.get(`memory:${row.id}`);
2140
+ if (!vector)
2141
+ continue;
2142
+ if (saveEmbeddingIfHashMatches(db, row.id, vector, registration.modelId, row.normalized_hash)) {
2143
+ writes += 1;
2144
+ } else {
2145
+ hashGuardRejected = true;
2146
+ }
2147
+ }
2148
+ }).immediate();
2149
+ return {
2150
+ writes,
2151
+ ...writes === 0 ? {
2152
+ refusalReason: embedded.refusalReason ?? (hashGuardRejected ? "memory_hash_guard_rejected" : "provider_returned_no_vectors")
2153
+ } : {}
2154
+ };
2155
+ }
2156
+ if (item.scope === "commit") {
2157
+ const db = dbForShadowQueue.get(item.projectIdentity);
2158
+ if (!db)
2159
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2160
+ const placeholders = boundedIds.map(() => "?").join(",");
2161
+ const rows = db.prepare(`SELECT sha, message FROM git_commits WHERE project_path = ? AND sha IN (${placeholders})`).all(item.projectIdentity, ...boundedIds);
2162
+ if (rows.length === 0)
2163
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2164
+ const embedded = await embedShadowItems(registration, rows.map((row) => ({
2165
+ id: `commit:${row.sha}`,
2166
+ text: row.message,
2167
+ contentSha256: contentSha2562(row.message)
2168
+ })), db, "commit");
2169
+ const live = shadowRegistrations.get(item.projectIdentity);
2170
+ if (!live || live.generation !== registration.generation) {
2171
+ return { writes: 0, refusalReason: "registration_retired_during_embed" };
2172
+ }
2173
+ let writes = 0;
2174
+ db.transaction(() => {
2175
+ for (const row of rows) {
2176
+ const vector = embedded.vectors.get(`commit:${row.sha}`);
2177
+ if (!vector)
2178
+ continue;
2179
+ saveCommitEmbedding(db, row.sha, vector, registration.modelId);
2180
+ writes += 1;
2181
+ }
2182
+ }).immediate();
2183
+ return {
2184
+ writes,
2185
+ ...writes === 0 ? { refusalReason: embedded.refusalReason ?? "provider_returned_no_vectors" } : {}
2186
+ };
2187
+ }
2188
+ const db = dbForShadowQueue.get(item.projectIdentity);
2189
+ if (!db)
2190
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2191
+ const placeholders = boundedIds.map(() => "?").join(",");
2192
+ const candidates = db.prepare(`SELECT id, session_id, start_message, end_message
2193
+ FROM compartments WHERE id IN (${placeholders})`).all(...boundedIds.map((id) => Number(id)));
2194
+ if (candidates.length === 0) {
2195
+ return { writes: 0, refusalReason: "candidate_rows_changed" };
2196
+ }
2197
+ const prepared = [];
2198
+ let ftsMappingIncomplete = false;
2199
+ let emptyCanonicalText = false;
2200
+ for (const candidate of candidates) {
2201
+ const mappedText = buildCanonicalChunkTextFromFts(db, candidate.session_id, candidate.start_message, candidate.end_message);
2202
+ if (mappedText === null) {
2203
+ ftsMappingIncomplete = true;
2204
+ } else {
2205
+ const text = mappedText || buildCompartmentSummaryFallbackText(db, candidate.id);
2206
+ const shadowMaxInputTokens = shadowMaxInputTokensFor(registration);
2207
+ const windows = chunkCanonicalText(text, candidate.start_message, candidate.end_message, shadowMaxInputTokens);
2208
+ const windowSourceKey = chunkWindowSourceKey(text, candidate.start_message, candidate.end_message, shadowMaxInputTokens);
2209
+ if (windows.length > 0)
2210
+ prepared.push({ candidate, windows, windowSourceKey });
2211
+ else
2212
+ emptyCanonicalText = true;
2213
+ }
2214
+ await new Promise((resolve) => setTimeout(resolve, 0));
2215
+ }
2216
+ if (prepared.length === 0) {
2217
+ return {
2218
+ writes: 0,
2219
+ refusalReason: ftsMappingIncomplete ? "chunk_fts_mapping_incomplete" : "chunk_empty_canonical_text"
2220
+ };
2221
+ }
2222
+ const items = prepared.flatMap((item) => item.windows.map((window) => ({
2223
+ id: `chunk:${item.candidate.id}:${window.windowIndex}`,
2224
+ text: window.text,
2225
+ contentSha256: contentSha2562(window.text)
2226
+ })));
2227
+ const embedded = await embedShadowItems(registration, items, db, "chunk");
2228
+ const live = shadowRegistrations.get(item.projectIdentity);
2229
+ if (!live || live.generation !== registration.generation) {
2230
+ return { writes: 0, refusalReason: "registration_retired_during_embed" };
2231
+ }
2232
+ let writes = 0;
2233
+ let partialVectorSet = false;
2234
+ for (const item of prepared) {
2235
+ const rows = item.windows.flatMap((window) => {
2236
+ const vector = embedded.vectors.get(`chunk:${item.candidate.id}:${window.windowIndex}`);
2237
+ return vector ? [
2238
+ {
2239
+ compartmentId: item.candidate.id,
2240
+ sessionId: item.candidate.session_id,
2241
+ projectPath: registration.projectIdentity,
2242
+ window,
2243
+ modelId: registration.chunkModelId,
2244
+ vector
2245
+ }
2246
+ ] : [];
2247
+ });
2248
+ if (rows.length === item.windows.length) {
2249
+ replaceCompartmentChunkEmbeddings(db, rows, item.windowSourceKey);
2250
+ writes += 1;
2251
+ } else {
2252
+ partialVectorSet = true;
2253
+ }
2254
+ }
2255
+ return {
2256
+ writes,
2257
+ ...writes === 0 ? {
2258
+ refusalReason: embedded.refusalReason ?? (partialVectorSet ? "chunk_partial_vector_set" : ftsMappingIncomplete ? "chunk_fts_mapping_incomplete" : emptyCanonicalText ? "chunk_empty_canonical_text" : "unknown_write_rejection")
2259
+ } : {}
2260
+ };
2261
+ }
2262
+ var dbForShadowQueue = new Map;
2263
+ async function runShadowWorker() {
2264
+ const startedAt = Date.now();
2265
+ let processed = 0;
2266
+ let processedBytes = 0;
2267
+ for (;; ) {
2268
+ if (shadowQueue.length === 0) {
2269
+ pumpShadowBackfill();
2270
+ if (shadowQueue.length === 0)
2271
+ break;
2272
+ }
2273
+ if (processed >= SHADOW_MAX_ITEMS_PER_TICK || Date.now() - startedAt >= SHADOW_MAX_WALL_CLOCK_MS) {
2274
+ break;
2275
+ }
2276
+ const item = shadowQueue.shift();
2277
+ if (!item)
2278
+ break;
2279
+ const itemBytes = item.ids.reduce((total, id) => total + id.length, 0);
2280
+ if (processed > 0 && processedBytes + itemBytes > SHADOW_MAX_BYTES_PER_TICK) {
2281
+ shadowQueue.unshift(item);
2282
+ break;
2283
+ }
2284
+ const generationAtStart = shadowRegistrations.get(item.projectIdentity)?.generation;
2285
+ const isStillCurrent = () => generationAtStart !== undefined && shadowRegistrations.get(item.projectIdentity)?.generation === generationAtStart;
2286
+ try {
2287
+ const outcome = await processShadowQueueItem(item);
2288
+ if (isStillCurrent()) {
2289
+ shadowBackfillLastWriteOutcomes.set(`${item.projectIdentity}:${item.scope}`, outcome);
2290
+ }
2291
+ } catch (error) {
2292
+ if (isStillCurrent()) {
2293
+ shadowBackfillLastWriteOutcomes.set(`${item.projectIdentity}:${item.scope}`, {
2294
+ writes: 0,
2295
+ refusalReason: "provider_returned_no_vectors"
2296
+ });
2297
+ }
2298
+ log2("[magic-context] Synapse shadow write failed:", error);
2299
+ }
2300
+ processed += item.ids.length;
2301
+ processedBytes += itemBytes;
2302
+ await new Promise((resolve) => setTimeout(resolve, 0));
2303
+ }
2304
+ }
2305
+ function registerProjectInObservationMode2(db, projectIdentity, sourceDirectory, failedConfig, failureSummary) {
2306
+ const prior = projectRegistrations.get(projectIdentity);
2307
+ const runtimeFingerprint = `observation:${sha256Prefix(failureSummary)}`;
2308
+ const generation = prior?.runtimeFingerprint === runtimeFingerprint && prior.observationMode ? prior.generation : ++globalRegistrationGeneration;
2309
+ const registration = {
2310
+ projectIdentity,
2311
+ sourceDirectory,
2312
+ config: resolveEmbeddingConfig(failedConfig),
2313
+ providerIdentity: OFF_PROVIDER_IDENTITY,
2314
+ runtimeFingerprint,
2315
+ provider: null,
2316
+ generation,
2317
+ features: { memoryEnabled: false, gitCommitEnabled: false },
2318
+ modelId: "off",
2319
+ chunkModelId: "off",
2320
+ observationMode: true
2321
+ };
2322
+ projectRegistrations.set(projectIdentity, registration);
2323
+ disposeProvider(prior?.provider ?? null);
2324
+ return snapshotFor(registration);
2325
+ }
2326
+ function unregisterProjectShadowEmbedding2(projectIdentity) {
2327
+ const shadow = shadowRegistrations.get(projectIdentity);
2328
+ shadowRegistrations.delete(projectIdentity);
2329
+ dbForShadowQueue.delete(projectIdentity);
2330
+ pendingShadowBackfills.delete(projectIdentity);
2331
+ for (let index = shadowQueue.length - 1;index >= 0; index -= 1) {
2332
+ if (shadowQueue[index].projectIdentity === projectIdentity)
2333
+ shadowQueue.splice(index, 1);
2334
+ }
2335
+ for (const scope of ["memory", "commit", "chunk"]) {
2336
+ const key = `${projectIdentity}:${scope}`;
2337
+ shadowBackfillLastIds.delete(key);
2338
+ shadowBackfillStopReasons.delete(key);
2339
+ shadowBackfillLastWriteOutcomes.delete(key);
2340
+ }
2341
+ const primaryProvider = projectRegistrations.get(projectIdentity)?.provider ?? null;
2342
+ if (shadow?.provider && shadow.provider !== primaryProvider) {
2343
+ disposeProvider(shadow.provider);
2344
+ }
2345
+ }
2346
+ function unregisterProjectEmbedding2(projectIdentity) {
2347
+ const prior = projectRegistrations.get(projectIdentity);
2348
+ const shadow = shadowRegistrations.get(projectIdentity);
2349
+ if (!prior && !shadow)
2350
+ return;
2351
+ projectRegistrations.delete(projectIdentity);
2352
+ shadowRegistrations.delete(projectIdentity);
2353
+ dbForShadowQueue.delete(projectIdentity);
2354
+ globalRegistrationGeneration += 1;
2355
+ disposeProvider(prior?.provider ?? null);
2356
+ disposeProvider(shadow?.provider ?? null);
2357
+ }
2358
+ function getProjectEmbeddingSnapshot2(projectIdentity) {
2359
+ const registration = projectRegistrations.get(projectIdentity);
2360
+ return registration ? snapshotFor(registration) : null;
2361
+ }
2362
+ function installProjectEmbeddingSearchBridge2(snapshot, provider) {
2363
+ projectRegistrations.set(snapshot.projectIdentity, {
2364
+ projectIdentity: snapshot.projectIdentity,
2365
+ sourceDirectory: snapshot.sourceDirectory,
2366
+ providerIdentity: snapshot.providerIdentity,
2367
+ runtimeFingerprint: snapshot.runtimeFingerprint,
2368
+ generation: snapshot.generation,
2369
+ features: { ...snapshot.features },
2370
+ modelId: snapshot.modelId,
2371
+ chunkModelId: snapshot.chunkModelId,
2372
+ config: { provider: "off" },
2373
+ provider,
2374
+ observationMode: !snapshot.historyEnabled
2375
+ });
2376
+ }
2377
+ function getProjectChunkEmbeddingModelId2(projectIdentity) {
2378
+ const registration = projectRegistrations.get(projectIdentity);
2379
+ return registration && !registration.observationMode ? registration.chunkModelId : "off";
2380
+ }
2381
+ function getProjectEmbeddingMaxInputTokens2(projectIdentity) {
2382
+ const registration = projectRegistrations.get(projectIdentity);
2383
+ const configMax = registration?.config && "max_input_tokens" in registration.config ? registration.config.max_input_tokens : undefined;
2384
+ return normalizeCompartmentChunkMaxInputTokens(registration?.provider?.maxInputTokens ?? configMax);
2385
+ }
2386
+ function getOrCreateProjectProvider(registration) {
2387
+ if (registration.providerIdentity === OFF_PROVIDER_IDENTITY || registration.observationMode) {
2388
+ return null;
2389
+ }
2390
+ if (registration.provider) {
2391
+ return registration.provider;
2392
+ }
2393
+ const provider = createProvider(registration.config, {
2394
+ projectRoot: registration.sourceDirectory,
2395
+ session: `project:${registration.projectIdentity}`
2396
+ });
2397
+ registration.provider = provider;
2398
+ return provider;
2399
+ }
2400
+ async function embedTextForProject2(projectIdentity, text, signal, purpose = "passage") {
2401
+ const registration = projectRegistrations.get(projectIdentity);
2402
+ if (!registration)
2403
+ return null;
2404
+ const generation = registration.generation;
2405
+ const modelId = registration.modelId;
2406
+ const provider = getOrCreateProjectProvider(registration);
2407
+ if (!provider)
2408
+ return null;
2409
+ const vector = await provider.embed(text, signal, purpose);
2410
+ if (!vector || isSynapseEmbeddingTruncated(vector))
2411
+ return null;
2412
+ const current = projectRegistrations.get(projectIdentity);
2413
+ if (!current || current.generation !== generation || current.runtimeFingerprint !== registration.runtimeFingerprint) {
2414
+ return null;
2415
+ }
2416
+ return { vector, modelId, chunkModelId: registration.chunkModelId, generation };
2417
+ }
2418
+ async function embedBatchForProject2(projectIdentity, texts, signal, purpose = "passage") {
2419
+ if (texts.length === 0) {
2420
+ const registration = projectRegistrations.get(projectIdentity);
2421
+ if (!registration || registration.observationMode)
2422
+ return null;
2423
+ return { vectors: [], modelId: registration.modelId, generation: registration.generation };
2424
+ }
2425
+ const registration = projectRegistrations.get(projectIdentity);
2426
+ if (!registration)
2427
+ return null;
2428
+ const generation = registration.generation;
2429
+ const modelId = registration.modelId;
2430
+ const runtimeFingerprint = registration.runtimeFingerprint;
2431
+ const provider = getOrCreateProjectProvider(registration);
2432
+ if (!provider)
2433
+ return null;
2434
+ const vectors = (await provider.embedBatch(texts, signal, purpose)).map((vector) => vector && !isSynapseEmbeddingTruncated(vector) ? vector : null);
2435
+ const current = projectRegistrations.get(projectIdentity);
2436
+ if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
2437
+ return null;
2438
+ }
2439
+ return { vectors, modelId, generation };
2440
+ }
2441
+ async function embedItemsForProject2(projectIdentity, items, signal, db, sessionId = projectIdentity) {
2442
+ const registration = projectRegistrations.get(projectIdentity);
2443
+ if (!registration || registration.observationMode || items.length === 0)
2444
+ return null;
2445
+ const generation = registration.generation;
2446
+ const modelId = registration.modelId;
2447
+ const runtimeFingerprint = registration.runtimeFingerprint;
2448
+ const provider = getOrCreateProjectProvider(registration);
2449
+ if (!provider)
2450
+ return null;
2451
+ const rawConfig = registration.config;
2452
+ const fingerprint = typeof rawConfig.synapse_fingerprint === "string" ? rawConfig.synapse_fingerprint : "";
2453
+ const tableEpoch = typeof rawConfig.synapse_table_epoch === "number" ? rawConfig.synapse_table_epoch : undefined;
2454
+ const isSynapse = registration.providerIdentity.startsWith("synapse:v1:") && fingerprint && tableEpoch !== undefined;
2455
+ const ledgerKey = isSynapse ? getSynapseBatchRequestKey({
2456
+ model: typeof rawConfig.model === "string" ? rawConfig.model : registration.modelId,
2457
+ fingerprint,
2458
+ tableEpoch,
2459
+ items
2460
+ }) : null;
2461
+ if (db && ledgerKey) {
2462
+ beginSynapseBatchLedger(db, {
2463
+ sessionId,
2464
+ projectPath: projectIdentity,
2465
+ scope: items[0].id.split(":", 1)[0],
2466
+ manifest: items.map(({ id, contentSha256 }) => ({ id, contentSha256 })),
2467
+ requestKey: ledgerKey
2468
+ });
2469
+ }
2470
+ let vectors;
2471
+ try {
2472
+ if (provider.embedItems) {
2473
+ const returned = await provider.embedItems(items, signal);
2474
+ vectors = new Map([...returned].filter(([, vector]) => !isSynapseEmbeddingTruncated(vector)));
2475
+ } else {
2476
+ const positional = await provider.embedBatch(items.map((item) => item.text), signal, "passage");
2477
+ vectors = new Map(items.flatMap((item, index) => {
2478
+ const vector = positional[index];
2479
+ return vector && !isSynapseEmbeddingTruncated(vector) ? [[item.id, vector]] : [];
2480
+ }));
2481
+ }
2482
+ } catch (error) {
2483
+ if (db && ledgerKey)
2484
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, "failed");
2485
+ throw error;
2486
+ }
2487
+ if (db && ledgerKey) {
2488
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, vectors.size === items.length ? "complete" : "partial");
2489
+ }
2490
+ const current = projectRegistrations.get(projectIdentity);
2491
+ if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
2492
+ return null;
2493
+ }
2494
+ return { vectors, modelId, generation };
2495
+ }
2496
+ async function embedItemsWindowBounded(projectIdentity, items, signal, db) {
2497
+ if (items.length <= MAX_WINDOWS_PER_EMBED_CALL) {
2498
+ return embedItemsForProject2(projectIdentity, items, signal, db, projectIdentity);
2499
+ }
2500
+ const vectors = new Map;
2501
+ let modelId = null;
2502
+ let generation = null;
2503
+ for (let start = 0;start < items.length; start += MAX_WINDOWS_PER_EMBED_CALL) {
2504
+ const result = await embedItemsForProject2(projectIdentity, items.slice(start, start + MAX_WINDOWS_PER_EMBED_CALL), signal, db, projectIdentity);
2505
+ if (!result)
2506
+ return null;
2507
+ if (modelId === null) {
2508
+ modelId = result.modelId;
2509
+ generation = result.generation;
2510
+ } else if (modelId !== result.modelId || generation !== result.generation) {
2511
+ return null;
2512
+ }
2513
+ for (const [id, vector] of result.vectors)
2514
+ vectors.set(id, vector);
2515
+ }
2516
+ return modelId === null || generation === null ? null : { vectors, modelId, generation };
2517
+ }
2518
+ function isUnembeddedMemoryRow(row) {
2519
+ if (row === null || typeof row !== "object")
2520
+ return false;
2521
+ const candidate = row;
2522
+ return typeof candidate.id === "number" && typeof candidate.content === "string" && typeof candidate.normalized_hash === "string";
2523
+ }
2524
+ function getLoadUnembeddedMemoriesStatement(db) {
2525
+ let stmt = loadUnembeddedMemoriesStatements.get(db);
2526
+ if (!stmt) {
2527
+ stmt = db.prepare("SELECT m.id AS id, m.content AS content, m.normalized_hash AS normalized_hash FROM memories m LEFT JOIN memory_embeddings me ON m.id = me.memory_id AND me.model_id = ? WHERE m.project_path = ? AND m.status = 'active' AND me.memory_id IS NULL LIMIT ?");
2528
+ loadUnembeddedMemoriesStatements.set(db, stmt);
2529
+ }
2530
+ return stmt;
2531
+ }
2532
+ async function embedUnembeddedMemoriesForProject2(db, projectIdentity, batchSize = 10) {
2533
+ const outcome = await embedUnembeddedMemoriesForProjectOutcome2(db, projectIdentity, batchSize);
2534
+ return outcome.kind === "embedded" ? outcome.count : 0;
2535
+ }
2536
+ async function embedUnembeddedMemoriesForProjectOutcome2(db, projectIdentity, batchSize = 10) {
2537
+ if (isEmbeddingHostBusy2())
2538
+ return { kind: "unavailable" };
2539
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2540
+ if (!snapshot?.enabled)
2541
+ return { kind: "disabled" };
2542
+ const normalizedBatchSize = Math.max(1, Math.floor(batchSize));
2543
+ const memories = getLoadUnembeddedMemoriesStatement(db).all(snapshot.modelId, projectIdentity, normalizedBatchSize).filter(isUnembeddedMemoryRow);
2544
+ if (memories.length === 0)
2545
+ return { kind: "done" };
2546
+ try {
2547
+ const result = await embedItemsForProject2(projectIdentity, memories.map((memory) => ({
2548
+ id: `memory:${memory.id}`,
2549
+ text: memory.content,
2550
+ contentSha256: contentSha2562(memory.content)
2551
+ })), undefined, db, projectIdentity);
2552
+ if (!result)
2553
+ return { kind: "unavailable" };
2554
+ let embeddedCount = 0;
2555
+ db.transaction(() => {
2556
+ for (const memory of memories) {
2557
+ const embedding = result.vectors.get(`memory:${memory.id}`);
2558
+ if (!embedding)
2559
+ continue;
2560
+ if (saveEmbeddingIfHashMatches(db, memory.id, embedding, result.modelId, memory.normalized_hash)) {
2561
+ embeddedCount += 1;
2562
+ }
2563
+ }
2564
+ }).immediate();
2565
+ enqueueShadowEmbeddingItems2(projectIdentity, "memory", memories.filter((memory) => result.vectors.has(`memory:${memory.id}`)).map((memory) => String(memory.id)));
2566
+ return { kind: "embedded", count: embeddedCount };
2567
+ } catch (error) {
2568
+ log2("[magic-context] failed to proactively embed missing memories:", error);
2569
+ return { kind: "failed", error };
2570
+ }
2571
+ }
2572
+ async function embedCommitBatch(db, projectIdentity, batchSize) {
2573
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2574
+ if (!snapshot?.gitCommitEnabled)
2575
+ return 0;
2576
+ const commits = loadUnembeddedCommits(db, projectIdentity, snapshot.modelId, Math.max(1, Math.floor(batchSize)));
2577
+ if (commits.length === 0)
2578
+ return 0;
2579
+ const result = await embedItemsForProject2(projectIdentity, commits.map((commit) => ({
2580
+ id: `commit:${commit.sha}`,
2581
+ text: commit.message,
2582
+ contentSha256: contentSha2562(commit.message)
2583
+ })), undefined, db, projectIdentity);
2584
+ if (!result)
2585
+ return 0;
2586
+ let embeddedCount = 0;
2587
+ db.transaction(() => {
2588
+ for (const commit of commits) {
2589
+ const embedding = result.vectors.get(`commit:${commit.sha}`);
2590
+ if (!embedding)
2591
+ continue;
2592
+ saveCommitEmbedding(db, commit.sha, embedding, result.modelId);
2593
+ embeddedCount += 1;
2594
+ }
2595
+ }).immediate();
2596
+ enqueueShadowEmbeddingItems2(projectIdentity, "commit", commits.filter((commit) => result.vectors.has(`commit:${commit.sha}`)).map((commit) => commit.sha));
2597
+ return embeddedCount;
2598
+ }
2599
+ async function drainCommitBacklogForProject2(db, projectIdentity, deadline) {
2600
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2601
+ if (!snapshot?.gitCommitEnabled)
2602
+ return 0;
2603
+ const holderId = `embed-sweep-${randomUUID()}`;
2604
+ const lease = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
2605
+ if (!lease.acquired) {
2606
+ return 0;
2607
+ }
2608
+ let total = 0;
2609
+ let leaseLost = false;
2610
+ const renewal = setInterval(() => {
2611
+ try {
2612
+ if (!renewGitSweepLease(db, projectIdentity, holderId))
2613
+ leaseLost = true;
2614
+ } catch {}
2615
+ }, SESSION_EMBED_LEASE_RENEWAL_MS);
2616
+ renewal.unref?.();
2617
+ try {
2618
+ while (!leaseLost && !isEmbeddingHostBusy2() && Date.now() < deadline && total < COMMIT_DRAIN_MAX_PER_SWEEP) {
2619
+ const embedded = await embedCommitBatch(db, projectIdentity, COMMIT_DRAIN_BATCH_SIZE);
2620
+ if (!renewGitSweepLease(db, projectIdentity, holderId))
2621
+ leaseLost = true;
2622
+ if (leaseLost || embedded === 0)
2623
+ break;
2624
+ total += embedded;
2625
+ if (embedded < COMMIT_DRAIN_BATCH_SIZE)
2626
+ break;
2627
+ }
2628
+ } finally {
2629
+ clearInterval(renewal);
2630
+ releaseGitSweepLease(db, projectIdentity, holderId);
2631
+ }
2632
+ return total;
2633
+ }
2634
+ async function embedCompartmentChunkBatch(db, projectIdentity, batchSize) {
2635
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2636
+ if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off")
2637
+ return 0;
2638
+ repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectIdentity);
2639
+ const candidates = await loadUnembeddedCompartmentChunkCandidatesPolite(db, projectIdentity, snapshot.chunkModelId, batchSize, getProjectEmbeddingMaxInputTokens2(projectIdentity), true);
2640
+ if (candidates.length === 0)
2641
+ return 0;
2642
+ const { embedded } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates);
2643
+ return embedded;
2644
+ }
2645
+ function getLastEmbeddingFailureForProject(projectIdentity) {
2646
+ const registration = projectRegistrations.get(projectIdentity);
2647
+ return registration?.provider?.getLastFailureReason?.() ?? null;
2648
+ }
2649
+ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
2650
+ const noWork = [];
2651
+ const failed = [];
2652
+ const failureReasons = [];
2653
+ if (candidates.length === 0)
2654
+ return { embedded: 0, noWork, failed, failureReasons };
2655
+ const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectIdentity);
2656
+ const prepared = [];
2657
+ for (const candidate of candidates) {
2658
+ await new Promise((resolve) => setTimeout(resolve, 0));
2659
+ const mappedText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
2660
+ if (mappedText === null)
2661
+ continue;
2662
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, candidate.id);
2663
+ if (canonicalText.length === 0) {
2664
+ recordChunkEmbedBackoff(db, candidate, projectIdentity, modelId);
2665
+ noWork.push(candidate.id);
2666
+ continue;
2667
+ }
2668
+ const windows = chunkCanonicalText(canonicalText, candidate.startMessage, candidate.endMessage, maxInputTokens);
2669
+ if (windows.length === 0 || chunkEmbeddingWindowsAreCurrent(db, candidate.id, modelId, windows, projectIdentity)) {
2670
+ noWork.push(candidate.id);
2671
+ continue;
2672
+ }
2673
+ prepared.push({
2674
+ candidate,
2675
+ windows,
2676
+ windowSourceKey: chunkWindowSourceKey(canonicalText, candidate.startMessage, candidate.endMessage, maxInputTokens)
2677
+ });
2678
+ }
2679
+ if (prepared.length === 0)
2680
+ return { embedded: 0, noWork, failed, failureReasons };
2681
+ let embedded = 0;
2682
+ let i = 0;
2683
+ while (i < prepared.length) {
2684
+ if (signal?.aborted)
2685
+ break;
2686
+ const slice = [];
2687
+ let windowCount = 0;
2688
+ do {
2689
+ const item = prepared[i];
2690
+ slice.push(item);
2691
+ windowCount += item.windows.length;
2692
+ i += 1;
2693
+ } while (i < prepared.length && windowCount + prepared[i].windows.length <= MAX_WINDOWS_PER_EMBED_CALL);
2694
+ const items = slice.flatMap((item) => item.windows.map((window) => ({
2695
+ id: `chunk:${item.candidate.id}:${window.windowIndex}`,
2696
+ text: window.text,
2697
+ contentSha256: contentSha2562(window.text)
2698
+ })));
2699
+ const persistedIds = new Set;
2700
+ for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
2701
+ if (signal?.aborted)
2702
+ break;
2703
+ await new Promise((resolve) => setTimeout(resolve, 15));
2704
+ let result = null;
2705
+ const attemptStart = Date.now();
2706
+ try {
2707
+ result = await embedItemsWindowBounded(projectIdentity, items, signal, db);
2708
+ } catch (error) {
2709
+ log2("[magic-context] failed to proactively embed compartment chunks:", error);
2710
+ }
2711
+ if (signal?.aborted)
2712
+ break;
2713
+ if (!result || result.vectors.size === 0) {
2714
+ const failure = getLastEmbeddingFailureForProject(projectIdentity);
2715
+ if (failure)
2716
+ failureReasons.push(failure);
2717
+ }
2718
+ if (result) {
2719
+ let writeSliceStarted = performance.now();
2720
+ for (const item of slice) {
2721
+ if (persistedIds.has(item.candidate.id))
2722
+ continue;
2723
+ const vectors = item.windows.map((window) => result.vectors.get(`chunk:${item.candidate.id}:${window.windowIndex}`));
2724
+ if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
2725
+ continue;
2726
+ }
2727
+ const rows = item.windows.map((window, index) => ({
2728
+ compartmentId: item.candidate.id,
2729
+ sessionId: item.candidate.sessionId,
2730
+ projectPath: projectIdentity,
2731
+ window,
2732
+ modelId,
2733
+ vector: vectors[index]
2734
+ }));
2735
+ replaceCompartmentChunkEmbeddings(db, rows, item.windowSourceKey);
2736
+ persistedIds.add(item.candidate.id);
2737
+ enqueueShadowEmbeddingItems2(projectIdentity, "chunk", [
2738
+ String(item.candidate.id)
2739
+ ]);
2740
+ if (performance.now() - writeSliceStarted >= 35) {
2741
+ await new Promise((resolve) => setTimeout(resolve, 0));
2742
+ writeSliceStarted = performance.now();
2743
+ }
2744
+ }
2745
+ }
2746
+ if (persistedIds.size === slice.length)
2747
+ break;
2748
+ if (persistedIds.size > 0)
2749
+ break;
2750
+ if (Date.now() - attemptStart >= EMBED_SLOW_FAILURE_NO_RETRY_MS)
2751
+ break;
2752
+ if (attempt < EMBED_SLICE_RETRY_ATTEMPTS - 1) {
2753
+ await new Promise((resolve) => setTimeout(resolve, EMBED_SLICE_RETRY_BASE_MS * 2 ** attempt));
2754
+ }
2755
+ }
2756
+ embedded += persistedIds.size;
2757
+ if (!signal?.aborted) {
2758
+ for (const item of slice) {
2759
+ if (!persistedIds.has(item.candidate.id)) {
2760
+ recordChunkEmbedBackoff(db, item.candidate, projectIdentity, modelId);
2761
+ failed.push(item.candidate.id);
2762
+ }
2763
+ }
2764
+ }
2765
+ }
2766
+ return { embedded, noWork, failed, failureReasons };
2767
+ }
2768
+ async function drainCompartmentChunkBacklogForProject(db, projectIdentity, deadline) {
2769
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2770
+ if (!snapshot?.historyEnabled)
2771
+ return 0;
2772
+ const holderId = `chunk-embed-sweep-${randomUUID()}`;
2773
+ const lease = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
2774
+ if (!lease.acquired) {
2775
+ return 0;
2776
+ }
2777
+ let total = 0;
2778
+ let leaseLost = false;
2779
+ const renewal = setInterval(() => {
2780
+ try {
2781
+ if (!renewGitSweepLease(db, projectIdentity, holderId))
2782
+ leaseLost = true;
2783
+ } catch {}
2784
+ }, SESSION_EMBED_LEASE_RENEWAL_MS);
2785
+ renewal.unref?.();
2786
+ try {
2787
+ while (!leaseLost && !isEmbeddingHostBusy2() && Date.now() < deadline && total < CHUNK_DRAIN_MAX_PER_SWEEP) {
2788
+ const embedded = await embedCompartmentChunkBatch(db, projectIdentity, CHUNK_DRAIN_BATCH_SIZE);
2789
+ if (!renewGitSweepLease(db, projectIdentity, holderId))
2790
+ leaseLost = true;
2791
+ if (leaseLost || embedded === 0)
2792
+ break;
2793
+ total += embedded;
2794
+ if (embedded < CHUNK_DRAIN_BATCH_SIZE)
2795
+ break;
2796
+ }
2797
+ } finally {
2798
+ clearInterval(renewal);
2799
+ releaseGitSweepLease(db, projectIdentity, holderId);
2800
+ }
2801
+ return total;
2802
+ }
2803
+ async function embedUnembeddedCompartmentChunksForProject2(db, projectIdentity) {
2804
+ return drainCompartmentChunkBacklogForProject(db, projectIdentity, Date.now() + SWEEP_MAX_WALL_CLOCK_MS);
2805
+ }
2806
+ async function embedSessionCompartmentChunks2(db, projectIdentity, sessionId, options) {
2807
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2808
+ if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off") {
2809
+ return { status: "disabled", embedded: 0, total: 0 };
2810
+ }
2811
+ recordSessionProjectIdentity(db, sessionId, projectIdentity);
2812
+ const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectIdentity);
2813
+ const total = await countUnembeddedSessionCompartmentsPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens);
2814
+ const holderId = `session-embed-${randomUUID()}`;
2815
+ const lease = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
2816
+ if (!lease.acquired)
2817
+ return { status: "busy", embedded: 0, total };
2818
+ let leaseLost = false;
2819
+ const drainAbort = new AbortController;
2820
+ const forwardCallerAbort = () => drainAbort.abort();
2821
+ if (options?.signal?.aborted)
2822
+ drainAbort.abort();
2823
+ else
2824
+ options?.signal?.addEventListener("abort", forwardCallerAbort, { once: true });
2825
+ const renewal = setInterval(() => {
2826
+ try {
2827
+ if (!renewGitSweepLease(db, projectIdentity, holderId)) {
2828
+ leaseLost = true;
2829
+ drainAbort.abort();
2830
+ }
2831
+ } catch {}
2832
+ }, SESSION_EMBED_LEASE_RENEWAL_MS);
2833
+ renewal.unref?.();
2834
+ const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
2835
+ const skipIds = [];
2836
+ const failedIds = [];
2837
+ let embedded = 0;
2838
+ let aborted = false;
2839
+ let providerDown = false;
2840
+ let consecutiveFailedBatches = 0;
2841
+ const failureReasons = [];
2842
+ try {
2843
+ options?.onProgress?.({ embedded, total });
2844
+ for (;; ) {
2845
+ if (leaseLost || drainAbort.signal.aborted || isEmbeddingHostBusy2()) {
2846
+ aborted = true;
2847
+ break;
2848
+ }
2849
+ const candidates = await loadUnembeddedSessionChunkCandidatesPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds], maxInputTokens, true);
2850
+ if (candidates.length === 0)
2851
+ break;
2852
+ const {
2853
+ embedded: n,
2854
+ noWork,
2855
+ failed,
2856
+ failureReasons: batchFailureReasons
2857
+ } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, drainAbort.signal);
2858
+ if (leaseLost || !renewGitSweepLease(db, projectIdentity, holderId)) {
2859
+ leaseLost = true;
2860
+ drainAbort.abort();
2861
+ aborted = true;
2862
+ break;
2863
+ }
2864
+ failureReasons.push(...batchFailureReasons);
2865
+ for (const id of noWork)
2866
+ skipIds.push(id);
2867
+ for (const id of failed)
2868
+ failedIds.push(id);
2869
+ if (n === 0 && noWork.length === 0) {
2870
+ consecutiveFailedBatches += 1;
2871
+ if (consecutiveFailedBatches >= MAX_CONSECUTIVE_FAILED_BATCHES) {
2872
+ providerDown = true;
2873
+ break;
2874
+ }
2875
+ } else {
2876
+ consecutiveFailedBatches = 0;
2877
+ }
2878
+ embedded += n;
2879
+ options?.onProgress?.({ embedded: Math.min(embedded, total), total });
2880
+ await new Promise((resolve) => setTimeout(resolve, 15));
2881
+ }
2882
+ } finally {
2883
+ clearInterval(renewal);
2884
+ options?.signal?.removeEventListener("abort", forwardCallerAbort);
2885
+ try {
2886
+ releaseGitSweepLease(db, projectIdentity, holderId);
2887
+ } catch (error) {
2888
+ log2("[magic-context] embed drain: lease release failed (will TTL-expire):", error);
2889
+ }
2890
+ }
2891
+ if (total === 0)
2892
+ return { status: "nothing", embedded: 0, total: 0 };
2893
+ if (aborted)
2894
+ return { status: "aborted", embedded, total, failed: failedIds.length };
2895
+ if (providerDown || failedIds.length > 0) {
2896
+ const remaining = Math.max(failedIds.length, await countUnembeddedSessionCompartmentsPolite(db, projectIdentity, sessionId, snapshot.chunkModelId, maxInputTokens) - skipIds.length);
2897
+ if (remaining > 0) {
2898
+ return {
2899
+ status: "stalled",
2900
+ embedded,
2901
+ total,
2902
+ remaining,
2903
+ failed: failedIds.length,
2904
+ failure: dominantEmbeddingFailure(failureReasons)
2905
+ };
2906
+ }
2907
+ }
2908
+ return { status: "done", embedded, total, failed: failedIds.length };
2909
+ }
2910
+ function getEmbeddingCoverageStatus2(db, projectIdentity, sessionId) {
2911
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2912
+ if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off") {
2913
+ return {
2914
+ enabled: false,
2915
+ model: snapshot?.model ?? "off",
2916
+ provider: snapshot?.provider ?? "off",
2917
+ ...snapshot?.synapseDescriptor ? { synapseDescriptor: snapshot.synapseDescriptor } : {},
2918
+ session: { embedded: 0, total: 0 },
2919
+ memories: { embedded: 0, total: 0 },
2920
+ commits: { embedded: 0, total: 0, gitEnabled: false },
2921
+ shadowBackfillStalls: listShadowBackfillStalls2(db, projectIdentity)
2922
+ };
2923
+ }
2924
+ const session = countSessionCompartmentEmbedCoverage(db, projectIdentity, sessionId, snapshot.chunkModelId, getProjectEmbeddingMaxInputTokens2(projectIdentity));
2925
+ const memories = snapshot.enabled ? getMemoryEmbedCoverage(db, projectIdentity, snapshot.modelId) : { embedded: 0, total: 0, memoryEnabled: false };
2926
+ const gitEnabled = snapshot.gitCommitEnabled;
2927
+ const commits = gitEnabled ? {
2928
+ embedded: countEmbeddedCommits(db, projectIdentity, snapshot.modelId),
2929
+ total: getCommitCount(db, projectIdentity),
2930
+ gitEnabled: true
2931
+ } : { embedded: 0, total: 0, gitEnabled: false };
2932
+ return {
2933
+ enabled: true,
2934
+ model: snapshot.model,
2935
+ provider: snapshot.provider,
2936
+ ...snapshot.synapseDescriptor ? { synapseDescriptor: snapshot.synapseDescriptor } : {},
2937
+ session,
2938
+ memories,
2939
+ commits,
2940
+ shadowBackfillStalls: listShadowBackfillStalls2(db, projectIdentity)
2941
+ };
2942
+ }
2943
+ async function sweepAllRegisteredProjects2(db, batchSize = 10) {
2944
+ if (projectSweepInProgress || isEmbeddingHostBusy2()) {
2945
+ log2("[magic-context] project embedding sweep already in progress, skipping this tick");
2946
+ return {
2947
+ memoriesEmbedded: 0,
2948
+ commitsEmbedded: 0,
2949
+ chunksEmbedded: 0,
2950
+ perProject: new Map
2951
+ };
2952
+ }
2953
+ projectSweepInProgress = true;
2954
+ const startedAt = Date.now();
2955
+ const deadline = startedAt + SWEEP_MAX_WALL_CLOCK_MS;
2956
+ const perProject = new Map;
2957
+ let memoriesEmbedded = 0;
2958
+ let commitsEmbedded = 0;
2959
+ let chunksEmbedded = 0;
2960
+ try {
2961
+ for (const projectIdentity of projectRegistrations.keys()) {
2962
+ let memories = 0;
2963
+ let commits = 0;
2964
+ let chunks = 0;
2965
+ let consecutiveEmpty = 0;
2966
+ while (Date.now() < deadline && !isEmbeddingHostBusy2()) {
2967
+ const count = await embedUnembeddedMemoriesForProject2(db, projectIdentity, batchSize);
2968
+ if (count === 0) {
2969
+ consecutiveEmpty += 1;
2970
+ if (consecutiveEmpty >= SWEEP_MAX_CONSECUTIVE_EMPTY)
2971
+ break;
2972
+ break;
2973
+ }
2974
+ consecutiveEmpty = 0;
2975
+ memories += count;
2976
+ memoriesEmbedded += count;
2977
+ if (count < batchSize)
2978
+ break;
2979
+ }
2980
+ if (Date.now() < deadline) {
2981
+ commits = await drainCommitBacklogForProject2(db, projectIdentity, deadline);
2982
+ commitsEmbedded += commits;
2983
+ }
2984
+ if (Date.now() < deadline) {
2985
+ chunks = await drainCompartmentChunkBacklogForProject(db, projectIdentity, deadline);
2986
+ chunksEmbedded += chunks;
2987
+ }
2988
+ perProject.set(projectIdentity, { memories, commits, chunks });
2989
+ if (Date.now() >= deadline)
2990
+ break;
2991
+ }
2992
+ } finally {
2993
+ projectSweepInProgress = false;
2994
+ }
2995
+ return { memoriesEmbedded, commitsEmbedded, chunksEmbedded, perProject };
2996
+ }
2997
+ function _setTestProviderFactoryForProject2(factory) {
2998
+ testProviderFactory = factory;
2999
+ }
3000
+ function _resetProjectEmbeddingRegistryForTests2() {
3001
+ for (const registration of projectRegistrations.values()) {
3002
+ disposeProvider(registration.provider);
3003
+ }
3004
+ for (const registration of shadowRegistrations.values()) {
3005
+ disposeProvider(registration.provider);
3006
+ }
3007
+ projectRegistrations.clear();
3008
+ shadowRegistrations.clear();
3009
+ shadowQueue.length = 0;
3010
+ pendingShadowBackfills.clear();
3011
+ shadowBackfillLastIds.clear();
3012
+ shadowBackfillStopReasons.clear();
3013
+ shadowBackfillLastWriteOutcomes.clear();
3014
+ dbForShadowQueue.clear();
3015
+ untrustedLoadProjects.clear();
3016
+ globalRegistrationGeneration = 0;
3017
+ projectSweepInProgress = false;
3018
+ testProviderFactory = null;
3019
+ shadowBackfillNow = () => Date.now();
3020
+ setBootQuietPeriodForTests(null);
3021
+ }
3022
+
3023
+ export { recordEmbeddingMeasurement, drainBackgroundBatches, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitSha, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, OpenAICompatibleEmbeddingProvider, recordSessionProjectIdentity, hasRecordedSessionProjectIdentity, describeShadowBackfillWriteRefusal2, listShadowBackfillStalls2, getShadowBackfillStopReason2, markProjectLoadUntrusted2, contentSha2562, drainProjectEmbeddingIdentityMaintenance2, drainStaleEmbeddingIdentitiesForProject2, registerProjectEmbedding2, registerProjectShadowEmbedding2, getShadowEmbeddingMeasurementCohort2, getPrimaryEmbeddingMeasurementCohort2, embedShadowTextForProject2, enqueueShadowEmbeddingItems2, getShadowBackfillRemaining2, flushShadowEmbeddingBacklog2, registerProjectInObservationMode2, unregisterProjectShadowEmbedding2, unregisterProjectEmbedding2, getProjectEmbeddingSnapshot2, installProjectEmbeddingSearchBridge2, getProjectChunkEmbeddingModelId2, getProjectEmbeddingMaxInputTokens2, embedTextForProject2, embedBatchForProject2, embedItemsForProject2, embedUnembeddedMemoriesForProject2, embedUnembeddedMemoriesForProjectOutcome2, drainCommitBacklogForProject2, embedUnembeddedCompartmentChunksForProject2, embedSessionCompartmentChunks2, getEmbeddingCoverageStatus2, sweepAllRegisteredProjects2, _setTestProviderFactoryForProject2, _resetProjectEmbeddingRegistryForTests2 };