@cortexkit/opencode-magic-context 0.49.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 (195) 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-kzx4dmk1.js → conflict-warning-hook-asnt6hfc.js} +3 -3
  10. package/dist/{context-nj5f293n.js → context-tfyhtdcs.js} +111 -45
  11. package/dist/{derive-budgets-qz5rrr08.js → derive-budgets-j4ry8j8n.js} +1 -1
  12. package/dist/{embedding-backfill-aetxv1vt.js → embedding-backfill-wyc3ykyf.js} +7 -7
  13. package/dist/embedding-worker-process.js +30 -0
  14. package/dist/embedding-worker.js +5 -5
  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/memory/embedding-worker-client.d.ts +8 -1
  18. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -1
  19. package/dist/features/magic-context/memory/embedding-worker-process.d.ts +2 -0
  20. package/dist/features/magic-context/memory/embedding-worker-process.d.ts.map +1 -0
  21. package/dist/features/magic-context/memory/onnx-telemetry.d.ts +3 -0
  22. package/dist/features/magic-context/memory/onnx-telemetry.d.ts.map +1 -0
  23. package/dist/features/magic-context/overflow-detection.d.ts +1 -2
  24. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  25. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  26. package/dist/features/magic-context/transform-decision-log.d.ts +1 -1
  27. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  28. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +1 -0
  29. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +1 -0
  32. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/hook.d.ts +1 -0
  35. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
  38. package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/lkg-persist.d.ts +8 -14
  40. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
  42. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
  43. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
  44. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
  45. package/dist/hooks/magic-context/lkg-replay.d.ts +3 -1
  46. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
  49. package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
  50. package/dist/hooks/magic-context/pass-outcome.d.ts +2 -2
  51. package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
  52. package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
  53. package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
  54. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/rust-mode-transform.d.ts +1 -0
  57. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/strip-content.d.ts +5 -2
  59. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  60. package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
  61. package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
  62. package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
  63. package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
  64. package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
  65. package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
  66. package/dist/hooks/magic-context/system-prompt-hash.d.ts +4 -0
  67. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  69. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +2 -0
  71. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/transform.d.ts +6 -0
  73. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  74. package/dist/{index-9qjqq45k.js → index-0pjvpfkf.js} +21 -1
  75. package/dist/index-6m7rdv7y.js +733 -0
  76. package/dist/{index-1r0k9js3.js → index-6tfxmc4n.js} +10 -10
  77. package/dist/{index-gzcmtmar.js → index-7w18gg78.js} +25 -1
  78. package/dist/{index-nm6a8xpd.js → index-att4bfan.js} +1 -1
  79. package/dist/{index-ezmszwbd.js → index-eypn4ba6.js} +7 -4
  80. package/dist/{index-ha87j7a8.js → index-fdtkt5r1.js} +6 -6
  81. package/dist/{index-kp5qe690.js → index-fg00p1cg.js} +38 -36
  82. package/dist/{index-1bc61ans.js → index-fvnzcnww.js} +44 -1
  83. package/dist/index-gbmqa9x9.js +1170 -0
  84. package/dist/{index-pxwp2hjk.js → index-gzky5rva.js} +30 -53
  85. package/dist/{index-kq57tdf0.js → index-k6xvbj2e.js} +255 -1075
  86. package/dist/{index-0w56v4fm.js → index-mw7c950g.js} +1 -1
  87. package/dist/{index-1g30axtz.js → index-p0n5ryq8.js} +82 -900
  88. package/dist/{index-b7mv1jx3.js → index-p1hnwfd8.js} +1 -1
  89. package/dist/{index-peshmj6h.js → index-r2zcs71c.js} +6 -4
  90. package/dist/{index-kmpvemph.js → index-rafsaxac.js} +2 -2
  91. package/dist/{index-stbr4ce6.js → index-s7fc0fkn.js} +1 -1
  92. package/dist/{index-hj2q50k0.js → index-sfhndpcb.js} +463 -6
  93. package/dist/index-sv0bb7vg.js +6972 -0
  94. package/dist/{index-57mrqed8.js → index-w23dh319.js} +17 -258
  95. package/dist/{index-9rt53q79.js → index-xgrwmj82.js} +1 -1
  96. package/dist/{index-h2py7207.js → index-xnanvj3w.js} +765 -1255
  97. package/dist/{index-2jcbj7r1.js → index-zfzdpeq2.js} +2269 -3802
  98. package/dist/{index-s4j7t92z.js → index-zg8yq4ya.js} +29 -744
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +209 -61
  101. package/dist/{message-index-bounded-h0mrd4pr.js → message-index-bounded-hqktkhdy.js} +7 -6
  102. package/dist/migration-worker.js +6 -5
  103. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -1
  104. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  105. package/dist/plugin/messages-transform.d.ts.map +1 -1
  106. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  107. package/dist/{project-embedding-registry-rtt0djyb.js → project-embedding-registry-0gv3h6y8.js} +6 -6
  108. package/dist/raw-ordinal-warmup-worker.js +1 -1
  109. package/dist/{read-session-chunk-ty89v75e.js → read-session-chunk-5mh0bh8y.js} +5 -4
  110. package/dist/{recomp-orchestrator-4f1yyd1q.js → recomp-orchestrator-kpkhkjhq.js} +20 -19
  111. package/dist/{search-pz4f4wge.js → search-p9w39qv4.js} +15 -14
  112. package/dist/{send-session-notification-38cd5dqt.js → send-session-notification-xffh3bbe.js} +2 -2
  113. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  114. package/dist/shared/storage-file-mutex.d.ts +9 -0
  115. package/dist/shared/storage-file-mutex.d.ts.map +1 -0
  116. package/dist/shared/storage-permissions.d.ts +6 -0
  117. package/dist/shared/storage-permissions.d.ts.map +1 -1
  118. package/dist/shared/window-geometry.d.ts +9 -66
  119. package/dist/shared/window-geometry.d.ts.map +1 -1
  120. package/dist/standalone-plugin-marker.d.ts +8 -0
  121. package/dist/standalone-plugin-marker.d.ts.map +1 -0
  122. package/dist/tools/ctx-reduce/constants.d.ts +1 -2
  123. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  124. package/dist/tools/ctx-reduce/tools.d.ts +1 -1
  125. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  126. package/dist/{transform-postprocess-phase-tck4g20s.js → transform-postprocess-phase-481j5a7z.js} +20 -19
  127. package/dist/v2/auto-search-worker.js +3 -3
  128. package/dist/v2/{context-crbt6p1y.js → context-gsdtha5v.js} +873 -2122
  129. package/dist/v2/{derive-budgets-fgej9j46.js → derive-budgets-enckmg7y.js} +2 -2
  130. package/dist/v2/{embedding-backfill-ph1qfyn3.js → embedding-backfill-dbvjbcmm.js} +8 -9
  131. package/dist/v2/embedding-worker-process.js +29 -0
  132. package/dist/v2/embedding-worker.js +3 -4
  133. package/dist/v2/hooks/context.d.ts.map +1 -1
  134. package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
  135. package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
  136. package/dist/v2/hooks/payload.d.ts.map +1 -1
  137. package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
  138. package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
  139. package/dist/v2/{message-index-bounded-xwqdywxg.js → message-index-bounded-p6v0n8qh.js} +8 -7
  140. package/dist/v2/migration-worker.js +6 -5
  141. package/dist/v2/{project-embedding-registry-d6m7tyxr.js → project-embedding-registry-nyq7z8y6.js} +7 -8
  142. package/dist/v2/raw-ordinal-warmup-worker.js +2 -2
  143. package/dist/v2/{read-session-chunk-8p5mdryx.js → read-session-chunk-fhyfe4qa.js} +6 -5
  144. package/dist/v2/{recomp-orchestrator-ckfgt6wq.js → recomp-orchestrator-5xy7w136.js} +22 -22
  145. package/dist/v2/{search-ym8rehhz.js → search-j7bakcwa.js} +17 -17
  146. package/dist/v2/{send-session-notification-5m0yapqx.js → send-session-notification-f6v698r5.js} +2 -2
  147. package/dist/v2/{server-jvxzm1jy.js → server-1fszbabv.js} +28 -28
  148. package/dist/v2/{server-3j4d00kf.js → server-2htmbqbv.js} +25 -1
  149. package/dist/v2/{server-c5rrgrcd.js → server-4c7jt8gq.js} +25 -1
  150. package/dist/v2/{server-ycw9qqcy.js → server-4enr7s6x.js} +1 -1
  151. package/dist/v2/{server-v4mewb78.js → server-6tcrjfw8.js} +1 -1
  152. package/dist/v2/{server-x4hscabv.js → server-7spkq1y6.js} +2257 -3746
  153. package/dist/v2/{server-sa8jvrfc.js → server-7vkj6zhb.js} +29 -744
  154. package/dist/v2/{server-xwz4dqh9.js → server-8xmq9h3f.js} +30 -53
  155. package/dist/v2/{server-1tk82krw.js → server-bgzy0phk.js} +463 -6
  156. package/dist/v2/server-c7n2ftng.js +6860 -0
  157. package/dist/v2/server-cvgn49tr.js +733 -0
  158. package/dist/v2/{server-zm570tr2.js → server-cw6521wn.js} +232 -7
  159. package/dist/v2/{server-pj4pjv02.js → server-czb2rkpk.js} +21 -1
  160. package/dist/v2/{server-19zjmn02.js → server-d6g4whc2.js} +20 -14
  161. package/dist/v2/{server-1bc61ans.js → server-fvnzcnww.js} +44 -1
  162. package/dist/v2/{server-w32kmdez.js → server-kh958yj8.js} +3 -3
  163. package/dist/v2/{server-q4ph9bwn.js → server-mqvtz7wz.js} +7 -7
  164. package/dist/v2/{server-2s6ayq3t.js → server-ras2sxnc.js} +133 -13
  165. package/dist/v2/{server-ss95ky04.js → server-s2st631p.js} +1 -1
  166. package/dist/v2/{server-2s9qz6n7.js → server-t528t8qm.js} +1 -1
  167. package/dist/v2/{server-8k2agx29.js → server-vb7pbd9p.js} +17 -258
  168. package/dist/v2/{server-zp53y8js.js → server-zbxjj2mz.js} +2 -2
  169. package/dist/v2/server.d.ts.map +1 -1
  170. package/dist/v2/server.js +149 -5
  171. package/dist/v2/{storage-tags-8vw924zn.js → storage-tags-5yxrvkaf.js} +1 -1
  172. package/dist/v2/{wrapup-orchestrator-a7efxaax.js → wrapup-orchestrator-yem5422s.js} +28 -28
  173. package/dist/{wrapup-orchestrator-barbc6h9.js → wrapup-orchestrator-xvrr27ws.js} +21 -20
  174. package/package.json +4 -4
  175. package/src/config/{mural-model-deprecation.ts → deprecated-config.ts} +19 -0
  176. package/src/config/index.test.ts +15 -37
  177. package/src/config/index.ts +2 -3
  178. package/src/config/project-security.ts +3 -3
  179. package/src/config/schema/magic-context.ts +11 -7
  180. package/src/features/magic-context/dreamer/task-registry.ts +2 -3
  181. package/src/shared/models-dev-cache.ts +1 -7
  182. package/src/shared/sqlite-640-review.test.ts +5 -1
  183. package/src/shared/storage-file-mutex-review.test.ts +162 -0
  184. package/src/shared/storage-file-mutex.ts +130 -0
  185. package/src/shared/storage-permissions.ts +46 -0
  186. package/src/shared/window-geometry.test.ts +102 -236
  187. package/src/shared/window-geometry.ts +23 -413
  188. package/dist/config/mural-model-deprecation.d.ts.map +0 -1
  189. package/dist/index-2jgwttpt.js +0 -3269
  190. package/dist/index-mfkzp7qj.js +0 -229
  191. package/dist/v2/server-4ez8mntn.js +0 -3213
  192. package/dist/v2/server-mfkzp7qj.js +0 -229
  193. package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
  194. /package/dist/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
  195. /package/dist/v2/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
@@ -9,7 +9,6 @@ import {
9
9
  } from "./index-1bt88epp.js";
10
10
  import {
11
11
  protectedToolTagNumbers,
12
- stripWellFormedLeadingTagPrefix,
13
12
  byteSize,
14
13
  stripTagPrefix,
15
14
  prependTag,
@@ -38,9 +37,7 @@ import {
38
37
  AGE_RECLAIM_MIN_TOKENS2,
39
38
  getOldestActiveUnprotectedToolTags2,
40
39
  getActiveToolTagsForAgeReclaim2,
41
- getReasoningTokenEstimatesByMessage2,
42
40
  tryGetReasoningTokenEstimatesByMessage2,
43
- getMaxTagNumberByOwnerMessage2,
44
41
  cachedTagOwnerRatios2,
45
42
  tagOwnerWarmupState2,
46
43
  installTagOwnerDelta2,
@@ -59,6 +56,7 @@ import {
59
56
  getMaxTagNumberBySession2,
60
57
  getTagNumberByMessageId2,
61
58
  getAssignableTagNumberByMessageId2,
59
+ getTagsBySession2,
62
60
  getActiveTagsBySession2,
63
61
  getTailHygieneTags2,
64
62
  getTagsByNumbers2,
@@ -87,23 +85,25 @@ import {
87
85
  isTransientSqliteError2
88
86
  } from "./index-kb9nn0a0.js";
89
87
  import {
90
- isValidLanguageCode,
91
- resolveModelConfigValue
92
- } from "./index-kq57tdf0.js";
88
+ isValidLanguageCode
89
+ } from "./index-k6xvbj2e.js";
93
90
  import {
94
91
  getProjectEmbeddingSnapshot2,
95
92
  embedTextForProject2,
96
93
  embedBatchForProject2
97
- } from "./index-kp5qe690.js";
94
+ } from "./index-fg00p1cg.js";
98
95
  import {
99
96
  isEmbeddingHostBusy2
100
97
  } from "./index-qt1qqasc.js";
101
98
  import {
102
- BoundedSessionMap,
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,
@@ -146,6 +146,48 @@ 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,
149
191
  rememberUnpublishedAutoSearchNoHint,
150
192
  getUnpublishedAutoSearchNoHint,
151
193
  forgetUnpublishedAutoSearchNoHint,
@@ -153,6 +195,9 @@ import {
153
195
  cancelAutoSearchWork,
154
196
  updateSessionMeta,
155
197
  advanceToolReclaimWatermark,
198
+ requestPendingMaterialization,
199
+ pendingMaterializationOrigin,
200
+ clearPendingMaterialization,
156
201
  saveSourceContent,
157
202
  replaceSourceContent,
158
203
  getSourceContents,
@@ -173,7 +218,7 @@ import {
173
218
  peekNoteNudgeText,
174
219
  markNoteNudgeDelivered,
175
220
  getActiveCompartmentRun
176
- } from "./index-2jcbj7r1.js";
221
+ } from "./index-zfzdpeq2.js";
177
222
  import {
178
223
  runSessionWarmupWorker
179
224
  } from "./index-h5zfkjyk.js";
@@ -181,35 +226,13 @@ import {
181
226
  openCodeDbExists,
182
227
  withReadOnlySessionDb,
183
228
  getMessageTimesFromOpenCodeDb
184
- } from "./index-9qjqq45k.js";
229
+ } from "./index-0pjvpfkf.js";
185
230
  import {
186
- stripSystemInjection,
187
- isTextPart,
188
- isToolPartWithOutput,
189
- isFilePart,
190
- buildFileSourceContent,
191
- toolPartHasUserAnswer,
192
- isEditTool,
193
- modelAcceptsEmptyContent,
194
- isAnthropicFamilyRoute,
195
- neutralizeDroppedReasoningPart,
196
- restoreNeutralizedReasoningPart,
197
- isNeutralizedReasoningPart,
198
- neutralizedReasoningSource,
199
- makeSentinel,
200
- makeWholeMessageSentinel,
201
- neutralizeWholeMessage,
202
- isSentinel,
203
- replaySentinelByMessageIds,
204
- SKELETON_REAL_INPUT_MAX_BYTES,
205
- partHasCompletedResult,
206
- extractToolCallObservation,
207
- ToolMutationBatch,
208
- createToolDropTarget
209
- } from "./index-2jgwttpt.js";
231
+ BoundedSessionMap
232
+ } from "./index-sfhndpcb.js";
210
233
  import {
211
234
  renderUserFacingFailure
212
- } from "./index-kmpvemph.js";
235
+ } from "./index-rafsaxac.js";
213
236
  import {
214
237
  getErrorMessage
215
238
  } from "./index-y8v6yerm.js";
@@ -2136,851 +2159,6 @@ function reclaimRideLabel(signals) {
2136
2159
  return `ride=${active.length > 0 ? active.join("+") : "none"}`;
2137
2160
  }
2138
2161
 
2139
- // src/features/magic-context/storage-reasoning-removal.ts
2140
- var NAMESPACE = "reasoningRemoval";
2141
- var BACKUP_NAMESPACE = "reasoningRemovalBackup";
2142
- function invalidState(sessionId) {
2143
- return new Error(`invalid persisted reasoning removal state for session ${sessionId}`);
2144
- }
2145
- function parseState(doc, sessionId, namespace = NAMESPACE) {
2146
- const lane = doc[namespace];
2147
- if (lane === undefined)
2148
- return { messageIds: new Set, dropLeavesReasoning: false };
2149
- if (!isRecord(lane) || !Array.isArray(lane.messageIds))
2150
- throw invalidState(sessionId);
2151
- const ids = new Set;
2152
- for (const id of lane.messageIds) {
2153
- if (typeof id !== "string" || id.length === 0)
2154
- throw invalidState(sessionId);
2155
- ids.add(id);
2156
- }
2157
- if (lane.dropLeavesReasoning !== undefined && typeof lane.dropLeavesReasoning !== "boolean") {
2158
- throw invalidState(sessionId);
2159
- }
2160
- return { messageIds: ids, dropLeavesReasoning: lane.dropLeavesReasoning === true };
2161
- }
2162
- function writeState(doc, state) {
2163
- doc.version = 2;
2164
- const lane = {
2165
- messageIds: [...state.messageIds],
2166
- ...state.dropLeavesReasoning ? { dropLeavesReasoning: true } : {}
2167
- };
2168
- doc[NAMESPACE] = lane;
2169
- doc[BACKUP_NAMESPACE] = { ...lane, messageIds: [...lane.messageIds] };
2170
- }
2171
- function getReasoningRemovalState(db, sessionId) {
2172
- const doc = readReplayEnvelope(db, sessionId);
2173
- try {
2174
- return parseState(doc, sessionId);
2175
- } catch (error) {
2176
- if (doc[BACKUP_NAMESPACE] === undefined)
2177
- throw error;
2178
- return parseState(doc, sessionId, BACKUP_NAMESPACE);
2179
- }
2180
- }
2181
- function addRemovedReasoningIds(db, sessionId, ids) {
2182
- const requested = [...ids].filter((id) => typeof id === "string" && id.length > 0);
2183
- if (requested.length === 0)
2184
- return true;
2185
- return updateReplayDocument(db, sessionId, (doc) => {
2186
- const current = parseState(doc, sessionId);
2187
- let changed = false;
2188
- for (const id of requested) {
2189
- if (current.messageIds.has(id))
2190
- continue;
2191
- current.messageIds.add(id);
2192
- changed = true;
2193
- }
2194
- if (!changed)
2195
- return false;
2196
- writeState(doc, current);
2197
- return true;
2198
- });
2199
- }
2200
- function markDropLeavesReasoning(db, sessionId) {
2201
- return updateReplayDocument(db, sessionId, (doc) => {
2202
- const current = parseState(doc, sessionId);
2203
- if (current.dropLeavesReasoning)
2204
- return false;
2205
- current.dropLeavesReasoning = true;
2206
- writeState(doc, current);
2207
- return true;
2208
- });
2209
- }
2210
-
2211
- // src/hooks/magic-context/active-anthropic-turn.ts
2212
- function isInActiveAnthropicTurn(messages, index, anthropic) {
2213
- const start = activeAnthropicTurnStart(messages, anthropic);
2214
- return start !== undefined && index >= start;
2215
- }
2216
- function activeAnthropicTurnStart(messages, anthropic) {
2217
- if (!anthropic)
2218
- return;
2219
- for (let user = messages.length - 1;user >= 0; user--) {
2220
- const message = messages[user];
2221
- if (!isRecord(message))
2222
- continue;
2223
- const info = isRecord(message.info) ? message.info : message;
2224
- if (info.role !== "user" || info.synthetic === true || message.synthetic === true)
2225
- continue;
2226
- const id = typeof info.id === "string" ? info.id : "";
2227
- if (id.startsWith("synth-user-"))
2228
- continue;
2229
- const parts = Array.isArray(message.parts) ? message.parts : Array.isArray(message.content) ? message.content : [];
2230
- if (parts.length > 0 && parts.every((part) => isRecord(part) && (part.synthetic === true || part.ignored === true || ["tool_result", "toolResult", "tool-result"].includes(String(part.type)))))
2231
- continue;
2232
- return user + 1;
2233
- }
2234
- return;
2235
- }
2236
- function hasAnthropicReasoning(messages) {
2237
- return messages.some((message) => {
2238
- if (!isRecord(message))
2239
- return false;
2240
- const info = isRecord(message.info) ? message.info : message;
2241
- 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))
2242
- return true;
2243
- const parts = Array.isArray(message.parts) ? message.parts : [];
2244
- return parts.some((part) => isRecord(part) && isRecord(part.metadata) && isRecord(part.metadata.anthropic));
2245
- });
2246
- }
2247
-
2248
- // src/hooks/magic-context/strip-content.ts
2249
- var MARKER_ONLY_PATTERN = /^(?:(?:§\d+§|\[dropped(?: §\d+§)?\]|\[cleared\])\s*)+$/;
2250
- function isMarkerOnlyText(text) {
2251
- const trimmed = text.trim();
2252
- return trimmed.length > 0 && MARKER_ONLY_PATTERN.test(trimmed);
2253
- }
2254
- var TAG_PREFIX_PATTERN = /^§\d+§\s*/;
2255
- var SYSTEM_INJECTION_PATTERNS = [
2256
- /^<!-- OMO_INTERNAL_INITIATOR -->$/,
2257
- /^<system-reminder>[\s\S]*<\/system-reminder>$/,
2258
- /^\[SYSTEM DIRECTIVE:/,
2259
- /^\[Category\+Skill Reminder\]/,
2260
- /^\[EDIT ERROR - IMMEDIATE ACTION REQUIRED\]/,
2261
- /^\[task CALL FAILED/,
2262
- /^\[EMERGENCY CONTEXT WINDOW WARNING\]/
2263
- ];
2264
- function isSystemInjectedText(text) {
2265
- const stripped = text.trim().replace(TAG_PREFIX_PATTERN, "").trim();
2266
- if (stripped.length === 0)
2267
- return false;
2268
- return SYSTEM_INJECTION_PATTERNS.some((pattern) => pattern.test(stripped));
2269
- }
2270
- function stripSystemInjectedMessages(messages, protectedTailStart, providerID, onFirstApplication) {
2271
- let stripped = 0;
2272
- const sentineledIds = [];
2273
- for (let i = 0;i < messages.length; i++) {
2274
- if (i >= protectedTailStart)
2275
- continue;
2276
- const msg = messages[i];
2277
- if (msg.parts.length === 0)
2278
- continue;
2279
- if (msg.info.role === "user")
2280
- continue;
2281
- if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
2282
- continue;
2283
- let hasContentPart = false;
2284
- let allContentIsSystemInjection = true;
2285
- for (const part of msg.parts) {
2286
- if (!isRecord(part))
2287
- continue;
2288
- const partType = part.type;
2289
- if (METADATA_PART_TYPES.has(partType))
2290
- continue;
2291
- if (part.ignored === true)
2292
- continue;
2293
- if (partType === "tool") {
2294
- allContentIsSystemInjection = false;
2295
- break;
2296
- }
2297
- if (partType === "text" && typeof part.text === "string") {
2298
- hasContentPart = true;
2299
- if (!isSystemInjectedText(part.text)) {
2300
- allContentIsSystemInjection = false;
2301
- break;
2302
- }
2303
- continue;
2304
- }
2305
- allContentIsSystemInjection = false;
2306
- break;
2307
- }
2308
- if (hasContentPart && allContentIsSystemInjection) {
2309
- onFirstApplication?.(msg, 0);
2310
- neutralizeWholeMessage(msg, providerID);
2311
- stripped++;
2312
- if (typeof msg.info.id === "string")
2313
- sentineledIds.push(msg.info.id);
2314
- }
2315
- }
2316
- return { stripped, sentineledIds };
2317
- }
2318
- var METADATA_PART_TYPES = new Set([
2319
- "step-start",
2320
- "step-finish",
2321
- "snapshot",
2322
- "patch",
2323
- "agent",
2324
- "retry",
2325
- "subtask",
2326
- "compaction"
2327
- ]);
2328
- function stripDroppedPlaceholderMessages(messages, providerID, onFirstApplication) {
2329
- let stripped = 0;
2330
- const sentineledIds = [];
2331
- for (let i = 0;i < messages.length; i++) {
2332
- const msg = messages[i];
2333
- if (msg.parts.length === 0)
2334
- continue;
2335
- if (msg.info.role === "user")
2336
- continue;
2337
- if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
2338
- continue;
2339
- let hasContentPart = false;
2340
- let hasNonDroppedContent = false;
2341
- for (const part of msg.parts) {
2342
- if (!isRecord(part)) {
2343
- hasNonDroppedContent = true;
2344
- break;
2345
- }
2346
- const partType = part.type;
2347
- if (METADATA_PART_TYPES.has(partType))
2348
- continue;
2349
- if (partType === "tool") {
2350
- hasNonDroppedContent = true;
2351
- break;
2352
- }
2353
- if ((partType === "text" || partType === "reasoning") && typeof part.text === "string") {
2354
- hasContentPart = true;
2355
- if (part.text.trim().length === 0)
2356
- continue;
2357
- if (!isMarkerOnlyText(part.text)) {
2358
- hasNonDroppedContent = true;
2359
- break;
2360
- }
2361
- continue;
2362
- }
2363
- hasNonDroppedContent = true;
2364
- break;
2365
- }
2366
- if (hasContentPart && !hasNonDroppedContent) {
2367
- onFirstApplication?.(msg, 0);
2368
- neutralizeWholeMessage(msg, providerID);
2369
- stripped++;
2370
- if (typeof msg.info.id === "string")
2371
- sentineledIds.push(msg.info.id);
2372
- }
2373
- }
2374
- return { stripped, sentineledIds };
2375
- }
2376
- function replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers, persistedWatermark) {
2377
- if (persistedWatermark <= 0)
2378
- return 0;
2379
- let cleared = 0;
2380
- for (const message of messages) {
2381
- const msgTag = messageTagNumbers.get(message) ?? 0;
2382
- if (msgTag === 0 || msgTag > persistedWatermark)
2383
- continue;
2384
- const parts = reasoningByMessage.get(message);
2385
- if (!parts)
2386
- continue;
2387
- for (const tp of parts) {
2388
- if (tp.type === "text")
2389
- continue;
2390
- if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
2391
- tp.thinking = "[cleared]";
2392
- cleared++;
2393
- }
2394
- if (tp.text !== undefined && tp.text !== "[cleared]") {
2395
- tp.text = "[cleared]";
2396
- cleared++;
2397
- }
2398
- }
2399
- }
2400
- return cleared;
2401
- }
2402
- function replayStrippedInlineThinking(messages, messageTagNumbers, persistedWatermark) {
2403
- if (persistedWatermark <= 0)
2404
- return 0;
2405
- let stripped = 0;
2406
- for (const message of messages) {
2407
- if (message.info.role !== "assistant")
2408
- continue;
2409
- const msgTag = messageTagNumbers.get(message) ?? 0;
2410
- if (msgTag === 0 || msgTag > persistedWatermark)
2411
- continue;
2412
- for (const part of message.parts) {
2413
- if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string")
2414
- continue;
2415
- if (!part.text.includes("<think"))
2416
- continue;
2417
- const cleaned = part.text.replace(INLINE_THINKING_PATTERN, "");
2418
- if (cleaned !== part.text) {
2419
- part.text = cleaned;
2420
- stripped++;
2421
- }
2422
- }
2423
- }
2424
- return stripped;
2425
- }
2426
- function clearOldReasoning(messages, reasoningByMessage, messageTagNumbers, cutoff) {
2427
- const ageCutoff = cutoff;
2428
- let cleared = 0;
2429
- for (const message of messages) {
2430
- const msgTag = messageTagNumbers.get(message) ?? 0;
2431
- if (msgTag === 0 || msgTag > ageCutoff)
2432
- continue;
2433
- const parts = reasoningByMessage.get(message);
2434
- if (!parts)
2435
- continue;
2436
- for (const tp of parts) {
2437
- if (tp.type === "text")
2438
- continue;
2439
- if (tp.thinking !== undefined && tp.thinking !== "[cleared]") {
2440
- tp.thinking = "[cleared]";
2441
- cleared++;
2442
- }
2443
- if (tp.text !== undefined && tp.text !== "[cleared]") {
2444
- tp.text = "[cleared]";
2445
- cleared++;
2446
- }
2447
- }
2448
- }
2449
- return cleared;
2450
- }
2451
- var CLEARED_REASONING_TYPES = new Set(["thinking", "reasoning"]);
2452
- function stripClearedReasoning(messages) {
2453
- let stripped = 0;
2454
- for (const message of messages) {
2455
- if (message.info.role !== "assistant")
2456
- continue;
2457
- for (let i = 0;i < message.parts.length; i++) {
2458
- const part = message.parts[i];
2459
- if (!isRecord(part))
2460
- continue;
2461
- const partType = part.type;
2462
- if (!CLEARED_REASONING_TYPES.has(partType))
2463
- continue;
2464
- if (!("thinking" in part) && !("text" in part))
2465
- continue;
2466
- const thinking = "thinking" in part ? part.thinking : undefined;
2467
- const text = "text" in part ? part.text : undefined;
2468
- const isCleared = (thinking === undefined || thinking === "[cleared]") && (text === undefined || text === "[cleared]");
2469
- if (!isCleared)
2470
- continue;
2471
- message.parts[i] = makeSentinel(part);
2472
- stripped++;
2473
- }
2474
- }
2475
- return stripped;
2476
- }
2477
- var INLINE_THINKING_PATTERN = /<(?:thinking|think)>[\s\S]*?<\/(?:thinking|think)>\s*/g;
2478
- function stripInlineThinking(messages, messageTagNumbers, cutoff) {
2479
- const ageCutoff = cutoff;
2480
- let stripped = 0;
2481
- for (const message of messages) {
2482
- if (message.info.role !== "assistant")
2483
- continue;
2484
- const msgTag = messageTagNumbers.get(message) ?? 0;
2485
- if (msgTag === 0 || msgTag > ageCutoff)
2486
- continue;
2487
- for (const part of message.parts) {
2488
- if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string")
2489
- continue;
2490
- const cleaned = part.text.replace(INLINE_THINKING_PATTERN, "");
2491
- if (cleaned !== part.text) {
2492
- part.text = cleaned;
2493
- stripped++;
2494
- }
2495
- }
2496
- }
2497
- return stripped;
2498
- }
2499
- var REASONING_IGNORED_PART_TYPES = new Set([
2500
- "step-start",
2501
- "step-finish",
2502
- "snapshot",
2503
- "patch",
2504
- "agent",
2505
- "retry",
2506
- "subtask",
2507
- "compaction"
2508
- ]);
2509
- var REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
2510
- function hasReasoningReplayContent(message) {
2511
- return message.parts.some((part) => {
2512
- if (!isRecord(part) || part.ignored === true)
2513
- return false;
2514
- const type = typeof part.type === "string" ? part.type : "";
2515
- if (REASONING_IGNORED_PART_TYPES.has(type))
2516
- return false;
2517
- return type !== "text" || typeof part.text !== "string" || part.text.trim().length > 0;
2518
- });
2519
- }
2520
- function findReasoningBearingAssistantIds(messages) {
2521
- const ids = new Set;
2522
- for (const message of messages) {
2523
- if (message.info.role !== "assistant")
2524
- continue;
2525
- const id = message.info.id;
2526
- if (typeof id !== "string" || id.length === 0)
2527
- continue;
2528
- if (message.parts.some((part) => isRecord(part) && REASONING_PART_TYPES.has(String(part.type)))) {
2529
- ids.add(id);
2530
- }
2531
- }
2532
- return [...ids];
2533
- }
2534
- function findLatestAssistantReasoningMutationExemptMessage(messages) {
2535
- for (let index = messages.length - 1;index >= 0; index -= 1) {
2536
- const message = messages[index];
2537
- if (message.info.role === "assistant" && hasReasoningReplayContent(message))
2538
- return message;
2539
- }
2540
- return;
2541
- }
2542
- function planMergedAssistantReasoningStrip(messages, mutationExemptMessage, frozenMessageIds, protectedMessages) {
2543
- const plan = [];
2544
- let prevRole;
2545
- let keptReasoningInRun = false;
2546
- for (const message of messages) {
2547
- const role = message.info.role;
2548
- if (role !== "assistant") {
2549
- prevRole = role;
2550
- keptReasoningInRun = false;
2551
- continue;
2552
- }
2553
- const firstInRun = prevRole !== "assistant";
2554
- if (firstInRun)
2555
- keptReasoningInRun = false;
2556
- if (protectedMessages?.has(message) || message === mutationExemptMessage || frozenMessageIds?.has(message.info.id ?? "")) {
2557
- prevRole = role;
2558
- continue;
2559
- }
2560
- let keepIndex = -1;
2561
- if (firstInRun && !keptReasoningInRun) {
2562
- for (let i = 0;i < message.parts.length; i++) {
2563
- const part = message.parts[i];
2564
- if (!isRecord(part))
2565
- continue;
2566
- const partType = part.type;
2567
- if (REASONING_IGNORED_PART_TYPES.has(partType))
2568
- continue;
2569
- if (part.ignored === true)
2570
- continue;
2571
- if (isSentinel(part))
2572
- continue;
2573
- if (partType === "text" && typeof part.text === "string" && part.text.trim() === "") {
2574
- continue;
2575
- }
2576
- if (REASONING_PART_TYPES.has(partType)) {
2577
- keepIndex = i;
2578
- }
2579
- break;
2580
- }
2581
- }
2582
- const stripIndices = [];
2583
- for (let i = 0;i < message.parts.length; i++) {
2584
- const part = message.parts[i];
2585
- if (!isRecord(part))
2586
- continue;
2587
- if (!REASONING_PART_TYPES.has(part.type))
2588
- continue;
2589
- if (part.cache_control !== undefined)
2590
- continue;
2591
- if (i === keepIndex) {
2592
- keptReasoningInRun = true;
2593
- continue;
2594
- }
2595
- stripIndices.push(i);
2596
- }
2597
- if (stripIndices.length > 0)
2598
- plan.push({ message, stripIndices });
2599
- prevRole = role;
2600
- }
2601
- return plan;
2602
- }
2603
- var MAX_FROZEN_TRAILING_BLANKS = 1e4;
2604
- var CANONICAL_BLANK_PART = { type: "text", text: "" };
2605
- function isSentinelInvisibleTextPart(part) {
2606
- return isRecord(part) && part.type === "text" && typeof part.text === "string" && stripWellFormedLeadingTagPrefix(part.text).trim() === "";
2607
- }
2608
- function isCanonicalBlankPart(part) {
2609
- return isRecord(part) && Object.keys(part).length === 2 && part.type === "text" && part.text === "";
2610
- }
2611
- function trailingBlankKeepCount(decision) {
2612
- if (decision === "keep")
2613
- return 1;
2614
- if (!decision.startsWith("keep:"))
2615
- return;
2616
- const countText = decision.slice("keep:".length);
2617
- if (!/^[1-9]\d*$/.test(countText))
2618
- return;
2619
- const count = Number(countText);
2620
- return Number.isSafeInteger(count) && count > 0 && count <= MAX_FROZEN_TRAILING_BLANKS ? count : undefined;
2621
- }
2622
- function trailingBlankDecisionForMessage(message) {
2623
- const id = message.info.id;
2624
- if (message.info.role !== "assistant" || typeof id !== "string" || id.length === 0) {
2625
- return;
2626
- }
2627
- let trailingCount = 0;
2628
- while (trailingCount < message.parts.length && isSentinelInvisibleTextPart(message.parts[message.parts.length - trailingCount - 1])) {
2629
- trailingCount += 1;
2630
- }
2631
- if (trailingCount > MAX_FROZEN_TRAILING_BLANKS && trailingCount < message.parts.length) {
2632
- return;
2633
- }
2634
- const decision = message.parts.length === 0 || trailingCount === message.parts.length ? "keep" : trailingCount === 0 ? "strip" : trailingCount === 1 ? "keep" : `keep:${trailingCount}`;
2635
- return [id, decision];
2636
- }
2637
- function snapshotTrailingBlankSourceDecisions(messages) {
2638
- const decisions = new Map;
2639
- for (const message of messages) {
2640
- const observed = trailingBlankDecisionForMessage(message);
2641
- if (observed)
2642
- decisions.set(...observed);
2643
- }
2644
- return decisions;
2645
- }
2646
- function findTrailingBlankDecisionCandidates(messages, frozenDecisions, options) {
2647
- const observedDecisions = options?.sourceDecisions ?? snapshotTrailingBlankSourceDecisions(messages);
2648
- const visibleIds = new Set(messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []));
2649
- const decisions = [];
2650
- for (const [id, decision] of observedDecisions) {
2651
- if (!visibleIds.has(id))
2652
- continue;
2653
- const frozen = frozenDecisions.get(id);
2654
- if (frozen !== undefined && (id !== options?.refreshMessageId || frozen === decision || frozen === "strip")) {
2655
- continue;
2656
- }
2657
- decisions.push([id, decision]);
2658
- }
2659
- return decisions;
2660
- }
2661
- function applyFrozenTrailingBlankDecisions(messages, frozenDecisions) {
2662
- let mutations = 0;
2663
- for (let messageIndex = 0;messageIndex < messages.length; messageIndex += 1) {
2664
- let message = messages[messageIndex];
2665
- const id = message.info.id;
2666
- if (message.info.role !== "assistant" || typeof id !== "string")
2667
- continue;
2668
- const decision = frozenDecisions.get(id);
2669
- if (!decision)
2670
- continue;
2671
- let lastMeaningfulIndex = message.parts.length - 1;
2672
- while (lastMeaningfulIndex >= 0 && isSentinelInvisibleTextPart(message.parts[lastMeaningfulIndex])) {
2673
- lastMeaningfulIndex -= 1;
2674
- }
2675
- const replaceParts = (start, deleteCount, insertBlankCount) => {
2676
- message = { ...message, parts: [...message.parts] };
2677
- messages[messageIndex] = message;
2678
- message.parts.splice(start, deleteCount, ...Array.from({ length: insertBlankCount }, () => ({ ...CANONICAL_BLANK_PART })));
2679
- };
2680
- if (lastMeaningfulIndex < 0) {
2681
- if (message.parts.length === 0)
2682
- continue;
2683
- if (message.parts.length !== 1 || !isCanonicalBlankPart(message.parts[0])) {
2684
- mutations += Math.max(1, message.parts.length);
2685
- replaceParts(0, message.parts.length, 1);
2686
- }
2687
- continue;
2688
- }
2689
- const trailingCount = message.parts.length - lastMeaningfulIndex - 1;
2690
- const keepCount = trailingBlankKeepCount(decision);
2691
- if (keepCount !== undefined) {
2692
- if (trailingCount === 0)
2693
- continue;
2694
- const blankIndex = lastMeaningfulIndex + 1;
2695
- const suffixIsCanonical = trailingCount === keepCount && message.parts.slice(blankIndex).every(isCanonicalBlankPart);
2696
- if (!suffixIsCanonical) {
2697
- mutations += Math.max(1, trailingCount, keepCount);
2698
- replaceParts(blankIndex, trailingCount, keepCount);
2699
- }
2700
- continue;
2701
- }
2702
- if (trailingCount === 0)
2703
- continue;
2704
- const lastMeaningfulPart = message.parts[lastMeaningfulIndex];
2705
- if (isRecord(lastMeaningfulPart) && REASONING_PART_TYPES.has(lastMeaningfulPart.type)) {
2706
- const blankIndex = lastMeaningfulIndex + 1;
2707
- if (trailingCount !== 1 || !isCanonicalBlankPart(message.parts[blankIndex])) {
2708
- mutations += Math.max(1, trailingCount);
2709
- replaceParts(blankIndex, trailingCount, 1);
2710
- }
2711
- continue;
2712
- }
2713
- mutations += trailingCount;
2714
- replaceParts(lastMeaningfulIndex + 1, trailingCount, 0);
2715
- }
2716
- return mutations;
2717
- }
2718
- function stripReasoningFromAssistantIds(messages, providerID, messageIds, protectedMessages) {
2719
- if (messageIds.size === 0)
2720
- return 0;
2721
- const emptySentinels = modelAcceptsEmptyContent(providerID);
2722
- let stripped = 0;
2723
- for (const message of messages) {
2724
- if (protectedMessages?.has(message))
2725
- continue;
2726
- const id = message.info.id;
2727
- if (typeof id !== "string" || !messageIds.has(id))
2728
- continue;
2729
- for (let index = 0;index < message.parts.length; index += 1) {
2730
- const part = message.parts[index];
2731
- if (!isRecord(part) || !REASONING_PART_TYPES.has(String(part.type)))
2732
- continue;
2733
- if (emptySentinels) {
2734
- message.parts[index] = makeSentinel(part);
2735
- } else {
2736
- message.parts.splice(index, 1);
2737
- index -= 1;
2738
- }
2739
- stripped += 1;
2740
- }
2741
- if (message.parts.length === 0)
2742
- message.parts.push(makeWholeMessageSentinel(providerID));
2743
- }
2744
- return stripped;
2745
- }
2746
- function findMergedReasoningStripDecisions(messages, providerID, frozenIds, options) {
2747
- if (providerID !== "anthropic")
2748
- return [];
2749
- const frozenParts = readFrozenMergedReasoningParts(frozenIds);
2750
- const decisions = [];
2751
- for (const entry of planMergedAssistantReasoningStrip(messages, options?.mutationExemptMessage, new Set(frozenParts.keys()), options?.protectedMessages)) {
2752
- const id = entry.message.info.id;
2753
- if (typeof id !== "string" || id.length === 0 || frozenParts.has(id))
2754
- continue;
2755
- const parts = entry.stripIndices.map((index) => {
2756
- const part = entry.message.parts[index];
2757
- return isRecord(part) && typeof part.id === "string" ? part.id : index;
2758
- });
2759
- decisions.push(id, MERGED_REASONING_PARTS_PREFIX + JSON.stringify([id, parts]));
2760
- }
2761
- return decisions;
2762
- }
2763
- function stripReasoningFromMergedAssistants(messages, providerID, options) {
2764
- if (providerID !== "anthropic")
2765
- return 0;
2766
- let stripped = 0;
2767
- const frozenParts = options?.frozenParts ?? readFrozenMergedReasoningParts(options?.frozenMessageIds ?? new Set);
2768
- for (const message of messages) {
2769
- if (message.info.role !== "assistant" || options?.restoreMessages?.has(message))
2770
- continue;
2771
- const parts = frozenParts.get(message.info.id ?? "");
2772
- if (!parts)
2773
- continue;
2774
- for (let index = 0;index < message.parts.length; index += 1) {
2775
- const part = message.parts[index];
2776
- if (!isRecord(part) || !REASONING_PART_TYPES.has(String(part.type)))
2777
- continue;
2778
- if (!parts.includes(index) && !(typeof part.id === "string" && parts.includes(part.id)))
2779
- continue;
2780
- message.parts[index] = makeSentinel(part);
2781
- stripped++;
2782
- }
2783
- }
2784
- for (const entry of planMergedAssistantReasoningStrip(messages, options?.mutationExemptMessage, options?.frozenPartMessageIds ?? new Set(frozenParts.keys()), options?.frozenMessageIds ? options.restoreMessages : options?.protectedMessages)) {
2785
- if (options?.frozenMessageIds) {
2786
- const id = entry.message.info.id;
2787
- if (typeof id !== "string" || !options.frozenMessageIds.has(id))
2788
- continue;
2789
- }
2790
- for (const index of entry.stripIndices) {
2791
- entry.message.parts[index] = makeSentinel(entry.message.parts[index]);
2792
- stripped++;
2793
- }
2794
- }
2795
- return stripped;
2796
- }
2797
- function stripProcessedImages(messages, frozenIds, options) {
2798
- const { detect, watermark, messageTagNumbers } = options;
2799
- let stripped = 0;
2800
- const newlyStrippedIds = [];
2801
- let hasAssistantResponse = false;
2802
- for (let i = messages.length - 1;i >= 0; i--) {
2803
- const msg = messages[i];
2804
- if (msg.info.role === "assistant") {
2805
- hasAssistantResponse = true;
2806
- continue;
2807
- }
2808
- if (msg.info.role !== "user") {
2809
- continue;
2810
- }
2811
- const id = typeof msg.info.id === "string" ? msg.info.id : undefined;
2812
- const inFrozen = id !== undefined && frozenIds.has(id);
2813
- const maxTag = messageTagNumbers.get(msg) ?? 0;
2814
- const isNewDetection = !inFrozen && detect && hasAssistantResponse && id !== undefined && maxTag <= watermark;
2815
- if (!inFrozen && !isNewDetection) {
2816
- continue;
2817
- }
2818
- let touchedThisMsg = false;
2819
- for (let j = 0;j < msg.parts.length; j++) {
2820
- const part = msg.parts[j];
2821
- if (!isRecord(part) || part.type !== "file") {
2822
- continue;
2823
- }
2824
- if (typeof part.mime !== "string" || !part.mime.startsWith("image/")) {
2825
- continue;
2826
- }
2827
- if (typeof part.url === "string" && part.url.startsWith("data:") && part.url.length > 200) {
2828
- if (isNewDetection)
2829
- options.onFirstApplication?.(msg, j);
2830
- msg.parts[j] = makeSentinel(part);
2831
- stripped++;
2832
- touchedThisMsg = true;
2833
- }
2834
- }
2835
- if (touchedThisMsg && isNewDetection && id !== undefined) {
2836
- newlyStrippedIds.push(id);
2837
- }
2838
- }
2839
- return { stripped, newlyStrippedIds };
2840
- }
2841
-
2842
- // src/hooks/magic-context/reasoning-budget.ts
2843
- function projectOpencodeReasoningBudgetCutoff(db, sessionId, messages, budget, watermark, proseRatio) {
2844
- const textEstimateByMessageId = getReasoningTokenEstimatesByMessage2(db, sessionId, proseRatio);
2845
- const maxTags = getMaxTagNumberByOwnerMessage2(db, sessionId);
2846
- const messageTags = new Map;
2847
- const gone = new Set(getReasoningRemovalState(db, sessionId).messageIds);
2848
- for (const message of messages) {
2849
- if (typeof message.info.id !== "string")
2850
- continue;
2851
- const tag = maxTags.get(message.info.id) ?? 0;
2852
- messageTags.set(message, tag);
2853
- if (tag > 0 && tag <= watermark)
2854
- gone.add(message.info.id);
2855
- }
2856
- const frozenMergedIds = getMergedReasoningStrippedIds(db, sessionId);
2857
- return opencodeReasoningBudgetCutoff({
2858
- messages,
2859
- messageTagNumbers: messageTags,
2860
- budget,
2861
- alreadyRemoved: gone,
2862
- textEstimateByMessageId,
2863
- proseRatio,
2864
- frozenMergedIds,
2865
- alsoGone: new Set([...frozenMergedIds].filter((id) => id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)).map((id) => id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length)))
2866
- });
2867
- }
2868
- var DEFAULT_KEEP_REASONING_TOKENS = 1e4;
2869
- var UNKNOWN_REASONING_STEP_TOKENS = 1000;
2870
- function resolveKeepReasoningTokens(config, modelKey) {
2871
- const values = config && typeof config === "object" ? Object.assign(Object.create(null), config) : undefined;
2872
- return typeof config === "number" ? config : resolveModelConfigValue(values, modelKey)?.value ?? values?.default ?? DEFAULT_KEEP_REASONING_TOKENS;
2873
- }
2874
- function reasoningStepCost(reported, textEstimate, opaque) {
2875
- if (reported !== undefined && Number.isFinite(reported) && reported > 0)
2876
- return reported;
2877
- if (textEstimate > 0)
2878
- return Math.ceil(textEstimate);
2879
- return opaque ? UNKNOWN_REASONING_STEP_TOKENS : 0;
2880
- }
2881
- function reasoningBudgetCutoff(steps, budget) {
2882
- const cost = (step) => step.alreadyRemoved ? 0 : typeof step.cost === "function" ? step.cost() : step.cost;
2883
- let kept = 0;
2884
- let upperBound = Number.POSITIVE_INFINITY;
2885
- for (const step of steps) {
2886
- if (!step.exempt)
2887
- continue;
2888
- kept += cost(step);
2889
- if (step.tag > 0)
2890
- upperBound = Math.min(upperBound, step.tag - 1);
2891
- }
2892
- for (let index = steps.length - 1;index >= 0; index--) {
2893
- const step = steps[index];
2894
- if (step.exempt || step.alreadyRemoved)
2895
- continue;
2896
- const tokens = cost(step);
2897
- if (kept + tokens <= budget) {
2898
- kept += tokens;
2899
- if (step.tag > 0)
2900
- upperBound = Math.min(upperBound, step.tag - 1);
2901
- continue;
2902
- }
2903
- let tag = step.tag;
2904
- for (let older = index - 1;tag <= 0 && older >= 0; older--)
2905
- tag = steps[older].tag;
2906
- return Math.max(0, Math.min(tag, upperBound));
2907
- }
2908
- return 0;
2909
- }
2910
- function reasoningTextAndOpaque(parts) {
2911
- let text = "";
2912
- let inlineText = "";
2913
- let opaque = false;
2914
- let hasReasoning = false;
2915
- const detailText = new Set;
2916
- for (const part of parts) {
2917
- if (!isRecord(part))
2918
- continue;
2919
- if (part.ignored === true)
2920
- continue;
2921
- if (isRecord(part.metadata)) {
2922
- const router = part.metadata.openrouter;
2923
- if (isRecord(router) && Array.isArray(router.reasoning_details) && router.reasoning_details.length > 0) {
2924
- hasReasoning = true;
2925
- opaque = true;
2926
- for (const detail of router.reasoning_details) {
2927
- if (!isRecord(detail))
2928
- continue;
2929
- if (detail.type === "reasoning.text" && typeof detail.text === "string")
2930
- detailText.add(detail.text);
2931
- if (detail.type === "reasoning.summary" && typeof detail.summary === "string")
2932
- detailText.add(detail.summary);
2933
- }
2934
- }
2935
- }
2936
- if (["reasoning", "thinking", "redacted_thinking"].includes(String(part.type))) {
2937
- hasReasoning = true;
2938
- const visible = part.type === "redacted_thinking" || part.redacted === true ? "" : typeof part.thinking === "string" ? part.thinking : typeof part.text === "string" ? part.text : "";
2939
- if (visible !== "[cleared]")
2940
- text += visible;
2941
- opaque ||= part.type === "redacted_thinking" || part.redacted === true || visible === "" && (part.metadata !== undefined || part.signature !== undefined || part.thinkingSignature !== undefined);
2942
- } else if (part.type === "text" && typeof part.text === "string") {
2943
- for (const match of part.text.matchAll(/<(?:thinking|think)>([\s\S]*?)<\/(?:thinking|think)>/gi))
2944
- inlineText += match[1];
2945
- }
2946
- }
2947
- return { text: text || [...detailText].join(""), inlineText, opaque, hasReasoning };
2948
- }
2949
- function opencodeReasoningBudgetCutoff(args) {
2950
- const assistants = args.messages.filter((message) => message.info.role === "assistant");
2951
- const newest = assistants.at(-1);
2952
- const exempt = findLatestAssistantReasoningMutationExemptMessage(args.messages);
2953
- const anthropic = args.anthropic ?? hasAnthropicReasoning(args.messages);
2954
- const indexOfMessage = new Map;
2955
- args.messages.forEach((message, index) => {
2956
- if (!indexOfMessage.has(message))
2957
- indexOfMessage.set(message, index);
2958
- });
2959
- const frozenParts = args.frozenMergedIds ? readFrozenMergedReasoningParts(args.frozenMergedIds) : undefined;
2960
- const frozenPartMessageIds = frozenParts ? new Set(frozenParts.keys()) : undefined;
2961
- return reasoningBudgetCutoff(assistants.map((message) => ({
2962
- tag: args.messageTagNumbers.get(message) ?? 0,
2963
- exempt: message === newest || message === exempt || isInActiveAnthropicTurn(args.messages, indexOfMessage.get(message) ?? -1, anthropic),
2964
- cost: () => {
2965
- const costMessage = { ...message, parts: [...message.parts] };
2966
- const id = message.info.id ?? "";
2967
- if (args.frozenMergedIds && (frozenParts?.has(id) || args.frozenMergedIds.has(id)))
2968
- stripReasoningFromMergedAssistants([costMessage], "anthropic", {
2969
- frozenMessageIds: args.frozenMergedIds,
2970
- frozenParts,
2971
- frozenPartMessageIds
2972
- });
2973
- const visible = reasoningTextAndOpaque(args.countNeutralized ? costMessage.parts.map(neutralizedReasoningSource) : costMessage.parts);
2974
- if (!visible.hasReasoning && !visible.inlineText)
2975
- return 0;
2976
- const info = message.info;
2977
- const tokens = isRecord(info.tokens) ? info.tokens.reasoning : undefined;
2978
- const typedGone = typeof message.info.id === "string" && (args.alreadyRemoved?.has(message.info.id) === true || args.alsoGone?.has(message.info.id) === true);
2979
- 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));
2980
- }
2981
- })), args.budget);
2982
- }
2983
-
2984
2162
  // src/hooks/magic-context/reasoning-budget-status.ts
2985
2163
  var sources = new Map;
2986
2164
  function captureOpencodeReasoningBudgetStatus(sessionId, messages, budget, prefixBound, proseRatio = 1) {
@@ -3347,14 +2525,14 @@ function retainedActiveThinkingParts(args) {
3347
2525
  }
3348
2526
 
3349
2527
  // src/features/magic-context/storage-caveman-rules.ts
3350
- var NAMESPACE2 = "caveman";
2528
+ var NAMESPACE = "caveman";
3351
2529
  var CURRENT_RULES_VERSION = 2;
3352
2530
  var ORIGINAL_RULES = {
3353
2531
  currentRules: false,
3354
2532
  englishWordRules: true,
3355
2533
  legacyReasoningTags: new Set
3356
2534
  };
3357
- function parseState2(lane) {
2535
+ function parseState(lane) {
3358
2536
  if (!isRecord(lane) || lane.rules !== CURRENT_RULES_VERSION)
3359
2537
  return ORIGINAL_RULES;
3360
2538
  const tags = Array.isArray(lane.legacyReasoningTags) ? lane.legacyReasoningTags : [];
@@ -3366,7 +2544,7 @@ function parseState2(lane) {
3366
2544
  }
3367
2545
  function getCavemanReplayState(db, sessionId) {
3368
2546
  try {
3369
- return parseState2(readReplayEnvelope(db, sessionId)[NAMESPACE2]);
2547
+ return parseState(readReplayEnvelope(db, sessionId)[NAMESPACE]);
3370
2548
  } catch (error) {
3371
2549
  if (error instanceof ReplayDocumentError)
3372
2550
  return ORIGINAL_RULES;
@@ -3376,11 +2554,11 @@ function getCavemanReplayState(db, sessionId) {
3376
2554
  function recordCavemanCurrentRules(db, sessionId, englishWordRules, legacyReasoningTags) {
3377
2555
  const tags = [...new Set(legacyReasoningTags)].sort((a, b) => a - b);
3378
2556
  const persisted = updateReplayDocument(db, sessionId, (doc) => {
3379
- const current = parseState2(doc[NAMESPACE2]);
2557
+ const current = parseState(doc[NAMESPACE]);
3380
2558
  if (current.currentRules && current.englishWordRules === englishWordRules)
3381
2559
  return false;
3382
2560
  doc.version = 2;
3383
- doc[NAMESPACE2] = {
2561
+ doc[NAMESPACE] = {
3384
2562
  rules: CURRENT_RULES_VERSION,
3385
2563
  legacyReasoningTags: current.currentRules ? [...current.legacyReasoningTags].sort((a, b) => a - b) : tags,
3386
2564
  ...englishWordRules ? {} : { englishWordRules: false }
@@ -5123,7 +4301,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
5123
4301
  accAssignTag += performance.now() - _tAssignText;
5124
4302
  const persistedSource = sourceContents.get(tagId);
5125
4303
  if (persistedSource !== undefined) {
5126
- textPart.text = persistedSource;
4304
+ textPart.text = options.normalizeRestoredAssistantText && message.info.role === "assistant" ? options.normalizeRestoredAssistantText(persistedSource) : persistedSource;
5127
4305
  } else {
5128
4306
  const sourceContent = stripTagPrefix(textPart.text);
5129
4307
  if (sourceContent.trim().length > 0) {
@@ -5978,6 +5156,7 @@ async function runPostTransformPhase2(args) {
5978
5156
  }
5979
5157
  const reasoningMutationExemptMessage = findLatestAssistantReasoningMutationExemptMessage(args.messages);
5980
5158
  const pendingMaterializationAtPassStart = args.pendingMaterializationSessions.has(args.sessionId);
5159
+ const pendingOrigin = pendingMaterializationOrigin(args.pendingMaterializationSessions, args.sessionId);
5981
5160
  const deferredMaterializationAtPassStart = args.deferredMaterializationSessions.has(args.sessionId);
5982
5161
  let isExplicitFlush = pendingMaterializationAtPassStart;
5983
5162
  const deferredMaterializationWasPending = deferredMaterializationAtPassStart;
@@ -6163,6 +5342,11 @@ async function runPostTransformPhase2(args) {
6163
5342
  }
6164
5343
  sessionLog2(args.sessionId, `m[0] HARD fold decision: reason=${m0MaterializeReason ?? foldDueDecision.reason ?? (foldExecutedThisPass ? "drift" : "soft_refresh")} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
6165
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
+ }
6166
5350
  logTransformTiming(args.sessionId, "pp.prefixPreflight", tPostprocessSetup, `foldExecuted=${foldExecutedThisPass} m1Refreshed=${publishedM1RefreshedThisPass}`);
6167
5351
  const tPassDecisions = performance.now();
6168
5352
  const frontToolCandidates = args.tags.filter((tag) => tag.type === "tool" && tag.status === "active" && args.targets.get(tag.tagNumber)?.canDrop?.());
@@ -6178,7 +5362,7 @@ async function runPostTransformPhase2(args) {
6178
5362
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
6179
5363
  const hasPendingUserOps = pendingOps.length > 0;
6180
5364
  if (args.schedulerDecision === "execute" && pendingOps.some((op) => newTargets.get(op.tagId)?.thinkingDropProtected))
6181
- args.pendingMaterializationSessions.add(args.sessionId);
5365
+ requestPendingMaterialization(args.pendingMaterializationSessions, args.sessionId, "thinking_hold");
6182
5366
  const formatPendingOpsDepth = () => {
6183
5367
  const depth = getPendingOpsCount(args.db, args.sessionId);
6184
5368
  return depth === null ? "not loaded (deferred pass)" : String(depth);
@@ -6269,7 +5453,7 @@ async function runPostTransformPhase2(args) {
6269
5453
  }
6270
5454
  if (shouldRunHeuristics) {
6271
5455
  const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
6272
- 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})`;
6273
5457
  sessionLog2(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
6274
5458
  } else if (args.schedulerDeferReason !== undefined && args.schedulerDeferReason !== null) {
6275
5459
  sessionLog2(args.sessionId, `heuristics WILL NOT RUN — reason=${args.schedulerDeferReason}`);
@@ -6332,7 +5516,7 @@ async function runPostTransformPhase2(args) {
6332
5516
  logTransformTiming(args.sessionId, "pp.passDecisions", tPassDecisions, `pendingOps=${pendingOps.length}`);
6333
5517
  try {
6334
5518
  if (shouldApplyPendingOps) {
6335
- 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})`;
6336
5520
  sessionLog2(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${formatPendingOpsDepth()}, context=${args.contextUsage.percentage.toFixed(1)}%`);
6337
5521
  const tApply = performance.now();
6338
5522
  pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, new Set([
@@ -6497,7 +5681,7 @@ async function runPostTransformPhase2(args) {
6497
5681
  heuristicOrReasoningEditBesidesTrim = heuristicMutationCount + clearedReasoning + strippedInline > 0;
6498
5682
  droppedCount += clearedReasoning + strippedInline + removedReasoningMessages;
6499
5683
  if (pendingMaterializationAtPassStart && !freezeM0M1 && !pendingOps.some((op) => newTargets.get(op.tagId)?.thinkingDropProtected)) {
6500
- args.pendingMaterializationSessions.delete(args.sessionId);
5684
+ clearPendingMaterialization(args.pendingMaterializationSessions, args.sessionId);
6501
5685
  }
6502
5686
  if (args.currentTurnId) {
6503
5687
  args.lastHeuristicsTurnId.set(args.sessionId, args.currentTurnId);
@@ -6630,15 +5814,13 @@ async function runPostTransformPhase2(args) {
6630
5814
  try {
6631
5815
  const tImg = performance.now();
6632
5816
  const frozenImageIds = replaySnapshot.processedImageStrippedIds;
6633
- const imageResult = stripProcessedImages(args.messages, frozenImageIds, {
5817
+ stripProcessedImages(args.messages, frozenImageIds, {
6634
5818
  detect: canEditWholePrefix && args.watermark > 0,
6635
5819
  watermark: args.watermark,
6636
5820
  messageTagNumbers: args.messageTagNumbers,
5821
+ persistNewIds: (ids) => addProcessedImageStrippedIds(args.db, args.sessionId, ids),
6637
5822
  onFirstApplication: recordFirstApplicationAt
6638
5823
  });
6639
- if (isCacheBustingPass && imageResult.newlyStrippedIds.length > 0) {
6640
- addProcessedImageStrippedIds(args.db, args.sessionId, imageResult.newlyStrippedIds);
6641
- }
6642
5824
  logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
6643
5825
  } catch (error) {
6644
5826
  failPass("image-strip-exception", error);
@@ -6955,7 +6137,7 @@ async function runPostTransformPhase2(args) {
6955
6137
  sessionLog2(args.sessionId, `sticky-injection GC: pruned ${prunedAnchors} note-nudge anchor(s)`);
6956
6138
  }
6957
6139
  }
6958
- const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? "explicit_flush" : null);
6140
+ const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? pendingOrigin : null);
6959
6141
  const materialized = m0RematerializedThisPass || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully;
6960
6142
  let bustedThisPass = firstApplicationEdits.any || firstRenderBust || pendingOpsDidMutate || heuristicOrReasoningDidMutate || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass;
6961
6143
  const proactiveThinkingStripPermitted = isCacheBustingPass && !activeThinkingPrefixHold;
@@ -7341,7 +6523,7 @@ function checkM0MutationDriftAndSignal2(args) {
7341
6523
  const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
7342
6524
  const cachedMaxMutationId = args.cachedM0MaxMutationId ?? 0;
7343
6525
  if (currentMaxMutationId !== cachedMaxMutationId) {
7344
- args.pendingMaterializationSessions.add(args.sessionId);
6526
+ requestPendingMaterialization(args.pendingMaterializationSessions, args.sessionId, "mutation_drift");
7345
6527
  args.historyRefreshSessions?.add(args.sessionId);
7346
6528
  sessionLog2(args.sessionId, `m[0] drift watcher: mutation id changed ${cachedMaxMutationId} → ${currentMaxMutationId}; scheduling next-pass materialization`);
7347
6529
  return true;
@@ -7349,4 +6531,4 @@ function checkM0MutationDriftAndSignal2(args) {
7349
6531
  return false;
7350
6532
  }
7351
6533
 
7352
- 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, findReasoningBearingAssistantIds, snapshotTrailingBlankSourceDecisions, projectOpencodeReasoningBudgetCutoff, resolveKeepReasoningTokens, reasoningBudgetCutoff, 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 };
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 };