@cortexkit/opencode-magic-context 0.49.34 → 0.49.35

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 (220) hide show
  1. package/dist/auto-search-worker.js +11 -6
  2. package/dist/chunk-embedding-write-worker.js +16 -14
  3. package/dist/{compaction-marker-candidates-31h86ph0.js → compaction-marker-candidates-g0p67ced.js} +3 -2
  4. package/dist/compaction-marker-candidates-worker.js +1 -1
  5. package/dist/{compartment-chunk-embedding-5q5gj67r.js → compartment-chunk-embedding-y4136are.js} +8 -7
  6. package/dist/{conflict-warning-hook-xgskea1v.js → conflict-warning-hook-hhw8z5ak.js} +9 -8
  7. package/dist/{context-p3xrarzt.js → context-fk8e3h9p.js} +1400 -701
  8. package/dist/{derive-budgets-pqybnx09.js → derive-budgets-htj16n4x.js} +3 -2
  9. package/dist/embedding-backfill-q6n72sy0.js +27 -0
  10. package/dist/embedding-worker-process.js +2 -1
  11. package/dist/embedding-worker.js +5 -4
  12. package/dist/expand-attachments-h33jbgyz.js +21 -0
  13. package/dist/features/magic-context/auto-search-diagnostics.d.ts +21 -0
  14. package/dist/features/magic-context/auto-search-diagnostics.d.ts.map +1 -0
  15. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +1 -1
  16. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  17. package/dist/features/magic-context/search.d.ts +4 -0
  18. package/dist/features/magic-context/search.d.ts.map +1 -1
  19. package/dist/features/magic-context/store-generation-rebase-labels.d.ts +6 -0
  20. package/dist/features/magic-context/store-generation-rebase-labels.d.ts.map +1 -0
  21. package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
  22. package/dist/{history-owner-36wp3mkb.js → history-owner-0z620wgz.js} +3 -2
  23. package/dist/hooks/magic-context/apply-operations.d.ts +20 -3
  24. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/auto-search-observation.d.ts +13 -0
  26. package/dist/hooks/magic-context/auto-search-observation.d.ts.map +1 -0
  27. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +5 -1
  29. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/compartment-commit-hashes.d.ts +4 -0
  31. package/dist/hooks/magic-context/compartment-commit-hashes.d.ts.map +1 -0
  32. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +1 -0
  33. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/final-wire-completeness.d.ts +15 -0
  36. package/dist/hooks/magic-context/final-wire-completeness.d.ts.map +1 -0
  37. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  38. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +1 -0
  39. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/read-session-chunk.d.ts +11 -0
  41. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  42. package/dist/hooks/magic-context/read-session-formatting.d.ts +2 -0
  43. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  44. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  46. package/dist/{index-as2amvn3.js → index-0c7p8mq5.js} +6 -531
  47. package/dist/{index-51rdvtkz.js → index-1rhgxqs8.js} +2 -2
  48. package/dist/index-2amn2s73.js +123 -0
  49. package/dist/{index-c7phnbvk.js → index-2p37txes.js} +1 -1
  50. package/dist/index-2qbtqg1w.js +529 -0
  51. package/dist/{index-waktfbjy.js → index-2v6nvy3k.js} +4 -4
  52. package/dist/{index-ftr84kkv.js → index-3d3872c6.js} +7 -5
  53. package/dist/{index-0677w9sd.js → index-3j9t1v4n.js} +55 -21
  54. package/dist/{index-atekmqef.js → index-4bgk5ztz.js} +363 -5499
  55. package/dist/{index-b88dwwrh.js → index-4xyjr62e.js} +1 -1
  56. package/dist/index-66a50f3e.js +777 -0
  57. package/dist/{index-04z754rd.js → index-87ctnzz9.js} +33 -5
  58. package/dist/{index-xrnsygfq.js → index-9wnbnx8f.js} +1 -1
  59. package/dist/{index-97spytxq.js → index-b6xz3qbe.js} +246 -420
  60. package/dist/{index-7g9dr8gy.js → index-brg2w6qc.js} +113 -133
  61. package/dist/{index-spwjbkc7.js → index-dnqqqc5f.js} +1 -1
  62. package/dist/index-dy7w6wm4.js +194 -0
  63. package/dist/{index-m1x9ghk5.js → index-ezv6dz3y.js} +37 -7
  64. package/dist/index-f297z1n8.js +4557 -0
  65. package/dist/{index-qgh1qwjj.js → index-f9b3vtt1.js} +1 -1
  66. package/dist/{index-v15ne3a3.js → index-faxb7mck.js} +2 -2
  67. package/dist/{index-rrv26qjz.js → index-fw42ms3m.js} +1 -1
  68. package/dist/{index-t5pck3ss.js → index-fxbk7gk3.js} +1 -1
  69. package/dist/{index-wfybj1dw.js → index-g4t7850m.js} +2 -2
  70. package/dist/{index-fm36bjv4.js → index-gyaa159j.js} +18 -276
  71. package/dist/{index-4pnsgvfk.js → index-hacf2tyx.js} +1 -1
  72. package/dist/{index-s1n8dd2n.js → index-jkanybgq.js} +2 -2
  73. package/dist/{index-2743x98y.js → index-jn0ddrhp.js} +29 -138
  74. package/dist/{index-h7tgn49j.js → index-jrfre9ah.js} +5 -222
  75. package/dist/{index-kfyb3k6n.js → index-jz5bk7xd.js} +2 -2
  76. package/dist/{index-np3rgfw4.js → index-ksv0a31x.js} +3 -3
  77. package/dist/{index-7kkphb6c.js → index-nj360hcs.js} +4 -4
  78. package/dist/{index-gkee6p4g.js → index-p56dszfp.js} +3 -3
  79. package/dist/{index-9gpw8hrm.js → index-pq0dpwrc.js} +4 -4
  80. package/dist/{index-rfxzazzy.js → index-pswsyf1w.js} +4 -4
  81. package/dist/{index-y1qwzvxn.js → index-pztqab6k.js} +2 -2
  82. package/dist/{index-rverk2vz.js → index-qncw9hey.js} +1 -1
  83. package/dist/index-qx8j6kds.js +270 -0
  84. package/dist/{index-kq5w68dp.js → index-txs8tce6.js} +1 -1
  85. package/dist/index-vzhhr1ht.js +532 -0
  86. package/dist/index-wh9fxds5.js +265 -0
  87. package/dist/{index-hbx7m8he.js → index-x2mrq5xv.js} +170 -48
  88. package/dist/{index-07vskjn8.js → index-xwwsbsd3.js} +15 -13
  89. package/dist/index-z4p0ry94.js +222 -0
  90. package/dist/index-z9zygwse.js +89 -0
  91. package/dist/{index-v7287tzq.js → index-zhqwda72.js} +19 -8
  92. package/dist/index.js +83 -72
  93. package/dist/{logger-94kew5wm.js → logger-qwnbcfj9.js} +2 -1
  94. package/dist/{message-fts-rowid-map-va36knh4.js → message-fts-rowid-map-xg7hr0mk.js} +5 -4
  95. package/dist/{message-index-bounded-qh91fdr3.js → message-index-bounded-narw7bnz.js} +12 -11
  96. package/dist/{message-time-backfill-4qva0b4f.js → message-time-backfill-39bm498k.js} +3 -2
  97. package/dist/migration-worker.js +13 -11
  98. package/dist/{project-embedding-registry-6yex0r9f.js → project-embedding-registry-tdz7985n.js} +13 -11
  99. package/dist/raw-ordinal-warmup-worker.js +12 -7
  100. package/dist/{read-session-chunk-kaghtr75.js → read-session-chunk-vmg1zjg0.js} +15 -10
  101. package/dist/{read-session-raw-b2sd67v4.js → read-session-raw-mncmzbm9.js} +3 -2
  102. package/dist/recomp-orchestrator-qyyhnc9b.js +68 -0
  103. package/dist/render-c5p0k846.js +43 -0
  104. package/dist/{safe-notification-target-mkr9yzvr.js → safe-notification-target-wztd7bgk.js} +3 -2
  105. package/dist/{search-archive-1kw2rp19.js → search-archive-0ny7p3bw.js} +13 -11
  106. package/dist/{search-p684j8ww.js → search-f6hwvcxk.js} +26 -23
  107. package/dist/{send-session-notification-vz86nt79.js → send-session-notification-0gwcz3fw.js} +7 -6
  108. package/dist/{storage-tags-6hvkk01c.js → storage-tags-zx1023km.js} +5 -4
  109. package/dist/store-620rjzt9.js +21 -0
  110. package/dist/store-reader-yh19h38c.js +14 -0
  111. package/dist/tools/ctx-expand/render.d.ts +5 -3
  112. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  113. package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -1
  114. package/dist/tools/ctx-expand/tools.d.ts +2 -0
  115. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  116. package/dist/tools/ctx-expand/v2-archive-reader.d.ts +33 -0
  117. package/dist/tools/ctx-expand/v2-archive-reader.d.ts.map +1 -0
  118. package/dist/{transform-postprocess-phase-ph38mhrs.js → transform-postprocess-phase-807ff6t2.js} +36 -30
  119. package/dist/v2/auto-search-worker.js +11 -6
  120. package/dist/v2/chunk-embedding-write-worker.js +16 -14
  121. package/dist/v2/{compaction-marker-candidates-m4vmye3w.js → compaction-marker-candidates-t1aq6gsj.js} +3 -2
  122. package/dist/v2/compaction-marker-candidates-worker.js +1 -1
  123. package/dist/v2/{compartment-chunk-embedding-rc31e6md.js → compartment-chunk-embedding-ncsk0r9e.js} +8 -7
  124. package/dist/v2/{context-s60hcatx.js → context-znqfkap4.js} +1725 -1095
  125. package/dist/v2/{derive-budgets-knf763tt.js → derive-budgets-sa0v7bz0.js} +4 -3
  126. package/dist/v2/embedding-backfill-11j425e0.js +26 -0
  127. package/dist/v2/embedding-worker-process.js +2 -1
  128. package/dist/v2/embedding-worker.js +5 -4
  129. package/dist/v2/expand-attachments-h33jbgyz.js +21 -0
  130. package/dist/v2/fold/idle.d.ts +15 -0
  131. package/dist/v2/fold/idle.d.ts.map +1 -0
  132. package/dist/v2/fold/native-replay-v3.d.ts +68 -0
  133. package/dist/v2/fold/native-replay-v3.d.ts.map +1 -0
  134. package/dist/v2/fold/native-replay.d.ts +58 -2
  135. package/dist/v2/fold/native-replay.d.ts.map +1 -1
  136. package/dist/v2/fold/policy.d.ts +2 -1
  137. package/dist/v2/fold/policy.d.ts.map +1 -1
  138. package/dist/v2/{history-owner-ad0crnrn.js → history-owner-fpka43cn.js} +3 -2
  139. package/dist/v2/hooks/context.d.ts.map +1 -1
  140. package/dist/v2/hooks/expand-attachments.d.ts +8 -0
  141. package/dist/v2/hooks/expand-attachments.d.ts.map +1 -0
  142. package/dist/v2/hooks/overflow-recovery.d.ts +45 -0
  143. package/dist/v2/hooks/overflow-recovery.d.ts.map +1 -0
  144. package/dist/v2/hooks/store.d.ts +7 -2
  145. package/dist/v2/hooks/store.d.ts.map +1 -1
  146. package/dist/v2/{logger-p34mjtja.js → logger-4cj6d03m.js} +2 -1
  147. package/dist/v2/{message-fts-rowid-map-78awh03v.js → message-fts-rowid-map-rmk571mb.js} +5 -4
  148. package/dist/v2/{message-index-bounded-4htdr1j6.js → message-index-bounded-620bppw7.js} +12 -11
  149. package/dist/v2/{message-time-backfill-zvthw6xb.js → message-time-backfill-0c4h7sg6.js} +3 -2
  150. package/dist/v2/migration-worker.js +13 -11
  151. package/dist/v2/ordinal-range.fixture.d.ts +7 -0
  152. package/dist/v2/ordinal-range.fixture.d.ts.map +1 -0
  153. package/dist/v2/{project-embedding-registry-1x5qe2fy.js → project-embedding-registry-bm5fe1a8.js} +13 -11
  154. package/dist/v2/raw-ordinal-warmup-worker.js +12 -7
  155. package/dist/v2/{read-session-chunk-1fa9qzwb.js → read-session-chunk-qfwv1k71.js} +15 -10
  156. package/dist/v2/{read-session-raw-5x088amc.js → read-session-raw-q294t8xs.js} +3 -2
  157. package/dist/v2/recomp-orchestrator-fcnjref7.js +67 -0
  158. package/dist/v2/render-98a1qv0b.js +42 -0
  159. package/dist/v2/{safe-notification-target-khnzg57c.js → safe-notification-target-gphhast7.js} +3 -2
  160. package/dist/v2/{search-archive-xfp51s0g.js → search-archive-r0y1bafr.js} +13 -11
  161. package/dist/v2/{search-wf8rqxhm.js → search-z1zqzsmh.js} +25 -22
  162. package/dist/v2/{send-session-notification-x5nzy34v.js → send-session-notification-fst6hkg7.js} +7 -6
  163. package/dist/v2/{server-qvy4qavp.js → server-1xesqm5h.js} +113 -133
  164. package/dist/v2/server-2amn2s73.js +123 -0
  165. package/dist/v2/{server-6g98c227.js → server-3schkz95.js} +4 -4
  166. package/dist/v2/server-468mya5v.js +209 -0
  167. package/dist/v2/server-55v5hpth.js +270 -0
  168. package/dist/v2/server-5jp38p98.js +532 -0
  169. package/dist/v2/{server-qjvk4a9t.js → server-69m30b21.js} +1 -1
  170. package/dist/v2/{server-jw5qe9y8.js → server-7ccxt4nq.js} +14 -216
  171. package/dist/v2/{server-3mz2qh5a.js → server-969cdpmg.js} +1 -1
  172. package/dist/v2/{server-835q39kd.js → server-9k0mjef7.js} +2 -2
  173. package/dist/v2/{server-qc915kw2.js → server-bez34e60.js} +4 -4
  174. package/dist/v2/{server-nxas8v1d.js → server-bpvsvtph.js} +3 -3
  175. package/dist/v2/{server-ab8017gw.js → server-bxpz2dcn.js} +29 -138
  176. package/dist/v2/{server-bsgd4dk1.js → server-dcws5831.js} +2 -2
  177. package/dist/v2/server-ef1mskas.js +777 -0
  178. package/dist/v2/{server-1bw1wcbp.js → server-f0j864ma.js} +1 -1
  179. package/dist/v2/{server-z2wft9zv.js → server-fqj6ddpr.js} +402 -5497
  180. package/dist/v2/{server-grakwy1v.js → server-hnknwaz8.js} +37 -7
  181. package/dist/v2/{server-h1byrhwx.js → server-hsf0qsn5.js} +19 -8
  182. package/dist/v2/{server-6495nmn9.js → server-jb6tjyeb.js} +5 -222
  183. package/dist/v2/{server-2aasmpsp.js → server-kkxzwa6w.js} +4 -4
  184. package/dist/v2/{server-a7x00tw8.js → server-mfn1yf9d.js} +1 -1
  185. package/dist/v2/{server-tkdabx8q.js → server-q0z2q2dx.js} +5 -530
  186. package/dist/v2/{server-ajxhrgjv.js → server-qa74bj91.js} +77 -17
  187. package/dist/v2/server-qf2kzsh2.js +4513 -0
  188. package/dist/v2/{server-gyy4k6mf.js → server-qmmkhz2z.js} +1 -1
  189. package/dist/v2/{server-29qp8nz4.js → server-qxzbmtqt.js} +1 -1
  190. package/dist/v2/{server-m1pfg2d4.js → server-r3chnxs5.js} +4 -4
  191. package/dist/v2/{server-vr4szghm.js → server-rktnzs89.js} +2 -2
  192. package/dist/v2/{server-6vd2n183.js → server-s9xgyyj9.js} +1 -1
  193. package/dist/v2/{server-53eh1r8r.js → server-sd8hvzte.js} +2 -2
  194. package/dist/v2/{server-k3t06fxr.js → server-sefxj8k1.js} +1 -1
  195. package/dist/v2/{server-v77xa5wj.js → server-tpt7bwq8.js} +1 -1
  196. package/dist/v2/{server-awr8qa4c.js → server-ws5exe6q.js} +2 -2
  197. package/dist/v2/server-x4m6xcn4.js +194 -0
  198. package/dist/v2/{server-806rzhs6.js → server-xbtw0p9t.js} +1 -1
  199. package/dist/v2/{server-cqjvxyrp.js → server-xy7w7hrd.js} +2 -2
  200. package/dist/v2/server-ypf1ap0v.js +529 -0
  201. package/dist/v2/server-z4p0ry94.js +222 -0
  202. package/dist/v2/server-z9zygwse.js +89 -0
  203. package/dist/v2/{server-ab1g0wn9.js → server-zzgtgqmd.js} +2 -2
  204. package/dist/v2/server.js +6 -5
  205. package/dist/v2/{storage-tags-18nbaanf.js → storage-tags-19s0ebf0.js} +5 -4
  206. package/dist/v2/store-reader-cgx47zkp.js +14 -0
  207. package/dist/v2/store-reader.d.ts +9 -2
  208. package/dist/v2/store-reader.d.ts.map +1 -1
  209. package/dist/v2/store-vdm8v3jd.js +21 -0
  210. package/dist/v2/v2-archive-reader-t2c0eypn.js +11 -0
  211. package/dist/v2/{wrapup-orchestrator-wxf7n5k6.js → wrapup-orchestrator-aqpqsveg.js} +46 -39
  212. package/dist/v2-archive-reader-tm2eayp2.js +11 -0
  213. package/dist/wrapup-orchestrator-k5yp19a6.js +55 -0
  214. package/package.json +1 -1
  215. package/src/shared/sqlite-transaction-mode-guard.test.ts +2 -0
  216. package/dist/embedding-backfill-0jgtqxen.js +0 -25
  217. package/dist/recomp-orchestrator-0y983w7h.js +0 -62
  218. package/dist/v2/embedding-backfill-f43hd8y6.js +0 -24
  219. package/dist/v2/recomp-orchestrator-7q9nvxte.js +0 -61
  220. package/dist/wrapup-orchestrator-ys2nrkkb.js +0 -49
@@ -0,0 +1,4557 @@
1
+ import {
2
+ tagTombstoneOwnerRange,
3
+ tagTombstoneOwnerKey,
4
+ tagRevisionKey,
5
+ tagIdentityRevisionKey,
6
+ deleteTagIdentityRevisions,
7
+ getTableColumnNames
8
+ } from "./index-9wnbnx8f.js";
9
+ import {
10
+ invalidateAutoEmbedSession,
11
+ drainBackgroundBatches
12
+ } from "./index-2amn2s73.js";
13
+ import {
14
+ getHarness2
15
+ } from "./index-pavzsdc6.js";
16
+ import {
17
+ getDataDir,
18
+ getMagicContextStorageDir
19
+ } from "./index-g2q4htwp.js";
20
+ import {
21
+ log2,
22
+ sessionLog2
23
+ } from "./index-jrfre9ah.js";
24
+ import {
25
+ prepareCachedStatement2,
26
+ withSqliteBackgroundWriter2,
27
+ withoutSqliteTransformPass2
28
+ } from "./index-gzy5w8ya.js";
29
+ import {
30
+ deleteUnmappedMessageFtsRows2
31
+ } from "./index-faxb7mck.js";
32
+ import {
33
+ deleteChunkEmbedBackoffForSession2
34
+ } from "./index-zhqwda72.js";
35
+ import {
36
+ isPidAlive,
37
+ readProcessStartTime
38
+ } from "./index-2p37txes.js";
39
+ import {
40
+ MERGED_REASONING_PARTS_PREFIX,
41
+ decodeMergedReasoningParts,
42
+ SESSION_META_SELECT_COLUMNS,
43
+ META_COLUMNS,
44
+ BOOLEAN_META_KEYS,
45
+ NULL_BIND_META_KEYS,
46
+ isSessionMetaRow,
47
+ getDefaultSessionMeta,
48
+ ensureSessionMetaRow,
49
+ toSessionMeta,
50
+ isRustMarkerAdmissionFenced,
51
+ readReplayEnvelope,
52
+ readReplayDocument,
53
+ updateReplayDocument,
54
+ writeReplayDocument,
55
+ parseStrippedPlaceholderState,
56
+ serializeStrippedPlaceholderState,
57
+ THINKING_BINDING_RECOVERY_FROZEN_PREFIX,
58
+ THINKING_BINDING_STRIP_ORDER_END_MARKER,
59
+ COMPACTION_OFF_THINKING_FROZEN_PREFIX,
60
+ getMergedReasoningStrippedIds,
61
+ addMergedReasoningStrippedIds,
62
+ parseProcessedImageMarkers,
63
+ serializeProcessedImageMarkers,
64
+ getPendingPiCompactionMarkerState,
65
+ logPiCompactionMarkerClear
66
+ } from "./index-brg2w6qc.js";
67
+ import {
68
+ stripTagPrefix,
69
+ isRecord,
70
+ providerVisibleMessage
71
+ } from "./index-ksv0a31x.js";
72
+ import {
73
+ withReadOnlySessionDb
74
+ } from "./index-pztqab6k.js";
75
+ import {
76
+ BoundedSessionMap,
77
+ getMeasuredToolDefinitionTokens
78
+ } from "./index-jkanybgq.js";
79
+ import {
80
+ layoutLkgPrefix,
81
+ assembleLkgPrefix
82
+ } from "./index-nj360hcs.js";
83
+ import {
84
+ gaDatabasePath2,
85
+ V2StoreReader2
86
+ } from "./index-66a50f3e.js";
87
+ import {
88
+ markCoveredInstructionRow,
89
+ isCoveredInstructionRow
90
+ } from "./index-z9zygwse.js";
91
+ import {
92
+ piModelRefToCanonical
93
+ } from "./index-avwt563y.js";
94
+ import {
95
+ logSlowWriteTransaction
96
+ } from "./index-fxbk7gk3.js";
97
+ import {
98
+ ensurePrivateStorageDirectorySync,
99
+ writeStorageFileSync,
100
+ writeStorageFileAtomicSync,
101
+ syncStorageDirectorySync,
102
+ writeStorageFileDurableAtomicSync
103
+ } from "./index-fvnzcnww.js";
104
+
105
+ // src/features/magic-context/session-activity.ts
106
+ var PREFIX = "retrospective_activity:";
107
+ var INTERVAL_MS = 15000;
108
+ var pending = new WeakMap;
109
+ function sessionActivityKey(sessionId) {
110
+ return `${PREFIX}${sessionId}`;
111
+ }
112
+ function deleteSessionActivity(db, sessionIds) {
113
+ if (sessionIds.length === 0)
114
+ return;
115
+ const sessions = pending.get(db);
116
+ for (const sessionId of sessionIds) {
117
+ const state = sessions?.get(sessionId);
118
+ if (state?.timer)
119
+ clearTimeout(state.timer);
120
+ sessions?.delete(sessionId);
121
+ }
122
+ const placeholders = sessionIds.map(() => "?").join(", ");
123
+ db.prepare(`DELETE FROM schema_migrations_meta WHERE key IN (${placeholders})`).run(...sessionIds.map(sessionActivityKey));
124
+ deleteTagIdentityRevisions(db, sessionIds);
125
+ }
126
+ function advanceSessionActivity(db, sessionId, time) {
127
+ if (!sessionId || !Number.isFinite(time) || time <= 0)
128
+ return;
129
+ db.prepare(`INSERT INTO schema_migrations_meta (key, value) VALUES (?, ?)
130
+ ON CONFLICT(key) DO UPDATE SET value = CAST(MAX(CAST(value AS INTEGER), CAST(excluded.value AS INTEGER)) AS TEXT)`).run(sessionActivityKey(sessionId), String(Math.floor(time)));
131
+ }
132
+ function observeSessionActivity(db, sessionId, time = Date.now()) {
133
+ if (!sessionId || !Number.isFinite(time) || time <= 0)
134
+ return;
135
+ let sessions = pending.get(db);
136
+ if (!sessions) {
137
+ sessions = new Map;
138
+ pending.set(db, sessions);
139
+ }
140
+ const current = sessions.get(sessionId);
141
+ if (!current || time - current.lastWrite >= INTERVAL_MS) {
142
+ if (current?.timer)
143
+ clearTimeout(current.timer);
144
+ advanceSessionActivity(db, sessionId, Math.max(time, current?.latest ?? 0));
145
+ sessions.set(sessionId, { lastWrite: time, latest: time });
146
+ return;
147
+ }
148
+ current.latest = Math.max(current.latest, time);
149
+ if (!current.timer) {
150
+ current.timer = setTimeout(() => {
151
+ current.timer = undefined;
152
+ try {
153
+ advanceSessionActivity(db, sessionId, current.latest);
154
+ current.lastWrite = Date.now();
155
+ } catch {
156
+ sessions.delete(sessionId);
157
+ }
158
+ }, Math.max(1, INTERVAL_MS - (time - current.lastWrite)));
159
+ current.timer.unref?.();
160
+ }
161
+ }
162
+ async function backfillSessionActivity(db, harness, latestTime) {
163
+ const completedKey = `retrospective_activity_backfill:${harness}:v1`;
164
+ if (db.prepare("SELECT 1 FROM schema_migrations_meta WHERE key = ?").get(completedKey))
165
+ return;
166
+ let cursor = "";
167
+ while (true) {
168
+ const rows = db.prepare(`SELECT session_id FROM session_projects
169
+ WHERE harness = ? AND session_id > ? ORDER BY session_id LIMIT 100`).all(harness, cursor);
170
+ if (rows.length === 0)
171
+ break;
172
+ for (const row of rows) {
173
+ const time = await latestTime(row.session_id);
174
+ if (time !== undefined)
175
+ advanceSessionActivity(db, row.session_id, time);
176
+ }
177
+ cursor = rows[rows.length - 1].session_id;
178
+ await new Promise((resolve) => setTimeout(resolve, 0));
179
+ }
180
+ db.prepare("INSERT OR IGNORE INTO schema_migrations_meta (key, value) VALUES (?, 'completed')").run(completedKey);
181
+ }
182
+
183
+ // src/features/magic-context/compartment-lease.ts
184
+ var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
185
+ var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
186
+ function getCompartmentLeaseBlocker(db, sessionId) {
187
+ const row = db.prepare(`SELECT holder_id AS holderId, owner_pid AS ownerPid,
188
+ acquired_at AS acquiredAt, expires_at AS expiresAt
189
+ FROM compartment_state_lease
190
+ WHERE session_id = ? AND expires_at > ?`).get(sessionId, Date.now());
191
+ return row ?? null;
192
+ }
193
+ function acquireCompartmentLease(db, sessionId, holderId) {
194
+ const acquiredAt = Date.now();
195
+ const expiresAt = acquiredAt + COMPARTMENT_LEASE_TTL_MS;
196
+ const ownerPid = process.pid;
197
+ const blocker = getCompartmentLeaseBlocker(db, sessionId);
198
+ if (blocker?.ownerPid && isPidAlive(blocker.ownerPid) === "dead") {
199
+ const reclaimed = db.prepare(`DELETE FROM compartment_state_lease
200
+ WHERE session_id = ? AND holder_id = ? AND owner_pid = ?
201
+ AND acquired_at = ? AND expires_at = ?`).run(sessionId, blocker.holderId, blocker.ownerPid, blocker.acquiredAt, blocker.expiresAt);
202
+ if (reclaimed.changes === 1) {
203
+ sessionLog2(sessionId, `reclaimed compartment lease from dead owner holder=${blocker.holderId} pid=${blocker.ownerPid}`);
204
+ }
205
+ }
206
+ const result = db.prepare(`INSERT INTO compartment_state_lease
207
+ (session_id, holder_id, owner_pid, acquired_at, expires_at)
208
+ VALUES (?, ?, ?, ?, ?)
209
+ ON CONFLICT(session_id) DO UPDATE SET
210
+ holder_id = excluded.holder_id,
211
+ owner_pid = excluded.owner_pid,
212
+ acquired_at = excluded.acquired_at,
213
+ expires_at = excluded.expires_at
214
+ WHERE compartment_state_lease.holder_id = excluded.holder_id
215
+ OR compartment_state_lease.expires_at <= ?`).run(sessionId, holderId, ownerPid, acquiredAt, expiresAt, acquiredAt);
216
+ if (result.changes !== 1) {
217
+ return null;
218
+ }
219
+ return { sessionId, holderId, acquiredAt, expiresAt, ownerPid };
220
+ }
221
+ function renewCompartmentLease(db, sessionId, holderId) {
222
+ const now = Date.now();
223
+ const expiresAt = now + COMPARTMENT_LEASE_TTL_MS;
224
+ const result = db.prepare(`UPDATE compartment_state_lease
225
+ SET expires_at = ?, acquired_at = ?
226
+ WHERE session_id = ? AND holder_id = ? AND expires_at > ?`).run(expiresAt, now, sessionId, holderId, now);
227
+ return result.changes === 1;
228
+ }
229
+ function releaseCompartmentLease(db, sessionId, holderId) {
230
+ db.prepare("DELETE FROM compartment_state_lease WHERE session_id = ? AND holder_id = ?").run(sessionId, holderId);
231
+ }
232
+ function releaseCompartmentLeaseBestEffort(db, sessionId, holderId, log = sessionLog2) {
233
+ try {
234
+ releaseCompartmentLease(db, sessionId, holderId);
235
+ } catch (err) {
236
+ log(sessionId, `lease release failed (${err instanceof Error ? err.message : String(err)}); row expires on its TTL`);
237
+ }
238
+ }
239
+ function isCompartmentLeaseHeld(db, sessionId, holderId) {
240
+ const row = db.prepare("SELECT 1 FROM compartment_state_lease WHERE session_id = ? AND holder_id = ? AND expires_at > ?").get(sessionId, holderId, Date.now());
241
+ return row != null;
242
+ }
243
+
244
+ // src/features/magic-context/no-content-compartment.ts
245
+ function isNoContentCompartment(row) {
246
+ return [row.title, row.content, row.p1, row.p2, row.p3, row.p4].every((value) => !value);
247
+ }
248
+
249
+ // src/features/magic-context/storage-m0-mutation-log.ts
250
+ var M0_MUTATION_TYPES = new Set([
251
+ "compartment_delete",
252
+ "compartment_merge",
253
+ "recomp_boundary_change",
254
+ "compartment_upgrade"
255
+ ]);
256
+ function assertMutationType(mutationType) {
257
+ if (!M0_MUTATION_TYPES.has(mutationType)) {
258
+ throw new Error(`Invalid m0 mutation type: ${mutationType}`);
259
+ }
260
+ }
261
+ function toM0Mutation(row) {
262
+ return {
263
+ id: row.id,
264
+ sessionId: row.session_id,
265
+ mutationType: row.mutation_type,
266
+ targetId: row.target_id,
267
+ queuedAt: row.queued_at
268
+ };
269
+ }
270
+ function queueM0Mutation(db, input) {
271
+ assertMutationType(input.mutationType);
272
+ const result = db.prepare(`INSERT INTO m0_mutation_log (session_id, mutation_type, target_id, queued_at)
273
+ VALUES (?, ?, ?, ?)`).run(input.sessionId, input.mutationType, input.targetId ?? null, input.queuedAt ?? Date.now());
274
+ const row = getM0Mutation(db, Number(result.lastInsertRowid));
275
+ if (!row) {
276
+ throw new Error("Failed to load queued m0 mutation");
277
+ }
278
+ return row;
279
+ }
280
+ function getM0Mutation(db, id) {
281
+ const row = db.prepare(`SELECT id, session_id, mutation_type, target_id, queued_at
282
+ FROM m0_mutation_log
283
+ WHERE id = ?`).get(id);
284
+ return row ? toM0Mutation(row) : null;
285
+ }
286
+ function getMaxM0MutationId(db, sessionId) {
287
+ const row = db.prepare("SELECT MAX(id) AS max_id FROM m0_mutation_log WHERE session_id = ?").get(sessionId);
288
+ return row?.max_id ?? null;
289
+ }
290
+
291
+ // src/features/magic-context/compartment-storage.ts
292
+ var insertCompartmentStatements = new WeakMap;
293
+ var insertFactStatements = new WeakMap;
294
+ function getInsertCompartmentStatement(db) {
295
+ let stmt = insertCompartmentStatements.get(db);
296
+ if (!stmt) {
297
+ stmt = db.prepare("INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, p1, p2, p3, p4, importance, episode_type, legacy, created_at, harness, start_block_index, end_block_index) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
298
+ insertCompartmentStatements.set(db, stmt);
299
+ }
300
+ return stmt;
301
+ }
302
+ function isStringOrNullish(v) {
303
+ return v === null || v === undefined || typeof v === "string";
304
+ }
305
+ function isNumberOrNullish(v) {
306
+ return v === null || v === undefined || typeof v === "number";
307
+ }
308
+ function isCompartmentRow(row) {
309
+ if (row === null || typeof row !== "object")
310
+ return false;
311
+ const candidate = row;
312
+ return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && isStringOrNullish(candidate.p1) && isStringOrNullish(candidate.p2) && isStringOrNullish(candidate.p3) && isStringOrNullish(candidate.p4) && isNumberOrNullish(candidate.importance) && isStringOrNullish(candidate.episode_type) && isNumberOrNullish(candidate.legacy) && typeof candidate.created_at === "number";
313
+ }
314
+ function insertCompartmentRows(db, sessionId, compartments, now) {
315
+ const stmt = getInsertCompartmentStatement(db);
316
+ for (const compartment of compartments) {
317
+ const hasTiers = typeof compartment.p1 === "string" && compartment.p1.length > 0;
318
+ stmt.run(sessionId, compartment.sequence, compartment.startMessage, compartment.endMessage, compartment.startMessageId, compartment.endMessageId, compartment.title, compartment.content, compartment.p1 ?? null, compartment.p2 ?? null, compartment.p3 ?? null, compartment.p4 ?? null, typeof compartment.importance === "number" ? compartment.importance : 50, compartment.episodeType ?? null, hasTiers || isNoContentCompartment(compartment) ? 0 : 1, now, getHarness2(), compartment.startBlockIndex ?? null, compartment.endBlockIndex ?? null);
319
+ }
320
+ if (compartments.length > 0)
321
+ invalidateAutoEmbedSession(sessionId);
322
+ }
323
+ function toCompartment(row) {
324
+ return {
325
+ id: row.id,
326
+ sessionId: row.session_id,
327
+ sequence: row.sequence,
328
+ startMessage: row.start_message,
329
+ endMessage: row.end_message,
330
+ startMessageId: row.start_message_id,
331
+ endMessageId: row.end_message_id,
332
+ ...row.start_block_index != null ? { startBlockIndex: row.start_block_index } : {},
333
+ ...row.end_block_index != null ? { endBlockIndex: row.end_block_index } : {},
334
+ title: row.title,
335
+ content: row.content,
336
+ p1: row.p1 ?? null,
337
+ p2: row.p2 ?? null,
338
+ p3: row.p3 ?? null,
339
+ p4: row.p4 ?? null,
340
+ importance: typeof row.importance === "number" ? row.importance : 50,
341
+ episodeType: row.episode_type ?? null,
342
+ legacy: typeof row.legacy === "number" ? row.legacy : 0,
343
+ createdAt: row.created_at,
344
+ rebaseStatus: row.rebase_status === "unresolved" ? "unresolved" : "ok"
345
+ };
346
+ }
347
+ function getCompartments(db, sessionId) {
348
+ const presentColumns = getTableColumnNames(db, "compartments");
349
+ const columns = [
350
+ "id",
351
+ "session_id",
352
+ "sequence",
353
+ "start_message",
354
+ "end_message",
355
+ "start_message_id",
356
+ "end_message_id",
357
+ "start_block_index",
358
+ "end_block_index",
359
+ "title",
360
+ "content",
361
+ "p1",
362
+ "p2",
363
+ "p3",
364
+ "p4",
365
+ "importance",
366
+ "episode_type",
367
+ "legacy",
368
+ "created_at",
369
+ "rebase_status"
370
+ ].filter((column) => presentColumns.has(column));
371
+ const rows = db.prepare(`SELECT ${columns.length ? columns.join(", ") : "NULL AS id"}
372
+ FROM compartments WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentRow);
373
+ return rows.map(toCompartment);
374
+ }
375
+ function getLastCompartmentEndMessage(db, sessionId) {
376
+ const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ? AND rebase_status != 'unresolved'").get(sessionId);
377
+ return row?.max_end ?? -1;
378
+ }
379
+ function getLastCompartmentEndMessageId(db, sessionId) {
380
+ const row = db.prepare("SELECT end_message_id FROM compartments WHERE session_id = ? AND rebase_status != 'unresolved' AND end_message_id IS NOT NULL AND end_message_id != '' ORDER BY sequence DESC LIMIT 1").get(sessionId);
381
+ const id = row?.end_message_id;
382
+ return id && id.length > 0 ? id : null;
383
+ }
384
+ function getCompartmentsByEndMessageId(db, sessionId, endMessageId) {
385
+ const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? AND end_message_id = ? ORDER BY sequence ASC").all(sessionId, endMessageId).filter(isCompartmentRow);
386
+ return rows.map(toCompartment);
387
+ }
388
+ function appendCompartments(db, sessionId, compartments) {
389
+ if (compartments.length === 0)
390
+ return;
391
+ const now = Date.now();
392
+ db.transaction(() => {
393
+ insertCompartmentRows(db, sessionId, compartments, now);
394
+ }).immediate();
395
+ }
396
+ function buildCompartmentBlock(compartments, facts, memoryBlock, dateRanges) {
397
+ const lines = [];
398
+ if (memoryBlock) {
399
+ lines.push(memoryBlock);
400
+ lines.push("");
401
+ }
402
+ for (const c of compartments) {
403
+ if (isNoContentCompartment(c))
404
+ continue;
405
+ const dates = dateRanges?.byId.get(c.id);
406
+ const dateAttr = dates ? ` start-date="${dates.start}" end-date="${dates.end}"` : "";
407
+ lines.push(`<compartment start="${c.startMessage}" end="${c.endMessage}"${dateAttr} title="${escapeXmlAttr(c.title)}">`);
408
+ lines.push(escapeXmlContent(c.content));
409
+ lines.push("</compartment>");
410
+ lines.push("");
411
+ }
412
+ const factsByCategory = new Map;
413
+ for (const f of facts) {
414
+ const existing = factsByCategory.get(f.category) ?? [];
415
+ existing.push(f.content);
416
+ factsByCategory.set(f.category, existing);
417
+ }
418
+ for (const [category, items] of factsByCategory) {
419
+ lines.push(`${category}:`);
420
+ for (const item of items) {
421
+ lines.push(`* ${escapeXmlContent(item)}`);
422
+ }
423
+ lines.push("");
424
+ }
425
+ return lines.join(`
426
+ `).trimEnd();
427
+ }
428
+ function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
429
+ const now = Date.now();
430
+ db.transaction(() => {
431
+ db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
432
+ const compartmentStmt = db.prepare("INSERT OR REPLACE INTO recomp_compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, p1, p2, p3, p4, importance, episode_type, pass_number, created_at, harness, start_block_index, end_block_index) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
433
+ for (const c of compartments) {
434
+ compartmentStmt.run(sessionId, c.sequence, c.startMessage, c.endMessage, c.startMessageId, c.endMessageId, c.title, c.content, c.p1 ?? null, c.p2 ?? null, c.p3 ?? null, c.p4 ?? null, typeof c.importance === "number" ? c.importance : 50, c.episodeType ?? null, passNumber, now, getHarness2(), c.startBlockIndex ?? null, c.endBlockIndex ?? null);
435
+ }
436
+ const factStmt = db.prepare("INSERT INTO recomp_facts (session_id, category, content, pass_number, created_at, harness) VALUES (?, ?, ?, ?, ?, ?)");
437
+ for (const f of facts) {
438
+ factStmt.run(sessionId, f.category, f.content, passNumber, now, getHarness2());
439
+ }
440
+ }).immediate();
441
+ }
442
+ function getRecompStaging(db, sessionId) {
443
+ const compartmentRows = db.prepare("SELECT * FROM recomp_compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isRecompCompartmentRow);
444
+ if (compartmentRows.length === 0)
445
+ return null;
446
+ const compartments = compartmentRows.map((row) => ({
447
+ sequence: row.sequence,
448
+ startMessage: row.start_message,
449
+ endMessage: row.end_message,
450
+ startMessageId: row.start_message_id,
451
+ endMessageId: row.end_message_id,
452
+ ...row.start_block_index != null ? { startBlockIndex: row.start_block_index } : {},
453
+ ...row.end_block_index != null ? { endBlockIndex: row.end_block_index } : {},
454
+ title: row.title,
455
+ content: row.content,
456
+ p1: row.p1 ?? null,
457
+ p2: row.p2 ?? null,
458
+ p3: row.p3 ?? null,
459
+ p4: row.p4 ?? null,
460
+ importance: typeof row.importance === "number" ? row.importance : 50,
461
+ episodeType: row.episode_type ?? null
462
+ }));
463
+ const factRows = db.prepare("SELECT category, content FROM recomp_facts WHERE session_id = ?").all(sessionId).filter(isRecompFactRow);
464
+ const maxPass = compartmentRows.reduce((m, r) => Math.max(m, r.pass_number), 0);
465
+ const lastEnd = compartmentRows[compartmentRows.length - 1]?.end_message ?? 0;
466
+ return {
467
+ compartments,
468
+ facts: factRows,
469
+ passCount: maxPass,
470
+ lastEndMessage: lastEnd
471
+ };
472
+ }
473
+ function clearRecompStaging(db, sessionId) {
474
+ db.transaction(() => {
475
+ db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
476
+ db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
477
+ try {
478
+ db.prepare("UPDATE session_meta SET recomp_partial_range_start = 0, recomp_partial_range_end = 0 WHERE session_id = ?").run(sessionId);
479
+ } catch {}
480
+ }).immediate();
481
+ }
482
+ function getRecompPartialRange(db, sessionId) {
483
+ try {
484
+ const row = db.prepare("SELECT recomp_partial_range_start AS start, recomp_partial_range_end AS end FROM session_meta WHERE session_id = ?").get(sessionId);
485
+ const start = typeof row?.start === "number" ? row.start : 0;
486
+ const end = typeof row?.end === "number" ? row.end : 0;
487
+ if (start <= 0 || end <= 0)
488
+ return null;
489
+ return { start, end };
490
+ } catch {
491
+ return null;
492
+ }
493
+ }
494
+ function setRecompPartialRange(db, sessionId, range) {
495
+ const start = range ? range.start : 0;
496
+ const end = range ? range.end : 0;
497
+ db.prepare("INSERT OR IGNORE INTO session_meta (session_id) VALUES (?)").run(sessionId);
498
+ db.prepare("UPDATE session_meta SET recomp_partial_range_start = ?, recomp_partial_range_end = ? WHERE session_id = ?").run(start, end, sessionId);
499
+ }
500
+ function isRecompCompartmentRow(row) {
501
+ if (row === null || typeof row !== "object")
502
+ return false;
503
+ const candidate = row;
504
+ return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && isStringOrNullish(candidate.p1) && isStringOrNullish(candidate.p2) && isStringOrNullish(candidate.p3) && isStringOrNullish(candidate.p4) && isNumberOrNullish(candidate.importance) && isStringOrNullish(candidate.episode_type) && typeof candidate.pass_number === "number" && typeof candidate.created_at === "number";
505
+ }
506
+ function isRecompFactRow(row) {
507
+ if (row === null || typeof row !== "object")
508
+ return false;
509
+ const candidate = row;
510
+ return typeof candidate.category === "string" && typeof candidate.content === "string";
511
+ }
512
+ function escapeXmlAttr(s) {
513
+ return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
514
+ }
515
+ function escapeXmlContent(s) {
516
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
517
+ }
518
+ function getUncoveredCompartmentEndsThrough(db, sessionId, endOrdinal = Number.MAX_SAFE_INTEGER, afterOrdinal = -1) {
519
+ const rows = db.prepare(`SELECT k.end_message_id, k.end_message,
520
+ n.start_message_id AS successor_id, n.start_message AS successor_start FROM compartments k
521
+ LEFT JOIN compartments n ON n.session_id = k.session_id AND n.sequence = k.sequence + 1
522
+ WHERE k.session_id = ?1 AND k.end_message <= ?2 AND k.end_message > ?3 AND k.end_block_index IS NOT NULL
523
+ AND NOT COALESCE(n.sequence IS NOT NULL AND (
524
+ (n.start_message_id = k.end_message_id AND n.start_block_index > k.end_block_index)
525
+ OR n.start_message = k.end_message + 1), 0)
526
+ ORDER BY k.sequence`).all(sessionId, endOrdinal, afterOrdinal);
527
+ return rows.map((row) => ({
528
+ endMessageId: row.end_message_id,
529
+ endMessage: row.end_message,
530
+ successorStartMessageId: row.successor_id,
531
+ successorStartMessage: row.successor_start
532
+ }));
533
+ }
534
+ function isPartialCompartmentEnd(db, sessionId, messageId) {
535
+ return Boolean(db.prepare("SELECT 1 FROM compartments WHERE session_id=? AND end_message_id=? AND end_block_index IS NOT NULL LIMIT 1").get(sessionId, messageId));
536
+ }
537
+ // src/features/magic-context/project-docs-hash.ts
538
+ import { createHash } from "node:crypto";
539
+ import { lstatSync, readFileSync, statSync } from "node:fs";
540
+ import path from "node:path";
541
+ var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
542
+ var PROJECT_DOCS_DELIMITER = `
543
+
544
+ ---
545
+
546
+ `;
547
+ var MAX_PROJECT_DOC_BYTES = 256 * 1024;
548
+ var docsCache = new Map;
549
+ var canonicalReadCountForTests = 0;
550
+ function canonicalizeDocContent(raw) {
551
+ return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
552
+ `).split(`
553
+ `).map((line) => line.replace(/[ \t]+$/, "")).join(`
554
+ `).replace(/\n+$/, "");
555
+ }
556
+ function fingerprintFile(filePath) {
557
+ try {
558
+ const stat = lstatSync(filePath);
559
+ const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
560
+ return {
561
+ exists: isReadableDoc,
562
+ mtimeMs: stat.mtimeMs,
563
+ size: stat.size
564
+ };
565
+ } catch {
566
+ return { exists: false, mtimeMs: 0, size: 0 };
567
+ }
568
+ }
569
+ function readDirectoryMtimeMs(projectDirectory) {
570
+ try {
571
+ return statSync(projectDirectory).mtimeMs;
572
+ } catch {
573
+ return 0;
574
+ }
575
+ }
576
+ function fingerprintsEqual(a, b) {
577
+ return a?.exists === b.exists && a.mtimeMs === b.mtimeMs && a.size === b.size;
578
+ }
579
+ function cacheFilesEqual(cachedFiles, currentFiles) {
580
+ for (const [filePath, current] of currentFiles) {
581
+ if (!fingerprintsEqual(cachedFiles.get(filePath), current)) {
582
+ return false;
583
+ }
584
+ }
585
+ return true;
586
+ }
587
+ function readCurrentFingerprints(projectDirectory) {
588
+ const files = new Map;
589
+ for (const filename of PROJECT_DOC_FILES) {
590
+ const filePath = path.join(projectDirectory, filename);
591
+ files.set(filePath, fingerprintFile(filePath));
592
+ }
593
+ return { directoryMtimeMs: readDirectoryMtimeMs(projectDirectory), files };
594
+ }
595
+ function readCanonicalPieces(projectDirectory, files) {
596
+ const hashPieces = [];
597
+ const renderedSections = [];
598
+ for (const filename of PROJECT_DOC_FILES) {
599
+ const filePath = path.join(projectDirectory, filename);
600
+ const fingerprint = files.get(filePath);
601
+ if (!fingerprint?.exists) {
602
+ continue;
603
+ }
604
+ let safeToRead = false;
605
+ try {
606
+ const st = lstatSync(filePath);
607
+ safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
608
+ } catch {
609
+ safeToRead = false;
610
+ }
611
+ if (!safeToRead) {
612
+ continue;
613
+ }
614
+ const canonicalContent = canonicalizeDocContent(readFileSync(filePath, "utf8"));
615
+ hashPieces.push(`file:${filename}
616
+ ${canonicalContent}`);
617
+ renderedSections.push(`<file name="${escapeXmlAttr(filename)}">
618
+ ${escapeXmlContent(canonicalContent)}
619
+ </file>`);
620
+ }
621
+ return { hashPieces, renderedSections };
622
+ }
623
+ function buildRenderedBlock(renderedSections) {
624
+ if (renderedSections.length === 0) {
625
+ return "";
626
+ }
627
+ return `<project-docs>
628
+ ${renderedSections.join(`
629
+
630
+ `)}
631
+ </project-docs>`;
632
+ }
633
+ function hashCanonicalPieces(hashPieces) {
634
+ if (hashPieces.length === 0) {
635
+ return "";
636
+ }
637
+ return createHash("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
638
+ }
639
+ function readProjectDocsCanonical(projectDirectory) {
640
+ canonicalReadCountForTests += 1;
641
+ const canonicalDirectory = path.resolve(projectDirectory);
642
+ const current = readCurrentFingerprints(canonicalDirectory);
643
+ const cached = docsCache.get(canonicalDirectory);
644
+ if (cached && cacheFilesEqual(cached.files, current.files)) {
645
+ cached.directoryMtimeMs = current.directoryMtimeMs;
646
+ return {
647
+ renderedBlock: cached.cachedRendered,
648
+ canonicalHash: cached.cachedHash
649
+ };
650
+ }
651
+ const { hashPieces, renderedSections } = readCanonicalPieces(canonicalDirectory, current.files);
652
+ const canonicalHash = hashCanonicalPieces(hashPieces);
653
+ const renderedBlock = buildRenderedBlock(renderedSections);
654
+ docsCache.set(canonicalDirectory, {
655
+ directoryMtimeMs: current.directoryMtimeMs,
656
+ files: current.files,
657
+ cachedHash: canonicalHash,
658
+ cachedRendered: renderedBlock
659
+ });
660
+ return { renderedBlock, canonicalHash };
661
+ }
662
+ // src/hooks/magic-context/lkg-slot.ts
663
+ import { createHash as createHash6 } from "node:crypto";
664
+
665
+ // src/hooks/magic-context/lkg-measured-request.ts
666
+ import { createHash as createHash4 } from "node:crypto";
667
+
668
+ // src/shared/provider-response-completion.ts
669
+ function providerResponseFailed(input) {
670
+ if (input.error !== undefined && input.error !== null && input.error !== "")
671
+ return true;
672
+ const finish = typeof input.finish === "string" ? input.finish.trim().toLowerCase() : "";
673
+ return ["error", "failed", "abort", "aborted", "interrupted", "cancelled", "canceled"].includes(finish);
674
+ }
675
+ function isSuccessfulProviderCompletion(input) {
676
+ if (providerResponseFailed(input))
677
+ return false;
678
+ return typeof input.completedAt === "number" && Number.isFinite(input.completedAt) && input.completedAt > 0 || typeof input.finish === "string" && input.finish.trim().length > 0;
679
+ }
680
+ // src/features/magic-context/storage-meta-session.ts
681
+ import { Buffer as Buffer2 } from "node:buffer";
682
+
683
+ // src/hooks/magic-context/lkg-recovery-fence.ts
684
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
685
+ import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync3, rmdirSync, rmSync as rmSync2 } from "node:fs";
686
+ import { basename, dirname, join as join2 } from "node:path";
687
+
688
+ // src/shared/storage-file-mutex.ts
689
+ import { execFileSync } from "node:child_process";
690
+ import { createHash as createHash2, randomUUID } from "node:crypto";
691
+ import { readdirSync, readFileSync as readFileSync2, rmSync } from "node:fs";
692
+ import { join } from "node:path";
693
+ var ticketChecksum = (name, ticket) => createHash2("sha256").update(JSON.stringify([name, ticket.choosing, ticket.number, ticket.birth])).digest("hex");
694
+ function processBirth(pid) {
695
+ if (process.platform === "linux") {
696
+ try {
697
+ const stat = readFileSync2(`/proc/${pid}/stat`, "utf8");
698
+ const ticks = stat.slice(stat.lastIndexOf(")") + 2).trim().split(/\s+/)[19];
699
+ if (!ticks || !/^\d+$/.test(ticks))
700
+ return null;
701
+ return `${readFileSync2("/proc/sys/kernel/random/boot_id", "utf8").trim()}:${ticks}`;
702
+ } catch {
703
+ return null;
704
+ }
705
+ }
706
+ if (process.platform === "darwin") {
707
+ try {
708
+ return execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
709
+ encoding: "utf8",
710
+ timeout: 1000,
711
+ windowsHide: true,
712
+ env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
713
+ stdio: ["ignore", "pipe", "pipe"]
714
+ }).trim() || null;
715
+ } catch {
716
+ return null;
717
+ }
718
+ }
719
+ const start = readProcessStartTime(pid);
720
+ return start === null ? null : String(start);
721
+ }
722
+ var pause = new Int32Array(new SharedArrayBuffer(4));
723
+ function withStorageFileMutex(directory, work, timeoutMs = 1000) {
724
+ ensurePrivateStorageDirectorySync(directory);
725
+ const name = `${process.pid}-${randomUUID()}.lock`;
726
+ const ownPath = join(directory, name);
727
+ const birth = processBirth(process.pid);
728
+ const ticket = { choosing: true, number: 0, birth, checksum: "" };
729
+ const encodedTicket = () => JSON.stringify({ ...ticket, checksum: ticketChecksum(name, ticket) });
730
+ for (let attempt = 0;; attempt++) {
731
+ try {
732
+ writeStorageFileSync(ownPath, encodedTicket(), { flag: "wx", forcePrivate: true });
733
+ break;
734
+ } catch (error) {
735
+ if (error.code !== "ENOENT" || attempt >= 2)
736
+ throw error;
737
+ ensurePrivateStorageDirectorySync(directory);
738
+ }
739
+ }
740
+ const deadline = performance.now() + timeoutMs;
741
+ const peers = () => {
742
+ const found = [];
743
+ for (const other of readdirSync(directory)) {
744
+ if (other === name || !/^\d+-[\da-f-]+\.lock$/.test(other))
745
+ continue;
746
+ const pid = Number(other.split("-")[0]);
747
+ const otherPath = join(directory, other);
748
+ let value = null;
749
+ try {
750
+ const parsed = JSON.parse(readFileSync2(otherPath, "utf8"));
751
+ if (typeof parsed.choosing === "boolean" && Number.isSafeInteger(parsed.number) && parsed.number >= 0 && (parsed.birth === null || typeof parsed.birth === "string") && parsed.checksum === ticketChecksum(other, parsed))
752
+ value = parsed;
753
+ } catch (error) {
754
+ if (error.code === "ENOENT")
755
+ continue;
756
+ }
757
+ const alive = isPidAlive(pid);
758
+ const actualBirth = alive === "alive" && value?.birth ? processBirth(pid) : null;
759
+ if (alive === "dead" || actualBirth !== null && value?.birth && actualBirth !== value.birth) {
760
+ rmSync(otherPath, { force: true });
761
+ continue;
762
+ }
763
+ found.push([other, value]);
764
+ }
765
+ return found;
766
+ };
767
+ try {
768
+ ticket.number = 1 + Math.max(0, ...peers().map(([, value]) => value?.number ?? 0));
769
+ ticket.choosing = false;
770
+ writeStorageFileAtomicSync(ownPath, encodedTicket(), true);
771
+ while (peers().some(([other, value]) => !value || value.choosing || value.number < ticket.number || value.number === ticket.number && other < name)) {
772
+ if (performance.now() >= deadline)
773
+ throw new Error("Storage safety publication lock is unavailable");
774
+ Atomics.wait(pause, 0, 0, 10);
775
+ }
776
+ const result = work();
777
+ if (result && typeof result.then === "function")
778
+ throw new TypeError("Storage publication mutex requires synchronous work");
779
+ return result;
780
+ } finally {
781
+ rmSync(ownPath, { force: true });
782
+ }
783
+ }
784
+
785
+ // src/hooks/magic-context/lkg-recovery-fence.ts
786
+ class LkgRecoveryFenceError extends Error {
787
+ constructor(message) {
788
+ super(message);
789
+ this.name = "LkgRecoveryFenceError";
790
+ }
791
+ }
792
+ var platform = process.platform;
793
+ var observer;
794
+ var knownFences = new BoundedSessionMap(1000);
795
+ var ioObserver;
796
+ var cacheKey = (sessionId) => `${getMagicContextStorageDir()}\x00${getHarness2()}\x00${sessionId}`;
797
+ function remember(sessionId, value) {
798
+ knownFences.set(cacheKey(sessionId), value);
799
+ return value;
800
+ }
801
+ function known(sessionId) {
802
+ const prior = knownFences.get(cacheKey(sessionId));
803
+ if (prior)
804
+ return prior;
805
+ const record = read(sessionId);
806
+ if (record)
807
+ return remember(sessionId, { state: record.state, record });
808
+ try {
809
+ lstatSync2(lkgRecoveryFencePath(sessionId));
810
+ } catch (error) {
811
+ if (error.code === "ENOENT")
812
+ return remember(sessionId, { state: "clean", record: null });
813
+ }
814
+ return remember(sessionId, { state: "invalid", record: null });
815
+ }
816
+ function clearLkgFenceProcessState(sessionId) {
817
+ if (sessionId)
818
+ knownFences.delete(cacheKey(sessionId));
819
+ else
820
+ knownFences.clear();
821
+ }
822
+ var durableFencesSupported = () => platform !== "win32";
823
+ var hash = (value) => createHash3("sha256").update(value).digest("hex");
824
+ var lkgServedArrayDigest = hash;
825
+ function lkgRecoveryFencePath(sessionId) {
826
+ return join2(getMagicContextStorageDir(), "lkg-recovery-fences", `${hash(sessionId)}.json`);
827
+ }
828
+ function metadata(slot) {
829
+ return [
830
+ slot.inputIdSeq,
831
+ slot.inputContentDigests,
832
+ slot.inputContentSignatures ?? null,
833
+ slot.piOutputEntryIds ?? null,
834
+ slot.lastInputMessageId,
835
+ slot.modelKey,
836
+ slot.providerKey
837
+ ];
838
+ }
839
+ function representationKey(slot) {
840
+ return createHash3("sha256").update(slot.jsonPrefix).update(JSON.stringify(metadata(slot))).digest("hex");
841
+ }
842
+ function lkgRecoverySlotKey(slot) {
843
+ return hash(JSON.stringify([
844
+ representationKey(slot),
845
+ slot.capturedAt,
846
+ slot.rowVersion ?? null,
847
+ slot.captureSequence ?? null
848
+ ]));
849
+ }
850
+ function payload(record) {
851
+ return [
852
+ record.version,
853
+ record.sessionId,
854
+ record.host,
855
+ record.modelKey,
856
+ record.providerKey,
857
+ record.slotKey,
858
+ record.servedDigest,
859
+ record.revision,
860
+ record.state
861
+ ];
862
+ }
863
+ function publishRecord(record) {
864
+ ioObserver?.("write");
865
+ try {
866
+ if (record.state === "clean")
867
+ observer?.("clean");
868
+ writeStorageFileDurableAtomicSync(lkgRecoveryFencePath(record.sessionId), JSON.stringify({ ...record, checksum: hash(JSON.stringify(payload(record))) }), () => observer?.("temp-synced"));
869
+ if (record.state === "dirty")
870
+ observer?.("dirty");
871
+ remember(record.sessionId, {
872
+ state: record.state,
873
+ record: { ...record, checksum: hash(JSON.stringify(payload(record))) }
874
+ });
875
+ } catch (error) {
876
+ const visible = read(record.sessionId);
877
+ if (record.state === "clean" && visible?.state === "clean" && visible.revision === record.revision && visible.slotKey === record.slotKey) {
878
+ const dirty = { ...record, state: "dirty" };
879
+ writeStorageFileDurableAtomicSync(lkgRecoveryFencePath(record.sessionId), JSON.stringify({ ...dirty, checksum: hash(JSON.stringify(payload(dirty))) }));
880
+ }
881
+ remember(record.sessionId, { state: "invalid", record: null });
882
+ throw error;
883
+ }
884
+ }
885
+ function read(sessionId) {
886
+ ioObserver?.("read");
887
+ try {
888
+ const path = lkgRecoveryFencePath(sessionId);
889
+ const stat = lstatSync2(path);
890
+ const directory = lstatSync2(dirname(path));
891
+ if (!stat.isFile() || stat.size > 4096 || !directory.isDirectory() || directory.isSymbolicLink() || process.platform !== "win32" && ((stat.mode & 63) !== 0 || (directory.mode & 63) !== 0 || process.getuid && stat.uid !== process.getuid()))
892
+ return null;
893
+ const value = JSON.parse(readFileSync3(path, "utf8"));
894
+ if (value.version !== 1 || value.sessionId !== sessionId || value.host !== getHarness2() || value.modelKey !== null && typeof value.modelKey !== "string" || value.providerKey !== null && typeof value.providerKey !== "string" || !/^[a-f0-9]{64}$/.test(value.slotKey) || !/^[a-f0-9]{64}$/.test(value.servedDigest) || typeof value.revision !== "string" || !["clean", "dirty"].includes(value.state) || value.checksum !== hash(JSON.stringify(payload(value))))
895
+ return null;
896
+ return value;
897
+ } catch {
898
+ return null;
899
+ }
900
+ }
901
+ function publish(sessionId, slot, state, revision) {
902
+ const record = {
903
+ version: 1,
904
+ sessionId,
905
+ host: getHarness2(),
906
+ modelKey: slot.modelKey,
907
+ providerKey: slot.providerKey,
908
+ slotKey: lkgRecoverySlotKey(slot),
909
+ servedDigest: hash(slot.jsonPrefix),
910
+ revision,
911
+ state
912
+ };
913
+ publishRecord(record);
914
+ }
915
+ function locked(sessionId, work) {
916
+ ioObserver?.("mutex");
917
+ return withStorageFileMutex(`${lkgRecoveryFencePath(sessionId)}.locks`, () => {
918
+ const path = lkgRecoveryFencePath(sessionId);
919
+ for (const name of readdirSync2(dirname(path))) {
920
+ if (name.startsWith(`${basename(path)}.`) && name.endsWith(".tmp"))
921
+ rmSync2(join2(dirname(path), name), { force: true });
922
+ }
923
+ return work();
924
+ });
925
+ }
926
+ function hasCleanLkgRecoveryFence(sessionId, _slot) {
927
+ if (!durableFencesSupported())
928
+ return false;
929
+ const state = known(sessionId);
930
+ return state.state === "clean";
931
+ }
932
+ function lkgFenceRequiresRebuild(sessionId, slot, processLocalProof) {
933
+ return !processLocalProof && (durableFencesSupported() ? !hasCleanLkgRecoveryFence(sessionId, slot) : true);
934
+ }
935
+ function lkgRecoveryFenceUnclean(sessionId) {
936
+ return durableFencesSupported() && known(sessionId).state !== "clean";
937
+ }
938
+ function dirtyLkgRecoveryRevision(sessionId, _slot) {
939
+ if (!durableFencesSupported())
940
+ return;
941
+ const record = known(sessionId).record;
942
+ return record?.state === "dirty" ? record.revision : undefined;
943
+ }
944
+ function ownsLkgDirtyFence(sessionId, revision) {
945
+ if (!durableFencesSupported())
946
+ return revision === "process-local";
947
+ const record = known(sessionId).record;
948
+ return revision !== undefined && record?.state === "dirty" && record.revision === revision;
949
+ }
950
+ function invalidateCleanLkgRecoveryFence(sessionId, load, ownRevision) {
951
+ if (!durableFencesSupported())
952
+ return "process-local";
953
+ const prior = known(sessionId);
954
+ if (prior.state === "dirty")
955
+ return prior.record?.revision === ownRevision ? ownRevision : undefined;
956
+ return locked(sessionId, () => {
957
+ const slot = load() ?? {
958
+ jsonPrefix: "",
959
+ inputIdSeq: [],
960
+ inputContentDigests: [],
961
+ lastInputMessageId: "",
962
+ modelKey: null,
963
+ providerKey: null,
964
+ capturedAt: 0
965
+ };
966
+ const record = read(sessionId);
967
+ if (record?.state !== "dirty") {
968
+ const revision = randomUUID2();
969
+ publish(sessionId, slot, "dirty", revision);
970
+ return revision;
971
+ }
972
+ return record?.state === "dirty" && record.revision === ownRevision ? ownRevision : undefined;
973
+ });
974
+ }
975
+ function prepareLkgCaptureFence(args) {
976
+ if (!durableFencesSupported())
977
+ return "process-local";
978
+ return locked(args.sessionId, () => {
979
+ const before = read(args.sessionId);
980
+ const owns = before?.state === "dirty" && before.revision === args.ownDirtyRevision;
981
+ const unchangedBytes = before?.state === "clean" && before.servedDigest === hash(args.slot.jsonPrefix);
982
+ if (!args.rebuild && before && !owns && !unchangedBytes && before.state !== "clean")
983
+ throw new LkgRecoveryFenceError(`A concurrent recovery requires a declared prefix rebuild (state=${before?.state}, owned=${owns}, previous=${!!args.previousSlot}, bytes=${unchangedBytes})`);
984
+ const revision = randomUUID2();
985
+ if (before)
986
+ publishRecord({ ...before, state: "dirty", revision });
987
+ else
988
+ publish(args.sessionId, args.previousSlot ?? args.slot, "dirty", revision);
989
+ return revision;
990
+ });
991
+ }
992
+ function certifyCommittedLkgCapture(args) {
993
+ if (!durableFencesSupported())
994
+ return false;
995
+ const state = known(args.sessionId);
996
+ if (state.state !== "dirty" || state.record?.revision !== args.revision)
997
+ return false;
998
+ return locked(args.sessionId, () => {
999
+ const before = read(args.sessionId);
1000
+ if (before?.state !== "dirty" || before.revision !== args.revision)
1001
+ return false;
1002
+ const saved = args.load();
1003
+ if (!saved || representationKey(saved) !== representationKey(args.slot) || hash(saved.jsonPrefix) !== args.latestServedDigest)
1004
+ return false;
1005
+ publish(args.sessionId, saved, "clean", args.revision);
1006
+ return true;
1007
+ });
1008
+ }
1009
+ function markLkgRecoveryDirty(args) {
1010
+ if (!durableFencesSupported()) {
1011
+ if (!args.processLocalProof)
1012
+ throw new LkgRecoveryFenceError("Restart replay requires a healthy rebuild on Windows");
1013
+ return "process-local";
1014
+ }
1015
+ const state = known(args.sessionId);
1016
+ if (state.state === "dirty" && args.processLocalProof && state.record && state.record.revision === args.ownDirtyRevision)
1017
+ return state.record.revision;
1018
+ if (state.state === "invalid")
1019
+ throw new LkgRecoveryFenceError("No clean durable recovery certificate");
1020
+ return locked(args.sessionId, () => {
1021
+ const slot = args.slot;
1022
+ const before = read(args.sessionId);
1023
+ if (before?.state === "dirty") {
1024
+ if (!args.processLocalProof || before.revision !== args.ownDirtyRevision)
1025
+ throw new LkgRecoveryFenceError(`Recovery superseded this process's last-good request (local=${args.processLocalProof}, owned=${before.revision === args.ownDirtyRevision})`);
1026
+ return before.revision;
1027
+ }
1028
+ if (before && before.state !== "clean")
1029
+ throw new LkgRecoveryFenceError("No clean durable recovery certificate");
1030
+ const revision = randomUUID2();
1031
+ publish(args.sessionId, slot, "dirty", revision);
1032
+ return revision;
1033
+ });
1034
+ }
1035
+ function commitLkgWithRecoveryFence(args) {
1036
+ if (!durableFencesSupported())
1037
+ return args.commit();
1038
+ const state = known(args.sessionId);
1039
+ if (state.state === "clean" && !args.requiredRevision && !args.retainDirtyRevision) {
1040
+ const committed = args.commit();
1041
+ if (committed) {
1042
+ observer?.("committed");
1043
+ remember(args.sessionId, { state: "clean", record: null });
1044
+ }
1045
+ return committed;
1046
+ }
1047
+ if (state.state === "invalid" && !args.rebuild)
1048
+ throw new LkgRecoveryFenceError("Unproven prior request requires a prefix rebuild");
1049
+ return locked(args.sessionId, () => {
1050
+ const before = read(args.sessionId);
1051
+ if (args.requiredRevision && before?.revision !== args.requiredRevision)
1052
+ throw new LkgRecoveryFenceError("A later publisher superseded the rollback snapshot");
1053
+ const ownsDirty = before?.state === "dirty" && (before.revision === args.retainDirtyRevision || before.revision === args.ownDirtyRevision);
1054
+ if (before?.state === "dirty" && !ownsDirty && !args.rebuild)
1055
+ throw new LkgRecoveryFenceError("A concurrent recovery requires a declared prefix rebuild");
1056
+ if (before?.state !== "dirty" && state.state === "invalid")
1057
+ publish(args.sessionId, args.load() ?? args.slot, "dirty", randomUUID2());
1058
+ if (!args.commit())
1059
+ return false;
1060
+ observer?.("committed");
1061
+ const saved = args.load();
1062
+ if (!saved || representationKey(saved) !== representationKey(args.slot))
1063
+ throw new LkgRecoveryFenceError("Last-good commit did not match its certificate");
1064
+ if (args.retainDirtyRevision || args.cleanDigest !== undefined && hash(saved.jsonPrefix) !== args.cleanDigest)
1065
+ return true;
1066
+ const dirty = read(args.sessionId);
1067
+ if (dirty?.state === "dirty")
1068
+ publish(args.sessionId, saved, "clean", dirty.revision);
1069
+ else
1070
+ remember(args.sessionId, { state: "clean", record: null });
1071
+ return true;
1072
+ });
1073
+ }
1074
+ function clearLkgRecoveryFence(sessionId, remove, shouldClear) {
1075
+ if (!durableFencesSupported())
1076
+ return remove?.();
1077
+ const path = lkgRecoveryFencePath(sessionId);
1078
+ const missing = (file) => {
1079
+ try {
1080
+ lstatSync2(file);
1081
+ return false;
1082
+ } catch (error) {
1083
+ return error.code === "ENOENT";
1084
+ }
1085
+ };
1086
+ if (!remove && !shouldClear && missing(path) && missing(`${path}.locks`)) {
1087
+ clearLkgFenceProcessState(sessionId);
1088
+ return;
1089
+ }
1090
+ try {
1091
+ return locked(sessionId, () => {
1092
+ const result = remove?.();
1093
+ if (shouldClear && !shouldClear(result))
1094
+ return result;
1095
+ rmSync2(lkgRecoveryFencePath(sessionId), { force: true });
1096
+ syncStorageDirectorySync(dirname(lkgRecoveryFencePath(sessionId)));
1097
+ clearLkgFenceProcessState(sessionId);
1098
+ return result;
1099
+ });
1100
+ } finally {
1101
+ try {
1102
+ rmdirSync(`${path}.locks`);
1103
+ } catch {}
1104
+ }
1105
+ }
1106
+
1107
+ // src/shared/auto-search-lifecycle.ts
1108
+ var pending2 = new Map;
1109
+ var unpublishedNoHints = new Map;
1110
+ function rememberUnpublishedAutoSearchNoHint(sessionId, messageId, reason) {
1111
+ let messages = unpublishedNoHints.get(sessionId);
1112
+ if (!messages) {
1113
+ messages = new Map;
1114
+ unpublishedNoHints.set(sessionId, messages);
1115
+ }
1116
+ if (!messages.has(messageId))
1117
+ messages.set(messageId, reason);
1118
+ }
1119
+ function getUnpublishedAutoSearchNoHint(sessionId, messageId) {
1120
+ return unpublishedNoHints.get(sessionId)?.get(messageId);
1121
+ }
1122
+ function forgetUnpublishedAutoSearchNoHint(sessionId, messageId) {
1123
+ const messages = unpublishedNoHints.get(sessionId);
1124
+ messages?.delete(messageId);
1125
+ if (messages?.size === 0)
1126
+ unpublishedNoHints.delete(sessionId);
1127
+ }
1128
+ function clearUnpublishedAutoSearchNoHints(sessionId) {
1129
+ if (sessionId === undefined)
1130
+ unpublishedNoHints.clear();
1131
+ else
1132
+ unpublishedNoHints.delete(sessionId);
1133
+ }
1134
+ function registerAutoSearchWork(sessionId) {
1135
+ const controller = new AbortController;
1136
+ const work = pending2.get(sessionId) ?? new Set;
1137
+ pending2.set(sessionId, work);
1138
+ work.add(controller);
1139
+ return {
1140
+ signal: controller.signal,
1141
+ done: () => {
1142
+ work.delete(controller);
1143
+ if (pending2.get(sessionId) === work && work.size === 0)
1144
+ pending2.delete(sessionId);
1145
+ }
1146
+ };
1147
+ }
1148
+ function cancelAutoSearchWork(sessionId) {
1149
+ for (const [id, work] of pending2) {
1150
+ if (sessionId !== undefined && id !== sessionId)
1151
+ continue;
1152
+ pending2.delete(id);
1153
+ for (const controller of work)
1154
+ controller.abort();
1155
+ }
1156
+ }
1157
+
1158
+ // src/features/magic-context/resolve-subagent-fallback.ts
1159
+ function resolveIsSubagentFromOpenCodeDb(sessionId) {
1160
+ try {
1161
+ return withReadOnlySessionDb((openCodeDb) => {
1162
+ const row = openCodeDb.prepare("SELECT parent_id FROM session WHERE id = ?").get(sessionId);
1163
+ if (!row)
1164
+ return null;
1165
+ return typeof row.parent_id === "string" && row.parent_id.length > 0;
1166
+ });
1167
+ } catch (error) {
1168
+ log2(`[magic-context] resolveIsSubagentFromOpenCodeDb failed for ${sessionId}:`, error);
1169
+ return null;
1170
+ }
1171
+ }
1172
+ function resolveIsSubagentFromOpenCode2Db(sessionId) {
1173
+ let reader;
1174
+ try {
1175
+ reader = new V2StoreReader2(gaDatabasePath2(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
1176
+ return reader.isSubagent(sessionId);
1177
+ } catch (error) {
1178
+ log2(`[magic-context] resolveIsSubagentFromOpenCode2Db failed for ${sessionId}:`, error);
1179
+ return null;
1180
+ } finally {
1181
+ reader?.close();
1182
+ }
1183
+ }
1184
+
1185
+ // src/features/magic-context/storage-session-tables.ts
1186
+ var SESSION_SCOPED_TABLES = [
1187
+ { table: "pending_ops", harnessScoped: true },
1188
+ { table: "source_contents", harnessScoped: true },
1189
+ { table: "tool_owner_backfill_state" },
1190
+ { table: "tags", harnessScoped: true },
1191
+ { table: "session_meta", harnessScoped: true },
1192
+ {
1193
+ table: "temporal_decisions",
1194
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = temporal_decisions.session_id)"
1195
+ },
1196
+ {
1197
+ table: "session_replay_decisions",
1198
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = session_replay_decisions.session_id)"
1199
+ },
1200
+ { table: "session_projects", harnessScoped: true },
1201
+ { table: "compartment_chunk_embeddings", harnessScoped: true },
1202
+ { table: "compartments", harnessScoped: true },
1203
+ {
1204
+ table: "compartment_history_versions",
1205
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM compartments AS remaining WHERE remaining.session_id = compartment_history_versions.session_id)"
1206
+ },
1207
+ { table: "compression_depth", harnessScoped: true },
1208
+ { table: "session_facts", harnessScoped: true },
1209
+ { table: "compartment_state_lease" },
1210
+ { table: "notes", harnessScoped: true, extraPredicate: "type = 'session'" },
1211
+ { table: "recomp_compartments", harnessScoped: true },
1212
+ { table: "recomp_facts", harnessScoped: true },
1213
+ { table: "user_memory_candidates" },
1214
+ { table: "primer_candidates", harnessScoped: true },
1215
+ { table: "m0_mutation_log" },
1216
+ { table: "compartment_events", harnessScoped: true },
1217
+ { table: "subagent_invocations", harnessScoped: true },
1218
+ { table: "historian_runs", harnessScoped: true },
1219
+ { table: "plugin_messages" },
1220
+ { table: "transform_decisions", harnessScoped: true },
1221
+ { table: "synapse_batch_ledger" },
1222
+ { table: "embedding_measurement_corpus" },
1223
+ { table: "pending_session_cleanup", harnessScoped: true },
1224
+ { table: "message_history_fts" },
1225
+ { table: "message_fts_rowid_map" },
1226
+ { table: "message_history_source", harnessScoped: true },
1227
+ { table: "message_history_index", harnessScoped: true },
1228
+ { table: "lkg_slots" },
1229
+ { table: "lkg_slot_chunks" }
1230
+ ];
1231
+ var cleanupStatements = new WeakMap;
1232
+ function cleanupStatement(db, sql) {
1233
+ let cache = cleanupStatements.get(db);
1234
+ if (!cache) {
1235
+ cache = new Map;
1236
+ cleanupStatements.set(db, cache);
1237
+ }
1238
+ let statement = cache.get(sql);
1239
+ if (!statement) {
1240
+ if (cache.size >= 256)
1241
+ cache.clear();
1242
+ statement = prepareCachedStatement2(db, sql);
1243
+ cache.set(sql, statement);
1244
+ }
1245
+ return statement;
1246
+ }
1247
+ function deleteSessionScopedRows(db, sessionIds, harness, options = {}) {
1248
+ if (sessionIds.length === 0)
1249
+ return 0;
1250
+ let deletableSessionIds = [...sessionIds];
1251
+ if (options.rustModuleCleanupAcknowledged !== true) {
1252
+ const placeholders = sessionIds.map(() => "?").join(", ");
1253
+ const harnessPredicate = harness === undefined ? "" : " AND harness = ?";
1254
+ const protectedRows = cleanupStatement(db, `SELECT session_id
1255
+ FROM pending_session_cleanup
1256
+ WHERE session_id IN (${placeholders})
1257
+ AND harness LIKE '%:rust'${harnessPredicate}`).all(...sessionIds, ...harness === undefined ? [] : [`${harness}:rust`]);
1258
+ const protectedSessionIds = new Set(protectedRows.map((row) => row.session_id));
1259
+ deletableSessionIds = sessionIds.filter((sessionId) => !protectedSessionIds.has(sessionId));
1260
+ }
1261
+ if (deletableSessionIds.length === 0)
1262
+ return 0;
1263
+ const placeholders = deletableSessionIds.map(() => "?").join(", ");
1264
+ const harnessTables = SESSION_SCOPED_TABLES.filter((definition) => definition.harnessScoped);
1265
+ if (options.preserveTagRevisionTombstones) {
1266
+ const owners = cleanupStatement(db, harnessTables.map((definition) => `SELECT session_id, harness FROM ${definition.table} WHERE session_id IN (${placeholders})${definition.extraPredicate ? ` AND ${definition.extraPredicate}` : ""}`).join(" UNION ")).all(...harnessTables.flatMap(() => deletableSessionIds));
1267
+ const record = cleanupStatement(db, "INSERT OR IGNORE INTO schema_migrations_meta (key, value) VALUES (?, ?)");
1268
+ for (const owner of owners)
1269
+ record.run(tagTombstoneOwnerKey(owner.session_id, owner.harness), owner.harness);
1270
+ const fallback = cleanupStatement(db, `INSERT INTO schema_migrations_meta (key, value)
1271
+ SELECT ?, ? WHERE NOT EXISTS (SELECT 1 FROM schema_migrations_meta WHERE key >= ? AND key < ?)`);
1272
+ for (const id of deletableSessionIds)
1273
+ fallback.run(tagTombstoneOwnerKey(id, getHarness2()), getHarness2(), ...tagTombstoneOwnerRange(id));
1274
+ }
1275
+ for (const sessionId of deletableSessionIds)
1276
+ deleteChunkEmbedBackoffForSession2(db, sessionId);
1277
+ for (const definition of SESSION_SCOPED_TABLES) {
1278
+ if (definition.table === "message_history_fts") {
1279
+ cleanupStatement(db, `DELETE FROM message_history_fts
1280
+ WHERE rowid IN (
1281
+ SELECT fts_rowid
1282
+ FROM message_fts_rowid_map
1283
+ WHERE session_id IN (${placeholders})
1284
+ )`).run(...deletableSessionIds);
1285
+ deleteUnmappedMessageFtsRows2(db, deletableSessionIds);
1286
+ continue;
1287
+ }
1288
+ const predicates = [`session_id IN (${placeholders})`];
1289
+ if (definition.extraPredicate)
1290
+ predicates.push(definition.extraPredicate);
1291
+ const bindHarness = harness !== undefined && definition.harnessScoped === true;
1292
+ if (bindHarness)
1293
+ predicates.push("harness = ?");
1294
+ const statement = cleanupStatement(db, `DELETE FROM ${definition.table} WHERE ${predicates.join(" AND ")}`);
1295
+ if (bindHarness)
1296
+ statement.run(...deletableSessionIds, harness);
1297
+ else
1298
+ statement.run(...deletableSessionIds);
1299
+ }
1300
+ deleteSessionActivity(db, deletableSessionIds);
1301
+ if (!options.preserveTagRevisionTombstones) {
1302
+ const retireOwner = cleanupStatement(db, harness === undefined ? "DELETE FROM schema_migrations_meta WHERE key >= ? AND key < ?" : "DELETE FROM schema_migrations_meta WHERE key = ?");
1303
+ const survivingRows = harnessTables.map((definition) => `EXISTS (SELECT 1 FROM ${definition.table} WHERE session_id = ?${definition.extraPredicate ? ` AND ${definition.extraPredicate}` : ""})`).join(" OR ");
1304
+ const retire = cleanupStatement(db, `DELETE FROM schema_migrations_meta WHERE key IN (?, ?)
1305
+ AND NOT (${survivingRows})
1306
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta AS owners WHERE owners.key >= ? AND owners.key < ?)`);
1307
+ for (const id of deletableSessionIds) {
1308
+ if (harness === undefined)
1309
+ retireOwner.run(...tagTombstoneOwnerRange(id));
1310
+ else
1311
+ retireOwner.run(tagTombstoneOwnerKey(id, harness));
1312
+ retire.run(tagIdentityRevisionKey(id), tagRevisionKey(id), ...harnessTables.map(() => id), ...tagTombstoneOwnerRange(id));
1313
+ }
1314
+ }
1315
+ if (!options.deferRecoveryFenceCleanup)
1316
+ for (const sessionId of deletableSessionIds)
1317
+ clearLkgRecoveryFence(sessionId);
1318
+ return deletableSessionIds.length;
1319
+ }
1320
+
1321
+ // src/features/magic-context/storage-meta-session.ts
1322
+ var SESSION_META_FALLBACK_SELECTS = {
1323
+ cache_ttl: "'5m' AS cache_ttl",
1324
+ last_nudge_band: "'' AS last_nudge_band",
1325
+ last_transform_error: "'' AS last_transform_error",
1326
+ system_prompt_hash: "'' AS system_prompt_hash",
1327
+ last_todo_state: "'' AS last_todo_state",
1328
+ tool_reclaim_watermark: "0 AS tool_reclaim_watermark",
1329
+ cached_m0_bytes: "NULL AS cached_m0_bytes",
1330
+ cached_m0_mural_data_url: "NULL AS cached_m0_mural_data_url",
1331
+ cached_m0_mural_hash: "NULL AS cached_m0_mural_hash",
1332
+ cached_m1_bytes: "NULL AS cached_m1_bytes",
1333
+ cached_m0_project_memory_epoch: "NULL AS cached_m0_project_memory_epoch",
1334
+ cached_m0_project_user_profile_version: "NULL AS cached_m0_project_user_profile_version",
1335
+ cached_m0_max_compartment_seq: "NULL AS cached_m0_max_compartment_seq",
1336
+ cached_m0_max_memory_id: "NULL AS cached_m0_max_memory_id",
1337
+ cached_m0_max_mutation_id: "NULL AS cached_m0_max_mutation_id",
1338
+ cached_m0_max_memory_mutation_id: "NULL AS cached_m0_max_memory_mutation_id",
1339
+ cached_m0_project_docs_hash: "NULL AS cached_m0_project_docs_hash",
1340
+ cached_m0_materialized_at: "NULL AS cached_m0_materialized_at",
1341
+ cached_m0_session_facts_version: "NULL AS cached_m0_session_facts_version",
1342
+ cached_m0_upgrade_state: "NULL AS cached_m0_upgrade_state",
1343
+ cached_m0_system_hash: "NULL AS cached_m0_system_hash",
1344
+ cached_m0_tool_set_hash: "NULL AS cached_m0_tool_set_hash",
1345
+ cached_m0_model_key: "NULL AS cached_m0_model_key",
1346
+ cached_m0_project_identity: "NULL AS cached_m0_project_identity",
1347
+ last_observed_model_key: "NULL AS last_observed_model_key",
1348
+ upgrade_reminded_at: "NULL AS upgrade_reminded_at",
1349
+ upgrade_reminder_last_sent_at: "NULL AS upgrade_reminder_last_sent_at",
1350
+ upgrade_reminder_count: "0 AS upgrade_reminder_count"
1351
+ };
1352
+ var sessionMetaSelectColumnsCache = new WeakMap;
1353
+ function getSessionMetaSelectColumns(db) {
1354
+ const cached = sessionMetaSelectColumnsCache.get(db);
1355
+ if (cached !== undefined)
1356
+ return cached;
1357
+ const existingColumns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
1358
+ const projection = SESSION_META_SELECT_COLUMNS.map((column) => {
1359
+ if (existingColumns.has(column))
1360
+ return column;
1361
+ return SESSION_META_FALLBACK_SELECTS[column] ?? `0 AS ${column}`;
1362
+ }).join(", ");
1363
+ sessionMetaSelectColumnsCache.set(db, projection);
1364
+ return projection;
1365
+ }
1366
+ function findSessionMeta(db, sessionId) {
1367
+ const result = db.prepare(`SELECT ${getSessionMetaSelectColumns(db)} FROM session_meta WHERE session_id = ?`).get(sessionId);
1368
+ return isSessionMetaRow(result) ? toSessionMeta(result) : undefined;
1369
+ }
1370
+ function readSessionMeta(db, sessionId) {
1371
+ return findSessionMeta(db, sessionId) ?? getDefaultSessionMeta(sessionId);
1372
+ }
1373
+ var parentReadRetries = new WeakMap;
1374
+ var PARENT_READ_ATTEMPTS = 5;
1375
+ var PARENT_READ_COOLDOWN_MS = 30000;
1376
+ function getOrCreateSessionMeta(db, sessionId) {
1377
+ const existing = findSessionMeta(db, sessionId);
1378
+ const harness = getHarness2();
1379
+ if (existing) {
1380
+ if (harness !== "opencode2")
1381
+ return existing;
1382
+ const row = db.prepare("SELECT is_subagent FROM session_meta WHERE session_id = ?").get(sessionId);
1383
+ if (row.is_subagent !== null)
1384
+ return existing;
1385
+ }
1386
+ const defaults = existing ?? getDefaultSessionMeta(sessionId);
1387
+ let retries = parentReadRetries.get(db);
1388
+ if (harness === "opencode2") {
1389
+ if (!retries) {
1390
+ retries = new BoundedSessionMap(1000);
1391
+ parentReadRetries.set(db, retries);
1392
+ }
1393
+ const retry = retries.get(sessionId);
1394
+ if (retry && retry.attempts >= PARENT_READ_ATTEMPTS && Date.now() - retry.at < PARENT_READ_COOLDOWN_MS)
1395
+ return defaults;
1396
+ }
1397
+ const fallbackSubagent = harness === "opencode" ? resolveIsSubagentFromOpenCodeDb(sessionId) : harness === "opencode2" ? resolveIsSubagentFromOpenCode2Db(sessionId) : null;
1398
+ if (fallbackSubagent === true) {
1399
+ defaults.isSubagent = true;
1400
+ }
1401
+ if (harness === "opencode2") {
1402
+ if (fallbackSubagent === null) {
1403
+ const previous = retries?.get(sessionId);
1404
+ const attempts = previous && Date.now() - previous.at < PARENT_READ_COOLDOWN_MS ? previous.attempts + 1 : 1;
1405
+ retries?.set(sessionId, { attempts, at: Date.now() });
1406
+ ensureSessionMetaRow(db, sessionId, null);
1407
+ return defaults;
1408
+ }
1409
+ retries?.delete(sessionId);
1410
+ ensureSessionMetaRow(db, sessionId, fallbackSubagent);
1411
+ db.prepare("UPDATE session_meta SET is_subagent = ? WHERE session_id = ? AND is_subagent IS NULL").run(fallbackSubagent ? 1 : 0, sessionId);
1412
+ return defaults;
1413
+ }
1414
+ ensureSessionMetaRow(db, sessionId);
1415
+ if (harness === "opencode" && fallbackSubagent === true) {
1416
+ db.prepare("UPDATE session_meta SET is_subagent = 1 WHERE session_id = ?").run(sessionId);
1417
+ }
1418
+ return defaults;
1419
+ }
1420
+ function updateSessionMeta(db, sessionId, updates) {
1421
+ const setClauses = [];
1422
+ const values = [];
1423
+ for (const [key, column] of Object.entries(META_COLUMNS)) {
1424
+ const value = updates[key];
1425
+ if (value === undefined)
1426
+ continue;
1427
+ if (value === null) {
1428
+ setClauses.push(`${column} = ?`);
1429
+ values.push(NULL_BIND_META_KEYS.has(key) ? null : "");
1430
+ } else if ((key === "cachedM0Bytes" || key === "cachedM1Bytes") && value instanceof Uint8Array) {
1431
+ setClauses.push(`${column} = ?`);
1432
+ values.push(Buffer2.from(value.buffer, value.byteOffset, value.byteLength));
1433
+ } else if (BOOLEAN_META_KEYS.has(key)) {
1434
+ setClauses.push(`${column} = ?`);
1435
+ values.push(value ? 1 : 0);
1436
+ } else if (typeof value === "string" || typeof value === "number") {
1437
+ setClauses.push(`${column} = ?`);
1438
+ values.push(key === "lastObservedModelKey" && typeof value === "string" ? piModelRefToCanonical(value) : value);
1439
+ }
1440
+ }
1441
+ if (setClauses.length === 0) {
1442
+ return;
1443
+ }
1444
+ db.transaction(() => {
1445
+ ensureSessionMetaRow(db, sessionId);
1446
+ db.prepare(`UPDATE session_meta SET ${setClauses.join(", ")} WHERE session_id = ?`).run(...values, sessionId);
1447
+ }).immediate();
1448
+ }
1449
+ function advanceToolReclaimWatermark(db, sessionId, maxTagNumber) {
1450
+ if (maxTagNumber <= 0)
1451
+ return;
1452
+ db.transaction(() => {
1453
+ ensureSessionMetaRow(db, sessionId);
1454
+ db.prepare("UPDATE session_meta SET tool_reclaim_watermark = MAX(COALESCE(tool_reclaim_watermark, 0), ?) WHERE session_id = ?").run(maxTagNumber, sessionId);
1455
+ }).immediate();
1456
+ }
1457
+ function rustCleanupHarness() {
1458
+ return `${getHarness2()}:rust`;
1459
+ }
1460
+ function markSessionCleanupPending(db, sessionId, rustModuleCleanupRequired = false) {
1461
+ const row = db.prepare(`INSERT INTO pending_session_cleanup (session_id, harness, requested_at, last_attempt_at)
1462
+ VALUES (?, ?, ?, NULL)
1463
+ ON CONFLICT(session_id) DO UPDATE SET
1464
+ harness = CASE
1465
+ WHEN pending_session_cleanup.harness LIKE '%:rust'
1466
+ THEN pending_session_cleanup.harness
1467
+ ELSE excluded.harness
1468
+ END,
1469
+ requested_at = MIN(pending_session_cleanup.requested_at, excluded.requested_at)
1470
+ RETURNING harness`).get(sessionId, rustModuleCleanupRequired ? rustCleanupHarness() : getHarness2(), Date.now());
1471
+ return row.harness.endsWith(":rust");
1472
+ }
1473
+ function retryPendingSessionCleanups(db, limit = 200) {
1474
+ const rows = db.prepare(`SELECT session_id
1475
+ FROM pending_session_cleanup
1476
+ WHERE harness NOT LIKE '%:rust'
1477
+ ORDER BY requested_at ASC, session_id ASC
1478
+ LIMIT ?`).all(Math.max(1, Math.floor(limit)));
1479
+ const failedSessionIds = [];
1480
+ let cleared = 0;
1481
+ for (const row of rows) {
1482
+ try {
1483
+ withoutSqliteTransformPass2(() => withSqliteBackgroundWriter2(() => {
1484
+ db.prepare("UPDATE pending_session_cleanup SET last_attempt_at = ? WHERE session_id = ?").run(Date.now(), row.session_id);
1485
+ clearSession(db, row.session_id, false, true);
1486
+ }));
1487
+ cleared += 1;
1488
+ } catch {
1489
+ failedSessionIds.push(row.session_id);
1490
+ }
1491
+ }
1492
+ return { attempted: rows.length, cleared, failedSessionIds };
1493
+ }
1494
+ async function retryPendingRustSessionCleanupsForProject(db, projectPath, deleteSession, limit = 200) {
1495
+ const harness = getHarness2();
1496
+ const rows = db.prepare(`SELECT pending.session_id
1497
+ FROM pending_session_cleanup pending
1498
+ JOIN session_projects projects
1499
+ ON projects.session_id = pending.session_id
1500
+ AND projects.harness = ?
1501
+ WHERE pending.harness = ?
1502
+ AND projects.project_path = ?
1503
+ ORDER BY pending.requested_at ASC, pending.session_id ASC
1504
+ LIMIT ?`).all(harness, rustCleanupHarness(), projectPath, Math.max(1, Math.floor(limit)));
1505
+ const failedSessionIds = [];
1506
+ let cleared = 0;
1507
+ for (const row of rows) {
1508
+ try {
1509
+ withoutSqliteTransformPass2(() => withSqliteBackgroundWriter2(() => db.prepare("UPDATE pending_session_cleanup SET last_attempt_at = ? WHERE session_id = ?").run(Date.now(), row.session_id)));
1510
+ await deleteSession(row.session_id);
1511
+ clearSession(db, row.session_id, true, true);
1512
+ cleared += 1;
1513
+ } catch {
1514
+ failedSessionIds.push(row.session_id);
1515
+ }
1516
+ }
1517
+ return { attempted: rows.length, cleared, failedSessionIds };
1518
+ }
1519
+ function clearSession(db, sessionId, rustModuleCleanupAcknowledged = false, permanentlyDeleted = false) {
1520
+ cancelAutoSearchWork(sessionId);
1521
+ let transactionStartedAt = 0;
1522
+ let clearedMarker = null;
1523
+ let eligibleSessions = 0;
1524
+ withoutSqliteTransformPass2(() => withSqliteBackgroundWriter2(() => db.transaction(() => {
1525
+ transactionStartedAt = performance.now();
1526
+ clearedMarker = getPendingPiCompactionMarkerState(db, sessionId);
1527
+ eligibleSessions = deleteSessionScopedRows(db, [sessionId], undefined, {
1528
+ rustModuleCleanupAcknowledged,
1529
+ preserveTagRevisionTombstones: !permanentlyDeleted,
1530
+ deferRecoveryFenceCleanup: true
1531
+ });
1532
+ }).immediate()));
1533
+ if (eligibleSessions > 0)
1534
+ clearLkgRecoveryFence(sessionId);
1535
+ if (clearedMarker)
1536
+ logPiCompactionMarkerClear(sessionId, clearedMarker, "session-reset");
1537
+ clearUnpublishedAutoSearchNoHints(sessionId);
1538
+ logSlowWriteTransaction("clear-session", transactionStartedAt);
1539
+ }
1540
+ // src/hooks/magic-context/pending-materialization.ts
1541
+ var origins = new WeakMap;
1542
+ var causes = new WeakMap;
1543
+ function requestPendingMaterialization(sessions, sessionId, origin) {
1544
+ let reasons = origins.get(sessions);
1545
+ if (!reasons)
1546
+ origins.set(sessions, reasons = new Map);
1547
+ let sessionCauses = causes.get(sessions);
1548
+ if (!sessionCauses)
1549
+ causes.set(sessions, sessionCauses = new Map);
1550
+ let pendingCauses = sessionCauses.get(sessionId);
1551
+ if (!sessions.has(sessionId) || !pendingCauses) {
1552
+ pendingCauses = new Set;
1553
+ sessionCauses.set(sessionId, pendingCauses);
1554
+ }
1555
+ pendingCauses.add(origin);
1556
+ if (!sessions.has(sessionId) || !reasons.has(sessionId) || origin === "fit_retry")
1557
+ reasons.set(sessionId, origin);
1558
+ sessions.add(sessionId);
1559
+ }
1560
+ function pendingMaterializationOrigin(sessions, sessionId) {
1561
+ return sessions.has(sessionId) ? origins.get(sessions)?.get(sessionId) ?? "pending_materialization" : "pending_materialization";
1562
+ }
1563
+ function hasPendingMaterializationOrigin(sessions, sessionId, origin) {
1564
+ return sessions.has(sessionId) && causes.get(sessions)?.get(sessionId)?.has(origin) === true;
1565
+ }
1566
+ function clearPendingMaterialization(sessions, sessionId) {
1567
+ sessions.delete(sessionId);
1568
+ origins.get(sessions)?.delete(sessionId);
1569
+ causes.get(sessions)?.delete(sessionId);
1570
+ }
1571
+ function hasOnlySystemHashMaterialization(sessions, sessionId) {
1572
+ const pendingCauses = causes.get(sessions)?.get(sessionId);
1573
+ return sessions.has(sessionId) && pendingCauses?.size === 1 && pendingCauses.has("system_hash");
1574
+ }
1575
+
1576
+ // src/hooks/magic-context/system-prompt-delivery.ts
1577
+ var pending3 = new BoundedSessionMap(1000);
1578
+ var retiredRequests = new WeakSet;
1579
+ var heldRequests = new WeakSet;
1580
+ var refreshOwners = new BoundedSessionMap(1000);
1581
+ function recordSystemRefreshOwnership(sessionId, hash, ownsHistoryRefresh, history, materialization) {
1582
+ const previous = refreshOwners.get(sessionId);
1583
+ const inherited = previous?.ownsHistoryRefresh === true && previous.history === history && history?.has(sessionId) === true && materialization !== undefined && hasOnlySystemHashMaterialization(materialization, sessionId);
1584
+ refreshOwners.set(sessionId, {
1585
+ hash,
1586
+ ownsHistoryRefresh: ownsHistoryRefresh || inherited,
1587
+ history
1588
+ });
1589
+ }
1590
+ function preparation(sessionId, request) {
1591
+ if (retiredRequests.has(request))
1592
+ return;
1593
+ const previous = pending3.get(sessionId);
1594
+ if (previous?.request === request)
1595
+ return previous;
1596
+ const next = { request, held: false };
1597
+ pending3.set(sessionId, next);
1598
+ return next;
1599
+ }
1600
+ function recordSystemPromptForRequest(sessionId, request, hash, db, ownsHistoryRefresh, history, materialization) {
1601
+ if (!request || !hash)
1602
+ return;
1603
+ if (ownsHistoryRefresh !== undefined)
1604
+ recordSystemRefreshOwnership(sessionId, hash, ownsHistoryRefresh, history, materialization);
1605
+ const previous = pending3.get(sessionId);
1606
+ if (previous?.request === request && previous.held && previous.hash && previous.hash !== hash) {
1607
+ retirePendingSystemPromptDelivery(sessionId);
1608
+ return;
1609
+ }
1610
+ const saved = preparation(sessionId, request);
1611
+ if (!saved)
1612
+ return;
1613
+ const owner = refreshOwners.get(sessionId);
1614
+ Object.assign(saved, {
1615
+ hash,
1616
+ db,
1617
+ ownsHistoryRefresh: owner?.hash === hash && owner.ownsHistoryRefresh
1618
+ });
1619
+ }
1620
+ function recordHeldHeadForRequest(sessionId, request, deferRefresh) {
1621
+ const saved = request && preparation(sessionId, request);
1622
+ if (saved) {
1623
+ heldRequests.add(saved.request);
1624
+ Object.assign(saved, { held: true, deferRefresh });
1625
+ }
1626
+ }
1627
+ function bindSystemPromptResponse(sessionId, request, response) {
1628
+ const saved = pending3.get(sessionId);
1629
+ if (!saved || saved.request !== request || request?.kind !== "v2" || !response.responseId || response.responseId === request.previousResponseId || response.modelKey !== request.modelKey || !Number.isFinite(response.createdAt) || response.createdAt <= request.startedAt)
1630
+ return;
1631
+ if (saved.response && saved.response.id !== response.responseId)
1632
+ return;
1633
+ saved.response = { id: response.responseId, createdAt: response.createdAt };
1634
+ }
1635
+ function isHeldHeadForRequest(sessionId, request) {
1636
+ const saved = pending3.get(sessionId);
1637
+ return saved?.request === request && saved?.held === true || request !== undefined && retiredRequests.has(request) && heldRequests.has(request);
1638
+ }
1639
+ function acknowledgeSystemPromptDelivery(args) {
1640
+ const saved = pending3.get(args.sessionId);
1641
+ if (!saved || saved.request !== args.request || !args.responseId)
1642
+ return;
1643
+ const request = saved.request;
1644
+ if (request.modelKey !== args.modelKey)
1645
+ return;
1646
+ if (request.kind === "v1") {
1647
+ if (args.v2 || request.responseId !== args.responseId)
1648
+ return;
1649
+ } else if (!args.v2 || request.previousResponseId === args.responseId || args.createdAt === undefined || !Number.isFinite(args.createdAt) || args.createdAt <= request.startedAt || saved.response?.id !== args.responseId || saved.response.createdAt !== args.createdAt)
1650
+ return;
1651
+ if (providerResponseFailed(args)) {
1652
+ retirePendingSystemPromptDelivery(args.sessionId);
1653
+ return;
1654
+ }
1655
+ if (!isSuccessfulProviderCompletion(args))
1656
+ return;
1657
+ retirePendingSystemPromptDelivery(args.sessionId);
1658
+ if (saved.held && saved.hash && saved.db) {
1659
+ try {
1660
+ updateSessionMeta(saved.db, args.sessionId, { cachedM0SystemHash: saved.hash });
1661
+ saved.deferRefresh?.(saved.ownsHistoryRefresh === true);
1662
+ refreshOwners.delete(args.sessionId);
1663
+ } catch (error) {
1664
+ sessionLog2(args.sessionId, "system delivery acknowledgement failed (keeping pending work):", error);
1665
+ }
1666
+ }
1667
+ }
1668
+ function deferDeliveredSystemRefresh(deps, sessionId, ownsHistoryRefresh) {
1669
+ if (!hasOnlySystemHashMaterialization(deps.pendingMaterializationSessions, sessionId))
1670
+ return;
1671
+ clearPendingMaterialization(deps.pendingMaterializationSessions, sessionId);
1672
+ (deps.deferredMaterializationSessions ??= new Set).add(sessionId);
1673
+ if (ownsHistoryRefresh && deps.historyRefreshSessions.delete(sessionId)) {
1674
+ (deps.deferredHistoryRefreshSessions ??= new Set).add(sessionId);
1675
+ }
1676
+ }
1677
+ function clearSystemPromptDelivery(sessionId) {
1678
+ retirePendingSystemPromptDelivery(sessionId);
1679
+ refreshOwners.delete(sessionId);
1680
+ }
1681
+ function retirePendingSystemPromptDelivery(sessionId) {
1682
+ const saved = pending3.get(sessionId);
1683
+ if (saved)
1684
+ retiredRequests.add(saved.request);
1685
+ pending3.delete(sessionId);
1686
+ }
1687
+
1688
+ // src/hooks/magic-context/lkg-measured-request.ts
1689
+ var requests = new BoundedSessionMap(1000);
1690
+ var claimedRequests = new WeakSet;
1691
+ var captures = new BoundedSessionMap(1000);
1692
+ function lkgProviderInputTotal(tokens) {
1693
+ const counts = [tokens?.input ?? 0, tokens?.cache?.read ?? 0, tokens?.cache?.write ?? 0];
1694
+ return counts.every((count) => Number.isSafeInteger(count) && count >= 0) ? counts.reduce((sum, count) => sum + count, 0) : Number.NaN;
1695
+ }
1696
+ function identity(slot) {
1697
+ return createHash4("sha256").update(JSON.stringify([
1698
+ slot.capturedAt,
1699
+ slot.captureSequence,
1700
+ slot.rowVersion,
1701
+ slot.modelKey,
1702
+ slot.providerKey,
1703
+ slot.inputIdSeq,
1704
+ slot.inputContentDigests
1705
+ ])).update(slot.jsonPrefix).digest("hex");
1706
+ }
1707
+ function envelope(modelKey, systemPromptTokens, agentName, sessionId) {
1708
+ const slash = modelKey.indexOf("/");
1709
+ return JSON.stringify([
1710
+ modelKey,
1711
+ systemPromptTokens,
1712
+ agentName,
1713
+ getMeasuredToolDefinitionTokens(modelKey.slice(0, slash), modelKey.slice(slash + 1), agentName, sessionId)
1714
+ ]);
1715
+ }
1716
+ function beginV2LkgRequest(sessionId, modelKey, previousResponseId, responseAfterSequence) {
1717
+ requests.set(sessionId, {
1718
+ kind: "v2",
1719
+ previousResponseId,
1720
+ startedAt: Date.now(),
1721
+ modelKey,
1722
+ responseAfterSequence
1723
+ });
1724
+ }
1725
+ function claimLkgRequestIdentity(sessionId) {
1726
+ const request = requests.get(sessionId);
1727
+ if (!request || claimedRequests.has(request))
1728
+ return;
1729
+ claimedRequests.add(request);
1730
+ return request;
1731
+ }
1732
+ function currentLkgRequestIdentity(sessionId) {
1733
+ return requests.get(sessionId);
1734
+ }
1735
+ function noteCapturedLkgRequest(args) {
1736
+ const request = args.request;
1737
+ if (!request || request.modelKey !== args.slot.modelKey) {
1738
+ captures.delete(args.sessionId);
1739
+ return;
1740
+ }
1741
+ captures.set(args.sessionId, {
1742
+ request,
1743
+ slot: identity(args.slot),
1744
+ prefixCount: JSON.parse(args.slot.jsonPrefix).length,
1745
+ envelope: envelope(request.modelKey, args.systemPromptTokens, args.agentName, args.sessionId)
1746
+ });
1747
+ }
1748
+ function noteLkgProviderResponse(args) {
1749
+ if (!args.responseId || !args.modelKey)
1750
+ return;
1751
+ if (!args.v2 && args.inputTokens === 0 && !args.completedAt && !args.finish && !args.error) {
1752
+ const previous = requests.get(args.sessionId);
1753
+ if (previous?.kind === "v1" && previous.responseId === args.responseId && previous.modelKey === args.modelKey)
1754
+ return;
1755
+ requests.set(args.sessionId, {
1756
+ kind: "v1",
1757
+ responseId: args.responseId,
1758
+ modelKey: args.modelKey
1759
+ });
1760
+ return;
1761
+ }
1762
+ acknowledgeSystemPromptDelivery({ ...args, request: requests.get(args.sessionId) });
1763
+ const capture = captures.get(args.sessionId);
1764
+ if (!capture || capture.usage || capture.request.modelKey !== args.modelKey || !Number.isSafeInteger(args.inputTokens) || args.inputTokens <= 0 || providerResponseFailed(args) || !args.completedAt && !args.finish)
1765
+ return;
1766
+ const request = capture.request;
1767
+ if (request.kind === "v1") {
1768
+ if (args.v2 || request.responseId !== args.responseId)
1769
+ return;
1770
+ } else if (!args.v2 || requests.get(args.sessionId) !== request || request.previousResponseId === args.responseId || args.createdAt === undefined || args.createdAt < request.startedAt)
1771
+ return;
1772
+ capture.usage = { responseId: args.responseId, inputTokens: args.inputTokens };
1773
+ }
1774
+ function measuredLkgPrefix(args) {
1775
+ const capture = captures.get(args.sessionId);
1776
+ if (!capture?.usage || !args.slot || capture.slot !== identity(args.slot) || capture.request.modelKey !== args.modelKey || capture.envelope !== envelope(args.modelKey, args.systemPromptTokens, args.agentName, args.sessionId))
1777
+ return;
1778
+ const appendedMessages = args.messages.slice(capture.prefixCount);
1779
+ if (appendedMessages[0]?.info.id !== capture.usage.responseId || appendedMessages[0]?.info.role !== "assistant" || JSON.stringify(args.messages.slice(0, capture.prefixCount)) !== args.slot.jsonPrefix)
1780
+ return;
1781
+ return { inputTokens: capture.usage.inputTokens, appendedMessages };
1782
+ }
1783
+ function clearLkgMeasuredRequest(sessionId) {
1784
+ requests.delete(sessionId);
1785
+ captures.delete(sessionId);
1786
+ clearSystemPromptDelivery(sessionId);
1787
+ }
1788
+ function clearCapturedLkgMeasurement(sessionId) {
1789
+ captures.delete(sessionId);
1790
+ }
1791
+
1792
+ // src/hooks/magic-context/lkg-persist.ts
1793
+ import { createHash as createHash5 } from "node:crypto";
1794
+ function parseStringArray(value) {
1795
+ if (typeof value !== "string")
1796
+ return null;
1797
+ let parsed;
1798
+ try {
1799
+ parsed = JSON.parse(value);
1800
+ } catch {
1801
+ return null;
1802
+ }
1803
+ if (!Array.isArray(parsed))
1804
+ return null;
1805
+ const result = [];
1806
+ for (const entry of parsed) {
1807
+ if (typeof entry !== "string" || entry.length === 0)
1808
+ return null;
1809
+ result.push(entry);
1810
+ }
1811
+ return result;
1812
+ }
1813
+ function parseNullableString(value) {
1814
+ if (value === null || value === undefined)
1815
+ return null;
1816
+ return typeof value === "string" ? value : undefined;
1817
+ }
1818
+ function parseNullableInteger(value) {
1819
+ if (value === null || value === undefined)
1820
+ return;
1821
+ return typeof value === "number" && Number.isSafeInteger(value) ? value : undefined;
1822
+ }
1823
+ function parsePersistedLkgSlot(row) {
1824
+ if (!row || typeof row !== "object")
1825
+ return;
1826
+ const record = row;
1827
+ const jsonPrefix = record.json_prefix;
1828
+ const lastInputMessageId = record.last_input_message_id;
1829
+ const capturedAt = record.captured_at;
1830
+ let inputIdsRaw = record.input_id_seq;
1831
+ let piOutputEntryIds;
1832
+ if (typeof inputIdsRaw === "string") {
1833
+ try {
1834
+ const metadata = JSON.parse(inputIdsRaw);
1835
+ if (metadata && !Array.isArray(metadata) && metadata.version === 1 && Array.isArray(metadata.piOutputEntryIds)) {
1836
+ if (!metadata.piOutputEntryIds.every((id) => id === null || typeof id === "string" && id.length > 0))
1837
+ return;
1838
+ piOutputEntryIds = metadata.piOutputEntryIds;
1839
+ inputIdsRaw = JSON.stringify(metadata.inputIds);
1840
+ }
1841
+ } catch {
1842
+ return;
1843
+ }
1844
+ }
1845
+ const inputIdSeq = parseStringArray(inputIdsRaw);
1846
+ const inputContentDigests = parseStringArray(record.input_content_digests);
1847
+ const modelKey = parseNullableString(record.model_key);
1848
+ const providerKey = parseNullableString(record.provider_key);
1849
+ if (typeof jsonPrefix !== "string" || typeof lastInputMessageId !== "string" || lastInputMessageId.length === 0 || typeof capturedAt !== "number" || !Number.isFinite(capturedAt) || inputIdSeq === null || inputContentDigests === null || inputContentDigests.length !== inputIdSeq.length || modelKey === undefined || providerKey === undefined) {
1850
+ return;
1851
+ }
1852
+ if (piOutputEntryIds) {
1853
+ try {
1854
+ const output = JSON.parse(jsonPrefix);
1855
+ const inputs = new Set(inputIdSeq);
1856
+ if (!Array.isArray(output) || output.length !== piOutputEntryIds.length || piOutputEntryIds.some((id) => id !== null && !inputs.has(id)))
1857
+ return;
1858
+ } catch {
1859
+ return;
1860
+ }
1861
+ }
1862
+ let inputContentSignatures;
1863
+ if (record.input_content_signatures !== null && record.input_content_signatures !== undefined) {
1864
+ const parsed = parseStringArray(record.input_content_signatures);
1865
+ if (parsed === null || parsed.length !== inputIdSeq.length)
1866
+ return;
1867
+ inputContentSignatures = parsed;
1868
+ }
1869
+ const slot = {
1870
+ jsonPrefix,
1871
+ inputIdSeq,
1872
+ inputContentDigests,
1873
+ lastInputMessageId,
1874
+ modelKey,
1875
+ providerKey,
1876
+ capturedAt
1877
+ };
1878
+ if (inputContentSignatures)
1879
+ slot.inputContentSignatures = inputContentSignatures;
1880
+ if (piOutputEntryIds)
1881
+ slot.piOutputEntryIds = piOutputEntryIds;
1882
+ const rowVersion = parseNullableInteger(record.row_version);
1883
+ if (rowVersion !== undefined)
1884
+ slot.rowVersion = rowVersion;
1885
+ const captureSequence = parseNullableInteger(record.capture_sequence);
1886
+ if (captureSequence !== undefined)
1887
+ slot.captureSequence = captureSequence;
1888
+ return slot;
1889
+ }
1890
+ var persistedFingerprints = new WeakMap;
1891
+ var PERSISTED_FINGERPRINT_MAX_SESSIONS = 1000;
1892
+ function rememberFingerprint(db, sessionId, fingerprint) {
1893
+ let saved = persistedFingerprints.get(db);
1894
+ if (!saved) {
1895
+ saved = new Map;
1896
+ persistedFingerprints.set(db, saved);
1897
+ }
1898
+ saved.delete(sessionId);
1899
+ if (saved.size >= PERSISTED_FINGERPRINT_MAX_SESSIONS) {
1900
+ const oldest = saved.keys().next().value;
1901
+ if (oldest !== undefined)
1902
+ saved.delete(oldest);
1903
+ }
1904
+ saved.set(sessionId, fingerprint);
1905
+ }
1906
+ function slotFingerprint(slot) {
1907
+ return createHash5("sha256").update(JSON.stringify([
1908
+ slot.jsonPrefix,
1909
+ slot.inputIdSeq,
1910
+ slot.inputContentDigests,
1911
+ slot.inputContentSignatures,
1912
+ slot.piOutputEntryIds,
1913
+ slot.lastInputMessageId,
1914
+ slot.modelKey,
1915
+ slot.providerKey,
1916
+ slot.rowVersion,
1917
+ slot.captureSequence
1918
+ ])).digest("hex");
1919
+ }
1920
+ function persistLkgSlot(db, sessionId, slot, publishMetadata) {
1921
+ const fingerprint = slotFingerprint(slot);
1922
+ if (!publishMetadata && persistedFingerprints.get(db)?.get(sessionId) === fingerprint) {
1923
+ const durable = loadPersistedLkgSlot(db, sessionId);
1924
+ if (durable && slotFingerprint(durable) === fingerprint)
1925
+ return true;
1926
+ }
1927
+ const layout = layoutLkgPrefix(slot.jsonPrefix);
1928
+ try {
1929
+ const inputIdSeq = JSON.stringify(slot.piOutputEntryIds ? { version: 1, inputIds: slot.inputIdSeq, piOutputEntryIds: slot.piOutputEntryIds } : slot.inputIdSeq);
1930
+ const inputContentDigests = JSON.stringify(slot.inputContentDigests);
1931
+ const inputContentSignatures = slot.inputContentSignatures ? JSON.stringify(slot.inputContentSignatures) : null;
1932
+ db.transaction(() => {
1933
+ const storedHashes = new Map;
1934
+ for (const row of db.prepare("SELECT chunk, hash FROM lkg_slot_chunks WHERE session_id = ?").all(sessionId)) {
1935
+ storedHashes.set(row.chunk, row.hash);
1936
+ }
1937
+ const upsertChunk = db.prepare(`INSERT INTO lkg_slot_chunks (session_id, chunk, hash, body) VALUES (?, ?, ?, ?)
1938
+ ON CONFLICT(session_id, chunk) DO UPDATE SET hash = excluded.hash, body = excluded.body`);
1939
+ for (let index = 0;index < layout.chunks.length; index += 1) {
1940
+ if (storedHashes.get(index) === layout.chunkHashes[index])
1941
+ continue;
1942
+ upsertChunk.run(sessionId, index, layout.chunkHashes[index], layout.chunks[index]);
1943
+ }
1944
+ db.prepare("DELETE FROM lkg_slot_chunks WHERE session_id = ? AND chunk >= ?").run(sessionId, layout.chunks.length);
1945
+ db.prepare(`INSERT INTO lkg_slots (
1946
+ session_id, json_prefix_chars, json_prefix_chunks, json_prefix_hash,
1947
+ input_id_seq, input_content_digests, input_content_signatures,
1948
+ last_input_message_id, model_key, provider_key,
1949
+ captured_at, row_version, capture_sequence
1950
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1951
+ ON CONFLICT(session_id) DO UPDATE SET
1952
+ json_prefix_chars = excluded.json_prefix_chars,
1953
+ json_prefix_chunks = excluded.json_prefix_chunks,
1954
+ json_prefix_hash = excluded.json_prefix_hash,
1955
+ input_id_seq = excluded.input_id_seq,
1956
+ input_content_digests = excluded.input_content_digests,
1957
+ input_content_signatures = excluded.input_content_signatures,
1958
+ last_input_message_id = excluded.last_input_message_id,
1959
+ model_key = excluded.model_key,
1960
+ provider_key = excluded.provider_key,
1961
+ captured_at = excluded.captured_at,
1962
+ row_version = excluded.row_version,
1963
+ capture_sequence = excluded.capture_sequence`).run(sessionId, layout.chars, layout.chunks.length, layout.hash, inputIdSeq, inputContentDigests, inputContentSignatures, slot.lastInputMessageId, slot.modelKey, slot.providerKey, slot.capturedAt, slot.rowVersion ?? null, slot.captureSequence ?? null);
1964
+ publishMetadata?.();
1965
+ }).immediate();
1966
+ rememberFingerprint(db, sessionId, fingerprint);
1967
+ return true;
1968
+ } catch (error) {
1969
+ if (!publishMetadata)
1970
+ sessionLog2(sessionId, "LKG snapshot persistence failed (in-memory slot retained):", error);
1971
+ return false;
1972
+ }
1973
+ }
1974
+ function saveLkgSlotToDb(db, sessionId, slot, publishMetadata, fence = {}) {
1975
+ return commitLkgWithRecoveryFence({
1976
+ sessionId,
1977
+ slot,
1978
+ ...fence,
1979
+ load: () => loadPersistedLkgSlot(db, sessionId, true),
1980
+ commit: () => persistLkgSlot(db, sessionId, slot, publishMetadata)
1981
+ });
1982
+ }
1983
+ function clearPersistedLkgSlot(db, sessionId) {
1984
+ try {
1985
+ clearPersistedLkgSlotStrict(db, sessionId);
1986
+ } catch (error) {
1987
+ sessionLog2(sessionId, "LKG snapshot durable clear failed:", error);
1988
+ }
1989
+ }
1990
+ function clearPersistedLkgSlotStrict(db, sessionId) {
1991
+ clearLkgRecoveryFence(sessionId, () => db.transaction(() => {
1992
+ db.prepare("DELETE FROM lkg_slot_chunks WHERE session_id = ?").run(sessionId);
1993
+ db.prepare("DELETE FROM lkg_slots WHERE session_id = ?").run(sessionId);
1994
+ }).immediate());
1995
+ persistedFingerprints.get(db)?.delete(sessionId);
1996
+ }
1997
+ function loadPersistedLkgSlot(db, sessionId, forPublication = false) {
1998
+ const rustHost = getHarness2() === "opencode" || getHarness2() === "opencode2";
1999
+ if (rustHost && !forPublication && isRustMarkerAdmissionFenced(db, sessionId))
2000
+ return;
2001
+ let row;
2002
+ let chunkRows;
2003
+ try {
2004
+ ({ row, chunkRows } = db.transaction(() => {
2005
+ const slotRow = db.prepare("SELECT * FROM lkg_slots WHERE session_id = ?").get(sessionId);
2006
+ if (!slotRow)
2007
+ return { row: undefined, chunkRows: [] };
2008
+ const slices = db.prepare("SELECT chunk, hash, body FROM lkg_slot_chunks WHERE session_id = ? ORDER BY chunk").all(sessionId);
2009
+ return { row: slotRow, chunkRows: slices };
2010
+ }).deferred());
2011
+ } catch (error) {
2012
+ sessionLog2(sessionId, "LKG snapshot durable load failed:", error);
2013
+ return;
2014
+ }
2015
+ if (!row)
2016
+ return;
2017
+ const prefix = assembleLkgPrefix({
2018
+ chars: row.json_prefix_chars,
2019
+ chunks: row.json_prefix_chunks,
2020
+ hash: row.json_prefix_hash
2021
+ }, chunkRows);
2022
+ const slot = prefix ? parsePersistedLkgSlot({ ...row, json_prefix: prefix.jsonPrefix }) : undefined;
2023
+ if (!prefix || !slot) {
2024
+ if (!prefix)
2025
+ sessionLog2(sessionId, "LKG snapshot slices failed verification; slot cleared");
2026
+ clearPersistedLkgSlot(db, sessionId);
2027
+ return;
2028
+ }
2029
+ return slot;
2030
+ }
2031
+ function pruneStaleLkgSlotsBatch(db, now) {
2032
+ const previousTimeout = db.prepare("PRAGMA busy_timeout").get();
2033
+ const cutoff = now - 7 * 24 * 60 * 60 * 1000;
2034
+ const stale = `captured_at < ? AND NOT EXISTS (
2035
+ SELECT 1 FROM session_projects sp
2036
+ WHERE sp.session_id = lkg_slots.session_id AND sp.updated_at >= ?
2037
+ )`;
2038
+ const slot = db.prepare(`SELECT session_id FROM lkg_slots WHERE ${stale} LIMIT 1`).get(cutoff, cutoff);
2039
+ const chunks = db.prepare(`SELECT rowid FROM lkg_slot_chunks c WHERE
2040
+ session_id = ? OR NOT EXISTS (SELECT 1 FROM lkg_slots s WHERE s.session_id = c.session_id)
2041
+ LIMIT 25`).all(slot?.session_id ?? "");
2042
+ if (!slot && chunks.length === 0)
2043
+ return { slots: 0, chunks: 0 };
2044
+ try {
2045
+ db.exec("PRAGMA busy_timeout = 0");
2046
+ let transactionStartedAt = 0;
2047
+ const remove = () => db.transaction(() => {
2048
+ transactionStartedAt = performance.now();
2049
+ const removed = slot ? db.prepare(`DELETE FROM lkg_slots WHERE session_id = ? AND ${stale}`).run(slot.session_id, cutoff, cutoff).changes : 0;
2050
+ const removeChunk = db.prepare(`DELETE FROM lkg_slot_chunks WHERE rowid = ? AND NOT EXISTS (
2051
+ SELECT 1 FROM lkg_slots s WHERE s.session_id = lkg_slot_chunks.session_id
2052
+ )`);
2053
+ let removedChunks = 0;
2054
+ for (const { rowid } of chunks)
2055
+ removedChunks += removeChunk.run(rowid).changes;
2056
+ return { slots: removed, chunks: removedChunks };
2057
+ }).immediate();
2058
+ const changes = slot ? clearLkgRecoveryFence(slot.session_id, remove, (result) => !!result?.slots) ?? {
2059
+ slots: 0,
2060
+ chunks: 0
2061
+ } : remove();
2062
+ logSlowWriteTransaction("lkg_stale_gc", transactionStartedAt);
2063
+ if (changes.slots && slot) {
2064
+ persistedFingerprints.get(db)?.delete(slot.session_id);
2065
+ }
2066
+ return changes;
2067
+ } finally {
2068
+ db.exec(`PRAGMA busy_timeout = ${Number(previousTimeout.timeout) || 0}`);
2069
+ }
2070
+ }
2071
+ async function drainStaleLkgSlots(db, now = Date.now(), budgetMs = 2000) {
2072
+ let removed = 0;
2073
+ await drainBackgroundBatches(() => {
2074
+ const batch = pruneStaleLkgSlotsBatch(db, now);
2075
+ removed += batch.slots;
2076
+ return batch.slots + batch.chunks > 0;
2077
+ }, { budgetMs });
2078
+ return removed;
2079
+ }
2080
+ function createDbLkgPersistence(db) {
2081
+ return {
2082
+ load: (sessionId) => loadPersistedLkgSlot(db, sessionId),
2083
+ clear: (sessionId) => clearPersistedLkgSlot(db, sessionId)
2084
+ };
2085
+ }
2086
+
2087
+ // src/hooks/magic-context/openai-compat-adjacency.ts
2088
+ function assertOpenAiCompatAdjacency(messages) {
2089
+ const violations = [];
2090
+ for (let i = 0;i < messages.length; i++) {
2091
+ const msg = messages[i];
2092
+ if (msg.role !== "assistant" || !msg.tool_calls || msg.tool_calls.length === 0) {
2093
+ continue;
2094
+ }
2095
+ const expectedIds = msg.tool_calls.map((tc) => tc.id);
2096
+ const expectedSet = new Set(expectedIds);
2097
+ const collected = new Map;
2098
+ let j = i + 1;
2099
+ while (j < messages.length && messages[j].role === "tool") {
2100
+ const toolMsg = messages[j];
2101
+ const id = toolMsg.tool_call_id;
2102
+ if (!id) {
2103
+ violations.push({
2104
+ index: i,
2105
+ kind: "unmatched_tool_call_id",
2106
+ detail: `tool message at index ${j} missing tool_call_id`
2107
+ });
2108
+ } else if (!expectedSet.has(id)) {
2109
+ violations.push({
2110
+ index: i,
2111
+ kind: "unmatched_tool_call_id",
2112
+ toolCallId: id,
2113
+ assistantToolCallIds: expectedIds,
2114
+ detail: `tool message at index ${j} references unexpected id ${id}`
2115
+ });
2116
+ } else {
2117
+ collected.set(id, j);
2118
+ }
2119
+ j++;
2120
+ }
2121
+ const followingRoles = messages.slice(i + 1, Math.min(messages.length, i + 4)).map((m) => m.role);
2122
+ const missing = expectedIds.filter((id) => !collected.has(id));
2123
+ if (missing.length > 0) {
2124
+ violations.push({
2125
+ index: i,
2126
+ kind: "missing_tool_messages",
2127
+ assistantToolCallIds: expectedIds,
2128
+ followingRoles,
2129
+ detail: missing.length === expectedIds.length ? `assistant at index ${i} has tool_calls but next messages are not contiguous tool role (following: ${followingRoles.join(", ") || "none"})` : `assistant at index ${i} missing tool results for: ${missing.join(", ")}`
2130
+ });
2131
+ if (j < messages.length && messages[j].role !== "tool") {
2132
+ const last = violations[violations.length - 1];
2133
+ last.detail += `; blocked by ${messages.slice(i + 1, j + 1).map((m, off) => `${m.role}[${i + 1 + off}]`).join(", ")}`;
2134
+ }
2135
+ }
2136
+ }
2137
+ for (let i = 0;i < messages.length; i++) {
2138
+ if (messages[i].role !== "tool")
2139
+ continue;
2140
+ const id = messages[i].tool_call_id ?? "";
2141
+ if (!id)
2142
+ continue;
2143
+ let found = false;
2144
+ for (let k = i - 1;k >= 0; k--) {
2145
+ const prev = messages[k];
2146
+ if (prev.role === "assistant" && prev.tool_calls?.some((tc) => tc.id === id)) {
2147
+ const between = messages.slice(k + 1, i);
2148
+ if (between.every((m) => m.role === "tool")) {
2149
+ found = true;
2150
+ }
2151
+ break;
2152
+ }
2153
+ if (prev.role === "assistant" || prev.role === "user")
2154
+ break;
2155
+ }
2156
+ if (!found) {
2157
+ violations.push({
2158
+ index: i,
2159
+ kind: "orphan_tool_message",
2160
+ toolCallId: id,
2161
+ detail: `tool message at index ${i} is not immediately after its assistant tool_calls`
2162
+ });
2163
+ }
2164
+ }
2165
+ return { ok: violations.length === 0, violations };
2166
+ }
2167
+
2168
+ // src/hooks/magic-context/lkg-replay.ts
2169
+ function canonicalLkgModelKeys(modelKey, providerKey) {
2170
+ const canonicalModelKey = modelKey ? piModelRefToCanonical(modelKey) : null;
2171
+ const slash = canonicalModelKey?.indexOf("/") ?? -1;
2172
+ return {
2173
+ modelKey: canonicalModelKey,
2174
+ providerKey: slash > 0 && canonicalModelKey ? canonicalModelKey.slice(0, slash) : providerKey
2175
+ };
2176
+ }
2177
+ function resolveLkgModelKeys(messages) {
2178
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
2179
+ const info = messages[index]?.info;
2180
+ const nested = info?.model;
2181
+ if (nested && typeof nested === "object") {
2182
+ const provider = nested.providerID;
2183
+ const model = nested.modelID;
2184
+ if (typeof provider === "string" && typeof model === "string") {
2185
+ return canonicalLkgModelKeys(`${provider}/${model}`, provider);
2186
+ }
2187
+ }
2188
+ const provider = info?.providerID;
2189
+ const model = info?.modelID;
2190
+ if (typeof provider === "string" && typeof model === "string") {
2191
+ return canonicalLkgModelKeys(`${provider}/${model}`, provider);
2192
+ }
2193
+ }
2194
+ return { modelKey: null, providerKey: null };
2195
+ }
2196
+ function projectLkgEntry(messages) {
2197
+ return projectEntryWithDigests(messages, messages.map(lkgContentDigest));
2198
+ }
2199
+ function createLkgEntryProjector(options = {}) {
2200
+ const cache = options.maxBytes === undefined ? sharedLkgEntryDigests : new LkgEntryDigestCache({
2201
+ sessionMaxBytes: options.maxBytes,
2202
+ totalMaxBytes: options.maxBytes,
2203
+ maxSessions: 16
2204
+ });
2205
+ return (sessionId, messages) => {
2206
+ const { digests, stats } = cache.digests(sessionId, messages);
2207
+ options.onReuse?.(stats);
2208
+ return projectEntryWithDigests(messages, digests);
2209
+ };
2210
+ }
2211
+ function projectEntryWithDigests(messages, digests) {
2212
+ return messages.map((message, index) => {
2213
+ const info = messageInfo(message);
2214
+ const time = info.time;
2215
+ const timeRecord = time && typeof time === "object" ? time : null;
2216
+ const timeCandidates = [
2217
+ timeRecord?.created,
2218
+ info.timeCreated,
2219
+ info.time_created,
2220
+ info.createdAt,
2221
+ info.created_at
2222
+ ];
2223
+ let timeCreated = null;
2224
+ for (const value of timeCandidates) {
2225
+ if (typeof value === "number" && Number.isFinite(value)) {
2226
+ timeCreated = value;
2227
+ break;
2228
+ }
2229
+ }
2230
+ let hasIncompleteTool = false;
2231
+ for (const rawPart of messageParts(message)) {
2232
+ if (!rawPart || typeof rawPart !== "object")
2233
+ continue;
2234
+ const part = rawPart;
2235
+ if (part.type !== "tool" || part.providerExecuted === true)
2236
+ continue;
2237
+ const state = part.state;
2238
+ const status = state && typeof state === "object" ? state.status : undefined;
2239
+ if (status !== "completed") {
2240
+ hasIncompleteTool = true;
2241
+ break;
2242
+ }
2243
+ }
2244
+ const id = info.id;
2245
+ const projection = {
2246
+ id: typeof id === "string" && id.length > 0 ? id : null,
2247
+ role: typeof info.role === "string" ? info.role : undefined,
2248
+ synthetic: info.synthetic === true,
2249
+ timeCreated,
2250
+ finish: info.finish,
2251
+ hasIncompleteTool
2252
+ };
2253
+ const contentDigest = digests[index] ?? null;
2254
+ Object.defineProperty(projection, "contentDigest", {
2255
+ value: () => contentDigest,
2256
+ enumerable: false
2257
+ });
2258
+ if (isCoveredInstructionRow(message.info))
2259
+ markCoveredInstructionRow(projection);
2260
+ return projection;
2261
+ });
2262
+ }
2263
+ function recordValue(info, key) {
2264
+ return info && typeof info === "object" ? info[key] : undefined;
2265
+ }
2266
+ function messageInfo(message) {
2267
+ if (message.info && typeof message.info === "object")
2268
+ return message.info;
2269
+ return message;
2270
+ }
2271
+ function messageParts(message) {
2272
+ return Array.isArray(message.parts) ? message.parts : [];
2273
+ }
2274
+ function isSynthetic(message) {
2275
+ return recordValue(messageInfo(message), "synthetic") === true;
2276
+ }
2277
+ function hasSyntheticParts(message) {
2278
+ const parts = messageParts(message);
2279
+ return parts.length > 0 && parts.every((part) => {
2280
+ return Boolean(part && typeof part === "object" && part.synthetic === true);
2281
+ });
2282
+ }
2283
+ function isSyntheticOutput(message) {
2284
+ return isSynthetic(message) || hasSyntheticParts(message);
2285
+ }
2286
+ function messageRole(message) {
2287
+ const infoRole = recordValue(messageInfo(message), "role");
2288
+ if (typeof infoRole === "string")
2289
+ return infoRole;
2290
+ const role = recordValue(message, "role");
2291
+ return typeof role === "string" ? role : undefined;
2292
+ }
2293
+ function messageId(message) {
2294
+ const id = recordValue(messageInfo(message), "id") ?? recordValue(message, "id");
2295
+ return typeof id === "string" && id.length > 0 ? id : null;
2296
+ }
2297
+ function latestAssistant(messages) {
2298
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
2299
+ if (messages[index].role === "assistant")
2300
+ return messages[index];
2301
+ }
2302
+ return null;
2303
+ }
2304
+ function isRealUser(message) {
2305
+ return message.role === "user" && !message.synthetic && message.id !== null;
2306
+ }
2307
+ function assistantIsActive(message) {
2308
+ return message.finish === "tool-calls" || message.hasIncompleteTool;
2309
+ }
2310
+ function findLkgAnchor(messages) {
2311
+ const assistant = latestAssistant(messages);
2312
+ const assistantTime = assistant?.timeCreated ?? null;
2313
+ if (assistant && assistantTime === null)
2314
+ return null;
2315
+ let anchor = -1;
2316
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
2317
+ const message = messages[index];
2318
+ if (!isRealUser(message))
2319
+ continue;
2320
+ if (assistant && assistantIsActive(assistant)) {
2321
+ if (assistantTime === null || message.timeCreated === null || message.timeCreated <= assistantTime) {
2322
+ continue;
2323
+ }
2324
+ }
2325
+ anchor = index;
2326
+ break;
2327
+ }
2328
+ return anchor >= 0 ? anchor : null;
2329
+ }
2330
+ function asEntryProjection(input) {
2331
+ if (input.length === 0 || "hasIncompleteTool" in input[0]) {
2332
+ return input;
2333
+ }
2334
+ return projectLkgEntry(input);
2335
+ }
2336
+ function outputMessageIsPostAnchor(message, inputIndexById, anchorIndex, systemIndices) {
2337
+ const id = messageId(message);
2338
+ if (id !== null) {
2339
+ const inputIndex = inputIndexById.get(id);
2340
+ if (inputIndex !== undefined)
2341
+ return inputIndex > anchorIndex;
2342
+ if (!isSyntheticOutput(message))
2343
+ return null;
2344
+ const linked = ["sourceMessageId", "ownerMessageId", "anchorMessageId", "messageId"].map((key) => recordValue(messageInfo(message), key)).find((value) => typeof value === "string");
2345
+ if (typeof linked === "string") {
2346
+ const linkedIndex = inputIndexById.get(linked);
2347
+ if (linkedIndex === undefined)
2348
+ return null;
2349
+ return linkedIndex > anchorIndex;
2350
+ }
2351
+ return false;
2352
+ }
2353
+ if (isCoveredInstructionRow(message.info))
2354
+ return false;
2355
+ if (messageRole(message) === "system") {
2356
+ const index = systemIndices.get(message);
2357
+ return index === undefined ? null : index > anchorIndex;
2358
+ }
2359
+ if (!isSyntheticOutput(message))
2360
+ return null;
2361
+ const linked = ["sourceMessageId", "ownerMessageId", "anchorMessageId"].map((key) => recordValue(message.info, key)).find((value) => typeof value === "string");
2362
+ if (typeof linked !== "string")
2363
+ return false;
2364
+ const linkedIndex = inputIndexById.get(linked);
2365
+ return linkedIndex === undefined ? null : linkedIndex > anchorIndex;
2366
+ }
2367
+ function buildLkgPrefix(input, output, completeOutput = false) {
2368
+ const projected = asEntryProjection(input);
2369
+ const anchorIndex = completeOutput && projected.length > 0 ? projected.length - 1 : findLkgAnchor(projected);
2370
+ if (anchorIndex === null)
2371
+ return null;
2372
+ const ids = projected.map((message, index) => lkgInputIdentity(message.id, message.role, index));
2373
+ if (ids.some((id) => id === null))
2374
+ return null;
2375
+ const validIds = ids;
2376
+ if (new Set(validIds).size !== validIds.length)
2377
+ return null;
2378
+ const anchorMessageId = validIds[anchorIndex];
2379
+ const inputContentDigests = projected.slice(0, anchorIndex + 1).map((message) => message.contentDigest?.() ?? null);
2380
+ if (inputContentDigests.some((digest) => digest === null))
2381
+ return null;
2382
+ const inputIndexById = new Map(validIds.map((id, index) => [id, index]));
2383
+ const systemIndices = new Map;
2384
+ if (!completeOutput) {
2385
+ const inputSystems = projected.flatMap((message, index) => message.id === null && message.role === "system" && !isCoveredInstructionRow(message) ? [{ message, index }] : []);
2386
+ const outputSystems = output.filter((message) => messageId(message) === null && messageRole(message) === "system");
2387
+ const restoredCount = outputSystems.length - inputSystems.length;
2388
+ if (restoredCount < 0 || outputSystems.slice(0, restoredCount).some((message) => !isCoveredInstructionRow(message.info)))
2389
+ return null;
2390
+ for (let index = 0;index < inputSystems.length; index += 1) {
2391
+ const source = inputSystems[index];
2392
+ const message = outputSystems[index + restoredCount];
2393
+ const digest = source.message.contentDigest?.();
2394
+ if (!digest || lkgContentDigest(message) !== digest)
2395
+ return null;
2396
+ if (isCoveredInstructionRow(message.info) && source.index > anchorIndex)
2397
+ return null;
2398
+ systemIndices.set(message, source.index);
2399
+ }
2400
+ }
2401
+ const prefix = [];
2402
+ for (const message of output) {
2403
+ const postAnchor = completeOutput ? false : outputMessageIsPostAnchor(message, inputIndexById, anchorIndex, systemIndices);
2404
+ if (postAnchor === null)
2405
+ return null;
2406
+ if (!postAnchor)
2407
+ prefix.push(providerVisibleMessage(message));
2408
+ }
2409
+ let jsonPrefix;
2410
+ try {
2411
+ jsonPrefix = JSON.stringify(prefix);
2412
+ if (typeof jsonPrefix !== "string")
2413
+ return null;
2414
+ } catch {
2415
+ return null;
2416
+ }
2417
+ return {
2418
+ anchorIndex,
2419
+ anchorMessageId,
2420
+ inputIdSeq: validIds.slice(0, anchorIndex + 1),
2421
+ inputContentDigests,
2422
+ jsonPrefix
2423
+ };
2424
+ }
2425
+ function captureLkgSlot(args) {
2426
+ const built = buildLkgPrefix(args.input, args.output, args.completeOutput);
2427
+ if (!built)
2428
+ return false;
2429
+ const modelKeys = canonicalLkgModelKeys(args.modelKey, args.providerKey);
2430
+ const slot = {
2431
+ jsonPrefix: built.jsonPrefix,
2432
+ inputIdSeq: built.inputIdSeq,
2433
+ inputContentDigests: built.inputContentDigests,
2434
+ lastInputMessageId: built.anchorMessageId,
2435
+ modelKey: modelKeys.modelKey,
2436
+ providerKey: modelKeys.providerKey,
2437
+ capturedAt: args.capturedAt ?? Date.now()
2438
+ };
2439
+ const captured = captureSlot(args.sessionId, slot);
2440
+ if (captured)
2441
+ noteCapturedLkgRequest({
2442
+ sessionId: args.sessionId,
2443
+ slot,
2444
+ request: built.anchorIndex === args.input.length - 1 ? claimLkgRequestIdentity(args.sessionId) : undefined,
2445
+ systemPromptTokens: args.systemPromptTokens ?? 0,
2446
+ agentName: args.agentName
2447
+ });
2448
+ return captured;
2449
+ }
2450
+ function entryIdsAreValid(slot, entryIds) {
2451
+ if (slot.inputIdSeq.length === 0 || entryIds.length < slot.inputIdSeq.length)
2452
+ return false;
2453
+ if (slot.inputIdSeq[slot.inputIdSeq.length - 1] !== slot.lastInputMessageId)
2454
+ return false;
2455
+ const seen = new Set;
2456
+ for (const id of entryIds) {
2457
+ if (!id || seen.has(id))
2458
+ return false;
2459
+ seen.add(id);
2460
+ }
2461
+ if (entryIds.indexOf(slot.lastInputMessageId) !== slot.inputIdSeq.length - 1)
2462
+ return false;
2463
+ for (let index = 0;index < slot.inputIdSeq.length; index += 1) {
2464
+ if (entryIds[index] !== slot.inputIdSeq[index])
2465
+ return false;
2466
+ }
2467
+ return true;
2468
+ }
2469
+ function entryContentIsValid(slot, entry) {
2470
+ return entry.entryContentDigests.length >= slot.inputContentDigests.length && slot.inputContentDigests.every((digest, index) => isLegacyLkgDigest(digest) ? entry.entryLegacyContentDigests?.[index] === digest : entry.entryContentDigests[index] === digest);
2471
+ }
2472
+ function partCallIds(message) {
2473
+ const ids = [];
2474
+ for (const rawPart of messageParts(message)) {
2475
+ if (!rawPart || typeof rawPart !== "object")
2476
+ continue;
2477
+ const part = rawPart;
2478
+ if (part.type !== "tool" && part.type !== "tool_use")
2479
+ continue;
2480
+ const callId = part.callID ?? part.callId ?? part.id;
2481
+ if (typeof callId === "string" && callId.length > 0)
2482
+ ids.push(callId);
2483
+ }
2484
+ return ids;
2485
+ }
2486
+ function partResultIds(message) {
2487
+ const ids = [];
2488
+ for (const rawPart of messageParts(message)) {
2489
+ if (!rawPart || typeof rawPart !== "object")
2490
+ continue;
2491
+ const part = rawPart;
2492
+ if (part.type !== "tool_result" && part.type !== "tool-result")
2493
+ continue;
2494
+ const callId = part.tool_call_id ?? part.tool_use_id ?? part.callID ?? part.callId;
2495
+ if (typeof callId === "string" && callId.length > 0)
2496
+ ids.push(callId);
2497
+ }
2498
+ return ids;
2499
+ }
2500
+ function partIsReasoning(part) {
2501
+ return Boolean(part && typeof part === "object" && part.type === "reasoning");
2502
+ }
2503
+ function partIsAnthropicThinking(part) {
2504
+ if (!part || typeof part !== "object")
2505
+ return false;
2506
+ const type = part.type;
2507
+ return type === "thinking" || type === "reasoning" || type === "redacted_thinking";
2508
+ }
2509
+ function partEndsAnthropicAssistantRun(part) {
2510
+ if (!part || typeof part !== "object")
2511
+ return false;
2512
+ const value = part;
2513
+ if (value.type !== "tool" || value.providerExecuted === true || !value.state || typeof value.state !== "object") {
2514
+ return false;
2515
+ }
2516
+ const status = value.state.status;
2517
+ return status === "completed" || status === "error";
2518
+ }
2519
+ function partIsOpenCodeStepMetadata(part) {
2520
+ if (!part || typeof part !== "object")
2521
+ return false;
2522
+ const type = part.type;
2523
+ return type === "step-start" || type === "step-finish";
2524
+ }
2525
+ function validateAnthropicReasoningRuns(messages) {
2526
+ let index = 0;
2527
+ while (index < messages.length) {
2528
+ if (messageRole(messages[index]) !== "assistant") {
2529
+ index += 1;
2530
+ continue;
2531
+ }
2532
+ let firstMessageInRun = null;
2533
+ let sawOtherContent = false;
2534
+ while (index < messages.length && messageRole(messages[index]) === "assistant") {
2535
+ for (const part of messageParts(messages[index])) {
2536
+ if (partEndsAnthropicAssistantRun(part)) {
2537
+ firstMessageInRun = null;
2538
+ sawOtherContent = false;
2539
+ } else if (!partIsOpenCodeStepMetadata(part)) {
2540
+ if (firstMessageInRun === null)
2541
+ firstMessageInRun = index;
2542
+ if (partIsAnthropicThinking(part)) {
2543
+ if (sawOtherContent || index !== firstMessageInRun)
2544
+ return false;
2545
+ } else {
2546
+ sawOtherContent = true;
2547
+ }
2548
+ }
2549
+ }
2550
+ index += 1;
2551
+ }
2552
+ }
2553
+ return true;
2554
+ }
2555
+ function validateLkgSeamBoundary(prefix, tail) {
2556
+ const last = prefix[prefix.length - 1];
2557
+ const first = tail[0];
2558
+ if (!last || !first)
2559
+ return true;
2560
+ const lastCalls = partCallIds(last);
2561
+ if (lastCalls.length === 0)
2562
+ return true;
2563
+ const firstCalls = new Set([...partCallIds(first), ...partResultIds(first)]);
2564
+ if (messageRole(first) === "tool" || lastCalls.some((callId) => firstCalls.has(callId)))
2565
+ return false;
2566
+ return !messageParts(last).some((part) => {
2567
+ if (!part || typeof part !== "object")
2568
+ return false;
2569
+ const value = part;
2570
+ if (value.type !== "tool")
2571
+ return false;
2572
+ const state = value.state;
2573
+ return !state || typeof state !== "object" || state.status !== "completed";
2574
+ });
2575
+ }
2576
+ function validateLkgSeam(prefix, tail, providerKey) {
2577
+ const all = [...prefix, ...tail];
2578
+ const ids = new Set;
2579
+ const calls = new Set;
2580
+ const results = new Set;
2581
+ for (const message of all) {
2582
+ const id = messageId(message);
2583
+ if (id !== null) {
2584
+ if (ids.has(id))
2585
+ return false;
2586
+ ids.add(id);
2587
+ }
2588
+ for (const callId of partCallIds(message)) {
2589
+ if (calls.has(callId))
2590
+ return false;
2591
+ calls.add(callId);
2592
+ }
2593
+ for (const callId of partResultIds(message)) {
2594
+ if (results.has(callId))
2595
+ return false;
2596
+ results.add(callId);
2597
+ }
2598
+ if (messageRole(message) !== "assistant" && messageParts(message).some(partIsReasoning))
2599
+ return false;
2600
+ if (providerKey !== "anthropic" && messageParts(message).some((part) => {
2601
+ if (!part || typeof part !== "object")
2602
+ return false;
2603
+ const value = part;
2604
+ return (value.type === "text" || value.type === "reasoning") && value.text === "";
2605
+ }))
2606
+ return false;
2607
+ }
2608
+ if (!validateLkgSeamBoundary(prefix, tail))
2609
+ return false;
2610
+ const wireCandidates = all.map((message) => message);
2611
+ if (wireCandidates.every((message) => typeof message.role === "string")) {
2612
+ const adjacency = assertOpenAiCompatAdjacency(wireCandidates);
2613
+ if (!adjacency.ok)
2614
+ return false;
2615
+ const wireCallIds = new Set;
2616
+ for (const wireMessage of wireCandidates) {
2617
+ for (const call of wireMessage.tool_calls ?? []) {
2618
+ if (wireCallIds.has(call.id))
2619
+ return false;
2620
+ wireCallIds.add(call.id);
2621
+ }
2622
+ }
2623
+ }
2624
+ return true;
2625
+ }
2626
+ function replayLkg(args) {
2627
+ const slot = getSlot(args.sessionId);
2628
+ if (!slot)
2629
+ return { ok: false, reason: "lkg_invalidated_reshape" };
2630
+ const requestedModelKeys = canonicalLkgModelKeys(args.modelKey, args.providerKey);
2631
+ const capturedModelKeys = canonicalLkgModelKeys(slot.modelKey, slot.providerKey);
2632
+ if (capturedModelKeys.modelKey !== requestedModelKeys.modelKey || capturedModelKeys.providerKey !== requestedModelKeys.providerKey) {
2633
+ dropSlot(args.sessionId, "lkg_model_mismatch");
2634
+ return { ok: false, reason: "lkg_model_mismatch" };
2635
+ }
2636
+ const entry = args.entry ?? noteEntry(args.sessionId, args.messages);
2637
+ if (!entry || entry.anchorIndex !== slot.inputIdSeq.length - 1 || !entryIdsAreValid(slot, entry.entryInputIds)) {
2638
+ dropSlot(args.sessionId, "lkg_invalidated_reshape");
2639
+ return { ok: false, reason: "lkg_invalidated_reshape" };
2640
+ }
2641
+ if (!entryContentIsValid(slot, entry)) {
2642
+ dropSlot(args.sessionId, "lkg_content_mismatch");
2643
+ return { ok: false, reason: "lkg_content_mismatch" };
2644
+ }
2645
+ let prefix;
2646
+ try {
2647
+ const parsed = JSON.parse(slot.jsonPrefix);
2648
+ if (!Array.isArray(parsed))
2649
+ throw new Error("prefix is not an array");
2650
+ prefix = parsed;
2651
+ } catch {
2652
+ dropSlot(args.sessionId, "lkg_seam_invalid");
2653
+ return { ok: false, reason: "lkg_seam_invalid" };
2654
+ }
2655
+ const replayed = [...prefix, ...entry.pristineTail];
2656
+ args.prepareReplay?.(replayed);
2657
+ if (!args.skipSeamValidation) {
2658
+ if (!validateLkgSeamBoundary(prefix, entry.pristineTail)) {
2659
+ dropSlot(args.sessionId, "lkg_unsafe_seam");
2660
+ return { ok: false, reason: "lkg_unsafe_seam" };
2661
+ }
2662
+ if (!validateLkgSeam(prefix, entry.pristineTail, requestedModelKeys.providerKey)) {
2663
+ dropSlot(args.sessionId, "lkg_seam_invalid");
2664
+ return { ok: false, reason: "lkg_seam_invalid" };
2665
+ }
2666
+ }
2667
+ if (requestedModelKeys.providerKey === "anthropic" && !validateAnthropicReasoningRuns(replayed)) {
2668
+ dropSlot(args.sessionId, "lkg_anthropic_reasoning_run_invalid");
2669
+ return { ok: false, reason: "lkg_anthropic_reasoning_run_invalid" };
2670
+ }
2671
+ return { ok: true, messages: replayed };
2672
+ }
2673
+ function messageIdOf(message) {
2674
+ if (typeof message !== "object" || message === null)
2675
+ return;
2676
+ const info = message.info;
2677
+ if (typeof info !== "object" || info === null)
2678
+ return;
2679
+ const id = info.id;
2680
+ return typeof id === "string" ? id : undefined;
2681
+ }
2682
+ function coldStartRawServedIndex(args) {
2683
+ const raw = messagesById(args.rawInput);
2684
+ const rendered = messagesById(args.moduleOutput);
2685
+ const rawKeys = [];
2686
+ let runStart = args.slotMessages.length;
2687
+ while (runStart > 0) {
2688
+ const served = args.slotMessages[runStart - 1];
2689
+ const id = messageIdOf(served);
2690
+ const rawMessage = id === undefined ? undefined : raw.get(id);
2691
+ if (rawMessage === undefined)
2692
+ break;
2693
+ const rawKey = args.key(rawMessage);
2694
+ if (args.key(served) !== rawKey)
2695
+ break;
2696
+ runStart -= 1;
2697
+ rawKeys[runStart] = rawKey;
2698
+ }
2699
+ for (let index = runStart;index < args.slotMessages.length; index += 1) {
2700
+ const id = messageIdOf(args.slotMessages[index]);
2701
+ const moduleMessage = rendered.get(id);
2702
+ if (moduleMessage !== undefined && args.key(moduleMessage) !== rawKeys[index]) {
2703
+ const runStartId = messageIdOf(args.slotMessages[runStart]);
2704
+ const rawRunStart = args.rawInput.findIndex((message) => messageIdOf(message) === runStartId);
2705
+ return { index, rawRunStart };
2706
+ }
2707
+ }
2708
+ return null;
2709
+ }
2710
+ function messagesById(messages) {
2711
+ const map = new Map;
2712
+ for (const message of messages) {
2713
+ const id = messageIdOf(message);
2714
+ if (id !== undefined)
2715
+ map.set(id, message);
2716
+ }
2717
+ return map;
2718
+ }
2719
+ function coldStartUncapturedReplay(args) {
2720
+ const lastSlotId = messageIdOf(args.slotMessages.at(-1));
2721
+ if (lastSlotId === undefined)
2722
+ return null;
2723
+ const slotEnd = args.rawInput.findIndex((message) => messageIdOf(message) === lastSlotId);
2724
+ if (slotEnd < 0)
2725
+ return null;
2726
+ const rendered = messagesById(args.moduleOutput);
2727
+ for (let index = slotEnd + 1;index < args.rawInput.length - 1; index += 1) {
2728
+ const rawMessage = args.rawInput[index];
2729
+ const info = rawMessage?.info;
2730
+ if (info?.role !== "user" || info.synthetic === true)
2731
+ continue;
2732
+ const id = messageIdOf(rawMessage);
2733
+ const moduleMessage = id === undefined ? undefined : rendered.get(id);
2734
+ if (moduleMessage === undefined)
2735
+ continue;
2736
+ if (args.key(moduleMessage) === args.key(rawMessage))
2737
+ continue;
2738
+ return {
2739
+ lastServed: [...args.slotMessages, ...args.rawInput.slice(slotEnd + 1)],
2740
+ rawUserIndex: index
2741
+ };
2742
+ }
2743
+ return null;
2744
+ }
2745
+
2746
+ // src/hooks/magic-context/lkg-recovery-prefix.ts
2747
+ var sessions = new BoundedSessionMap(1000);
2748
+ function noteUncertifiedNormalLkg(sessionId, revision) {
2749
+ sessions.set(sessionId, {
2750
+ ...sessions.get(sessionId),
2751
+ fenceRevision: revision,
2752
+ uncertifiedNormal: true
2753
+ });
2754
+ }
2755
+ function hasProcessLocalLkgProof(sessionId) {
2756
+ return sessions.has(sessionId) && !sessions.get(sessionId)?.uncertifiedNormal;
2757
+ }
2758
+ function lkgDirtyRevision(sessionId) {
2759
+ return sessions.get(sessionId)?.fenceRevision;
2760
+ }
2761
+ function rememberLkgDirtyRevision(sessionId, revision) {
2762
+ sessions.set(sessionId, { ...sessions.get(sessionId), fenceRevision: revision });
2763
+ }
2764
+ function clearLkgRecoverySession(sessionId) {
2765
+ sessions.delete(sessionId);
2766
+ clearLkgFenceProcessState(sessionId);
2767
+ }
2768
+ function noteLkgCapturedPrefix(sessionId) {
2769
+ if (!sessions.has(sessionId))
2770
+ sessions.set(sessionId, {});
2771
+ }
2772
+ function readPersistedLkgUntaggedInputIds(db, sessionId) {
2773
+ try {
2774
+ const saved = readReplayEnvelope(db, sessionId, "read").lkgUntaggedInputIds;
2775
+ return Array.isArray(saved) ? saved.filter((id) => typeof id === "string" && id.length > 0) : [];
2776
+ } catch (error) {
2777
+ sessionLog2(sessionId, "LKG untagged-input record unreadable:", error);
2778
+ return [];
2779
+ }
2780
+ }
2781
+ function persistLkgUntaggedInputIds(db, sessionId, ids) {
2782
+ const next = [...new Set(ids)].sort();
2783
+ try {
2784
+ return updateReplayDocument(db, sessionId, (doc) => {
2785
+ const saved = Array.isArray(doc.lkgUntaggedInputIds) ? doc.lkgUntaggedInputIds : [];
2786
+ if (JSON.stringify(saved) === JSON.stringify(next))
2787
+ return false;
2788
+ doc.version = 2;
2789
+ if (next.length > 0)
2790
+ doc.lkgUntaggedInputIds = next;
2791
+ else
2792
+ delete doc.lkgUntaggedInputIds;
2793
+ return true;
2794
+ });
2795
+ } catch (error) {
2796
+ sessionLog2(sessionId, "LKG untagged-input record write failed:", error);
2797
+ return false;
2798
+ }
2799
+ }
2800
+ function noteLkgRecoveryPrefix(args) {
2801
+ const digests = [
2802
+ ...args.entry.entryContentDigests,
2803
+ ...args.entry.pristineTail.map(lkgContentDigest)
2804
+ ];
2805
+ if (digests.length !== args.entry.entryInputIds.length || digests.some((value) => !value))
2806
+ return false;
2807
+ const ids = args.entry.entryInputIds;
2808
+ if (ids.some((id) => !id) || new Set(ids).size !== ids.length)
2809
+ return false;
2810
+ const untaggedInputIds = new Set([
2811
+ ...sessions.get(args.sessionId)?.prefix?.untaggedInputIds ?? [],
2812
+ ...args.db ? readPersistedLkgUntaggedInputIds(args.db, args.sessionId) : [],
2813
+ ...ids.slice(args.entry.anchorIndex + 1)
2814
+ ]);
2815
+ sessions.set(args.sessionId, {
2816
+ fenceRevision: sessions.get(args.sessionId)?.fenceRevision,
2817
+ prefix: {
2818
+ inputs: ids.map((id, index) => ({ id, digest: digests[index] })),
2819
+ json: JSON.stringify(args.messages),
2820
+ untaggedInputIds,
2821
+ modelKey: args.modelKey,
2822
+ providerKey: args.providerKey
2823
+ }
2824
+ });
2825
+ if (args.db)
2826
+ persistLkgUntaggedInputIds(args.db, args.sessionId, untaggedInputIds);
2827
+ return true;
2828
+ }
2829
+ function readLkgRecoveryPrefix(sessionId, inputs, messages, db) {
2830
+ return readRecoveryIdentityPrefix(sessionId, inputs.map((input, index) => ({
2831
+ id: lkgInputIdentity(input.id, input.role, index),
2832
+ contentDigest: input.contentDigest
2833
+ })), messages, db);
2834
+ }
2835
+ function readRecoveryIdentityPrefix(sessionId, inputs, messages, db) {
2836
+ const state = sessions.get(sessionId);
2837
+ const slot = db && (!state || state.prefix || state.uncertifiedNormal) ? loadPersistedLkgSlot(db, sessionId, true) ?? getSlot(sessionId) : getSlot(sessionId);
2838
+ const prefix = state?.prefix;
2839
+ if (!prefix && state?.uncertifiedNormal && ownsLkgDirtyFence(sessionId, state.fenceRevision))
2840
+ return {};
2841
+ if (!prefix)
2842
+ return !state && lkgRecoveryFenceUnclean(sessionId) || slot && lkgFenceRequiresRebuild(sessionId, slot, !!state) ? { rebuildReason: "lkg_restart_rebuild" } : {};
2843
+ const keys = resolveLkgModelKeys(messages);
2844
+ if (state?.fenceRevision !== undefined && (!slot || !ownsLkgDirtyFence(sessionId, state.fenceRevision)) || prefix.modelKey !== keys.modelKey || prefix.providerKey !== keys.providerKey || inputs.length < prefix.inputs.length || prefix.inputs.some((input, index) => input.id !== inputs[index]?.id || input.digest !== inputs[index]?.contentDigest?.()))
2845
+ return { rebuildReason: "lkg_recovery_input_rebuild" };
2846
+ return { prefix };
2847
+ }
2848
+ function noteLkgHealthyPrefix(sessionId, inputs, messages, release) {
2849
+ const prefix = sessions.get(sessionId)?.prefix;
2850
+ sessions.set(sessionId, {
2851
+ fenceRevision: sessions.get(sessionId)?.fenceRevision,
2852
+ prefix: prefix && !release ? {
2853
+ ...prefix,
2854
+ inputs: inputs.map((input, index) => ({
2855
+ id: lkgInputIdentity(input.id, input.role, index) ?? "",
2856
+ digest: input.contentDigest?.() ?? ""
2857
+ })),
2858
+ json: JSON.stringify(messages)
2859
+ } : undefined
2860
+ });
2861
+ }
2862
+ function lkgRecoveryReplayUnproven(sessionId) {
2863
+ const slot = getSlot(sessionId);
2864
+ return !!slot && !sessions.has(sessionId) && lkgFenceRequiresRebuild(sessionId, slot, false);
2865
+ }
2866
+ function lkgRecoveryEntryUnproven(sessionId, entry, messages) {
2867
+ if (!sessions.get(sessionId)?.prefix)
2868
+ return false;
2869
+ const digests = [...entry.entryContentDigests, ...entry.pristineTail.map(lkgContentDigest)];
2870
+ const inputs = entry.entryInputIds.map((id, index) => ({
2871
+ id,
2872
+ contentDigest: () => digests[index] ?? null
2873
+ }));
2874
+ return !!readRecoveryIdentityPrefix(sessionId, inputs, messages).rebuildReason;
2875
+ }
2876
+
2877
+ // src/hooks/magic-context/lkg-slot.ts
2878
+ var POSITIONAL_SYSTEM_KEY = "\x00mc-system:";
2879
+ function lkgInputIdentity(id, role, index) {
2880
+ if (typeof id === "string" && id.length > 0)
2881
+ return id.startsWith(POSITIONAL_SYSTEM_KEY) ? null : id;
2882
+ return role === "system" ? `${POSITIONAL_SYSTEM_KEY}${index}` : null;
2883
+ }
2884
+ var LKG_SINGLE_SLOT_BYTES = 72 * 1024 * 1024;
2885
+ var LKG_TOTAL_BYTES = 160 * 1024 * 1024;
2886
+ var LKG_METADATA_BYTES = 256;
2887
+
2888
+ class MagicContextLkgHeapHolder {
2889
+ entries = new Map;
2890
+ }
2891
+ var lkgHeapHolder = new MagicContextLkgHeapHolder;
2892
+ var totalBytes = 0;
2893
+ var hydrationPassBySession = new BoundedSessionMap(1000);
2894
+ var hydrationAttemptBySession = new BoundedSessionMap(1000);
2895
+ var persistenceBackend;
2896
+ function registerLkgPersistence(backend) {
2897
+ persistenceBackend = backend;
2898
+ hydrationPassBySession.clear();
2899
+ hydrationAttemptBySession.clear();
2900
+ }
2901
+ function beginLkgPass(sessionId) {
2902
+ const next = (hydrationPassBySession.peek(sessionId) ?? 0) + 1;
2903
+ hydrationPassBySession.set(sessionId, next);
2904
+ }
2905
+ function slotBytes(slot) {
2906
+ const digestBytes = slot.inputContentDigests.reduce((total, digest) => total + 2 * digest.length, 0);
2907
+ const ownershipBytes = slot.piOutputEntryIds?.reduce((total, id) => total + (id?.length ?? 0) * 2 + 8, 0) ?? 0;
2908
+ return 2 * slot.jsonPrefix.length + digestBytes + ownershipBytes + LKG_METADATA_BYTES;
2909
+ }
2910
+ var LKG_SNAPSHOT_ARRAY = Symbol("array");
2911
+ var LKG_SNAPSHOT_OBJECT = Symbol("object");
2912
+ var LKG_SNAPSHOT_KEY = Symbol("key");
2913
+ var LKG_SNAPSHOT_STRING = Symbol("string");
2914
+ var LKG_SNAPSHOT_NUMBER = Symbol("number");
2915
+ var LKG_SNAPSHOT_BOOLEAN = Symbol("boolean");
2916
+ var LKG_SNAPSHOT_NULL = Symbol("null");
2917
+ var LKG_SNAPSHOT_UNDEFINED = Symbol("undefined");
2918
+ var FNV1A_32_OFFSET = 2166136261;
2919
+ var FNV1A_32_PRIME = 16777619;
2920
+ function updateFnv1a32(hash, value) {
2921
+ let next = hash;
2922
+ for (let index = 0;index < value.length; index += 1) {
2923
+ next ^= value.charCodeAt(index);
2924
+ next = Math.imul(next, FNV1A_32_PRIME) >>> 0;
2925
+ }
2926
+ return next;
2927
+ }
2928
+ function isSnapshotObjectChild(value) {
2929
+ return value !== undefined && typeof value !== "function" && typeof value !== "symbol";
2930
+ }
2931
+ function visitMessageContentFields(value, visitor) {
2932
+ if (value === null)
2933
+ return visitor.field(LKG_SNAPSHOT_NULL);
2934
+ if (typeof value === "string") {
2935
+ return visitor.field(LKG_SNAPSHOT_STRING) && visitor.field(value);
2936
+ }
2937
+ if (typeof value === "number") {
2938
+ return visitor.field(LKG_SNAPSHOT_NUMBER) && visitor.field(value);
2939
+ }
2940
+ if (typeof value === "boolean") {
2941
+ return visitor.field(LKG_SNAPSHOT_BOOLEAN) && visitor.field(value);
2942
+ }
2943
+ if (value === undefined || typeof value === "function" || typeof value === "symbol") {
2944
+ return visitor.field(LKG_SNAPSHOT_UNDEFINED);
2945
+ }
2946
+ if (Array.isArray(value)) {
2947
+ if (!visitor.field(LKG_SNAPSHOT_ARRAY) || !visitor.field(value.length))
2948
+ return false;
2949
+ for (const item of value) {
2950
+ if (!visitMessageContentFields(item, visitor))
2951
+ return false;
2952
+ }
2953
+ return true;
2954
+ }
2955
+ if (typeof value === "object") {
2956
+ if (!visitor.field(LKG_SNAPSHOT_OBJECT))
2957
+ return false;
2958
+ const objectToken = visitor.beginObject();
2959
+ if (objectToken === undefined)
2960
+ return false;
2961
+ let entryCount = 0;
2962
+ for (const key in value) {
2963
+ if (!Object.hasOwn(value, key))
2964
+ continue;
2965
+ const child = value[key];
2966
+ if (!isSnapshotObjectChild(child))
2967
+ continue;
2968
+ entryCount += 1;
2969
+ if (!visitor.field(LKG_SNAPSHOT_KEY) || !visitor.field(key) || !visitMessageContentFields(child, visitor)) {
2970
+ return false;
2971
+ }
2972
+ }
2973
+ return visitor.endObject(objectToken, entryCount);
2974
+ }
2975
+ return visitor.field(LKG_SNAPSHOT_UNDEFINED);
2976
+ }
2977
+ function contentSnapshotValue(value) {
2978
+ if (!value || typeof value !== "object")
2979
+ return value;
2980
+ return withoutEmptyUserDiffSummary(providerVisibleMessage(value));
2981
+ }
2982
+ function withoutEmptyUserDiffSummary(value) {
2983
+ if (!value || typeof value !== "object")
2984
+ return value;
2985
+ const message = value;
2986
+ const info = message.info;
2987
+ const summary = info?.summary;
2988
+ if (!Array.isArray(message.parts) || info?.role !== "user" || summary === null || typeof summary !== "object" || Array.isArray(summary) || Object.keys(summary).length !== 1 || !Array.isArray(summary.diffs) || summary.diffs.length !== 0)
2989
+ return value;
2990
+ return {
2991
+ ...message,
2992
+ info: Object.fromEntries(Object.entries(info).filter(([key]) => key !== "summary"))
2993
+ };
2994
+ }
2995
+ function messageContentFields(message) {
2996
+ const fields = [];
2997
+ const complete = visitMessageContentFields(contentSnapshotValue(message), {
2998
+ field(value) {
2999
+ fields.push(value);
3000
+ return true;
3001
+ },
3002
+ beginObject() {
3003
+ const countIndex = fields.length;
3004
+ fields.push(0);
3005
+ return countIndex;
3006
+ },
3007
+ endObject(countIndex, entryCount) {
3008
+ fields[countIndex] = entryCount;
3009
+ return true;
3010
+ }
3011
+ });
3012
+ if (!complete)
3013
+ throw new Error("message content snapshot traversal stopped unexpectedly");
3014
+ return fields;
3015
+ }
3016
+ function signatureForFields(fields) {
3017
+ let hash = FNV1A_32_OFFSET;
3018
+ for (const field of fields) {
3019
+ const value = typeof field === "symbol" ? field.description ?? "" : String(field);
3020
+ hash = updateFnv1a32(hash, `${typeof field}:${value.length}:`);
3021
+ hash = updateFnv1a32(hash, value);
3022
+ hash = updateFnv1a32(hash, "\x00");
3023
+ }
3024
+ return hash.toString(16).padStart(8, "0");
3025
+ }
3026
+ function lkgContentFields(value) {
3027
+ return flattenContentFields(contentSnapshotValue(value));
3028
+ }
3029
+ function flattenContentFields(snapshot) {
3030
+ const fields = [];
3031
+ const seen = new WeakSet;
3032
+ const visit = (child) => {
3033
+ if (child === null)
3034
+ fields.push(LKG_SNAPSHOT_NULL);
3035
+ else if (typeof child === "string")
3036
+ fields.push(LKG_SNAPSHOT_STRING, child);
3037
+ else if (typeof child === "number")
3038
+ fields.push(LKG_SNAPSHOT_NUMBER, child);
3039
+ else if (typeof child === "boolean")
3040
+ fields.push(LKG_SNAPSHOT_BOOLEAN, child);
3041
+ else if (child === undefined || typeof child === "function" || typeof child === "symbol") {
3042
+ fields.push(LKG_SNAPSHOT_UNDEFINED);
3043
+ } else if (Array.isArray(child)) {
3044
+ if (seen.has(child))
3045
+ throw new Error("cyclic message");
3046
+ seen.add(child);
3047
+ fields.push(LKG_SNAPSHOT_ARRAY, child.length);
3048
+ for (const item of child)
3049
+ visit(item);
3050
+ seen.delete(child);
3051
+ } else if (typeof child === "object") {
3052
+ if (seen.has(child))
3053
+ throw new Error("cyclic message");
3054
+ seen.add(child);
3055
+ const entries = Object.entries(child).filter(([, entry]) => entry !== undefined && typeof entry !== "function" && typeof entry !== "symbol");
3056
+ fields.push(LKG_SNAPSHOT_OBJECT, entries.length);
3057
+ for (const [key, entry] of entries) {
3058
+ fields.push(LKG_SNAPSHOT_KEY, key);
3059
+ visit(entry);
3060
+ }
3061
+ seen.delete(child);
3062
+ } else
3063
+ fields.push(LKG_SNAPSHOT_UNDEFINED);
3064
+ };
3065
+ try {
3066
+ visit(snapshot);
3067
+ return fields;
3068
+ } catch {
3069
+ return null;
3070
+ }
3071
+ }
3072
+ var DIGEST_TAG_STRING = 1;
3073
+ var DIGEST_TAG_NUMBER = 2;
3074
+ var DIGEST_TAG_TRUE = 3;
3075
+ var DIGEST_TAG_FALSE = 4;
3076
+ var DIGEST_TAG_OTHER_SYMBOL = 5;
3077
+ var DIGEST_SYMBOL_TAGS = new Map([
3078
+ [LKG_SNAPSHOT_ARRAY, 16],
3079
+ [LKG_SNAPSHOT_OBJECT, 17],
3080
+ [LKG_SNAPSHOT_KEY, 18],
3081
+ [LKG_SNAPSHOT_STRING, 19],
3082
+ [LKG_SNAPSHOT_NUMBER, 20],
3083
+ [LKG_SNAPSHOT_BOOLEAN, 21],
3084
+ [LKG_SNAPSHOT_NULL, 22],
3085
+ [LKG_SNAPSHOT_UNDEFINED, 23]
3086
+ ]);
3087
+ var DIGEST_CHUNK_BYTES = 64 * 1024;
3088
+ var digestChunk;
3089
+ function lkgContentDigestFromFields(fields) {
3090
+ lkgDigestsComputed += 1;
3091
+ const hash = createHash6("sha256");
3092
+ digestChunk ??= Buffer.allocUnsafe(DIGEST_CHUNK_BYTES);
3093
+ const chunk = digestChunk;
3094
+ let offset = 0;
3095
+ const room = (bytes) => {
3096
+ if (offset + bytes <= chunk.length)
3097
+ return;
3098
+ hash.update(chunk.subarray(0, offset));
3099
+ offset = 0;
3100
+ };
3101
+ const writeString = (tag, value) => {
3102
+ const bytes = value.length * 2;
3103
+ room(5);
3104
+ chunk[offset] = tag;
3105
+ chunk.writeUInt32LE(value.length, offset + 1);
3106
+ offset += 5;
3107
+ if (bytes <= chunk.length - offset) {
3108
+ chunk.write(value, offset, bytes, "utf16le");
3109
+ offset += bytes;
3110
+ return;
3111
+ }
3112
+ hash.update(chunk.subarray(0, offset));
3113
+ offset = 0;
3114
+ hash.update(Buffer.from(value, "utf16le"));
3115
+ };
3116
+ for (const field of fields) {
3117
+ if (typeof field === "string") {
3118
+ writeString(DIGEST_TAG_STRING, field);
3119
+ } else if (typeof field === "number") {
3120
+ room(9);
3121
+ chunk[offset] = DIGEST_TAG_NUMBER;
3122
+ chunk.writeDoubleLE(field, offset + 1);
3123
+ offset += 9;
3124
+ } else if (typeof field === "boolean") {
3125
+ room(1);
3126
+ chunk[offset] = field ? DIGEST_TAG_TRUE : DIGEST_TAG_FALSE;
3127
+ offset += 1;
3128
+ } else {
3129
+ const tag = DIGEST_SYMBOL_TAGS.get(field);
3130
+ if (tag === undefined) {
3131
+ writeString(DIGEST_TAG_OTHER_SYMBOL, field.description ?? "");
3132
+ } else {
3133
+ room(1);
3134
+ chunk[offset] = tag;
3135
+ offset += 1;
3136
+ }
3137
+ }
3138
+ }
3139
+ if (offset > 0)
3140
+ hash.update(chunk.subarray(0, offset));
3141
+ return LKG_DIGEST_FORMAT_PREFIX + hash.digest("base64url");
3142
+ }
3143
+ var LKG_DIGEST_FORMAT_PREFIX = "2.";
3144
+ function isLegacyLkgDigest(digest) {
3145
+ return !digest.startsWith(LKG_DIGEST_FORMAT_PREFIX);
3146
+ }
3147
+ function legacyLkgDigestFromFields(fields) {
3148
+ lkgDigestsComputed += 1;
3149
+ let key = "";
3150
+ for (const field of fields) {
3151
+ const value = typeof field === "symbol" ? field.description ?? "" : String(field);
3152
+ key += `${typeof field}:${value.length}:${value}\x00`;
3153
+ }
3154
+ return createHash6("sha256").update(key).digest("base64url");
3155
+ }
3156
+ function legacyLkgContentDigest(message) {
3157
+ const fields = flattenContentFields(withoutEmptyUserDiffSummary(message));
3158
+ return fields ? legacyLkgDigestFromFields(fields) : null;
3159
+ }
3160
+ var digestMemo = new Map;
3161
+ var DIGEST_MEMO_MAX_BYTES = 16 * 1024 * 1024;
3162
+ function equalContentFields(left, right) {
3163
+ if (left === right)
3164
+ return true;
3165
+ if (left.length !== right.length)
3166
+ return false;
3167
+ for (let index = 0;index < left.length; index += 1) {
3168
+ if (!Object.is(left[index], right[index]))
3169
+ return false;
3170
+ }
3171
+ return true;
3172
+ }
3173
+ function exactReusablePrefix(current, prior) {
3174
+ if (!prior)
3175
+ return 0;
3176
+ let prefix = 0;
3177
+ while (prefix < current.length && prefix < prior.length && current[prefix]?.id === prior[prefix]?.id && equalContentFields(current[prefix]?.fields ?? [], prior[prefix]?.fields ?? [])) {
3178
+ prefix += 1;
3179
+ }
3180
+ return prefix;
3181
+ }
3182
+ function incrementalLkgContentDigests(entries, prior) {
3183
+ const aligned = prior !== undefined && prior.ids.length === prior.signatures.length && prior.signatures.length === prior.digests.length;
3184
+ let reusedPrefix = 0;
3185
+ if (aligned && prior) {
3186
+ while (reusedPrefix < entries.length && reusedPrefix < prior.ids.length && entries[reusedPrefix]?.id === prior.ids[reusedPrefix] && entries[reusedPrefix]?.signature === prior.signatures[reusedPrefix] && !isLegacyLkgDigest(prior.digests[reusedPrefix] ?? "")) {
3187
+ reusedPrefix += 1;
3188
+ }
3189
+ }
3190
+ const digests = [];
3191
+ if (aligned && prior) {
3192
+ for (let index = 0;index < reusedPrefix; index += 1) {
3193
+ digests.push(prior.digests[index]);
3194
+ }
3195
+ }
3196
+ for (let index = reusedPrefix;index < entries.length; index += 1) {
3197
+ digests.push(lkgContentDigestFromFields(entries[index]?.fields ?? []));
3198
+ }
3199
+ return { digests, reusedPrefix };
3200
+ }
3201
+ function lkgContentDigest(message) {
3202
+ const fields = lkgContentFields(message);
3203
+ return fields ? lkgContentDigestFromFields(fields) : null;
3204
+ }
3205
+ function touch(sessionId, entry) {
3206
+ lkgHeapHolder.entries.delete(sessionId);
3207
+ lkgHeapHolder.entries.set(sessionId, entry);
3208
+ }
3209
+ function lkgSlotRejection(sessionId, slot) {
3210
+ if (slot.inputContentDigests.length !== slot.inputIdSeq.length)
3211
+ return `digest_count=${slot.inputContentDigests.length} inputs=${slot.inputIdSeq.length}`;
3212
+ const emptyDigest = slot.inputContentDigests.findIndex((digest) => digest.length === 0);
3213
+ if (emptyDigest >= 0)
3214
+ return `empty_digest_at=${emptyDigest}`;
3215
+ if (slot.inputContentSignatures !== undefined) {
3216
+ if (slot.inputContentSignatures.length !== slot.inputIdSeq.length)
3217
+ return `signature_count=${slot.inputContentSignatures.length} inputs=${slot.inputIdSeq.length}`;
3218
+ const emptySignature = slot.inputContentSignatures.findIndex((signature) => signature.length === 0);
3219
+ if (emptySignature >= 0)
3220
+ return `empty_signature_at=${emptySignature}`;
3221
+ }
3222
+ const bytes = slotBytes(slot);
3223
+ if (bytes > LKG_SINGLE_SLOT_BYTES)
3224
+ return `slot_bytes=${bytes}`;
3225
+ const prior = lkgHeapHolder.entries.get(sessionId);
3226
+ if (prior?.slot.rowVersion !== undefined && slot.rowVersion !== undefined && (slot.rowVersion < prior.slot.rowVersion || slot.rowVersion === prior.slot.rowVersion && (slot.captureSequence ?? 0) < (prior.slot.captureSequence ?? 0))) {
3227
+ return `stale row_version=${slot.rowVersion}/${prior.slot.rowVersion} capture_sequence=${slot.captureSequence ?? 0}/${prior.slot.captureSequence ?? 0}`;
3228
+ }
3229
+ return null;
3230
+ }
3231
+ function captureSlot(sessionId, slot) {
3232
+ if (lkgSlotRejection(sessionId, slot) !== null)
3233
+ return false;
3234
+ const bytes = slotBytes(slot);
3235
+ const prior = lkgHeapHolder.entries.get(sessionId);
3236
+ if (prior)
3237
+ totalBytes -= prior.bytes;
3238
+ lkgHeapHolder.entries.delete(sessionId);
3239
+ while (totalBytes + bytes > LKG_TOTAL_BYTES) {
3240
+ const oldest = lkgHeapHolder.entries.keys().next().value;
3241
+ if (oldest === undefined)
3242
+ break;
3243
+ const evicted = lkgHeapHolder.entries.get(oldest);
3244
+ lkgHeapHolder.entries.delete(oldest);
3245
+ if (evicted)
3246
+ totalBytes -= evicted.bytes;
3247
+ }
3248
+ if (totalBytes + bytes > LKG_TOTAL_BYTES) {
3249
+ if (prior) {
3250
+ lkgHeapHolder.entries.set(sessionId, prior);
3251
+ totalBytes += prior.bytes;
3252
+ }
3253
+ return false;
3254
+ }
3255
+ const entry = {
3256
+ slot: {
3257
+ ...slot,
3258
+ ...slot.piOutputEntryIds ? { piOutputEntryIds: [...slot.piOutputEntryIds] } : {},
3259
+ inputIdSeq: [...slot.inputIdSeq],
3260
+ inputContentDigests: [...slot.inputContentDigests],
3261
+ inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
3262
+ },
3263
+ bytes
3264
+ };
3265
+ lkgHeapHolder.entries.set(sessionId, entry);
3266
+ totalBytes += bytes;
3267
+ hydrationAttemptBySession.delete(sessionId);
3268
+ noteLkgCapturedPrefix(sessionId);
3269
+ return true;
3270
+ }
3271
+ function installHydratedSlot(sessionId, slot) {
3272
+ const bytes = slotBytes(slot);
3273
+ if (bytes > LKG_SINGLE_SLOT_BYTES)
3274
+ return false;
3275
+ const prior = lkgHeapHolder.entries.get(sessionId);
3276
+ if (prior)
3277
+ totalBytes -= prior.bytes;
3278
+ lkgHeapHolder.entries.delete(sessionId);
3279
+ while (totalBytes + bytes > LKG_TOTAL_BYTES) {
3280
+ const oldest = lkgHeapHolder.entries.keys().next().value;
3281
+ if (oldest === undefined)
3282
+ break;
3283
+ const evicted = lkgHeapHolder.entries.get(oldest);
3284
+ lkgHeapHolder.entries.delete(oldest);
3285
+ if (evicted)
3286
+ totalBytes -= evicted.bytes;
3287
+ }
3288
+ if (totalBytes + bytes > LKG_TOTAL_BYTES) {
3289
+ if (prior) {
3290
+ lkgHeapHolder.entries.set(sessionId, prior);
3291
+ totalBytes += prior.bytes;
3292
+ }
3293
+ return false;
3294
+ }
3295
+ const entry = {
3296
+ slot: {
3297
+ ...slot,
3298
+ ...slot.piOutputEntryIds ? { piOutputEntryIds: [...slot.piOutputEntryIds] } : {},
3299
+ inputIdSeq: [...slot.inputIdSeq],
3300
+ inputContentDigests: [...slot.inputContentDigests],
3301
+ inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
3302
+ },
3303
+ bytes
3304
+ };
3305
+ lkgHeapHolder.entries.set(sessionId, entry);
3306
+ totalBytes += bytes;
3307
+ return true;
3308
+ }
3309
+ function hydrateSlotFromPersistence(sessionId) {
3310
+ const backend = persistenceBackend;
3311
+ if (!backend)
3312
+ return;
3313
+ let loaded;
3314
+ try {
3315
+ loaded = backend.load(sessionId);
3316
+ } catch (error) {
3317
+ sessionLog2(sessionId, "LKG durable hydration failed:", error);
3318
+ return;
3319
+ }
3320
+ if (!loaded)
3321
+ return;
3322
+ if (!installHydratedSlot(sessionId, loaded))
3323
+ return;
3324
+ sessionLog2(sessionId, "lkg_hydrated_from_disk");
3325
+ const entry = lkgHeapHolder.entries.get(sessionId);
3326
+ return entry ? copySlotForRead(entry.slot) : undefined;
3327
+ }
3328
+ function copySlotForRead(slot) {
3329
+ return {
3330
+ ...slot,
3331
+ ...slot.piOutputEntryIds ? { piOutputEntryIds: [...slot.piOutputEntryIds] } : {},
3332
+ inputIdSeq: [...slot.inputIdSeq],
3333
+ inputContentDigests: [...slot.inputContentDigests],
3334
+ inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
3335
+ };
3336
+ }
3337
+ function getInMemorySlot(sessionId) {
3338
+ const entry = lkgHeapHolder.entries.get(sessionId);
3339
+ return entry ? copySlotForRead(entry.slot) : undefined;
3340
+ }
3341
+ function getSlot(sessionId) {
3342
+ const entry = lkgHeapHolder.entries.get(sessionId);
3343
+ if (!entry) {
3344
+ const pass = hydrationPassBySession.peek(sessionId);
3345
+ if (pass !== undefined) {
3346
+ if (hydrationAttemptBySession.peek(sessionId) === pass)
3347
+ return;
3348
+ hydrationAttemptBySession.set(sessionId, pass);
3349
+ }
3350
+ return hydrateSlotFromPersistence(sessionId);
3351
+ }
3352
+ touch(sessionId, entry);
3353
+ return copySlotForRead(entry.slot);
3354
+ }
3355
+ function forgetInMemorySlot(sessionId) {
3356
+ clearLkgRecoverySession(sessionId);
3357
+ const entry = lkgHeapHolder.entries.get(sessionId);
3358
+ if (entry) {
3359
+ lkgHeapHolder.entries.delete(sessionId);
3360
+ totalBytes -= entry.bytes;
3361
+ }
3362
+ }
3363
+ function dropSlot(sessionId, _reason) {
3364
+ clearCapturedLkgMeasurement(sessionId);
3365
+ forgetInMemorySlot(sessionId);
3366
+ const backend = persistenceBackend;
3367
+ if (!backend)
3368
+ return;
3369
+ try {
3370
+ backend.clear(sessionId);
3371
+ } catch (error) {
3372
+ sessionLog2(sessionId, "LKG durable clear failed:", error);
3373
+ }
3374
+ const pass = hydrationPassBySession.peek(sessionId);
3375
+ if (pass !== undefined)
3376
+ hydrationAttemptBySession.set(sessionId, pass);
3377
+ }
3378
+ function noteEntry(sessionId, input) {
3379
+ const slot = getSlot(sessionId);
3380
+ if (!slot)
3381
+ return null;
3382
+ const messages = input;
3383
+ const entryInputIds = messages.map((message, index) => lkgInputIdentity(message.info?.id, message.info?.role, index) ?? "");
3384
+ const anchorIndex = entryInputIds.indexOf(slot.lastInputMessageId);
3385
+ if (anchorIndex < 0)
3386
+ return null;
3387
+ const digests = sharedLkgEntryDigests.digests(sessionId, messages).digests;
3388
+ const entryContentDigests = [];
3389
+ for (let index = 0;index <= anchorIndex; index += 1) {
3390
+ const digest = digests[index];
3391
+ if (digest === null || digest === undefined)
3392
+ return null;
3393
+ entryContentDigests.push(digest);
3394
+ }
3395
+ const pristineTail = structuredClone(messages.slice(anchorIndex + 1));
3396
+ const entryLegacyContentDigests = slot.inputContentDigests.some(isLegacyLkgDigest) ? messages.slice(0, anchorIndex + 1).map((message) => legacyLkgContentDigest(message)) : undefined;
3397
+ return {
3398
+ pristineTail,
3399
+ entryInputIds,
3400
+ entryContentDigests,
3401
+ ...entryLegacyContentDigests ? { entryLegacyContentDigests } : {},
3402
+ anchorIndex
3403
+ };
3404
+ }
3405
+ function contentMatchesFields(value, fields) {
3406
+ let cursor = 0;
3407
+ const visit = (child) => {
3408
+ if (child === null)
3409
+ return fields[cursor++] === LKG_SNAPSHOT_NULL;
3410
+ switch (typeof child) {
3411
+ case "string": {
3412
+ if (fields[cursor] !== LKG_SNAPSHOT_STRING)
3413
+ return false;
3414
+ const prior = fields[cursor + 1];
3415
+ if (typeof prior !== "string" || prior.length !== child.length)
3416
+ return false;
3417
+ if (prior !== child)
3418
+ return false;
3419
+ lkgEntryWork.comparedChars += child.length;
3420
+ fields[cursor + 1] = child;
3421
+ cursor += 2;
3422
+ return true;
3423
+ }
3424
+ case "number":
3425
+ if (fields[cursor] !== LKG_SNAPSHOT_NUMBER)
3426
+ return false;
3427
+ if (!Object.is(fields[cursor + 1], child))
3428
+ return false;
3429
+ cursor += 2;
3430
+ return true;
3431
+ case "boolean":
3432
+ if (fields[cursor] !== LKG_SNAPSHOT_BOOLEAN || fields[cursor + 1] !== child) {
3433
+ return false;
3434
+ }
3435
+ cursor += 2;
3436
+ return true;
3437
+ case "object": {
3438
+ if (Array.isArray(child)) {
3439
+ if (fields[cursor] !== LKG_SNAPSHOT_ARRAY)
3440
+ return false;
3441
+ if (fields[cursor + 1] !== child.length)
3442
+ return false;
3443
+ cursor += 2;
3444
+ for (const item of child) {
3445
+ if (!visit(item))
3446
+ return false;
3447
+ }
3448
+ return true;
3449
+ }
3450
+ if (fields[cursor] !== LKG_SNAPSHOT_OBJECT)
3451
+ return false;
3452
+ const keys = Object.keys(child);
3453
+ let entryCount = 0;
3454
+ for (const key of keys) {
3455
+ if (isSnapshotObjectChild(child[key])) {
3456
+ entryCount += 1;
3457
+ }
3458
+ }
3459
+ if (fields[cursor + 1] !== entryCount)
3460
+ return false;
3461
+ cursor += 2;
3462
+ for (const key of keys) {
3463
+ const entry = child[key];
3464
+ if (!isSnapshotObjectChild(entry))
3465
+ continue;
3466
+ if (fields[cursor] !== LKG_SNAPSHOT_KEY || fields[cursor + 1] !== key) {
3467
+ return false;
3468
+ }
3469
+ cursor += 2;
3470
+ if (!visit(entry))
3471
+ return false;
3472
+ }
3473
+ return true;
3474
+ }
3475
+ default:
3476
+ return fields[cursor++] === LKG_SNAPSHOT_UNDEFINED;
3477
+ }
3478
+ };
3479
+ try {
3480
+ return visit(contentSnapshotValue(value)) && cursor === fields.length;
3481
+ } catch {
3482
+ return false;
3483
+ } finally {
3484
+ lkgEntryWork.comparedFields += Math.min(cursor, fields.length);
3485
+ }
3486
+ }
3487
+ var lkgEntryWork = {
3488
+ flattenedMessages: 0,
3489
+ flattenedChars: 0,
3490
+ hashedMessages: 0,
3491
+ comparedMessages: 0,
3492
+ comparedFields: 0,
3493
+ comparedChars: 0
3494
+ };
3495
+ function lkgEntryBytes(id, fields) {
3496
+ let bytes = id.length * 2 + 166;
3497
+ for (const field of fields) {
3498
+ bytes += 16;
3499
+ if (typeof field === "string")
3500
+ bytes += field.length * 2;
3501
+ }
3502
+ return bytes;
3503
+ }
3504
+
3505
+ class LkgEntryDigestCache {
3506
+ limits;
3507
+ sessions = new Map;
3508
+ totalBytes = 0;
3509
+ constructor(limits) {
3510
+ this.limits = limits;
3511
+ }
3512
+ digests(sessionId, messages) {
3513
+ const prior = this.sessions.get(sessionId);
3514
+ const sessionCount = this.sessions.size + (prior ? 0 : 1);
3515
+ const share = Math.min(this.limits.sessionMaxBytes, Math.floor(this.limits.totalMaxBytes / Math.min(sessionCount, this.limits.maxSessions)));
3516
+ const retained = new Map;
3517
+ const digests = [];
3518
+ let reused = 0;
3519
+ let size = 0;
3520
+ for (const message of messages) {
3521
+ const rawId = message.info?.id;
3522
+ const id = typeof rawId === "string" ? rawId : "";
3523
+ let entry = prior?.entries.get(id);
3524
+ if (entry)
3525
+ lkgEntryWork.comparedMessages += 1;
3526
+ if (entry && contentMatchesFields(message, entry.fields)) {
3527
+ reused += 1;
3528
+ } else {
3529
+ entry = undefined;
3530
+ const fields = lkgContentFields(message);
3531
+ lkgEntryWork.flattenedMessages += 1;
3532
+ if (fields) {
3533
+ for (const field of fields) {
3534
+ if (typeof field === "string")
3535
+ lkgEntryWork.flattenedChars += field.length;
3536
+ }
3537
+ lkgEntryWork.hashedMessages += 1;
3538
+ entry = {
3539
+ fields,
3540
+ digest: lkgContentDigestFromFields(fields),
3541
+ bytes: lkgEntryBytes(id, fields)
3542
+ };
3543
+ }
3544
+ }
3545
+ digests.push(entry?.digest ?? null);
3546
+ if (!entry || retained.has(id) || size + entry.bytes > share)
3547
+ continue;
3548
+ retained.set(id, entry);
3549
+ size += entry.bytes;
3550
+ }
3551
+ this.store(sessionId, retained, size, share);
3552
+ return { digests, stats: { reused, retained: retained.size, retainedBytes: size } };
3553
+ }
3554
+ store(sessionId, entries, bytes, share) {
3555
+ const prior = this.sessions.get(sessionId);
3556
+ if (prior) {
3557
+ this.totalBytes -= prior.bytes;
3558
+ this.sessions.delete(sessionId);
3559
+ }
3560
+ if (entries.size === 0)
3561
+ return;
3562
+ while (this.sessions.size >= this.limits.maxSessions) {
3563
+ const oldest = this.sessions.entries().next().value;
3564
+ if (!oldest)
3565
+ break;
3566
+ this.totalBytes -= oldest[1].bytes;
3567
+ this.sessions.delete(oldest[0]);
3568
+ }
3569
+ for (const other of this.sessions.values()) {
3570
+ if (other.bytes <= share)
3571
+ continue;
3572
+ let kept = 0;
3573
+ for (const [id, entry] of other.entries) {
3574
+ if (kept + entry.bytes > share)
3575
+ other.entries.delete(id);
3576
+ else
3577
+ kept += entry.bytes;
3578
+ }
3579
+ this.totalBytes -= other.bytes - kept;
3580
+ other.bytes = kept;
3581
+ }
3582
+ while (this.totalBytes + bytes > this.limits.totalMaxBytes) {
3583
+ const oldest = this.sessions.entries().next().value;
3584
+ if (!oldest)
3585
+ break;
3586
+ this.totalBytes -= oldest[1].bytes;
3587
+ this.sessions.delete(oldest[0]);
3588
+ }
3589
+ this.sessions.set(sessionId, { entries, bytes });
3590
+ this.totalBytes += bytes;
3591
+ }
3592
+ stats() {
3593
+ return {
3594
+ totalBytes: this.totalBytes,
3595
+ sessions: [...this.sessions].map(([sessionId, session]) => ({
3596
+ sessionId,
3597
+ bytes: session.bytes
3598
+ }))
3599
+ };
3600
+ }
3601
+ clear() {
3602
+ this.sessions.clear();
3603
+ this.totalBytes = 0;
3604
+ }
3605
+ }
3606
+ var LKG_ENTRY_CACHE_TOTAL_BYTES = 256 * 1024 * 1024;
3607
+ var LKG_ENTRY_CACHE_SESSION_BYTES = 128 * 1024 * 1024;
3608
+ var LKG_ENTRY_CACHE_MAX_SESSIONS = 16;
3609
+ var sharedLkgEntryDigests = new LkgEntryDigestCache({
3610
+ sessionMaxBytes: LKG_ENTRY_CACHE_SESSION_BYTES,
3611
+ totalMaxBytes: LKG_ENTRY_CACHE_TOTAL_BYTES,
3612
+ maxSessions: LKG_ENTRY_CACHE_MAX_SESSIONS
3613
+ });
3614
+ var lkgDigestsComputed = 0;
3615
+ function getLkgSlotHeapStats() {
3616
+ return {
3617
+ count: lkgHeapHolder.entries.size,
3618
+ totalBytes,
3619
+ sessions: [...lkgHeapHolder.entries].map(([sessionId, entry]) => ({
3620
+ sessionId,
3621
+ bytes: entry.bytes
3622
+ }))
3623
+ };
3624
+ }
3625
+
3626
+ // src/hooks/magic-context/tool-sweep-policy.ts
3627
+ var TOOL_SWEEP_SCOPED_MARKER = "@tool-sweep-scoped";
3628
+ var RESERVED_LEDGER_CONTROL_ENTRIES = [
3629
+ TOOL_SWEEP_SCOPED_MARKER,
3630
+ THINKING_BINDING_STRIP_ORDER_END_MARKER
3631
+ ];
3632
+ function isReservedLedgerControlEntry(entry) {
3633
+ return RESERVED_LEDGER_CONTROL_ENTRIES.includes(entry);
3634
+ }
3635
+ function useScopedToolSweep(db, sessionId, canAdopt) {
3636
+ if (getMergedReasoningStrippedIds(db, sessionId).has(TOOL_SWEEP_SCOPED_MARKER))
3637
+ return true;
3638
+ if (!canAdopt)
3639
+ return false;
3640
+ return addMergedReasoningStrippedIds(db, sessionId, [TOOL_SWEEP_SCOPED_MARKER]);
3641
+ }
3642
+ function servedRowKeys(messages) {
3643
+ const keys = [];
3644
+ for (const message of messages) {
3645
+ if (!Array.isArray(message?.parts) || !message.parts.some(partReachesProvider))
3646
+ continue;
3647
+ const id = message.info?.id;
3648
+ keys.push(typeof id === "string" && id.length > 0 ? id : JSON.stringify(message.info));
3649
+ }
3650
+ return keys;
3651
+ }
3652
+ function partReachesProvider(part) {
3653
+ if (!isRecord(part))
3654
+ return true;
3655
+ if (part.type !== "text")
3656
+ return true;
3657
+ return typeof part.text === "string" && stripTagPrefix(part.text).trim().length > 0;
3658
+ }
3659
+ function firstDivergence(left, right) {
3660
+ const shared = Math.min(left.length, right.length);
3661
+ for (let index = 0;index < shared; index += 1) {
3662
+ if (left[index] !== right[index])
3663
+ return index;
3664
+ }
3665
+ return left.length === right.length ? -1 : shared;
3666
+ }
3667
+ function reproducesLastServed(lastServed, candidate) {
3668
+ if (lastServed.length === 0 || candidate.length < lastServed.length)
3669
+ return false;
3670
+ return lastServed.every((key, index) => candidate[index] === key);
3671
+ }
3672
+ function classifyToolSweepCandidates(lastServed, candidates) {
3673
+ if (!lastServed) {
3674
+ return {
3675
+ condition: "lkg_absent",
3676
+ scoped: true,
3677
+ legacyDivergence: -1,
3678
+ scopedDivergence: -1,
3679
+ lastServedRows: 0
3680
+ };
3681
+ }
3682
+ const legacyKeys = servedRowKeys(candidates.legacy);
3683
+ const scopedKeys = servedRowKeys(candidates.scoped);
3684
+ const lastKeys = servedRowKeys(lastServed);
3685
+ const decision = {
3686
+ legacyDivergence: firstDivergence(lastKeys, legacyKeys),
3687
+ scopedDivergence: firstDivergence(lastKeys, scopedKeys),
3688
+ lastServedRows: lastKeys.length
3689
+ };
3690
+ if (reproducesLastServed(lastKeys, legacyKeys)) {
3691
+ return { condition: "matched_old", scoped: false, ...decision };
3692
+ }
3693
+ if (reproducesLastServed(lastKeys, scopedKeys)) {
3694
+ return { condition: "matched_scoped", scoped: true, ...decision };
3695
+ }
3696
+ return { condition: "matched_neither", scoped: false, ...decision };
3697
+ }
3698
+ function parseLastServedArray(jsonPrefix) {
3699
+ if (!jsonPrefix)
3700
+ return null;
3701
+ try {
3702
+ const parsed = JSON.parse(jsonPrefix);
3703
+ return Array.isArray(parsed) ? parsed : null;
3704
+ } catch {
3705
+ return null;
3706
+ }
3707
+ }
3708
+ function createPreAdoptionToolSweepResolver(db, sessionId) {
3709
+ const snapshot = getSlot(sessionId)?.jsonPrefix;
3710
+ return (candidates) => {
3711
+ const decision = classifyToolSweepCandidates(parseLastServedArray(snapshot), candidates);
3712
+ sessionLog2(sessionId, `tool_sweep_lkg_mismatch session=${sessionId} condition=${decision.condition} ` + `last_served_rows=${decision.lastServedRows} legacy_divergence=${decision.legacyDivergence} ` + `scoped_divergence=${decision.scopedDivergence}`);
3713
+ if (!decision.scoped)
3714
+ return false;
3715
+ addMergedReasoningStrippedIds(db, sessionId, [TOOL_SWEEP_SCOPED_MARKER]);
3716
+ return true;
3717
+ };
3718
+ }
3719
+
3720
+ // src/features/magic-context/pi-content-decisions.ts
3721
+ var PREFIX2 = "pi-content-replay-v1:";
3722
+ function encodePiContentDecision(kind, messageId) {
3723
+ return PREFIX2 + JSON.stringify([kind, messageId]);
3724
+ }
3725
+ function decodePiContentDecision(value) {
3726
+ if (!value.startsWith(PREFIX2))
3727
+ return null;
3728
+ try {
3729
+ const pair = JSON.parse(value.slice(PREFIX2.length));
3730
+ if (Array.isArray(pair) && pair.length === 2 && (pair[0] === "reminder-strip" || pair[0] === "seam-temporal-strip" || pair[0] === "tag-identity-repair-once" || pair[0] === "tag-identity-repair-pending" || pair[0] === "tag-identity-rebuild-failed" || pair[0] === "tag-identity-recurring") && typeof pair[1] === "string" && pair[1].length > 0)
3731
+ return [pair[0], pair[1]];
3732
+ } catch {}
3733
+ return null;
3734
+ }
3735
+
3736
+ // src/features/magic-context/storage-native-replay.ts
3737
+ var NATIVE_TOOL_INPUTS = "native tool inputs";
3738
+ var NATIVE_REASONING_IDS = "native reasoning ids";
3739
+ var nativeWriteBarriers = new WeakMap;
3740
+ function invalidPersistedReplayState(lane, sessionId) {
3741
+ return new Error(`invalid persisted ${lane} state for session ${sessionId}`);
3742
+ }
3743
+ function assertNonEmptyId(value, lane, sessionId) {
3744
+ if (typeof value !== "string" || value.length === 0) {
3745
+ throw invalidPersistedReplayState(lane, sessionId);
3746
+ }
3747
+ }
3748
+ function assertSerializedToolInput(value, sessionId) {
3749
+ if (typeof value !== "string") {
3750
+ throw invalidPersistedReplayState(NATIVE_TOOL_INPUTS, sessionId);
3751
+ }
3752
+ try {
3753
+ if (!isRecord(JSON.parse(value))) {
3754
+ throw new SyntaxError("native tool input must be an object");
3755
+ }
3756
+ } catch {
3757
+ throw invalidPersistedReplayState(NATIVE_TOOL_INPUTS, sessionId);
3758
+ }
3759
+ }
3760
+ function parseNativeToolInputs(value, sessionId) {
3761
+ if (!isRecord(value)) {
3762
+ throw invalidPersistedReplayState(NATIVE_TOOL_INPUTS, sessionId);
3763
+ }
3764
+ const inputs = new Map;
3765
+ for (const [id, input] of Object.entries(value)) {
3766
+ assertNonEmptyId(id, NATIVE_TOOL_INPUTS, sessionId);
3767
+ assertSerializedToolInput(input, sessionId);
3768
+ inputs.set(id, input);
3769
+ }
3770
+ return inputs;
3771
+ }
3772
+ function parseNativeReasoningIds(value, sessionId) {
3773
+ if (!Array.isArray(value)) {
3774
+ throw invalidPersistedReplayState(NATIVE_REASONING_IDS, sessionId);
3775
+ }
3776
+ const ids = new Set;
3777
+ for (const id of value) {
3778
+ assertNonEmptyId(id, NATIVE_REASONING_IDS, sessionId);
3779
+ ids.add(id);
3780
+ }
3781
+ return ids;
3782
+ }
3783
+ function parseNativeReplayState(doc, sessionId) {
3784
+ const native = doc.piNative;
3785
+ if (native === undefined) {
3786
+ return { toolInputs: new Map, reasoningIds: new Set };
3787
+ }
3788
+ if (!isRecord(native)) {
3789
+ throw invalidPersistedReplayState("native replay", sessionId);
3790
+ }
3791
+ return {
3792
+ toolInputs: parseNativeToolInputs(native.toolInputs, sessionId),
3793
+ reasoningIds: parseNativeReasoningIds(native.reasoningIds, sessionId)
3794
+ };
3795
+ }
3796
+ function getNativeReplayState(db, sessionId) {
3797
+ return parseNativeReplayState(readReplayEnvelope(db, sessionId), sessionId);
3798
+ }
3799
+
3800
+ // src/features/magic-context/storage-clone.ts
3801
+ function clonePiContentDecisions(raw, filter) {
3802
+ if (!raw)
3803
+ return null;
3804
+ let entries;
3805
+ try {
3806
+ entries = JSON.parse(raw);
3807
+ } catch {
3808
+ return null;
3809
+ }
3810
+ if (!Array.isArray(entries))
3811
+ return null;
3812
+ const copied = [];
3813
+ for (const entry of entries) {
3814
+ if (typeof entry !== "string")
3815
+ continue;
3816
+ if (isReservedLedgerControlEntry(entry)) {
3817
+ copied.push(entry);
3818
+ continue;
3819
+ }
3820
+ const decision = decodePiContentDecision(entry);
3821
+ if (decision) {
3822
+ const [kind, id] = decision;
3823
+ const root = kind === "reminder-strip" ? id.replace(/:p\d+$/, "") : id;
3824
+ if (!filter.includeMessageId(root))
3825
+ continue;
3826
+ copied.push(encodePiContentDecision(kind, `${mapMessageId(filter, root)}${id.slice(root.length)}`));
3827
+ continue;
3828
+ }
3829
+ const mergedParts = decodeMergedReasoningParts(entry);
3830
+ if (mergedParts) {
3831
+ const [messageId, parts] = mergedParts;
3832
+ if (!filter.includeMessageId(messageId))
3833
+ continue;
3834
+ const mappedParts = parts.map((part) => typeof part === "string" ? mapMessageId(filter, part) ?? part : part);
3835
+ copied.push(`${MERGED_REASONING_PARTS_PREFIX}${JSON.stringify([
3836
+ mapMessageId(filter, messageId) ?? messageId,
3837
+ mappedParts
3838
+ ])}`);
3839
+ continue;
3840
+ }
3841
+ const thinkingPrefix = [
3842
+ THINKING_BINDING_RECOVERY_FROZEN_PREFIX,
3843
+ COMPACTION_OFF_THINKING_FROZEN_PREFIX
3844
+ ].find((prefix) => entry.startsWith(prefix));
3845
+ if (thinkingPrefix) {
3846
+ const messageId = entry.slice(thinkingPrefix.length);
3847
+ if (messageId.length === 0 || !filter.includeMessageId(messageId))
3848
+ continue;
3849
+ copied.push(`${thinkingPrefix}${mapMessageId(filter, messageId) ?? messageId}`);
3850
+ continue;
3851
+ }
3852
+ if (entry.startsWith(MERGED_REASONING_PARTS_PREFIX) || entry.startsWith("pi-content-replay-"))
3853
+ continue;
3854
+ if (entry.length === 0 || !filter.includeMessageId(entry))
3855
+ continue;
3856
+ copied.push(mapMessageId(filter, entry) ?? entry);
3857
+ }
3858
+ return copied.length ? JSON.stringify(copied) : null;
3859
+ }
3860
+ function runImmediate(db, body) {
3861
+ db.exec("BEGIN IMMEDIATE");
3862
+ const transactionStartedAt = performance.now();
3863
+ let committed = false;
3864
+ try {
3865
+ const result = body();
3866
+ db.exec("COMMIT");
3867
+ committed = true;
3868
+ logSlowWriteTransaction("storage_clone_copy", transactionStartedAt);
3869
+ return result;
3870
+ } finally {
3871
+ if (!committed) {
3872
+ try {
3873
+ db.exec("ROLLBACK");
3874
+ } catch {}
3875
+ }
3876
+ }
3877
+ }
3878
+ function countRows(db, table, sessionId) {
3879
+ const row = db.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE session_id = ?`).get(sessionId);
3880
+ return typeof row?.count === "number" ? row.count : 0;
3881
+ }
3882
+ function mapMessageId(filter, messageId) {
3883
+ if (messageId === null)
3884
+ return null;
3885
+ return filter.mapMessageId?.(messageId) ?? messageId;
3886
+ }
3887
+ function tableExists(db, table) {
3888
+ const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);
3889
+ return row !== null && row !== undefined;
3890
+ }
3891
+ function insertDynamicRow(db, table, row) {
3892
+ const names = Object.keys(row);
3893
+ const quoted = names.map((name) => `"${name.replaceAll('"', '""')}"`);
3894
+ const placeholders = names.map(() => "?").join(", ");
3895
+ db.prepare(`INSERT INTO "${table.replaceAll('"', '""')}" (${quoted.join(", ")}) VALUES (${placeholders})`).run(...names.map((name) => row[name]));
3896
+ }
3897
+ function anchoredMessageId(blockId) {
3898
+ const separator = blockId.lastIndexOf("#");
3899
+ return separator > 0 ? blockId.slice(0, separator) : blockId;
3900
+ }
3901
+ function copyPiSessionNotesAndFacts(db, sourceSessionId, destinationSessionId, filter) {
3902
+ let notesCopied = 0;
3903
+ if (tableExists(db, "notes")) {
3904
+ const sourceNotes = db.prepare("SELECT * FROM notes WHERE session_id = ? AND type = 'session' ORDER BY id ASC").all(sourceSessionId);
3905
+ for (const source of sourceNotes) {
3906
+ const row = {
3907
+ ...source,
3908
+ session_id: destinationSessionId
3909
+ };
3910
+ delete row.id;
3911
+ const blockId = typeof source.anchor_block_id === "string" ? source.anchor_block_id : "";
3912
+ if (blockId) {
3913
+ const sourceMessageId = anchoredMessageId(blockId);
3914
+ if (!filter.includeMessageId(sourceMessageId))
3915
+ continue;
3916
+ const mappedMessageId = mapMessageId(filter, sourceMessageId) ?? sourceMessageId;
3917
+ row.anchor_block_id = `${mappedMessageId}${blockId.slice(sourceMessageId.length)}`;
3918
+ const mappedOrdinal = filter.resolveBoundaryOrdinal(sourceMessageId);
3919
+ if (mappedOrdinal === undefined)
3920
+ continue;
3921
+ if ("anchor_ordinal" in row)
3922
+ row.anchor_ordinal = mappedOrdinal;
3923
+ } else if (typeof source.anchor_ordinal === "number" && filter.mapOrdinal) {
3924
+ const mappedOrdinal = filter.mapOrdinal(source.anchor_ordinal);
3925
+ if (mappedOrdinal === undefined)
3926
+ continue;
3927
+ row.anchor_ordinal = mappedOrdinal;
3928
+ }
3929
+ insertDynamicRow(db, "notes", row);
3930
+ notesCopied += 1;
3931
+ }
3932
+ }
3933
+ let factsCopied = 0;
3934
+ if (tableExists(db, "session_facts")) {
3935
+ const sourceFacts = db.prepare("SELECT * FROM session_facts WHERE session_id = ? ORDER BY id ASC").all(sourceSessionId);
3936
+ for (const source of sourceFacts) {
3937
+ const row = {
3938
+ ...source,
3939
+ session_id: destinationSessionId
3940
+ };
3941
+ delete row.id;
3942
+ insertDynamicRow(db, "session_facts", row);
3943
+ factsCopied += 1;
3944
+ }
3945
+ }
3946
+ return { notesCopied, factsCopied };
3947
+ }
3948
+ function filterIdBlob(raw, filter) {
3949
+ if (!raw)
3950
+ return "";
3951
+ try {
3952
+ const value = JSON.parse(raw);
3953
+ if (!Array.isArray(value))
3954
+ return "";
3955
+ const filtered = value.filter((id) => typeof id === "string" && filter.includeMessageId(id)).map((id) => mapMessageId(filter, id));
3956
+ return filtered.length > 0 ? JSON.stringify(filtered) : "";
3957
+ } catch {
3958
+ return "";
3959
+ }
3960
+ }
3961
+ function filterProcessedImageBlob(raw, filter) {
3962
+ return serializeProcessedImageMarkers(new Map([...parseProcessedImageMarkers(raw)].filter(([id]) => filter.includeMessageId(id)).map(([id, marker]) => [mapMessageId(filter, id) ?? id, marker])));
3963
+ }
3964
+ function filterStrippedPlaceholderBlob(raw, filter) {
3965
+ const state = parseStrippedPlaceholderState(raw);
3966
+ const keep = (ids) => ids.filter((id) => filter.includeMessageId(id)).map((id) => mapMessageId(filter, id) ?? id);
3967
+ const ids = keep(state.ids);
3968
+ const copied = new Set(ids);
3969
+ return serializeStrippedPlaceholderState({
3970
+ ids,
3971
+ hiddenSeamIds: keep(state.hiddenSeamIds).filter((id) => copied.has(id))
3972
+ });
3973
+ }
3974
+ function filterNativeToolInputs(inputs, copiedToolCallIds, filter) {
3975
+ const filtered = new Map;
3976
+ for (const [sourceId, serializedInput] of inputs) {
3977
+ if (!copiedToolCallIds.has(sourceId))
3978
+ continue;
3979
+ const destinationId = mapMessageId(filter, sourceId);
3980
+ if (destinationId === null)
3981
+ continue;
3982
+ const existing = filtered.get(destinationId);
3983
+ if (existing !== undefined && existing !== serializedInput) {
3984
+ throw new Error(`native tool input clone collision for ${destinationId}`);
3985
+ }
3986
+ filtered.set(destinationId, serializedInput);
3987
+ }
3988
+ return Object.fromEntries(filtered);
3989
+ }
3990
+ function filterNativeReasoningIds(ids, filter) {
3991
+ const filtered = new Set;
3992
+ for (const sourceId of ids) {
3993
+ if (!filter.includeMessageId(sourceId))
3994
+ continue;
3995
+ const destinationId = mapMessageId(filter, sourceId);
3996
+ if (destinationId !== null)
3997
+ filtered.add(destinationId);
3998
+ }
3999
+ return [...filtered];
4000
+ }
4001
+ function cloneReplayDocument(db, sourceSessionId, copiedToolCallIds, filter) {
4002
+ const document = readReplayDocument(db, sourceSessionId);
4003
+ const trailingBlank = new Map;
4004
+ for (const [sourceId, decision] of Object.entries(document.trailingBlank)) {
4005
+ if (!filter.includeMessageId(sourceId))
4006
+ continue;
4007
+ const destinationId = mapMessageId(filter, sourceId);
4008
+ if (destinationId === null)
4009
+ continue;
4010
+ const existing = trailingBlank.get(destinationId);
4011
+ if (existing !== undefined && existing !== decision) {
4012
+ throw new Error(`trailing blank clone collision for ${destinationId}`);
4013
+ }
4014
+ trailingBlank.set(destinationId, decision);
4015
+ }
4016
+ document.trailingBlank = Object.fromEntries(trailingBlank);
4017
+ if (document.version === 1 || document.piNative === undefined)
4018
+ return document;
4019
+ const nativeReplay = getNativeReplayState(db, sourceSessionId);
4020
+ return {
4021
+ ...document,
4022
+ piNative: {
4023
+ ...document.piNative,
4024
+ toolInputs: filterNativeToolInputs(nativeReplay.toolInputs, copiedToolCallIds, filter),
4025
+ reasoningIds: filterNativeReasoningIds(nativeReplay.reasoningIds, filter)
4026
+ }
4027
+ };
4028
+ }
4029
+ var TAG_ID_QUERY_CHUNK_SIZE = 900;
4030
+ function selectRowsByTagIds(db, sqlPrefix, sessionId, tagIds) {
4031
+ const rows = [];
4032
+ for (let start = 0;start < tagIds.length; start += TAG_ID_QUERY_CHUNK_SIZE) {
4033
+ const chunk = tagIds.slice(start, start + TAG_ID_QUERY_CHUNK_SIZE);
4034
+ const placeholders = chunk.map(() => "?").join(", ");
4035
+ rows.push(...db.prepare(`${sqlPrefix} (${placeholders})`).all(sessionId, ...chunk));
4036
+ }
4037
+ return rows;
4038
+ }
4039
+ function clampWatermark(value, maxCopiedTag) {
4040
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
4041
+ return 0;
4042
+ return Math.min(Math.floor(value), maxCopiedTag);
4043
+ }
4044
+ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, filter) {
4045
+ let clearedMarker = null;
4046
+ const result = runImmediate(db, () => {
4047
+ const hasTemporalDecisions = tableExists(db, "temporal_decisions");
4048
+ if (filter.requireEmptyDestinationMeta === true && countRows(db, "session_meta", destinationSessionId) > 0 || countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0 || hasTemporalDecisions && countRows(db, "temporal_decisions", destinationSessionId) > 0 || filter.copySessionNotesAndFacts === true && (tableExists(db, "notes") && countRows(db, "notes", destinationSessionId) > 0 || tableExists(db, "session_facts") && countRows(db, "session_facts", destinationSessionId) > 0)) {
4049
+ return {
4050
+ kind: "destination-not-empty",
4051
+ compartmentsCopied: 0,
4052
+ tagsCopied: 0,
4053
+ pendingOpsCopied: 0,
4054
+ notesCopied: 0,
4055
+ factsCopied: 0,
4056
+ pendingMarkerMigrated: false
4057
+ };
4058
+ }
4059
+ const compartmentColumns = db.prepare("PRAGMA table_info(compartments)").all();
4060
+ const hasBlockIndices = ["start_block_index", "end_block_index"].every((name) => compartmentColumns.some((column) => column.name === name));
4061
+ const blockProjection = hasBlockIndices ? "start_block_index, end_block_index" : "NULL AS start_block_index, NULL AS end_block_index";
4062
+ const sourceCompartments = db.prepare(`SELECT sequence, start_message, end_message, start_message_id, end_message_id,
4063
+ title, content, p1, p2, p3, p4, importance, episode_type, legacy,
4064
+ created_at, harness, ${blockProjection}
4065
+ FROM compartments WHERE session_id = ? ORDER BY sequence ASC`).all(sourceSessionId);
4066
+ const insertCompartment = db.prepare(`INSERT INTO compartments
4067
+ (session_id, sequence, start_message, end_message, start_message_id,
4068
+ end_message_id, title, content, p1, p2, p3, p4, importance,
4069
+ episode_type, legacy, created_at, harness${hasBlockIndices ? ", start_block_index, end_block_index" : ""})
4070
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?${hasBlockIndices ? ", ?, ?" : ""})`);
4071
+ const copiedCompartments = [];
4072
+ for (const row of sourceCompartments) {
4073
+ const startMessage = filter.resolveBoundaryOrdinal(row.start_message_id);
4074
+ const endMessage = filter.resolveBoundaryOrdinal(row.end_message_id);
4075
+ if (startMessage === undefined || endMessage === undefined)
4076
+ continue;
4077
+ insertCompartment.run(destinationSessionId, row.sequence, startMessage, endMessage, mapMessageId(filter, row.start_message_id), mapMessageId(filter, row.end_message_id), row.title, row.content, row.p1, row.p2, row.p3, row.p4, row.importance, row.episode_type, row.legacy, row.created_at, row.harness, ...hasBlockIndices ? [row.start_block_index, row.end_block_index] : []);
4078
+ copiedCompartments.push({
4079
+ sequence: row.sequence,
4080
+ startMessage,
4081
+ endMessage,
4082
+ startMessageId: mapMessageId(filter, row.start_message_id) ?? row.start_message_id,
4083
+ endMessageId: mapMessageId(filter, row.end_message_id) ?? row.end_message_id
4084
+ });
4085
+ }
4086
+ const sourceTags = db.prepare(`SELECT id, message_id, type, status, byte_size, tag_number, harness,
4087
+ entry_fingerprint, token_count, input_token_count,
4088
+ reasoning_token_count, reasoning_byte_size, drop_mode, tool_name,
4089
+ input_byte_size, caveman_depth, tool_owner_message_id
4090
+ FROM tags WHERE session_id = ? ORDER BY tag_number ASC`).all(sourceSessionId);
4091
+ const insertTag = db.prepare(`INSERT INTO tags
4092
+ (session_id, message_id, type, status, byte_size, tag_number, harness,
4093
+ entry_fingerprint, token_count, input_token_count, reasoning_token_count,
4094
+ reasoning_byte_size, drop_mode, tool_name, input_byte_size,
4095
+ caveman_depth, tool_owner_message_id)
4096
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
4097
+ const copiedTagNumbers = [];
4098
+ const copiedTagIds = new Map;
4099
+ const copiedToolCallIds = new Set;
4100
+ for (const row of sourceTags) {
4101
+ if (!filter.includeTag({
4102
+ messageId: row.message_id,
4103
+ type: row.type,
4104
+ tagNumber: row.tag_number,
4105
+ toolOwnerMessageId: row.tool_owner_message_id
4106
+ })) {
4107
+ continue;
4108
+ }
4109
+ const insertResult = insertTag.run(destinationSessionId, mapMessageId(filter, row.message_id), row.type, row.status, row.byte_size, row.tag_number, row.harness, row.entry_fingerprint, row.token_count, row.input_token_count, row.reasoning_token_count, row.reasoning_byte_size, row.drop_mode, row.tool_name, row.input_byte_size, row.caveman_depth, mapMessageId(filter, row.tool_owner_message_id));
4110
+ const insertedTagId = Number(insertResult.lastInsertRowid);
4111
+ if (!Number.isSafeInteger(insertedTagId) || insertedTagId <= 0) {
4112
+ throw new Error(`failed to obtain destination tag id for tag ${row.tag_number}`);
4113
+ }
4114
+ const sourceTagId = filter.mapTagId ? row.id : row.tag_number;
4115
+ const destinationTagId = filter.mapTagId ? filter.mapTagId(sourceTagId, insertedTagId) : sourceTagId;
4116
+ copiedTagIds.set(sourceTagId, destinationTagId);
4117
+ copiedTagNumbers.push(row.tag_number);
4118
+ if (row.type === "tool")
4119
+ copiedToolCallIds.add(row.message_id);
4120
+ }
4121
+ if (copiedTagNumbers.length > 0) {
4122
+ const sourceContents = selectRowsByTagIds(db, `SELECT tag_id, content, created_at, harness
4123
+ FROM source_contents
4124
+ WHERE session_id = ? AND tag_id IN`, sourceSessionId, [...copiedTagIds.keys()]);
4125
+ const insertSourceContent = db.prepare("INSERT INTO source_contents (tag_id, session_id, content, created_at, harness) VALUES (?, ?, ?, ?, ?)");
4126
+ for (const row of sourceContents) {
4127
+ const destinationTagId = copiedTagIds.get(row.tag_id);
4128
+ if (destinationTagId === undefined)
4129
+ continue;
4130
+ insertSourceContent.run(destinationTagId, destinationSessionId, row.content, row.created_at, row.harness);
4131
+ }
4132
+ const pendingOps = selectRowsByTagIds(db, `SELECT id, tag_id, operation, queued_at, harness
4133
+ FROM pending_ops
4134
+ WHERE session_id = ? AND tag_id IN`, sourceSessionId, copiedTagNumbers).sort((a, b) => a.id - b.id);
4135
+ const insertPendingOp = db.prepare("INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness) VALUES (?, ?, ?, ?, ?)");
4136
+ for (const row of pendingOps) {
4137
+ insertPendingOp.run(destinationSessionId, row.tag_id, row.operation, row.queued_at, row.harness);
4138
+ }
4139
+ }
4140
+ if (hasTemporalDecisions) {
4141
+ const temporalRows = db.prepare("SELECT message_id,marker FROM temporal_decisions WHERE session_id=?").all(sourceSessionId);
4142
+ const insertTemporal = db.prepare("INSERT INTO temporal_decisions(session_id,message_id,marker) VALUES (?,?,?)");
4143
+ for (const row of temporalRows) {
4144
+ if (filter.includeMessageId(row.message_id))
4145
+ insertTemporal.run(destinationSessionId, mapMessageId(filter, row.message_id), row.marker);
4146
+ }
4147
+ }
4148
+ const inherited = filter.copySessionNotesAndFacts === true ? copyPiSessionNotesAndFacts(db, sourceSessionId, destinationSessionId, filter) : { notesCopied: 0, factsCopied: 0 };
4149
+ const meta = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
4150
+ pi_stable_id_scheme, stripped_placeholder_ids,
4151
+ stale_reduce_stripped_ids, processed_image_stripped_ids, merged_reasoning_stripped_ids,
4152
+ pending_pi_compaction_marker_state, last_todo_state,
4153
+ todo_synthetic_call_id, todo_synthetic_anchor_message_id,
4154
+ todo_synthetic_state_json
4155
+ FROM session_meta WHERE session_id = ?`).get(sourceSessionId);
4156
+ const maxCopiedTag = copiedTagNumbers.reduce((max, value) => Math.max(max, value), 0);
4157
+ const pendingMarker = filter.selectPendingPiMarker(meta?.pending_pi_compaction_marker_state ?? null, copiedCompartments);
4158
+ if (pendingMarker === null)
4159
+ clearedMarker = getPendingPiCompactionMarkerState(db, destinationSessionId);
4160
+ const todoAnchor = meta?.todo_synthetic_anchor_message_id ?? "";
4161
+ const migrateTodo = todoAnchor.length > 0 && filter.includeMessageId(todoAnchor);
4162
+ db.prepare(`INSERT INTO session_meta
4163
+ (session_id, harness, counter, cleared_reasoning_through_tag,
4164
+ tool_reclaim_watermark, pi_stable_id_scheme, stripped_placeholder_ids,
4165
+ stale_reduce_stripped_ids, processed_image_stripped_ids, merged_reasoning_stripped_ids,
4166
+ pending_pi_compaction_marker_state, last_todo_state,
4167
+ todo_synthetic_call_id, todo_synthetic_anchor_message_id,
4168
+ todo_synthetic_state_json)
4169
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
4170
+ ON CONFLICT(session_id) DO UPDATE SET
4171
+ harness = excluded.harness,
4172
+ counter = excluded.counter,
4173
+ cleared_reasoning_through_tag = excluded.cleared_reasoning_through_tag,
4174
+ tool_reclaim_watermark = excluded.tool_reclaim_watermark,
4175
+ pi_stable_id_scheme = excluded.pi_stable_id_scheme,
4176
+ stripped_placeholder_ids = excluded.stripped_placeholder_ids,
4177
+ stale_reduce_stripped_ids = excluded.stale_reduce_stripped_ids,
4178
+ processed_image_stripped_ids = excluded.processed_image_stripped_ids,
4179
+ merged_reasoning_stripped_ids = excluded.merged_reasoning_stripped_ids,
4180
+ pending_pi_compaction_marker_state = excluded.pending_pi_compaction_marker_state,
4181
+ last_todo_state = excluded.last_todo_state,
4182
+ todo_synthetic_call_id = excluded.todo_synthetic_call_id,
4183
+ todo_synthetic_anchor_message_id = excluded.todo_synthetic_anchor_message_id,
4184
+ todo_synthetic_state_json = excluded.todo_synthetic_state_json,
4185
+ cached_m0_bytes = NULL,
4186
+ cached_m1_bytes = NULL`).run(destinationSessionId, getHarness2(), maxCopiedTag, clampWatermark(meta?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta?.pi_stable_id_scheme === "number" && Number.isFinite(meta.pi_stable_id_scheme) ? meta.pi_stable_id_scheme : null, filterStrippedPlaceholderBlob(meta?.stripped_placeholder_ids ?? null, filter), filterIdBlob(meta?.stale_reduce_stripped_ids ?? null, filter), filterProcessedImageBlob(meta?.processed_image_stripped_ids ?? null, filter), clonePiContentDecisions(meta?.merged_reasoning_stripped_ids ?? null, filter), pendingMarker, migrateTodo ? meta?.last_todo_state ?? "" : "", migrateTodo ? meta?.todo_synthetic_call_id ?? "" : "", migrateTodo ? mapMessageId(filter, todoAnchor) ?? "" : "", migrateTodo ? meta?.todo_synthetic_state_json ?? "" : "");
4187
+ const metaColumnRows = db.prepare("PRAGMA table_info(session_meta)").all();
4188
+ const metaColumns = new Set(metaColumnRows.map((column) => column.name));
4189
+ if (metaColumns.has("trailing_blank_decisions")) {
4190
+ const replayDocument = cloneReplayDocument(db, sourceSessionId, copiedToolCallIds, filter);
4191
+ writeReplayDocument(db, destinationSessionId, replayDocument);
4192
+ }
4193
+ const pendingOpsRow = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?").get(destinationSessionId);
4194
+ return {
4195
+ kind: "migrated",
4196
+ compartmentsCopied: copiedCompartments.length,
4197
+ tagsCopied: copiedTagNumbers.length,
4198
+ pendingOpsCopied: typeof pendingOpsRow?.count === "number" ? pendingOpsRow.count : 0,
4199
+ notesCopied: inherited.notesCopied,
4200
+ factsCopied: inherited.factsCopied,
4201
+ pendingMarkerMigrated: pendingMarker !== null
4202
+ };
4203
+ });
4204
+ if (clearedMarker)
4205
+ logPiCompactionMarkerClear(destinationSessionId, clearedMarker, "clone-replaced");
4206
+ return result;
4207
+ }
4208
+ // src/features/magic-context/historian-failure-reason.ts
4209
+ var MAX_HISTORIAN_FAILURE_REASON_LENGTH = 512;
4210
+ var KNOWN_PROVIDER_ERROR_TYPES = [
4211
+ "authentication_error",
4212
+ "context_length_exceeded",
4213
+ "insufficient_quota",
4214
+ "invalid_api_key",
4215
+ "invalid_request_error",
4216
+ "model_not_found",
4217
+ "overloaded_error",
4218
+ "permission_error",
4219
+ "rate_limit_error",
4220
+ "server_error",
4221
+ "content_filter"
4222
+ ];
4223
+ function capHistorianFailureReason(reason, fallback = "provider_error") {
4224
+ const value = typeof reason === "string" && reason.trim() ? reason : fallback;
4225
+ return value.slice(0, MAX_HISTORIAN_FAILURE_REASON_LENGTH);
4226
+ }
4227
+ function externalHistorianFailureReason(error, prefix = "provider_error") {
4228
+ const record = typeof error === "object" && error !== null ? error : undefined;
4229
+ const message = typeof error === "string" ? error : typeof record?.message === "string" ? record.message : String(error ?? "");
4230
+ const normalized = message.toLowerCase();
4231
+ const dataRecord = typeof record?.data === "object" && record.data !== null ? record.data : undefined;
4232
+ const statusValue = record?.statusCode ?? record?.status ?? record?.status_code ?? dataRecord?.statusCode ?? dataRecord?.status ?? dataRecord?.status_code;
4233
+ const structuredStatus = typeof statusValue === "number" || typeof statusValue === "string" ? /^[1-5]\d{2}$/.exec(String(statusValue))?.[0] : undefined;
4234
+ const status = structuredStatus ?? /(?:\bhttp(?:\s+status)?|\bstatus(?:\s+code)?|\bapi\s+error|\berror)\s*[(:= ]+([1-5]\d{2})\b/i.exec(message)?.[1];
4235
+ const structuredTypes = [record?.type, dataRecord?.type].filter((value) => typeof value === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,39}$/.test(value));
4236
+ const structuredType = [record?.type, record?.code, dataRecord?.type, dataRecord?.code].filter((value) => typeof value === "string").join(" ").toLowerCase();
4237
+ const providerType = KNOWN_PROVIDER_ERROR_TYPES.find((value) => normalized.includes(value) || structuredType.includes(value)) ?? (structuredTypes[0]?.toLowerCase() || (/model not found|unknown model|model does not exist/.test(normalized) ? "model_not_found" : undefined));
4238
+ const structuredCode = record?.code ?? dataRecord?.code;
4239
+ const safeCode = typeof structuredCode === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,39}$/.test(structuredCode) ? structuredCode : /\b(?:code|error code)\s*[:= ]\s*([A-Za-z][A-Za-z0-9_.-]{0,39})\b/i.exec(message)?.[1];
4240
+ const nameField = typeof record?.name === "string" ? record.name : undefined;
4241
+ const className = nameField && nameField !== "Error" ? nameField : error?.constructor?.name;
4242
+ const safeClass = className && className !== "Error" && /^[A-Za-z][A-Za-z0-9]{0,39}(?:Error|Exception)$/.test(className) ? `class_${className}` : undefined;
4243
+ const detail = [
4244
+ status ? `http_${status}` : undefined,
4245
+ providerType,
4246
+ safeCode ? `code_${safeCode}` : undefined,
4247
+ safeClass
4248
+ ].filter((part) => part !== undefined);
4249
+ return capHistorianFailureReason(`${prefix}${detail.length > 0 ? `:${detail.join(":")}` : ""}`);
4250
+ }
4251
+
4252
+ // src/features/magic-context/storage-historian-runs.ts
4253
+ function recordHistorianRun(db, input) {
4254
+ try {
4255
+ const failureReason = input.failureReason == null ? input.status === "failed" ? "provider_error" : null : capHistorianFailureReason(input.failureReason, input.status === "failed" ? "provider_error" : "");
4256
+ const result = db.prepare(`INSERT INTO historian_runs (
4257
+ session_id, harness, subagent_invocation_id, run_kind, status,
4258
+ failure_reason, chunk_start_ordinal, chunk_end_ordinal, unprocessed_from,
4259
+ compartments_produced, compartment_id_min, compartment_id_max,
4260
+ facts_emitted, facts_by_category_json, events_emitted,
4261
+ importance_min, importance_max, importance_avg,
4262
+ discarded_last, legacy, created_at
4263
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.sessionId, input.harness, input.subagentInvocationId ?? null, input.runKind, input.status, failureReason, input.chunkStartOrdinal ?? null, input.chunkEndOrdinal ?? null, input.unprocessedFrom ?? null, input.compartmentsProduced ?? 0, input.compartmentIdMin ?? null, input.compartmentIdMax ?? null, input.factsEmitted ?? 0, JSON.stringify({
4264
+ ...input.factsByCategory ?? {},
4265
+ facts_promoted: input.factsPromoted ?? 0,
4266
+ events_published: input.eventsPublished ?? 0
4267
+ }), input.eventsEmitted ?? 0, input.importanceMin ?? null, input.importanceMax ?? null, input.importanceAvg ?? null, input.discardedLast ? 1 : 0, input.legacy ? 1 : 0, Date.now());
4268
+ return Number(result.lastInsertRowid);
4269
+ } catch {
4270
+ return null;
4271
+ }
4272
+ }
4273
+ function summarizeImportance(values) {
4274
+ const nums = values.filter((v) => typeof v === "number" && Number.isFinite(v));
4275
+ if (nums.length === 0)
4276
+ return { min: null, max: null, avg: null };
4277
+ let min = nums[0];
4278
+ let max = nums[0];
4279
+ let sum = 0;
4280
+ for (const v of nums) {
4281
+ if (v < min)
4282
+ min = v;
4283
+ if (v > max)
4284
+ max = v;
4285
+ sum += v;
4286
+ }
4287
+ return { min, max, avg: sum / nums.length };
4288
+ }
4289
+ function tallyFactsByCategory(facts) {
4290
+ const out = {};
4291
+ for (const f of facts) {
4292
+ const cat = (f.category ?? "UNKNOWN").trim() || "UNKNOWN";
4293
+ out[cat] = (out[cat] ?? 0) + 1;
4294
+ }
4295
+ return out;
4296
+ }
4297
+ // src/features/magic-context/storage-memory-mutation-log.ts
4298
+ var MEMORY_MUTATION_TYPES = new Set(["archive", "delete", "update", "superseded"]);
4299
+ var MEMORY_VISIBILITY_MUTATION_CATEGORY = "__mc_visibility__";
4300
+ var MAX_MEMORY_REPLACEMENT_DEPTH = 8;
4301
+ var TERMINAL_MUTATION_TYPES = new Set(["archive", "delete", "superseded"]);
4302
+ function isTerminalMutation(row) {
4303
+ return TERMINAL_MUTATION_TYPES.has(row.mutationType);
4304
+ }
4305
+ function assertMemoryMutationType(mutationType) {
4306
+ if (!MEMORY_MUTATION_TYPES.has(mutationType)) {
4307
+ throw new Error(`Invalid memory mutation type: ${mutationType}`);
4308
+ }
4309
+ }
4310
+ function toMemoryMutation(row) {
4311
+ return {
4312
+ id: row.id,
4313
+ projectPath: row.project_path,
4314
+ mutationType: row.mutation_type,
4315
+ targetMemoryId: row.target_memory_id,
4316
+ supersededById: row.superseded_by_id,
4317
+ category: row.category,
4318
+ newContent: row.new_content,
4319
+ visibilityChanged: row.category === MEMORY_VISIBILITY_MUTATION_CATEGORY,
4320
+ queuedAt: row.queued_at
4321
+ };
4322
+ }
4323
+ function queueMemoryMutation(db, input) {
4324
+ assertMemoryMutationType(input.mutationType);
4325
+ const result = db.prepare(`INSERT INTO memory_mutation_log
4326
+ (project_path, mutation_type, target_memory_id, superseded_by_id, category, new_content, queued_at)
4327
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(input.projectPath, input.mutationType, input.targetMemoryId, input.supersededById ?? null, input.category ?? null, input.newContent ?? null, input.queuedAt ?? Date.now());
4328
+ const row = getMemoryMutation(db, Number(result.lastInsertRowid));
4329
+ if (!row) {
4330
+ throw new Error("Failed to load queued memory mutation");
4331
+ }
4332
+ return row;
4333
+ }
4334
+ function getMemoryMutation(db, id) {
4335
+ const row = db.prepare(`SELECT id, project_path, mutation_type, target_memory_id,
4336
+ superseded_by_id, category, new_content, queued_at
4337
+ FROM memory_mutation_log
4338
+ WHERE id = ?`).get(id);
4339
+ return row ? toMemoryMutation(row) : null;
4340
+ }
4341
+ function uniqueProjectPaths(projectPaths) {
4342
+ return [...new Set(projectPaths.filter((path) => path.length > 0))];
4343
+ }
4344
+ function placeholders(values) {
4345
+ return values.map(() => "?").join(", ");
4346
+ }
4347
+ function coalesceMutations(rows) {
4348
+ const chosenByTarget = new Map;
4349
+ for (const dbRow of rows) {
4350
+ const candidate = toMemoryMutation(dbRow);
4351
+ const current = chosenByTarget.get(candidate.targetMemoryId);
4352
+ if (!current) {
4353
+ chosenByTarget.set(candidate.targetMemoryId, candidate);
4354
+ continue;
4355
+ }
4356
+ const visibilityChanged = current.visibilityChanged || candidate.visibilityChanged;
4357
+ const currentTerminal = isTerminalMutation(current);
4358
+ const candidateTerminal = isTerminalMutation(candidate);
4359
+ if (currentTerminal && !candidateTerminal) {
4360
+ chosenByTarget.set(candidate.targetMemoryId, { ...current, visibilityChanged });
4361
+ continue;
4362
+ }
4363
+ chosenByTarget.set(candidate.targetMemoryId, { ...candidate, visibilityChanged });
4364
+ }
4365
+ return [...chosenByTarget.values()].sort((left, right) => left.id - right.id);
4366
+ }
4367
+ function getMemoryMutationsForRenderByIdentitySet(db, projectPaths, afterId, renderedMemoryIds) {
4368
+ const identities = uniqueProjectPaths(projectPaths);
4369
+ if (identities.length === 0)
4370
+ return [];
4371
+ const cursor = afterId ?? 0;
4372
+ const visibilityTargets = db.prepare(`SELECT DISTINCT target_memory_id
4373
+ FROM memory_mutation_log
4374
+ WHERE project_path IN (${placeholders(identities)})
4375
+ AND id > ?
4376
+ AND category = ?`).all(...identities, cursor, MEMORY_VISIBILITY_MUTATION_CATEGORY);
4377
+ const requestedTargets = new Set(renderedMemoryIds);
4378
+ for (const row of visibilityTargets)
4379
+ requestedTargets.add(row.target_memory_id);
4380
+ if (requestedTargets.size === 0)
4381
+ return [];
4382
+ const queried = new Set;
4383
+ let frontier = [...requestedTargets].sort((left, right) => left - right);
4384
+ const loaded = [];
4385
+ for (let depth = 0;depth <= MAX_MEMORY_REPLACEMENT_DEPTH; depth += 1) {
4386
+ frontier = frontier.filter((target) => {
4387
+ if (queried.has(target))
4388
+ return false;
4389
+ queried.add(target);
4390
+ return true;
4391
+ });
4392
+ if (frontier.length === 0)
4393
+ break;
4394
+ const batch = db.prepare(`SELECT id, project_path, mutation_type, target_memory_id,
4395
+ superseded_by_id, category, new_content, queued_at
4396
+ FROM memory_mutation_log
4397
+ WHERE project_path IN (${placeholders(identities)})
4398
+ AND id > ?
4399
+ AND target_memory_id IN (${placeholders(frontier)})
4400
+ ORDER BY id ASC`).all(...identities, cursor, ...frontier);
4401
+ loaded.push(...batch);
4402
+ frontier = coalesceMutations(batch).filter((mutation) => mutation.mutationType === "superseded").flatMap((mutation) => mutation.supersededById === null ? [] : [mutation.supersededById]);
4403
+ }
4404
+ const byTarget = new Map(coalesceMutations(loaded).map((mutation) => [mutation.targetMemoryId, mutation]));
4405
+ const resolved = [];
4406
+ for (const target of [...requestedTargets].sort((left, right) => left - right)) {
4407
+ const mutation = byTarget.get(target);
4408
+ if (!mutation)
4409
+ continue;
4410
+ if (mutation.mutationType !== "superseded") {
4411
+ resolved.push(mutation);
4412
+ continue;
4413
+ }
4414
+ let terminal = mutation.supersededById;
4415
+ const visited = new Set([target]);
4416
+ let depth = 0;
4417
+ while (terminal !== null) {
4418
+ if (visited.has(terminal)) {
4419
+ terminal = null;
4420
+ break;
4421
+ }
4422
+ visited.add(terminal);
4423
+ const next = byTarget.get(terminal);
4424
+ if (next?.mutationType !== "superseded")
4425
+ break;
4426
+ if (depth >= MAX_MEMORY_REPLACEMENT_DEPTH - 1) {
4427
+ terminal = null;
4428
+ break;
4429
+ }
4430
+ terminal = next.supersededById;
4431
+ depth += 1;
4432
+ }
4433
+ resolved.push({ ...mutation, supersededById: terminal });
4434
+ }
4435
+ return resolved.sort((left, right) => left.id - right.id);
4436
+ }
4437
+ function getMemoryMutationsForRender(db, projectPath, afterId, renderedMemoryIds) {
4438
+ return getMemoryMutationsForRenderByIdentitySet(db, [projectPath], afterId, renderedMemoryIds);
4439
+ }
4440
+ function getMemoryMutationsForRenderByProjects(db, projectPaths, afterId, renderedMemoryIds) {
4441
+ return getMemoryMutationsForRenderByIdentitySet(db, projectPaths, afterId, renderedMemoryIds);
4442
+ }
4443
+ function getMaxMemoryMutationId(db, projectPath) {
4444
+ const row = db.prepare("SELECT MAX(id) AS max_id FROM memory_mutation_log WHERE project_path = ?").get(projectPath);
4445
+ return row?.max_id ?? null;
4446
+ }
4447
+ function getMaxMemoryMutationIdForProjects(db, projectPaths) {
4448
+ const identities = uniqueProjectPaths(projectPaths);
4449
+ if (identities.length === 0)
4450
+ return null;
4451
+ if (identities.length === 1)
4452
+ return getMaxMemoryMutationId(db, identities[0]);
4453
+ const row = db.prepare(`SELECT MAX(id) AS max_id
4454
+ FROM memory_mutation_log
4455
+ WHERE project_path IN (${placeholders(identities)})`).get(...identities);
4456
+ return row?.max_id ?? null;
4457
+ }
4458
+ // src/features/magic-context/storage-project-state.ts
4459
+ var GLOBAL_USER_PROFILE_PROJECT_PATH = "__global__";
4460
+ function toProjectState(row) {
4461
+ return {
4462
+ projectPath: row.project_path,
4463
+ projectMemoryEpoch: row.project_memory_epoch,
4464
+ projectUserProfileVersion: row.project_user_profile_version,
4465
+ updatedAt: row.updated_at
4466
+ };
4467
+ }
4468
+ var getProjectStateStatements = new WeakMap;
4469
+ function getProjectState(db, projectPath) {
4470
+ let statement = getProjectStateStatements.get(db);
4471
+ if (!statement) {
4472
+ statement = db.prepare(`SELECT project_path, project_memory_epoch, project_user_profile_version, updated_at
4473
+ FROM project_state
4474
+ WHERE project_path = ?`);
4475
+ getProjectStateStatements.set(db, statement);
4476
+ }
4477
+ const row = statement.get(projectPath);
4478
+ return row ? toProjectState(row) : null;
4479
+ }
4480
+ function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PROJECT_PATH, now = Date.now()) {
4481
+ db.prepare(`INSERT INTO project_state
4482
+ (project_path, project_memory_epoch, project_user_profile_version, updated_at)
4483
+ VALUES (?, 0, 1, ?)
4484
+ ON CONFLICT(project_path) DO UPDATE SET
4485
+ project_user_profile_version = project_user_profile_version + 1,
4486
+ updated_at = excluded.updated_at`).run(projectPath, now);
4487
+ const state = getProjectState(db, projectPath);
4488
+ if (!state) {
4489
+ throw new Error(`Failed to bump project user profile version for ${projectPath}`);
4490
+ }
4491
+ return state;
4492
+ }
4493
+ // src/features/magic-context/storage-source.ts
4494
+ var sourceReadStatements = new WeakMap;
4495
+ function isSourceContentRow(row) {
4496
+ if (row === null || typeof row !== "object")
4497
+ return false;
4498
+ const r = row;
4499
+ return typeof r.tag_id === "number" && typeof r.content === "string";
4500
+ }
4501
+ function saveSourceContent(db, sessionId, tagId, content) {
4502
+ db.prepare("INSERT OR IGNORE INTO source_contents (tag_id, session_id, content, created_at, harness) VALUES (?, ?, ?, ?, ?)").run(tagId, sessionId, content, Date.now(), getHarness2());
4503
+ }
4504
+ function replaceSourceContent(db, sessionId, tagId, content) {
4505
+ db.prepare(`INSERT INTO source_contents (tag_id, session_id, content, created_at, harness)
4506
+ VALUES (?, ?, ?, ?, ?)
4507
+ ON CONFLICT(session_id, tag_id)
4508
+ DO UPDATE SET content = excluded.content, created_at = excluded.created_at`).run(tagId, sessionId, content, Date.now(), getHarness2());
4509
+ }
4510
+ function getSourceContents(db, sessionId, tagIds) {
4511
+ if (tagIds.length === 0) {
4512
+ return new Map;
4513
+ }
4514
+ let statement = sourceReadStatements.get(db);
4515
+ if (!statement) {
4516
+ statement = db.prepare("SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (SELECT value FROM json_each(?))");
4517
+ sourceReadStatements.set(db, statement);
4518
+ }
4519
+ const rows = statement.all(sessionId, JSON.stringify(tagIds)).filter(isSourceContentRow);
4520
+ const sources = new Map;
4521
+ for (const row of rows) {
4522
+ sources.set(row.tag_id, row.content);
4523
+ }
4524
+ return sources;
4525
+ }
4526
+ // src/features/magic-context/storage-subagent-invocations.ts
4527
+ function clampToken(value) {
4528
+ return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
4529
+ }
4530
+ function recordSubagentInvocation(db, input) {
4531
+ const result = db.prepare(`INSERT INTO subagent_invocations (
4532
+ session_id, harness, subagent, task, provider_id, model_id,
4533
+ started_at, ended_at, status,
4534
+ input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
4535
+ error, parent_invocation_id
4536
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.sessionId, input.harness, input.subagent, input.task ?? null, input.providerId ?? null, input.modelId ?? null, input.startedAt, input.endedAt, input.status, clampToken(input.inputTokens), clampToken(input.outputTokens), clampToken(input.cacheReadTokens), clampToken(input.cacheWriteTokens), input.error ?? null, input.parentInvocationId ?? null);
4537
+ return Number(result.lastInsertRowid);
4538
+ }
4539
+ function getLatestHistorianInvocationId(db, sessionId) {
4540
+ try {
4541
+ const row = db.prepare(`SELECT id FROM subagent_invocations
4542
+ WHERE session_id = ? AND subagent = 'historian'
4543
+ ORDER BY id DESC LIMIT 1`).get(sessionId);
4544
+ return typeof row?.id === "number" ? row.id : null;
4545
+ } catch {
4546
+ return null;
4547
+ }
4548
+ }
4549
+ // src/features/magic-context/storage-v22-backfill-failures.ts
4550
+ var ERROR_CLASSES = new Set([
4551
+ "not_git_repo",
4552
+ "git_missing",
4553
+ "git_timeout",
4554
+ "permission_denied",
4555
+ "unknown"
4556
+ ]);
4557
+ export { advanceSessionActivity, observeSessionActivity, backfillSessionActivity, COMPARTMENT_LEASE_RENEWAL_MS, getCompartmentLeaseBlocker, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, isNoContentCompartment, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getCompartmentsByEndMessageId, appendCompartments, buildCompartmentBlock, saveRecompStagingPass, getRecompStaging, clearRecompStaging, getRecompPartialRange, setRecompPartialRange, escapeXmlAttr, escapeXmlContent, getUncoveredCompartmentEndsThrough, isPartialCompartmentEnd, readProjectDocsCanonical, providerResponseFailed, isSuccessfulProviderCompletion, LkgRecoveryFenceError, lkgServedArrayDigest, hasCleanLkgRecoveryFence, dirtyLkgRecoveryRevision, ownsLkgDirtyFence, invalidateCleanLkgRecoveryFence, prepareLkgCaptureFence, certifyCommittedLkgCapture, markLkgRecoveryDirty, rememberUnpublishedAutoSearchNoHint, getUnpublishedAutoSearchNoHint, forgetUnpublishedAutoSearchNoHint, registerAutoSearchWork, cancelAutoSearchWork, readSessionMeta, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, clearSession, requestPendingMaterialization, pendingMaterializationOrigin, hasPendingMaterializationOrigin, clearPendingMaterialization, recordSystemPromptForRequest, recordHeldHeadForRequest, bindSystemPromptResponse, isHeldHeadForRequest, deferDeliveredSystemRefresh, retirePendingSystemPromptDelivery, lkgProviderInputTotal, beginV2LkgRequest, claimLkgRequestIdentity, currentLkgRequestIdentity, noteCapturedLkgRequest, noteLkgProviderResponse, measuredLkgPrefix, clearLkgMeasuredRequest, saveLkgSlotToDb, clearPersistedLkgSlotStrict, loadPersistedLkgSlot, drainStaleLkgSlots, createDbLkgPersistence, resolveLkgModelKeys, createLkgEntryProjector, captureLkgSlot, validateAnthropicReasoningRuns, validateLkgSeam, replayLkg, coldStartRawServedIndex, coldStartUncapturedReplay, noteUncertifiedNormalLkg, hasProcessLocalLkgProof, lkgDirtyRevision, rememberLkgDirtyRevision, readPersistedLkgUntaggedInputIds, persistLkgUntaggedInputIds, noteLkgRecoveryPrefix, readLkgRecoveryPrefix, noteLkgHealthyPrefix, lkgRecoveryReplayUnproven, lkgRecoveryEntryUnproven, lkgInputIdentity, registerLkgPersistence, beginLkgPass, visitMessageContentFields, contentSnapshotValue, messageContentFields, signatureForFields, exactReusablePrefix, incrementalLkgContentDigests, lkgSlotRejection, captureSlot, getInMemorySlot, getSlot, forgetInMemorySlot, dropSlot, noteEntry, getLkgSlotHeapStats, TOOL_SWEEP_SCOPED_MARKER, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, externalHistorianFailureReason, recordHistorianRun, summarizeImportance, tallyFactsByCategory, MEMORY_VISIBILITY_MUTATION_CATEGORY, queueMemoryMutation, getMemoryMutationsForRender, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationId, getMaxMemoryMutationIdForProjects, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, recordSubagentInvocation, getLatestHistorianInvocationId };