@cortexkit/opencode-magic-context 0.47.0 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/dist/agents/magic-context-prompt.d.ts +1 -1
  2. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  3. package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
  4. package/dist/auto-search-worker.js +27 -30
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/mural-model-deprecation.d.ts +15 -0
  7. package/dist/config/mural-model-deprecation.d.ts.map +1 -0
  8. package/dist/config/project-security.d.ts +0 -3
  9. package/dist/config/project-security.d.ts.map +1 -1
  10. package/dist/config/schema/magic-context.d.ts +10 -6
  11. package/dist/config/schema/magic-context.d.ts.map +1 -1
  12. package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-kzx4dmk1.js} +12 -10
  13. package/dist/{context-wq4ffwyb.js → context-nj5f293n.js} +2765 -1925
  14. package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-qz5rrr08.js} +4 -3
  15. package/dist/embedding-activity-g1dhes6g.js +10 -0
  16. package/dist/embedding-backfill-aetxv1vt.js +21 -0
  17. package/dist/embedding-cache-mgyr73ef.js +16 -0
  18. package/dist/embedding-worker.js +11 -9
  19. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
  21. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
  23. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
  25. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
  27. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  29. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  30. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  31. package/dist/features/magic-context/message-index-async.d.ts +16 -3
  32. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  33. package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
  34. package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
  35. package/dist/features/magic-context/message-index.d.ts +7 -1
  36. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  37. package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
  38. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  39. package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
  40. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  41. package/dist/features/magic-context/search-rerank.d.ts +35 -0
  42. package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
  43. package/dist/features/magic-context/search.d.ts +40 -0
  44. package/dist/features/magic-context/search.d.ts.map +1 -1
  45. package/dist/features/magic-context/session-activity.d.ts.map +1 -1
  46. package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
  47. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  49. package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
  50. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  51. package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
  52. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  53. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  54. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  55. package/dist/features/magic-context/storage-session-tables.d.ts +2 -0
  56. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  57. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
  58. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
  59. package/dist/features/magic-context/storage-tags.d.ts +153 -4
  60. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  61. package/dist/features/magic-context/storage.d.ts +1 -1
  62. package/dist/features/magic-context/storage.d.ts.map +1 -1
  63. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  64. package/dist/features/magic-context/tagger.d.ts +2 -0
  65. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  66. package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
  67. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  68. package/dist/harness-e4avh192.js +10 -0
  69. package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
  70. package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
  73. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
  74. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  75. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +34 -3
  77. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/command-handler.d.ts +3 -0
  79. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
  84. package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
  87. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/hook.d.ts +3 -2
  89. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
  92. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
  94. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
  96. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
  98. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
  100. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
  101. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
  102. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
  103. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
  104. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
  105. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
  106. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
  107. package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
  108. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  109. package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
  110. package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
  111. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
  112. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
  113. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
  114. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
  115. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
  116. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
  117. package/dist/hooks/magic-context/read-session-chunk.d.ts +19 -1
  118. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  119. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
  121. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  122. package/dist/hooks/magic-context/read-session-raw.d.ts +118 -1
  123. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  124. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
  126. package/dist/hooks/magic-context/rust-mode-transform.d.ts +36 -0
  127. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/sentinel.d.ts +41 -1
  129. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
  131. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
  132. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
  133. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
  134. package/dist/hooks/magic-context/strip-content.d.ts +14 -2
  135. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  136. package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
  137. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  138. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  139. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  140. package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
  141. package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
  142. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  143. package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
  144. package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
  145. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +13 -0
  146. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  147. package/dist/hooks/magic-context/transform.d.ts +9 -2
  148. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  149. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  150. package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
  151. package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
  152. package/dist/{index-5gq3b2ya.js → index-1bt88epp.js} +227 -205
  153. package/dist/{index-cwf6s3ay.js → index-1g30axtz.js} +3279 -2907
  154. package/dist/{index-5a2r0p9f.js → index-1r0k9js3.js} +20 -13
  155. package/dist/index-2bvekkfy.js +11 -0
  156. package/dist/{index-6d9e1m08.js → index-2jcbj7r1.js} +13301 -13225
  157. package/dist/index-2jgwttpt.js +3269 -0
  158. package/dist/index-4dhv7mqz.js +131 -0
  159. package/dist/{index-sj29b3z2.js → index-4mjhqadz.js} +3 -3
  160. package/dist/{index-0c82743p.js → index-57mrqed8.js} +17 -15
  161. package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
  162. package/dist/index-7jzrrxap.js +931 -0
  163. package/dist/index-8ajstryz.js +18 -0
  164. package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
  165. package/dist/{index-6wkcswft.js → index-9qjqq45k.js} +29 -19
  166. package/dist/{index-adwfkpex.js → index-9rt53q79.js} +23 -23
  167. package/dist/index-b7mv1jx3.js +1060 -0
  168. package/dist/index-d9vfe7xq.js +16 -0
  169. package/dist/{index-gg8j07zz.js → index-ezmszwbd.js} +8 -6
  170. package/dist/index-fb3zxn06.js +13 -0
  171. package/dist/index-fr0wbhdn.js +43 -0
  172. package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
  173. package/dist/index-gzcmtmar.js +171 -0
  174. package/dist/{index-w2t4ah5j.js → index-h2py7207.js} +6762 -7400
  175. package/dist/index-h2wc01qk.js +120 -0
  176. package/dist/index-h5zfkjyk.js +1277 -0
  177. package/dist/{index-92bp57hg.js → index-ha87j7a8.js} +1343 -149
  178. package/dist/index-hj2q50k0.js +856 -0
  179. package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
  180. package/dist/index-kmpvemph.js +1314 -0
  181. package/dist/index-kp5qe690.js +3030 -0
  182. package/dist/{index-m5fe6jch.js → index-kq57tdf0.js} +152 -2453
  183. package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
  184. package/dist/{v2/server-njt3np1k.js → index-nm6a8xpd.js} +220 -961
  185. package/dist/{index-hybnrwq0.js → index-nsjyysj0.js} +137 -130
  186. package/dist/index-nydv6g8r.js +3569 -0
  187. package/dist/index-pavzsdc6.js +17 -0
  188. package/dist/index-peshmj6h.js +152 -0
  189. package/dist/index-pxwp2hjk.js +571 -0
  190. package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
  191. package/dist/{v2/server-51dv1pr5.js → index-qx53vezw.js} +301 -27
  192. package/dist/{index-rrrsepyw.js → index-s4j7t92z.js} +90 -85
  193. package/dist/{index-9pk9exrb.js → index-stbr4ce6.js} +18 -18
  194. package/dist/{index-fzbvakh0.js → index-tqf7yg27.js} +3 -3
  195. package/dist/index-vkbqdnkj.js +2307 -0
  196. package/dist/{index-8da2zjhz.js → index-z1tjp257.js} +9 -7
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +608 -349
  199. package/dist/logger-ewak5q1s.js +20 -0
  200. package/dist/message-index-bounded-h0mrd4pr.js +124 -0
  201. package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-8x06r9kx.js} +8 -6
  202. package/dist/migration-worker.js +25 -18
  203. package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  204. package/dist/plugin/dream-timer.d.ts +1 -1
  205. package/dist/plugin/dream-timer.d.ts.map +1 -1
  206. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
  207. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  208. package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
  209. package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
  210. package/dist/plugin/host-stall-profiler.d.ts +2 -95
  211. package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
  212. package/dist/plugin/messages-transform.d.ts +0 -13
  213. package/dist/plugin/messages-transform.d.ts.map +1 -1
  214. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  215. package/dist/plugin/tool-registry.d.ts.map +1 -1
  216. package/dist/project-embedding-registry-rtt0djyb.js +88 -0
  217. package/dist/raw-ordinal-warmup-worker.js +60 -0
  218. package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-ty89v75e.js} +17 -9
  219. package/dist/read-session-raw-8sjbc9h0.js +60 -0
  220. package/dist/recomp-orchestrator-4f1yyd1q.js +57 -0
  221. package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-q0cyrx3x.js} +4 -2
  222. package/dist/search-pz4f4wge.js +45 -0
  223. package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-38cd5dqt.js} +10 -7
  224. package/dist/shared/auto-search-lifecycle.d.ts +14 -0
  225. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
  226. package/dist/shared/conflict-detector.d.ts.map +1 -1
  227. package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
  228. package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
  229. package/dist/shared/host-stall-profiler-common.d.ts +58 -0
  230. package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
  231. package/dist/shared/host-stall-profiler-node.d.ts +36 -0
  232. package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
  233. package/dist/shared/host-stall-profiler-report.d.ts +68 -0
  234. package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
  235. package/dist/shared/host-stall-profiler.d.ts +5 -0
  236. package/dist/shared/host-stall-profiler.d.ts.map +1 -0
  237. package/dist/shared/logger.d.ts.map +1 -1
  238. package/dist/shared/model-resolution.d.ts +2 -3
  239. package/dist/shared/model-resolution.d.ts.map +1 -1
  240. package/dist/shared/models-dev-temperature.d.ts +18 -0
  241. package/dist/shared/models-dev-temperature.d.ts.map +1 -0
  242. package/dist/shared/project-directory-key.d.ts +16 -0
  243. package/dist/shared/project-directory-key.d.ts.map +1 -1
  244. package/dist/shared/sqlite.d.ts +30 -0
  245. package/dist/shared/sqlite.d.ts.map +1 -1
  246. package/dist/shared/stable-json.d.ts.map +1 -1
  247. package/dist/shared/subagent-temperature.d.ts +46 -0
  248. package/dist/shared/subagent-temperature.d.ts.map +1 -0
  249. package/dist/shared/user-facing-codes.d.ts +0 -5
  250. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  251. package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  252. package/dist/sqlite-mhjkerzq.js +46 -0
  253. package/dist/storage-memory-07fx57k6.js +71 -0
  254. package/dist/storage-tags-k0pda32s.js +133 -0
  255. package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
  256. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  257. package/dist/tools/ctx-note/constants.d.ts +4 -0
  258. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  259. package/dist/tools/ctx-note/tools.d.ts +1 -0
  260. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  261. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  262. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  263. package/dist/tools/ctx-search/types.d.ts +1 -0
  264. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  265. package/dist/tools/parameter-descriptions.d.ts +2 -2
  266. package/dist/tools/parameter-descriptions.d.ts.map +1 -1
  267. package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-tck4g20s.js} +35 -20
  268. package/dist/transformers-node-wasm.js +18415 -18415
  269. package/dist/v2/auto-search-worker.js +27 -30
  270. package/dist/v2/{context-14v1hr8b.js → context-crbt6p1y.js} +4708 -4218
  271. package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-fgej9j46.js} +4 -3
  272. package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
  273. package/dist/v2/embedding-backfill-ph1qfyn3.js +21 -0
  274. package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
  275. package/dist/v2/embedding-worker.js +12 -9
  276. package/dist/v2/fold/host-media.d.ts +4 -0
  277. package/dist/v2/fold/host-media.d.ts.map +1 -1
  278. package/dist/v2/fold/memory-cache.d.ts +70 -0
  279. package/dist/v2/fold/memory-cache.d.ts.map +1 -0
  280. package/dist/v2/fold/native-codec.d.ts +10 -0
  281. package/dist/v2/fold/native-codec.d.ts.map +1 -0
  282. package/dist/v2/fold/native-replay.d.ts +58 -0
  283. package/dist/v2/fold/native-replay.d.ts.map +1 -0
  284. package/dist/v2/fold/policy.d.ts +24 -0
  285. package/dist/v2/fold/policy.d.ts.map +1 -0
  286. package/dist/v2/harness-e4avh192.js +10 -0
  287. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  288. package/dist/v2/hidden-completion.d.ts +7 -0
  289. package/dist/v2/hidden-completion.d.ts.map +1 -1
  290. package/dist/v2/hooks/context.d.ts +2 -2
  291. package/dist/v2/hooks/context.d.ts.map +1 -1
  292. package/dist/v2/hooks/dream-manual.d.ts +1 -1
  293. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  294. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  295. package/dist/v2/hooks/dream-trigger.d.ts +5 -3
  296. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  297. package/dist/v2/hooks/generate.d.ts +9 -2
  298. package/dist/v2/hooks/generate.d.ts.map +1 -1
  299. package/dist/v2/hooks/payload.d.ts.map +1 -1
  300. package/dist/v2/hooks/tools.d.ts.map +1 -1
  301. package/dist/v2/hooks/types.d.ts +6 -0
  302. package/dist/v2/hooks/types.d.ts.map +1 -1
  303. package/dist/v2/logger-pj02s7sr.js +19 -0
  304. package/dist/v2/message-index-bounded-xwqdywxg.js +123 -0
  305. package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-cje68egj.js} +7 -7
  306. package/dist/v2/migration-worker.js +24 -17
  307. package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  308. package/dist/v2/project-embedding-registry-d6m7tyxr.js +86 -0
  309. package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
  310. package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-8p5mdryx.js} +16 -8
  311. package/dist/v2/read-session-raw-j8dvp7f4.js +59 -0
  312. package/dist/v2/recomp-orchestrator-ckfgt6wq.js +57 -0
  313. package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-y3p1hce9.js} +3 -3
  314. package/dist/v2/search-ym8rehhz.js +45 -0
  315. package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-5m0yapqx.js} +9 -8
  316. package/dist/v2/{server-rz514f14.js → server-19zjmn02.js} +2044 -2060
  317. package/dist/v2/server-1tk82krw.js +796 -0
  318. package/dist/v2/server-2bvekkfy.js +11 -0
  319. package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
  320. package/dist/v2/server-2s6ayq3t.js +1048 -0
  321. package/dist/v2/{server-fcdehk1s.js → server-2s9qz6n7.js} +4 -4
  322. package/dist/v2/server-3j4d00kf.js +171 -0
  323. package/dist/v2/{server-14vq4kpm.js → server-3t0q2cqx.js} +3 -3
  324. package/dist/v2/server-4dhv7mqz.js +131 -0
  325. package/dist/v2/server-4ez8mntn.js +3213 -0
  326. package/dist/v2/{server-6r257mf5.js → server-676xw7at.js} +3 -3
  327. package/dist/v2/{server-vs5gpnd4.js → server-6byqfbqf.js} +165 -145
  328. package/dist/v2/server-7ekna9zs.js +120 -0
  329. package/dist/v2/server-7h861yms.js +1272 -0
  330. package/dist/v2/server-7jzrrxap.js +931 -0
  331. package/dist/v2/server-8ajstryz.js +18 -0
  332. package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
  333. package/dist/v2/{server-cpepxy2q.js → server-8k2agx29.js} +14 -12
  334. package/dist/v2/server-c5rrgrcd.js +3545 -0
  335. package/dist/v2/server-d9vfe7xq.js +16 -0
  336. package/dist/v2/server-fb3zxn06.js +13 -0
  337. package/dist/v2/server-fr0wbhdn.js +43 -0
  338. package/dist/v2/{server-y10vbq6y.js → server-hb6xhh9q.js} +11 -1053
  339. package/dist/v2/server-jvxzm1jy.js +3023 -0
  340. package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
  341. package/dist/{index-5eqk6z3s.js → v2/server-kzns2hbz.js} +301 -27
  342. package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
  343. package/dist/v2/server-pavzsdc6.js +17 -0
  344. package/dist/v2/{server-vd4e7174.js → server-pj4pjv02.js} +21 -17
  345. package/dist/v2/{server-e0c1b7a7.js → server-q4ph9bwn.js} +1340 -148
  346. package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
  347. package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
  348. package/dist/v2/{server-d0sraw7m.js → server-sa8jvrfc.js} +291 -286
  349. package/dist/v2/server-ss95ky04.js +1048 -0
  350. package/dist/v2/{server-1qbnzc80.js → server-t4k4qexw.js} +142 -150
  351. package/dist/{index-x3kwrmqk.js → v2/server-v4mewb78.js} +35 -792
  352. package/dist/v2/server-w32kmdez.js +154 -0
  353. package/dist/v2/{server-nf82q6pt.js → server-x4hscabv.js} +5547 -5449
  354. package/dist/v2/server-xwz4dqh9.js +569 -0
  355. package/dist/v2/{server-efhwzx05.js → server-ycw9qqcy.js} +23 -23
  356. package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
  357. package/dist/v2/server-zp53y8js.js +1311 -0
  358. package/dist/v2/server.js +16 -14
  359. package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  360. package/dist/v2/sqlite-mhjkerzq.js +46 -0
  361. package/dist/v2/storage-memory-07fx57k6.js +71 -0
  362. package/dist/v2/storage-tags-8vw924zn.js +132 -0
  363. package/dist/v2/store-reader.d.ts +24 -2
  364. package/dist/v2/store-reader.d.ts.map +1 -1
  365. package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
  366. package/dist/v2/transformers-node-wasm.js +18415 -18415
  367. package/dist/v2/tui/index.d.ts.map +1 -1
  368. package/dist/v2/tui/types.d.ts +1 -10
  369. package/dist/v2/tui/types.d.ts.map +1 -1
  370. package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-a7efxaax.js} +51 -30
  371. package/dist/wrapup-orchestrator-barbc6h9.js +44 -0
  372. package/package.json +4 -3
  373. package/src/agents/magic-context-prompt.ts +27 -2
  374. package/src/agents/smart-notes-enabled.test.ts +294 -0
  375. package/src/agents/smart-notes-on.golden.json +70 -0
  376. package/src/config/index.test.ts +67 -1
  377. package/src/config/index.ts +2 -0
  378. package/src/config/latch-permanence-guard.test.ts +4 -0
  379. package/src/config/mural-model-deprecation.ts +24 -0
  380. package/src/config/project-security.hostile-matrix.test.ts +4 -44
  381. package/src/config/project-security.test.ts +9 -14
  382. package/src/config/project-security.ts +13 -55
  383. package/src/config/schema/magic-context.test.ts +2 -2
  384. package/src/config/schema/magic-context.ts +16 -10
  385. package/src/features/magic-context/dreamer/task-registry.ts +6 -0
  386. package/src/shared/auto-search-lifecycle.ts +43 -0
  387. package/src/shared/conflict-detector.test.ts +56 -0
  388. package/src/shared/conflict-detector.ts +16 -5
  389. package/src/shared/host-stall-profiler-bun.ts +358 -0
  390. package/src/shared/host-stall-profiler-common.ts +159 -0
  391. package/src/shared/host-stall-profiler-node.test.ts +234 -0
  392. package/src/shared/host-stall-profiler-node.ts +274 -0
  393. package/src/shared/host-stall-profiler-report.ts +248 -0
  394. package/src/shared/host-stall-profiler.ts +57 -0
  395. package/src/shared/logger.test.ts +38 -0
  396. package/src/shared/logger.ts +10 -2
  397. package/src/shared/model-resolution.test.ts +54 -17
  398. package/src/shared/model-resolution.ts +6 -17
  399. package/src/shared/models-dev-temperature.ts +107 -0
  400. package/src/shared/project-directory-key.test.ts +59 -0
  401. package/src/shared/project-directory-key.ts +20 -0
  402. package/src/shared/sqlite.test.ts +52 -0
  403. package/src/shared/sqlite.ts +339 -23
  404. package/src/shared/stable-json-linear.test.ts +109 -0
  405. package/src/shared/stable-json.ts +37 -7
  406. package/src/shared/subagent-temperature.test.ts +270 -0
  407. package/src/shared/subagent-temperature.ts +110 -0
  408. package/src/shared/user-facing-codes.ts +2 -6
  409. package/src/shared/write-transaction-attribution.test.ts +2 -2
  410. package/src/v2/tui/host-contract.test.ts +41 -67
  411. package/src/v2/tui/index.ts +6 -214
  412. package/src/v2/tui/types.ts +5 -17
  413. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
  414. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
  415. package/dist/features/magic-context/checkout-claim.d.ts +0 -155
  416. package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
  417. package/dist/index-bb36vgr3.js +0 -6608
  418. package/dist/index-fnn5pjtt.js +0 -6554
  419. package/dist/recomp-orchestrator-rervg6q4.js +0 -42
  420. package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
  421. package/dist/v2/server-3trjk1hx.js +0 -6360
  422. package/dist/v2/server-nm9n3aqq.js +0 -6461
  423. package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
  424. /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
  425. /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
@@ -0,0 +1,3569 @@
1
+ import {
2
+ hasMeasuredDecisionCalibration,
3
+ providerMass
4
+ } from "./index-1zx87sdm.js";
5
+ import {
6
+ estimateTokens
7
+ } from "./index-qx53vezw.js";
8
+ import {
9
+ getHarness2
10
+ } from "./index-pavzsdc6.js";
11
+ import {
12
+ sessionLog2
13
+ } from "./index-nsjyysj0.js";
14
+ import {
15
+ getTagIdentityWriteGeneration2,
16
+ getSqliteDatabasePath2
17
+ } from "./index-kb9nn0a0.js";
18
+ import {
19
+ tagIdentityRevisionKey,
20
+ tagOrderConstraintIndex,
21
+ stableStringify
22
+ } from "./index-1bt88epp.js";
23
+ import {
24
+ DEFAULT_PROTECTED_TOOLS,
25
+ normalizeProtectedToolName,
26
+ mergeProtectedTools
27
+ } from "./index-d9vfe7xq.js";
28
+
29
+ // src/shared/record-type-guard.ts
30
+ function isRecord(value) {
31
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32
+ }
33
+
34
+ // src/features/magic-context/storage-tags.ts
35
+ import { isMainThread } from "node:worker_threads";
36
+
37
+ // src/features/magic-context/reclaim-protection.ts
38
+ var CTX_REDUCE_KEEP = DEFAULT_PROTECTED_TOOLS.ctx_reduce;
39
+ function adoptedProtectedToolsPolicy(current, previous, rebuilding, hasBaseline) {
40
+ if (rebuilding || !hasBaseline)
41
+ return mergeProtectedTools(current);
42
+ return { ...previous ?? { todowrite: 0, ctx_reduce: 3 } };
43
+ }
44
+ function protectedToolTagNumbers(tags, protectedTools) {
45
+ const counts = mergeProtectedTools(protectedTools);
46
+ const protectedTags = new Set;
47
+ for (const tag of [...tags].sort((left, right) => right.tagNumber - left.tagNumber)) {
48
+ if (tag.status !== undefined && tag.status !== "active")
49
+ continue;
50
+ if (tag.type !== undefined && tag.type !== "tool")
51
+ continue;
52
+ const name = normalizeProtectedToolName(tag.toolName);
53
+ if (!Object.hasOwn(counts, name) || counts[name] <= 0)
54
+ continue;
55
+ protectedTags.add(tag.tagNumber);
56
+ counts[name] -= 1;
57
+ }
58
+ return protectedTags;
59
+ }
60
+ function protectedToolTokenCount(tags, counts, calibration) {
61
+ const protectedTags = protectedToolTagNumbers(tags, counts);
62
+ const tokens = tags.reduce((sum, tag) => sum + (protectedTags.has(tag.tagNumber) ? tag.tokenCount ?? 0 : 0), 0);
63
+ return calibration && hasMeasuredDecisionCalibration(calibration) ? providerMass({ tools: tokens }, calibration) : 0;
64
+ }
65
+
66
+ // src/hooks/magic-context/tag-content-primitives.ts
67
+ var encoder = new TextEncoder;
68
+ var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
69
+ var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
70
+ var DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
71
+ var DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
72
+ var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
73
+ var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
74
+ var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
75
+ function stripWellFormedLeadingTagPrefix(value) {
76
+ return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
77
+ }
78
+ function stripCompleteTagPairsGlobally(value) {
79
+ return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
80
+ }
81
+ function stripMalformedTagNotationGlobally(value) {
82
+ return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
83
+ }
84
+ function stripDanglingTagNotationGlobally(value) {
85
+ return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
86
+ }
87
+ function stripTagSectionCharacters(value) {
88
+ return value.replace(STRAY_SECTION_CHAR_REGEX, "");
89
+ }
90
+ function stripPersistedAssistantText(value) {
91
+ let text = stripWellFormedLeadingTagPrefix(value);
92
+ text = stripCompleteTagPairsGlobally(text);
93
+ text = stripMalformedTagNotationGlobally(text);
94
+ text = stripDanglingTagNotationGlobally(text);
95
+ text = stripTagSectionCharacters(text);
96
+ return text.trim();
97
+ }
98
+ function byteSize(value) {
99
+ return encoder.encode(value).length;
100
+ }
101
+ function stripTagPrefix(value) {
102
+ let stripped = value;
103
+ for (let pass = 0;pass < 8; pass++) {
104
+ const prev = stripped;
105
+ stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
106
+ stripped = stripped.replace(TAG_PREFIX_REGEX, "");
107
+ stripped = stripped.replace(DANGLING_TAG_PREFIX_REGEX, "");
108
+ if (stripped === prev)
109
+ break;
110
+ }
111
+ return stripped;
112
+ }
113
+ function peelLeadingMcTagNotation(value) {
114
+ const body = stripTagPrefix(value);
115
+ if (body === value)
116
+ return { tagPrefix: "", body };
117
+ return { tagPrefix: value.slice(0, value.length - body.length), body };
118
+ }
119
+ function prependTag(tagId, value) {
120
+ const stripped = stripTagPrefix(value);
121
+ return `§${tagId}§ ${stripped}`;
122
+ }
123
+ function isThinkingPart(part) {
124
+ if (part === null || typeof part !== "object")
125
+ return false;
126
+ const candidate = part;
127
+ return candidate.type === "thinking" || candidate.type === "reasoning";
128
+ }
129
+
130
+ // src/shared/tag-owner-id.ts
131
+ var TEXT_TAG_IDENTITY_MARKER = ":mc-text-v1:";
132
+ var POSITIONAL_CONTENT_SUFFIX = /:(?:p|file)\d+$/;
133
+ var CONTENT_DERIVED_TEXT_SUFFIX = /:mc-text-v1:[0-9a-f]+:[0-9a-f]+:o\d+$/;
134
+ function contentTagOwnerMessageId(contentId) {
135
+ const positional = POSITIONAL_CONTENT_SUFFIX.exec(contentId);
136
+ if (positional)
137
+ return contentId.slice(0, positional.index);
138
+ const derived = CONTENT_DERIVED_TEXT_SUFFIX.exec(contentId);
139
+ if (derived)
140
+ return contentId.slice(0, derived.index);
141
+ return contentId;
142
+ }
143
+
144
+ // src/hooks/magic-context/image-token-estimate.ts
145
+ var IMAGE_TOKEN_DIVISOR = 750;
146
+ var IMAGE_FALLBACK_TOKENS = 1200;
147
+ var IMAGE_TOKEN_CAP = 4500;
148
+ function estimateImageTokensFromDataUrl(url) {
149
+ const comma = url.indexOf(",");
150
+ if (comma < 0)
151
+ return IMAGE_FALLBACK_TOKENS;
152
+ const header = url.slice(0, comma);
153
+ const payload = url.slice(comma + 1);
154
+ const sliceLen = Math.min(512, payload.length);
155
+ const preview = payload.slice(0, sliceLen);
156
+ let bytes;
157
+ try {
158
+ bytes = base64Decode(preview);
159
+ } catch {
160
+ return IMAGE_FALLBACK_TOKENS;
161
+ }
162
+ if (header.includes("image/png")) {
163
+ const dims = parsePngDimensions(bytes);
164
+ if (dims)
165
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
166
+ } else if (header.includes("image/jpeg") || header.includes("image/jpg")) {
167
+ const dims = parseJpegDimensions(createBase64ByteReader(payload, bytes));
168
+ if (dims)
169
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
170
+ } else if (header.includes("image/webp")) {
171
+ const dims = parseWebpDimensions(bytes);
172
+ if (dims)
173
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
174
+ } else if (header.includes("image/gif")) {
175
+ const dims = parseGifDimensions(bytes);
176
+ if (dims)
177
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
178
+ }
179
+ return IMAGE_FALLBACK_TOKENS;
180
+ }
181
+ function estimateToolAttachmentImageTokens(state) {
182
+ if (!state || typeof state !== "object")
183
+ return 0;
184
+ const attachments = state.attachments;
185
+ if (!Array.isArray(attachments))
186
+ return 0;
187
+ let tokens = 0;
188
+ for (const attachment of attachments) {
189
+ if (!attachment || typeof attachment !== "object")
190
+ continue;
191
+ const { mime, url } = attachment;
192
+ if (typeof mime !== "string" || !mime.startsWith("image/"))
193
+ continue;
194
+ tokens += typeof url === "string" && url.startsWith("data:") ? estimateImageTokensFromDataUrl(url) : IMAGE_FALLBACK_TOKENS;
195
+ }
196
+ return tokens;
197
+ }
198
+ function clampImageTokens(n) {
199
+ if (n < 1)
200
+ return 1;
201
+ if (n > IMAGE_TOKEN_CAP)
202
+ return IMAGE_TOKEN_CAP;
203
+ return n;
204
+ }
205
+ function base64Decode(b64) {
206
+ const pad = b64.length % 4;
207
+ const padded = pad === 0 ? b64 : b64 + "=".repeat(4 - pad);
208
+ const binary = atob(padded);
209
+ const out = new Uint8Array(binary.length);
210
+ for (let i = 0;i < binary.length; i++)
211
+ out[i] = binary.charCodeAt(i);
212
+ return out;
213
+ }
214
+ function parsePngDimensions(b) {
215
+ if (b.length < 24)
216
+ return null;
217
+ if (b[0] !== 137 || b[1] !== 80 || b[2] !== 78 || b[3] !== 71 || b[4] !== 13 || b[5] !== 10 || b[6] !== 26 || b[7] !== 10)
218
+ return null;
219
+ const w = readUint32BE(b, 16);
220
+ const h = readUint32BE(b, 20);
221
+ if (!w || !h)
222
+ return null;
223
+ return { w, h };
224
+ }
225
+ var READER_PREVIEW_CHARS = 512;
226
+ var READER_PREVIEW_BYTES = 384;
227
+ var READER_WINDOW_CHARS = 4096;
228
+ var READER_WINDOW_BYTES = 3072;
229
+ function createBase64ByteReader(payload, preview) {
230
+ const windows = new Map;
231
+ return (offset) => {
232
+ if (offset < READER_PREVIEW_BYTES)
233
+ return preview[offset];
234
+ const index = Math.floor((offset - READER_PREVIEW_BYTES) / READER_WINDOW_BYTES);
235
+ let window = windows.get(index);
236
+ if (window === undefined) {
237
+ const start = READER_PREVIEW_CHARS + index * READER_WINDOW_CHARS;
238
+ const chars = payload.slice(start, start + READER_WINDOW_CHARS);
239
+ try {
240
+ window = chars.length > 0 ? base64Decode(chars) : null;
241
+ } catch {
242
+ window = null;
243
+ }
244
+ windows.set(index, window);
245
+ }
246
+ return window?.[offset - READER_PREVIEW_BYTES - index * READER_WINDOW_BYTES];
247
+ };
248
+ }
249
+ var JPEG_SCAN_LIMIT_BYTES = 256 * 1024;
250
+ function parseJpegDimensions(byteAt) {
251
+ if (byteAt(0) !== 255 || byteAt(1) !== 216 || byteAt(3) === undefined)
252
+ return null;
253
+ let i = 2;
254
+ while (i < JPEG_SCAN_LIMIT_BYTES && byteAt(i + 8) !== undefined) {
255
+ if (byteAt(i) !== 255) {
256
+ i++;
257
+ continue;
258
+ }
259
+ const marker = byteAt(i + 1);
260
+ if (marker === undefined)
261
+ break;
262
+ if (isSofMarker(marker)) {
263
+ const h = byteAt(i + 5) << 8 | byteAt(i + 6);
264
+ const w = byteAt(i + 7) << 8 | byteAt(i + 8);
265
+ if (w && h)
266
+ return { w, h };
267
+ return null;
268
+ }
269
+ if (marker === 216 || marker === 217 || marker === 1) {
270
+ i += 2;
271
+ continue;
272
+ }
273
+ const segLen = byteAt(i + 2) << 8 | byteAt(i + 3);
274
+ if (segLen < 2)
275
+ return null;
276
+ i += 2 + segLen;
277
+ }
278
+ return null;
279
+ }
280
+ function isSofMarker(m) {
281
+ if (m >= 192 && m <= 195)
282
+ return true;
283
+ if (m >= 197 && m <= 199)
284
+ return true;
285
+ if (m >= 201 && m <= 203)
286
+ return true;
287
+ if (m >= 205 && m <= 207)
288
+ return true;
289
+ return false;
290
+ }
291
+ function parseWebpDimensions(b) {
292
+ if (b.length < 30)
293
+ return null;
294
+ if (b[0] !== 82 || b[1] !== 73 || b[2] !== 70 || b[3] !== 70)
295
+ return null;
296
+ if (b[8] !== 87 || b[9] !== 69 || b[10] !== 66 || b[11] !== 80)
297
+ return null;
298
+ const variant = String.fromCharCode(b[12], b[13], b[14], b[15]);
299
+ if (variant === "VP8 ") {
300
+ const w = (b[26] | b[27] << 8) & 16383;
301
+ const h = (b[28] | b[29] << 8) & 16383;
302
+ if (w && h)
303
+ return { w, h };
304
+ } else if (variant === "VP8L") {
305
+ const b0 = b[21];
306
+ const b1 = b[22];
307
+ const b2 = b[23];
308
+ const b3 = b[24];
309
+ const w = 1 + ((b0 | b1 << 8) & 16383);
310
+ const h = 1 + ((b1 >> 6 | b2 << 2 | b3 << 10) & 16383);
311
+ if (w && h)
312
+ return { w, h };
313
+ } else if (variant === "VP8X") {
314
+ const w = 1 + (b[24] | b[25] << 8 | b[26] << 16);
315
+ const h = 1 + (b[27] | b[28] << 8 | b[29] << 16);
316
+ if (w && h)
317
+ return { w, h };
318
+ }
319
+ return null;
320
+ }
321
+ function parseGifDimensions(b) {
322
+ if (b.length < 10)
323
+ return null;
324
+ if (b[0] !== 71 || b[1] !== 73 || b[2] !== 70)
325
+ return null;
326
+ const w = b[6] | b[7] << 8;
327
+ const h = b[8] | b[9] << 8;
328
+ if (!w || !h)
329
+ return null;
330
+ return { w, h };
331
+ }
332
+ function readUint32BE(b, offset) {
333
+ return (b[offset] << 24 | b[offset + 1] << 16 | b[offset + 2] << 8 | b[offset + 3]) >>> 0;
334
+ }
335
+
336
+ // src/hooks/magic-context/provider-visible-parts.ts
337
+ function isRecord2(value) {
338
+ return value !== null && typeof value === "object" && !Array.isArray(value);
339
+ }
340
+ var KEPT_TOOL_STATE_FIELDS = new Set([
341
+ "status",
342
+ "input",
343
+ "output",
344
+ "error",
345
+ "attachments",
346
+ "content"
347
+ ]);
348
+ var KEPT_TOOL_STATE_TIME_FIELD = "compacted";
349
+ var KEPT_ERROR_METADATA_FIELDS = ["interrupted", "output"];
350
+ function providerVisibleToolState(state) {
351
+ const view = {};
352
+ for (const key of Object.keys(state)) {
353
+ const value = state[key];
354
+ if (KEPT_TOOL_STATE_FIELDS.has(key)) {
355
+ view[key] = value;
356
+ } else if (key === "time" && isRecord2(value)) {
357
+ view.time = value[KEPT_TOOL_STATE_TIME_FIELD] === undefined ? {} : { [KEPT_TOOL_STATE_TIME_FIELD]: value[KEPT_TOOL_STATE_TIME_FIELD] };
358
+ } else if (key === "metadata" && state.status === "error" && isRecord2(value)) {
359
+ const kept = {};
360
+ for (const field of KEPT_ERROR_METADATA_FIELDS) {
361
+ if (Object.hasOwn(value, field))
362
+ kept[field] = value[field];
363
+ }
364
+ view.metadata = kept;
365
+ }
366
+ }
367
+ return view;
368
+ }
369
+ function toolStateIsReduced(state) {
370
+ for (const key of Object.keys(state)) {
371
+ if (KEPT_TOOL_STATE_FIELDS.has(key))
372
+ continue;
373
+ const value = state[key];
374
+ if (key === "time" && isRecord2(value)) {
375
+ const keys = Object.keys(value);
376
+ if (keys.length === 0)
377
+ continue;
378
+ if (keys.length === 1 && keys[0] === KEPT_TOOL_STATE_TIME_FIELD)
379
+ continue;
380
+ return false;
381
+ }
382
+ if (key === "metadata" && state.status === "error" && isRecord2(value)) {
383
+ const extra = Object.keys(value).some((field) => !KEPT_ERROR_METADATA_FIELDS.includes(field));
384
+ if (!extra)
385
+ continue;
386
+ }
387
+ return false;
388
+ }
389
+ return true;
390
+ }
391
+ function providerVisiblePart(part) {
392
+ if (!isRecord2(part) || part.type !== "tool" || !isRecord2(part.state))
393
+ return part;
394
+ if (toolStateIsReduced(part.state))
395
+ return part;
396
+ return { ...part, state: providerVisibleToolState(part.state) };
397
+ }
398
+ function providerVisibleMessage(message) {
399
+ if (!isRecord2(message) || !Array.isArray(message.parts))
400
+ return message;
401
+ let parts;
402
+ for (let index = 0;index < message.parts.length; index += 1) {
403
+ const part = message.parts[index];
404
+ const view = providerVisiblePart(part);
405
+ if (view !== part) {
406
+ parts ??= message.parts.slice(0, index);
407
+ parts.push(view);
408
+ } else if (parts) {
409
+ parts.push(part);
410
+ }
411
+ }
412
+ return parts ? { ...message, parts } : message;
413
+ }
414
+
415
+ // src/hooks/magic-context/todo-view.ts
416
+ import { createHash } from "node:crypto";
417
+ var TODO_STATUS_PENDING = "pending";
418
+ var TODO_STATUS_IN_PROGRESS = "in_progress";
419
+ var TODO_STATUS_COMPLETED = "completed";
420
+ var TODO_STATUS_CANCELLED = "cancelled";
421
+ var TODO_PRIORITY_HIGH = "high";
422
+ var TODO_PRIORITY_MEDIUM = "medium";
423
+ var TODO_PRIORITY_LOW = "low";
424
+ var TODO_STATUSES = [
425
+ TODO_STATUS_PENDING,
426
+ TODO_STATUS_IN_PROGRESS,
427
+ TODO_STATUS_COMPLETED,
428
+ TODO_STATUS_CANCELLED
429
+ ];
430
+ var TODO_PRIORITIES = [
431
+ TODO_PRIORITY_HIGH,
432
+ TODO_PRIORITY_MEDIUM,
433
+ TODO_PRIORITY_LOW
434
+ ];
435
+ var TODO_STATUS_SET = new Set(TODO_STATUSES);
436
+ var TODO_PRIORITY_SET = new Set(TODO_PRIORITIES);
437
+ var TERMINAL_STATUSES = new Set([
438
+ TODO_STATUS_COMPLETED,
439
+ TODO_STATUS_CANCELLED
440
+ ]);
441
+ var TITLE_DONE_STATUSES = new Set([TODO_STATUS_COMPLETED]);
442
+ var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
443
+ function normalizeTodoStateJson(todos) {
444
+ if (!Array.isArray(todos))
445
+ return null;
446
+ const normalized = [];
447
+ for (const todo of todos) {
448
+ if (!isTodoItem(todo))
449
+ return null;
450
+ normalized.push({
451
+ content: todo.content,
452
+ status: todo.status,
453
+ priority: todo.priority ?? TODO_PRIORITY_MEDIUM
454
+ });
455
+ }
456
+ return JSON.stringify(normalized);
457
+ }
458
+ function buildSyntheticTodoPart(stateJson) {
459
+ const todos = parseTodoState(stateJson);
460
+ if (todos === null || todos.length === 0)
461
+ return null;
462
+ if (todos.every((t) => TERMINAL_STATUSES.has(t.status)))
463
+ return null;
464
+ const callID = computeSyntheticCallId(stateJson);
465
+ const activeCount = todos.filter((t) => !TITLE_DONE_STATUSES.has(t.status)).length;
466
+ const output = JSON.stringify(todos, null, 2);
467
+ const ts = 0;
468
+ return {
469
+ type: "tool",
470
+ callID,
471
+ tool: "todowrite",
472
+ state: {
473
+ status: "completed",
474
+ input: { todos },
475
+ output,
476
+ title: `${activeCount} todos`,
477
+ metadata: { todos, truncated: false },
478
+ time: { start: ts, end: ts }
479
+ },
480
+ syntheticTodoMarker: true
481
+ };
482
+ }
483
+ function computeSyntheticCallId(stateJson) {
484
+ const hash = createHash("sha256").update(stateJson).digest("hex").slice(0, 16);
485
+ return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
486
+ }
487
+ function isSyntheticTodoPart(part) {
488
+ if (part === null || typeof part !== "object")
489
+ return false;
490
+ const p = part;
491
+ if (p.syntheticTodoMarker === true)
492
+ return true;
493
+ return p.type === "tool" && p.tool === "todowrite" && typeof p.callID === "string" && p.callID.startsWith(SYNTHETIC_CALL_ID_PREFIX);
494
+ }
495
+ function parseTodoState(stateJson) {
496
+ if (stateJson.length === 0)
497
+ return null;
498
+ try {
499
+ const parsed = JSON.parse(stateJson);
500
+ if (!Array.isArray(parsed))
501
+ return null;
502
+ const result = [];
503
+ for (const item of parsed) {
504
+ if (!isTodoItem(item))
505
+ return null;
506
+ result.push({
507
+ content: item.content,
508
+ status: item.status,
509
+ priority: item.priority ?? TODO_PRIORITY_MEDIUM
510
+ });
511
+ }
512
+ return result;
513
+ } catch {
514
+ return null;
515
+ }
516
+ }
517
+ function isTodoStatus(value) {
518
+ return typeof value === "string" && TODO_STATUS_SET.has(value);
519
+ }
520
+ function isTodoPriority(value) {
521
+ return typeof value === "string" && TODO_PRIORITY_SET.has(value);
522
+ }
523
+ function isTodoItem(value) {
524
+ if (value === null || typeof value !== "object")
525
+ return false;
526
+ const todo = value;
527
+ return typeof todo.content === "string" && isTodoStatus(todo.status) && (todo.priority === undefined || isTodoPriority(todo.priority));
528
+ }
529
+
530
+ // src/hooks/magic-context/tail-hygiene-walk.ts
531
+ var MAX_CONTENT_MEMO_ENTRIES = 1e5;
532
+ var MAX_CONTENT_MEMO_BYTES = 256 * 1024 * 1024;
533
+ var contentMemo = new Map;
534
+ var contentMemoOrder = new Set;
535
+ var contentMemoBytes = 0;
536
+ var FNV1A_32_OFFSET = 2166136261;
537
+ var FNV1A_32_PRIME = 16777619;
538
+ var TAG_PREFIX = /^§\d+§\s*/;
539
+ var DROP_PREFIXES = ["[dropped", "[truncated"];
540
+ var CHANNEL1_REMINDER_OPEN = `
541
+
542
+ <system-reminder>
543
+ `;
544
+ var CHANNEL1_REMINDER_CLOSE = `
545
+ </system-reminder>`;
546
+ var TODO_HEAD_ANCHOR_ID = "__magic_context_todo_head__";
547
+ function fnv1a32(value) {
548
+ let hash = FNV1A_32_OFFSET;
549
+ for (let index = 0;index < value.length; index += 1) {
550
+ hash ^= value.charCodeAt(index);
551
+ hash = Math.imul(hash, FNV1A_32_PRIME) >>> 0;
552
+ }
553
+ return hash.toString(16).padStart(8, "0");
554
+ }
555
+ function memoizedContent(kind, content) {
556
+ let byContent = contentMemo.get(kind);
557
+ if (!byContent) {
558
+ byContent = new Map;
559
+ contentMemo.set(kind, byContent);
560
+ }
561
+ const cached = byContent.get(content);
562
+ if (cached)
563
+ return cached;
564
+ let hash = FNV1A_32_OFFSET;
565
+ for (const segment of [kind, "\x00", content]) {
566
+ for (let index = 0;index < segment.length; index += 1) {
567
+ hash ^= segment.charCodeAt(index);
568
+ hash = Math.imul(hash, FNV1A_32_PRIME) >>> 0;
569
+ }
570
+ }
571
+ const measured = {
572
+ hash: hash.toString(16).padStart(8, "0"),
573
+ tokens: kind === "excluded" ? 0 : undefined,
574
+ keyBytes: (kind.length + 1 + content.length) * 2 + 32,
575
+ kind,
576
+ content
577
+ };
578
+ byContent.set(content, measured);
579
+ contentMemoOrder.add(measured);
580
+ contentMemoBytes += measured.keyBytes;
581
+ while (contentMemoOrder.size > MAX_CONTENT_MEMO_ENTRIES || contentMemoBytes > MAX_CONTENT_MEMO_BYTES) {
582
+ const oldest = contentMemoOrder.values().next().value;
583
+ if (!oldest)
584
+ break;
585
+ contentMemoBytes -= oldest.keyBytes;
586
+ contentMemo.get(oldest.kind)?.delete(oldest.content);
587
+ contentMemoOrder.delete(oldest);
588
+ }
589
+ return measured;
590
+ }
591
+ function memoizedTokens(kind, content) {
592
+ const measured = memoizedContent(kind, content);
593
+ if (measured.tokens === undefined) {
594
+ measured.tokens = estimateTokens(content);
595
+ }
596
+ return measured.tokens;
597
+ }
598
+ function safeStableStringify(value) {
599
+ if (value === undefined || value === null)
600
+ return "";
601
+ if (typeof value === "string")
602
+ return value;
603
+ try {
604
+ return stableStringify(value);
605
+ } catch {
606
+ return String(value);
607
+ }
608
+ }
609
+ function firstString(record, fields) {
610
+ for (const field of fields) {
611
+ const value = record[field];
612
+ if (typeof value === "string")
613
+ return value;
614
+ }
615
+ return "";
616
+ }
617
+ function callIdFromPart(part) {
618
+ const direct = firstString(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
619
+ if (direct)
620
+ return direct;
621
+ const state = isRecord(part.state) ? part.state : null;
622
+ return state ? firstString(state, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) : "";
623
+ }
624
+ function toolResultCallId(part) {
625
+ return firstString(part, ["tool_use_id", "toolUseId", "callID", "callId"]);
626
+ }
627
+ function messageIdentity(message, messageIndex) {
628
+ return typeof message.info.id === "string" ? message.info.id : `ordinal:${messageIndex}:${message.info.role ?? "unknown"}`;
629
+ }
630
+ function collectToolPartIdentities(messages) {
631
+ const identities = new Map;
632
+ const pendingOwners = new Map;
633
+ for (let messageIndex = 0;messageIndex < messages.length; messageIndex += 1) {
634
+ const message = messages[messageIndex];
635
+ const currentOwner = messageIdentity(message, messageIndex);
636
+ for (const part of message.parts) {
637
+ if (!isRecord(part))
638
+ continue;
639
+ if (part.type === "tool-invocation" || part.type === "tool_use") {
640
+ const callId = callIdFromPart(part);
641
+ if (!callId)
642
+ continue;
643
+ const owners = pendingOwners.get(callId) ?? [];
644
+ owners.push(currentOwner);
645
+ pendingOwners.set(callId, owners);
646
+ identities.set(part, {
647
+ callId,
648
+ ownerMessageId: currentOwner,
649
+ messageIndex,
650
+ kind: "invocation"
651
+ });
652
+ continue;
653
+ }
654
+ if (part.type === "tool_result") {
655
+ const callId = toolResultCallId(part);
656
+ if (!callId)
657
+ continue;
658
+ const owners = pendingOwners.get(callId);
659
+ const ownerMessageId = owners?.shift() ?? currentOwner;
660
+ identities.set(part, {
661
+ callId,
662
+ ownerMessageId,
663
+ messageIndex,
664
+ kind: "result"
665
+ });
666
+ continue;
667
+ }
668
+ if (part.type === "tool") {
669
+ const callId = callIdFromPart(part);
670
+ if (!callId)
671
+ continue;
672
+ identities.set(part, {
673
+ callId,
674
+ ownerMessageId: currentOwner,
675
+ messageIndex,
676
+ kind: "native"
677
+ });
678
+ }
679
+ }
680
+ }
681
+ return identities;
682
+ }
683
+ function isMachineGeneratedUserPart(part) {
684
+ if (!isRecord(part))
685
+ return false;
686
+ const metadata = isRecord(part.metadata) ? part.metadata : null;
687
+ const marker = metadata && isRecord(metadata.marker) ? metadata.marker : null;
688
+ return part.synthetic === true || part.ignored === true || marker?.kind != null || isSyntheticTodoPart(part);
689
+ }
690
+ function isSyntheticMessage(message) {
691
+ const syntheticUserRow = message.info.role === "user" && message.parts.length > 0 && message.parts.every(isMachineGeneratedUserPart);
692
+ return syntheticUserRow || message.info.summary === true || message.info.id === TODO_HEAD_ANCHOR_ID;
693
+ }
694
+ function countRealUserMessages(messages) {
695
+ let count = 0;
696
+ for (const message of messages) {
697
+ if (message.info.role === "user" && !isSyntheticMessage(message))
698
+ count += 1;
699
+ }
700
+ return count;
701
+ }
702
+ function isSyntheticPart(part) {
703
+ return isMachineGeneratedUserPart(part);
704
+ }
705
+ function stripChannel1ReminderSpans(output) {
706
+ let stripped = output;
707
+ while (stripped.endsWith(CHANNEL1_REMINDER_CLOSE)) {
708
+ const opener = stripped.lastIndexOf(CHANNEL1_REMINDER_OPEN);
709
+ if (opener < 0)
710
+ break;
711
+ stripped = stripped.slice(0, opener);
712
+ }
713
+ return stripped;
714
+ }
715
+ function isDropSentinel(content) {
716
+ let stripped = content.trimStart();
717
+ const tag = TAG_PREFIX.exec(stripped);
718
+ if (tag)
719
+ stripped = stripped.slice(tag[0].length).trimStart();
720
+ return DROP_PREFIXES.some((prefix) => stripped.slice(0, prefix.length).toLowerCase() === prefix);
721
+ }
722
+ function toolOutputText(part) {
723
+ if (part.type === "tool") {
724
+ const state = isRecord(part.state) ? part.state : null;
725
+ if (!state)
726
+ return null;
727
+ if (state.output !== undefined)
728
+ return safeStableStringify(state.output);
729
+ if (state.error !== undefined)
730
+ return safeStableStringify(state.error);
731
+ if (state.result !== undefined)
732
+ return safeStableStringify(state.result);
733
+ return null;
734
+ }
735
+ if (part.type === "tool_result") {
736
+ const value = part.content ?? part.output ?? part.result;
737
+ return value === undefined ? null : safeStableStringify(value);
738
+ }
739
+ return null;
740
+ }
741
+ function toolInputText(part) {
742
+ if (part.type === "tool") {
743
+ const state = isRecord(part.state) ? part.state : null;
744
+ if (!state || state.input === undefined)
745
+ return null;
746
+ return safeStableStringify(state.input);
747
+ }
748
+ if (part.type === "tool-invocation") {
749
+ const value = part.args ?? part.input;
750
+ return value === undefined ? null : safeStableStringify(value);
751
+ }
752
+ if (part.type === "tool_use") {
753
+ return part.input === undefined ? null : safeStableStringify(part.input);
754
+ }
755
+ return null;
756
+ }
757
+ function messageIdForTag(tag) {
758
+ if (tag.type === "tool")
759
+ return tag.toolOwnerMessageId;
760
+ return contentTagOwnerMessageId(tag.messageId);
761
+ }
762
+ function resolveProtectedTagNumbers(tags, protectedTagNumbersInput, protectedToolTags) {
763
+ const protectedNumbers = new Set(protectedTagNumbersInput);
764
+ const protectedCtxReduceTags = protectedToolTags ?? protectedToolTagNumbers(tags);
765
+ for (const tagNumber of protectedCtxReduceTags)
766
+ protectedNumbers.add(tagNumber);
767
+ return protectedNumbers;
768
+ }
769
+ function neighborhoodConsistent(args) {
770
+ let previousMax = null;
771
+ for (let index = 0;index <= args.messageIndex; index += 1) {
772
+ const bound = args.boundsByMessageIndex.get(index);
773
+ if (bound)
774
+ previousMax = previousMax === null ? bound.max : Math.max(previousMax, bound.max);
775
+ }
776
+ let nextMin = null;
777
+ for (let index = args.messageIndex + 1;index < args.messageCount; index += 1) {
778
+ const bound = args.boundsByMessageIndex.get(index);
779
+ if (bound)
780
+ nextMin = nextMin === null ? bound.min : Math.min(nextMin, bound.min);
781
+ }
782
+ if (previousMax === null || nextMin === null)
783
+ return false;
784
+ return args.orphanTagNumber >= previousMax && args.orphanTagNumber <= nextMin;
785
+ }
786
+ function buildTagAttribution(args) {
787
+ const protectedNumbers = resolveProtectedTagNumbers(args.tags, args.protectedTagNumbers, args.protectedToolTags);
788
+ const messageTags = new Map;
789
+ const exactToolTags = new Map;
790
+ const orphanTagsByCall = new Map;
791
+ const messageIndexById = new Map;
792
+ for (let index = 0;index < args.messages.length; index += 1) {
793
+ const id = args.messages[index].info.id;
794
+ if (typeof id === "string")
795
+ messageIndexById.set(id, index);
796
+ }
797
+ const boundsByMessageIndex = new Map;
798
+ for (const tag of args.tags) {
799
+ if (tag.type === "tool") {
800
+ if (tag.toolOwnerMessageId === null) {
801
+ const rows = orphanTagsByCall.get(tag.messageId) ?? [];
802
+ rows.push(tag);
803
+ orphanTagsByCall.set(tag.messageId, rows);
804
+ } else {
805
+ exactToolTags.set(`${tag.toolOwnerMessageId}\x00${tag.messageId}`, tag);
806
+ }
807
+ } else {
808
+ messageTags.set(tag.messageId, tag);
809
+ }
810
+ const ownerId = messageIdForTag(tag);
811
+ const index = ownerId === null ? undefined : messageIndexById.get(ownerId);
812
+ if (index === undefined)
813
+ continue;
814
+ const existing = boundsByMessageIndex.get(index);
815
+ boundsByMessageIndex.set(index, {
816
+ min: existing ? Math.min(existing.min, tag.tagNumber) : tag.tagNumber,
817
+ max: existing ? Math.max(existing.max, tag.tagNumber) : tag.tagNumber
818
+ });
819
+ }
820
+ const toolTagsByPart = new Map;
821
+ const orphanCandidateOwners = new Map;
822
+ for (const [part, identity] of args.toolIdentities) {
823
+ const exact = exactToolTags.get(`${identity.ownerMessageId}\x00${identity.callId}`);
824
+ if (exact) {
825
+ toolTagsByPart.set(part, exact);
826
+ continue;
827
+ }
828
+ const orphans = orphanTagsByCall.get(identity.callId);
829
+ if (orphans?.length !== 1)
830
+ continue;
831
+ if (!neighborhoodConsistent({
832
+ orphanTagNumber: orphans[0].tagNumber,
833
+ messageIndex: identity.messageIndex,
834
+ boundsByMessageIndex,
835
+ messageCount: args.messages.length
836
+ })) {
837
+ continue;
838
+ }
839
+ const byOwner = orphanCandidateOwners.get(identity.callId) ?? new Map;
840
+ const ownerParts = byOwner.get(identity.ownerMessageId) ?? [];
841
+ ownerParts.push(identity);
842
+ byOwner.set(identity.ownerMessageId, ownerParts);
843
+ orphanCandidateOwners.set(identity.callId, byOwner);
844
+ }
845
+ for (const [callId, byOwner] of orphanCandidateOwners) {
846
+ if (byOwner.size !== 1)
847
+ continue;
848
+ const orphan = orphanTagsByCall.get(callId)?.[0];
849
+ if (!orphan)
850
+ continue;
851
+ const ownerId = byOwner.keys().next().value;
852
+ if (typeof ownerId !== "string")
853
+ continue;
854
+ for (const [part, identity] of args.toolIdentities) {
855
+ if (identity.callId === callId && identity.ownerMessageId === ownerId) {
856
+ toolTagsByPart.set(part, orphan);
857
+ }
858
+ }
859
+ }
860
+ return { protectedNumbers, messageTags, toolTagsByPart };
861
+ }
862
+ function snapshot(args) {
863
+ const memo = memoizedContent(args.kind, args.content);
864
+ const tag = args.tag;
865
+ const isProtected = tag ? args.protectedNumbers.has(tag.tagNumber) : false;
866
+ const queuedForDrop = tag ? args.pendingDropTagNumbers.has(tag.tagNumber) : false;
867
+ const uTokens = tag?.status === "active" && !isProtected && !queuedForDrop && args.kind !== "excluded" ? args.tokens : 0;
868
+ return {
869
+ key: args.key,
870
+ contentHash: memo.hash,
871
+ kind: args.kind,
872
+ tokens: args.tokens,
873
+ uTokens,
874
+ tagNumber: tag?.tagNumber ?? null,
875
+ tagStatus: tag?.status ?? null,
876
+ protected: isProtected,
877
+ queuedForDrop
878
+ };
879
+ }
880
+ function excludedSnapshot(key, part) {
881
+ const content = safeStableStringify(part);
882
+ return snapshot({
883
+ key,
884
+ kind: "excluded",
885
+ content,
886
+ tokens: 0,
887
+ tag: undefined,
888
+ protectedNumbers: new Set,
889
+ pendingDropTagNumbers: new Set
890
+ });
891
+ }
892
+ function fileContentAndTokens(part) {
893
+ const mime = typeof part.mime === "string" ? part.mime : "";
894
+ const type = typeof part.type === "string" ? part.type.toLowerCase() : "";
895
+ const url = typeof part.url === "string" ? part.url : "";
896
+ if (mime.startsWith("image/") || type.includes("image")) {
897
+ return {
898
+ content: url,
899
+ tokens: url.startsWith("data:") ? estimateImageTokensFromDataUrl(url) : 1200
900
+ };
901
+ }
902
+ const content = firstString(part, ["content", "text", "source", "url"]);
903
+ const tokens = memoizedTokens("file", content);
904
+ return { content, tokens };
905
+ }
906
+ function contentSignature(parts) {
907
+ return fnv1a32(parts.map((part) => `${part.key}:${part.contentHash}`).join("\x00"));
908
+ }
909
+ function structuralSize(value) {
910
+ if (typeof value === "string")
911
+ return value.length;
912
+ if (Array.isArray(value)) {
913
+ let size = value.length;
914
+ for (let index = 0;index < value.length; index += 1) {
915
+ size += structuralSize(value[index]);
916
+ }
917
+ return size;
918
+ }
919
+ if (value !== null && typeof value === "object") {
920
+ let size = 0;
921
+ for (const key in value) {
922
+ if (Object.hasOwn(value, key)) {
923
+ size += 1 + structuralSize(value[key]);
924
+ }
925
+ }
926
+ return size;
927
+ }
928
+ return 0;
929
+ }
930
+ function tailHygieneStructuralSignature(messages) {
931
+ const partCounts = [];
932
+ let totalBytes = 0;
933
+ for (const message of messages) {
934
+ partCounts.push(message.parts.length);
935
+ totalBytes += structuralSize(providerVisibleMessage(message));
936
+ }
937
+ return { messageCount: messages.length, partCounts, totalBytes };
938
+ }
939
+ function sameTailHygieneStructuralSignature(expected, actual) {
940
+ if (expected.messageCount !== actual.messageCount || expected.totalBytes !== actual.totalBytes || expected.partCounts.length !== actual.partCounts.length) {
941
+ return false;
942
+ }
943
+ return expected.partCounts.every((count, index) => count === actual.partCounts[index]);
944
+ }
945
+ function measureTailHygiene(input) {
946
+ return measureWithReplay(input);
947
+ }
948
+ function measureWithReplay(input, replay) {
949
+ const pendingDropTagNumbers = input.pendingDropTagNumbers ?? new Set;
950
+ const unchanged = input.messages.map((message, index) => {
951
+ const previous = replay?.messages[index];
952
+ return previous !== undefined && sameReplayMessage(previous, message);
953
+ });
954
+ const toolIdentities = collectToolPartIdentities(input.messages);
955
+ const attribution = buildTagAttribution({
956
+ messages: input.messages,
957
+ tags: input.tags,
958
+ toolIdentities,
959
+ protectedTagNumbers: input.protectedTagNumbers,
960
+ protectedToolTags: input.protectedToolTags
961
+ });
962
+ const toolOutputs = input.messages.map((message, index) => message.parts.map((part, partIndex) => unchanged[index] ? replay?.measured.toolOutputs[index][partIndex] ?? null : isRecord(part) ? toolOutputText(part) : null));
963
+ const outputByPart = new Map;
964
+ input.messages.forEach((message, index) => {
965
+ message.parts.forEach((part, partIndex) => {
966
+ outputByPart.set(part, toolOutputs[index][partIndex]);
967
+ });
968
+ });
969
+ const droppedToolOwners = new Set;
970
+ for (const [part, identity] of toolIdentities) {
971
+ if (!isRecord(part))
972
+ continue;
973
+ const output = outputByPart.get(part) ?? null;
974
+ if (output !== null && isDropSentinel(output)) {
975
+ droppedToolOwners.add(`${identity.ownerMessageId}\x00${identity.callId}`);
976
+ }
977
+ }
978
+ const parts = [];
979
+ let t = 0;
980
+ let u = 0;
981
+ let newestMessagePartStart = 0;
982
+ const messagePartStarts = [];
983
+ for (let messageIndex = 0;messageIndex < input.messages.length; messageIndex += 1) {
984
+ const message = input.messages[messageIndex];
985
+ messagePartStarts.push(parts.length);
986
+ if (messageIndex === input.messages.length - 1)
987
+ newestMessagePartStart = parts.length;
988
+ const messageKey = messageIdentity(message, messageIndex);
989
+ const priorMessage = replay?.messages[messageIndex];
990
+ const reusable = unchanged[messageIndex] && priorMessage && message.parts.every((part, index) => {
991
+ const current = toolIdentities.get(part);
992
+ const prior = replay?.measured.toolOwners.get(priorMessage.parts[index]);
993
+ if (!current || !prior)
994
+ return current === prior;
995
+ const currentKey = `${current.ownerMessageId}\x00${current.callId}`;
996
+ const priorKey = `${prior.ownerMessageId}\x00${prior.callId}`;
997
+ return currentKey === priorKey && droppedToolOwners.has(currentKey) === replay?.measured.droppedToolOwners.has(priorKey);
998
+ });
999
+ if (reusable && replay) {
1000
+ const start = replay.measured.messagePartStarts[messageIndex];
1001
+ const end = replay.measured.messagePartStarts[messageIndex + 1] ?? replay.measured.parts.length;
1002
+ for (let index = start;index < end; index += 1) {
1003
+ const prior = replay.measured.parts[index];
1004
+ const partIndex = Number(prior.key.slice(messageKey.length + 1).split("\x00")[0]);
1005
+ const tag = prior.kind === "text" ? attribution.messageTags.get(`${message.info.id}:p${partIndex}`) : prior.kind === "file" ? attribution.messageTags.get(`${message.info.id}:file${partIndex}`) : prior.kind === "toolInput" || prior.kind === "toolOutput" ? attribution.toolTagsByPart.get(message.parts[partIndex]) : undefined;
1006
+ const protectedPart = tag ? attribution.protectedNumbers.has(tag.tagNumber) : false;
1007
+ const queuedForDrop = tag ? pendingDropTagNumbers.has(tag.tagNumber) : false;
1008
+ const uTokens = tag?.status === "active" && !protectedPart && !queuedForDrop && prior.kind !== "excluded" ? prior.tokens : 0;
1009
+ const measured = prior.tagNumber === (tag?.tagNumber ?? null) && prior.tagStatus === (tag?.status ?? null) && prior.protected === protectedPart && prior.queuedForDrop === queuedForDrop && prior.uTokens === uTokens ? prior : {
1010
+ ...prior,
1011
+ tagNumber: tag?.tagNumber ?? null,
1012
+ tagStatus: tag?.status ?? null,
1013
+ protected: protectedPart,
1014
+ queuedForDrop,
1015
+ uTokens
1016
+ };
1017
+ parts.push(measured);
1018
+ t += measured.tokens;
1019
+ u += measured.uTokens;
1020
+ }
1021
+ continue;
1022
+ }
1023
+ const messageSynthetic = isSyntheticMessage(message);
1024
+ for (let partIndex = 0;partIndex < message.parts.length; partIndex += 1) {
1025
+ const part = message.parts[partIndex];
1026
+ const key = `${messageKey}\x00${partIndex}`;
1027
+ if (messageSynthetic || isSyntheticPart(part) || !isRecord(part)) {
1028
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1029
+ continue;
1030
+ }
1031
+ const type = typeof part.type === "string" ? part.type : "";
1032
+ if (type === "reasoning" || type === "thinking" || type === "redacted_thinking" || type === "signature") {
1033
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1034
+ continue;
1035
+ }
1036
+ if (type === "text") {
1037
+ const rawContent = firstString(part, ["text", "content"]);
1038
+ const content = rawContent === null ? null : stripChannel1ReminderSpans(rawContent);
1039
+ if (!content || isDropSentinel(content)) {
1040
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1041
+ continue;
1042
+ }
1043
+ const tokens = memoizedTokens("text", content);
1044
+ const tag = attribution.messageTags.get(`${message.info.id}:p${partIndex}`);
1045
+ const measured = snapshot({
1046
+ key: `${key}\x00text`,
1047
+ kind: "text",
1048
+ content,
1049
+ tokens,
1050
+ tag,
1051
+ protectedNumbers: attribution.protectedNumbers,
1052
+ pendingDropTagNumbers
1053
+ });
1054
+ parts.push(measured);
1055
+ t += measured.tokens;
1056
+ u += measured.uTokens;
1057
+ continue;
1058
+ }
1059
+ if (type === "file" || type.includes("image") || type === "source") {
1060
+ const file = fileContentAndTokens(part);
1061
+ if (!file.content || isDropSentinel(file.content)) {
1062
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1063
+ continue;
1064
+ }
1065
+ const tag = attribution.messageTags.get(`${message.info.id}:file${partIndex}`);
1066
+ const measured = snapshot({
1067
+ key: `${key}\x00file`,
1068
+ kind: "file",
1069
+ content: file.content,
1070
+ tokens: file.tokens,
1071
+ tag,
1072
+ protectedNumbers: attribution.protectedNumbers,
1073
+ pendingDropTagNumbers
1074
+ });
1075
+ parts.push(measured);
1076
+ t += measured.tokens;
1077
+ u += measured.uTokens;
1078
+ continue;
1079
+ }
1080
+ const toolIdentity = toolIdentities.get(part);
1081
+ if (toolIdentity) {
1082
+ const ownerKey = `${toolIdentity.ownerMessageId}\x00${toolIdentity.callId}`;
1083
+ if (droppedToolOwners.has(ownerKey)) {
1084
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1085
+ continue;
1086
+ }
1087
+ const tag = attribution.toolTagsByPart.get(part);
1088
+ const inputText = toolInputText(part);
1089
+ if (inputText !== null) {
1090
+ const tokens = memoizedTokens("toolInput", inputText);
1091
+ const measured = snapshot({
1092
+ key: `${key}\x00toolInput`,
1093
+ kind: "toolInput",
1094
+ content: inputText,
1095
+ tokens,
1096
+ tag,
1097
+ protectedNumbers: attribution.protectedNumbers,
1098
+ pendingDropTagNumbers
1099
+ });
1100
+ parts.push(measured);
1101
+ t += measured.tokens;
1102
+ u += measured.uTokens;
1103
+ }
1104
+ const rawOutput = outputByPart.get(part) ?? null;
1105
+ if (rawOutput !== null) {
1106
+ const output = stripChannel1ReminderSpans(rawOutput);
1107
+ if (isDropSentinel(output)) {
1108
+ parts.push(excludedSnapshot(`${key}\x00excludedOutput`, output));
1109
+ } else {
1110
+ const tokens = memoizedTokens("toolOutput", output) + (part.type === "tool" ? estimateToolAttachmentImageTokens(part.state) : 0);
1111
+ const measured = snapshot({
1112
+ key: `${key}\x00toolOutput`,
1113
+ kind: "toolOutput",
1114
+ content: output,
1115
+ tokens,
1116
+ tag,
1117
+ protectedNumbers: attribution.protectedNumbers,
1118
+ pendingDropTagNumbers
1119
+ });
1120
+ parts.push(measured);
1121
+ t += measured.tokens;
1122
+ u += measured.uTokens;
1123
+ }
1124
+ }
1125
+ if (inputText === null && rawOutput === null) {
1126
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1127
+ }
1128
+ continue;
1129
+ }
1130
+ parts.push(excludedSnapshot(`${key}\x00excluded`, part));
1131
+ }
1132
+ }
1133
+ return {
1134
+ u: Math.min(Math.max(0, u), Math.max(0, t)),
1135
+ t: Math.max(0, t),
1136
+ contentSignature: contentSignature(parts),
1137
+ parts,
1138
+ newestMessagePartStart,
1139
+ messagePartStarts,
1140
+ toolOutputs,
1141
+ toolOwners: toolIdentities,
1142
+ droppedToolOwners
1143
+ };
1144
+ }
1145
+ function messageIdFromPartKey(key) {
1146
+ const separator = key.indexOf("\x00");
1147
+ return separator > 0 ? key.slice(0, separator) : key;
1148
+ }
1149
+ function prefixMismatch(baseline, current, partIndex, field) {
1150
+ return {
1151
+ valid: false,
1152
+ boundaryAdvanceU: 0,
1153
+ queuedDropDeltaU: 0,
1154
+ mismatch: {
1155
+ partIndex,
1156
+ messageId: messageIdFromPartKey(baseline[partIndex]?.key ?? ""),
1157
+ field,
1158
+ frozenParts: baseline.length,
1159
+ measuredParts: current.length
1160
+ }
1161
+ };
1162
+ }
1163
+ function compareMeasuredTailPrefix(baseline, current) {
1164
+ if (current.length < baseline.length) {
1165
+ return prefixMismatch(baseline, current, current.length, "shorter");
1166
+ }
1167
+ let boundaryAdvanceU = 0;
1168
+ let queuedDropDeltaU = 0;
1169
+ for (let index = 0;index < baseline.length; index += 1) {
1170
+ const before = baseline[index];
1171
+ const after = current[index];
1172
+ const changedField = comparedField(before, after);
1173
+ if (changedField)
1174
+ return prefixMismatch(baseline, current, index, changedField);
1175
+ if (before.protected && !after.protected) {
1176
+ boundaryAdvanceU += after.uTokens;
1177
+ } else if (before.queuedForDrop !== after.queuedForDrop) {
1178
+ queuedDropDeltaU += after.uTokens - before.uTokens;
1179
+ }
1180
+ }
1181
+ return { valid: true, boundaryAdvanceU, queuedDropDeltaU };
1182
+ }
1183
+ function comparedField(before, after) {
1184
+ if (before.key !== after.key)
1185
+ return "key";
1186
+ if (before.contentHash !== after.contentHash)
1187
+ return "contentHash";
1188
+ if (before.kind !== after.kind)
1189
+ return "kind";
1190
+ if (before.tokens !== after.tokens)
1191
+ return "tokens";
1192
+ if (before.tagNumber !== after.tagNumber)
1193
+ return "tagNumber";
1194
+ if (before.tagStatus !== after.tagStatus)
1195
+ return "tagStatus";
1196
+ if (!before.protected && after.protected)
1197
+ return "protection-entered";
1198
+ if (before.protected && !after.protected) {
1199
+ return after.tagStatus === "active" ? null : "protection-exit-inactive";
1200
+ }
1201
+ if (before.queuedForDrop !== after.queuedForDrop) {
1202
+ return before.tagStatus === "active" && after.tagStatus === "active" ? null : "queued-drop-inactive";
1203
+ }
1204
+ return before.uTokens === after.uTokens ? null : "uTokens";
1205
+ }
1206
+ function formatTailHygienePrefixMismatch(mismatch, baselineGeneration) {
1207
+ return [
1208
+ "tail hygiene prefix invalidated:",
1209
+ `part_index=${mismatch.partIndex}`,
1210
+ `message=${mismatch.messageId || "unknown"}`,
1211
+ `field=${mismatch.field}`,
1212
+ `frozen_parts=${mismatch.frozenParts}`,
1213
+ `measured_parts=${mismatch.measuredParts}`,
1214
+ "action=re-measured",
1215
+ `generation=${baselineGeneration}`
1216
+ ].join(" ");
1217
+ }
1218
+ function sameReplayValue(before, after) {
1219
+ if (before === after)
1220
+ return true;
1221
+ if (!before || !after || typeof before !== "object" || typeof after !== "object") {
1222
+ return false;
1223
+ }
1224
+ if (Array.isArray(before)) {
1225
+ if (!Array.isArray(after) || before.length !== after.length)
1226
+ return false;
1227
+ for (let index = 0;index < before.length; index += 1) {
1228
+ if (!sameReplayValue(before[index], after[index]))
1229
+ return false;
1230
+ }
1231
+ return true;
1232
+ }
1233
+ if (Array.isArray(after))
1234
+ return false;
1235
+ const prototype = Object.getPrototypeOf(before);
1236
+ if (prototype !== Object.prototype && prototype !== null || Object.getPrototypeOf(after) !== prototype)
1237
+ return false;
1238
+ const left = before;
1239
+ const right = after;
1240
+ const keys = Object.keys(left);
1241
+ if (keys.length !== Object.keys(right).length)
1242
+ return false;
1243
+ for (const key of keys) {
1244
+ if (!Object.hasOwn(right, key) || !sameReplayValue(left[key], right[key]))
1245
+ return false;
1246
+ }
1247
+ return true;
1248
+ }
1249
+ function copyReplayValue(value) {
1250
+ if (Array.isArray(value))
1251
+ return value.map(copyReplayValue);
1252
+ if (value !== null && typeof value === "object") {
1253
+ const prototype = Object.getPrototypeOf(value);
1254
+ if (prototype !== Object.prototype && prototype !== null)
1255
+ return structuredClone(value);
1256
+ const copy = Object.create(prototype);
1257
+ for (const key of Object.keys(value))
1258
+ copy[key] = copyReplayValue(value[key]);
1259
+ return copy;
1260
+ }
1261
+ return value;
1262
+ }
1263
+ function sameNumbers(before, after) {
1264
+ if (before.size !== after.size)
1265
+ return false;
1266
+ for (const number of before)
1267
+ if (!after.has(number))
1268
+ return false;
1269
+ return true;
1270
+ }
1271
+ function sameReplayMessage(left, right) {
1272
+ return left.info.id === right.info.id && left.info.role === right.info.role && left.info.summary === right.info.summary && sameReplayValue(left.parts, right.parts.map(providerVisiblePart));
1273
+ }
1274
+ function replaySnapshotParts(parts) {
1275
+ return copyReplayValue(parts.map(providerVisiblePart));
1276
+ }
1277
+ function sameReplayMessages(before, after) {
1278
+ if (before.length !== after.length)
1279
+ return false;
1280
+ for (let index = 0;index < before.length; index += 1) {
1281
+ const left = before[index];
1282
+ const right = after[index];
1283
+ if (!sameReplayMessage(left, right))
1284
+ return false;
1285
+ }
1286
+ return true;
1287
+ }
1288
+ var baselineMeasurementMemo = new Map;
1289
+ var MAX_BASELINE_MEMO_SIZE = 128 * 1024 * 1024;
1290
+ var baselineMemoSize = 0;
1291
+ function retainBaselineMeasurement(key, memo) {
1292
+ const previous = baselineMeasurementMemo.get(key);
1293
+ if (previous)
1294
+ baselineMemoSize -= previous.size;
1295
+ baselineMeasurementMemo.delete(key);
1296
+ if (memo.size > MAX_BASELINE_MEMO_SIZE)
1297
+ return;
1298
+ baselineMeasurementMemo.set(key, memo);
1299
+ baselineMemoSize += memo.size;
1300
+ while (baselineMemoSize > MAX_BASELINE_MEMO_SIZE || baselineMeasurementMemo.size > 8) {
1301
+ const oldest = baselineMeasurementMemo.keys().next().value;
1302
+ if (!oldest)
1303
+ break;
1304
+ baselineMemoSize -= baselineMeasurementMemo.get(oldest)?.size ?? 0;
1305
+ baselineMeasurementMemo.delete(oldest);
1306
+ }
1307
+ }
1308
+ function freezeTailHygieneMeasurement(measured) {
1309
+ const cut = Math.min(Math.max(0, measured.newestMessagePartStart), measured.parts.length);
1310
+ let baselineT = 0;
1311
+ let baselineU = 0;
1312
+ for (let index = 0;index < cut; index += 1) {
1313
+ baselineT += measured.parts[index].tokens;
1314
+ baselineU += measured.parts[index].uTokens;
1315
+ }
1316
+ let turnDeltaT = 0;
1317
+ let turnDeltaU = 0;
1318
+ for (let index = cut;index < measured.parts.length; index += 1) {
1319
+ const part = measured.parts[index];
1320
+ turnDeltaT += part.tokens;
1321
+ if (part.kind !== "toolOutput" || !part.protected)
1322
+ turnDeltaU += part.uTokens;
1323
+ }
1324
+ baselineT = Math.max(0, baselineT);
1325
+ return {
1326
+ baselineU: Math.min(Math.max(0, baselineU), baselineT),
1327
+ baselineT,
1328
+ turnDeltaU,
1329
+ turnDeltaT,
1330
+ baselineParts: cut === measured.parts.length ? measured.parts : measured.parts.slice(0, cut)
1331
+ };
1332
+ }
1333
+ function refreshTailHygieneBaseline(input) {
1334
+ const protectedToolsPolicy = adoptedProtectedToolsPolicy(input.protectedTools, input.previous?.protectedToolsPolicy, input.cacheBusting, !!input.previous);
1335
+ const protectedToolTags = protectedToolTagNumbers(input.tags, protectedToolsPolicy);
1336
+ input = {
1337
+ ...input,
1338
+ protectedToolTags,
1339
+ protectedTagNumbers: new Set([...input.protectedTagNumbers, ...protectedToolTags])
1340
+ };
1341
+ const pendingDropTagNumbers = input.pendingDropTagNumbers ?? new Set;
1342
+ const cached = input.previous ? baselineMeasurementMemo.get(input.previous.baselineParts) : undefined;
1343
+ const hit = !input.cacheBusting && cached && sameReplayMessages(cached.messages, input.messages) && sameReplayValue(cached.tags, input.tags) && sameNumbers(cached.protectedTagNumbers, input.protectedTagNumbers) && sameNumbers(cached.pendingDropTagNumbers, pendingDropTagNumbers);
1344
+ const rawMeasured = hit ? cached.measured : measureWithReplay(input, cached);
1345
+ const frozenCalibration = !input.cacheBusting && input.previous ? {
1346
+ toolsRatio: input.previous.toolsRatio,
1347
+ proseRatio: input.previous.proseRatio,
1348
+ hygieneUnitsVersion: input.previous.hygieneUnitsVersion
1349
+ } : {
1350
+ toolsRatio: input.calibration?.toolsRatio ?? 1,
1351
+ proseRatio: input.calibration?.proseRatio ?? 1,
1352
+ hygieneUnitsVersion: input.hygieneUnitsVersion ?? 1
1353
+ };
1354
+ const ratioFor = (kind) => kind === "toolInput" || kind === "toolOutput" ? frozenCalibration.toolsRatio : kind === "text" || kind === "file" ? frozenCalibration.proseRatio : 1;
1355
+ const measured = {
1356
+ ...rawMeasured,
1357
+ parts: rawMeasured.parts.map((part) => {
1358
+ const ratio = ratioFor(part.kind);
1359
+ return { ...part, tokens: part.tokens * ratio, uTokens: part.uTokens * ratio };
1360
+ })
1361
+ };
1362
+ const memo = hit ? cached : {
1363
+ messages: input.messages.map((message, index) => cached?.messages[index] && sameReplayMessage(cached.messages[index], message) ? cached.messages[index] : {
1364
+ info: {
1365
+ id: message.info.id,
1366
+ role: message.info.role,
1367
+ summary: message.info.summary
1368
+ },
1369
+ parts: replaySnapshotParts(message.parts)
1370
+ }),
1371
+ tags: structuredClone(input.tags),
1372
+ protectedTagNumbers: new Set(input.protectedTagNumbers),
1373
+ pendingDropTagNumbers: new Set(pendingDropTagNumbers),
1374
+ measured: rawMeasured,
1375
+ size: 2 * structuralSize(input.messages.map(providerVisibleMessage)) + 512 * input.tags.length
1376
+ };
1377
+ if (!hit) {
1378
+ const owners = new Map;
1379
+ input.messages.forEach((message, index) => {
1380
+ message.parts.forEach((part, partIndex) => {
1381
+ const identity = rawMeasured.toolOwners.get(part);
1382
+ if (identity)
1383
+ owners.set(memo.messages[index].parts[partIndex], identity);
1384
+ });
1385
+ });
1386
+ rawMeasured.toolOwners = owners;
1387
+ }
1388
+ const now = input.now ?? Date.now();
1389
+ const refrozen = (mismatch) => {
1390
+ const frozen = freezeTailHygieneMeasurement(measured);
1391
+ retainBaselineMeasurement(frozen.baselineParts, memo);
1392
+ return {
1393
+ ...frozen,
1394
+ protectedToolsPolicy,
1395
+ hygieneUnitsVersion: frozenCalibration.hygieneUnitsVersion,
1396
+ toolsRatio: frozenCalibration.toolsRatio,
1397
+ proseRatio: frozenCalibration.proseRatio,
1398
+ baselineGeneration: (input.previous?.baselineGeneration ?? 0) + 1,
1399
+ computedAt: now,
1400
+ evaluable: true,
1401
+ generationInvalidated: false,
1402
+ contentSignature: measured.contentSignature,
1403
+ channel1PostReduceGrace: input.previous?.channel1PostReduceGrace,
1404
+ lastPrefixMismatch: mismatch
1405
+ };
1406
+ };
1407
+ if (input.cacheBusting || !input.previous)
1408
+ return refrozen();
1409
+ const prefix = compareMeasuredTailPrefix(input.previous.baselineParts, measured.parts);
1410
+ if (!prefix.valid)
1411
+ return refrozen(prefix.mismatch);
1412
+ retainBaselineMeasurement(input.previous.baselineParts, memo);
1413
+ let turnDeltaT = 0;
1414
+ let turnDeltaU = prefix.boundaryAdvanceU + prefix.queuedDropDeltaU;
1415
+ for (let index = input.previous.baselineParts.length;index < measured.parts.length; index += 1) {
1416
+ const part = measured.parts[index];
1417
+ turnDeltaT += part.tokens;
1418
+ if (part.kind !== "toolOutput" || !part.protected)
1419
+ turnDeltaU += part.uTokens;
1420
+ }
1421
+ return {
1422
+ ...input.previous,
1423
+ protectedToolsPolicy,
1424
+ turnDeltaU,
1425
+ turnDeltaT,
1426
+ evaluable: true,
1427
+ generationInvalidated: false,
1428
+ contentSignature: measured.contentSignature,
1429
+ lastPrefixMismatch: undefined
1430
+ };
1431
+ }
1432
+ function effectiveTailHygiene(baseline) {
1433
+ const t = Math.ceil(Math.max(0, baseline.baselineT + baseline.turnDeltaT));
1434
+ const u = Math.min(t, Math.ceil(Math.max(0, baseline.baselineU + baseline.turnDeltaU)));
1435
+ return { u, t };
1436
+ }
1437
+ function assertTailHygieneContentUnchanged(input) {
1438
+ const actual = measureTailHygiene(input).contentSignature;
1439
+ if (actual !== input.expectedSignature) {
1440
+ throw new Error(`tail hygiene walk was not the last byte-affecting operation: expected ${input.expectedSignature}, got ${actual}`);
1441
+ }
1442
+ }
1443
+ function assertTailHygieneContentUnchangedIfEnabled(input) {
1444
+ if (process.env.MAGIC_CONTEXT_DEBUG_ASSERTIONS === "1") {
1445
+ assertTailHygieneContentUnchanged(input);
1446
+ }
1447
+ }
1448
+
1449
+ // src/hooks/magic-context/ctx-reduce-nudge.ts
1450
+ var CHANNEL1_SENTINEL = "<system-reminder>";
1451
+ var TOKENS_PER_BYTE = 0.25;
1452
+ var CHANNEL1_MIN_TOKENS = 60000;
1453
+ var CHANNEL1_FLOOR_TOKENS = 25000;
1454
+ var CHANNEL1_REFIRE_FLOOR_TOKENS = 25000;
1455
+ var S_GENTLE = 0.2;
1456
+ var S_FIRM = 0.4;
1457
+ var S_URGENT = 0.6;
1458
+ var CHANNEL2_SEVERITY_THRESHOLD = 0.75;
1459
+ var CHANNEL2_FLOOR_TOKENS = 50000;
1460
+ var LEVEL_RANK = { gentle: 1, firm: 2, urgent: 3 };
1461
+ var DROP_SENTINELS = ["[dropped", "[truncated"];
1462
+ function channel1RefireTokens(tailTokens) {
1463
+ const scaled = Math.round(0.08 * Math.max(0, tailTokens));
1464
+ return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
1465
+ }
1466
+ function isDroppedToolOutput(output) {
1467
+ const head = output.trimStart().replace(/^§\d+§\s*/, "").slice(0, 16).toLowerCase();
1468
+ return DROP_SENTINELS.some((sentinel) => head.startsWith(sentinel));
1469
+ }
1470
+ function toolOutputTokens(output) {
1471
+ return estimateTokens(stripChannel1ReminderSpans(output));
1472
+ }
1473
+ function channel1Band(undroppedTokens, tailTokens) {
1474
+ if (tailTokens < CHANNEL1_MIN_TOKENS || undroppedTokens < CHANNEL1_FLOOR_TOKENS) {
1475
+ return "quiet";
1476
+ }
1477
+ const severity = Math.min(1, Math.max(0, undroppedTokens / Math.max(tailTokens, 1)));
1478
+ if (severity >= S_URGENT)
1479
+ return "urgent";
1480
+ if (severity >= S_FIRM)
1481
+ return "firm";
1482
+ if (severity >= S_GENTLE)
1483
+ return "gentle";
1484
+ return "quiet";
1485
+ }
1486
+ function nudgeBand(undroppedTokens, tailTokens) {
1487
+ const base = channel1Band(undroppedTokens, tailTokens);
1488
+ const severity = Math.min(1, Math.max(0, undroppedTokens / Math.max(tailTokens, 1)));
1489
+ return base === "urgent" && undroppedTokens >= CHANNEL2_FLOOR_TOKENS && severity >= CHANNEL2_SEVERITY_THRESHOLD ? "channel2" : base;
1490
+ }
1491
+ function decideChannel1(input) {
1492
+ const tailTokens = Math.max(0, input.baselineT + input.turnDeltaT);
1493
+ const undroppedTokens = Math.min(tailTokens, Math.max(0, input.baselineU + input.turnDeltaU));
1494
+ const severity = Math.min(1, Math.max(0, undroppedTokens / Math.max(tailTokens, 1)));
1495
+ const previousLevel = input.lastNudgeLevel;
1496
+ let lastNudge = Math.max(0, input.lastNudgeUndropped);
1497
+ let nextLevel = previousLevel;
1498
+ let clearPostReduceGrace = false;
1499
+ const growthThreshold = channel1RefireTokens(tailTokens);
1500
+ const graceBaselineU = input.postReduceGraceBaselineU === undefined ? null : Math.max(0, input.postReduceGraceBaselineU);
1501
+ const graceGrowth = graceBaselineU === null ? 0 : undroppedTokens - graceBaselineU;
1502
+ const cadenceGrowth = undroppedTokens - lastNudge;
1503
+ const currentTurn = input.currentRealUserTurnCount;
1504
+ const lastFireTurn = input.lastFireOrdinal;
1505
+ const stickyTurnsRemaining = currentTurn === undefined || lastFireTurn === undefined || lastFireTurn > currentTurn ? 0 : Math.max(0, CHANNEL1_STICKY_REAL_USER_TURN_GAP - (currentTurn - lastFireTurn));
1506
+ const measuredBand = channel1Band(undroppedTokens, tailTokens);
1507
+ const quiet = (reason, dampeningState, level = measuredBand === "quiet" ? "gentle" : measuredBand) => ({
1508
+ fire: false,
1509
+ sticky: false,
1510
+ level,
1511
+ band: measuredBand,
1512
+ undroppedTokens,
1513
+ tailTokens,
1514
+ severity,
1515
+ graceBaselineU,
1516
+ graceGrowth,
1517
+ growthThreshold,
1518
+ cadenceGrowth,
1519
+ stickyTurnsRemaining,
1520
+ dampeningState,
1521
+ verdictReason: reason,
1522
+ nextLastNudge: lastNudge,
1523
+ nextLastNudgeLevel: nextLevel,
1524
+ clearPostReduceGrace
1525
+ });
1526
+ if (input.evaluable === false || input.generationInvalidated === true) {
1527
+ return quiet("baseline-unevaluable", "baseline-hold");
1528
+ }
1529
+ if (input.hasRecentReduce)
1530
+ return quiet("recent-reduce-refresh", "baseline-hold");
1531
+ if (input.agentDropsAppliedThisPass) {
1532
+ return quiet("agent-drops-applied", "baseline-hold");
1533
+ }
1534
+ if (input.postReduceGracePending) {
1535
+ return quiet("post-reduce-baseline-pending", "baseline-hold");
1536
+ }
1537
+ const level = measuredBand === "quiet" ? "" : measuredBand;
1538
+ const previousRank = previousLevel === "" ? 0 : LEVEL_RANK[previousLevel];
1539
+ const currentRank = level === "" ? 0 : LEVEL_RANK[level];
1540
+ let graceReleaseReason = null;
1541
+ if (graceBaselineU !== null) {
1542
+ const preReduceLevel = input.postReduceGracePreLevel ?? previousLevel;
1543
+ const preReduceRank = preReduceLevel === "" ? 0 : LEVEL_RANK[preReduceLevel];
1544
+ const regrowthReached = graceGrowth >= growthThreshold;
1545
+ const escalatedAbovePreReduceBand = currentRank > preReduceRank;
1546
+ if (!regrowthReached && !escalatedAbovePreReduceBand) {
1547
+ return quiet("post-reduce-compliance-grace", "post-reduce-grace");
1548
+ }
1549
+ clearPostReduceGrace = true;
1550
+ graceReleaseReason = regrowthReached ? "post-reduce-regrowth-reached" : "post-reduce-band-escalation";
1551
+ }
1552
+ if (level === "") {
1553
+ nextLevel = "";
1554
+ lastNudge = 0;
1555
+ if (tailTokens < CHANNEL1_MIN_TOKENS) {
1556
+ return quiet("tail-below-minimum", "none");
1557
+ }
1558
+ if (undroppedTokens < CHANNEL1_FLOOR_TOKENS) {
1559
+ return quiet("reclaimable-below-floor", "none");
1560
+ }
1561
+ return quiet("ratio-below-gentle", "none");
1562
+ }
1563
+ if (currentRank < previousRank) {
1564
+ nextLevel = level;
1565
+ lastNudge = undroppedTokens;
1566
+ return quiet("band-deescalation", "band-hysteresis", level);
1567
+ }
1568
+ const crossedFromBelow = currentRank > previousRank;
1569
+ const cadenceReached = currentRank === previousRank && cadenceGrowth >= growthThreshold;
1570
+ const stickyTurnGapReached = stickyTurnsRemaining === 0;
1571
+ if (!crossedFromBelow && !cadenceReached) {
1572
+ return quiet("cadence-growth", "cadence", level);
1573
+ }
1574
+ if (!crossedFromBelow && !stickyTurnGapReached) {
1575
+ return quiet("sticky-turn-floor", "sticky-floor", level);
1576
+ }
1577
+ return {
1578
+ fire: true,
1579
+ sticky: !crossedFromBelow,
1580
+ level,
1581
+ band: measuredBand,
1582
+ undroppedTokens,
1583
+ tailTokens,
1584
+ severity,
1585
+ graceBaselineU,
1586
+ graceGrowth,
1587
+ growthThreshold,
1588
+ cadenceGrowth,
1589
+ stickyTurnsRemaining,
1590
+ dampeningState: "none",
1591
+ verdictReason: graceReleaseReason ?? (crossedFromBelow ? "band-crossing" : "cadence-refire"),
1592
+ nextLastNudge: undroppedTokens,
1593
+ nextLastNudgeLevel: level,
1594
+ clearPostReduceGrace
1595
+ };
1596
+ }
1597
+ function evaluateChannel2(input) {
1598
+ const unavailable = (reason) => ({
1599
+ evaluable: false,
1600
+ shouldTrigger: false,
1601
+ reclaimableTokens: 0,
1602
+ tailTokens: 0,
1603
+ severity: 0,
1604
+ band: "quiet",
1605
+ verdictReason: reason
1606
+ });
1607
+ if (!input)
1608
+ return unavailable("baseline-unavailable");
1609
+ if (input.evaluable !== true)
1610
+ return unavailable("baseline-unevaluable");
1611
+ if (input.generationInvalidated === true)
1612
+ return unavailable("generation-invalidated");
1613
+ const values = [input.baselineU, input.baselineT, input.turnDeltaU, input.turnDeltaT];
1614
+ if (values.some((value) => !Number.isFinite(value)))
1615
+ return unavailable("non-finite-input");
1616
+ const tailTokens = Math.max(0, input.baselineT + input.turnDeltaT);
1617
+ const reclaimableTokens = Math.min(tailTokens, Math.max(0, input.baselineU + input.turnDeltaU));
1618
+ const severity = Math.min(1, Math.max(0, reclaimableTokens / Math.max(tailTokens, 1)));
1619
+ const band = nudgeBand(reclaimableTokens, tailTokens);
1620
+ let verdictReason = "ceiling-threshold-met";
1621
+ if (tailTokens < CHANNEL1_MIN_TOKENS)
1622
+ verdictReason = "tail-below-minimum";
1623
+ else if (reclaimableTokens < CHANNEL2_FLOOR_TOKENS) {
1624
+ verdictReason = "reclaimable-below-floor";
1625
+ } else if (severity < CHANNEL2_SEVERITY_THRESHOLD)
1626
+ verdictReason = "ratio-below-ceiling";
1627
+ return {
1628
+ evaluable: true,
1629
+ shouldTrigger: verdictReason === "ceiling-threshold-met",
1630
+ reclaimableTokens,
1631
+ tailTokens,
1632
+ severity,
1633
+ band,
1634
+ verdictReason
1635
+ };
1636
+ }
1637
+ function formatRatio(value) {
1638
+ return Number.isFinite(value) ? value.toFixed(4) : "nan";
1639
+ }
1640
+ function formatChannel1Evaluation(decision, ctxReduceCallable = true) {
1641
+ return [
1642
+ "channel1 evaluation:",
1643
+ `ctx_reduce=${ctxReduceCallable ? "callable" : "unavailable"}`,
1644
+ `U=${decision.undroppedTokens}`,
1645
+ `T=${decision.tailTokens}`,
1646
+ `ratio=${formatRatio(decision.severity)}`,
1647
+ `band=${decision.band}`,
1648
+ `grace_baseline_u=${decision.graceBaselineU ?? "none"}`,
1649
+ `grace_growth=${decision.graceGrowth}`,
1650
+ `growth_threshold=${decision.growthThreshold}`,
1651
+ `sticky_floor_turns_remaining=${decision.stickyTurnsRemaining}`,
1652
+ `dampening=${decision.dampeningState}`,
1653
+ `verdict=${decision.fire ? "fire" : "hold"}`,
1654
+ `reason=${ctxReduceCallable ? decision.verdictReason : "ctx-reduce-unavailable"}`
1655
+ ].join(" ");
1656
+ }
1657
+ function formatChannel2Evaluation(evaluation, input) {
1658
+ const leaseAfter = input.leaseAfter ?? input.leaseBefore;
1659
+ let verdict = "hold";
1660
+ let reason = evaluation.verdictReason;
1661
+ if (input.ctxReduceCallable === false) {
1662
+ reason = "ctx-reduce-unavailable";
1663
+ } else if (input.gateHoldReason) {
1664
+ reason = input.gateHoldReason;
1665
+ } else if (evaluation.shouldTrigger) {
1666
+ if (input.leaseBefore === "" && input.leaseAfter === undefined) {
1667
+ verdict = "arm";
1668
+ } else if (leaseAfter === "pending") {
1669
+ verdict = input.leaseBefore === "" ? "arm" : "pending";
1670
+ reason = input.leaseBefore === "" ? evaluation.verdictReason : "lease-pending";
1671
+ } else if (leaseAfter === "claimed") {
1672
+ reason = "lease-claimed";
1673
+ } else if (leaseAfter === "delivered") {
1674
+ reason = "lease-delivered";
1675
+ } else {
1676
+ reason = "lease-cas-not-armed";
1677
+ }
1678
+ }
1679
+ return [
1680
+ "channel2 evaluation:",
1681
+ `ctx_reduce=${input.ctxReduceCallable === false ? "unavailable" : "callable"}`,
1682
+ `U=${evaluation.reclaimableTokens}`,
1683
+ `T=${evaluation.tailTokens}`,
1684
+ `ratio=${formatRatio(evaluation.severity)}`,
1685
+ `band=${evaluation.band}`,
1686
+ `lease=${input.leaseBefore || "empty"}->${leaseAfter || "empty"}`,
1687
+ `verdict=${verdict}`,
1688
+ `reason=${reason}`
1689
+ ].join(" ");
1690
+ }
1691
+ function approxThousands(tokens) {
1692
+ return `${Math.round(tokens / 1000)}k`;
1693
+ }
1694
+ function formatOldestReclaimableHint(hint) {
1695
+ if (!hint || hint.length === 0)
1696
+ return "";
1697
+ const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
1698
+ return rendered.length > 0 ? `
1699
+ oldest reclaimable: ${rendered}.` : "";
1700
+ }
1701
+ function reclaimableToolOutputCount(parts) {
1702
+ return parts.filter((part) => part.kind === "toolOutput" && part.uTokens > 0).length;
1703
+ }
1704
+ function formatReclaimableOutputSummary(count, tokens) {
1705
+ const outputCount = Math.max(0, Math.floor(count));
1706
+ const outputs = outputCount === 0 ? "spent tool outputs" : `${outputCount} spent tool output${outputCount === 1 ? "" : "s"}`;
1707
+ return `${outputs} (~${approxThousands(tokens)} tokens)`;
1708
+ }
1709
+ function buildChannel2Reminder(undroppedTokens, reclaimableToolOutputs, hint) {
1710
+ const summary = formatReclaimableOutputSummary(reclaimableToolOutputs, undroppedTokens);
1711
+ const hintText = formatOldestReclaimableHint(hint);
1712
+ return `<system-reminder>
1713
+ ` + `Your next step: call ctx_reduce on the outputs you've already used (${summary}). Then continue your task.${hintText}
1714
+ ` + `</system-reminder>`;
1715
+ }
1716
+ var CHANNEL1_STICKY_REAL_USER_TURN_GAP = 5;
1717
+ function buildChannel1Reminder(level, undroppedTokens, reclaimableToolOutputs, hint, sticky = false) {
1718
+ const summary = formatReclaimableOutputSummary(reclaimableToolOutputs, undroppedTokens);
1719
+ const hintText = formatOldestReclaimableHint(hint);
1720
+ if (sticky) {
1721
+ return `
1722
+
1723
+ <system-reminder>
1724
+ Still unstamped: ${summary}. Stamp the ones you've used with ctx_reduce now.${hintText}
1725
+ </system-reminder>`;
1726
+ }
1727
+ let body;
1728
+ switch (level) {
1729
+ case "gentle":
1730
+ body = `Housekeeping: ${summary} are reclaimable. Stamp each output with ctx_reduce as soon as you've taken what you need from it; don't wait for the task to finish.`;
1731
+ break;
1732
+ case "firm":
1733
+ body = `${summary} are reclaimable. Make a ctx_reduce pass now over the outputs you've already used, then continue.`;
1734
+ break;
1735
+ case "urgent":
1736
+ body = `${summary} are still unstamped. Call ctx_reduce now, before your next tool call, on every output you've already used.`;
1737
+ break;
1738
+ }
1739
+ return `
1740
+
1741
+ <system-reminder>
1742
+ ${body}${hintText}
1743
+ </system-reminder>`;
1744
+ }
1745
+
1746
+ // src/hooks/magic-context/emergency-drop.ts
1747
+ var TARGET_FRACTION = 0.3;
1748
+ var TIER_RECENCY_RESERVE = 0.2;
1749
+ var EMERGENCY_REARM_MIN_TOKENS = 2000;
1750
+ var EMERGENCY_MIN_ACHIEVABLE_RECLAIM_TOKENS = EMERGENCY_REARM_MIN_TOKENS;
1751
+ var T1_TOOLS = new Set(["read", "todowrite", "task", "aft_outline", "aft_zoom"]);
1752
+ var T2_TOOLS = new Set(["edit", "write", "apply_patch", "grep", "glob", "aft_search"]);
1753
+ function normalizeToolName(toolName) {
1754
+ if (!toolName)
1755
+ return "";
1756
+ let name = toolName.toLowerCase();
1757
+ if (name.startsWith("mcp_"))
1758
+ name = name.slice(4);
1759
+ return name;
1760
+ }
1761
+ function resolveToolTier(toolName) {
1762
+ const name = normalizeToolName(toolName);
1763
+ if (T1_TOOLS.has(name))
1764
+ return 1;
1765
+ if (T2_TOOLS.has(name))
1766
+ return 2;
1767
+ return 3;
1768
+ }
1769
+ function tagReclaimBytes(tag) {
1770
+ return tag.byteSize + tag.inputByteSize + tag.reasoningByteSize;
1771
+ }
1772
+ function estimateEmergencyDropReclaimTokens(tag) {
1773
+ if (tag.reclaimableTokens !== undefined)
1774
+ return Number.isFinite(tag.reclaimableTokens) ? Math.max(0, tag.reclaimableTokens) : 0;
1775
+ return Math.round(tagReclaimBytes(tag) * TOKENS_PER_BYTE);
1776
+ }
1777
+ function planEmergencyDrop(input) {
1778
+ const {
1779
+ tags,
1780
+ floorTags,
1781
+ currentTotalInputTokens,
1782
+ ceilingTokens,
1783
+ priorInputSample,
1784
+ hasPriorDrop
1785
+ } = input;
1786
+ const noop = (reason) => ({
1787
+ shouldDrop: false,
1788
+ tagNumbers: [],
1789
+ reclaimTokens: 0,
1790
+ reason
1791
+ });
1792
+ if (!Number.isFinite(ceilingTokens) || ceilingTokens <= 0) {
1793
+ return noop("unknown-ceiling");
1794
+ }
1795
+ if (!Number.isFinite(currentTotalInputTokens) || currentTotalInputTokens <= 0) {
1796
+ return noop("unknown-usage");
1797
+ }
1798
+ const absoluteEmergency = (input.usagePercentage ?? 0) >= 95;
1799
+ if (hasPriorDrop && !absoluteEmergency) {
1800
+ return noop(`pressure-episode-latched (prior sample ${priorInputSample}; awaiting exit or independent bust)`);
1801
+ }
1802
+ let tailTokens = 0;
1803
+ for (const tag of floorTags) {
1804
+ if (tag.status !== "active")
1805
+ continue;
1806
+ tailTokens += tag.servedTokens ?? estimateEmergencyDropReclaimTokens(tag);
1807
+ }
1808
+ const fixedFloor = Math.max(currentTotalInputTokens - tailTokens, 0);
1809
+ const workingSpan = Math.max(ceilingTokens - fixedFloor, 0);
1810
+ const target = fixedFloor + TARGET_FRACTION * workingSpan;
1811
+ const reclaimTokens = Math.round(currentTotalInputTokens - target);
1812
+ const floorNote = fixedFloor > ceilingTokens ? `; fixed floor ≈${Math.round(fixedFloor)} already exceeds ceiling ${Math.round(ceilingTokens)}: tool drops cannot reach the target` : "";
1813
+ if (reclaimTokens <= EMERGENCY_REARM_MIN_TOKENS) {
1814
+ return noop(`reclaim<=min (${reclaimTokens} <= ${EMERGENCY_REARM_MIN_TOKENS})${floorNote}`);
1815
+ }
1816
+ const cutoff = input.protectedCutoff;
1817
+ const windowYields = absoluteEmergency;
1818
+ const tierActive = { 1: [], 2: [] };
1819
+ for (const tag of tags) {
1820
+ if (tag.status !== "active" || tag.type !== "tool")
1821
+ continue;
1822
+ const tier = resolveToolTier(tag.toolName);
1823
+ if (tier === 1 || tier === 2)
1824
+ tierActive[tier].push(tag.tagNumber);
1825
+ }
1826
+ const reserved = new Set;
1827
+ for (const tier of [1, 2]) {
1828
+ const nums = tierActive[tier];
1829
+ if (nums.length === 0)
1830
+ continue;
1831
+ nums.sort((a, b) => b - a);
1832
+ const reserveCount = absoluteEmergency ? 0 : Math.ceil(TIER_RECENCY_RESERVE * nums.length);
1833
+ for (let i = 0;i < reserveCount && i < nums.length; i++) {
1834
+ reserved.add(nums[i]);
1835
+ }
1836
+ }
1837
+ const protectedTags = input.protectedToolTags ?? protectedToolTagNumbers(floorTags, input.protectedTools);
1838
+ const byTier = { 1: [], 2: [], 3: [] };
1839
+ for (const tag of tags) {
1840
+ if (tag.status !== "active" || tag.type !== "tool")
1841
+ continue;
1842
+ if (!windowYields) {
1843
+ if (cutoff !== null) {
1844
+ if (tag.tagNumber >= cutoff)
1845
+ continue;
1846
+ }
1847
+ }
1848
+ if (protectedTags.has(tag.tagNumber))
1849
+ continue;
1850
+ const tier = resolveToolTier(tag.toolName);
1851
+ if ((tier === 1 || tier === 2) && reserved.has(tag.tagNumber))
1852
+ continue;
1853
+ byTier[tier].push(tag);
1854
+ }
1855
+ const selected = [];
1856
+ let reclaimed = 0;
1857
+ outer:
1858
+ for (const tier of [3, 2, 1]) {
1859
+ const group = byTier[tier];
1860
+ group.sort((a, b) => a.tagNumber - b.tagNumber);
1861
+ for (const tag of group) {
1862
+ selected.push(tag.tagNumber);
1863
+ reclaimed += estimateEmergencyDropReclaimTokens(tag);
1864
+ if (reclaimed >= reclaimTokens)
1865
+ break outer;
1866
+ }
1867
+ }
1868
+ if (selected.length === 0) {
1869
+ return noop(`no-candidates${floorNote}`);
1870
+ }
1871
+ if (!input.passAlreadyPriced && reclaimed < EMERGENCY_MIN_ACHIEVABLE_RECLAIM_TOKENS) {
1872
+ return noop(`achievable reclaim below minimum (${selected.length} tags, reclaim≈${Math.round(reclaimed)} < ${EMERGENCY_MIN_ACHIEVABLE_RECLAIM_TOKENS} against gap ${reclaimTokens})${floorNote}`);
1873
+ }
1874
+ return {
1875
+ shouldDrop: true,
1876
+ tagNumbers: selected,
1877
+ reclaimTokens,
1878
+ reason: `tiered drop: ${selected.length} tags, reclaim≈${reclaimed}/${reclaimTokens} tokens (floor≈${fixedFloor}, ceiling=${Math.round(ceilingTokens)})${floorNote}`
1879
+ };
1880
+ }
1881
+ function measureEmergencyTag(tag, target, calibration, skeleton) {
1882
+ const observation = target?.measureReclaim?.(skeleton);
1883
+ if (observation) {
1884
+ const before = observation.beforeTools * calibration.toolsRatio + observation.beforeProse * calibration.proseRatio;
1885
+ const after = observation.afterTools * calibration.toolsRatio + observation.afterProse * calibration.proseRatio;
1886
+ return { ...tag, servedTokens: before, reclaimableTokens: Math.max(0, before - after) };
1887
+ }
1888
+ const content = target?.getContent?.();
1889
+ const served = content ? estimateTokens(content) * (tag.type === "tool" ? calibration.toolsRatio : calibration.proseRatio) : 0;
1890
+ return { ...tag, servedTokens: served, reclaimableTokens: 0 };
1891
+ }
1892
+
1893
+ // src/features/magic-context/storage-ops.ts
1894
+ var queuePendingOpStatements = new WeakMap;
1895
+ var queueUnchangedDropStatements = new WeakMap;
1896
+ var getPendingOpsStatements = new WeakMap;
1897
+ var getPendingOpsCountStatements = new WeakMap;
1898
+ var hasPendingDropOpsStatements = new WeakMap;
1899
+ var clearPendingOpsStatements = new WeakMap;
1900
+ var removePendingOpStatements = new WeakMap;
1901
+ function getQueuePendingOpStatement(db) {
1902
+ let stmt = queuePendingOpStatements.get(db);
1903
+ if (!stmt) {
1904
+ stmt = db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
1905
+ SELECT ?, ?, ?, ?, ? WHERE NOT EXISTS (
1906
+ SELECT 1 FROM pending_ops WHERE session_id = ? AND tag_id = ? AND operation = ?
1907
+ )`);
1908
+ queuePendingOpStatements.set(db, stmt);
1909
+ }
1910
+ return stmt;
1911
+ }
1912
+ function getPendingOpsStatement(db) {
1913
+ let stmt = getPendingOpsStatements.get(db);
1914
+ if (!stmt) {
1915
+ stmt = db.prepare("SELECT id, session_id, tag_id, operation, queued_at FROM pending_ops WHERE session_id = ? ORDER BY queued_at ASC, id ASC");
1916
+ getPendingOpsStatements.set(db, stmt);
1917
+ }
1918
+ return stmt;
1919
+ }
1920
+ function getClearPendingOpsStatement(db) {
1921
+ let stmt = clearPendingOpsStatements.get(db);
1922
+ if (!stmt) {
1923
+ stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ?");
1924
+ clearPendingOpsStatements.set(db, stmt);
1925
+ }
1926
+ return stmt;
1927
+ }
1928
+ function getRemovePendingOpStatement(db) {
1929
+ let stmt = removePendingOpStatements.get(db);
1930
+ if (!stmt) {
1931
+ stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?");
1932
+ removePendingOpStatements.set(db, stmt);
1933
+ }
1934
+ return stmt;
1935
+ }
1936
+ function isPendingOpRow(row) {
1937
+ if (row === null || typeof row !== "object")
1938
+ return false;
1939
+ const r = row;
1940
+ return typeof r.id === "number" && typeof r.session_id === "string" && typeof r.tag_id === "number" && typeof r.operation === "string" && typeof r.queued_at === "number";
1941
+ }
1942
+ function toPendingOp(row) {
1943
+ if (row.operation !== "drop") {
1944
+ sessionLog2(row.session_id, `unknown pending operation "${row.operation}"; ignoring`);
1945
+ return null;
1946
+ }
1947
+ return {
1948
+ id: row.id,
1949
+ sessionId: row.session_id,
1950
+ tagId: row.tag_id,
1951
+ operation: row.operation,
1952
+ queuedAt: row.queued_at
1953
+ };
1954
+ }
1955
+ function queuePendingOp(db, sessionId, tagId, operation, queuedAt = Date.now()) {
1956
+ getQueuePendingOpStatement(db).run(sessionId, tagId, operation, queuedAt, getHarness2(), sessionId, tagId, operation);
1957
+ }
1958
+ function queuePendingDropForUnchangedTag(db, sessionId, tag) {
1959
+ let statement = queueUnchangedDropStatements.get(db);
1960
+ if (!statement) {
1961
+ statement = db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
1962
+ SELECT session_id, tag_number, 'drop', ?, ? FROM tags
1963
+ WHERE id = ? AND session_id = ? AND tag_number = ? AND message_id = ?
1964
+ AND type = ? AND tool_owner_message_id IS ? AND status = 'active'
1965
+ AND NOT EXISTS (
1966
+ SELECT 1 FROM pending_ops WHERE session_id = tags.session_id
1967
+ AND tag_id = tags.tag_number AND operation = 'drop'
1968
+ )`);
1969
+ queueUnchangedDropStatements.set(db, statement);
1970
+ }
1971
+ return statement.run(Date.now(), getHarness2(), tag.id ?? null, sessionId, tag.tagNumber, tag.messageId, tag.type, tag.toolOwnerMessageId).changes > 0;
1972
+ }
1973
+ function getPendingOps(db, sessionId) {
1974
+ const rows = getPendingOpsStatement(db).all(sessionId).filter(isPendingOpRow);
1975
+ return rows.map(toPendingOp).filter((op) => op !== null);
1976
+ }
1977
+ function hasPendingDropOps(db, sessionId) {
1978
+ let statement = hasPendingDropOpsStatements.get(db);
1979
+ if (!statement) {
1980
+ statement = db.prepare(`SELECT EXISTS (
1981
+ SELECT 1 FROM pending_ops WHERE session_id = ? AND operation = 'drop'
1982
+ AND typeof(id) IN ('integer', 'real')
1983
+ AND typeof(session_id) = 'text'
1984
+ AND typeof(tag_id) IN ('integer', 'real')
1985
+ AND typeof(queued_at) IN ('integer', 'real')
1986
+ ) AS present`);
1987
+ hasPendingDropOpsStatements.set(db, statement);
1988
+ }
1989
+ return statement.get(sessionId).present === 1;
1990
+ }
1991
+ function getPendingOpsCount(db, sessionId) {
1992
+ try {
1993
+ let statement = getPendingOpsCountStatements.get(db);
1994
+ if (!statement) {
1995
+ statement = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?");
1996
+ getPendingOpsCountStatements.set(db, statement);
1997
+ }
1998
+ const row = statement.get(sessionId);
1999
+ return typeof row?.count === "number" && Number.isFinite(row.count) ? row.count : null;
2000
+ } catch {
2001
+ return null;
2002
+ }
2003
+ }
2004
+ function clearPendingOps(db, sessionId) {
2005
+ getClearPendingOpsStatement(db).run(sessionId);
2006
+ }
2007
+ function removePendingOp(db, sessionId, tagId) {
2008
+ getRemovePendingOpStatement(db).run(sessionId, tagId);
2009
+ }
2010
+
2011
+ // src/features/magic-context/storage-tags.ts
2012
+ var insertTagStatements = new WeakMap;
2013
+ var updateTagStatusStatements = new WeakMap;
2014
+ var updateTagDropModeStatements = new WeakMap;
2015
+ var updateTagMessageIdStatements = new WeakMap;
2016
+ var getTagNumbersByMessageIdStatements = new WeakMap;
2017
+ var deleteTagsByMessageIdStatements = new WeakMap;
2018
+ var getMaxTagNumberBySessionStatements = new WeakMap;
2019
+ var getTagNumberByMessageIdStatements = new WeakMap;
2020
+ var getAssignableTagNumberByMessageIdStatements = new WeakMap;
2021
+ var hasPiFallbackMessageTagStatements = new WeakMap;
2022
+ var WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX = "__mc_whitespace_assistant_inert__:";
2023
+ var WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX = "mc:whitespace-assistant:";
2024
+ function getInsertTagStatement(db) {
2025
+ let stmt = insertTagStatements.get(db);
2026
+ if (!stmt) {
2027
+ stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness, tool_owner_message_id, entry_fingerprint, token_count, input_token_count, reasoning_token_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
2028
+ insertTagStatements.set(db, stmt);
2029
+ }
2030
+ return stmt;
2031
+ }
2032
+ function getUpdateTagStatusStatement(db) {
2033
+ let stmt = updateTagStatusStatements.get(db);
2034
+ if (!stmt) {
2035
+ stmt = db.prepare("UPDATE tags SET status = ? WHERE session_id = ? AND tag_number = ?");
2036
+ updateTagStatusStatements.set(db, stmt);
2037
+ }
2038
+ return stmt;
2039
+ }
2040
+ function getUpdateTagDropModeStatement(db) {
2041
+ let stmt = updateTagDropModeStatements.get(db);
2042
+ if (!stmt) {
2043
+ stmt = db.prepare("UPDATE tags SET drop_mode = ? WHERE session_id = ? AND tag_number = ?");
2044
+ updateTagDropModeStatements.set(db, stmt);
2045
+ }
2046
+ return stmt;
2047
+ }
2048
+ var updateTagByteSizeStatements = new WeakMap;
2049
+ var updateTagInputByteSizeStatements = new WeakMap;
2050
+ var RECENT_OWNER_SCAN_PAGE_SIZE = 128;
2051
+ var recentTagOwnerStatements = new WeakMap;
2052
+ function ownerMessageIdForTagRow(row) {
2053
+ if (row.type === "tool") {
2054
+ return row.tool_owner_message_id ?? row.message_id;
2055
+ }
2056
+ return contentTagOwnerMessageId(row.message_id);
2057
+ }
2058
+ function getRecentTagOwnerStatement(db) {
2059
+ let statement = recentTagOwnerStatements.get(db);
2060
+ if (!statement) {
2061
+ statement = db.prepare(`SELECT type, message_id, tool_owner_message_id
2062
+ FROM tags
2063
+ WHERE session_id = ?
2064
+ ORDER BY tag_number DESC, id DESC
2065
+ LIMIT ? OFFSET ?`);
2066
+ recentTagOwnerStatements.set(db, statement);
2067
+ }
2068
+ return statement;
2069
+ }
2070
+ function getRecentTagOwnerMessageIds2(db, sessionId, maxOwners) {
2071
+ const recent = new Set;
2072
+ if (!Number.isFinite(maxOwners) || maxOwners <= 0)
2073
+ return recent;
2074
+ const statement = getRecentTagOwnerStatement(db);
2075
+ let offset = 0;
2076
+ while (recent.size < maxOwners) {
2077
+ const rows = statement.all(sessionId, RECENT_OWNER_SCAN_PAGE_SIZE, offset);
2078
+ for (const row of rows) {
2079
+ if (typeof row.type !== "string" || typeof row.message_id !== "string")
2080
+ continue;
2081
+ const ownerId = row.type === "tool" ? typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null : contentTagOwnerMessageId(row.message_id);
2082
+ if (!ownerId || recent.has(ownerId))
2083
+ continue;
2084
+ recent.add(ownerId);
2085
+ if (recent.size >= maxOwners)
2086
+ break;
2087
+ }
2088
+ if (rows.length < RECENT_OWNER_SCAN_PAGE_SIZE)
2089
+ break;
2090
+ offset += rows.length;
2091
+ }
2092
+ return recent;
2093
+ }
2094
+ function getActiveTagTokenAggregate2(db, sessionId, protectedCutoff = null) {
2095
+ const toolOutputExpr = protectedCutoff !== null ? `COALESCE(SUM(CASE WHEN type = 'tool' AND tag_number < ? THEN COALESCE(token_count, 0) ELSE 0 END), 0)` : `COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)`;
2096
+ const sql = `SELECT
2097
+ COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
2098
+ + COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
2099
+ COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
2100
+ ${toolOutputExpr} AS tool_output,
2101
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
2102
+ FROM tags
2103
+ WHERE session_id = ? AND status = 'active'`;
2104
+ const params = protectedCutoff !== null ? [protectedCutoff, sessionId] : [sessionId];
2105
+ const row = db.prepare(sql).get(...params);
2106
+ return {
2107
+ conversation: row?.conversation ?? 0,
2108
+ toolCall: row?.tool_call ?? 0,
2109
+ toolOutput: row?.tool_output ?? 0,
2110
+ nullCount: row?.null_count ?? 0
2111
+ };
2112
+ }
2113
+ var RECLAIM_HINT_EXCLUDED_TOOLS = new Set([
2114
+ "ask",
2115
+ "bash_kill",
2116
+ "bash_status",
2117
+ "board",
2118
+ "task",
2119
+ "todoread",
2120
+ "todowrite",
2121
+ "work"
2122
+ ]);
2123
+ var AGE_RECLAIM_MIN_TOKENS2 = 250;
2124
+ function isReclaimHintExcludedTool(toolName) {
2125
+ if (!toolName)
2126
+ return false;
2127
+ const normalized = toolName.toLowerCase().replace(/^mcp_/, "");
2128
+ return normalized.startsWith("ctx_") || RECLAIM_HINT_EXCLUDED_TOOLS.has(normalized);
2129
+ }
2130
+ function getOldestActiveUnprotectedToolTags2(db, sessionId, protectedTagNumbers = new Set, limit = 4) {
2131
+ if (limit <= 0)
2132
+ return [];
2133
+ const boundedLimit = Math.max(1, Math.min(10, Math.floor(limit)));
2134
+ const valueFloor = `AND (
2135
+ (token_count IS NULL AND input_token_count IS NULL)
2136
+ OR (COALESCE(token_count, 0) + COALESCE(input_token_count, 0)) >= ?
2137
+ )`;
2138
+ const params = [sessionId, AGE_RECLAIM_MIN_TOKENS2];
2139
+ const rows = db.prepare(`SELECT tag_number, tool_name
2140
+ FROM tags
2141
+ WHERE session_id = ? AND status = 'active' AND type = 'tool'
2142
+ AND NOT EXISTS (
2143
+ SELECT 1 FROM pending_ops
2144
+ WHERE pending_ops.session_id = tags.session_id
2145
+ AND pending_ops.tag_id = tags.tag_number
2146
+ AND pending_ops.operation = 'drop'
2147
+ )
2148
+ ${valueFloor}
2149
+ ORDER BY tag_number ASC, id ASC`).all(...params);
2150
+ return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
2151
+ tagNumber: row.tag_number,
2152
+ toolName: typeof row.tool_name === "string" ? row.tool_name : null
2153
+ })).filter((tag) => !protectedTagNumbers.has(tag.tagNumber) && !isReclaimHintExcludedTool(tag.toolName)).sort((left, right) => resolveToolTier(right.toolName) - resolveToolTier(left.toolName) || left.tagNumber - right.tagNumber).slice(0, boundedLimit);
2154
+ }
2155
+ var getActiveToolTagsForAgeReclaimStatements = new WeakMap;
2156
+ function getActiveToolTagsForAgeReclaim2(db, sessionId) {
2157
+ let stmt = getActiveToolTagsForAgeReclaimStatements.get(db);
2158
+ if (!stmt) {
2159
+ stmt = db.prepare(`SELECT tag_number, tool_name, token_count, input_token_count
2160
+ FROM tags
2161
+ WHERE session_id = ? AND status = 'active' AND type = 'tool'
2162
+ ORDER BY tag_number ASC, id ASC`);
2163
+ getActiveToolTagsForAgeReclaimStatements.set(db, stmt);
2164
+ }
2165
+ const rows = stmt.all(sessionId);
2166
+ const tags = rows.filter((row) => typeof row.tag_number === "number").map((row) => {
2167
+ const outputTokens = typeof row.token_count === "number" ? row.token_count : null;
2168
+ const inputTokens = typeof row.input_token_count === "number" ? row.input_token_count : null;
2169
+ return {
2170
+ tagNumber: row.tag_number,
2171
+ toolName: typeof row.tool_name === "string" ? row.tool_name : null,
2172
+ reclaimableTokens: outputTokens === null && inputTokens === null ? null : (outputTokens ?? 0) + (inputTokens ?? 0)
2173
+ };
2174
+ });
2175
+ return tags;
2176
+ }
2177
+ function getTriggerTagTokenUpperBound2(db, sessionId, floor = 0) {
2178
+ const sql = floor > 0 ? `SELECT
2179
+ COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
2180
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
2181
+ FROM tags
2182
+ WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?` : `SELECT
2183
+ COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
2184
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
2185
+ FROM tags
2186
+ WHERE session_id = ? AND status IN ('active', 'dropped')`;
2187
+ const row = floor > 0 ? db.prepare(sql).get(sessionId, floor) : db.prepare(sql).get(sessionId);
2188
+ return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
2189
+ }
2190
+ var scopedActiveTokenTotalStatements = new WeakMap;
2191
+ function getActiveTagTokenTotalsByMessage2(db, sessionId, messageIds) {
2192
+ if (messageIds?.length === 0)
2193
+ return new Map;
2194
+ const fields = "id, tag_number, type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count".split(", ").map((field) => `tags.${field}`).join(", ");
2195
+ let scoped = scopedActiveTokenTotalStatements.get(db);
2196
+ if (messageIds && !scoped) {
2197
+ scoped = db.prepare(`
2198
+ SELECT ${fields} FROM json_each(?) AS owners
2199
+ CROSS JOIN tags INDEXED BY idx_tags_session_message_id
2200
+ WHERE session_id = ? AND tags.type != 'tool' AND +status = 'active'
2201
+ AND message_id >= owners.value || ':' AND message_id < owners.value || ';'
2202
+ UNION
2203
+ SELECT ${fields} FROM tags INDEXED BY idx_tags_session_message_id
2204
+ WHERE session_id = ? AND type != 'tool' AND +status = 'active'
2205
+ AND message_id IN (SELECT value FROM json_each(?))
2206
+ UNION
2207
+ SELECT ${fields} FROM tags INDEXED BY idx_tags_pi_fallback_tool_owner
2208
+ WHERE session_id = ? AND type = 'tool' AND +status = 'active'
2209
+ AND tool_owner_message_id IN (SELECT value FROM json_each(?))
2210
+ UNION
2211
+ SELECT ${fields} FROM tags INDEXED BY idx_tags_session_message_id
2212
+ WHERE session_id = ? AND type = 'tool' AND +status = 'active'
2213
+ AND tool_owner_message_id IS NULL AND message_id IN (SELECT value FROM json_each(?))
2214
+ ORDER BY tag_number, id`);
2215
+ scopedActiveTokenTotalStatements.set(db, scoped);
2216
+ }
2217
+ const owners = messageIds ? new Set(messageIds) : undefined;
2218
+ const encoded = owners ? JSON.stringify([...owners]) : "";
2219
+ const rows = messageIds && scoped ? scoped.all(encoded, sessionId, sessionId, encoded, sessionId, encoded, sessionId, encoded) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
2220
+ FROM tags
2221
+ WHERE session_id = ? AND status = 'active'`).all(sessionId);
2222
+ const out = new Map;
2223
+ for (const row of rows) {
2224
+ const owner = ownerMessageIdForTagRow(row);
2225
+ if (owners && !owners.has(owner))
2226
+ continue;
2227
+ let entry = out.get(owner);
2228
+ if (!entry) {
2229
+ entry = { conversation: 0, toolCall: 0, toolOutput: 0, hasNull: false };
2230
+ out.set(owner, entry);
2231
+ }
2232
+ const reasoning = row.reasoning_token_count ?? 0;
2233
+ if (row.type === "tool") {
2234
+ const output = row.token_count ?? 0;
2235
+ entry.toolCall += output + (row.input_token_count ?? 0);
2236
+ entry.toolOutput += output;
2237
+ } else {
2238
+ entry.conversation += row.token_count ?? 0;
2239
+ }
2240
+ entry.conversation += reasoning;
2241
+ if (row.token_count === null)
2242
+ entry.hasNull = true;
2243
+ }
2244
+ return out;
2245
+ }
2246
+ var updateTagTokenCountStatements = new WeakMap;
2247
+ var updateTagInputTokenCountStatements = new WeakMap;
2248
+ function getPersistedToolTagAccounting2(db, sessionId, tagNumber) {
2249
+ const row = db.prepare(`SELECT byte_size AS byteSize,
2250
+ token_count AS tokenCount,
2251
+ input_byte_size AS inputByteSize,
2252
+ input_token_count AS inputTokenCount
2253
+ FROM tags
2254
+ WHERE session_id = ? AND tag_number = ? AND type = 'tool'`).get(sessionId, tagNumber);
2255
+ if (!row || typeof row.byteSize !== "number" || row.tokenCount !== null && typeof row.tokenCount !== "number" || typeof row.inputByteSize !== "number" || row.inputTokenCount !== null && typeof row.inputTokenCount !== "number") {
2256
+ return null;
2257
+ }
2258
+ return row;
2259
+ }
2260
+ function getAllStatusTagTokenTotalsFlat2(db, sessionId, floor = 0, calibration = { proseRatio: 1, toolsRatio: 1 }) {
2261
+ const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
2262
+ FROM tags
2263
+ WHERE session_id = ? AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
2264
+ FROM tags
2265
+ WHERE session_id = ?`).all(sessionId);
2266
+ const totals = new Map;
2267
+ const nullMessageIds = new Set;
2268
+ for (const row of rows) {
2269
+ if (row.type === "tool" && row.tool_owner_message_id === null)
2270
+ continue;
2271
+ const owner = ownerMessageIdForTagRow(row);
2272
+ if (row.token_count === null) {
2273
+ nullMessageIds.add(owner);
2274
+ totals.delete(owner);
2275
+ continue;
2276
+ }
2277
+ if (nullMessageIds.has(owner))
2278
+ continue;
2279
+ const ratio = row.type === "tool" ? calibration.toolsRatio : calibration.proseRatio;
2280
+ const weight = ((row.token_count ?? 0) + (row.input_token_count ?? 0)) * ratio + (row.reasoning_token_count ?? 0) * calibration.proseRatio;
2281
+ totals.set(owner, (totals.get(owner) ?? 0) + weight);
2282
+ }
2283
+ return { totals, nullMessageIds };
2284
+ }
2285
+ function getReasoningTokenEstimatesByMessage2(db, sessionId, proseRatio) {
2286
+ const summary = readTagOwnerSummary(db, sessionId, proseRatio);
2287
+ return summary.reasoningEstimatesByRatio.get(proseRatio) ?? new Map;
2288
+ }
2289
+ function tryGetReasoningTokenEstimatesByMessage2(db, sessionId, ratio) {
2290
+ try {
2291
+ return getReasoningTokenEstimatesByMessage2(db, sessionId, ratio);
2292
+ } catch (error) {
2293
+ if (error instanceof TagOwnerSummaryNotReady)
2294
+ return;
2295
+ throw error;
2296
+ }
2297
+ }
2298
+ function getMaxTagNumberByOwnerMessage2(db, sessionId) {
2299
+ return readTagOwnerSummary(db, sessionId).maxTagByOwner;
2300
+ }
2301
+ var tagOwnerSummaries = new WeakMap;
2302
+ var MAX_CACHED_PROSE_RATIOS = 4;
2303
+ var TAG_OWNER_PAGE_LIMIT = 512;
2304
+
2305
+ class TagOwnerSummaryNotReady extends Error {
2306
+ constructor() {
2307
+ super("tag owner summary needs off-thread preparation");
2308
+ }
2309
+ }
2310
+ function scanTagOwnerSummary2(db, sessionId, ratio, ratios = []) {
2311
+ db.exec("BEGIN");
2312
+ try {
2313
+ return readTagOwnerSummary(db, sessionId, ratio, ratios);
2314
+ } finally {
2315
+ db.exec("ROLLBACK");
2316
+ }
2317
+ }
2318
+ function cachedTagOwnerRatios2(db, sessionId) {
2319
+ return [...tagOwnerSummaries.get(db)?.get(sessionId)?.reasoningEstimatesByRatio.keys() ?? []];
2320
+ }
2321
+ function tagOwnerWarmupState2(db, sessionId) {
2322
+ const cached = tagOwnerSummaries.get(db)?.get(sessionId);
2323
+ if (!cached || cached.unownedToolRows.size > TAG_OWNER_PAGE_LIMIT)
2324
+ return;
2325
+ return {
2326
+ dataVersion: cached.dataVersion,
2327
+ generation: cached.generation,
2328
+ schemaVersion: cached.schemaVersion,
2329
+ globalLastRowId: cached.globalLastRowId,
2330
+ lastRowId: cached.lastRowId,
2331
+ rowCount: cached.rowCount,
2332
+ identityRevision: cached.identityRevision,
2333
+ unownedToolRows: new Set(cached.unownedToolRows)
2334
+ };
2335
+ }
2336
+ function scanTagOwnerDelta2(db, sessionId, state) {
2337
+ db.exec("BEGIN");
2338
+ try {
2339
+ const globalLastRowId = db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id;
2340
+ if (globalLastRowId - state.globalLastRowId > TAG_OWNER_PAGE_LIMIT)
2341
+ return null;
2342
+ const rows = appendedSinceForeignCommit(db, sessionId, state);
2343
+ if (!rows)
2344
+ return null;
2345
+ return { rows, adopted: adoptedSinceForeignCommit(db, state), globalLastRowId };
2346
+ } finally {
2347
+ db.exec("ROLLBACK");
2348
+ }
2349
+ }
2350
+ function installTagOwnerDelta2(db, sessionId, state, delta, versions) {
2351
+ const cached = tagOwnerSummaries.get(db)?.get(sessionId);
2352
+ if (!cached || cached.rowCount !== state.rowCount || cached.globalLastRowId !== state.globalLastRowId || cached.identityRevision !== state.identityRevision || delta.rows.length > TAG_OWNER_PAGE_LIMIT || delta.adopted.length > TAG_OWNER_PAGE_LIMIT)
2353
+ return false;
2354
+ tagOwnerShapeChecks++;
2355
+ tagOwnerRowsRead += delta.rows.length + delta.adopted.length;
2356
+ for (const row of delta.rows)
2357
+ foldTagOwnerRow(cached, row);
2358
+ for (const row of delta.adopted)
2359
+ foldTagOwnerRow(cached, row, false);
2360
+ cached.globalLastRowId = delta.globalLastRowId;
2361
+ cached.dataVersion = versions.dataVersion;
2362
+ cached.schemaVersion = versions.schemaVersion;
2363
+ cached.generation = versions.generation;
2364
+ return true;
2365
+ }
2366
+ function installTagOwnerSummary2(db, sessionId, summary, versions, shapeChecked = false) {
2367
+ if (shapeChecked)
2368
+ tagOwnerShapeChecks++;
2369
+ summary.dataVersion = versions.dataVersion;
2370
+ summary.schemaVersion = versions.schemaVersion;
2371
+ summary.generation = versions.generation;
2372
+ const sessions = tagOwnerSummaries.get(db) ?? new Map;
2373
+ sessions.set(sessionId, summary);
2374
+ tagOwnerSummaries.set(db, sessions);
2375
+ }
2376
+ function isTagOwnerSummaryReady2(db, sessionId, ratio) {
2377
+ try {
2378
+ readTagOwnerSummary(db, sessionId, ratio);
2379
+ return true;
2380
+ } catch (error) {
2381
+ if (error instanceof TagOwnerSummaryNotReady)
2382
+ return false;
2383
+ throw error;
2384
+ }
2385
+ }
2386
+ var tagOwnerRowsRead = 0;
2387
+ var tagOwnerShapeChecks = 0;
2388
+ function foldTagOwnerRow(summary, row, newRow = true) {
2389
+ summary.lastRowId = Math.max(summary.lastRowId, row.id);
2390
+ if (newRow)
2391
+ summary.rowCount += 1;
2392
+ if (row.type === "tool" && typeof row.tool_owner_message_id !== "string")
2393
+ summary.unownedToolRows.add(row.id);
2394
+ else
2395
+ summary.unownedToolRows.delete(row.id);
2396
+ const owner = row.type === "tool" ? typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null : typeof row.message_id === "string" ? contentTagOwnerMessageId(row.message_id) : null;
2397
+ if (owner) {
2398
+ summary.maxTagByOwner.set(owner, Math.max(summary.maxTagByOwner.get(owner) ?? 0, row.tag_number));
2399
+ }
2400
+ if (row.type !== "message" || row.reasoning_token_count === null)
2401
+ return;
2402
+ const reasoningOwner = ownerMessageIdForTagRow({
2403
+ type: row.type,
2404
+ message_id: row.message_id,
2405
+ tool_owner_message_id: row.tool_owner_message_id
2406
+ });
2407
+ for (const [ratio, estimates] of summary.reasoningEstimatesByRatio) {
2408
+ estimates.set(reasoningOwner, Math.max(estimates.get(reasoningOwner) ?? 0, row.reasoning_token_count * ratio));
2409
+ }
2410
+ }
2411
+ var TAG_OWNER_COLUMNS = "id, type, message_id, tool_owner_message_id, tag_number, reasoning_token_count";
2412
+ function connectionInTransaction(db) {
2413
+ try {
2414
+ const state = db;
2415
+ return state.inTransaction !== false && state.isTransaction !== false;
2416
+ } catch {
2417
+ return true;
2418
+ }
2419
+ }
2420
+ var TAG_OWNER_APPENDED_WITH_SHAPE_SQL = `SELECT ${TAG_OWNER_COLUMNS}, 0 AS shape, NULL AS tag_count, NULL AS max_id, NULL AS revision
2421
+ FROM tags WHERE id > ? AND +session_id = ?
2422
+ UNION ALL
2423
+ SELECT NULL, NULL, NULL, NULL, NULL, NULL, 1, COUNT(*), MAX(id), (SELECT value FROM schema_migrations_meta WHERE key = ?)
2424
+ FROM tags WHERE session_id = ?`;
2425
+ function readTagIdentityRevision(db, sessionId) {
2426
+ const row = db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(tagIdentityRevisionKey(sessionId));
2427
+ return typeof row?.value === "string" ? row.value : null;
2428
+ }
2429
+ function captureInitialTagOwnerRevision(db, sessionId, cached, appendedRows) {
2430
+ if (cached.identityRevision !== null || appendedRows === 0)
2431
+ return true;
2432
+ const revision = readTagIdentityRevision(db, sessionId);
2433
+ if (revision !== null && !/^[1-9]\d*:0$/.test(revision))
2434
+ return false;
2435
+ cached.identityRevision = revision;
2436
+ return true;
2437
+ }
2438
+ function appendedSinceForeignCommit(db, sessionId, cached) {
2439
+ tagOwnerShapeChecks += 1;
2440
+ const rows = db.prepare(TAG_OWNER_APPENDED_WITH_SHAPE_SQL).all(cached.globalLastRowId, sessionId, tagIdentityRevisionKey(sessionId), sessionId);
2441
+ const shape = rows.find((row) => row.shape === 1);
2442
+ const appended = rows.filter((row) => row.shape === 0);
2443
+ const highest = appended.reduce((max, row) => Math.max(max, row.id), cached.lastRowId);
2444
+ if (!shape || (shape.revision ?? null) !== cached.identityRevision || shape.tag_count !== cached.rowCount + appended.length || (shape.max_id ?? 0) !== highest)
2445
+ return null;
2446
+ return appended;
2447
+ }
2448
+ function adoptedSinceForeignCommit(db, cached) {
2449
+ if (cached.unownedToolRows.size === 0)
2450
+ return [];
2451
+ return db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags
2452
+ WHERE id IN (SELECT value FROM json_each(?)) AND tool_owner_message_id IS NOT NULL LIMIT ${TAG_OWNER_PAGE_LIMIT + 1}`).all(JSON.stringify([...cached.unownedToolRows]));
2453
+ }
2454
+ function readTagOwnerSummary(db, sessionId, proseRatio, extraRatios = []) {
2455
+ const inTransaction = connectionInTransaction(db);
2456
+ const versions = inTransaction ? null : db.prepare("SELECT data_version AS dataVersion, (SELECT schema_version FROM pragma_schema_version) AS schemaVersion FROM pragma_data_version").get();
2457
+ const dataVersion = versions?.dataVersion ?? -1;
2458
+ const schemaVersion = versions?.schemaVersion ?? -1;
2459
+ const generation = getTagIdentityWriteGeneration2();
2460
+ const offThreadOnly = isMainThread && Boolean(getSqliteDatabasePath2(db));
2461
+ const sessions = tagOwnerSummaries.get(db) ?? new Map;
2462
+ const cached = inTransaction ? undefined : sessions.get(sessionId);
2463
+ if (cached && (cached.generation === generation || cached.identityRevision === readTagIdentityRevision(db, sessionId)) && cached.schemaVersion === schemaVersion && (proseRatio === undefined || cached.reasoningEstimatesByRatio.has(proseRatio))) {
2464
+ let rows;
2465
+ let globalLastRowId = db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id;
2466
+ if (offThreadOnly && (globalLastRowId - cached.globalLastRowId > TAG_OWNER_PAGE_LIMIT || cached.dataVersion !== dataVersion && cached.unownedToolRows.size > TAG_OWNER_PAGE_LIMIT))
2467
+ throw new TagOwnerSummaryNotReady;
2468
+ if (cached.dataVersion === dataVersion && cached.generation === generation) {
2469
+ const statement = db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags WHERE id > ? AND +session_id = ? ORDER BY id LIMIT ${TAG_OWNER_PAGE_LIMIT + 1}`);
2470
+ rows = statement.all(cached.globalLastRowId, sessionId);
2471
+ if (!offThreadOnly) {
2472
+ let page = rows;
2473
+ while (page.length === TAG_OWNER_PAGE_LIMIT + 1) {
2474
+ page = statement.all(page[page.length - 1].id, sessionId);
2475
+ rows.push(...page);
2476
+ }
2477
+ }
2478
+ if (!captureInitialTagOwnerRevision(db, sessionId, cached, rows.length)) {
2479
+ if (offThreadOnly)
2480
+ throw new TagOwnerSummaryNotReady;
2481
+ rows = null;
2482
+ }
2483
+ } else {
2484
+ if (offThreadOnly)
2485
+ db.exec("BEGIN");
2486
+ try {
2487
+ globalLastRowId = db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM tags").get().id;
2488
+ if (offThreadOnly && globalLastRowId - cached.globalLastRowId > TAG_OWNER_PAGE_LIMIT)
2489
+ throw new TagOwnerSummaryNotReady;
2490
+ rows = appendedSinceForeignCommit(db, sessionId, cached);
2491
+ const adopted = rows ? adoptedSinceForeignCommit(db, cached) : [];
2492
+ if (!rows || rows.length > TAG_OWNER_PAGE_LIMIT || adopted.length > TAG_OWNER_PAGE_LIMIT) {
2493
+ if (offThreadOnly)
2494
+ throw new TagOwnerSummaryNotReady;
2495
+ } else if (offThreadOnly) {
2496
+ tagOwnerRowsRead += rows.length + adopted.length;
2497
+ for (const row of rows)
2498
+ foldTagOwnerRow(cached, row);
2499
+ for (const row of adopted)
2500
+ foldTagOwnerRow(cached, row, false);
2501
+ cached.dataVersion = dataVersion;
2502
+ cached.generation = generation;
2503
+ cached.globalLastRowId = globalLastRowId;
2504
+ return cached;
2505
+ }
2506
+ } finally {
2507
+ if (offThreadOnly)
2508
+ db.exec("ROLLBACK");
2509
+ }
2510
+ }
2511
+ if (rows) {
2512
+ const adopted = cached.dataVersion === dataVersion ? [] : adoptedSinceForeignCommit(db, cached);
2513
+ if (isMainThread && getSqliteDatabasePath2(db) && (rows.length > TAG_OWNER_PAGE_LIMIT || adopted.length > TAG_OWNER_PAGE_LIMIT))
2514
+ throw new TagOwnerSummaryNotReady;
2515
+ tagOwnerRowsRead += rows.length + adopted.length;
2516
+ for (const row of rows)
2517
+ foldTagOwnerRow(cached, row);
2518
+ for (const row of adopted)
2519
+ foldTagOwnerRow(cached, row, false);
2520
+ cached.dataVersion = dataVersion;
2521
+ cached.generation = generation;
2522
+ cached.globalLastRowId = globalLastRowId;
2523
+ return cached;
2524
+ }
2525
+ }
2526
+ if (isMainThread && getSqliteDatabasePath2(db))
2527
+ throw new TagOwnerSummaryNotReady;
2528
+ const ratios = [
2529
+ ...new Set([...cached?.reasoningEstimatesByRatio.keys() ?? [], ...extraRatios])
2530
+ ];
2531
+ if (proseRatio !== undefined && !ratios.includes(proseRatio))
2532
+ ratios.push(proseRatio);
2533
+ const summary = {
2534
+ dataVersion,
2535
+ schemaVersion,
2536
+ generation,
2537
+ lastRowId: 0,
2538
+ globalLastRowId: db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id,
2539
+ rowCount: 0,
2540
+ unownedToolRows: new Set,
2541
+ identityRevision: readTagIdentityRevision(db, sessionId),
2542
+ maxTagByOwner: new Map,
2543
+ reasoningEstimatesByRatio: new Map(ratios.slice(-MAX_CACHED_PROSE_RATIOS).map((ratio) => [ratio, new Map]))
2544
+ };
2545
+ const rows = db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags WHERE session_id = ? ORDER BY id`).all(sessionId);
2546
+ tagOwnerRowsRead += rows.length;
2547
+ for (const row of rows)
2548
+ foldTagOwnerRow(summary, row);
2549
+ if (!inTransaction) {
2550
+ sessions.set(sessionId, summary);
2551
+ tagOwnerSummaries.set(db, sessions);
2552
+ }
2553
+ return summary;
2554
+ }
2555
+ function tagTokenCountIsNull2(db, sessionId, tagNumber) {
2556
+ const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
2557
+ return row != null && row.token_count === null;
2558
+ }
2559
+ function backfillTagTokenCounts2(db, sessionId, tagNumber, counts) {
2560
+ db.prepare(`UPDATE tags
2561
+ SET token_count = CASE WHEN ? IS NOT NULL THEN MAX(COALESCE(token_count, 0), ?) ELSE token_count END,
2562
+ input_token_count = ?,
2563
+ reasoning_token_count = ?
2564
+ WHERE session_id = ? AND tag_number = ? AND token_count IS NULL`).run(counts.tokenCount ?? null, counts.tokenCount ?? null, counts.inputTokenCount ?? null, counts.reasoningTokenCount ?? null, sessionId, tagNumber);
2565
+ }
2566
+ function getUpdateTagMessageIdStatement(db) {
2567
+ let stmt = updateTagMessageIdStatements.get(db);
2568
+ if (!stmt) {
2569
+ stmt = db.prepare(`UPDATE tags SET message_id = ?
2570
+ WHERE session_id = ?
2571
+ AND tag_number = ?
2572
+ AND message_id NOT LIKE '${WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX}%'`);
2573
+ updateTagMessageIdStatements.set(db, stmt);
2574
+ }
2575
+ return stmt;
2576
+ }
2577
+ function getTagNumbersByMessageIdStatement(db) {
2578
+ let stmt = getTagNumbersByMessageIdStatements.get(db);
2579
+ if (!stmt) {
2580
+ stmt = db.prepare("SELECT tag_number FROM tags WHERE session_id = ? AND (message_id = ? OR message_id LIKE ? ESCAPE '\\' OR message_id LIKE ? ESCAPE '\\' OR message_id LIKE ? ESCAPE '\\') ORDER BY tag_number ASC");
2581
+ getTagNumbersByMessageIdStatements.set(db, stmt);
2582
+ }
2583
+ return stmt;
2584
+ }
2585
+ function getDeleteTagsByMessageIdStatement(db) {
2586
+ let stmt = deleteTagsByMessageIdStatements.get(db);
2587
+ if (!stmt) {
2588
+ stmt = db.prepare("DELETE FROM tags WHERE session_id = ? AND (message_id = ? OR message_id LIKE ? ESCAPE '\\' OR message_id LIKE ? ESCAPE '\\' OR message_id LIKE ? ESCAPE '\\')");
2589
+ deleteTagsByMessageIdStatements.set(db, stmt);
2590
+ }
2591
+ return stmt;
2592
+ }
2593
+ function getMaxTagNumberBySessionStatement(db) {
2594
+ let stmt = getMaxTagNumberBySessionStatements.get(db);
2595
+ if (!stmt) {
2596
+ stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ?");
2597
+ getMaxTagNumberBySessionStatements.set(db, stmt);
2598
+ }
2599
+ return stmt;
2600
+ }
2601
+ function getTagNumberByMessageIdStatement(db) {
2602
+ let stmt = getTagNumberByMessageIdStatements.get(db);
2603
+ if (!stmt) {
2604
+ stmt = db.prepare("SELECT tag_number FROM tags INDEXED BY idx_tags_session_message_id WHERE session_id = ? AND message_id = ? ORDER BY tag_number ASC LIMIT 1");
2605
+ getTagNumberByMessageIdStatements.set(db, stmt);
2606
+ }
2607
+ return stmt;
2608
+ }
2609
+ function getAssignableTagNumberByMessageIdStatement(db) {
2610
+ let stmt = getAssignableTagNumberByMessageIdStatements.get(db);
2611
+ if (!stmt) {
2612
+ stmt = db.prepare(`SELECT tag_number FROM tags INDEXED BY idx_tags_session_message_id
2613
+ WHERE session_id = ?
2614
+ AND message_id = ?
2615
+ AND NOT (
2616
+ status = 'compacted'
2617
+ AND COALESCE(
2618
+ entry_fingerprint LIKE '${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%',
2619
+ 0
2620
+ ) = 1
2621
+ )
2622
+ ORDER BY tag_number ASC
2623
+ LIMIT 1`);
2624
+ getAssignableTagNumberByMessageIdStatements.set(db, stmt);
2625
+ }
2626
+ return stmt;
2627
+ }
2628
+ function isTagRow(row) {
2629
+ if (row === null || typeof row !== "object")
2630
+ return false;
2631
+ const r = row;
2632
+ return typeof r.id === "number" && typeof r.message_id === "string" && typeof r.type === "string" && typeof r.status === "string" && typeof r.byte_size === "number" && typeof r.session_id === "string" && typeof r.tag_number === "number";
2633
+ }
2634
+ function toTagEntry(row) {
2635
+ const type = row.type === "tool" ? "tool" : row.type === "file" ? "file" : "message";
2636
+ const status = row.status === "dropped" || row.status === "compacted" ? row.status : "active";
2637
+ return {
2638
+ id: row.id,
2639
+ tagNumber: row.tag_number,
2640
+ messageId: row.message_id,
2641
+ type,
2642
+ status,
2643
+ dropMode: row.drop_mode === "truncated" ? "truncated" : row.drop_mode === "skeleton_real" ? "skeleton_real" : row.drop_mode === "skeleton_stripped" ? "skeleton_stripped" : row.drop_mode === "edit_marker" ? "edit_marker" : row.drop_mode === "edit_marker_stripped" ? "edit_marker_stripped" : "full",
2644
+ toolName: row.tool_name ?? null,
2645
+ inputByteSize: row.input_byte_size ?? 0,
2646
+ byteSize: row.byte_size,
2647
+ reasoningByteSize: row.reasoning_byte_size ?? 0,
2648
+ sessionId: row.session_id,
2649
+ cavemanDepth: typeof row.caveman_depth === "number" && Number.isFinite(row.caveman_depth) ? row.caveman_depth : 0,
2650
+ toolOwnerMessageId: typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null,
2651
+ tokenCount: typeof row.token_count === "number" ? row.token_count : null
2652
+ };
2653
+ }
2654
+ function isTagNumberRow(row) {
2655
+ if (row === null || typeof row !== "object")
2656
+ return false;
2657
+ const r = row;
2658
+ return typeof r.tag_number === "number";
2659
+ }
2660
+ function isMaxTagNumberRow(row) {
2661
+ if (row === null || typeof row !== "object")
2662
+ return false;
2663
+ const r = row;
2664
+ return typeof r.max_tag_number === "number";
2665
+ }
2666
+ function escapeLikePattern(value) {
2667
+ return value.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
2668
+ }
2669
+ function insertTag2(db, sessionId, messageId, type, byteSize, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null, tokenCounts = null) {
2670
+ getInsertTagStatement(db).run(sessionId, messageId, type, byteSize, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness2(), toolOwnerMessageId, entryFingerprint, tokenCounts?.tokenCount ?? null, tokenCounts?.inputTokenCount ?? null, tokenCounts?.reasoningTokenCount ?? null);
2671
+ return tagNumber;
2672
+ }
2673
+ function updateTagStatus2(db, sessionId, tagId, status) {
2674
+ getUpdateTagStatusStatement(db).run(status, sessionId, tagId);
2675
+ }
2676
+ function markWhitespaceAssistantTagInert2(db, sessionId, tagNumber, contentId) {
2677
+ db.prepare(`UPDATE tags
2678
+ SET status = 'compacted',
2679
+ message_id = ?,
2680
+ entry_fingerprint = ?
2681
+ WHERE session_id = ? AND tag_number = ? AND type = 'message'`).run(`${WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX}${tagNumber}`, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}${contentId}`, sessionId, tagNumber);
2682
+ }
2683
+ var inertWhitespaceStatements = new WeakMap;
2684
+ function getInertWhitespaceAssistantTags2(db, sessionId, messageIds) {
2685
+ if (messageIds) {
2686
+ let statement = inertWhitespaceStatements.get(db);
2687
+ if (!statement) {
2688
+ statement = db.prepare(`SELECT tag_number AS tagNumber, entry_fingerprint AS entryFingerprint
2689
+ FROM json_each(?) AS owners CROSS JOIN tags
2690
+ WHERE tags.session_id = ? AND tags.type = 'message' AND tags.status = 'compacted'
2691
+ AND entry_fingerprint >= ? || owners.value || ':p'
2692
+ AND entry_fingerprint < ? || owners.value || ':q'
2693
+ ORDER BY CAST(owners.key AS INTEGER), entry_fingerprint, tags.id`);
2694
+ inertWhitespaceStatements.set(db, statement);
2695
+ }
2696
+ const rows = statement.all(JSON.stringify([...new Set(messageIds)]), sessionId, WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX, WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX);
2697
+ return rows.map((row) => ({
2698
+ tagNumber: row.tagNumber,
2699
+ contentId: row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length)
2700
+ }));
2701
+ }
2702
+ const rows = db.prepare(`SELECT tag_number AS tagNumber, entry_fingerprint AS entryFingerprint
2703
+ FROM tags
2704
+ WHERE session_id = ?
2705
+ AND type = 'message'
2706
+ AND status = 'compacted'
2707
+ AND entry_fingerprint LIKE ?`).all(sessionId, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%`);
2708
+ return rows.flatMap((row) => {
2709
+ const contentId = row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length);
2710
+ return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
2711
+ });
2712
+ }
2713
+ var inertWhitespaceByNumberStatements = new WeakMap;
2714
+ function getInertWhitespaceAssistantTagsByNumbers2(db, sessionId, tagNumbers) {
2715
+ if (tagNumbers.length === 0)
2716
+ return [];
2717
+ let statement = inertWhitespaceByNumberStatements.get(db);
2718
+ if (!statement) {
2719
+ statement = db.prepare(`SELECT tags.tag_number AS tagNumber, tags.entry_fingerprint AS entryFingerprint
2720
+ FROM json_each(?) AS wanted CROSS JOIN tags
2721
+ WHERE tags.session_id = ?
2722
+ AND tags.tag_number = wanted.value
2723
+ AND tags.type = 'message'
2724
+ AND tags.status = 'compacted'
2725
+ AND tags.entry_fingerprint LIKE ?
2726
+ ORDER BY tags.tag_number, tags.id`);
2727
+ inertWhitespaceByNumberStatements.set(db, statement);
2728
+ }
2729
+ const rows = statement.all(JSON.stringify([...new Set(tagNumbers)]), sessionId, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%`);
2730
+ return rows.flatMap((row) => {
2731
+ const contentId = row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length);
2732
+ return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
2733
+ });
2734
+ }
2735
+ function updateTagDropMode2(db, sessionId, tagNumber, dropMode) {
2736
+ getUpdateTagDropModeStatement(db).run(dropMode, sessionId, tagNumber);
2737
+ }
2738
+ function updateCavemanDepth2(db, sessionId, tagNumber, depth) {
2739
+ db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
2740
+ }
2741
+ function updateTagMessageId2(db, sessionId, tagId, messageId) {
2742
+ getUpdateTagMessageIdStatement(db).run(messageId, sessionId, tagId);
2743
+ }
2744
+ function hasPiFallbackMessageTags2(db, sessionId) {
2745
+ let statement = hasPiFallbackMessageTagStatements.get(db);
2746
+ if (!statement) {
2747
+ statement = db.prepare(`SELECT 1
2748
+ FROM tags
2749
+ WHERE session_id = ?
2750
+ AND type = 'message'
2751
+ AND message_id LIKE 'pi-msg-%'
2752
+ LIMIT 1`);
2753
+ hasPiFallbackMessageTagStatements.set(db, statement);
2754
+ }
2755
+ return statement.get(sessionId) != null;
2756
+ }
2757
+ function findAdoptableFallbackTags2(db, sessionId, entryFingerprint) {
2758
+ const rows = db.prepare(`SELECT tag_number AS tagNumber, message_id AS messageId
2759
+ FROM tags
2760
+ WHERE session_id = ?
2761
+ AND type = 'message'
2762
+ AND entry_fingerprint = ?
2763
+ AND message_id LIKE 'pi-msg-%'`).all(sessionId, entryFingerprint);
2764
+ return rows;
2765
+ }
2766
+ function adoptFallbackTagMessageId2(db, sessionId, tagNumber, oldFallbackMessageId, newRealMessageId) {
2767
+ if (oldFallbackMessageId.startsWith(WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX))
2768
+ return false;
2769
+ const result = db.prepare(`UPDATE tags SET message_id = ?
2770
+ WHERE session_id = ? AND tag_number = ? AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
2771
+ return (result.changes ?? 0) > 0;
2772
+ }
2773
+ function isPiFallbackToolOwnerTag(row) {
2774
+ if (row === null || typeof row !== "object")
2775
+ return false;
2776
+ const r = row;
2777
+ return typeof r.tagNumber === "number" && typeof r.callId === "string" && typeof r.toolOwnerMessageId === "string" && typeof r.status === "string";
2778
+ }
2779
+ function isPiFallbackFoldTagRow(row) {
2780
+ if (row === null || typeof row !== "object")
2781
+ return false;
2782
+ const r = row;
2783
+ return typeof r.tagNumber === "number" && typeof r.messageId === "string" && (typeof r.toolOwnerMessageId === "string" || r.toolOwnerMessageId === null) && typeof r.type === "string" && typeof r.status === "string" && (typeof r.byteSize === "number" || r.byteSize === null) && (typeof r.reasoningByteSize === "number" || r.reasoningByteSize === null) && (typeof r.inputByteSize === "number" || r.inputByteSize === null) && (typeof r.tokenCount === "number" || r.tokenCount === null) && (typeof r.inputTokenCount === "number" || r.inputTokenCount === null) && (typeof r.reasoningTokenCount === "number" || r.reasoningTokenCount === null);
2784
+ }
2785
+ function isPendingOpIdentityRow(row) {
2786
+ if (row === null || typeof row !== "object")
2787
+ return false;
2788
+ const r = row;
2789
+ return typeof r.id === "number" && typeof r.operation === "string";
2790
+ }
2791
+ function maxNullableNumber(a, b) {
2792
+ if (typeof a === "number" && typeof b === "number")
2793
+ return Math.max(a, b);
2794
+ if (typeof a === "number")
2795
+ return a;
2796
+ if (typeof b === "number")
2797
+ return b;
2798
+ return null;
2799
+ }
2800
+ function getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber) {
2801
+ const row = db.prepare(`SELECT tag_number AS tagNumber,
2802
+ message_id AS messageId,
2803
+ tool_owner_message_id AS toolOwnerMessageId,
2804
+ type,
2805
+ status,
2806
+ byte_size AS byteSize,
2807
+ reasoning_byte_size AS reasoningByteSize,
2808
+ input_byte_size AS inputByteSize,
2809
+ token_count AS tokenCount,
2810
+ input_token_count AS inputTokenCount,
2811
+ reasoning_token_count AS reasoningTokenCount
2812
+ FROM tags
2813
+ WHERE session_id = ? AND tag_number = ?`).get(sessionId, tagNumber);
2814
+ return isPiFallbackFoldTagRow(row) ? row : null;
2815
+ }
2816
+ function getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, ownerMsgId) {
2817
+ const row = db.prepare(`SELECT tag_number AS tagNumber,
2818
+ message_id AS messageId,
2819
+ tool_owner_message_id AS toolOwnerMessageId,
2820
+ type,
2821
+ status,
2822
+ byte_size AS byteSize,
2823
+ reasoning_byte_size AS reasoningByteSize,
2824
+ input_byte_size AS inputByteSize,
2825
+ token_count AS tokenCount,
2826
+ input_token_count AS inputTokenCount,
2827
+ reasoning_token_count AS reasoningTokenCount
2828
+ FROM tags
2829
+ WHERE session_id = ?
2830
+ AND message_id = ?
2831
+ AND type = 'tool'
2832
+ AND tool_owner_message_id = ?
2833
+ LIMIT 1`).get(sessionId, callId, ownerMsgId);
2834
+ return isPiFallbackFoldTagRow(row) ? row : null;
2835
+ }
2836
+ function getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, messageId) {
2837
+ return db.prepare(`SELECT tag_number AS tagNumber,
2838
+ message_id AS messageId,
2839
+ tool_owner_message_id AS toolOwnerMessageId,
2840
+ type,
2841
+ status,
2842
+ byte_size AS byteSize,
2843
+ reasoning_byte_size AS reasoningByteSize,
2844
+ input_byte_size AS inputByteSize,
2845
+ token_count AS tokenCount,
2846
+ input_token_count AS inputTokenCount,
2847
+ reasoning_token_count AS reasoningTokenCount
2848
+ FROM tags
2849
+ WHERE session_id = ?
2850
+ AND message_id = ?
2851
+ AND type = 'message'
2852
+ ORDER BY tag_number ASC`).all(sessionId, messageId).filter(isPiFallbackFoldTagRow);
2853
+ }
2854
+ var foldStatements = new WeakMap;
2855
+ function foldStatement(db, sql) {
2856
+ let statements = foldStatements.get(db);
2857
+ if (!statements) {
2858
+ statements = new Map;
2859
+ foldStatements.set(db, statements);
2860
+ }
2861
+ let statement = statements.get(sql);
2862
+ if (!statement) {
2863
+ statement = db.prepare(sql);
2864
+ statements.set(sql, statement);
2865
+ }
2866
+ return statement;
2867
+ }
2868
+ function mergeSizeAndTokenColumnsIntoSurvivor(db, sessionId, survivor, duplicate) {
2869
+ foldStatement(db, `UPDATE tags
2870
+ SET byte_size = ?,
2871
+ reasoning_byte_size = ?,
2872
+ input_byte_size = ?,
2873
+ token_count = ?,
2874
+ input_token_count = ?,
2875
+ reasoning_token_count = ?
2876
+ WHERE session_id = ? AND tag_number = ?`).run(maxNullableNumber(survivor.byteSize, duplicate.byteSize), maxNullableNumber(survivor.reasoningByteSize, duplicate.reasoningByteSize), maxNullableNumber(survivor.inputByteSize, duplicate.inputByteSize), maxNullableNumber(survivor.tokenCount, duplicate.tokenCount), maxNullableNumber(survivor.inputTokenCount, duplicate.inputTokenCount), maxNullableNumber(survivor.reasoningTokenCount, duplicate.reasoningTokenCount), sessionId, survivor.tagNumber);
2877
+ survivor.byteSize = maxNullableNumber(survivor.byteSize, duplicate.byteSize);
2878
+ survivor.reasoningByteSize = maxNullableNumber(survivor.reasoningByteSize, duplicate.reasoningByteSize);
2879
+ survivor.inputByteSize = maxNullableNumber(survivor.inputByteSize, duplicate.inputByteSize);
2880
+ survivor.tokenCount = maxNullableNumber(survivor.tokenCount, duplicate.tokenCount);
2881
+ survivor.inputTokenCount = maxNullableNumber(survivor.inputTokenCount, duplicate.inputTokenCount);
2882
+ survivor.reasoningTokenCount = maxNullableNumber(survivor.reasoningTokenCount, duplicate.reasoningTokenCount);
2883
+ }
2884
+ function applyDroppedStatusIfNeeded(db, sessionId, survivor, duplicate) {
2885
+ if (survivor.status === "dropped")
2886
+ return;
2887
+ if (duplicate.status !== "dropped")
2888
+ return;
2889
+ foldStatement(db, "UPDATE tags SET status = 'dropped' WHERE session_id = ? AND tag_number = ?").run(sessionId, survivor.tagNumber);
2890
+ survivor.status = "dropped";
2891
+ }
2892
+ function retargetPendingOps(db, sessionId, fromTagNumber, toTagNumber) {
2893
+ const rows = foldStatement(db, `SELECT id, operation
2894
+ FROM pending_ops
2895
+ WHERE session_id = ? AND tag_id = ?
2896
+ ORDER BY id ASC`).all(sessionId, fromTagNumber).filter(isPendingOpIdentityRow);
2897
+ for (const row of rows) {
2898
+ const existing = foldStatement(db, `SELECT 1
2899
+ FROM pending_ops
2900
+ WHERE session_id = ? AND tag_id = ? AND operation = ?
2901
+ LIMIT 1`).get(sessionId, toTagNumber, row.operation);
2902
+ if (existing) {
2903
+ foldStatement(db, "DELETE FROM pending_ops WHERE session_id = ? AND id = ?").run(sessionId, row.id);
2904
+ } else {
2905
+ foldStatement(db, "UPDATE pending_ops SET tag_id = ? WHERE session_id = ? AND id = ?").run(toTagNumber, sessionId, row.id);
2906
+ }
2907
+ }
2908
+ foldStatement(db, "DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?").run(sessionId, fromTagNumber);
2909
+ }
2910
+ function deleteFoldedDuplicateTag(db, sessionId, tagNumber) {
2911
+ foldStatement(db, "DELETE FROM source_contents WHERE session_id = ? AND tag_id = ?").run(sessionId, tagNumber);
2912
+ foldStatement(db, "DELETE FROM tags WHERE session_id = ? AND tag_number = ?").run(sessionId, tagNumber);
2913
+ foldStatement(db, "DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?").run(sessionId, tagNumber);
2914
+ }
2915
+ function foldDuplicateIntoSurvivor(db, sessionId, survivor, duplicate, duplicateMayHaveQueuedOps = true, propagateDroppedStatus = true) {
2916
+ mergeSizeAndTokenColumnsIntoSurvivor(db, sessionId, survivor, duplicate);
2917
+ if (propagateDroppedStatus)
2918
+ applyDroppedStatusIfNeeded(db, sessionId, survivor, duplicate);
2919
+ if (duplicateMayHaveQueuedOps) {
2920
+ retargetPendingOps(db, sessionId, duplicate.tagNumber, survivor.tagNumber);
2921
+ }
2922
+ deleteFoldedDuplicateTag(db, sessionId, duplicate.tagNumber);
2923
+ }
2924
+ function readPartTagRowsByMessage(db, sessionId) {
2925
+ const rows = db.prepare(`SELECT tag_number AS tagNumber,
2926
+ message_id AS messageId,
2927
+ tool_owner_message_id AS toolOwnerMessageId,
2928
+ type,
2929
+ status,
2930
+ byte_size AS byteSize,
2931
+ reasoning_byte_size AS reasoningByteSize,
2932
+ input_byte_size AS inputByteSize,
2933
+ token_count AS tokenCount,
2934
+ input_token_count AS inputTokenCount,
2935
+ reasoning_token_count AS reasoningTokenCount
2936
+ FROM tags
2937
+ WHERE session_id = ?
2938
+ AND type = 'message'
2939
+ ORDER BY tag_number ASC`).all(sessionId).filter(isPiFallbackFoldTagRow);
2940
+ const byMessage = new Map;
2941
+ for (const row of rows) {
2942
+ const marker = row.messageId.lastIndexOf(":p");
2943
+ if (marker < 0)
2944
+ continue;
2945
+ const suffix = row.messageId.slice(marker + 2);
2946
+ if (!/^\d+$/.test(suffix))
2947
+ continue;
2948
+ const messageId = row.messageId.slice(0, marker);
2949
+ const group = byMessage.get(messageId);
2950
+ const entry = { ...row, partIndex: Number.parseInt(suffix, 10) };
2951
+ if (group)
2952
+ group.push(entry);
2953
+ else
2954
+ byMessage.set(messageId, [entry]);
2955
+ }
2956
+ for (const group of byMessage.values())
2957
+ group.sort((a, b) => a.partIndex - b.partIndex);
2958
+ return byMessage;
2959
+ }
2960
+ function readQueuedTagNumbers(db, sessionId) {
2961
+ const rows = db.prepare("SELECT tag_id AS tagNumber, operation FROM pending_ops WHERE session_id = ? AND tag_id IS NOT NULL").all(sessionId);
2962
+ const any = new Set;
2963
+ const drop = new Set;
2964
+ for (const row of rows) {
2965
+ if (typeof row.tagNumber !== "number")
2966
+ continue;
2967
+ any.add(row.tagNumber);
2968
+ if (row.operation === "drop")
2969
+ drop.add(row.tagNumber);
2970
+ }
2971
+ return { any, drop };
2972
+ }
2973
+ function foldShrunkPartTags2(db, sessionId, messages) {
2974
+ const result = {
2975
+ foldedTagNumbers: [],
2976
+ rekeyedTagNumbers: [],
2977
+ discardedDropTagNumbers: []
2978
+ };
2979
+ if (messages.length === 0)
2980
+ return result;
2981
+ const rowsByMessage = readPartTagRowsByMessage(db, sessionId);
2982
+ const queuedTags = readQueuedTagNumbers(db, sessionId);
2983
+ const discardDrop = foldStatement(db, "DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ? AND operation = 'drop'");
2984
+ const rekey = foldStatement(db, "UPDATE tags SET message_id = ? WHERE session_id = ? AND tag_number = ? AND type = 'message'");
2985
+ for (const { messageId, partCount } of messages) {
2986
+ const rows = rowsByMessage.get(messageId) ?? [];
2987
+ if (rows.length === 0)
2988
+ continue;
2989
+ const orphans = rows.filter((row) => row.partIndex >= partCount);
2990
+ if (orphans.length === 0)
2991
+ continue;
2992
+ const queued = [
2993
+ ...new Set(rows.map((row) => row.tagNumber).filter((tag) => queuedTags.drop.has(tag)))
2994
+ ].sort((a, b) => a - b);
2995
+ if (queued.length > 0 && queued.length < rows.length) {
2996
+ for (const tagNumber of queued) {
2997
+ discardDrop.run(sessionId, tagNumber);
2998
+ result.discardedDropTagNumbers.push(tagNumber);
2999
+ }
3000
+ }
3001
+ let survivor = rows.find((row) => row.partIndex < partCount) ?? null;
3002
+ if (survivor === null) {
3003
+ const lowest = orphans[0];
3004
+ if (!lowest)
3005
+ continue;
3006
+ rekey.run(`${messageId}:p0`, sessionId, lowest.tagNumber);
3007
+ result.rekeyedTagNumbers.push(lowest.tagNumber);
3008
+ survivor = { ...lowest, messageId: `${messageId}:p0`, partIndex: 0 };
3009
+ }
3010
+ for (const orphan of orphans) {
3011
+ if (orphan.tagNumber === survivor.tagNumber)
3012
+ continue;
3013
+ foldDuplicateIntoSurvivor(db, sessionId, survivor, orphan, queuedTags.any.has(orphan.tagNumber), false);
3014
+ result.foldedTagNumbers.push(orphan.tagNumber);
3015
+ }
3016
+ }
3017
+ result.discardedDropTagNumbers.sort((a, b) => a - b);
3018
+ result.foldedTagNumbers.sort((a, b) => a - b);
3019
+ return result;
3020
+ }
3021
+ function hasPiFallbackToolOwnerTags2(db, sessionId) {
3022
+ const row = db.prepare(`SELECT 1
3023
+ FROM tags
3024
+ WHERE session_id = ?
3025
+ AND type = 'tool'
3026
+ AND tool_owner_message_id LIKE 'pi-msg-%'
3027
+ LIMIT 1`).get(sessionId);
3028
+ return row != null;
3029
+ }
3030
+ function findPiFallbackToolOwnerTags2(db, sessionId) {
3031
+ return db.prepare(`SELECT tag_number AS tagNumber,
3032
+ message_id AS callId,
3033
+ tool_owner_message_id AS toolOwnerMessageId,
3034
+ status
3035
+ FROM tags
3036
+ WHERE session_id = ?
3037
+ AND type = 'tool'
3038
+ AND tool_owner_message_id LIKE 'pi-msg-%'
3039
+ ORDER BY tag_number ASC`).all(sessionId).filter(isPiFallbackToolOwnerTag);
3040
+ }
3041
+
3042
+ class PiTagIdentityConflictError extends Error {
3043
+ code = "PI_TAG_IDENTITY_CONFLICT";
3044
+ constructor(detail, kind = "tool") {
3045
+ super(`Magic Context ${kind}-tag identity conflict: ${detail}. This turn was refused without sending raw history; resending alone will not repair it`);
3046
+ this.name = "PiTagIdentityConflictError";
3047
+ }
3048
+ }
3049
+ function selectPiTagSurvivor(rows, servedTagNumbers, cachedSurvivor, kind, rebuildingSurvivor) {
3050
+ const served = rows.filter((row) => servedTagNumbers.has(row.tagNumber));
3051
+ const cached = cachedSurvivor === undefined ? undefined : rows.find((row) => row.tagNumber === cachedSurvivor);
3052
+ const rebuilding = rows.find((row) => row.tagNumber === rebuildingSurvivor);
3053
+ if (cachedSurvivor !== undefined && !cached || served.length !== 1 && !cached && !rebuilding) {
3054
+ throw new PiTagIdentityConflictError(served.length > 1 ? `Conflicting served Pi ${kind} tag numbers; no byte-safe cached survivor is proven` : `duplicate ${kind} tag identities have no proven served-byte survivor`, kind);
3055
+ }
3056
+ const kept = cached ?? rebuilding ?? served[0];
3057
+ if (!kept)
3058
+ throw new PiTagIdentityConflictError("no served survivor is proven", kind);
3059
+ return kept;
3060
+ }
3061
+ function foldPiIdentityDuplicate(db, sessionId, kept, duplicate) {
3062
+ const owesDrop = kept.status !== "dropped" && duplicate.status === "dropped";
3063
+ foldDuplicateIntoSurvivor(db, sessionId, kept, duplicate, true, false);
3064
+ if (owesDrop)
3065
+ queuePendingOp(db, sessionId, kept.tagNumber, "drop");
3066
+ }
3067
+ function adoptPiFallbackToolOwnerTag2(db, sessionId, tagNumber, callId, oldOwnerMessageId, newOwnerMessageId, servedTagNumbers = new Set, cachedSurvivor, rebuildingSurvivor) {
3068
+ const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
3069
+ if (survivor === null || survivor.type !== "tool" || survivor.messageId !== callId || survivor.toolOwnerMessageId !== oldOwnerMessageId) {
3070
+ return { action: "skipped" };
3071
+ }
3072
+ const existing = getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, newOwnerMessageId);
3073
+ if (existing === null) {
3074
+ const result = db.prepare(`UPDATE tags
3075
+ SET tool_owner_message_id = ?
3076
+ WHERE session_id = ?
3077
+ AND tag_number = ?
3078
+ AND type = 'tool'
3079
+ AND message_id = ?
3080
+ AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
3081
+ return (result.changes ?? 0) > 0 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
3082
+ }
3083
+ if (existing.tagNumber === tagNumber) {
3084
+ return { action: "skipped" };
3085
+ }
3086
+ const kept = selectPiTagSurvivor([survivor, existing], servedTagNumbers, cachedSurvivor, "tool", rebuildingSurvivor);
3087
+ if (kept.tagNumber === survivor.tagNumber) {
3088
+ foldPiIdentityDuplicate(db, sessionId, survivor, existing);
3089
+ db.prepare("UPDATE tags SET tool_owner_message_id = ? WHERE session_id = ? AND tag_number = ?").run(newOwnerMessageId, sessionId, tagNumber);
3090
+ return { action: "folded", tagNumber, deletedTagNumbers: [existing.tagNumber] };
3091
+ }
3092
+ foldPiIdentityDuplicate(db, sessionId, existing, survivor);
3093
+ return {
3094
+ action: "folded",
3095
+ tagNumber: existing.tagNumber,
3096
+ deletedTagNumbers: [tagNumber]
3097
+ };
3098
+ }
3099
+ function adoptPiFallbackMessageTag2(db, sessionId, tagNumber, oldFallbackMessageId, newRealMessageId, servedTagNumbers = new Set, cachedSurvivor, rebuildingSurvivor) {
3100
+ if (oldFallbackMessageId.startsWith(WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX)) {
3101
+ return { action: "skipped" };
3102
+ }
3103
+ const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
3104
+ if (survivor === null || survivor.type !== "message" || survivor.messageId !== oldFallbackMessageId) {
3105
+ return { action: "skipped" };
3106
+ }
3107
+ const duplicates = getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, newRealMessageId).filter((row) => row.tagNumber !== tagNumber);
3108
+ if (duplicates.length === 0) {
3109
+ const result = db.prepare(`UPDATE tags
3110
+ SET message_id = ?
3111
+ WHERE session_id = ?
3112
+ AND tag_number = ?
3113
+ AND type = 'message'
3114
+ AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
3115
+ return (result.changes ?? 0) > 0 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
3116
+ }
3117
+ const realSurvivor = selectPiTagSurvivor([survivor, ...duplicates], servedTagNumbers, cachedSurvivor, "message", rebuildingSurvivor);
3118
+ const deletedTagNumbers = [];
3119
+ for (const duplicate of [survivor, ...duplicates]) {
3120
+ if (duplicate.tagNumber === realSurvivor.tagNumber)
3121
+ continue;
3122
+ foldPiIdentityDuplicate(db, sessionId, realSurvivor, duplicate);
3123
+ deletedTagNumbers.push(duplicate.tagNumber);
3124
+ }
3125
+ if (realSurvivor.tagNumber === tagNumber) {
3126
+ db.prepare("UPDATE tags SET message_id = ? WHERE session_id = ? AND tag_number = ?").run(newRealMessageId, sessionId, tagNumber);
3127
+ }
3128
+ return {
3129
+ action: "folded",
3130
+ tagNumber: realSurvivor.tagNumber,
3131
+ deletedTagNumbers
3132
+ };
3133
+ }
3134
+ function markTagsCompactedByMessageIds2(db, sessionId, messageIds, eligibleTagNumbers) {
3135
+ const ids = new Set(messageIds);
3136
+ if (ids.size === 0 || eligibleTagNumbers?.size === 0)
3137
+ return 0;
3138
+ const asciiLower = (value) => value.replace(/[A-Z]/g, (char) => char.toLowerCase());
3139
+ const foldedIds = new Set(Array.from(ids, asciiLower));
3140
+ const nulPrefixes = new Set(Array.from(ids).filter((id) => id.includes("\x00")).map((id) => asciiLower(id.split("\x00")[0])));
3141
+ const matches = (messageId, owner) => {
3142
+ if (messageId !== null && ids.has(messageId))
3143
+ return true;
3144
+ if (owner !== null && ids.has(owner))
3145
+ return true;
3146
+ if (messageId === null)
3147
+ return false;
3148
+ const nul = messageId.indexOf("\x00");
3149
+ const value = nul < 0 ? messageId : messageId.slice(0, nul);
3150
+ if (nulPrefixes.size > 0 && nulPrefixes.has(asciiLower(value)))
3151
+ return true;
3152
+ for (let colon = value.indexOf(":");colon >= 0; colon = value.indexOf(":", colon + 1)) {
3153
+ const suffix = value[colon + 1];
3154
+ if ((suffix === "p" || suffix === "P" || asciiLower(value.slice(colon + 1, colon + 5)) === "file") && foldedIds.has(asciiLower(value.slice(0, colon))))
3155
+ return true;
3156
+ }
3157
+ return false;
3158
+ };
3159
+ const rows = db.prepare(`WITH ids AS MATERIALIZED (
3160
+ SELECT value AS source_id, lower(value) AS folded_id FROM json_each(?)
3161
+ )
3162
+ SELECT id, tag_number, message_id, tool_owner_message_id FROM tags INDEXED BY ${tagOrderConstraintIndex(db)}
3163
+ WHERE session_id = ? ${eligibleTagNumbers ? "AND tag_number IN (SELECT value FROM json_each(?))" : ""}
3164
+ AND status IN ('active', 'dropped') AND (
3165
+ message_id IN (SELECT source_id FROM ids)
3166
+ OR tool_owner_message_id IN (SELECT source_id FROM ids)
3167
+ OR (instr(lower(message_id), ':p') > 0 AND
3168
+ lower(substr(message_id, 1, instr(lower(message_id), ':p') - 1)) IN (SELECT folded_id FROM ids))
3169
+ OR (instr(lower(message_id), ':file') > 0 AND
3170
+ lower(substr(message_id, 1, instr(lower(message_id), ':file') - 1)) IN (SELECT folded_id FROM ids))
3171
+ OR (? AND instr(message_id, ':') > 0)
3172
+ OR ?
3173
+ )`).all(JSON.stringify(Array.from(ids)), sessionId, ...eligibleTagNumbers ? [JSON.stringify([...eligibleTagNumbers])] : [], Array.from(ids).some((id) => id.includes(":")) ? 1 : 0, nulPrefixes.size > 0 ? 1 : 0);
3174
+ const candidates = rows.filter((row) => (eligibleTagNumbers === undefined || eligibleTagNumbers.has(row.tag_number)) && matches(row.message_id, row.tool_owner_message_id));
3175
+ if (candidates.length === 0)
3176
+ return 0;
3177
+ const update = db.prepare(`UPDATE tags SET status = 'compacted'
3178
+ WHERE id = ? AND session_id = ?
3179
+ AND status IN ('active', 'dropped')
3180
+ AND message_id IS ? AND tool_owner_message_id IS ?
3181
+ RETURNING tag_number`);
3182
+ let cursor = 0;
3183
+ let changed = 0;
3184
+ const batch = db.transaction(() => {
3185
+ const start = performance.now();
3186
+ let processed = 0;
3187
+ do {
3188
+ const row = candidates[cursor++];
3189
+ const retired = update.get(row.id, sessionId, row.message_id, row.tool_owner_message_id);
3190
+ if (retired) {
3191
+ removePendingOp(db, sessionId, retired.tag_number);
3192
+ changed++;
3193
+ }
3194
+ processed++;
3195
+ } while (cursor < candidates.length && processed < 128 && performance.now() - start < 8);
3196
+ });
3197
+ while (cursor < candidates.length)
3198
+ batch.immediate();
3199
+ return changed;
3200
+ }
3201
+ function deleteTagsByMessageId2(db, sessionId, messageId) {
3202
+ const deleteTransaction = db.transaction(() => {
3203
+ const escapedMessageId = escapeLikePattern(messageId);
3204
+ const textPartPattern = `${escapedMessageId}:p%`;
3205
+ const filePartPattern = `${escapedMessageId}:file%`;
3206
+ const contentDerivedTextPattern = `${escapedMessageId}${escapeLikePattern(TEXT_TAG_IDENTITY_MARKER)}%`;
3207
+ const messageScopedTags = getTagNumbersByMessageIdStatement(db).all(sessionId, messageId, textPartPattern, filePartPattern, contentDerivedTextPattern).filter(isTagNumberRow).map((row) => row.tag_number);
3208
+ const ownerScopedTagNumbers = getOwnerScopedToolTagNumbers(db, sessionId, messageId);
3209
+ if (messageScopedTags.length === 0 && ownerScopedTagNumbers.length === 0) {
3210
+ return [];
3211
+ }
3212
+ if (messageScopedTags.length > 0) {
3213
+ getDeleteTagsByMessageIdStatement(db).run(sessionId, messageId, textPartPattern, filePartPattern, contentDerivedTextPattern);
3214
+ }
3215
+ if (ownerScopedTagNumbers.length > 0) {
3216
+ deleteToolTagsByOwner(db, sessionId, messageId);
3217
+ }
3218
+ const merged = new Set([...messageScopedTags, ...ownerScopedTagNumbers]);
3219
+ return Array.from(merged).sort((a, b) => a - b);
3220
+ });
3221
+ return deleteTransaction.immediate();
3222
+ }
3223
+ var getOwnerScopedToolTagNumbersStatements = new WeakMap;
3224
+ function getOwnerScopedToolTagNumbers(db, sessionId, ownerMsgId) {
3225
+ let stmt = getOwnerScopedToolTagNumbersStatements.get(db);
3226
+ if (!stmt) {
3227
+ stmt = db.prepare("SELECT tag_number FROM tags WHERE session_id = ? AND type = 'tool' AND tool_owner_message_id = ? ORDER BY tag_number ASC");
3228
+ getOwnerScopedToolTagNumbersStatements.set(db, stmt);
3229
+ }
3230
+ return stmt.all(sessionId, ownerMsgId).filter(isTagNumberRow).map((row) => row.tag_number);
3231
+ }
3232
+ function getMaxTagNumberBySession2(db, sessionId) {
3233
+ const row = getMaxTagNumberBySessionStatement(db).get(sessionId);
3234
+ return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
3235
+ }
3236
+ function getTagNumberByMessageId2(db, sessionId, messageId) {
3237
+ const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
3238
+ return isTagNumberRow(row) ? row.tag_number : null;
3239
+ }
3240
+ function getAssignableTagNumberByMessageId2(db, sessionId, messageId) {
3241
+ const row = getAssignableTagNumberByMessageIdStatement(db).get(sessionId, messageId);
3242
+ return isTagNumberRow(row) ? row.tag_number : null;
3243
+ }
3244
+ var getMinMessageTagNumberForRawIdStatements = new WeakMap;
3245
+ function isMinTagNumberRow(row) {
3246
+ return row !== null && typeof row === "object" && "m" in row;
3247
+ }
3248
+ function getMinMessageTagNumberForRawId2(db, sessionId, rawId) {
3249
+ if (rawId.includes(":"))
3250
+ return null;
3251
+ let stmt = getMinMessageTagNumberForRawIdStatements.get(db);
3252
+ if (!stmt) {
3253
+ stmt = db.prepare("SELECT MIN(tag_number) AS m FROM tags WHERE session_id = ? AND message_id >= ? AND message_id < ?");
3254
+ getMinMessageTagNumberForRawIdStatements.set(db, stmt);
3255
+ }
3256
+ const row = stmt.get(sessionId, `${rawId}:`, `${rawId};`);
3257
+ return isMinTagNumberRow(row) && typeof row.m === "number" ? row.m : null;
3258
+ }
3259
+ var TAGGER_FLOOR_SCAN_MESSAGES = 8;
3260
+ var TAGGER_FLOOR_MAX_PROBES = 64;
3261
+ var TAGGER_FLOOR_SAFETY_MARGIN = 256;
3262
+ var TAGGER_FLOOR_PER_SKIP_MARGIN = 64;
3263
+ function deriveTagLoadFloor2(db, sessionId, rawIds) {
3264
+ let min = Number.POSITIVE_INFINITY;
3265
+ let probes = 0;
3266
+ let hits = 0;
3267
+ let skippedBeforeFirstHit = 0;
3268
+ for (const rawId of rawIds) {
3269
+ if (typeof rawId !== "string" || rawId.length === 0)
3270
+ continue;
3271
+ if (probes >= TAGGER_FLOOR_MAX_PROBES)
3272
+ break;
3273
+ probes++;
3274
+ const m = getMinMessageTagNumberForRawId2(db, sessionId, rawId);
3275
+ if (m === null) {
3276
+ if (hits === 0)
3277
+ skippedBeforeFirstHit++;
3278
+ continue;
3279
+ }
3280
+ if (m < min)
3281
+ min = m;
3282
+ if (++hits >= TAGGER_FLOOR_SCAN_MESSAGES)
3283
+ break;
3284
+ }
3285
+ if (!Number.isFinite(min))
3286
+ return 0;
3287
+ const margin = TAGGER_FLOOR_SAFETY_MARGIN + skippedBeforeFirstHit * TAGGER_FLOOR_PER_SKIP_MARGIN;
3288
+ return Math.max(0, min - margin);
3289
+ }
3290
+ var TAG_SELECT_COLUMNS2 = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id, token_count";
3291
+ function getTagsBySession2(db, sessionId) {
3292
+ const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
3293
+ return rows.map(toTagEntry);
3294
+ }
3295
+ var getActiveTagsBySessionStatements = new WeakMap;
3296
+ var getNullOwnerToolTagsBySessionStatements = new WeakMap;
3297
+ var getDroppedTagsBySessionStatements = new WeakMap;
3298
+ var getMaxDroppedTagNumberStatements = new WeakMap;
3299
+ function getActiveTagsBySessionStatement(db) {
3300
+ let stmt = getActiveTagsBySessionStatements.get(db);
3301
+ if (!stmt) {
3302
+ stmt = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY tag_number ASC, id ASC`);
3303
+ getActiveTagsBySessionStatements.set(db, stmt);
3304
+ }
3305
+ return stmt;
3306
+ }
3307
+ function getDroppedTagsBySessionStatement(db) {
3308
+ let stmt = getDroppedTagsBySessionStatements.get(db);
3309
+ if (!stmt) {
3310
+ stmt = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? AND status = 'dropped' ORDER BY tag_number ASC, id ASC`);
3311
+ getDroppedTagsBySessionStatements.set(db, stmt);
3312
+ }
3313
+ return stmt;
3314
+ }
3315
+ function getMaxDroppedTagNumberStatement(db) {
3316
+ let stmt = getMaxDroppedTagNumberStatements.get(db);
3317
+ if (!stmt) {
3318
+ stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ? AND status = 'dropped'");
3319
+ getMaxDroppedTagNumberStatements.set(db, stmt);
3320
+ }
3321
+ return stmt;
3322
+ }
3323
+ function getActiveTagsBySession2(db, sessionId) {
3324
+ const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
3325
+ return rows.map(toTagEntry);
3326
+ }
3327
+ function getTailHygieneTags2(db, sessionId) {
3328
+ const active = getActiveTagsBySession2(db, sessionId);
3329
+ let orphanStatement = getNullOwnerToolTagsBySessionStatements.get(db);
3330
+ if (!orphanStatement) {
3331
+ orphanStatement = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags
3332
+ WHERE session_id = ? AND type = 'tool' AND tool_owner_message_id IS NULL
3333
+ ORDER BY tag_number ASC, id ASC`);
3334
+ getNullOwnerToolTagsBySessionStatements.set(db, orphanStatement);
3335
+ }
3336
+ const seen = new Set(active.map((tag) => `${tag.tagNumber}\x00${tag.messageId}\x00${tag.type}`));
3337
+ for (const row of orphanStatement.all(sessionId).filter(isTagRow)) {
3338
+ const orphan = toTagEntry(row);
3339
+ const key = `${orphan.tagNumber}\x00${orphan.messageId}\x00${orphan.type}`;
3340
+ if (!seen.has(key))
3341
+ active.push(orphan);
3342
+ }
3343
+ return active;
3344
+ }
3345
+ function getDroppedTagsBySession2(db, sessionId, scope) {
3346
+ const rows = (scope ? db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags INDEXED BY idx_tags_pi_fallback_tool_owner
3347
+ WHERE session_id = ? AND type = 'tool' AND +status = 'dropped'
3348
+ AND tool_owner_message_id IN (SELECT value FROM json_each(?))
3349
+ UNION ALL
3350
+ SELECT ${TAG_SELECT_COLUMNS2} FROM tags INDEXED BY idx_tags_session_message_id
3351
+ WHERE session_id = ? AND type != 'tool' AND +status = 'dropped'
3352
+ AND message_id IN (SELECT value FROM json_each(?))
3353
+ ORDER BY tag_number ASC, id ASC`).all(sessionId, JSON.stringify(scope.ownerIds), sessionId, JSON.stringify(scope.messageAddresses)) : getDroppedTagsBySessionStatement(db).all(sessionId)).filter(isTagRow);
3354
+ return rows.map(toTagEntry);
3355
+ }
3356
+ function getTagsForPendingOperations2(db, sessionId, pendingTagNumbers, protectedCount, recentToolWindow) {
3357
+ const byNumber = new Map;
3358
+ for (const tag of getTagsByNumbers2(db, sessionId, pendingTagNumbers)) {
3359
+ byNumber.set(tag.tagNumber, tag);
3360
+ }
3361
+ const addRows = (sql, limit) => {
3362
+ if (limit <= 0)
3363
+ return;
3364
+ const rows = db.prepare(sql).all(sessionId, limit).filter(isTagRow);
3365
+ for (const row of rows) {
3366
+ const tag = toTagEntry(row);
3367
+ byNumber.set(tag.tagNumber, tag);
3368
+ }
3369
+ };
3370
+ addRows(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags
3371
+ WHERE session_id = ? AND status = 'active'
3372
+ ORDER BY tag_number DESC, id DESC LIMIT ?`, protectedCount);
3373
+ addRows(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags
3374
+ WHERE session_id = ? AND type = 'tool'
3375
+ ORDER BY tag_number DESC, id DESC LIMIT ?`, recentToolWindow);
3376
+ return [...byNumber.values()].sort((left, right) => left.tagNumber - right.tagNumber);
3377
+ }
3378
+ function getTagsByNumbers2(db, sessionId, tagNumbers) {
3379
+ if (tagNumbers.length === 0)
3380
+ return [];
3381
+ if (tagNumbers.length > 900) {
3382
+ const all = [];
3383
+ for (let i = 0;i < tagNumbers.length; i += 900) {
3384
+ all.push(...getTagsByNumbers2(db, sessionId, tagNumbers.slice(i, i + 900)));
3385
+ }
3386
+ return all;
3387
+ }
3388
+ const placeholders = tagNumbers.map(() => "?").join(",");
3389
+ const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
3390
+ return rows.map(toTagEntry);
3391
+ }
3392
+ var newestToolTagNumberStatements = new WeakMap;
3393
+ function getNewestToolTagNumbers2(db, sessionId, limit) {
3394
+ if (limit <= 0)
3395
+ return [];
3396
+ let statement = newestToolTagNumberStatements.get(db);
3397
+ if (!statement) {
3398
+ statement = db.prepare(`SELECT tag_number FROM tags
3399
+ WHERE session_id = ? AND type = 'tool'
3400
+ AND typeof(message_id) = 'text'
3401
+ AND typeof(status) = 'text'
3402
+ AND typeof(byte_size) IN ('integer', 'real')
3403
+ AND typeof(tag_number) IN ('integer', 'real')
3404
+ ORDER BY tag_number DESC
3405
+ LIMIT ?`);
3406
+ newestToolTagNumberStatements.set(db, statement);
3407
+ }
3408
+ return statement.all(sessionId, limit).map((row) => row.tag_number);
3409
+ }
3410
+ var droppedNumberStatements = new WeakMap;
3411
+ function getDroppedTagsByNumbers2(db, sessionId, tagNumbers) {
3412
+ if (tagNumbers.length === 0)
3413
+ return [];
3414
+ if (tagNumbers.length > 900) {
3415
+ const all = [];
3416
+ for (let i = 0;i < tagNumbers.length; i += 900) {
3417
+ all.push(...getDroppedTagsByNumbers2(db, sessionId, tagNumbers.slice(i, i + 900)));
3418
+ }
3419
+ return all;
3420
+ }
3421
+ let statement = droppedNumberStatements.get(db);
3422
+ if (!statement) {
3423
+ statement = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? AND status = 'dropped' AND tag_number IN (SELECT value FROM json_each(?)) ORDER BY tag_number ASC, id ASC`);
3424
+ droppedNumberStatements.set(db, statement);
3425
+ }
3426
+ const rows = statement.all(sessionId, JSON.stringify(tagNumbers)).filter(isTagRow);
3427
+ return rows.map(toTagEntry);
3428
+ }
3429
+ function getMaxDroppedTagNumber2(db, sessionId) {
3430
+ const row = getMaxDroppedTagNumberStatement(db).get(sessionId);
3431
+ return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
3432
+ }
3433
+ var tagByIdStatements = new WeakMap;
3434
+ function getTagById2(db, sessionId, tagId) {
3435
+ let statement = tagByIdStatements.get(db);
3436
+ if (!statement) {
3437
+ statement = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? AND tag_number = ?`);
3438
+ tagByIdStatements.set(db, statement);
3439
+ }
3440
+ const result = statement.get(sessionId, tagId);
3441
+ if (!isTagRow(result)) {
3442
+ return null;
3443
+ }
3444
+ return toTagEntry(result);
3445
+ }
3446
+ function getTopNBySize2(db, sessionId, n) {
3447
+ if (n <= 0) {
3448
+ return [];
3449
+ }
3450
+ const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS2} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY byte_size DESC, tag_number ASC LIMIT ?`).all(sessionId, n).filter(isTagRow);
3451
+ return rows.map(toTagEntry);
3452
+ }
3453
+ var getToolTagNumberByOwnerStatements = new WeakMap;
3454
+ var getNullOwnerToolTagStatements = new WeakMap;
3455
+ var adoptNullOwnerToolTagStatements = new WeakMap;
3456
+ var getToolOwnerByTagIdStatements = new WeakMap;
3457
+ var deleteToolTagsByOwnerStatements = new WeakMap;
3458
+ function getGetToolTagNumberByOwnerStatement(db) {
3459
+ let stmt = getToolTagNumberByOwnerStatements.get(db);
3460
+ if (!stmt) {
3461
+ stmt = db.prepare(`SELECT tag_number FROM tags
3462
+ WHERE session_id = ? AND message_id = ?
3463
+ AND type = 'tool' AND tool_owner_message_id = ?
3464
+ LIMIT 1`);
3465
+ getToolTagNumberByOwnerStatements.set(db, stmt);
3466
+ }
3467
+ return stmt;
3468
+ }
3469
+ function getToolTagNumberByOwner2(db, sessionId, callId, ownerMsgId) {
3470
+ const row = getGetToolTagNumberByOwnerStatement(db).get(sessionId, callId, ownerMsgId);
3471
+ return isTagNumberRow(row) ? row.tag_number : null;
3472
+ }
3473
+ function isNullOwnerToolTagRow(row) {
3474
+ if (row === null || typeof row !== "object")
3475
+ return false;
3476
+ const r = row;
3477
+ return typeof r.id === "number" && typeof r.tag_number === "number";
3478
+ }
3479
+ function getGetNullOwnerToolTagStatement(db) {
3480
+ let stmt = getNullOwnerToolTagStatements.get(db);
3481
+ if (!stmt) {
3482
+ stmt = db.prepare(`SELECT id, tag_number FROM tags
3483
+ WHERE session_id = ? AND message_id = ?
3484
+ AND type = 'tool' AND tool_owner_message_id IS NULL
3485
+ ORDER BY tag_number ASC
3486
+ LIMIT 1`);
3487
+ getNullOwnerToolTagStatements.set(db, stmt);
3488
+ }
3489
+ return stmt;
3490
+ }
3491
+ function getNullOwnerToolTag2(db, sessionId, callId) {
3492
+ const row = getGetNullOwnerToolTagStatement(db).get(sessionId, callId);
3493
+ if (!isNullOwnerToolTagRow(row))
3494
+ return null;
3495
+ return { id: row.id, tagNumber: row.tag_number };
3496
+ }
3497
+ function getAdoptNullOwnerToolTagStatement(db) {
3498
+ let stmt = adoptNullOwnerToolTagStatements.get(db);
3499
+ if (!stmt) {
3500
+ stmt = db.prepare(`UPDATE tags
3501
+ SET tool_owner_message_id = ?
3502
+ WHERE id = ? AND tool_owner_message_id IS NULL`);
3503
+ adoptNullOwnerToolTagStatements.set(db, stmt);
3504
+ }
3505
+ return stmt;
3506
+ }
3507
+ function getToolOwnerByTagIdStatement(db) {
3508
+ let stmt = getToolOwnerByTagIdStatements.get(db);
3509
+ if (!stmt) {
3510
+ stmt = db.prepare("SELECT tool_owner_message_id FROM tags WHERE id = ?");
3511
+ getToolOwnerByTagIdStatements.set(db, stmt);
3512
+ }
3513
+ return stmt;
3514
+ }
3515
+ function adoptNullOwnerToolTag2(db, rowId, ownerMsgId) {
3516
+ return db.transaction(() => {
3517
+ const before = getToolOwnerByTagIdStatement(db).get(rowId);
3518
+ if (!before || before.tool_owner_message_id !== null)
3519
+ return false;
3520
+ getAdoptNullOwnerToolTagStatement(db).run(ownerMsgId, rowId);
3521
+ const after = getToolOwnerByTagIdStatement(db).get(rowId);
3522
+ return after?.tool_owner_message_id === ownerMsgId;
3523
+ }).immediate();
3524
+ }
3525
+ function getCandidateToolOwners2(db, sessionId, callId) {
3526
+ const rows = db.prepare(`SELECT DISTINCT tool_owner_message_id
3527
+ FROM tags
3528
+ WHERE session_id = ?
3529
+ AND message_id = ?
3530
+ AND type = 'tool'
3531
+ AND tool_owner_message_id IS NOT NULL`).all(sessionId, callId);
3532
+ return rows.map((r) => r.tool_owner_message_id);
3533
+ }
3534
+ function pickNearestPriorOwner2(candidates, currentMessageId, times) {
3535
+ const currentTime = times.get(currentMessageId);
3536
+ if (typeof currentTime !== "number")
3537
+ return null;
3538
+ let best = null;
3539
+ for (const id of candidates) {
3540
+ const t = times.get(id);
3541
+ if (typeof t !== "number")
3542
+ continue;
3543
+ if (t > currentTime)
3544
+ continue;
3545
+ if (t === currentTime && id >= currentMessageId)
3546
+ continue;
3547
+ if (best === null || t > best.time || t === best.time && id > best.id) {
3548
+ best = { id, time: t };
3549
+ }
3550
+ }
3551
+ return best?.id ?? null;
3552
+ }
3553
+ function getDeleteToolTagsByOwnerStatement(db) {
3554
+ let stmt = deleteToolTagsByOwnerStatements.get(db);
3555
+ if (!stmt) {
3556
+ stmt = db.prepare(`DELETE FROM tags
3557
+ WHERE session_id = ?
3558
+ AND type = 'tool'
3559
+ AND tool_owner_message_id = ?
3560
+ RETURNING id`);
3561
+ deleteToolTagsByOwnerStatements.set(db, stmt);
3562
+ }
3563
+ return stmt;
3564
+ }
3565
+ function deleteToolTagsByOwner(db, sessionId, ownerMsgId) {
3566
+ return getDeleteToolTagsByOwnerStatement(db).all(sessionId, ownerMsgId).length;
3567
+ }
3568
+
3569
+ export { protectedToolTagNumbers, protectedToolTokenCount, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, isRecord, contentTagOwnerMessageId, estimateImageTokensFromDataUrl, estimateToolAttachmentImageTokens, providerVisiblePart, providerVisibleMessage, normalizeTodoStateJson, buildSyntheticTodoPart, computeSyntheticCallId, isSyntheticTodoPart, countRealUserMessages, tailHygieneStructuralSignature, sameTailHygieneStructuralSignature, formatTailHygienePrefixMismatch, refreshTailHygieneBaseline, effectiveTailHygiene, assertTailHygieneContentUnchangedIfEnabled, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, isDroppedToolOutput, toolOutputTokens, decideChannel1, evaluateChannel2, formatChannel1Evaluation, formatChannel2Evaluation, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, estimateEmergencyDropReclaimTokens, planEmergencyDrop, measureEmergencyTag, queuePendingOp, queuePendingDropForUnchangedTag, getPendingOps, hasPendingDropOps, getPendingOpsCount, clearPendingOps, removePendingOp, getRecentTagOwnerMessageIds2, getActiveTagTokenAggregate2, AGE_RECLAIM_MIN_TOKENS2, getOldestActiveUnprotectedToolTags2, getActiveToolTagsForAgeReclaim2, getTriggerTagTokenUpperBound2, getActiveTagTokenTotalsByMessage2, getPersistedToolTagAccounting2, getAllStatusTagTokenTotalsFlat2, getReasoningTokenEstimatesByMessage2, tryGetReasoningTokenEstimatesByMessage2, getMaxTagNumberByOwnerMessage2, scanTagOwnerSummary2, cachedTagOwnerRatios2, tagOwnerWarmupState2, scanTagOwnerDelta2, installTagOwnerDelta2, installTagOwnerSummary2, isTagOwnerSummaryReady2, tagTokenCountIsNull2, backfillTagTokenCounts2, insertTag2, updateTagStatus2, markWhitespaceAssistantTagInert2, getInertWhitespaceAssistantTags2, getInertWhitespaceAssistantTagsByNumbers2, updateTagDropMode2, updateCavemanDepth2, updateTagMessageId2, hasPiFallbackMessageTags2, findAdoptableFallbackTags2, adoptFallbackTagMessageId2, foldShrunkPartTags2, hasPiFallbackToolOwnerTags2, findPiFallbackToolOwnerTags2, adoptPiFallbackToolOwnerTag2, adoptPiFallbackMessageTag2, markTagsCompactedByMessageIds2, deleteTagsByMessageId2, getMaxTagNumberBySession2, getTagNumberByMessageId2, getAssignableTagNumberByMessageId2, getMinMessageTagNumberForRawId2, deriveTagLoadFloor2, TAG_SELECT_COLUMNS2, getTagsBySession2, getActiveTagsBySession2, getTailHygieneTags2, getDroppedTagsBySession2, getTagsForPendingOperations2, getTagsByNumbers2, getNewestToolTagNumbers2, getDroppedTagsByNumbers2, getMaxDroppedTagNumber2, getTagById2, getTopNBySize2, getToolTagNumberByOwner2, getNullOwnerToolTag2, adoptNullOwnerToolTag2, getCandidateToolOwners2, pickNearestPriorOwner2 };