@cortexkit/opencode-magic-context 0.48.0 → 0.49.1

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 (304) hide show
  1. package/dist/{announcement-fp14dw0n.js → announcement-hdbkt8v5.js} +1 -1
  2. package/dist/auto-search-worker.js +3 -3
  3. package/dist/config/{mural-model-deprecation.d.ts → deprecated-config.d.ts} +4 -1
  4. package/dist/config/deprecated-config.d.ts.map +1 -0
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/project-security.d.ts +2 -2
  7. package/dist/config/schema/magic-context.d.ts +4 -4
  8. package/dist/config/schema/magic-context.d.ts.map +1 -1
  9. package/dist/{conflict-warning-hook-w8cykrnf.js → conflict-warning-hook-asnt6hfc.js} +7 -7
  10. package/dist/{context-m0cy262m.js → context-tfyhtdcs.js} +187 -68
  11. package/dist/{derive-budgets-sg0xsq7s.js → derive-budgets-j4ry8j8n.js} +2 -2
  12. package/dist/embedding-backfill-wyc3ykyf.js +21 -0
  13. package/dist/embedding-worker-process.js +30 -0
  14. package/dist/embedding-worker.js +6 -6
  15. package/dist/features/magic-context/dreamer/task-registry.d.ts +2 -3
  16. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  17. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  18. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  19. package/dist/features/magic-context/memory/embedding-worker-client.d.ts +8 -1
  20. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -1
  21. package/dist/features/magic-context/memory/embedding-worker-process.d.ts +2 -0
  22. package/dist/features/magic-context/memory/embedding-worker-process.d.ts.map +1 -0
  23. package/dist/features/magic-context/memory/onnx-telemetry.d.ts +3 -0
  24. package/dist/features/magic-context/memory/onnx-telemetry.d.ts.map +1 -0
  25. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  26. package/dist/features/magic-context/overflow-detection.d.ts +1 -2
  27. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  28. package/dist/features/magic-context/pi-content-decisions.d.ts +1 -1
  29. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  30. package/dist/features/magic-context/search-rerank.d.ts +35 -0
  31. package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
  32. package/dist/features/magic-context/search.d.ts +11 -0
  33. package/dist/features/magic-context/search.d.ts.map +1 -1
  34. package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
  35. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  36. package/dist/features/magic-context/storage-meta-session.d.ts +1 -1
  37. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  38. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  39. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  40. package/dist/features/magic-context/storage-session-tables.d.ts +2 -0
  41. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  42. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +29 -9
  43. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -1
  44. package/dist/features/magic-context/storage-tags.d.ts +9 -0
  45. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  46. package/dist/features/magic-context/storage.d.ts +1 -1
  47. package/dist/features/magic-context/storage.d.ts.map +1 -1
  48. package/dist/features/magic-context/tagger.d.ts +2 -0
  49. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  50. package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
  51. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  52. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +1 -0
  53. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
  56. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
  57. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  58. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +2 -0
  60. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/command-handler.d.ts +2 -0
  62. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
  64. package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +1 -0
  67. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
  69. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/hook.d.ts +3 -1
  72. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
  75. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
  77. package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/lkg-persist.d.ts +8 -14
  79. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
  81. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
  82. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
  83. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
  84. package/dist/hooks/magic-context/lkg-replay.d.ts +3 -1
  85. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
  88. package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
  89. package/dist/hooks/magic-context/pass-outcome.d.ts +3 -2
  90. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
  92. package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
  93. package/dist/hooks/magic-context/read-session-chunk.d.ts +7 -1
  94. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
  96. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/read-session-raw.d.ts +35 -0
  98. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  100. package/dist/hooks/magic-context/rust-mode-transform.d.ts +37 -0
  101. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  102. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
  103. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
  104. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
  105. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
  106. package/dist/hooks/magic-context/strip-content.d.ts +5 -2
  107. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  108. package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
  109. package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
  110. package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
  111. package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
  112. package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
  113. package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
  114. package/dist/hooks/magic-context/system-prompt-hash.d.ts +4 -0
  115. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  116. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  117. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  118. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +15 -0
  119. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/transform.d.ts +7 -0
  121. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  122. package/dist/{index-ty64eqcn.js → index-0pjvpfkf.js} +24 -4
  123. package/dist/{index-db7zwa3v.js → index-1bt88epp.js} +93 -9
  124. package/dist/{index-2y0s2hep.js → index-4mjhqadz.js} +1 -1
  125. package/dist/index-6m7rdv7y.js +733 -0
  126. package/dist/{index-k1xb52kd.js → index-6tfxmc4n.js} +11 -11
  127. package/dist/{index-fbv1dn35.js → index-7w18gg78.js} +26 -2
  128. package/dist/{index-7mx8v0pw.js → index-att4bfan.js} +4 -4
  129. package/dist/{index-mmyh6d8f.js → index-eypn4ba6.js} +11 -6
  130. package/dist/{index-q2tqeqde.js → index-fdtkt5r1.js} +1229 -78
  131. package/dist/{index-c43kr12f.js → index-fg00p1cg.js} +42 -40
  132. package/dist/{v2/server-1bc61ans.js → index-fvnzcnww.js} +44 -1
  133. package/dist/index-gbmqa9x9.js +1170 -0
  134. package/dist/{index-knh4y330.js → index-gzky5rva.js} +31 -49
  135. package/dist/{index-0qhce371.js → index-h2wc01qk.js} +2 -2
  136. package/dist/{index-dhwzyd54.js → index-h5zfkjyk.js} +160 -25
  137. package/dist/{index-bhvjj0ys.js → index-k6xvbj2e.js} +255 -1075
  138. package/dist/{index-0w56v4fm.js → index-mw7c950g.js} +1 -1
  139. package/dist/{index-8j7gqj40.js → index-nsjyysj0.js} +6 -2
  140. package/dist/{index-k9nnwad5.js → index-nydv6g8r.js} +44 -7
  141. package/dist/{index-f0h6xwqm.js → index-p0n5ryq8.js} +304 -960
  142. package/dist/{index-pg50n748.js → index-p1hnwfd8.js} +4 -4
  143. package/dist/{index-1qb0z7wa.js → index-qx53vezw.js} +1 -1
  144. package/dist/{index-5zygecde.js → index-r2zcs71c.js} +8 -6
  145. package/dist/{index-cb7emxgj.js → index-rafsaxac.js} +336 -6
  146. package/dist/{index-z8e0psj8.js → index-s7fc0fkn.js} +3 -3
  147. package/dist/{index-14cjxt20.js → index-sfhndpcb.js} +505 -11
  148. package/dist/index-sv0bb7vg.js +6972 -0
  149. package/dist/{index-jcbd3znx.js → index-tqf7yg27.js} +1 -1
  150. package/dist/{index-72nhv486.js → index-vkbqdnkj.js} +2 -2
  151. package/dist/{index-pdecwzrd.js → index-w23dh319.js} +18 -259
  152. package/dist/{index-yq8n9qcb.js → index-xgrwmj82.js} +4 -4
  153. package/dist/{index-0an7742d.js → index-xnanvj3w.js} +1364 -2278
  154. package/dist/{index-eeezr5zz.js → index-z1tjp257.js} +1 -1
  155. package/dist/{index-692jzy0p.js → index-zfzdpeq2.js} +2279 -4061
  156. package/dist/{index-q7h7csab.js → index-zg8yq4ya.js} +34 -749
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +241 -76
  159. package/dist/{logger-d3wex3dz.js → logger-ewak5q1s.js} +1 -1
  160. package/dist/{message-index-bounded-7ezbgddp.js → message-index-bounded-hqktkhdy.js} +15 -14
  161. package/dist/{message-time-backfill-brbd63hv.js → message-time-backfill-8x06r9kx.js} +2 -2
  162. package/dist/migration-worker.js +11 -10
  163. package/dist/plugin/hooks/create-session-hooks.d.ts +5 -1
  164. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  165. package/dist/plugin/messages-transform.d.ts.map +1 -1
  166. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  167. package/dist/plugin/tool-registry.d.ts.map +1 -1
  168. package/dist/{project-embedding-registry-7qzptcw7.js → project-embedding-registry-0gv3h6y8.js} +10 -10
  169. package/dist/raw-ordinal-warmup-worker.js +4 -4
  170. package/dist/{read-session-chunk-6k83m4fj.js → read-session-chunk-5mh0bh8y.js} +12 -9
  171. package/dist/{read-session-raw-3g9qy1xa.js → read-session-raw-8sjbc9h0.js} +5 -3
  172. package/dist/{recomp-orchestrator-d3fp1cy0.js → recomp-orchestrator-kpkhkjhq.js} +28 -27
  173. package/dist/{safe-notification-target-5ffqq32m.js → safe-notification-target-q0cyrx3x.js} +2 -2
  174. package/dist/{search-epax1ecv.js → search-p9w39qv4.js} +22 -21
  175. package/dist/{send-session-notification-erecz4y4.js → send-session-notification-xffh3bbe.js} +5 -5
  176. package/dist/shared/auto-search-lifecycle.d.ts +14 -0
  177. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
  178. package/dist/shared/logger.d.ts.map +1 -1
  179. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  180. package/dist/shared/models-dev-temperature.d.ts +18 -0
  181. package/dist/shared/models-dev-temperature.d.ts.map +1 -0
  182. package/dist/shared/project-directory-key.d.ts +16 -0
  183. package/dist/shared/project-directory-key.d.ts.map +1 -1
  184. package/dist/shared/storage-file-mutex.d.ts +9 -0
  185. package/dist/shared/storage-file-mutex.d.ts.map +1 -0
  186. package/dist/shared/storage-permissions.d.ts +6 -0
  187. package/dist/shared/storage-permissions.d.ts.map +1 -1
  188. package/dist/shared/subagent-temperature.d.ts +46 -0
  189. package/dist/shared/subagent-temperature.d.ts.map +1 -0
  190. package/dist/shared/window-geometry.d.ts +9 -66
  191. package/dist/shared/window-geometry.d.ts.map +1 -1
  192. package/dist/standalone-plugin-marker.d.ts +8 -0
  193. package/dist/standalone-plugin-marker.d.ts.map +1 -0
  194. package/dist/{storage-tags-d3b0v2ss.js → storage-tags-k0pda32s.js} +6 -4
  195. package/dist/tools/ctx-reduce/constants.d.ts +1 -2
  196. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  197. package/dist/tools/ctx-reduce/tools.d.ts +1 -1
  198. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  199. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  200. package/dist/tools/ctx-search/types.d.ts +1 -0
  201. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  202. package/dist/{transform-postprocess-phase-spcy2qre.js → transform-postprocess-phase-481j5a7z.js} +28 -27
  203. package/dist/v2/auto-search-worker.js +3 -3
  204. package/dist/v2/{context-sf98kstd.js → context-gsdtha5v.js} +1619 -3111
  205. package/dist/v2/{derive-budgets-3vc0y84t.js → derive-budgets-enckmg7y.js} +3 -3
  206. package/dist/v2/embedding-backfill-dbvjbcmm.js +20 -0
  207. package/dist/v2/embedding-worker-process.js +29 -0
  208. package/dist/v2/embedding-worker.js +6 -7
  209. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  210. package/dist/v2/hidden-completion.d.ts +7 -0
  211. package/dist/v2/hidden-completion.d.ts.map +1 -1
  212. package/dist/v2/hooks/context.d.ts.map +1 -1
  213. package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
  214. package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
  215. package/dist/v2/hooks/dream-trigger.d.ts +4 -1
  216. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  217. package/dist/v2/hooks/generate.d.ts +9 -2
  218. package/dist/v2/hooks/generate.d.ts.map +1 -1
  219. package/dist/v2/hooks/payload.d.ts.map +1 -1
  220. package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
  221. package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
  222. package/dist/v2/{logger-mxd0ym09.js → logger-pj02s7sr.js} +1 -1
  223. package/dist/v2/{message-index-bounded-dy3s2k1e.js → message-index-bounded-p6v0n8qh.js} +15 -14
  224. package/dist/v2/{message-time-backfill-gtx1pwk1.js → message-time-backfill-cje68egj.js} +2 -2
  225. package/dist/v2/migration-worker.js +11 -10
  226. package/dist/v2/{project-embedding-registry-1tgba5dv.js → project-embedding-registry-nyq7z8y6.js} +11 -12
  227. package/dist/v2/raw-ordinal-warmup-worker.js +4 -4
  228. package/dist/v2/{read-session-chunk-rh4khdkv.js → read-session-chunk-fhyfe4qa.js} +12 -9
  229. package/dist/v2/{read-session-raw-bsbmf0vj.js → read-session-raw-j8dvp7f4.js} +5 -3
  230. package/dist/v2/recomp-orchestrator-5xy7w136.js +57 -0
  231. package/dist/v2/{safe-notification-target-73ax1p5v.js → safe-notification-target-y3p1hce9.js} +2 -2
  232. package/dist/v2/{search-nzkwrc6n.js → search-j7bakcwa.js} +23 -23
  233. package/dist/v2/{send-session-notification-6km439kn.js → send-session-notification-f6v698r5.js} +5 -5
  234. package/dist/v2/{server-7wwc2nga.js → server-1fszbabv.js} +32 -32
  235. package/dist/v2/{server-k228xhjg.js → server-2htmbqbv.js} +26 -2
  236. package/dist/v2/{server-aan4q8mx.js → server-3t0q2cqx.js} +1 -1
  237. package/dist/v2/{server-686jg6eb.js → server-4c7jt8gq.js} +68 -7
  238. package/dist/v2/{server-xxm59eww.js → server-4enr7s6x.js} +4 -4
  239. package/dist/v2/{server-zxhgvsf9.js → server-676xw7at.js} +1 -1
  240. package/dist/v2/{server-52awr2mw.js → server-6byqfbqf.js} +93 -9
  241. package/dist/v2/{server-e0vdaae2.js → server-6tcrjfw8.js} +4 -4
  242. package/dist/v2/{server-qye6ykf7.js → server-7ekna9zs.js} +2 -2
  243. package/dist/v2/{server-g5r0n3b6.js → server-7h861yms.js} +160 -25
  244. package/dist/v2/{server-k8x2rbxc.js → server-7spkq1y6.js} +3457 -5192
  245. package/dist/v2/{server-8pyt7hev.js → server-7vkj6zhb.js} +34 -749
  246. package/dist/v2/{server-yczc713m.js → server-8xmq9h3f.js} +31 -49
  247. package/dist/v2/{server-sggvvzhb.js → server-bgzy0phk.js} +505 -11
  248. package/dist/v2/server-c7n2ftng.js +6860 -0
  249. package/dist/v2/server-cvgn49tr.js +733 -0
  250. package/dist/v2/{server-zm570tr2.js → server-cw6521wn.js} +232 -7
  251. package/dist/v2/{server-xdfwt6kh.js → server-czb2rkpk.js} +23 -3
  252. package/dist/v2/{server-x2g40a71.js → server-d6g4whc2.js} +21 -15
  253. package/dist/{index-1bc61ans.js → v2/server-fvnzcnww.js} +44 -1
  254. package/dist/v2/{server-4k748ke6.js → server-hb6xhh9q.js} +2 -2
  255. package/dist/v2/{server-gjcr4w98.js → server-kh958yj8.js} +5 -5
  256. package/dist/v2/{server-1r6pmz4f.js → server-kzns2hbz.js} +1 -1
  257. package/dist/v2/{server-psqc7e9n.js → server-mqvtz7wz.js} +1227 -78
  258. package/dist/v2/{server-vqpf3167.js → server-ras2sxnc.js} +135 -15
  259. package/dist/v2/{server-ezhze64f.js → server-s2st631p.js} +4 -4
  260. package/dist/v2/{server-5m3dt5r1.js → server-t4k4qexw.js} +6 -2
  261. package/dist/v2/{server-z2037m6z.js → server-t528t8qm.js} +2 -2
  262. package/dist/v2/{server-v06jcv0w.js → server-vb7pbd9p.js} +18 -259
  263. package/dist/v2/{server-8tqanswc.js → server-zbxjj2mz.js} +331 -4
  264. package/dist/v2/server.d.ts.map +1 -1
  265. package/dist/v2/server.js +150 -6
  266. package/dist/v2/{storage-tags-w4tv77sn.js → storage-tags-5yxrvkaf.js} +6 -4
  267. package/dist/v2/store-reader.d.ts +8 -2
  268. package/dist/v2/store-reader.d.ts.map +1 -1
  269. package/dist/v2/{wrapup-orchestrator-mz7efs7w.js → wrapup-orchestrator-yem5422s.js} +36 -36
  270. package/dist/wrapup-orchestrator-xvrr27ws.js +45 -0
  271. package/package.json +4 -4
  272. package/src/config/{mural-model-deprecation.ts → deprecated-config.ts} +19 -0
  273. package/src/config/index.test.ts +15 -37
  274. package/src/config/index.ts +2 -3
  275. package/src/config/project-security.ts +3 -3
  276. package/src/config/schema/magic-context.ts +11 -7
  277. package/src/features/magic-context/dreamer/task-registry.ts +2 -3
  278. package/src/shared/auto-search-lifecycle.ts +43 -0
  279. package/src/shared/logger.test.ts +38 -0
  280. package/src/shared/logger.ts +10 -2
  281. package/src/shared/models-dev-cache.ts +1 -7
  282. package/src/shared/models-dev-temperature.ts +107 -0
  283. package/src/shared/project-directory-key.test.ts +59 -0
  284. package/src/shared/project-directory-key.ts +20 -0
  285. package/src/shared/sqlite-640-review.test.ts +5 -1
  286. package/src/shared/storage-file-mutex-review.test.ts +162 -0
  287. package/src/shared/storage-file-mutex.ts +130 -0
  288. package/src/shared/storage-permissions.ts +46 -0
  289. package/src/shared/subagent-temperature.test.ts +270 -0
  290. package/src/shared/subagent-temperature.ts +110 -0
  291. package/src/shared/window-geometry.test.ts +102 -236
  292. package/src/shared/window-geometry.ts +23 -413
  293. package/dist/config/mural-model-deprecation.d.ts.map +0 -1
  294. package/dist/embedding-backfill-9rcm1mfy.js +0 -21
  295. package/dist/index-bdckkfw6.js +0 -3261
  296. package/dist/index-mfkzp7qj.js +0 -229
  297. package/dist/v2/embedding-backfill-vn8g1nh1.js +0 -21
  298. package/dist/v2/recomp-orchestrator-az61rfcg.js +0 -57
  299. package/dist/v2/server-2fbhp79z.js +0 -3205
  300. package/dist/v2/server-mfkzp7qj.js +0 -229
  301. package/dist/wrapup-orchestrator-amzta1t4.js +0 -44
  302. package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
  303. /package/dist/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
  304. /package/dist/v2/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
@@ -1,9 +1,14 @@
1
1
  import {
2
2
  getHarness2
3
3
  } from "./index-pavzsdc6.js";
4
+ import {
5
+ tagIdentityRevisionKey,
6
+ getTemporalDecisions,
7
+ freezeTemporalDecisions,
8
+ stableStringify
9
+ } from "./index-1bt88epp.js";
4
10
  import {
5
11
  protectedToolTagNumbers,
6
- stripWellFormedLeadingTagPrefix,
7
12
  byteSize,
8
13
  stripTagPrefix,
9
14
  prependTag,
@@ -32,9 +37,7 @@ import {
32
37
  AGE_RECLAIM_MIN_TOKENS2,
33
38
  getOldestActiveUnprotectedToolTags2,
34
39
  getActiveToolTagsForAgeReclaim2,
35
- getReasoningTokenEstimatesByMessage2,
36
40
  tryGetReasoningTokenEstimatesByMessage2,
37
- getMaxTagNumberByOwnerMessage2,
38
41
  cachedTagOwnerRatios2,
39
42
  tagOwnerWarmupState2,
40
43
  installTagOwnerDelta2,
@@ -53,6 +56,7 @@ import {
53
56
  getMaxTagNumberBySession2,
54
57
  getTagNumberByMessageId2,
55
58
  getAssignableTagNumberByMessageId2,
59
+ getTagsBySession2,
56
60
  getActiveTagsBySession2,
57
61
  getTailHygieneTags2,
58
62
  getTagsByNumbers2,
@@ -64,16 +68,16 @@ import {
64
68
  adoptNullOwnerToolTag2,
65
69
  getCandidateToolOwners2,
66
70
  pickNearestPriorOwner2
67
- } from "./index-k9nnwad5.js";
71
+ } from "./index-nydv6g8r.js";
68
72
  import {
69
73
  textMentionsRecentCommit,
70
74
  hasMeaningfulUserText2,
71
75
  estimateTokens
72
- } from "./index-1qb0z7wa.js";
76
+ } from "./index-qx53vezw.js";
73
77
  import {
74
78
  log2,
75
79
  sessionLog2
76
- } from "./index-8j7gqj40.js";
80
+ } from "./index-nsjyysj0.js";
77
81
  import {
78
82
  getTagIdentityWriteGeneration2,
79
83
  getSqliteDatabasePath2,
@@ -81,29 +85,25 @@ import {
81
85
  isTransientSqliteError2
82
86
  } from "./index-kb9nn0a0.js";
83
87
  import {
84
- getTemporalDecisions,
85
- freezeTemporalDecisions,
86
- stableStringify
87
- } from "./index-db7zwa3v.js";
88
- import {
89
- isValidLanguageCode,
90
- resolveModelConfigValue
91
- } from "./index-bhvjj0ys.js";
88
+ isValidLanguageCode
89
+ } from "./index-k6xvbj2e.js";
92
90
  import {
93
91
  getProjectEmbeddingSnapshot2,
94
92
  embedTextForProject2,
95
93
  embedBatchForProject2
96
- } from "./index-c43kr12f.js";
94
+ } from "./index-fg00p1cg.js";
97
95
  import {
98
96
  isEmbeddingHostBusy2
99
97
  } from "./index-qt1qqasc.js";
100
98
  import {
101
- BoundedSessionMap,
102
- renderUserFacingFailure,
103
- getMaxM0MutationId,
99
+ stripSystemInjection,
100
+ isTextPart,
101
+ isToolPartWithOutput,
102
+ isFilePart,
103
+ buildFileSourceContent,
104
+ toolPartHasUserAnswer,
105
+ isEditTool,
104
106
  escalationBands,
105
- MERGED_REASONING_PARTS_PREFIX,
106
- readFrozenMergedReasoningParts,
107
107
  HYGIENE_PROVIDER_UNITS_VERSION,
108
108
  sessionDecisionCalibration,
109
109
  transitionSessionHygieneUnits,
@@ -120,7 +120,7 @@ import {
120
120
  getAutoSearchHintDecisions,
121
121
  appendAutoSearchHintDecision,
122
122
  pruneNoteNudgeAnchors,
123
- pruneAutoSearchHintDecisions,
123
+ flushAutoSearchHintDecisionRetirement,
124
124
  getPersistedTodoPermissionDenied,
125
125
  setPersistedTodoPermissionDenied,
126
126
  getPersistedTodoSyntheticAnchor,
@@ -146,10 +146,58 @@ import {
146
146
  setPendingCompactionMarkerState,
147
147
  replacePendingCompactionMarkerStateIf,
148
148
  clearPendingCompactionMarkerStateIf,
149
+ getReasoningRemovalState,
150
+ addRemovedReasoningIds,
151
+ markDropLeavesReasoning,
152
+ modelAcceptsEmptyContent,
153
+ isAnthropicFamilyRoute,
154
+ neutralizeDroppedReasoningPart,
155
+ restoreNeutralizedReasoningPart,
156
+ isNeutralizedReasoningPart,
157
+ makeSentinel,
158
+ makeWholeMessageSentinel,
159
+ isSentinel,
160
+ replaySentinelByMessageIds,
161
+ isInActiveAnthropicTurn,
162
+ hasAnthropicReasoning,
163
+ stripSystemInjectedMessages,
164
+ stripDroppedPlaceholderMessages,
165
+ replayClearedReasoning,
166
+ replayStrippedInlineThinking,
167
+ clearOldReasoning,
168
+ stripClearedReasoning,
169
+ stripInlineThinking,
170
+ findReasoningBearingAssistantIds,
171
+ findLatestAssistantReasoningMutationExemptMessage,
172
+ snapshotTrailingBlankSourceDecisions,
173
+ findTrailingBlankDecisionCandidates,
174
+ applyFrozenTrailingBlankDecisions,
175
+ stripReasoningFromAssistantIds,
176
+ findMergedReasoningStripDecisions,
177
+ stripReasoningFromMergedAssistants,
178
+ stripProcessedImages,
179
+ DEFAULT_KEEP_REASONING_TOKENS,
180
+ reasoningStepCost,
181
+ reasoningTextAndOpaque,
182
+ opencodeReasoningBudgetCutoff,
183
+ SKELETON_REAL_INPUT_MAX_BYTES,
184
+ partHasCompletedResult,
185
+ extractToolCallObservation,
186
+ ToolMutationBatch,
187
+ createToolDropTarget
188
+ } from "./index-sv0bb7vg.js";
189
+ import {
190
+ getMaxM0MutationId,
191
+ rememberUnpublishedAutoSearchNoHint,
192
+ getUnpublishedAutoSearchNoHint,
193
+ forgetUnpublishedAutoSearchNoHint,
149
194
  registerAutoSearchWork,
150
195
  cancelAutoSearchWork,
151
196
  updateSessionMeta,
152
197
  advanceToolReclaimWatermark,
198
+ requestPendingMaterialization,
199
+ pendingMaterializationOrigin,
200
+ clearPendingMaterialization,
153
201
  saveSourceContent,
154
202
  replaceSourceContent,
155
203
  getSourceContents,
@@ -170,40 +218,21 @@ import {
170
218
  peekNoteNudgeText,
171
219
  markNoteNudgeDelivered,
172
220
  getActiveCompartmentRun
173
- } from "./index-692jzy0p.js";
221
+ } from "./index-zfzdpeq2.js";
174
222
  import {
175
223
  runSessionWarmupWorker
176
- } from "./index-dhwzyd54.js";
224
+ } from "./index-h5zfkjyk.js";
177
225
  import {
178
226
  openCodeDbExists,
179
227
  withReadOnlySessionDb,
180
228
  getMessageTimesFromOpenCodeDb
181
- } from "./index-ty64eqcn.js";
229
+ } from "./index-0pjvpfkf.js";
182
230
  import {
183
- stripSystemInjection,
184
- isTextPart,
185
- isToolPartWithOutput,
186
- isFilePart,
187
- buildFileSourceContent,
188
- toolPartHasUserAnswer,
189
- isEditTool,
190
- modelAcceptsEmptyContent,
191
- isAnthropicFamilyRoute,
192
- neutralizeDroppedReasoningPart,
193
- restoreNeutralizedReasoningPart,
194
- isNeutralizedReasoningPart,
195
- neutralizedReasoningSource,
196
- makeSentinel,
197
- makeWholeMessageSentinel,
198
- neutralizeWholeMessage,
199
- isSentinel,
200
- replaySentinelByMessageIds,
201
- SKELETON_REAL_INPUT_MAX_BYTES,
202
- partHasCompletedResult,
203
- extractToolCallObservation,
204
- ToolMutationBatch,
205
- createToolDropTarget
206
- } from "./index-bdckkfw6.js";
231
+ BoundedSessionMap
232
+ } from "./index-sfhndpcb.js";
233
+ import {
234
+ renderUserFacingFailure
235
+ } from "./index-rafsaxac.js";
207
236
  import {
208
237
  getErrorMessage
209
238
  } from "./index-y8v6yerm.js";
@@ -213,7 +242,7 @@ import {
213
242
  } from "./index-d9vfe7xq.js";
214
243
  import {
215
244
  logSlowWriteTransaction
216
- } from "./index-2y0s2hep.js";
245
+ } from "./index-4mjhqadz.js";
217
246
 
218
247
  // src/features/magic-context/tagger.ts
219
248
  var TOOL_COMPOSITE_KEY_SEP = "\x00";
@@ -221,7 +250,9 @@ function makeToolCompositeKey(ownerMsgId, callId) {
221
250
  return `${ownerMsgId}${TOOL_COMPOSITE_KEY_SEP}${callId}`;
222
251
  }
223
252
  var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
224
- var GET_TAGS_VERSION_SQL = `SELECT tags_version FROM session_meta WHERE session_id = ?`;
253
+ var GET_TAGS_VERSION_SQL = `SELECT
254
+ (SELECT tags_version FROM session_meta WHERE session_id = ?) AS tags_version,
255
+ (SELECT value FROM schema_migrations_meta WHERE key = ?) AS identity_revision`;
225
256
  var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id, byte_size, token_count, input_byte_size, input_token_count FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
226
257
  var GET_ASSIGNMENTS_SCOPED_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id, byte_size, token_count, input_byte_size, input_token_count FROM tags WHERE session_id = ? AND tag_number >= ? ORDER BY tag_number ASC";
227
258
  var probeTagsVersionStatements = new WeakMap;
@@ -342,10 +373,16 @@ function createTagger() {
342
373
  const memCounter = heapHolder.counters.get(sessionId) ?? 0;
343
374
  const dbMax = getMaxTagNumberBySession2(db, sessionId);
344
375
  const next = Math.max(memCounter, dbMax) + 1;
376
+ const loaded = heapHolder.loadSignatures.get(sessionId);
377
+ let ownedInitialIdentity;
345
378
  try {
346
379
  db.transaction(() => {
380
+ const admitted = loaded?.db === db && loaded.identityRevision === null ? probeSignature(sessionId, db) : null;
381
+ const initializesOwnedEpoch = admitted !== null && loaded !== undefined && admitted.identityRevision === null && admitted.tagsVersion === loaded.tagsVersion;
347
382
  getUpsertCounterStatement(db).run(sessionId, next, getHarness2());
348
383
  insertTag2(db, sessionId, messageId, type, byteSize, next, reasoningByteSize, toolName, inputByteSize, toolOwnerMessageId, entryFingerprint, tokenCounts);
384
+ if (initializesOwnedEpoch)
385
+ ownedInitialIdentity = probeSignature(sessionId, db).identityRevision;
349
386
  }).immediate();
350
387
  } catch (error) {
351
388
  if (!isUniqueConstraintError(error)) {
@@ -366,6 +403,8 @@ function createTagger() {
366
403
  const signature = heapHolder.loadSignatures.get(sessionId);
367
404
  if (signature?.db === db) {
368
405
  signature.tagsVersion += 1;
406
+ if (signature === loaded && ownedInitialIdentity !== undefined)
407
+ signature.identityRevision = ownedInitialIdentity;
369
408
  }
370
409
  if (type === "tool") {
371
410
  getSessionToolAccounting(sessionId).set(next, {
@@ -468,15 +507,16 @@ function createTagger() {
468
507
  return heapHolder.counters.get(sessionId) ?? 0;
469
508
  }
470
509
  function probeSignature(sessionId, db) {
471
- const row = getProbeTagsVersionStatement(db).get(sessionId);
510
+ const row = getProbeTagsVersionStatement(db).get(sessionId, tagIdentityRevisionKey(sessionId));
472
511
  return {
473
- tagsVersion: row?.tags_version ?? 0
512
+ tagsVersion: row?.tags_version ?? 0,
513
+ identityRevision: row?.identity_revision ?? null
474
514
  };
475
515
  }
476
516
  function initFromDb(sessionId, db, floor = 0) {
477
517
  const probe = probeSignature(sessionId, db);
478
518
  const cached = heapHolder.loadSignatures.get(sessionId);
479
- if (cached !== undefined && cached.db === db && cached.tagsVersion === probe.tagsVersion && cached.floor === floor) {
519
+ if (cached !== undefined && cached.db === db && cached.tagsVersion === probe.tagsVersion && cached.identityRevision === probe.identityRevision && cached.floor === floor) {
480
520
  return;
481
521
  }
482
522
  const row = db.prepare(GET_COUNTER_SQL).get(sessionId);
@@ -509,6 +549,7 @@ function createTagger() {
509
549
  heapHolder.loadSignatures.set(sessionId, {
510
550
  db,
511
551
  tagsVersion: probe.tagsVersion,
552
+ identityRevision: probe.identityRevision,
512
553
  floor
513
554
  });
514
555
  }
@@ -516,6 +557,10 @@ function createTagger() {
516
557
  const signature = heapHolder.loadSignatures.get(sessionId);
517
558
  return signature?.db === db ? signature.tagsVersion : undefined;
518
559
  }
560
+ function getLoadedTagIdentityRevision(sessionId, db) {
561
+ const signature = heapHolder.loadSignatures.get(sessionId);
562
+ return signature?.db === db ? signature.identityRevision : undefined;
563
+ }
519
564
  function cleanup(sessionId) {
520
565
  heapHolder.counters.delete(sessionId);
521
566
  heapHolder.assignments.delete(sessionId);
@@ -558,6 +603,7 @@ function createTagger() {
558
603
  getCounter,
559
604
  initFromDb,
560
605
  getLoadedTagsVersion,
606
+ getLoadedTagIdentityRevision,
561
607
  cleanup,
562
608
  getHeapStats
563
609
  };
@@ -606,6 +652,8 @@ function persistAutoSearchSkip(db, sessionId, messageId, reason = "timeout") {
606
652
  ok = outcome.ok && outcome.decision.decision === "no-hint";
607
653
  } catch {}
608
654
  assertTransformWrite2();
655
+ if (!ok)
656
+ rememberUnpublishedAutoSearchNoHint(sessionId, messageId, reason);
609
657
  const persistence = Promise.resolve(ok);
610
658
  messages.set(messageId, persistence);
611
659
  return persistence;
@@ -1237,7 +1285,36 @@ function queueAutoSearchRegistration(db, projectPath, register) {
1237
1285
  function persistAutoSearchDecision(db, sessionId, decision, startedAt) {
1238
1286
  if (performance.now() - startedAt >= AUTO_SEARCH_TIMEOUT_MS)
1239
1287
  return null;
1240
- return appendAutoSearchHintDecision(db, sessionId, decision);
1288
+ let outcome;
1289
+ try {
1290
+ outcome = appendAutoSearchHintDecision(db, sessionId, decision);
1291
+ } catch (error) {
1292
+ assertTransformWrite2();
1293
+ rememberUnpublishedAutoSearchNoHint(sessionId, decision.messageId, decision.decision === "no-hint" ? decision.reason : "error");
1294
+ if (!isTransientSqliteError2(error))
1295
+ throw error;
1296
+ log2(`[auto-search] decision save hit a busy store for session ${sessionId}; serving without a hint and retrying the save on a later pass: ${error instanceof Error ? error.message : String(error)}`);
1297
+ return { ok: false, kind: "storage-busy" };
1298
+ }
1299
+ if (!outcome.ok) {
1300
+ assertTransformWrite2();
1301
+ rememberUnpublishedAutoSearchNoHint(sessionId, decision.messageId, decision.decision === "no-hint" ? decision.reason : "error");
1302
+ } else if (outcome.decision.decision === "no-hint") {
1303
+ forgetUnpublishedAutoSearchNoHint(sessionId, decision.messageId);
1304
+ }
1305
+ return outcome;
1306
+ }
1307
+ function retryUnpublishedAutoSearchNoHint(db, sessionId, messageId, startedAt) {
1308
+ const reason = getUnpublishedAutoSearchNoHint(sessionId, messageId);
1309
+ if (reason === undefined)
1310
+ return false;
1311
+ try {
1312
+ persistAutoSearchDecision(db, sessionId, { messageId, decision: "no-hint", reason }, startedAt);
1313
+ } catch (error) {
1314
+ assertTransformWrite2();
1315
+ log2(`[auto-search] frozen omission save still failed for session ${sessionId}: ${error instanceof Error ? error.message : String(error)}`);
1316
+ }
1317
+ return true;
1241
1318
  }
1242
1319
  async function searchAutoHint(db, sessionId, projectPath, query, options, entry = new URL(new URL(import.meta.url).pathname.endsWith(".ts") ? "./auto-search-worker.ts" : "./auto-search-worker.js", import.meta.url)) {
1243
1320
  return executeAutoSearchWorker(db, sessionId, projectPath, query, options, entry, "search");
@@ -1625,6 +1702,9 @@ async function runAutoSearchHint(args) {
1625
1702
  return coalesceAutoSearchTurn(db, sessionId, userMsgId, async (lifecycleSignal) => {
1626
1703
  if (lifecycleSignal.aborted)
1627
1704
  return AUTO_SEARCH_OK;
1705
+ if (retryUnpublishedAutoSearchNoHint(db, sessionId, userMsgId, startedAt)) {
1706
+ return AUTO_SEARCH_OK;
1707
+ }
1628
1708
  if (wasAutoSearchSkipped(db, sessionId, userMsgId))
1629
1709
  return AUTO_SEARCH_OK;
1630
1710
  const existing = getAutoSearchHintDecisions(db, sessionId);
@@ -1655,7 +1735,10 @@ async function runAutoSearchHint(args) {
1655
1735
  return { ok: false, kind: "timeout" };
1656
1736
  }
1657
1737
  if (!outcome.ok)
1658
- return { ok: false, kind: "cas-exhaustion" };
1738
+ return {
1739
+ ok: false,
1740
+ kind: outcome.kind === "storage-busy" ? "storage-busy" : "cas-exhaustion"
1741
+ };
1659
1742
  if (outcome.kind === "already-present" && outcome.decision.decision === "hint") {
1660
1743
  appendReminderToUserMessageById(messages, userMsgId, outcome.decision.text);
1661
1744
  }
@@ -1699,8 +1782,11 @@ async function runAutoSearchHint(args) {
1699
1782
  });
1700
1783
  }, startedAt);
1701
1784
  } catch (error) {
1702
- log2(`[auto-search] unified search failed for session ${sessionId} (will retry next pass): ${error instanceof Error ? error.message : String(error)}`);
1703
- return { ok: false, kind: "search-failure" };
1785
+ if (lifecycleSignal.aborted)
1786
+ return AUTO_SEARCH_OK;
1787
+ log2(`[auto-search] unified search failed for session ${sessionId} (no-hint frozen for this turn): ${error instanceof Error ? error.message : String(error)}`);
1788
+ const outcome = await writeNoHintAndReconcile("error");
1789
+ return outcome.ok ? { ok: false, kind: "search-failure" } : outcome;
1704
1790
  }
1705
1791
  if (lifecycleSignal.aborted)
1706
1792
  return AUTO_SEARCH_OK;
@@ -1735,6 +1821,8 @@ ${hintText}`;
1735
1821
  return { ok: false, kind: "timeout" };
1736
1822
  }
1737
1823
  if (!outcome.ok) {
1824
+ if (outcome.kind === "storage-busy")
1825
+ return { ok: false, kind: "storage-busy" };
1738
1826
  sessionLog2(sessionId, `auto-search: CAS exhausted for ${userMsgId}; skipping wire append`);
1739
1827
  return { ok: false, kind: "cas-exhaustion" };
1740
1828
  }
@@ -1748,6 +1836,8 @@ ${hintText}`;
1748
1836
  queueAutoSearchBackfill(db, sessionId, options.projectPath, rawPrompt);
1749
1837
  }
1750
1838
  }, () => {
1839
+ if (getUnpublishedAutoSearchNoHint(sessionId, userMsgId) !== undefined)
1840
+ return;
1751
1841
  if (wasAutoSearchSkipped(db, sessionId, userMsgId))
1752
1842
  return;
1753
1843
  const decision = getAutoSearchHintDecisions(db, sessionId).find((entry) => entry.messageId === userMsgId);
@@ -2069,851 +2159,6 @@ function reclaimRideLabel(signals) {
2069
2159
  return `ride=${active.length > 0 ? active.join("+") : "none"}`;
2070
2160
  }
2071
2161
 
2072
- // src/features/magic-context/storage-reasoning-removal.ts
2073
- var NAMESPACE = "reasoningRemoval";
2074
- var BACKUP_NAMESPACE = "reasoningRemovalBackup";
2075
- function invalidState(sessionId) {
2076
- return new Error(`invalid persisted reasoning removal state for session ${sessionId}`);
2077
- }
2078
- function parseState(doc, sessionId, namespace = NAMESPACE) {
2079
- const lane = doc[namespace];
2080
- if (lane === undefined)
2081
- return { messageIds: new Set, dropLeavesReasoning: false };
2082
- if (!isRecord(lane) || !Array.isArray(lane.messageIds))
2083
- throw invalidState(sessionId);
2084
- const ids = new Set;
2085
- for (const id of lane.messageIds) {
2086
- if (typeof id !== "string" || id.length === 0)
2087
- throw invalidState(sessionId);
2088
- ids.add(id);
2089
- }
2090
- if (lane.dropLeavesReasoning !== undefined && typeof lane.dropLeavesReasoning !== "boolean") {
2091
- throw invalidState(sessionId);
2092
- }
2093
- return { messageIds: ids, dropLeavesReasoning: lane.dropLeavesReasoning === true };
2094
- }
2095
- function writeState(doc, state) {
2096
- doc.version = 2;
2097
- const lane = {
2098
- messageIds: [...state.messageIds],
2099
- ...state.dropLeavesReasoning ? { dropLeavesReasoning: true } : {}
2100
- };
2101
- doc[NAMESPACE] = lane;
2102
- doc[BACKUP_NAMESPACE] = { ...lane, messageIds: [...lane.messageIds] };
2103
- }
2104
- function getReasoningRemovalState(db, sessionId) {
2105
- const doc = readReplayEnvelope(db, sessionId);
2106
- try {
2107
- return parseState(doc, sessionId);
2108
- } catch (error) {
2109
- if (doc[BACKUP_NAMESPACE] === undefined)
2110
- throw error;
2111
- return parseState(doc, sessionId, BACKUP_NAMESPACE);
2112
- }
2113
- }
2114
- function addRemovedReasoningIds(db, sessionId, ids) {
2115
- const requested = [...ids].filter((id) => typeof id === "string" && id.length > 0);
2116
- if (requested.length === 0)
2117
- return true;
2118
- return updateReplayDocument(db, sessionId, (doc) => {
2119
- const current = parseState(doc, sessionId);
2120
- let changed = false;
2121
- for (const id of requested) {
2122
- if (current.messageIds.has(id))
2123
- continue;
2124
- current.messageIds.add(id);
2125
- changed = true;
2126
- }
2127
- if (!changed)
2128
- return false;
2129
- writeState(doc, current);
2130
- return true;
2131
- });
2132
- }
2133
- function markDropLeavesReasoning(db, sessionId) {
2134
- return updateReplayDocument(db, sessionId, (doc) => {
2135
- const current = parseState(doc, sessionId);
2136
- if (current.dropLeavesReasoning)
2137
- return false;
2138
- current.dropLeavesReasoning = true;
2139
- writeState(doc, current);
2140
- return true;
2141
- });
2142
- }
2143
-
2144
- // src/hooks/magic-context/active-anthropic-turn.ts
2145
- function isInActiveAnthropicTurn(messages, index, anthropic) {
2146
- const start = activeAnthropicTurnStart(messages, anthropic);
2147
- return start !== undefined && index >= start;
2148
- }
2149
- function activeAnthropicTurnStart(messages, anthropic) {
2150
- if (!anthropic)
2151
- return;
2152
- for (let user = messages.length - 1;user >= 0; user--) {
2153
- const message = messages[user];
2154
- if (!isRecord(message))
2155
- continue;
2156
- const info = isRecord(message.info) ? message.info : message;
2157
- if (info.role !== "user" || info.synthetic === true || message.synthetic === true)
2158
- continue;
2159
- const id = typeof info.id === "string" ? info.id : "";
2160
- if (id.startsWith("synth-user-"))
2161
- continue;
2162
- const parts = Array.isArray(message.parts) ? message.parts : Array.isArray(message.content) ? message.content : [];
2163
- if (parts.length > 0 && parts.every((part) => isRecord(part) && (part.synthetic === true || part.ignored === true || ["tool_result", "toolResult", "tool-result"].includes(String(part.type)))))
2164
- continue;
2165
- return user + 1;
2166
- }
2167
- return;
2168
- }
2169
- function hasAnthropicReasoning(messages) {
2170
- return messages.some((message) => {
2171
- if (!isRecord(message))
2172
- return false;
2173
- const info = isRecord(message.info) ? message.info : message;
2174
- if (isAnthropicFamilyRoute(typeof info.providerID === "string" ? info.providerID : typeof info.provider === "string" ? info.provider : undefined, typeof info.modelID === "string" ? info.modelID : typeof info.model === "string" ? info.model : undefined))
2175
- return true;
2176
- const parts = Array.isArray(message.parts) ? message.parts : [];
2177
- return parts.some((part) => isRecord(part) && isRecord(part.metadata) && isRecord(part.metadata.anthropic));
2178
- });
2179
- }
2180
-
2181
- // src/hooks/magic-context/strip-content.ts
2182
- var MARKER_ONLY_PATTERN = /^(?:(?:§\d+§|\[dropped(?: §\d+§)?\]|\[cleared\])\s*)+$/;
2183
- function isMarkerOnlyText(text) {
2184
- const trimmed = text.trim();
2185
- return trimmed.length > 0 && MARKER_ONLY_PATTERN.test(trimmed);
2186
- }
2187
- var TAG_PREFIX_PATTERN = /^§\d+§\s*/;
2188
- var SYSTEM_INJECTION_PATTERNS = [
2189
- /^<!-- OMO_INTERNAL_INITIATOR -->$/,
2190
- /^<system-reminder>[\s\S]*<\/system-reminder>$/,
2191
- /^\[SYSTEM DIRECTIVE:/,
2192
- /^\[Category\+Skill Reminder\]/,
2193
- /^\[EDIT ERROR - IMMEDIATE ACTION REQUIRED\]/,
2194
- /^\[task CALL FAILED/,
2195
- /^\[EMERGENCY CONTEXT WINDOW WARNING\]/
2196
- ];
2197
- function isSystemInjectedText(text) {
2198
- const stripped = text.trim().replace(TAG_PREFIX_PATTERN, "").trim();
2199
- if (stripped.length === 0)
2200
- return false;
2201
- return SYSTEM_INJECTION_PATTERNS.some((pattern) => pattern.test(stripped));
2202
- }
2203
- function stripSystemInjectedMessages(messages, protectedTailStart, providerID, onFirstApplication) {
2204
- let stripped = 0;
2205
- const sentineledIds = [];
2206
- for (let i = 0;i < messages.length; i++) {
2207
- if (i >= protectedTailStart)
2208
- continue;
2209
- const msg = messages[i];
2210
- if (msg.parts.length === 0)
2211
- continue;
2212
- if (msg.info.role === "user")
2213
- continue;
2214
- if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
2215
- continue;
2216
- let hasContentPart = false;
2217
- let allContentIsSystemInjection = true;
2218
- for (const part of msg.parts) {
2219
- if (!isRecord(part))
2220
- continue;
2221
- const partType = part.type;
2222
- if (METADATA_PART_TYPES.has(partType))
2223
- continue;
2224
- if (part.ignored === true)
2225
- continue;
2226
- if (partType === "tool") {
2227
- allContentIsSystemInjection = false;
2228
- break;
2229
- }
2230
- if (partType === "text" && typeof part.text === "string") {
2231
- hasContentPart = true;
2232
- if (!isSystemInjectedText(part.text)) {
2233
- allContentIsSystemInjection = false;
2234
- break;
2235
- }
2236
- continue;
2237
- }
2238
- allContentIsSystemInjection = false;
2239
- break;
2240
- }
2241
- if (hasContentPart && allContentIsSystemInjection) {
2242
- onFirstApplication?.(msg, 0);
2243
- neutralizeWholeMessage(msg, providerID);
2244
- stripped++;
2245
- if (typeof msg.info.id === "string")
2246
- sentineledIds.push(msg.info.id);
2247
- }
2248
- }
2249
- return { stripped, sentineledIds };
2250
- }
2251
- var METADATA_PART_TYPES = new Set([
2252
- "step-start",
2253
- "step-finish",
2254
- "snapshot",
2255
- "patch",
2256
- "agent",
2257
- "retry",
2258
- "subtask",
2259
- "compaction"
2260
- ]);
2261
- function stripDroppedPlaceholderMessages(messages, providerID, onFirstApplication) {
2262
- let stripped = 0;
2263
- const sentineledIds = [];
2264
- for (let i = 0;i < messages.length; i++) {
2265
- const msg = messages[i];
2266
- if (msg.parts.length === 0)
2267
- continue;
2268
- if (msg.info.role === "user")
2269
- continue;
2270
- if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
2271
- continue;
2272
- let hasContentPart = false;
2273
- let hasNonDroppedContent = false;
2274
- for (const part of msg.parts) {
2275
- if (!isRecord(part)) {
2276
- hasNonDroppedContent = true;
2277
- break;
2278
- }
2279
- const partType = part.type;
2280
- if (METADATA_PART_TYPES.has(partType))
2281
- continue;
2282
- if (partType === "tool") {
2283
- hasNonDroppedContent = true;
2284
- break;
2285
- }
2286
- if ((partType === "text" || partType === "reasoning") && typeof part.text === "string") {
2287
- hasContentPart = true;
2288
- if (part.text.trim().length === 0)
2289
- continue;
2290
- if (!isMarkerOnlyText(part.text)) {
2291
- hasNonDroppedContent = true;
2292
- break;
2293
- }
2294
- continue;
2295
- }
2296
- hasNonDroppedContent = true;
2297
- break;
2298
- }
2299
- if (hasContentPart && !hasNonDroppedContent) {
2300
- onFirstApplication?.(msg, 0);
2301
- neutralizeWholeMessage(msg, providerID);
2302
- stripped++;
2303
- if (typeof msg.info.id === "string")
2304
- sentineledIds.push(msg.info.id);
2305
- }
2306
- }
2307
- return { stripped, sentineledIds };
2308
- }
2309
- function replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers, persistedWatermark) {
2310
- if (persistedWatermark <= 0)
2311
- return 0;
2312
- let cleared = 0;
2313
- for (const message of messages) {
2314
- const msgTag = messageTagNumbers.get(message) ?? 0;
2315
- if (msgTag === 0 || msgTag > persistedWatermark)
2316
- continue;
2317
- const parts = reasoningByMessage.get(message);
2318
- if (!parts)
2319
- continue;
2320
- for (const tp of parts) {
2321
- if (tp.type === "text")
2322
- continue;
2323
- if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
2324
- tp.thinking = "[cleared]";
2325
- cleared++;
2326
- }
2327
- if (tp.text !== undefined && tp.text !== "[cleared]") {
2328
- tp.text = "[cleared]";
2329
- cleared++;
2330
- }
2331
- }
2332
- }
2333
- return cleared;
2334
- }
2335
- function replayStrippedInlineThinking(messages, messageTagNumbers, persistedWatermark) {
2336
- if (persistedWatermark <= 0)
2337
- return 0;
2338
- let stripped = 0;
2339
- for (const message of messages) {
2340
- if (message.info.role !== "assistant")
2341
- continue;
2342
- const msgTag = messageTagNumbers.get(message) ?? 0;
2343
- if (msgTag === 0 || msgTag > persistedWatermark)
2344
- continue;
2345
- for (const part of message.parts) {
2346
- if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string")
2347
- continue;
2348
- if (!part.text.includes("<think"))
2349
- continue;
2350
- const cleaned = part.text.replace(INLINE_THINKING_PATTERN, "");
2351
- if (cleaned !== part.text) {
2352
- part.text = cleaned;
2353
- stripped++;
2354
- }
2355
- }
2356
- }
2357
- return stripped;
2358
- }
2359
- function clearOldReasoning(messages, reasoningByMessage, messageTagNumbers, cutoff) {
2360
- const ageCutoff = cutoff;
2361
- let cleared = 0;
2362
- for (const message of messages) {
2363
- const msgTag = messageTagNumbers.get(message) ?? 0;
2364
- if (msgTag === 0 || msgTag > ageCutoff)
2365
- continue;
2366
- const parts = reasoningByMessage.get(message);
2367
- if (!parts)
2368
- continue;
2369
- for (const tp of parts) {
2370
- if (tp.type === "text")
2371
- continue;
2372
- if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
2373
- tp.thinking = "[cleared]";
2374
- cleared++;
2375
- }
2376
- if (tp.text !== undefined && tp.text !== "[cleared]") {
2377
- tp.text = "[cleared]";
2378
- cleared++;
2379
- }
2380
- }
2381
- }
2382
- return cleared;
2383
- }
2384
- var CLEARED_REASONING_TYPES = new Set(["thinking", "reasoning"]);
2385
- function stripClearedReasoning(messages) {
2386
- let stripped = 0;
2387
- for (const message of messages) {
2388
- if (message.info.role !== "assistant")
2389
- continue;
2390
- for (let i = 0;i < message.parts.length; i++) {
2391
- const part = message.parts[i];
2392
- if (!isRecord(part))
2393
- continue;
2394
- const partType = part.type;
2395
- if (!CLEARED_REASONING_TYPES.has(partType))
2396
- continue;
2397
- if (!("thinking" in part) && !("text" in part))
2398
- continue;
2399
- const thinking = "thinking" in part ? part.thinking : undefined;
2400
- const text = "text" in part ? part.text : undefined;
2401
- const isCleared = (thinking === undefined || thinking === "[cleared]") && (text === undefined || text === "[cleared]");
2402
- if (!isCleared)
2403
- continue;
2404
- message.parts[i] = makeSentinel(part);
2405
- stripped++;
2406
- }
2407
- }
2408
- return stripped;
2409
- }
2410
- var INLINE_THINKING_PATTERN = /<(?:thinking|think)>[\s\S]*?<\/(?:thinking|think)>\s*/g;
2411
- function stripInlineThinking(messages, messageTagNumbers, cutoff) {
2412
- const ageCutoff = cutoff;
2413
- let stripped = 0;
2414
- for (const message of messages) {
2415
- if (message.info.role !== "assistant")
2416
- continue;
2417
- const msgTag = messageTagNumbers.get(message) ?? 0;
2418
- if (msgTag === 0 || msgTag > ageCutoff)
2419
- continue;
2420
- for (const part of message.parts) {
2421
- if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string")
2422
- continue;
2423
- const cleaned = part.text.replace(INLINE_THINKING_PATTERN, "");
2424
- if (cleaned !== part.text) {
2425
- part.text = cleaned;
2426
- stripped++;
2427
- }
2428
- }
2429
- }
2430
- return stripped;
2431
- }
2432
- var REASONING_IGNORED_PART_TYPES = new Set([
2433
- "step-start",
2434
- "step-finish",
2435
- "snapshot",
2436
- "patch",
2437
- "agent",
2438
- "retry",
2439
- "subtask",
2440
- "compaction"
2441
- ]);
2442
- var REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
2443
- function hasReasoningReplayContent(message) {
2444
- return message.parts.some((part) => {
2445
- if (!isRecord(part) || part.ignored === true)
2446
- return false;
2447
- const type = typeof part.type === "string" ? part.type : "";
2448
- if (REASONING_IGNORED_PART_TYPES.has(type))
2449
- return false;
2450
- return type !== "text" || typeof part.text !== "string" || part.text.trim().length > 0;
2451
- });
2452
- }
2453
- function findReasoningBearingAssistantIds(messages) {
2454
- const ids = new Set;
2455
- for (const message of messages) {
2456
- if (message.info.role !== "assistant")
2457
- continue;
2458
- const id = message.info.id;
2459
- if (typeof id !== "string" || id.length === 0)
2460
- continue;
2461
- if (message.parts.some((part) => isRecord(part) && REASONING_PART_TYPES.has(String(part.type)))) {
2462
- ids.add(id);
2463
- }
2464
- }
2465
- return [...ids];
2466
- }
2467
- function findLatestAssistantReasoningMutationExemptMessage(messages) {
2468
- for (let index = messages.length - 1;index >= 0; index -= 1) {
2469
- const message = messages[index];
2470
- if (message.info.role === "assistant" && hasReasoningReplayContent(message))
2471
- return message;
2472
- }
2473
- return;
2474
- }
2475
- function planMergedAssistantReasoningStrip(messages, mutationExemptMessage, frozenMessageIds, protectedMessages) {
2476
- const plan = [];
2477
- let prevRole;
2478
- let keptReasoningInRun = false;
2479
- for (const message of messages) {
2480
- const role = message.info.role;
2481
- if (role !== "assistant") {
2482
- prevRole = role;
2483
- keptReasoningInRun = false;
2484
- continue;
2485
- }
2486
- const firstInRun = prevRole !== "assistant";
2487
- if (firstInRun)
2488
- keptReasoningInRun = false;
2489
- if (protectedMessages?.has(message) || message === mutationExemptMessage || frozenMessageIds?.has(message.info.id ?? "")) {
2490
- prevRole = role;
2491
- continue;
2492
- }
2493
- let keepIndex = -1;
2494
- if (firstInRun && !keptReasoningInRun) {
2495
- for (let i = 0;i < message.parts.length; i++) {
2496
- const part = message.parts[i];
2497
- if (!isRecord(part))
2498
- continue;
2499
- const partType = part.type;
2500
- if (REASONING_IGNORED_PART_TYPES.has(partType))
2501
- continue;
2502
- if (part.ignored === true)
2503
- continue;
2504
- if (isSentinel(part))
2505
- continue;
2506
- if (partType === "text" && typeof part.text === "string" && part.text.trim() === "") {
2507
- continue;
2508
- }
2509
- if (REASONING_PART_TYPES.has(partType)) {
2510
- keepIndex = i;
2511
- }
2512
- break;
2513
- }
2514
- }
2515
- const stripIndices = [];
2516
- for (let i = 0;i < message.parts.length; i++) {
2517
- const part = message.parts[i];
2518
- if (!isRecord(part))
2519
- continue;
2520
- if (!REASONING_PART_TYPES.has(part.type))
2521
- continue;
2522
- if (part.cache_control !== undefined)
2523
- continue;
2524
- if (i === keepIndex) {
2525
- keptReasoningInRun = true;
2526
- continue;
2527
- }
2528
- stripIndices.push(i);
2529
- }
2530
- if (stripIndices.length > 0)
2531
- plan.push({ message, stripIndices });
2532
- prevRole = role;
2533
- }
2534
- return plan;
2535
- }
2536
- var MAX_FROZEN_TRAILING_BLANKS = 1e4;
2537
- var CANONICAL_BLANK_PART = { type: "text", text: "" };
2538
- function isSentinelInvisibleTextPart(part) {
2539
- return isRecord(part) && part.type === "text" && typeof part.text === "string" && stripWellFormedLeadingTagPrefix(part.text).trim() === "";
2540
- }
2541
- function isCanonicalBlankPart(part) {
2542
- return isRecord(part) && Object.keys(part).length === 2 && part.type === "text" && part.text === "";
2543
- }
2544
- function trailingBlankKeepCount(decision) {
2545
- if (decision === "keep")
2546
- return 1;
2547
- if (!decision.startsWith("keep:"))
2548
- return;
2549
- const countText = decision.slice("keep:".length);
2550
- if (!/^[1-9]\d*$/.test(countText))
2551
- return;
2552
- const count = Number(countText);
2553
- return Number.isSafeInteger(count) && count > 0 && count <= MAX_FROZEN_TRAILING_BLANKS ? count : undefined;
2554
- }
2555
- function trailingBlankDecisionForMessage(message) {
2556
- const id = message.info.id;
2557
- if (message.info.role !== "assistant" || typeof id !== "string" || id.length === 0) {
2558
- return;
2559
- }
2560
- let trailingCount = 0;
2561
- while (trailingCount < message.parts.length && isSentinelInvisibleTextPart(message.parts[message.parts.length - trailingCount - 1])) {
2562
- trailingCount += 1;
2563
- }
2564
- if (trailingCount > MAX_FROZEN_TRAILING_BLANKS && trailingCount < message.parts.length) {
2565
- return;
2566
- }
2567
- const decision = message.parts.length === 0 || trailingCount === message.parts.length ? "keep" : trailingCount === 0 ? "strip" : trailingCount === 1 ? "keep" : `keep:${trailingCount}`;
2568
- return [id, decision];
2569
- }
2570
- function snapshotTrailingBlankSourceDecisions(messages) {
2571
- const decisions = new Map;
2572
- for (const message of messages) {
2573
- const observed = trailingBlankDecisionForMessage(message);
2574
- if (observed)
2575
- decisions.set(...observed);
2576
- }
2577
- return decisions;
2578
- }
2579
- function findTrailingBlankDecisionCandidates(messages, frozenDecisions, options) {
2580
- const observedDecisions = options?.sourceDecisions ?? snapshotTrailingBlankSourceDecisions(messages);
2581
- const visibleIds = new Set(messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []));
2582
- const decisions = [];
2583
- for (const [id, decision] of observedDecisions) {
2584
- if (!visibleIds.has(id))
2585
- continue;
2586
- const frozen = frozenDecisions.get(id);
2587
- if (frozen !== undefined && (id !== options?.refreshMessageId || frozen === decision || frozen === "strip")) {
2588
- continue;
2589
- }
2590
- decisions.push([id, decision]);
2591
- }
2592
- return decisions;
2593
- }
2594
- function applyFrozenTrailingBlankDecisions(messages, frozenDecisions) {
2595
- let mutations = 0;
2596
- for (let messageIndex = 0;messageIndex < messages.length; messageIndex += 1) {
2597
- let message = messages[messageIndex];
2598
- const id = message.info.id;
2599
- if (message.info.role !== "assistant" || typeof id !== "string")
2600
- continue;
2601
- const decision = frozenDecisions.get(id);
2602
- if (!decision)
2603
- continue;
2604
- let lastMeaningfulIndex = message.parts.length - 1;
2605
- while (lastMeaningfulIndex >= 0 && isSentinelInvisibleTextPart(message.parts[lastMeaningfulIndex])) {
2606
- lastMeaningfulIndex -= 1;
2607
- }
2608
- const replaceParts = (start, deleteCount, insertBlankCount) => {
2609
- message = { ...message, parts: [...message.parts] };
2610
- messages[messageIndex] = message;
2611
- message.parts.splice(start, deleteCount, ...Array.from({ length: insertBlankCount }, () => ({ ...CANONICAL_BLANK_PART })));
2612
- };
2613
- if (lastMeaningfulIndex < 0) {
2614
- if (message.parts.length === 0)
2615
- continue;
2616
- if (message.parts.length !== 1 || !isCanonicalBlankPart(message.parts[0])) {
2617
- mutations += Math.max(1, message.parts.length);
2618
- replaceParts(0, message.parts.length, 1);
2619
- }
2620
- continue;
2621
- }
2622
- const trailingCount = message.parts.length - lastMeaningfulIndex - 1;
2623
- const keepCount = trailingBlankKeepCount(decision);
2624
- if (keepCount !== undefined) {
2625
- if (trailingCount === 0)
2626
- continue;
2627
- const blankIndex = lastMeaningfulIndex + 1;
2628
- const suffixIsCanonical = trailingCount === keepCount && message.parts.slice(blankIndex).every(isCanonicalBlankPart);
2629
- if (!suffixIsCanonical) {
2630
- mutations += Math.max(1, trailingCount, keepCount);
2631
- replaceParts(blankIndex, trailingCount, keepCount);
2632
- }
2633
- continue;
2634
- }
2635
- if (trailingCount === 0)
2636
- continue;
2637
- const lastMeaningfulPart = message.parts[lastMeaningfulIndex];
2638
- if (isRecord(lastMeaningfulPart) && REASONING_PART_TYPES.has(lastMeaningfulPart.type)) {
2639
- const blankIndex = lastMeaningfulIndex + 1;
2640
- if (trailingCount !== 1 || !isCanonicalBlankPart(message.parts[blankIndex])) {
2641
- mutations += Math.max(1, trailingCount);
2642
- replaceParts(blankIndex, trailingCount, 1);
2643
- }
2644
- continue;
2645
- }
2646
- mutations += trailingCount;
2647
- replaceParts(lastMeaningfulIndex + 1, trailingCount, 0);
2648
- }
2649
- return mutations;
2650
- }
2651
- function stripReasoningFromAssistantIds(messages, providerID, messageIds, protectedMessages) {
2652
- if (messageIds.size === 0)
2653
- return 0;
2654
- const emptySentinels = modelAcceptsEmptyContent(providerID);
2655
- let stripped = 0;
2656
- for (const message of messages) {
2657
- if (protectedMessages?.has(message))
2658
- continue;
2659
- const id = message.info.id;
2660
- if (typeof id !== "string" || !messageIds.has(id))
2661
- continue;
2662
- for (let index = 0;index < message.parts.length; index += 1) {
2663
- const part = message.parts[index];
2664
- if (!isRecord(part) || !REASONING_PART_TYPES.has(String(part.type)))
2665
- continue;
2666
- if (emptySentinels) {
2667
- message.parts[index] = makeSentinel(part);
2668
- } else {
2669
- message.parts.splice(index, 1);
2670
- index -= 1;
2671
- }
2672
- stripped += 1;
2673
- }
2674
- if (message.parts.length === 0)
2675
- message.parts.push(makeWholeMessageSentinel(providerID));
2676
- }
2677
- return stripped;
2678
- }
2679
- function findMergedReasoningStripDecisions(messages, providerID, frozenIds, options) {
2680
- if (providerID !== "anthropic")
2681
- return [];
2682
- const frozenParts = readFrozenMergedReasoningParts(frozenIds);
2683
- const decisions = [];
2684
- for (const entry of planMergedAssistantReasoningStrip(messages, options?.mutationExemptMessage, new Set(frozenParts.keys()), options?.protectedMessages)) {
2685
- const id = entry.message.info.id;
2686
- if (typeof id !== "string" || id.length === 0 || frozenParts.has(id))
2687
- continue;
2688
- const parts = entry.stripIndices.map((index) => {
2689
- const part = entry.message.parts[index];
2690
- return isRecord(part) && typeof part.id === "string" ? part.id : index;
2691
- });
2692
- decisions.push(id, MERGED_REASONING_PARTS_PREFIX + JSON.stringify([id, parts]));
2693
- }
2694
- return decisions;
2695
- }
2696
- function stripReasoningFromMergedAssistants(messages, providerID, options) {
2697
- if (providerID !== "anthropic")
2698
- return 0;
2699
- let stripped = 0;
2700
- const frozenParts = options?.frozenParts ?? readFrozenMergedReasoningParts(options?.frozenMessageIds ?? new Set);
2701
- for (const message of messages) {
2702
- if (message.info.role !== "assistant" || options?.restoreMessages?.has(message))
2703
- continue;
2704
- const parts = frozenParts.get(message.info.id ?? "");
2705
- if (!parts)
2706
- continue;
2707
- for (let index = 0;index < message.parts.length; index += 1) {
2708
- const part = message.parts[index];
2709
- if (!isRecord(part) || !REASONING_PART_TYPES.has(String(part.type)))
2710
- continue;
2711
- if (!parts.includes(index) && !(typeof part.id === "string" && parts.includes(part.id)))
2712
- continue;
2713
- message.parts[index] = makeSentinel(part);
2714
- stripped++;
2715
- }
2716
- }
2717
- for (const entry of planMergedAssistantReasoningStrip(messages, options?.mutationExemptMessage, options?.frozenPartMessageIds ?? new Set(frozenParts.keys()), options?.frozenMessageIds ? options.restoreMessages : options?.protectedMessages)) {
2718
- if (options?.frozenMessageIds) {
2719
- const id = entry.message.info.id;
2720
- if (typeof id !== "string" || !options.frozenMessageIds.has(id))
2721
- continue;
2722
- }
2723
- for (const index of entry.stripIndices) {
2724
- entry.message.parts[index] = makeSentinel(entry.message.parts[index]);
2725
- stripped++;
2726
- }
2727
- }
2728
- return stripped;
2729
- }
2730
- function stripProcessedImages(messages, frozenIds, options) {
2731
- const { detect, watermark, messageTagNumbers } = options;
2732
- let stripped = 0;
2733
- const newlyStrippedIds = [];
2734
- let hasAssistantResponse = false;
2735
- for (let i = messages.length - 1;i >= 0; i--) {
2736
- const msg = messages[i];
2737
- if (msg.info.role === "assistant") {
2738
- hasAssistantResponse = true;
2739
- continue;
2740
- }
2741
- if (msg.info.role !== "user") {
2742
- continue;
2743
- }
2744
- const id = typeof msg.info.id === "string" ? msg.info.id : undefined;
2745
- const inFrozen = id !== undefined && frozenIds.has(id);
2746
- const maxTag = messageTagNumbers.get(msg) ?? 0;
2747
- const isNewDetection = !inFrozen && detect && hasAssistantResponse && id !== undefined && maxTag <= watermark;
2748
- if (!inFrozen && !isNewDetection) {
2749
- continue;
2750
- }
2751
- let touchedThisMsg = false;
2752
- for (let j = 0;j < msg.parts.length; j++) {
2753
- const part = msg.parts[j];
2754
- if (!isRecord(part) || part.type !== "file") {
2755
- continue;
2756
- }
2757
- if (typeof part.mime !== "string" || !part.mime.startsWith("image/")) {
2758
- continue;
2759
- }
2760
- if (typeof part.url === "string" && part.url.startsWith("data:") && part.url.length > 200) {
2761
- if (isNewDetection)
2762
- options.onFirstApplication?.(msg, j);
2763
- msg.parts[j] = makeSentinel(part);
2764
- stripped++;
2765
- touchedThisMsg = true;
2766
- }
2767
- }
2768
- if (touchedThisMsg && isNewDetection && id !== undefined) {
2769
- newlyStrippedIds.push(id);
2770
- }
2771
- }
2772
- return { stripped, newlyStrippedIds };
2773
- }
2774
-
2775
- // src/hooks/magic-context/reasoning-budget.ts
2776
- function projectOpencodeReasoningBudgetCutoff(db, sessionId, messages, budget, watermark, proseRatio) {
2777
- const textEstimateByMessageId = getReasoningTokenEstimatesByMessage2(db, sessionId, proseRatio);
2778
- const maxTags = getMaxTagNumberByOwnerMessage2(db, sessionId);
2779
- const messageTags = new Map;
2780
- const gone = new Set(getReasoningRemovalState(db, sessionId).messageIds);
2781
- for (const message of messages) {
2782
- if (typeof message.info.id !== "string")
2783
- continue;
2784
- const tag = maxTags.get(message.info.id) ?? 0;
2785
- messageTags.set(message, tag);
2786
- if (tag > 0 && tag <= watermark)
2787
- gone.add(message.info.id);
2788
- }
2789
- const frozenMergedIds = getMergedReasoningStrippedIds(db, sessionId);
2790
- return opencodeReasoningBudgetCutoff({
2791
- messages,
2792
- messageTagNumbers: messageTags,
2793
- budget,
2794
- alreadyRemoved: gone,
2795
- textEstimateByMessageId,
2796
- proseRatio,
2797
- frozenMergedIds,
2798
- alsoGone: new Set([...frozenMergedIds].filter((id) => id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)).map((id) => id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length)))
2799
- });
2800
- }
2801
- var DEFAULT_KEEP_REASONING_TOKENS = 1e4;
2802
- var UNKNOWN_REASONING_STEP_TOKENS = 1000;
2803
- function resolveKeepReasoningTokens(config, modelKey) {
2804
- const values = config && typeof config === "object" ? Object.assign(Object.create(null), config) : undefined;
2805
- return typeof config === "number" ? config : resolveModelConfigValue(values, modelKey)?.value ?? values?.default ?? DEFAULT_KEEP_REASONING_TOKENS;
2806
- }
2807
- function reasoningStepCost(reported, textEstimate, opaque) {
2808
- if (reported !== undefined && Number.isFinite(reported) && reported > 0)
2809
- return reported;
2810
- if (textEstimate > 0)
2811
- return Math.ceil(textEstimate);
2812
- return opaque ? UNKNOWN_REASONING_STEP_TOKENS : 0;
2813
- }
2814
- function reasoningBudgetCutoff(steps, budget) {
2815
- const cost = (step) => step.alreadyRemoved ? 0 : typeof step.cost === "function" ? step.cost() : step.cost;
2816
- let kept = 0;
2817
- let upperBound = Number.POSITIVE_INFINITY;
2818
- for (const step of steps) {
2819
- if (!step.exempt)
2820
- continue;
2821
- kept += cost(step);
2822
- if (step.tag > 0)
2823
- upperBound = Math.min(upperBound, step.tag - 1);
2824
- }
2825
- for (let index = steps.length - 1;index >= 0; index--) {
2826
- const step = steps[index];
2827
- if (step.exempt || step.alreadyRemoved)
2828
- continue;
2829
- const tokens = cost(step);
2830
- if (kept + tokens <= budget) {
2831
- kept += tokens;
2832
- if (step.tag > 0)
2833
- upperBound = Math.min(upperBound, step.tag - 1);
2834
- continue;
2835
- }
2836
- let tag = step.tag;
2837
- for (let older = index - 1;tag <= 0 && older >= 0; older--)
2838
- tag = steps[older].tag;
2839
- return Math.max(0, Math.min(tag, upperBound));
2840
- }
2841
- return 0;
2842
- }
2843
- function reasoningTextAndOpaque(parts) {
2844
- let text = "";
2845
- let inlineText = "";
2846
- let opaque = false;
2847
- let hasReasoning = false;
2848
- const detailText = new Set;
2849
- for (const part of parts) {
2850
- if (!isRecord(part))
2851
- continue;
2852
- if (part.ignored === true)
2853
- continue;
2854
- if (isRecord(part.metadata)) {
2855
- const router = part.metadata.openrouter;
2856
- if (isRecord(router) && Array.isArray(router.reasoning_details) && router.reasoning_details.length > 0) {
2857
- hasReasoning = true;
2858
- opaque = true;
2859
- for (const detail of router.reasoning_details) {
2860
- if (!isRecord(detail))
2861
- continue;
2862
- if (detail.type === "reasoning.text" && typeof detail.text === "string")
2863
- detailText.add(detail.text);
2864
- if (detail.type === "reasoning.summary" && typeof detail.summary === "string")
2865
- detailText.add(detail.summary);
2866
- }
2867
- }
2868
- }
2869
- if (["reasoning", "thinking", "redacted_thinking"].includes(String(part.type))) {
2870
- hasReasoning = true;
2871
- const visible = part.type === "redacted_thinking" || part.redacted === true ? "" : typeof part.thinking === "string" ? part.thinking : typeof part.text === "string" ? part.text : "";
2872
- if (visible !== "[cleared]")
2873
- text += visible;
2874
- opaque ||= part.type === "redacted_thinking" || part.redacted === true || visible === "" && (part.metadata !== undefined || part.signature !== undefined || part.thinkingSignature !== undefined);
2875
- } else if (part.type === "text" && typeof part.text === "string") {
2876
- for (const match of part.text.matchAll(/<(?:thinking|think)>([\s\S]*?)<\/(?:thinking|think)>/gi))
2877
- inlineText += match[1];
2878
- }
2879
- }
2880
- return { text: text || [...detailText].join(""), inlineText, opaque, hasReasoning };
2881
- }
2882
- function opencodeReasoningBudgetCutoff(args) {
2883
- const assistants = args.messages.filter((message) => message.info.role === "assistant");
2884
- const newest = assistants.at(-1);
2885
- const exempt = findLatestAssistantReasoningMutationExemptMessage(args.messages);
2886
- const anthropic = args.anthropic ?? hasAnthropicReasoning(args.messages);
2887
- const indexOfMessage = new Map;
2888
- args.messages.forEach((message, index) => {
2889
- if (!indexOfMessage.has(message))
2890
- indexOfMessage.set(message, index);
2891
- });
2892
- const frozenParts = args.frozenMergedIds ? readFrozenMergedReasoningParts(args.frozenMergedIds) : undefined;
2893
- const frozenPartMessageIds = frozenParts ? new Set(frozenParts.keys()) : undefined;
2894
- return reasoningBudgetCutoff(assistants.map((message) => ({
2895
- tag: args.messageTagNumbers.get(message) ?? 0,
2896
- exempt: message === newest || message === exempt || isInActiveAnthropicTurn(args.messages, indexOfMessage.get(message) ?? -1, anthropic),
2897
- cost: () => {
2898
- const costMessage = { ...message, parts: [...message.parts] };
2899
- const id = message.info.id ?? "";
2900
- if (args.frozenMergedIds && (frozenParts?.has(id) || args.frozenMergedIds.has(id)))
2901
- stripReasoningFromMergedAssistants([costMessage], "anthropic", {
2902
- frozenMessageIds: args.frozenMergedIds,
2903
- frozenParts,
2904
- frozenPartMessageIds
2905
- });
2906
- const visible = reasoningTextAndOpaque(args.countNeutralized ? costMessage.parts.map(neutralizedReasoningSource) : costMessage.parts);
2907
- if (!visible.hasReasoning && !visible.inlineText)
2908
- return 0;
2909
- const info = message.info;
2910
- const tokens = isRecord(info.tokens) ? info.tokens.reasoning : undefined;
2911
- const typedGone = typeof message.info.id === "string" && (args.alreadyRemoved?.has(message.info.id) === true || args.alsoGone?.has(message.info.id) === true);
2912
- return (visible.hasReasoning && !typedGone ? reasoningStepCost(typeof tokens === "number" ? tokens : undefined, estimateTokens(visible.text) * (args.proseRatio ?? 1), visible.opaque) : 0) + Math.ceil(estimateTokens(visible.inlineText) * (args.proseRatio ?? 1));
2913
- }
2914
- })), args.budget);
2915
- }
2916
-
2917
2162
  // src/hooks/magic-context/reasoning-budget-status.ts
2918
2163
  var sources = new Map;
2919
2164
  function captureOpencodeReasoningBudgetStatus(sessionId, messages, budget, prefixBound, proseRatio = 1) {
@@ -3001,11 +2246,15 @@ function opencodeReasoningBudgetStatus(messages, budget, prefixBound, proseRatio
3001
2246
 
3002
2247
  // src/hooks/magic-context/emergency-fail-closed.ts
3003
2248
  var ENGINE_RECONNECTING_USER_MESSAGE = "Magic Context's engine is reconnecting. Send your message again in a few seconds.";
2249
+ var ENGINE_BUSY_USER_MESSAGE = "Magic Context is still applying the previous context update for this session. Send your message again in a moment.";
3004
2250
  var PROTECTED_TOOL_RESULTS_OVER_LIMIT = "The tool results kept by protected_tools are larger than this model's context window, so this turn was not sent. Lower the protected_tools counts.";
3005
2251
  var PROTECTED_TOOL_RESULTS_OVER_LIMIT_CODE = "protected_tool_results_over_limit";
2252
+ var SIGNED_TURN_OVER_LIMIT = "This turn's context is larger than the model's context window even after all of its thinking and reclaimable tool output were removed, so it was not sent. Send a new message or start a new session to continue.";
2253
+ var SIGNED_TURN_OVER_LIMIT_CODE = "signed_turn_over_limit";
2254
+ var SIGNED_THINKING_RESET_FENCE_FAILED = "Magic Context could not record a thinking reset for this session, so this turn was not sent. Send your message again.";
3006
2255
  function contextRefusalError(message) {
3007
2256
  return new EmergencyFailClosedError(message, {
3008
- code: message === PROTECTED_TOOL_RESULTS_OVER_LIMIT ? PROTECTED_TOOL_RESULTS_OVER_LIMIT_CODE : undefined
2257
+ code: message === PROTECTED_TOOL_RESULTS_OVER_LIMIT ? PROTECTED_TOOL_RESULTS_OVER_LIMIT_CODE : message === SIGNED_TURN_OVER_LIMIT ? SIGNED_TURN_OVER_LIMIT_CODE : undefined
3009
2258
  });
3010
2259
  }
3011
2260
  function protectedToolRefusal(error) {
@@ -3015,6 +2264,8 @@ function protectedToolRefusal(error) {
3015
2264
  const current = error;
3016
2265
  if (current.code === PROTECTED_TOOL_RESULTS_OVER_LIMIT_CODE)
3017
2266
  return contextRefusalError(PROTECTED_TOOL_RESULTS_OVER_LIMIT);
2267
+ if (current.code === SIGNED_TURN_OVER_LIMIT_CODE)
2268
+ return contextRefusalError(SIGNED_TURN_OVER_LIMIT);
3018
2269
  error = current.cause;
3019
2270
  }
3020
2271
  return;
@@ -3024,6 +2275,11 @@ function outgoingContextRefusal(estimate, limit, protectedToolTokens = 0) {
3024
2275
  return;
3025
2276
  return PROTECTED_TOOL_RESULTS_OVER_LIMIT;
3026
2277
  }
2278
+ function signedTurnContextRefusal(estimate, limit) {
2279
+ if (estimate?.refusalGrade !== true || typeof estimate.refusalTokens !== "number" || !Number.isFinite(estimate.refusalTokens) || !limit || !Number.isFinite(limit) || limit <= 0 || estimate.refusalTokens <= limit)
2280
+ return;
2281
+ return SIGNED_TURN_OVER_LIMIT;
2282
+ }
3027
2283
 
3028
2284
  class EmergencyFailClosedError extends Error {
3029
2285
  code;
@@ -3269,14 +2525,14 @@ function retainedActiveThinkingParts(args) {
3269
2525
  }
3270
2526
 
3271
2527
  // src/features/magic-context/storage-caveman-rules.ts
3272
- var NAMESPACE2 = "caveman";
2528
+ var NAMESPACE = "caveman";
3273
2529
  var CURRENT_RULES_VERSION = 2;
3274
2530
  var ORIGINAL_RULES = {
3275
2531
  currentRules: false,
3276
2532
  englishWordRules: true,
3277
2533
  legacyReasoningTags: new Set
3278
2534
  };
3279
- function parseState2(lane) {
2535
+ function parseState(lane) {
3280
2536
  if (!isRecord(lane) || lane.rules !== CURRENT_RULES_VERSION)
3281
2537
  return ORIGINAL_RULES;
3282
2538
  const tags = Array.isArray(lane.legacyReasoningTags) ? lane.legacyReasoningTags : [];
@@ -3288,7 +2544,7 @@ function parseState2(lane) {
3288
2544
  }
3289
2545
  function getCavemanReplayState(db, sessionId) {
3290
2546
  try {
3291
- return parseState2(readReplayEnvelope(db, sessionId)[NAMESPACE2]);
2547
+ return parseState(readReplayEnvelope(db, sessionId)[NAMESPACE]);
3292
2548
  } catch (error) {
3293
2549
  if (error instanceof ReplayDocumentError)
3294
2550
  return ORIGINAL_RULES;
@@ -3298,11 +2554,11 @@ function getCavemanReplayState(db, sessionId) {
3298
2554
  function recordCavemanCurrentRules(db, sessionId, englishWordRules, legacyReasoningTags) {
3299
2555
  const tags = [...new Set(legacyReasoningTags)].sort((a, b) => a - b);
3300
2556
  const persisted = updateReplayDocument(db, sessionId, (doc) => {
3301
- const current = parseState2(doc[NAMESPACE2]);
2557
+ const current = parseState(doc[NAMESPACE]);
3302
2558
  if (current.currentRules && current.englishWordRules === englishWordRules)
3303
2559
  return false;
3304
2560
  doc.version = 2;
3305
- doc[NAMESPACE2] = {
2561
+ doc[NAMESPACE] = {
3306
2562
  rules: CURRENT_RULES_VERSION,
3307
2563
  legacyReasoningTags: current.currentRules ? [...current.legacyReasoningTags].sort((a, b) => a - b) : tags,
3308
2564
  ...englishWordRules ? {} : { englishWordRules: false }
@@ -4343,6 +3599,39 @@ function postprocessReplaySnapshot(db, sessionId) {
4343
3599
  };
4344
3600
  }
4345
3601
 
3602
+ // src/hooks/magic-context/strict-thinking-prefix.ts
3603
+ function servedPrefixMatches(args) {
3604
+ const heads = args.messages?.slice(0, 2);
3605
+ if (!heads || heads.length !== 2 || args.m0Text == null || args.m1Text == null)
3606
+ return false;
3607
+ const text = (message) => {
3608
+ if (!isRecord(message))
3609
+ return;
3610
+ if (typeof message.content === "string")
3611
+ return message.content;
3612
+ const parts = Array.isArray(message.parts) ? message.parts : message.content;
3613
+ if (!Array.isArray(parts))
3614
+ return;
3615
+ return parts.filter(isRecord).filter((part) => part.type === "text").map((part) => String(part.text ?? "")).join("");
3616
+ };
3617
+ if (text(heads[0]) !== args.m0Text || text(heads[1]) !== args.m1Text)
3618
+ return false;
3619
+ const head = heads[0];
3620
+ if (!isRecord(head))
3621
+ return false;
3622
+ const parts = Array.isArray(head.parts) ? head.parts : head.content;
3623
+ if (!Array.isArray(parts))
3624
+ return !args.muralDataUrl;
3625
+ const images = parts.filter(isRecord).filter((part) => part.type === "image" || part.type === "file");
3626
+ if (!args.muralDataUrl)
3627
+ return images.length === 0;
3628
+ if (images.length !== 1)
3629
+ return false;
3630
+ const image = images[0];
3631
+ const url = typeof image.url === "string" ? image.url : typeof image.data === "string" && typeof image.mimeType === "string" ? `data:${image.mimeType};base64,${image.data}` : undefined;
3632
+ return url === args.muralDataUrl;
3633
+ }
3634
+
4346
3635
  // src/hooks/magic-context/supersession-reclaim.ts
4347
3636
  var SUPERSESSION_RECENT_MESSAGE_WINDOW = 20;
4348
3637
  function recentSupersessionOwnerMessageIds(db, sessionId) {
@@ -4655,6 +3944,7 @@ function getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages)
4655
3944
  const messageIds = messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []);
4656
3945
  const ownersKey = JSON.stringify(messageIds);
4657
3946
  const tagsVersion = tagger.getLoadedTagsVersion?.(sessionId, db);
3947
+ const identityRevision = tagger.getLoadedTagIdentityRevision?.(sessionId, db);
4658
3948
  if (tagsVersion === undefined)
4659
3949
  return getInertWhitespaceAssistantTags2(db, sessionId, messageIds);
4660
3950
  let bySession = inertWhitespaceCache.get(db);
@@ -4663,10 +3953,10 @@ function getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages)
4663
3953
  inertWhitespaceCache.set(db, bySession);
4664
3954
  }
4665
3955
  const cached = bySession.get(sessionId);
4666
- if (cached?.tagsVersion === tagsVersion && cached.ownersKey === ownersKey)
3956
+ if (cached?.tagsVersion === tagsVersion && cached.identityRevision === identityRevision && cached.ownersKey === ownersKey)
4667
3957
  return cached.tags;
4668
3958
  const tags = getInertWhitespaceAssistantTags2(db, sessionId, messageIds);
4669
- bySession.set(sessionId, { tagsVersion, ownersKey, tags });
3959
+ bySession.set(sessionId, { tagsVersion, identityRevision, ownersKey, tags });
4670
3960
  return tags;
4671
3961
  }
4672
3962
  function makeToolOwnerCacheKey(sessionId, callId) {
@@ -5011,7 +4301,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5011
4301
  accAssignTag += performance.now() - _tAssignText;
5012
4302
  const persistedSource = sourceContents.get(tagId);
5013
4303
  if (persistedSource !== undefined) {
5014
- textPart.text = persistedSource;
4304
+ textPart.text = options.normalizeRestoredAssistantText && message.info.role === "assistant" ? options.normalizeRestoredAssistantText(persistedSource) : persistedSource;
5015
4305
  } else {
5016
4306
  const sourceContent = stripTagPrefix(textPart.text);
5017
4307
  if (sourceContent.trim().length > 0) {
@@ -5509,6 +4799,8 @@ function applyRustModeThinkingStrips(args, hostEditBeforeNewestThinking) {
5509
4799
  const recoveryMessageIds = new Set;
5510
4800
  let thinkingBindingRecovery = null;
5511
4801
  let proactiveThinkingStrip = null;
4802
+ const signedThinkingReset = args.cacheBustingPass === true && args.moduleSignedThinkingReset === true;
4803
+ const stripProtection = signedThinkingReset ? undefined : args.protectedThinkingMessages;
5512
4804
  {
5513
4805
  try {
5514
4806
  for (const id of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
@@ -5535,26 +4827,31 @@ function applyRustModeThinkingStrips(args, hostEditBeforeNewestThinking) {
5535
4827
  } catch (error) {
5536
4828
  sessionLog2(args.sessionId, "rust thinking binding recovery failed:", error);
5537
4829
  }
5538
- stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds, args.protectedThinkingMessages);
5539
- const moduleBustStrips = !args.activeThinkingTurn && args.cacheBustingPass === true && (args.moduleReasoningTrimOnly !== true || hostEditBeforeNewestThinking);
5540
- const stripFrom = args.thinkingBindingRecoveryEnabledForModel === true ? proactiveStripStartIndex({ ...args, cacheBustingPass: moduleBustStrips }) : null;
4830
+ stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, recoveryMessageIds, stripProtection);
4831
+ const moduleBustStrips = signedThinkingReset || !args.activeThinkingTurn && args.cacheBustingPass === true && (args.moduleReasoningTrimOnly !== true || hostEditBeforeNewestThinking);
4832
+ const stripFrom = args.thinkingBindingRecoveryEnabledForModel === true || signedThinkingReset ? proactiveStripStartIndex({ ...args, cacheBustingPass: moduleBustStrips }) : null;
5541
4833
  if (stripFrom !== null) {
4834
+ const stripped = args.messages.slice(stripFrom);
5542
4835
  const outcome = freezeReasoningOnBustingPass2({
5543
4836
  db: args.db,
5544
4837
  sessionId: args.sessionId,
5545
- messages: args.messages.slice(stripFrom),
5546
- protectedMessages: args.protectedThinkingMessages,
4838
+ messages: stripped,
4839
+ protectedMessages: stripProtection,
5547
4840
  alreadyFrozen: recoveryMessageIds
5548
4841
  });
5549
4842
  if (outcome.strip) {
5550
4843
  proactiveThinkingStrip = outcome.strip;
5551
4844
  for (const id of outcome.strip.messageIds)
5552
4845
  recoveryMessageIds.add(id);
5553
- stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, new Set(outcome.strip.messageIds), args.protectedThinkingMessages);
4846
+ }
4847
+ const removed = signedThinkingReset ? new Set(findReasoningBearingAssistantIds(stripped)) : new Set(outcome.strip?.messageIds ?? []);
4848
+ if (removed.size > 0) {
4849
+ stripReasoningFromAssistantIds(args.messages, args.resolvedProviderID, removed, stripProtection);
5554
4850
  }
5555
4851
  }
5556
4852
  }
5557
- args.restoreLatestTurnOriginals?.();
4853
+ if (!signedThinkingReset)
4854
+ args.restoreLatestTurnOriginals?.();
5558
4855
  return { thinkingBindingRecovery, proactiveThinkingStrip };
5559
4856
  }
5560
4857
  function runRustModePostprocess2(args) {
@@ -5597,7 +4894,7 @@ function runRustModePostprocess2(args) {
5597
4894
  appendReminderToUserMessageById(args.messages, anchor.messageId, anchor.text);
5598
4895
  }
5599
4896
  for (const decision of getAutoSearchHintDecisions(args.db, args.sessionId)) {
5600
- if (decision.decision === "hint") {
4897
+ if (decision.decision === "hint" && getUnpublishedAutoSearchNoHint(args.sessionId, decision.messageId) === undefined) {
5601
4898
  appendReminderToUserMessageById(args.messages, decision.messageId, decision.text);
5602
4899
  }
5603
4900
  }
@@ -5859,8 +5156,9 @@ async function runPostTransformPhase2(args) {
5859
5156
  }
5860
5157
  const reasoningMutationExemptMessage = findLatestAssistantReasoningMutationExemptMessage(args.messages);
5861
5158
  const pendingMaterializationAtPassStart = args.pendingMaterializationSessions.has(args.sessionId);
5159
+ const pendingOrigin = pendingMaterializationOrigin(args.pendingMaterializationSessions, args.sessionId);
5862
5160
  const deferredMaterializationAtPassStart = args.deferredMaterializationSessions.has(args.sessionId);
5863
- const isExplicitFlush = pendingMaterializationAtPassStart;
5161
+ let isExplicitFlush = pendingMaterializationAtPassStart;
5864
5162
  const deferredMaterializationWasPending = deferredMaterializationAtPassStart;
5865
5163
  const alreadyRanThisTurn = args.currentTurnId !== null && args.lastHeuristicsTurnId.get(args.sessionId) === args.currentTurnId;
5866
5164
  const forceMaterialization = args.fullFeatureMode && !compactionOff && args.contextUsage.percentage >= args.forceMaterializationPercentage;
@@ -5877,8 +5175,8 @@ async function runPostTransformPhase2(args) {
5877
5175
  }
5878
5176
  const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
5879
5177
  const compartmentRunning = args.canRunCompartments && !args.awaitedCompartmentRun && activeCompartmentRun !== undefined;
5880
- const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
5881
- const materializationRequested = isExplicitFlush || deferredMaterialize;
5178
+ let deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
5179
+ let materializationRequested = isExplicitFlush || deferredMaterialize;
5882
5180
  const m0M1EnabledForFold = args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory) && (args.fullFeatureMode || compactionOff);
5883
5181
  const frozenThinking = new Set(args.activeThinkingTurn ? getMergedReasoningStrippedIds(args.db, args.sessionId) : []);
5884
5182
  const bindingThinking = new Set([...frozenThinking].filter((id) => id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)).map((id) => id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length)));
@@ -5890,9 +5188,9 @@ async function runPostTransformPhase2(args) {
5890
5188
  bindingIds: bindingThinking,
5891
5189
  removedIds: getReasoningRemovalState(args.db, args.sessionId).messageIds
5892
5190
  }) : new Set;
5893
- const activeThinkingTurn = retainedThinking.size > 0;
5191
+ let activeThinkingTurn = retainedThinking.size > 0;
5894
5192
  const protectedThinkingMessages = new Set(args.messages.filter((message) => message.parts.some((part) => retainedThinking.has(part))));
5895
- const newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
5193
+ let newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
5896
5194
  let maxReasoningTag = 0;
5897
5195
  for (const tag of args.messageTagNumbers.values())
5898
5196
  maxReasoningTag = Math.max(maxReasoningTag, tag);
@@ -5902,7 +5200,28 @@ async function runPostTransformPhase2(args) {
5902
5200
  if (tag && tag > 0)
5903
5201
  safeReasoningCutoff = Math.min(safeReasoningCutoff, tag - 1);
5904
5202
  }
5905
- const freezeM0M1 = args.freezeM0M1 === true || activeThinkingTurn && args.thinkingBindingRecoveryEnabledForModel === true;
5203
+ let activeThinkingPrefixHold = args.activeThinkingPrefixHold === true || activeThinkingTurn && args.thinkingBindingRecoveryEnabledForModel === true;
5204
+ let freezeM0M1 = args.freezeM0M1 === true || activeThinkingPrefixHold;
5205
+ let rewritingSignedPrefix = false;
5206
+ let thinkingReleasedForFit = false;
5207
+ const releaseThinkingForRewrite = (forFit = false) => {
5208
+ const stripped = freezeReasoningOnBustingPass2({
5209
+ db: args.db,
5210
+ sessionId: args.sessionId,
5211
+ messages: args.messages,
5212
+ alreadyFrozen: bindingThinking
5213
+ });
5214
+ if (stripped.persistenceFailed)
5215
+ throw new Error("Cannot persist signed thinking omission before prefix rewrite");
5216
+ retainedThinking.clear();
5217
+ protectedThinkingMessages.clear();
5218
+ activeThinkingTurn = false;
5219
+ activeThinkingPrefixHold = false;
5220
+ freezeM0M1 = args.directoryPrefixHold === true;
5221
+ newTargets = args.targets;
5222
+ rewritingSignedPrefix = true;
5223
+ thinkingReleasedForFit ||= forFit;
5224
+ };
5906
5225
  const foldDueDecision = m0M1EnabledForFold && args.m0M1 && !freezeM0M1 ? mustMaterialize({
5907
5226
  db: args.db,
5908
5227
  sessionId: args.sessionId,
@@ -5922,6 +5241,7 @@ async function runPostTransformPhase2(args) {
5922
5241
  const cachedPrefixBeforePreflight = shouldCaptureCachedPrefix ? prepareCachedM0M1Replay(args.db, args.sessionId) : undefined;
5923
5242
  const completeCachedPrefixAvailable = args.sessionMeta.cachedM0Bytes != null && args.sessionMeta.cachedM1Bytes != null || cachedPrefixBeforePreflight !== undefined || m0M1EnabledForFold && !shouldCaptureCachedPrefix && hasCompleteCachedM0M1(args.db, args.sessionId);
5924
5243
  const firstRenderBust = m0M1EnabledForFold && !completeCachedPrefixAvailable;
5244
+ const servedBeforeFirstRender = firstRenderBust ? args.readLastServedMessages?.() : null;
5925
5245
  let foldExecutedThisPass = false;
5926
5246
  let foldBustsServedPrefixThisPass = false;
5927
5247
  let publishedM1RefreshedThisPass = false;
@@ -5939,7 +5259,7 @@ async function runPostTransformPhase2(args) {
5939
5259
  m1Bytes: args.sessionMeta.cachedM1Bytes ?? null,
5940
5260
  muralDataUrl: args.sessionMeta.cachedM0MuralDataUrl ?? null
5941
5261
  };
5942
- if ((foldDueDecision.value || softRefreshOpportunity) && m0M1EnabledForFold && args.m0M1) {
5262
+ if ((foldDueDecision.value || softRefreshOpportunity || firstRenderBust && activeThinkingPrefixHold) && m0M1EnabledForFold && args.m0M1) {
5943
5263
  let committedFoldBustsServedPrefix;
5944
5264
  try {
5945
5265
  const previousM1 = args.sessionMeta.cachedM1Bytes?.toString("utf8");
@@ -5964,7 +5284,12 @@ async function runPostTransformPhase2(args) {
5964
5284
  onFoldPrepare: () => {
5965
5285
  const conversions = prepareLegacyToolSkeletonConversions(args.db, args.sessionId, args.targets);
5966
5286
  return (db, rendered) => {
5967
- const bustsPrefix = foldBustsServedPrefix(foldDueDecision.reason, servedPrefixBeforeFold, rendered);
5287
+ const bustsPrefix = activeThinkingPrefixHold ? !servedPrefixMatches({
5288
+ messages: servedBeforeFirstRender,
5289
+ m0Text: rendered.m0Bytes.toString(),
5290
+ m1Text: rendered.m1Bytes.toString(),
5291
+ muralDataUrl: rendered.muralDataUrl
5292
+ }) : foldBustsServedPrefix(foldDueDecision.reason, servedPrefixBeforeFold, rendered);
5968
5293
  if (bustsPrefix) {
5969
5294
  if (!conversions.isCurrent(db)) {
5970
5295
  throw new MaterializeContentionError({
@@ -5981,6 +5306,9 @@ async function runPostTransformPhase2(args) {
5981
5306
  }
5982
5307
  });
5983
5308
  preparedPrefix = foldResult;
5309
+ if (activeThinkingPrefixHold && firstRenderBust && committedFoldBustsServedPrefix) {
5310
+ releaseThinkingForRewrite();
5311
+ }
5984
5312
  prefixPreflightFailed = foldResult.materializationContentionRetryExhausted === true;
5985
5313
  foldExecutedThisPass = foldExecutesThisPass(foldDueDecision.value || softRefreshOpportunity, foldResult.m0RematerializedThisPass);
5986
5314
  foldBustsServedPrefixThisPass = foldExecutedThisPass && (committedFoldBustsServedPrefix ?? true);
@@ -6014,18 +5342,33 @@ async function runPostTransformPhase2(args) {
6014
5342
  }
6015
5343
  sessionLog2(args.sessionId, `m[0] HARD fold decision: reason=${m0MaterializeReason ?? foldDueDecision.reason ?? (foldExecutedThisPass ? "drift" : "soft_refresh")} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
6016
5344
  }
5345
+ if (args.normalizeRecoveryTail && (foldBustsServedPrefixThisPass || firstRenderBust)) {
5346
+ args.normalizeRecoveryTail();
5347
+ args.tags = getTagsBySession2(args.db, args.sessionId);
5348
+ newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
5349
+ }
6017
5350
  logTransformTiming(args.sessionId, "pp.prefixPreflight", tPostprocessSetup, `foldExecuted=${foldExecutedThisPass} m1Refreshed=${publishedM1RefreshedThisPass}`);
6018
5351
  const tPassDecisions = performance.now();
5352
+ const frontToolCandidates = args.tags.filter((tag) => tag.type === "tool" && tag.status === "active" && args.targets.get(tag.tagNumber)?.canDrop?.());
5353
+ if (activeThinkingPrefixHold && (args.forceSignedRebuildForFit || args.contextUsage.percentage >= 95 && frontToolCandidates.length > 0 && frontToolCandidates.every((tag) => newTargets.get(tag.tagNumber)?.thinkingRewriteProtected === true))) {
5354
+ releaseThinkingForRewrite(true);
5355
+ }
5356
+ if (activeThinkingPrefixHold) {
5357
+ isExplicitFlush = false;
5358
+ deferredMaterialize = false;
5359
+ materializationRequested = false;
5360
+ }
6019
5361
  const shouldReadPendingOps = !compactionOff && (materializationRequested || publishedM1RefreshedThisPass || args.schedulerDecision === "execute" || forceMaterialization || foldExecutedThisPass || firstRenderBust || compartmentRunning);
6020
5362
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
6021
5363
  const hasPendingUserOps = pendingOps.length > 0;
6022
5364
  if (args.schedulerDecision === "execute" && pendingOps.some((op) => newTargets.get(op.tagId)?.thinkingDropProtected))
6023
- args.pendingMaterializationSessions.add(args.sessionId);
5365
+ requestPendingMaterialization(args.pendingMaterializationSessions, args.sessionId, "thinking_hold");
6024
5366
  const formatPendingOpsDepth = () => {
6025
5367
  const depth = getPendingOpsCount(args.db, args.sessionId);
6026
5368
  return depth === null ? "not loaded (deferred pass)" : String(depth);
6027
5369
  };
6028
- const idleExpiryRebuild = !freezeM0M1 && args.m0M1?.hardSignals?.cacheExpired === true;
5370
+ const heldIdleExpiryRebuild = activeThinkingPrefixHold && args.m0M1?.hardSignals?.cacheExpired === true;
5371
+ const idleExpiryRebuild = (!freezeM0M1 || activeThinkingPrefixHold) && args.m0M1?.hardSignals?.cacheExpired === true;
6029
5372
  const rideSignals = {
6030
5373
  subagentExecute: !args.fullFeatureMode && args.schedulerDecision === "execute",
6031
5374
  hardFold: foldBustsServedPrefixThisPass || firstRenderBust || idleExpiryRebuild,
@@ -6033,15 +5376,16 @@ async function runPostTransformPhase2(args) {
6033
5376
  explicitFlush: isExplicitFlush || deferredMaterialize && !prefixPreflightFailed,
6034
5377
  publishedHistory: publishedM1RefreshedThisPass || !m0M1EnabledForFold && (args.pendingCompartmentInjection?.compartmentCount ?? 0) > 0 && (args.historyRebuiltThisPass || args.rebuiltHistoryFromInitialPrepare || args.canConsumeDeferredLate && args.deferredHistoryWasPendingAtPassStart)
6035
5378
  };
6036
- const publishedWorkDrainAllowed = !compactionOff && hasReclaimRide(rideSignals);
5379
+ const publishedWorkDrainAllowed = !compactionOff && (!activeThinkingPrefixHold || firstRenderBust || idleExpiryRebuild || emergencyDropEligible) && hasReclaimRide(rideSignals);
6037
5380
  const shouldApplyPendingOps = publishedWorkDrainAllowed;
6038
- const shouldRunHeuristics = !compactionOff && hasReclaimRide(rideSignals) && (rideSignals.publishedHistory || materializationRequested || forceMaterialization || foldBustsServedPrefixThisPass || firstRenderBust || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
5381
+ const shouldRunHeuristics = publishedWorkDrainAllowed && (rideSignals.publishedHistory || materializationRequested || forceMaterialization || foldBustsServedPrefixThisPass || firstRenderBust || heldIdleExpiryRebuild || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
6039
5382
  const isCacheBustingPass = publishedWorkDrainAllowed;
5383
+ const canEditWholePrefix = isCacheBustingPass && !activeThinkingPrefixHold;
6040
5384
  const previousTemporalDecisions = args.temporalCandidates && !compactionOff ? new Map([
6041
5385
  ...args.temporalObservedDecisions ?? [],
6042
5386
  ...getTemporalDecisions(args.db, args.sessionId, args.temporalReplayIds ?? args.temporalCandidates.keys())
6043
5387
  ]) : undefined;
6044
- const temporalDecisions = args.temporalCandidates && !compactionOff ? isCacheBustingPass ? new Map([
5388
+ const temporalDecisions = args.temporalCandidates && !compactionOff ? canEditWholePrefix ? new Map([
6045
5389
  ...previousTemporalDecisions ?? [],
6046
5390
  ...freezeTemporalDecisions(args.db, args.sessionId, args.temporalCandidates)
6047
5391
  ]) : previousTemporalDecisions : undefined;
@@ -6109,7 +5453,7 @@ async function runPostTransformPhase2(args) {
6109
5453
  }
6110
5454
  if (shouldRunHeuristics) {
6111
5455
  const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
6112
- const reason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `${reclaimRideLabel(rideSignals)} subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
5456
+ const reason = isExplicitFlush ? `pending_materialization origin=${pendingOrigin}` : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `${reclaimRideLabel(rideSignals)} subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
6113
5457
  sessionLog2(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
6114
5458
  } else if (args.schedulerDeferReason !== undefined && args.schedulerDeferReason !== null) {
6115
5459
  sessionLog2(args.sessionId, `heuristics WILL NOT RUN — reason=${args.schedulerDeferReason}`);
@@ -6172,7 +5516,7 @@ async function runPostTransformPhase2(args) {
6172
5516
  logTransformTiming(args.sessionId, "pp.passDecisions", tPassDecisions, `pendingOps=${pendingOps.length}`);
6173
5517
  try {
6174
5518
  if (shouldApplyPendingOps) {
6175
- const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (scheduler=${args.schedulerDecision})`;
5519
+ const applyReason = isExplicitFlush ? `pending_materialization origin=${pendingOrigin}` : deferredMaterialize ? "deferred_materialization" : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (scheduler=${args.schedulerDecision})`;
6176
5520
  sessionLog2(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${formatPendingOpsDepth()}, context=${args.contextUsage.percentage.toFixed(1)}%`);
6177
5521
  const tApply = performance.now();
6178
5522
  pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, new Set([
@@ -6199,7 +5543,7 @@ async function runPostTransformPhase2(args) {
6199
5543
  wordRules: args.cavemanTextCompression.wordRules
6200
5544
  } : undefined;
6201
5545
  const heuristicTags = shouldApplyPendingOps ? getActiveTagsBySession2(args.db, args.sessionId) : args.tags;
6202
- const emergencyRewriteAlreadyPriced = pendingOpsDidMutate || foldBustsServedPrefixThisPass || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
5546
+ const emergencyRewriteAlreadyPriced = pendingOpsDidMutate || foldBustsServedPrefixThisPass || firstRenderBust || heldIdleExpiryRebuild || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
6203
5547
  if (emergencyDropEligible && emergencyRewriteAlreadyPriced && getEmergencyInputSample(args.db, args.sessionId) > 0) {
6204
5548
  clearEmergencyDropSample(args.db, args.sessionId);
6205
5549
  }
@@ -6260,7 +5604,7 @@ async function runPostTransformPhase2(args) {
6260
5604
  }
6261
5605
  }
6262
5606
  const reasoningEstimates = tryGetReasoningTokenEstimatesByMessage2(args.db, args.sessionId, sessionDecisionCalibration(args.db, args.sessionId).proseRatio);
6263
- const budgetCutoff = routineCleanupApplied && reasoningEstimates ? Math.min(safeReasoningCutoff, opencodeReasoningBudgetCutoff({
5607
+ const budgetCutoff = routineCleanupApplied && !activeThinkingPrefixHold && reasoningEstimates ? Math.min(safeReasoningCutoff, opencodeReasoningBudgetCutoff({
6264
5608
  messages: args.messages,
6265
5609
  messageTagNumbers: args.messageTagNumbers,
6266
5610
  budget: args.keepReasoningTokens ?? DEFAULT_KEEP_REASONING_TOKENS,
@@ -6282,7 +5626,7 @@ async function runPostTransformPhase2(args) {
6282
5626
  replayStrippedInlineThinking(args.messages, args.messageTagNumbers, persistedInlineWatermark);
6283
5627
  }
6284
5628
  let removedReasoningMessages = 0;
6285
- if (routineCleanupApplied && reasoningRemovalSelectable && reasoningRemovalReadable) {
5629
+ if (routineCleanupApplied && !prefixBoundModel && reasoningRemovalSelectable && reasoningRemovalReadable) {
6286
5630
  const newIds = selectReasoningRemovals({
6287
5631
  messages: args.messages,
6288
5632
  messageTagNumbers: args.messageTagNumbers,
@@ -6337,7 +5681,7 @@ async function runPostTransformPhase2(args) {
6337
5681
  heuristicOrReasoningEditBesidesTrim = heuristicMutationCount + clearedReasoning + strippedInline > 0;
6338
5682
  droppedCount += clearedReasoning + strippedInline + removedReasoningMessages;
6339
5683
  if (pendingMaterializationAtPassStart && !freezeM0M1 && !pendingOps.some((op) => newTargets.get(op.tagId)?.thinkingDropProtected)) {
6340
- args.pendingMaterializationSessions.delete(args.sessionId);
5684
+ clearPendingMaterialization(args.pendingMaterializationSessions, args.sessionId);
6341
5685
  }
6342
5686
  if (args.currentTurnId) {
6343
5687
  args.lastHeuristicsTurnId.set(args.sessionId, args.currentTurnId);
@@ -6399,7 +5743,7 @@ async function runPostTransformPhase2(args) {
6399
5743
  logTransformTiming(args.sessionId, "toolReclaim.select", tReclaimSelect, `targets=${autoReclaimTargetCount}`);
6400
5744
  if (syntheticPendingOps.length > 0) {
6401
5745
  const tReclaimApply = performance.now();
6402
- autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
5746
+ autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
6403
5747
  logTransformTiming(args.sessionId, "toolReclaim.apply", tReclaimApply);
6404
5748
  if (autoReclaimDidMutate) {
6405
5749
  droppedCount += syntheticPendingOps.length;
@@ -6452,7 +5796,7 @@ async function runPostTransformPhase2(args) {
6452
5796
  const t8 = performance.now();
6453
5797
  const frozenStaleReduceIds = replaySnapshot.staleReduceStrippedIds;
6454
5798
  const staleReduceResult = dropStaleReduceCalls(args.messages, frozenStaleReduceIds, {
6455
- detect: isCacheBustingPass,
5799
+ detect: canEditWholePrefix,
6456
5800
  protectedCount: args.protectedCount,
6457
5801
  protectedCallIds: new Set(args.tags.filter((tag) => protectedToolTags.has(tag.tagNumber)).map((tag) => tag.messageId)),
6458
5802
  onFirstApplication: recordFirstApplicationAt
@@ -6470,15 +5814,13 @@ async function runPostTransformPhase2(args) {
6470
5814
  try {
6471
5815
  const tImg = performance.now();
6472
5816
  const frozenImageIds = replaySnapshot.processedImageStrippedIds;
6473
- const imageResult = stripProcessedImages(args.messages, frozenImageIds, {
6474
- detect: isCacheBustingPass && args.watermark > 0,
5817
+ stripProcessedImages(args.messages, frozenImageIds, {
5818
+ detect: canEditWholePrefix && args.watermark > 0,
6475
5819
  watermark: args.watermark,
6476
5820
  messageTagNumbers: args.messageTagNumbers,
5821
+ persistNewIds: (ids) => addProcessedImageStrippedIds(args.db, args.sessionId, ids),
6477
5822
  onFirstApplication: recordFirstApplicationAt
6478
5823
  });
6479
- if (isCacheBustingPass && imageResult.newlyStrippedIds.length > 0) {
6480
- addProcessedImageStrippedIds(args.db, args.sessionId, imageResult.newlyStrippedIds);
6481
- }
6482
5824
  logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
6483
5825
  } catch (error) {
6484
5826
  failPass("image-strip-exception", error);
@@ -6715,7 +6057,7 @@ async function runPostTransformPhase2(args) {
6715
6057
  messages: args.messages,
6716
6058
  fullFeatureMode: args.fullFeatureMode,
6717
6059
  compactionOff,
6718
- isCacheBustingPass,
6060
+ isCacheBustingPass: canEditWholePrefix,
6719
6061
  sessionMeta: args.sessionMeta,
6720
6062
  todowriteAvailability: args.todowriteAvailability,
6721
6063
  client: args.client,
@@ -6782,7 +6124,7 @@ async function runPostTransformPhase2(args) {
6782
6124
  autoSearchHintAppendedThisPass = autoSearchCompletedThisPass && countAutoSearchHints(args.db, args.sessionId) !== autoSearchHintsBefore;
6783
6125
  logTransformTiming(args.sessionId, "pp.autoSearchHint", tAutoSearch);
6784
6126
  }
6785
- if (args.fullFeatureMode && isCacheBustingPass) {
6127
+ if (args.fullFeatureMode && canEditWholePrefix) {
6786
6128
  const visibleIds = new Set;
6787
6129
  for (const message of args.messages) {
6788
6130
  if (typeof message.info?.id === "string") {
@@ -6790,15 +6132,15 @@ async function runPostTransformPhase2(args) {
6790
6132
  }
6791
6133
  }
6792
6134
  const prunedAnchors = pruneNoteNudgeAnchors(args.db, args.sessionId, visibleIds);
6793
- const prunedDecisions = pruneAutoSearchHintDecisions(args.db, args.sessionId, visibleIds);
6794
- if (prunedAnchors > 0 || prunedDecisions > 0) {
6795
- sessionLog2(args.sessionId, `sticky-injection GC: pruned ${prunedAnchors} note-nudge anchor(s), ${prunedDecisions} auto-search decision(s)`);
6135
+ flushAutoSearchHintDecisionRetirement(args.db, args.sessionId, visibleIds);
6136
+ if (prunedAnchors > 0) {
6137
+ sessionLog2(args.sessionId, `sticky-injection GC: pruned ${prunedAnchors} note-nudge anchor(s)`);
6796
6138
  }
6797
6139
  }
6798
- const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? "explicit_flush" : null);
6140
+ const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? pendingOrigin : null);
6799
6141
  const materialized = m0RematerializedThisPass || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully;
6800
6142
  let bustedThisPass = firstApplicationEdits.any || firstRenderBust || pendingOpsDidMutate || heuristicOrReasoningDidMutate || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass;
6801
- const proactiveThinkingStripPermitted = isCacheBustingPass;
6143
+ const proactiveThinkingStripPermitted = isCacheBustingPass && !activeThinkingPrefixHold;
6802
6144
  const tFrozenDecisions = performance.now();
6803
6145
  if (reasoningMutationTargetUnknown) {
6804
6146
  const reasoningCandidates = args.reasoningByMessage.size > 0 ? args.reasoningByMessage.keys() : args.messages;
@@ -6849,7 +6191,7 @@ async function runPostTransformPhase2(args) {
6849
6191
  sessionLog2(args.sessionId, "thinking binding recovery: persistence failed; leaving the bound blocks intact");
6850
6192
  }
6851
6193
  }
6852
- if (canUseEmptySentinels && isCacheBustingPass) {
6194
+ if (canUseEmptySentinels && canEditWholePrefix) {
6853
6195
  const candidates = findMergedReasoningStripDecisions(args.messages, args.resolvedProviderID, mergedReasoningStrippedIds, {
6854
6196
  mutationExemptMessage: reasoningMutationExemptMessage,
6855
6197
  protectedMessages: protectedThinkingMessages
@@ -6895,7 +6237,7 @@ async function runPostTransformPhase2(args) {
6895
6237
  recordFirstApplicationAt(message, partIndex);
6896
6238
  }
6897
6239
  };
6898
- if (isCacheBustingPass && trailingBlankDecisions.size > 0) {
6240
+ if (canEditWholePrefix && trailingBlankDecisions.size > 0) {
6899
6241
  const visibleMessageIds = new Set(args.messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []));
6900
6242
  const poisonedKeepIds = [];
6901
6243
  for (const [id, decision] of trailingBlankDecisions) {
@@ -7000,7 +6342,7 @@ async function runPostTransformPhase2(args) {
7000
6342
  }
7001
6343
  }
7002
6344
  }
7003
- const prefixEditBesidesReasoningTrim = firstRenderBust || materializationRequested || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully || foldBustsServedPrefixThisPass || publishedM1RefreshedThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass || pendingOpsDidMutate || heuristicOrReasoningEditBesidesTrim || emergency || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || deferredClearedMarkerRetires || noteNudgeAppendedThisPass || todoAnchorMovedThisPass || autoSearchHintAppendedThisPass || dropModeSwitchesThisPass || firstApplicationEdits.beforeNewerThinking;
6345
+ const prefixEditBesidesReasoningTrim = firstRenderBust || heldIdleExpiryRebuild || materializationRequested || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully || foldBustsServedPrefixThisPass || publishedM1RefreshedThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass || pendingOpsDidMutate || heuristicOrReasoningEditBesidesTrim || emergency || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || deferredClearedMarkerRetires || noteNudgeAppendedThisPass || todoAnchorMovedThisPass || autoSearchHintAppendedThisPass || dropModeSwitchesThisPass || firstApplicationEdits.beforeNewerThinking;
7004
6346
  let proactiveThinkingStrip = null;
7005
6347
  if (!compactionOff && args.thinkingBindingRecoveryEnabledForModel === true && proactiveThinkingStripPermitted && prefixEditBesidesReasoningTrim) {
7006
6348
  const outcome = freezeReasoningOnBustingPass2({
@@ -7047,8 +6389,9 @@ async function runPostTransformPhase2(args) {
7047
6389
  const removedReasoningParts = reasoningRemovalEnabled ? removeReasoningParts(args.messages, removedReasoningIds, args.resolvedProviderID) : 0;
7048
6390
  const reasoningStatusRatio = sessionDecisionCalibration(args.db, args.sessionId).proseRatio;
7049
6391
  captureOpencodeReasoningBudgetStatus(args.sessionId, args.messages, args.keepReasoningTokens ?? DEFAULT_KEEP_REASONING_TOKENS, prefixBoundModel, reasoningStatusRatio);
7050
- args.restoreLatestTurnOriginals?.();
7051
- if (args.restoreLatestTurnOriginals) {
6392
+ if (!rewritingSignedPrefix)
6393
+ args.restoreLatestTurnOriginals?.();
6394
+ if (!rewritingSignedPrefix && args.restoreLatestTurnOriginals) {
7052
6395
  refreshReasoningRemovalUnion();
7053
6396
  if (replayCommittedVisibleDrops()) {
7054
6397
  finalizeMessageRepresentation2(args.messages, args.resolvedProviderID, finalizeOptions);
@@ -7172,14 +6515,15 @@ async function runPostTransformPhase2(args) {
7172
6515
  bustedThisPass,
7173
6516
  prefixTrimStatus: deliveredPrefix?.prefixTrimStatus ?? null,
7174
6517
  thinkingBindingRecovery,
7175
- proactiveThinkingStrip
6518
+ proactiveThinkingStrip,
6519
+ thinkingReleasedForFit
7176
6520
  };
7177
6521
  }
7178
6522
  function checkM0MutationDriftAndSignal2(args) {
7179
6523
  const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
7180
6524
  const cachedMaxMutationId = args.cachedM0MaxMutationId ?? 0;
7181
6525
  if (currentMaxMutationId !== cachedMaxMutationId) {
7182
- args.pendingMaterializationSessions.add(args.sessionId);
6526
+ requestPendingMaterialization(args.pendingMaterializationSessions, args.sessionId, "mutation_drift");
7183
6527
  args.historyRefreshSessions?.add(args.sessionId);
7184
6528
  sessionLog2(args.sessionId, `m[0] drift watcher: mutation id changed ${cachedMaxMutationId} → ${currentMaxMutationId}; scheduling next-pass materialization`);
7185
6529
  return true;
@@ -7187,4 +6531,4 @@ function checkM0MutationDriftAndSignal2(args) {
7187
6531
  return false;
7188
6532
  }
7189
6533
 
7190
- export { createTagger, cavemanWordRulesForLanguage, searchMessageHistoryOffThread, findSessionId, findLastUserMessageId, clearAutoSearchForSession, setCtxReduceRegisteredGlobally, resolveCtxReduceAvailabilityFromMessages, resolveCtxReduceAvailability, primeCtxReduceSpawnPermission, ctxReduceSpawnPermissionReadNeeded, spawnAgentFromMessages, spawnAgentFromOpenCodeDb, todowritePermissionDenied, cachedToolPermissionDenied, clearToolPermissionDenied, resolveTodowriteAvailabilityFromMessages, resolveTodowriteAvailability, canConsumeDeferredOnThisPass, hasReclaimRide, reclaimRideLabel, replayClearedReasoning, replayStrippedInlineThinking, stripClearedReasoning, snapshotTrailingBlankSourceDecisions, projectOpencodeReasoningBudgetCutoff, resolveKeepReasoningTokens, reasoningBudgetCutoff, captureOpencodeReasoningBudgetStatus, reasoningBudgetStatusLine, ENGINE_RECONNECTING_USER_MESSAGE, contextRefusalError, protectedToolRefusal, outgoingContextRefusal, EmergencyFailClosedError, latestAssistantTurnStart, latestAssistantTurnMessages, hasActiveAnthropicThinkingTurn, replayCavemanCompression, DegradedPassRefusalError, degradedPassError, applyFlushedStatuses, prewarmTagOwners, waitForTagOwners, stripStructuralNoise, logTransformTiming, hasRecentAssistantCommit, tagMessages, resetDegradedCacheCount2, isSyntheticHeadMessage2, applyTodoSynthesis2, freezeReasoningOnBustingPass2, firstServedDivergenceIndex2, rustModeServedKeyAfterPersistedStrips2, replayRustModeBindingMismatchStrips2, RUST_MARKER_LOCK_SKIP_LOG2, applyRustModeDeferredCompactionMarker2, clearRustModeBoundaryRecord2, runRustModePostprocess2, reconcileMarkerRepresentation2, clearPendingCompactionMarkerAfterSuccessfulDrain2, defaultCompactionMarkerStrategy2, abortSessionFailClosed2, evaluateEmergencyFailClosed2, finalizeMessageRepresentation2, runPostTransformPhase2, checkM0MutationDriftAndSignal2 };
6534
+ export { createTagger, cavemanWordRulesForLanguage, searchMessageHistoryOffThread, findSessionId, findLastUserMessageId, clearAutoSearchForSession, setCtxReduceRegisteredGlobally, resolveCtxReduceAvailabilityFromMessages, resolveCtxReduceAvailability, primeCtxReduceSpawnPermission, ctxReduceSpawnPermissionReadNeeded, spawnAgentFromMessages, spawnAgentFromOpenCodeDb, todowritePermissionDenied, cachedToolPermissionDenied, clearToolPermissionDenied, resolveTodowriteAvailabilityFromMessages, resolveTodowriteAvailability, canConsumeDeferredOnThisPass, hasReclaimRide, reclaimRideLabel, captureOpencodeReasoningBudgetStatus, reasoningBudgetStatusLine, ENGINE_RECONNECTING_USER_MESSAGE, ENGINE_BUSY_USER_MESSAGE, SIGNED_THINKING_RESET_FENCE_FAILED, contextRefusalError, protectedToolRefusal, outgoingContextRefusal, signedTurnContextRefusal, EmergencyFailClosedError, latestAssistantTurnStart, latestAssistantTurnMessages, hasActiveAnthropicThinkingTurn, replayCavemanCompression, DegradedPassRefusalError, degradedPassError, applyFlushedStatuses, prewarmTagOwners, waitForTagOwners, stripStructuralNoise, logTransformTiming, hasRecentAssistantCommit, tagMessages, resetDegradedCacheCount2, isSyntheticHeadMessage2, applyTodoSynthesis2, freezeReasoningOnBustingPass2, firstServedDivergenceIndex2, rustModeServedKeyAfterPersistedStrips2, replayRustModeBindingMismatchStrips2, RUST_MARKER_LOCK_SKIP_LOG2, applyRustModeDeferredCompactionMarker2, clearRustModeBoundaryRecord2, runRustModePostprocess2, reconcileMarkerRepresentation2, clearPendingCompactionMarkerAfterSuccessfulDrain2, defaultCompactionMarkerStrategy2, abortSessionFailClosed2, evaluateEmergencyFailClosed2, finalizeMessageRepresentation2, runPostTransformPhase2, checkM0MutationDriftAndSignal2 };