@retaw106/mmc-oc 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/config/deprecated-config.d.ts +4 -0
  3. package/dist/config/deprecated-config.d.ts.map +1 -0
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/project-security.d.ts +2 -2
  6. package/dist/config/schema/magic-context.d.ts +3 -3
  7. package/dist/config/schema/magic-context.d.ts.map +1 -1
  8. package/dist/config-init.js +2 -2
  9. package/dist/{context-mrvm92n8.js → context-wt7g4f8k.js} +1641 -1543
  10. package/dist/{derive-budgets-rjjz5f7y.js → derive-budgets-s1p37t2g.js} +2 -2
  11. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  12. package/dist/features/magic-context/historian-failure-reason.d.ts +7 -0
  13. package/dist/features/magic-context/historian-failure-reason.d.ts.map +1 -0
  14. package/dist/features/magic-context/message-index-async.d.ts +21 -3
  15. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  16. package/dist/features/magic-context/message-index.d.ts +7 -1
  17. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  18. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  19. package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
  20. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  21. package/dist/features/magic-context/search.d.ts +29 -0
  22. package/dist/features/magic-context/search.d.ts.map +1 -1
  23. package/dist/features/magic-context/storage-clone.d.ts +2 -0
  24. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  25. package/dist/features/magic-context/storage-compartment-history-version.d.ts +4 -0
  26. package/dist/features/magic-context/storage-compartment-history-version.d.ts.map +1 -0
  27. package/dist/features/magic-context/storage-db.d.ts +1 -1
  28. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  29. package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
  30. package/dist/features/magic-context/storage-meta-persisted.d.ts +23 -5
  31. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  32. package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
  33. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  34. package/dist/features/magic-context/storage-session-tables.d.ts +5 -1
  35. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  36. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
  37. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
  38. package/dist/features/magic-context/storage-tags.d.ts +155 -5
  39. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  40. package/dist/features/magic-context/tagger.d.ts +2 -0
  41. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  42. package/dist/features/magic-context/transform-decision-log.d.ts +3 -0
  43. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  44. package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
  45. package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
  46. package/dist/hooks/magic-context/apply-operations.d.ts +7 -0
  47. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/auto-search-runner.d.ts +2 -2
  49. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  50. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  51. package/dist/hooks/magic-context/history-boundary-repair.d.ts +11 -2
  52. package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
  53. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
  55. package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/lkg-persist.d.ts +10 -13
  57. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
  59. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
  60. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
  61. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
  62. package/dist/hooks/magic-context/lkg-replay.d.ts +16 -9
  63. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/lkg-slot.d.ts +141 -2
  65. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
  67. package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
  68. package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
  69. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
  71. package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
  72. package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
  74. package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
  75. package/dist/hooks/magic-context/read-session-chunk.d.ts +22 -1
  76. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
  78. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
  80. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/read-session-raw.d.ts +123 -1
  82. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  84. package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/sentinel.d.ts +41 -1
  86. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
  88. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
  89. package/dist/hooks/magic-context/strip-content.d.ts +38 -24
  90. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
  92. package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
  93. package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
  94. package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
  95. package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
  96. package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
  97. package/dist/hooks/magic-context/system-prompt-hash.d.ts +18 -5
  98. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/tag-messages.d.ts +19 -0
  100. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/tag-owner-warmup.d.ts +14 -0
  102. package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
  103. package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
  104. package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
  105. package/dist/hooks/magic-context/tool-drop-target.d.ts +2 -0
  106. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  107. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +7 -0
  108. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  109. package/dist/hooks/magic-context/transform.d.ts +21 -4
  110. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  111. package/dist/index-18yrysyj.js +1477 -0
  112. package/dist/{index-g2z2k5m4.js → index-3gj1ak4c.js} +2 -2
  113. package/dist/{index-5cep2r9n.js → index-5ty9rnbx.js} +60 -258
  114. package/dist/{index-amycb7b1.js → index-a5mw0xp3.js} +3 -3
  115. package/dist/{index-1j34a56j.js → index-czba8tw3.js} +266 -32
  116. package/dist/{index-qbkzdkk0.js → index-k59af64t.js} +6 -2
  117. package/dist/{index-53g38ggt.js → index-kmbme1v1.js} +1 -1
  118. package/dist/{index-5b7x80ec.js → index-kw21z5pe.js} +6055 -3973
  119. package/dist/{index-33gprt9g.js → index-yjv8dpht.js} +1 -1
  120. package/dist/{index-btp5tdc8.js → index-z2w1eq3y.js} +840 -456
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +114 -2
  123. package/dist/{message-time-backfill-phrwp2fz.js → message-time-backfill-sykevdax.js} +3 -3
  124. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  125. package/dist/{read-session-chunk-2xm4sc4y.js → read-session-chunk-863d6c06.js} +6 -4
  126. package/dist/recomp-orchestrator-wrjy3qym.js +21 -0
  127. package/dist/{safe-notification-target-ph3xd1ve.js → safe-notification-target-1jkf0m82.js} +2 -2
  128. package/dist/{send-session-notification-rnc4nrsr.js → send-session-notification-cz6ev088.js} +5 -5
  129. package/dist/shared/auto-search-lifecycle.d.ts +14 -0
  130. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
  131. package/dist/shared/logger.d.ts.map +1 -1
  132. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  133. package/dist/shared/models-dev-temperature.d.ts +18 -0
  134. package/dist/shared/models-dev-temperature.d.ts.map +1 -0
  135. package/dist/shared/processed-image-eligibility.d.ts +22 -0
  136. package/dist/shared/processed-image-eligibility.d.ts.map +1 -0
  137. package/dist/shared/project-directory-key.d.ts +16 -0
  138. package/dist/shared/project-directory-key.d.ts.map +1 -1
  139. package/dist/shared/recovery-reasoning-prefix.d.ts +9 -0
  140. package/dist/shared/recovery-reasoning-prefix.d.ts.map +1 -0
  141. package/dist/shared/sqlite.d.ts +33 -1
  142. package/dist/shared/sqlite.d.ts.map +1 -1
  143. package/dist/shared/stable-json.d.ts.map +1 -1
  144. package/dist/shared/storage-file-mutex.d.ts +9 -0
  145. package/dist/shared/storage-file-mutex.d.ts.map +1 -0
  146. package/dist/shared/storage-permissions.d.ts +6 -0
  147. package/dist/shared/storage-permissions.d.ts.map +1 -1
  148. package/dist/shared/subagent-temperature.d.ts +46 -0
  149. package/dist/shared/subagent-temperature.d.ts.map +1 -0
  150. package/dist/shared/tag-owner-id.d.ts +1 -0
  151. package/dist/shared/tag-owner-id.d.ts.map +1 -1
  152. package/dist/shared/tag-transcript.d.ts +9 -0
  153. package/dist/shared/tag-transcript.d.ts.map +1 -1
  154. package/dist/shared/window-geometry.d.ts +9 -66
  155. package/dist/shared/window-geometry.d.ts.map +1 -1
  156. package/dist/standalone-plugin-marker.d.ts +8 -0
  157. package/dist/standalone-plugin-marker.d.ts.map +1 -0
  158. package/dist/tools/ctx-expand/search-archive.d.ts +4 -0
  159. package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -0
  160. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  161. package/dist/tools/ctx-reduce/constants.d.ts +1 -2
  162. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  163. package/dist/tools/ctx-reduce/tools.d.ts +1 -1
  164. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  165. package/dist/v2/hooks/context.d.ts +1 -1
  166. package/dist/v2/hooks/context.d.ts.map +1 -1
  167. package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
  168. package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
  169. package/dist/v2/hooks/generate.d.ts +9 -2
  170. package/dist/v2/hooks/generate.d.ts.map +1 -1
  171. package/dist/v2/hooks/payload.d.ts.map +1 -1
  172. package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
  173. package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
  174. package/dist/v2/server.d.ts.map +1 -1
  175. package/dist/v2/server.js +34550 -30855
  176. package/dist/web/main.js +373 -19
  177. package/dist/{wrapup-orchestrator-yknks3ad.js → wrapup-orchestrator-bmybc5p5.js} +10 -10
  178. package/package.json +1 -1
  179. package/src/config/deprecated-config.ts +18 -0
  180. package/src/config/index.test.ts +13 -37
  181. package/src/config/index.ts +2 -2
  182. package/src/config/project-security.ts +3 -3
  183. package/src/config/schema/magic-context.ts +10 -6
  184. package/src/shared/auto-search-lifecycle.ts +43 -0
  185. package/src/shared/logger.ts +10 -2
  186. package/src/shared/models-dev-cache.ts +1 -7
  187. package/src/shared/models-dev-temperature.ts +107 -0
  188. package/src/shared/processed-image-eligibility.test.ts +68 -0
  189. package/src/shared/processed-image-eligibility.ts +41 -0
  190. package/src/shared/processed-image-position-review.json +20 -0
  191. package/src/shared/processed-image-position-review.test.ts +19 -0
  192. package/src/shared/project-directory-key.ts +20 -0
  193. package/src/shared/recovery-reasoning-prefix.test.ts +34 -0
  194. package/src/shared/recovery-reasoning-prefix.ts +35 -0
  195. package/src/shared/sqlite-acquisition-routing.test.ts +4 -3
  196. package/src/shared/sqlite-foreground-wait.test.ts +68 -0
  197. package/src/shared/sqlite-pass-scope.test.ts +4 -4
  198. package/src/shared/sqlite-writer-diagnostics.test.ts +52 -12
  199. package/src/shared/sqlite.ts +380 -39
  200. package/src/shared/stable-json.ts +37 -7
  201. package/src/shared/storage-file-mutex.test.ts +50 -0
  202. package/src/shared/storage-file-mutex.ts +130 -0
  203. package/src/shared/storage-permissions.ts +46 -0
  204. package/src/shared/subagent-temperature.ts +110 -0
  205. package/src/shared/tag-owner-id.ts +13 -0
  206. package/src/shared/tag-transcript.ts +118 -0
  207. package/src/shared/window-geometry.test.ts +102 -236
  208. package/src/shared/window-geometry.ts +23 -413
  209. package/dist/index-ramz5kkm.js +0 -514
  210. package/dist/recomp-orchestrator-frmwj9hz.js +0 -21
  211. package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
@@ -5,17 +5,30 @@ import {
5
5
  hasMeasuredDecisionCalibration,
6
6
  providerMass
7
7
  } from "./index-x37vg474.js";
8
+ import {
9
+ getTagIdentityWriteGeneration
10
+ } from "./index-czba8tw3.js";
8
11
  import {
9
12
  getHarness,
10
13
  sessionLog
11
- } from "./index-qbkzdkk0.js";
14
+ } from "./index-k59af64t.js";
12
15
  import {
13
16
  isKnownAutocommit,
17
+ readRawSessionMessagesFromDb,
18
+ readRawSessionMessagePageFromDb,
19
+ readRawSessionMessageSummaryPageFromDb,
20
+ countRawSessionMessageOrdinalsFromDb,
21
+ readRawSessionMessageIdOrdinalsForRangeFromDb,
22
+ readRawSessionTailFromDb,
23
+ warmRawSessionOrdinalsForDb,
24
+ readRawSessionMessageOrdinalByIdFromDb,
25
+ readRawSessionMessageByIdFromDb,
26
+ hasRawSessionMessageByIdFromDb,
14
27
  openCodeDbExists,
15
28
  withReadOnlySessionDb,
16
29
  getRawSessionMessageCountFromDb,
17
30
  getMessageTimesFromOpenCodeDb
18
- } from "./index-ramz5kkm.js";
31
+ } from "./index-18yrysyj.js";
19
32
 
20
33
  // src/shared/protected-tools-policy.ts
21
34
  var DEFAULT_PROTECTED_TOOLS = {
@@ -67,7 +80,7 @@ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
67
80
  import { createRequire } from "node:module";
68
81
  import { homedir } from "node:os";
69
82
  import { dirname, join, resolve } from "node:path";
70
- import { pathToFileURL } from "node:url";
83
+ import { fileURLToPath, pathToFileURL } from "node:url";
71
84
 
72
85
  // src/shared/commit-detection.ts
73
86
  var HASH_HEX = "[0-9a-f]{7,12}";
@@ -92,6 +105,272 @@ function removeSystemReminders(text) {
92
105
  return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
93
106
  }
94
107
 
108
+ // src/hooks/magic-context/token-count-exact.ts
109
+ var NO_RANK = 4294967295;
110
+ var LONG_PIECE_BYTES = 256;
111
+ var MERGE_CACHE_GENERATION = 50000;
112
+ function hasInternals(tokenizer) {
113
+ const value = tokenizer;
114
+ return !!value && value.patternRegex instanceof RegExp && value.patternRegex.global && typeof value.stringRankEncoder === "object" && value.stringRankEncoder !== null && Array.isArray(value.binaryFirstByteIndex);
115
+ }
116
+ var textEncoder = new TextEncoder;
117
+ var textDecoder = new TextDecoder("utf-8");
118
+ function isValidUtf8(bytes) {
119
+ let index = 0;
120
+ while (index < bytes.length) {
121
+ const first = bytes[index];
122
+ let size = 0;
123
+ let codePoint = 0;
124
+ if (first <= 127) {
125
+ size = 1;
126
+ codePoint = first;
127
+ } else if ((first & 224) === 192) {
128
+ size = 2;
129
+ codePoint = first & 31;
130
+ if (first <= 193)
131
+ return false;
132
+ } else if ((first & 240) === 224) {
133
+ size = 3;
134
+ codePoint = first & 15;
135
+ } else if ((first & 248) === 240) {
136
+ size = 4;
137
+ codePoint = first & 7;
138
+ if (first > 244)
139
+ return false;
140
+ } else
141
+ return false;
142
+ if (index + size > bytes.length)
143
+ return false;
144
+ for (let offset = 1;offset < size; offset += 1) {
145
+ const byte = bytes[index + offset];
146
+ if ((byte & 192) !== 128)
147
+ return false;
148
+ codePoint = codePoint << 6 | byte & 63;
149
+ }
150
+ if (size === 2 && codePoint < 128)
151
+ return false;
152
+ if (size === 3 && codePoint < 2048)
153
+ return false;
154
+ if (size === 4 && codePoint < 65536)
155
+ return false;
156
+ if (codePoint >= 55296 && codePoint <= 57343)
157
+ return false;
158
+ if (codePoint > 1114111)
159
+ return false;
160
+ index += size;
161
+ }
162
+ return true;
163
+ }
164
+ function binarySearchBytes(sorted, key) {
165
+ let low = 0;
166
+ let high = sorted.length - 1;
167
+ while (low <= high) {
168
+ const mid = low + high >>> 1;
169
+ const midKey = sorted[mid][0];
170
+ let compare = 0;
171
+ const shared = Math.min(midKey.length, key.length);
172
+ for (let index = 0;index < shared; index += 1) {
173
+ compare = midKey[index] - key[index];
174
+ if (compare !== 0)
175
+ break;
176
+ }
177
+ if (compare === 0)
178
+ compare = midKey.length - key.length;
179
+ if (compare === 0)
180
+ return sorted[mid][1];
181
+ if (compare < 0)
182
+ low = mid + 1;
183
+ else
184
+ high = mid - 1;
185
+ }
186
+ return -1;
187
+ }
188
+ function rankOf(tokenizer, slice) {
189
+ if (isValidUtf8(slice)) {
190
+ const rank = tokenizer.stringRankEncoder[textDecoder.decode(slice)];
191
+ if (rank !== undefined)
192
+ return rank;
193
+ }
194
+ const bucket = tokenizer.binaryFirstByteIndex[slice[0]];
195
+ if (bucket !== null && bucket !== undefined) {
196
+ const rank = binarySearchBytes(bucket, slice);
197
+ if (rank !== -1)
198
+ return rank;
199
+ }
200
+ return NO_RANK;
201
+ }
202
+ function mergeByScanning(tokenizer, bytes) {
203
+ const starts = [];
204
+ const ranks = [];
205
+ const pairRank = (index) => {
206
+ const end = starts[index + 2];
207
+ return end === undefined ? NO_RANK : rankOf(tokenizer, bytes.subarray(starts[index], end));
208
+ };
209
+ for (let index = 0;index <= bytes.length; index += 1)
210
+ starts.push(index);
211
+ for (let index = 0;index < starts.length; index += 1)
212
+ ranks.push(pairRank(index));
213
+ while (starts.length > 1) {
214
+ let minRank = NO_RANK;
215
+ let minIndex = -1;
216
+ for (let index = 0;index < ranks.length - 1; index += 1) {
217
+ if (ranks[index] < minRank) {
218
+ minRank = ranks[index];
219
+ minIndex = index;
220
+ }
221
+ }
222
+ if (minIndex === -1)
223
+ break;
224
+ starts.splice(minIndex + 1, 1);
225
+ ranks.splice(minIndex, 1);
226
+ ranks[minIndex] = pairRank(minIndex);
227
+ if (minIndex > 0)
228
+ ranks[minIndex - 1] = pairRank(minIndex - 1);
229
+ }
230
+ const tokens = [];
231
+ for (let index = 0;index < starts.length - 1; index += 1) {
232
+ const rank = rankOf(tokenizer, bytes.subarray(starts[index], starts[index + 1]));
233
+ if (rank !== NO_RANK)
234
+ tokens.push(rank);
235
+ }
236
+ return tokens;
237
+ }
238
+ function mergeWithHeap(tokenizer, bytes) {
239
+ const length = bytes.length;
240
+ const next = new Int32Array(length + 1);
241
+ const prev = new Int32Array(length + 1);
242
+ const alive = new Uint8Array(length + 1).fill(1);
243
+ const rank = new Float64Array(length + 1).fill(NO_RANK);
244
+ for (let index = 0;index <= length; index += 1) {
245
+ next[index] = index + 1;
246
+ prev[index] = index - 1;
247
+ }
248
+ const heapRank = [];
249
+ const heapAt = [];
250
+ const less = (a, b) => heapRank[a] < heapRank[b] || heapRank[a] === heapRank[b] && heapAt[a] < heapAt[b];
251
+ const swap = (a, b) => {
252
+ [heapRank[a], heapRank[b]] = [heapRank[b], heapRank[a]];
253
+ [heapAt[a], heapAt[b]] = [heapAt[b], heapAt[a]];
254
+ };
255
+ const push = (value, at) => {
256
+ heapRank.push(value);
257
+ heapAt.push(at);
258
+ let child = heapRank.length - 1;
259
+ while (child > 0) {
260
+ const parent = child - 1 >> 1;
261
+ if (!less(child, parent))
262
+ break;
263
+ swap(child, parent);
264
+ child = parent;
265
+ }
266
+ };
267
+ const pop = () => {
268
+ const last = heapRank.length - 1;
269
+ swap(0, last);
270
+ heapRank.pop();
271
+ heapAt.pop();
272
+ let parent = 0;
273
+ for (;; ) {
274
+ const left = parent * 2 + 1;
275
+ const right = left + 1;
276
+ let smallest = parent;
277
+ if (left < heapRank.length && less(left, smallest))
278
+ smallest = left;
279
+ if (right < heapRank.length && less(right, smallest))
280
+ smallest = right;
281
+ if (smallest === parent)
282
+ break;
283
+ swap(parent, smallest);
284
+ parent = smallest;
285
+ }
286
+ };
287
+ const pairRank = (at) => {
288
+ const middle = next[at];
289
+ if (middle >= length)
290
+ return NO_RANK;
291
+ return rankOf(tokenizer, bytes.subarray(at, next[middle]));
292
+ };
293
+ const update = (at) => {
294
+ rank[at] = pairRank(at);
295
+ if (rank[at] !== NO_RANK)
296
+ push(rank[at], at);
297
+ };
298
+ for (let at = 0;at < length; at += 1)
299
+ update(at);
300
+ while (heapRank.length > 0) {
301
+ const value = heapRank[0];
302
+ const at = heapAt[0];
303
+ pop();
304
+ if (!alive[at] || rank[at] !== value)
305
+ continue;
306
+ const removed = next[at];
307
+ alive[removed] = 0;
308
+ next[at] = next[removed];
309
+ prev[next[removed]] = at;
310
+ update(at);
311
+ if (at > 0)
312
+ update(prev[at]);
313
+ }
314
+ const tokens = [];
315
+ for (let at = 0;at < length; at = next[at]) {
316
+ const value = rankOf(tokenizer, bytes.subarray(at, next[at]));
317
+ if (value !== NO_RANK)
318
+ tokens.push(value);
319
+ }
320
+ return tokens;
321
+ }
322
+ var mergeCaches = new WeakMap;
323
+ var mergedPieces = 0;
324
+ function mergePiece(tokenizer, piece) {
325
+ let cache = mergeCaches.get(tokenizer);
326
+ if (!cache) {
327
+ cache = { current: new Map, previous: new Map };
328
+ mergeCaches.set(tokenizer, cache);
329
+ }
330
+ let tokens = cache.current.get(piece);
331
+ if (tokens)
332
+ return tokens;
333
+ tokens = cache.previous.get(piece);
334
+ if (!tokens) {
335
+ const bytes = textEncoder.encode(piece);
336
+ mergedPieces += 1;
337
+ tokens = bytes.length > LONG_PIECE_BYTES ? mergeWithHeap(tokenizer, bytes) : mergeByScanning(tokenizer, bytes);
338
+ }
339
+ if (cache.current.size >= MERGE_CACHE_GENERATION) {
340
+ cache.previous = cache.current;
341
+ cache.current = new Map;
342
+ }
343
+ cache.current.set(piece, tokens);
344
+ return tokens;
345
+ }
346
+ function encodeTokensExactly(tokenizer, text) {
347
+ if (!hasInternals(tokenizer)) {
348
+ return tokenizer.encode(text, "all");
349
+ }
350
+ if (text.length < 10) {
351
+ const direct = tokenizer.stringRankEncoder[text];
352
+ if (direct !== undefined)
353
+ return [direct];
354
+ }
355
+ const tokens = [];
356
+ const regex = tokenizer.patternRegex;
357
+ regex.lastIndex = 0;
358
+ for (let match = regex.exec(text);match !== null; match = regex.exec(text)) {
359
+ const piece = match[0];
360
+ const direct = tokenizer.stringRankEncoder[piece];
361
+ if (direct !== undefined) {
362
+ tokens.push(direct);
363
+ continue;
364
+ }
365
+ for (const token of mergePiece(tokenizer, piece))
366
+ tokens.push(token);
367
+ }
368
+ return tokens;
369
+ }
370
+ function countTokensExactly(tokenizer, text) {
371
+ return encodeTokensExactly(tokenizer, text).length;
372
+ }
373
+
95
374
  // src/hooks/magic-context/read-session-formatting.ts
96
375
  var MAX_COMMITS_PER_BLOCK = 5;
97
376
  function hasMeaningfulUserText2(parts) {
@@ -204,22 +483,30 @@ var tokenizerSerializedTableBytes;
204
483
  function tokenizerPackageRoots() {
205
484
  const cwd = process.cwd();
206
485
  const openCodeCache = join(process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "opencode");
207
- const roots = [cwd, openCodeCache];
208
486
  const candidates = [];
209
- for (const root of roots) {
487
+ const probeRoot = (root) => {
210
488
  for (const packageDir of TOKENIZER_PACKAGE_DIRS) {
211
489
  candidates.push(join(root, "node_modules", ...packageDir, "node_modules", "ai-tokenizer"));
212
490
  }
213
491
  candidates.push(join(root, "node_modules", "ai-tokenizer"));
492
+ };
493
+ for (const root of [cwd, openCodeCache]) {
494
+ probeRoot(root);
214
495
  }
215
- let ancestor = process.argv[1] ? dirname(resolve(process.argv[1])) : cwd;
216
- while (true) {
217
- candidates.push(join(ancestor, "node_modules", "ai-tokenizer"));
218
- const parent = dirname(ancestor);
219
- if (parent === ancestor)
220
- break;
221
- ancestor = parent;
222
- }
496
+ const pushAncestors = (startDir) => {
497
+ let ancestor = startDir;
498
+ while (true) {
499
+ candidates.push(join(ancestor, "node_modules", "ai-tokenizer"));
500
+ const parent = dirname(ancestor);
501
+ if (parent === ancestor)
502
+ break;
503
+ ancestor = parent;
504
+ }
505
+ };
506
+ pushAncestors(process.argv[1] ? dirname(resolve(process.argv[1])) : cwd);
507
+ const ownDir = dirname(fileURLToPath(new URL(import.meta.url)));
508
+ pushAncestors(ownDir);
509
+ probeRoot(join(homedir(), ".omp", "plugins"));
223
510
  return [...new Set(candidates)];
224
511
  }
225
512
  function packageImportTarget(value) {
@@ -379,7 +666,7 @@ function estimateTokens(text) {
379
666
  if (!activeTokenizer)
380
667
  return estimateTokensHeuristically(text);
381
668
  try {
382
- return activeTokenizer.encode(text, "all").length;
669
+ return countTokensExactly(activeTokenizer, text);
383
670
  } catch (error) {
384
671
  tokenizer = undefined;
385
672
  tokenizerLoadAttempted = true;
@@ -500,10 +787,34 @@ function mergeCommitHashes(existing, next) {
500
787
  var encoder = new TextEncoder;
501
788
  var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
502
789
  var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
790
+ var DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
503
791
  var DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
792
+ var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
793
+ var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
794
+ var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
504
795
  function stripWellFormedLeadingTagPrefix(value) {
505
796
  return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
506
797
  }
798
+ function stripCompleteTagPairsGlobally(value) {
799
+ return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
800
+ }
801
+ function stripMalformedTagNotationGlobally(value) {
802
+ return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
803
+ }
804
+ function stripDanglingTagNotationGlobally(value) {
805
+ return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
806
+ }
807
+ function stripTagSectionCharacters(value) {
808
+ return value.replace(STRAY_SECTION_CHAR_REGEX, "");
809
+ }
810
+ function stripPersistedAssistantText(value) {
811
+ let text = stripWellFormedLeadingTagPrefix(value);
812
+ text = stripCompleteTagPairsGlobally(text);
813
+ text = stripMalformedTagNotationGlobally(text);
814
+ text = stripDanglingTagNotationGlobally(text);
815
+ text = stripTagSectionCharacters(text);
816
+ return text.trim();
817
+ }
507
818
  function byteSize(value) {
508
819
  return encoder.encode(value).length;
509
820
  }
@@ -543,15 +854,34 @@ function isRecord(value) {
543
854
 
544
855
  // src/shared/stable-json.ts
545
856
  function stableStringify(value, seen = new WeakSet) {
546
- if (value === undefined)
547
- return "undefined";
548
- if (value === null || typeof value !== "object")
549
- return JSON.stringify(value) ?? String(value);
550
- if (seen.has(value))
551
- return '"[Circular]"';
857
+ const pieces = [];
858
+ writeStable(value, seen, pieces);
859
+ return pieces.join("");
860
+ }
861
+ function writeStable(value, seen, pieces) {
862
+ if (value === undefined) {
863
+ pieces.push("undefined");
864
+ return;
865
+ }
866
+ if (value === null || typeof value !== "object") {
867
+ pieces.push(JSON.stringify(value) ?? String(value));
868
+ return;
869
+ }
870
+ if (seen.has(value)) {
871
+ pieces.push('"[Circular]"');
872
+ return;
873
+ }
552
874
  seen.add(value);
553
875
  if (Array.isArray(value)) {
554
- return `[${value.map((item) => stableStringify(item, seen)).join(",")}]`;
876
+ pieces.push("[");
877
+ for (let index = 0;index < value.length; index += 1) {
878
+ if (index > 0)
879
+ pieces.push(",");
880
+ if (index in value)
881
+ writeStable(value[index], seen, pieces);
882
+ }
883
+ pieces.push("]");
884
+ return;
555
885
  }
556
886
  const entries = Object.entries(value).sort(([a], [b]) => {
557
887
  if (a < b)
@@ -560,10 +890,18 @@ function stableStringify(value, seen = new WeakSet) {
560
890
  return 1;
561
891
  return 0;
562
892
  });
563
- return `{${entries.map(([key, child]) => `${JSON.stringify(key)}:${stableStringify(child, seen)}`).join(",")}}`;
893
+ pieces.push("{");
894
+ entries.forEach(([key, child], index) => {
895
+ if (index > 0)
896
+ pieces.push(",");
897
+ pieces.push(JSON.stringify(key), ":");
898
+ writeStable(child, seen, pieces);
899
+ });
900
+ pieces.push("}");
564
901
  }
565
902
 
566
903
  // src/shared/tag-owner-id.ts
904
+ var PI_FALLBACK_PREFIXES_JSON = JSON.stringify([..."pi-msg-"].reduce((prefixes, char) => prefixes.flatMap((prefix) => /[a-z]/.test(char) ? [prefix + char, prefix + char.toUpperCase()] : [prefix + char]), [""]));
567
905
  var POSITIONAL_CONTENT_SUFFIX = /:(?:p|file)\d+$/;
568
906
  var CONTENT_DERIVED_TEXT_SUFFIX = /:mc-text-v1:[0-9a-f]+:[0-9a-f]+:o\d+$/;
569
907
  function contentTagOwnerMessageId(contentId) {
@@ -2392,6 +2730,117 @@ function removePendingOp(db, sessionId, tagId) {
2392
2730
  getRemovePendingOpStatement(db).run(sessionId, tagId);
2393
2731
  }
2394
2732
 
2733
+ // src/features/magic-context/storage-tag-identity-revision.ts
2734
+ var TAG_IDENTITY_REVISION_PREFIX = "tag_identity_revision:";
2735
+ var TAG_REVISION_PREFIX = "tag_revision:";
2736
+ var TAG_TOMBSTONE_OWNER_PREFIX = "tag_revision_owner:";
2737
+ var TAG_REVISION_INCARNATION_KEY = "tag_revision_incarnation";
2738
+ var tagRevisionIncarnationSql = (value) => `CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, 1, INSTR(${value}, ':') - 1) ELSE '0' END`;
2739
+ var tagRevisionCountSql = (value) => `CAST(CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, INSTR(${value}, ':') + 1) ELSE ${value} END AS INTEGER)`;
2740
+ var ADVANCE = (delta = "1") => `CASE
2741
+ WHEN ${tagRevisionCountSql("value")} <= 9223372036854775807 - ${delta}
2742
+ THEN (${tagRevisionIncarnationSql("value")}) || ':' || CAST(${tagRevisionCountSql("value")} + ${delta} AS TEXT)
2743
+ ELSE NULL END`;
2744
+ function tagTombstoneOwnerRange(sessionId) {
2745
+ const stem = `${TAG_TOMBSTONE_OWNER_PREFIX}${JSON.stringify(sessionId)}`;
2746
+ return [`${stem}:`, `${stem};`];
2747
+ }
2748
+ function tagTombstoneOwnerKey(sessionId, harness) {
2749
+ return `${tagTombstoneOwnerRange(sessionId)[0]}${harness}`;
2750
+ }
2751
+ function tagRevisionKey(sessionId) {
2752
+ return `${TAG_REVISION_PREFIX}${sessionId}`;
2753
+ }
2754
+ function tagIdentityRevisionKey(sessionId) {
2755
+ return `${TAG_IDENTITY_REVISION_PREFIX}${sessionId}`;
2756
+ }
2757
+ var BUMP = (session, prefix = TAG_IDENTITY_REVISION_PREFIX) => `INSERT INTO schema_migrations_meta (key, value)
2758
+ VALUES ('${prefix}' || ${session}, '1')
2759
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`;
2760
+ var TAG_INSERT_CONFLICT_ROWS = `SELECT id, session_id, tag_number FROM tags WHERE id = NEW.id
2761
+ UNION SELECT id, session_id, tag_number FROM tags WHERE session_id = NEW.session_id AND tag_number = NEW.tag_number
2762
+ UNION SELECT id, session_id, tag_number FROM tags
2763
+ WHERE NEW.type = 'tool' AND NEW.tool_owner_message_id IS NOT NULL
2764
+ AND type = 'tool' AND tool_owner_message_id IS NOT NULL
2765
+ AND session_id = NEW.session_id AND message_id = NEW.message_id
2766
+ AND tool_owner_message_id = NEW.tool_owner_message_id`;
2767
+ var BUMP_INSERT_CONFLICTS = (prefix) => `INSERT INTO schema_migrations_meta (key, value)
2768
+ SELECT '${prefix}' || session_id, CAST(COUNT(*) AS TEXT)
2769
+ FROM (${TAG_INSERT_CONFLICT_ROWS}) GROUP BY session_id
2770
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE("CAST(excluded.value AS INTEGER)")}`;
2771
+ var TRIGGER_SQL = `CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_identity_revision_au
2772
+ AFTER UPDATE OF id, session_id, message_id, tag_number, type, tool_owner_message_id, reasoning_token_count
2773
+ ON main.tags
2774
+ BEGIN
2775
+ ${BUMP("OLD.session_id")};
2776
+ INSERT INTO schema_migrations_meta (key, value)
2777
+ SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || NEW.session_id, '1'
2778
+ WHERE NEW.session_id IS NOT OLD.session_id
2779
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
2780
+ END`;
2781
+ function installTagIdentityRevisionTrigger(db) {
2782
+ db.exec(`DROP TRIGGER IF EXISTS temp.mc_tag_identity_revision_au;
2783
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_bi;
2784
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_ai;
2785
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_au;
2786
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_ad;
2787
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_seed_ai;`);
2788
+ db.exec(`CREATE TEMP TRIGGER mc_tag_revision_seed_ai AFTER INSERT ON main.schema_migrations_meta
2789
+ WHEN INSTR(NEW.value, ':') = 0 AND (
2790
+ SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
2791
+ OR SUBSTR(NEW.key, 1, ${TAG_IDENTITY_REVISION_PREFIX.length}) = '${TAG_IDENTITY_REVISION_PREFIX}')
2792
+ BEGIN
2793
+ INSERT INTO schema_migrations_meta (key, value) VALUES ('${TAG_REVISION_INCARNATION_KEY}', '1')
2794
+ ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
2795
+ WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
2796
+ ELSE NULL END AS TEXT);
2797
+ UPDATE schema_migrations_meta SET value =
2798
+ (SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}')
2799
+ || ':' || CAST(NEW.value AS TEXT) WHERE key = NEW.key;
2800
+ INSERT INTO schema_migrations_meta (key, value)
2801
+ SELECT '${TAG_REVISION_INCARNATION_KEY}', '1'
2802
+ WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
2803
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
2804
+ WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}))
2805
+ ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
2806
+ WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
2807
+ ELSE NULL END AS TEXT);
2808
+ INSERT INTO schema_migrations_meta (key, value)
2809
+ SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}),
2810
+ (SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}') || ':0'
2811
+ WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
2812
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
2813
+ WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}));
2814
+ END;`);
2815
+ db.exec(TRIGGER_SQL);
2816
+ db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_bi BEFORE INSERT ON main.tags BEGIN
2817
+ ${BUMP_INSERT_CONFLICTS(TAG_REVISION_PREFIX)};
2818
+ ${BUMP_INSERT_CONFLICTS(TAG_IDENTITY_REVISION_PREFIX)};
2819
+ UPDATE session_meta SET tags_version = tags_version + 1
2820
+ WHERE session_id IN (SELECT session_id FROM (${TAG_INSERT_CONFLICT_ROWS}));
2821
+ END;`);
2822
+ db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ai AFTER INSERT ON main.tags BEGIN
2823
+ ${BUMP("NEW.session_id", TAG_REVISION_PREFIX)};
2824
+ END;
2825
+ CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_au AFTER UPDATE ON main.tags BEGIN
2826
+ ${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
2827
+ INSERT INTO schema_migrations_meta (key, value)
2828
+ SELECT '${TAG_REVISION_PREFIX}' || NEW.session_id, '1'
2829
+ WHERE NEW.session_id IS NOT OLD.session_id
2830
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
2831
+ END;
2832
+ CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ad AFTER DELETE ON main.tags BEGIN
2833
+ ${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
2834
+ END;`);
2835
+ }
2836
+ function deleteTagIdentityRevisions(db, sessionIds) {
2837
+ const statement = db.prepare(`INSERT INTO schema_migrations_meta (key, value) VALUES (?, '1')
2838
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`);
2839
+ for (const sessionId of sessionIds) {
2840
+ statement.run(tagIdentityRevisionKey(sessionId));
2841
+ }
2842
+ }
2843
+
2395
2844
  // src/features/magic-context/storage-tags.ts
2396
2845
  var insertTagStatements = new WeakMap;
2397
2846
  var updateTagStatusStatements = new WeakMap;
@@ -2610,8 +3059,41 @@ function getActiveTagTokenTotalsByMessage(db, sessionId, messageIds) {
2610
3059
  }
2611
3060
  var updateTagTokenCountStatements = new WeakMap;
2612
3061
  var updateTagInputTokenCountStatements = new WeakMap;
2613
- function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration = { proseRatio: 1, toolsRatio: 1 }, options) {
2614
- const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
3062
+ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration = { proseRatio: 1, toolsRatio: 1 }, options, ownerMessageIds) {
3063
+ const columns = "type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count";
3064
+ const owners = ownerMessageIds ? new Set(ownerMessageIds) : undefined;
3065
+ let scanOrder = "id";
3066
+ if (owners) {
3067
+ const planStatement = db.prepare(`EXPLAIN QUERY PLAN SELECT ${columns} FROM tags WHERE session_id = ?${floor > 0 ? " AND tag_number >= ?" : ""}`);
3068
+ let plan;
3069
+ try {
3070
+ plan = planStatement.all(sessionId, ...floor > 0 ? [floor] : []);
3071
+ } finally {
3072
+ planStatement.finalize?.();
3073
+ }
3074
+ const index = plan.map((row) => /USING (?:COVERING )?INDEX (\S+)/.exec(row.detail)?.[1]).find(Boolean);
3075
+ if (index) {
3076
+ const keyStatement = db.prepare("SELECT name, coll, desc FROM pragma_index_xinfo(?) WHERE key = 1 ORDER BY seqno");
3077
+ let keys;
3078
+ try {
3079
+ keys = keyStatement.all(index);
3080
+ } finally {
3081
+ keyStatement.finalize?.();
3082
+ }
3083
+ scanOrder = [
3084
+ ...keys.map((key) => `"${(key.name ?? "id").replaceAll('"', '""')}" COLLATE "${key.coll.replaceAll('"', '""')}"${key.desc ? " DESC" : ""}`),
3085
+ "id"
3086
+ ].join(", ");
3087
+ }
3088
+ }
3089
+ const rows = owners ? db.prepare(`SELECT ${columns} FROM tags WHERE id IN (
3090
+ SELECT t.id FROM json_each(?) o CROSS JOIN tags t INDEXED BY idx_tags_session_message_id
3091
+ ON t.session_id = ? AND t.message_id >= o.value AND t.message_id < o.value || ';'
3092
+ UNION
3093
+ SELECT t.id FROM json_each(?) o CROSS JOIN tags t INDEXED BY idx_tags_pi_fallback_tool_owner
3094
+ ON t.session_id = ? AND t.tool_owner_message_id = o.value
3095
+ WHERE t.type = 'tool'
3096
+ ) AND tag_number >= ? ORDER BY ${scanOrder}`).all(JSON.stringify([...owners]), sessionId, JSON.stringify([...owners]), sessionId, floor) : floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
2615
3097
  FROM tags
2616
3098
  WHERE session_id = ? AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
2617
3099
  FROM tags
@@ -2624,6 +3106,8 @@ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration =
2624
3106
  if (options?.excludeToolTags === true && row.type === "tool")
2625
3107
  continue;
2626
3108
  const owner = ownerMessageIdForTagRow(row);
3109
+ if (owners && !owners.has(owner))
3110
+ continue;
2627
3111
  if (row.token_count === null) {
2628
3112
  nullMessageIds.add(owner);
2629
3113
  totals.delete(owner);
@@ -2638,15 +3122,199 @@ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration =
2638
3122
  return { totals, nullMessageIds };
2639
3123
  }
2640
3124
  function getReasoningTokenEstimatesByMessage(db, sessionId, proseRatio) {
2641
- const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, reasoning_token_count FROM tags WHERE session_id = ? AND reasoning_token_count IS NOT NULL`).all(sessionId);
2642
- const totals = new Map;
2643
- for (const row of rows) {
2644
- if (row.type !== "message")
2645
- continue;
2646
- const id = ownerMessageIdForTagRow(row);
2647
- totals.set(id, Math.max(totals.get(id) ?? 0, row.reasoning_token_count * proseRatio));
3125
+ const summary = readTagOwnerSummary(db, sessionId, proseRatio);
3126
+ return summary.reasoningEstimatesByRatio.get(proseRatio) ?? new Map;
3127
+ }
3128
+ function tryGetReasoningTokenEstimatesByMessage(db, sessionId, ratio) {
3129
+ try {
3130
+ return getReasoningTokenEstimatesByMessage(db, sessionId, ratio);
3131
+ } catch (error) {
3132
+ if (error instanceof TagOwnerSummaryNotReady)
3133
+ return;
3134
+ throw error;
3135
+ }
3136
+ }
3137
+ function getMaxTagNumberByOwnerMessage(db, sessionId) {
3138
+ return readTagOwnerSummary(db, sessionId).maxTagByOwner;
3139
+ }
3140
+ var tagOwnerSummaries = new WeakMap;
3141
+ var MAX_CACHED_PROSE_RATIOS = 4;
3142
+ var TAG_OWNER_PAGE_LIMIT = 512;
3143
+
3144
+ class TagOwnerSummaryNotReady extends Error {
3145
+ constructor() {
3146
+ super("tag owner summary needs off-thread preparation");
2648
3147
  }
2649
- return totals;
3148
+ }
3149
+ function scanTagOwnerSummary(db, sessionId, ratio, ratios = []) {
3150
+ db.exec("BEGIN");
3151
+ try {
3152
+ return readTagOwnerSummary(db, sessionId, ratio, ratios);
3153
+ } finally {
3154
+ db.exec("ROLLBACK");
3155
+ }
3156
+ }
3157
+ function isTagOwnerSummaryReady(db, sessionId, ratio) {
3158
+ try {
3159
+ readTagOwnerSummary(db, sessionId, ratio);
3160
+ return true;
3161
+ } catch (error) {
3162
+ if (error instanceof TagOwnerSummaryNotReady)
3163
+ return false;
3164
+ throw error;
3165
+ }
3166
+ }
3167
+ var tagOwnerRowsRead = 0;
3168
+ var tagOwnerShapeChecks = 0;
3169
+ function foldTagOwnerRow(summary, row, newRow = true) {
3170
+ summary.lastRowId = Math.max(summary.lastRowId, row.id);
3171
+ if (newRow)
3172
+ summary.rowCount += 1;
3173
+ if (row.type === "tool" && typeof row.tool_owner_message_id !== "string")
3174
+ summary.unownedToolRows.add(row.id);
3175
+ else
3176
+ summary.unownedToolRows.delete(row.id);
3177
+ const owner = row.type === "tool" ? typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null : typeof row.message_id === "string" ? contentTagOwnerMessageId(row.message_id) : null;
3178
+ if (owner) {
3179
+ summary.maxTagByOwner.set(owner, Math.max(summary.maxTagByOwner.get(owner) ?? 0, row.tag_number));
3180
+ }
3181
+ if (row.type !== "message" || row.reasoning_token_count === null)
3182
+ return;
3183
+ const reasoningOwner = ownerMessageIdForTagRow({
3184
+ type: row.type,
3185
+ message_id: row.message_id,
3186
+ tool_owner_message_id: row.tool_owner_message_id
3187
+ });
3188
+ for (const [ratio, estimates] of summary.reasoningEstimatesByRatio) {
3189
+ estimates.set(reasoningOwner, Math.max(estimates.get(reasoningOwner) ?? 0, row.reasoning_token_count * ratio));
3190
+ }
3191
+ }
3192
+ var TAG_OWNER_COLUMNS = "id, type, message_id, tool_owner_message_id, tag_number, reasoning_token_count";
3193
+ function connectionInTransaction(db) {
3194
+ try {
3195
+ const state = db;
3196
+ return state.inTransaction !== false && state.isTransaction !== false;
3197
+ } catch {
3198
+ return true;
3199
+ }
3200
+ }
3201
+ var TAG_OWNER_APPENDED_WITH_SHAPE_SQL = `SELECT ${TAG_OWNER_COLUMNS}, 0 AS shape, NULL AS tag_count, NULL AS max_id, NULL AS revision
3202
+ FROM tags WHERE id > ? AND +session_id = ?
3203
+ UNION ALL
3204
+ SELECT NULL, NULL, NULL, NULL, NULL, NULL, 1, COUNT(*), MAX(id), (SELECT value FROM schema_migrations_meta WHERE key = ?)
3205
+ FROM tags WHERE session_id = ?`;
3206
+ function readTagIdentityRevision(db, sessionId) {
3207
+ const row = db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(tagIdentityRevisionKey(sessionId));
3208
+ return typeof row?.value === "string" ? row.value : null;
3209
+ }
3210
+ function captureInitialTagOwnerRevision(db, sessionId, cached, appendedRows) {
3211
+ if (cached.identityRevision !== null || appendedRows === 0)
3212
+ return true;
3213
+ const revision = readTagIdentityRevision(db, sessionId);
3214
+ if (revision !== null && !/^[1-9]\d*:0$/.test(revision))
3215
+ return false;
3216
+ cached.identityRevision = revision;
3217
+ return true;
3218
+ }
3219
+ function appendedSinceForeignCommit(db, sessionId, cached) {
3220
+ tagOwnerShapeChecks += 1;
3221
+ const rows = db.prepare(TAG_OWNER_APPENDED_WITH_SHAPE_SQL).all(cached.globalLastRowId, sessionId, tagIdentityRevisionKey(sessionId), sessionId);
3222
+ const shape = rows.find((row) => row.shape === 1);
3223
+ const appended = rows.filter((row) => row.shape === 0);
3224
+ const highest = appended.reduce((max, row) => Math.max(max, row.id), cached.lastRowId);
3225
+ if (!shape || (shape.revision ?? null) !== cached.identityRevision || shape.tag_count !== cached.rowCount + appended.length || (shape.max_id ?? 0) !== highest)
3226
+ return null;
3227
+ return appended;
3228
+ }
3229
+ function adoptedSinceForeignCommit(db, cached) {
3230
+ if (cached.unownedToolRows.size === 0)
3231
+ return [];
3232
+ return db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags
3233
+ WHERE id IN (SELECT value FROM json_each(?)) AND tool_owner_message_id IS NOT NULL LIMIT ${TAG_OWNER_PAGE_LIMIT + 1}`).all(JSON.stringify([...cached.unownedToolRows]));
3234
+ }
3235
+ function readTagOwnerSummary(db, sessionId, proseRatio, extraRatios = []) {
3236
+ const inTransaction = connectionInTransaction(db);
3237
+ const versions = inTransaction ? null : db.prepare("SELECT data_version AS dataVersion, (SELECT schema_version FROM pragma_schema_version) AS schemaVersion FROM pragma_data_version").get();
3238
+ const dataVersion = versions?.dataVersion ?? -1;
3239
+ const schemaVersion = versions?.schemaVersion ?? -1;
3240
+ const generation = getTagIdentityWriteGeneration();
3241
+ const sessions = tagOwnerSummaries.get(db) ?? new Map;
3242
+ const cached = inTransaction ? undefined : sessions.get(sessionId);
3243
+ if (cached && (cached.generation === generation || cached.identityRevision === readTagIdentityRevision(db, sessionId)) && cached.schemaVersion === schemaVersion && (proseRatio === undefined || cached.reasoningEstimatesByRatio.has(proseRatio))) {
3244
+ let rows;
3245
+ let globalLastRowId = db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id;
3246
+ if (cached.dataVersion === dataVersion && cached.generation === generation) {
3247
+ const statement = db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags WHERE id > ? AND +session_id = ? ORDER BY id LIMIT ${TAG_OWNER_PAGE_LIMIT + 1}`);
3248
+ rows = statement.all(cached.globalLastRowId, sessionId);
3249
+ let page = rows;
3250
+ while (page.length === TAG_OWNER_PAGE_LIMIT + 1) {
3251
+ page = statement.all(page[page.length - 1].id, sessionId);
3252
+ rows.push(...page);
3253
+ }
3254
+ if (!captureInitialTagOwnerRevision(db, sessionId, cached, rows.length)) {
3255
+ rows = null;
3256
+ }
3257
+ } else {
3258
+ try {
3259
+ globalLastRowId = db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM tags").get().id;
3260
+ rows = appendedSinceForeignCommit(db, sessionId, cached);
3261
+ const adopted = rows ? adoptedSinceForeignCommit(db, cached) : [];
3262
+ if (!rows || rows.length > TAG_OWNER_PAGE_LIMIT || adopted.length > TAG_OWNER_PAGE_LIMIT) {
3263
+ rows = null;
3264
+ } else {
3265
+ tagOwnerRowsRead += rows.length + adopted.length;
3266
+ for (const row of rows)
3267
+ foldTagOwnerRow(cached, row);
3268
+ for (const row of adopted)
3269
+ foldTagOwnerRow(cached, row, false);
3270
+ cached.dataVersion = dataVersion;
3271
+ cached.generation = generation;
3272
+ cached.globalLastRowId = globalLastRowId;
3273
+ return cached;
3274
+ }
3275
+ } catch {
3276
+ rows = null;
3277
+ }
3278
+ }
3279
+ if (rows) {
3280
+ const adopted = cached.dataVersion === dataVersion ? [] : adoptedSinceForeignCommit(db, cached);
3281
+ tagOwnerRowsRead += rows.length + adopted.length;
3282
+ for (const row of rows)
3283
+ foldTagOwnerRow(cached, row);
3284
+ for (const row of adopted)
3285
+ foldTagOwnerRow(cached, row, false);
3286
+ cached.dataVersion = dataVersion;
3287
+ cached.generation = generation;
3288
+ cached.globalLastRowId = globalLastRowId;
3289
+ return cached;
3290
+ }
3291
+ }
3292
+ const ratios = [
3293
+ ...new Set([...cached?.reasoningEstimatesByRatio.keys() ?? [], ...extraRatios])
3294
+ ];
3295
+ if (proseRatio !== undefined && !ratios.includes(proseRatio))
3296
+ ratios.push(proseRatio);
3297
+ const summary = {
3298
+ dataVersion,
3299
+ schemaVersion,
3300
+ generation,
3301
+ lastRowId: 0,
3302
+ globalLastRowId: db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id,
3303
+ rowCount: 0,
3304
+ unownedToolRows: new Set,
3305
+ identityRevision: readTagIdentityRevision(db, sessionId),
3306
+ maxTagByOwner: new Map,
3307
+ reasoningEstimatesByRatio: new Map(ratios.slice(-MAX_CACHED_PROSE_RATIOS).map((ratio) => [ratio, new Map]))
3308
+ };
3309
+ const rows = db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags WHERE session_id = ? ORDER BY id`).all(sessionId);
3310
+ tagOwnerRowsRead += rows.length;
3311
+ for (const row of rows)
3312
+ foldTagOwnerRow(summary, row);
3313
+ if (!inTransaction) {
3314
+ sessions.set(sessionId, summary);
3315
+ tagOwnerSummaries.set(db, sessions);
3316
+ }
3317
+ return summary;
2650
3318
  }
2651
3319
  function tagTokenCountIsNull(db, sessionId, tagNumber) {
2652
3320
  const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
@@ -2689,7 +3357,7 @@ function getTagNumberByMessageIdStatement(db) {
2689
3357
  function getAssignableTagNumberByMessageIdStatement(db) {
2690
3358
  let stmt = getAssignableTagNumberByMessageIdStatements.get(db);
2691
3359
  if (!stmt) {
2692
- stmt = db.prepare(`SELECT tag_number FROM tags
3360
+ stmt = db.prepare(`SELECT tag_number FROM tags INDEXED BY idx_tags_session_message_id
2693
3361
  WHERE session_id = ?
2694
3362
  AND message_id = ?
2695
3363
  AND NOT (
@@ -2787,6 +3455,28 @@ function getInertWhitespaceAssistantTags(db, sessionId, messageIds) {
2787
3455
  return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
2788
3456
  });
2789
3457
  }
3458
+ var inertWhitespaceByNumberStatements = new WeakMap;
3459
+ function getInertWhitespaceAssistantTagsByNumbers(db, sessionId, tagNumbers) {
3460
+ if (tagNumbers.length === 0)
3461
+ return [];
3462
+ let statement = inertWhitespaceByNumberStatements.get(db);
3463
+ if (!statement) {
3464
+ statement = db.prepare(`SELECT tags.tag_number AS tagNumber, tags.entry_fingerprint AS entryFingerprint
3465
+ FROM json_each(?) AS wanted CROSS JOIN tags
3466
+ WHERE tags.session_id = ?
3467
+ AND tags.tag_number = wanted.value
3468
+ AND tags.type = 'message'
3469
+ AND tags.status = 'compacted'
3470
+ AND tags.entry_fingerprint LIKE ?
3471
+ ORDER BY tags.tag_number, tags.id`);
3472
+ inertWhitespaceByNumberStatements.set(db, statement);
3473
+ }
3474
+ const rows = statement.all(JSON.stringify([...new Set(tagNumbers)]), sessionId, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%`);
3475
+ return rows.flatMap((row) => {
3476
+ const contentId = row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length);
3477
+ return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
3478
+ });
3479
+ }
2790
3480
  function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
2791
3481
  getUpdateTagDropModeStatement(db).run(dropMode, sessionId, tagNumber);
2792
3482
  }
@@ -3013,7 +3703,8 @@ function markTagsCompactedByMessageIds(db, sessionId, messageIds, eligibleTagNum
3013
3703
  SELECT value AS source_id, lower(value) AS folded_id FROM json_each(?)
3014
3704
  )
3015
3705
  SELECT id, tag_number, message_id, tool_owner_message_id FROM tags INDEXED BY ${tagOrderConstraintIndex(db)}
3016
- WHERE session_id = ? AND status IN ('active', 'dropped') AND (
3706
+ WHERE session_id = ? ${eligibleTagNumbers ? "AND tag_number IN (SELECT value FROM json_each(?))" : ""}
3707
+ AND status IN ('active', 'dropped') AND (
3017
3708
  message_id IN (SELECT source_id FROM ids)
3018
3709
  OR tool_owner_message_id IN (SELECT source_id FROM ids)
3019
3710
  OR (instr(lower(message_id), ':p') > 0 AND
@@ -3022,8 +3713,8 @@ function markTagsCompactedByMessageIds(db, sessionId, messageIds, eligibleTagNum
3022
3713
  lower(substr(message_id, 1, instr(lower(message_id), ':file') - 1)) IN (SELECT folded_id FROM ids))
3023
3714
  OR (? AND instr(message_id, ':') > 0)
3024
3715
  OR ?
3025
- )`).all(JSON.stringify(Array.from(ids)), sessionId, Array.from(ids).some((id) => id.includes(":")) ? 1 : 0, nulPrefixes.size > 0 ? 1 : 0);
3026
- const candidates = rows.filter((row) => (eligibleTagNumbers === undefined || eligibleTagNumbers.has(row.tag_number)) && matches(row.message_id, row.tool_owner_message_id));
3716
+ )`).all(JSON.stringify(Array.from(ids)), sessionId, ...eligibleTagNumbers ? [JSON.stringify([...eligibleTagNumbers])] : [], Array.from(ids).some((id) => id.includes(":")) ? 1 : 0, nulPrefixes.size > 0 ? 1 : 0);
3717
+ const candidates = rows.filter((row) => matches(row.message_id, row.tool_owner_message_id));
3027
3718
  if (candidates.length === 0)
3028
3719
  return 0;
3029
3720
  const update = db.prepare(`UPDATE tags SET status = 'compacted'
@@ -3685,421 +4376,83 @@ function isHostRenderedSystemMessage(message) {
3685
4376
  return (typeof id !== "string" || id.length === 0) && message.info.role === "system";
3686
4377
  }
3687
4378
 
3688
- // src/hooks/magic-context/read-session-raw.ts
3689
- function isStrictGapHealingMessage(message) {
3690
- if (message.storeType === "synthetic")
3691
- return true;
3692
- let sawTool = false;
3693
- for (const part of message.parts) {
3694
- if (!part || typeof part !== "object" || Array.isArray(part))
3695
- return false;
3696
- const record = part;
3697
- const type = typeof record.type === "string" ? record.type : "";
3698
- if (type === "tool" || type === "tool_use" || type === "tool_result") {
3699
- sawTool = true;
3700
- continue;
3701
- }
3702
- const text = typeof record.text === "string" ? record.text : typeof record.content === "string" ? record.content : "";
3703
- if (text.trim().length > 0 || type.length > 0)
3704
- return false;
3705
- }
3706
- return sawTool;
3707
- }
3708
- var RAW_MESSAGE_PARTS_BY_ID_SQL = "SELECT message_id, data, time_updated FROM part WHERE +session_id = ? AND likelihood(message_id = ?, 0.000001) ORDER BY time_created ASC, id ASC";
3709
- function isRawMessageRow(row) {
3710
- if (row === null || typeof row !== "object")
3711
- return false;
3712
- const candidate = row;
3713
- return typeof candidate.id === "string" && typeof candidate.data === "string";
3714
- }
3715
- function isRawPartRow(row) {
3716
- if (row === null || typeof row !== "object")
3717
- return false;
3718
- const candidate = row;
3719
- return typeof candidate.message_id === "string" && typeof candidate.data === "string";
3720
- }
3721
- function parseJsonRecord(value) {
3722
- try {
3723
- const parsed = JSON.parse(value);
3724
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
3725
- return null;
4379
+ // src/hooks/magic-context/provider-visible-parts.ts
4380
+ function isRecord2(value) {
4381
+ return value !== null && typeof value === "object" && !Array.isArray(value);
4382
+ }
4383
+ var KEPT_TOOL_STATE_FIELDS = new Set([
4384
+ "status",
4385
+ "input",
4386
+ "output",
4387
+ "error",
4388
+ "attachments",
4389
+ "content"
4390
+ ]);
4391
+ var KEPT_TOOL_STATE_TIME_FIELD = "compacted";
4392
+ var KEPT_ERROR_METADATA_FIELDS = ["interrupted", "output"];
4393
+ function providerVisibleToolState(state) {
4394
+ const view = {};
4395
+ for (const key of Object.keys(state)) {
4396
+ const value = state[key];
4397
+ if (KEPT_TOOL_STATE_FIELDS.has(key)) {
4398
+ view[key] = value;
4399
+ } else if (key === "time" && isRecord2(value)) {
4400
+ view.time = value[KEPT_TOOL_STATE_TIME_FIELD] === undefined ? {} : { [KEPT_TOOL_STATE_TIME_FIELD]: value[KEPT_TOOL_STATE_TIME_FIELD] };
4401
+ } else if (key === "metadata" && state.status === "error" && isRecord2(value)) {
4402
+ const kept = {};
4403
+ for (const field of KEPT_ERROR_METADATA_FIELDS) {
4404
+ if (Object.hasOwn(value, field))
4405
+ kept[field] = value[field];
4406
+ }
4407
+ view.metadata = kept;
3726
4408
  }
3727
- return parsed;
3728
- } catch {
3729
- return null;
3730
4409
  }
4410
+ return view;
3731
4411
  }
3732
- function isRawCompactionSummaryInfo(info) {
3733
- if (info === null || typeof info !== "object" || Array.isArray(info))
3734
- return false;
3735
- const candidate = info;
3736
- return candidate.summary === true && candidate.finish === "stop";
3737
- }
3738
- function parseJsonUnknown(value) {
3739
- try {
3740
- return JSON.parse(value);
3741
- } catch {
3742
- return null;
3743
- }
3744
- }
3745
- function attachRawPartVersion(value, timeUpdated) {
3746
- if (value === null || typeof value !== "object" || Array.isArray(value))
3747
- return value;
3748
- if (typeof timeUpdated !== "number")
3749
- return value;
3750
- try {
3751
- Object.defineProperty(value, "__magicContextPartUpdatedAt", {
3752
- value: timeUpdated,
3753
- enumerable: false,
3754
- configurable: true
3755
- });
3756
- } catch {}
3757
- return value;
3758
- }
3759
- function readRawSessionMessagesFromDb(db, sessionId) {
3760
- const messageRows = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
3761
- const partsByMessageId = new Map;
3762
- const partMessageBatchSize = 128;
3763
- for (let offset = 0;offset < messageRows.length; offset += partMessageBatchSize) {
3764
- const messageIds = messageRows.slice(offset, offset + partMessageBatchSize).map((row) => row.id);
3765
- if (messageIds.length === 0)
4412
+ function toolStateIsReduced(state) {
4413
+ for (const key of Object.keys(state)) {
4414
+ if (KEPT_TOOL_STATE_FIELDS.has(key))
3766
4415
  continue;
3767
- const placeholders = messageIds.map(() => "?").join(", ");
3768
- const partRows = db.prepare(`SELECT message_id, data, time_updated
3769
- FROM part
3770
- WHERE +session_id = ?
3771
- AND likelihood(message_id IN (${placeholders}), 0.000001)
3772
- ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageIds).filter(isRawPartRow);
3773
- for (const part of partRows) {
3774
- const list = partsByMessageId.get(part.message_id) ?? [];
3775
- list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
3776
- partsByMessageId.set(part.message_id, list);
3777
- }
3778
- }
3779
- const filtered = messageRows.filter((row) => !isRawCompactionSummaryInfo(parseJsonRecord(row.data)));
3780
- return filtered.flatMap((row, index) => {
3781
- const info = parseJsonRecord(row.data);
3782
- if (!info)
3783
- return [];
3784
- const role = typeof info.role === "string" ? info.role : "unknown";
3785
- return {
3786
- ordinal: index + 1,
3787
- id: row.id,
3788
- role,
3789
- parts: partsByMessageId.get(row.id) ?? [],
3790
- createdAt: row.time_created ?? null,
3791
- version: row.time_updated ?? null
3792
- };
3793
- });
3794
- }
3795
- function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER, after) {
3796
- const messageRows = readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark, after);
3797
- if (messageRows.length === 0)
3798
- return [];
3799
- const placeholders = messageRows.map(() => "?").join(", ");
3800
- const partRows = db.prepare(`SELECT message_id, data, time_updated
3801
- FROM part
3802
- WHERE +session_id = ?
3803
- AND likelihood(message_id IN (${placeholders}), 0.000001)
3804
- ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
3805
- return assembleRawMessagePage(messageRows, partRows);
3806
- }
3807
- function readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark, after) {
3808
- const remaining = Math.max(0, Math.floor(finalWatermark) - Math.floor(afterOrdinal));
3809
- const pageSize = Math.min(Math.max(1, Math.floor(limit)), remaining);
3810
- if (pageSize === 0)
3811
- return [];
3812
- const parameters = [sessionId];
3813
- if (after)
3814
- parameters.push(after.timeCreated, after.timeCreated, after.timeCreated, after.id);
3815
- parameters.push(pageSize);
3816
- if (!after)
3817
- parameters.push(Math.max(0, Math.floor(afterOrdinal)));
3818
- return db.prepare(`SELECT id, data, time_created, time_updated
3819
- FROM message
3820
- WHERE session_id = ?
3821
- ${after ? "AND time_created >= ? AND (time_created > ? OR (time_created = ? AND id > ?))" : ""}
3822
- AND NOT (
3823
- CASE WHEN json_valid(data) = 1
3824
- THEN COALESCE(json_extract(data, '$.summary'), 0)
3825
- ELSE 0 END = 1
3826
- AND CASE WHEN json_valid(data) = 1
3827
- THEN COALESCE(json_extract(data, '$.finish'), '')
3828
- ELSE '' END = 'stop'
3829
- )
3830
- ORDER BY time_created ASC, id ASC
3831
- LIMIT ? ${after ? "" : "OFFSET ?"}`).all(...parameters).filter(isRawMessageRow).map((row, index) => ({
3832
- ...row,
3833
- ordinal: Math.floor(afterOrdinal) + index + 1
3834
- }));
3835
- }
3836
- function assembleRawMessagePage(messageRows, partRows) {
3837
- const partsByMessageId = new Map;
3838
- for (const part of partRows) {
3839
- const list = partsByMessageId.get(part.message_id) ?? [];
3840
- list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
3841
- partsByMessageId.set(part.message_id, list);
3842
- }
3843
- return messageRows.map((row) => {
3844
- const info = parseJsonRecord(row.data);
3845
- return {
3846
- ordinal: row.ordinal,
3847
- id: row.id,
3848
- role: typeof info?.role === "string" ? info.role : "unknown",
3849
- parts: partsByMessageId.get(row.id) ?? [],
3850
- createdAt: row.time_created ?? null,
3851
- version: row.time_updated ?? null
3852
- };
3853
- });
3854
- }
3855
- var RAW_SUMMARY_TEXT_MAX_CHARS = 8192;
3856
- var RAW_SUMMARY_ARG_MAX_CHARS = 512;
3857
- var RAW_SUMMARY_TOOL_INPUT_KEYS = [
3858
- "description",
3859
- "filePath",
3860
- "path",
3861
- "pattern",
3862
- "query",
3863
- "symbol",
3864
- "module",
3865
- "action"
3866
- ];
3867
- function summaryStringField(jsonPath) {
3868
- return `CASE WHEN json_type(data, '${jsonPath}') = 'text' THEN substr(json_extract(data, '${jsonPath}'), 1, ${RAW_SUMMARY_ARG_MAX_CHARS}) END`;
3869
- }
3870
- var RAW_SUMMARY_PART_DATA_SQL = `CASE
3871
- WHEN json_extract(data, '$.type') = 'text'
3872
- THEN json_set(data, '$.text', substr(json_extract(data, '$.text'), 1, ${RAW_SUMMARY_TEXT_MAX_CHARS}))
3873
- ELSE json_object(
3874
- 'type', 'tool',
3875
- 'tool', ${summaryStringField("$.tool")},
3876
- 'callID', ${summaryStringField("$.callID")},
3877
- 'state', json_object(
3878
- 'status', ${summaryStringField("$.state.status")},
3879
- 'input', json_object(${RAW_SUMMARY_TOOL_INPUT_KEYS.map((key) => `'${key}', ${summaryStringField(`$.state.input.${key}`)}`).join(", ")}),
3880
- 'metadata', json_object('description', ${summaryStringField("$.state.metadata.description")})
3881
- )
3882
- )
3883
- END`;
3884
- function readRawSessionMessageSummaryPageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER, after) {
3885
- const messageRows = readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark, after);
3886
- if (messageRows.length === 0)
3887
- return [];
3888
- const placeholders = messageRows.map(() => "?").join(", ");
3889
- const partRows = db.prepare(`SELECT message_id, ${RAW_SUMMARY_PART_DATA_SQL} AS data, time_updated
3890
- FROM part
3891
- WHERE +session_id = ?
3892
- AND likelihood(message_id IN (${placeholders}), 0.000001)
3893
- AND json_valid(data) = 1
3894
- AND json_extract(data, '$.type') IN ('text', 'tool')
3895
- ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
3896
- return assembleRawMessagePage(messageRows, partRows);
3897
- }
3898
- function countRawSessionMessageOrdinalsFromDb(db, sessionId) {
3899
- const row = db.prepare(`SELECT COUNT(*) AS count
3900
- FROM message
3901
- WHERE session_id = ?
3902
- AND NOT (
3903
- CASE WHEN json_valid(data) = 1
3904
- THEN COALESCE(json_extract(data, '$.summary'), 0)
3905
- ELSE 0 END = 1
3906
- AND CASE WHEN json_valid(data) = 1
3907
- THEN COALESCE(json_extract(data, '$.finish'), '')
3908
- ELSE '' END = 'stop'
3909
- )`).get(sessionId);
3910
- return typeof row?.count === "number" ? row.count : 0;
3911
- }
3912
- function readRawSessionMessageIdOrdinalsForRangeFromDb(db, sessionId, fromOrdinal, toOrdinal) {
3913
- const from = Math.max(1, Math.floor(fromOrdinal));
3914
- const to = Math.floor(toOrdinal);
3915
- if (to < from)
3916
- return new Map;
3917
- const rows = db.prepare(`
3918
- SELECT id, data FROM message WHERE session_id = ?
3919
- AND CASE WHEN json_valid(data) THEN NOT (
3920
- COALESCE(json_type(data, '$.summary'), '') = 'true'
3921
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
3922
- ) ELSE 1 END
3923
- ORDER BY time_created, id LIMIT ? OFFSET ?
3924
- `).all(sessionId, to - from + 1, from - 1).filter(isRawMessageRow);
3925
- const result = new Map;
3926
- for (const [index, row] of rows.entries()) {
3927
- if (parseJsonRecord(row.data))
3928
- result.set(row.id, from + index);
3929
- }
3930
- return result;
3931
- }
3932
- function isAnchorRow(row) {
3933
- return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
3934
- }
3935
- function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
3936
- const anchorRow = db.prepare("SELECT time_created, id, data FROM message WHERE id = ? AND session_id = ?").get(anchorMessageId, sessionId);
3937
- if (!isAnchorRow(anchorRow))
3938
- return null;
3939
- const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
3940
- if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
3941
- return null;
3942
- const messageRows = db.prepare(`SELECT id, data, time_created, time_updated FROM message
3943
- WHERE session_id = ?
3944
- AND (time_created > ? OR (time_created = ? AND id >= ?))
3945
- ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
3946
- const filtered = messageRows.filter((row) => {
3947
- const info = parseJsonRecord(row.data);
3948
- return !(info?.summary === true && info?.finish === "stop");
3949
- });
3950
- const ids = filtered.map((row) => row.id);
3951
- const partsByMessageId = new Map;
3952
- if (ids.length > 0) {
3953
- const CHUNK = 800;
3954
- for (let i = 0;i < ids.length; i += CHUNK) {
3955
- const slice = ids.slice(i, i + CHUNK);
3956
- const placeholders = slice.map(() => "?").join(",");
3957
- const partRows = db.prepare(`SELECT message_id, data, time_updated FROM part WHERE +session_id = ? AND likelihood(message_id IN (${placeholders}), 0.000001) ORDER BY time_created ASC, id ASC`).all(sessionId, ...slice).filter(isRawPartRow);
3958
- for (const part of partRows) {
3959
- const list = partsByMessageId.get(part.message_id) ?? [];
3960
- list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
3961
- partsByMessageId.set(part.message_id, list);
3962
- }
4416
+ const value = state[key];
4417
+ if (key === "time" && isRecord2(value)) {
4418
+ const keys = Object.keys(value);
4419
+ if (keys.length === 0)
4420
+ continue;
4421
+ if (keys.length === 1 && keys[0] === KEPT_TOOL_STATE_TIME_FIELD)
4422
+ continue;
4423
+ return false;
3963
4424
  }
3964
- }
3965
- const messages = [];
3966
- let ord = baseOrdinal;
3967
- for (const row of filtered) {
3968
- const info = parseJsonRecord(row.data);
3969
- if (!info) {
3970
- ord += 1;
3971
- continue;
4425
+ if (key === "metadata" && state.status === "error" && isRecord2(value)) {
4426
+ const extra = Object.keys(value).some((field) => !KEPT_ERROR_METADATA_FIELDS.includes(field));
4427
+ if (!extra)
4428
+ continue;
3972
4429
  }
3973
- messages.push({
3974
- ordinal: ord,
3975
- id: row.id,
3976
- role: typeof info.role === "string" ? info.role : "unknown",
3977
- parts: partsByMessageId.get(row.id) ?? [],
3978
- createdAt: row.time_created ?? null,
3979
- version: row.time_updated ?? null
3980
- });
3981
- ord += 1;
4430
+ return false;
3982
4431
  }
3983
- return { messages, absoluteMessageCount: Math.max(0, ord - 1) };
4432
+ return true;
3984
4433
  }
3985
- function extractInMemoryMessageViews(messages) {
3986
- return messages.map((m) => {
3987
- const info = m.info ?? {};
3988
- return {
3989
- id: typeof info.id === "string" ? info.id : "",
3990
- role: typeof info.role === "string" ? info.role : "unknown",
3991
- parts: Array.isArray(m.parts) ? m.parts : [],
3992
- summary: info.summary === true ? true : undefined,
3993
- finish: typeof info.finish === "string" ? info.finish : undefined
3994
- };
3995
- });
4434
+ function providerVisiblePart(part) {
4435
+ if (!isRecord2(part) || part.type !== "tool" || !isRecord2(part.state))
4436
+ return part;
4437
+ if (toolStateIsReduced(part.state))
4438
+ return part;
4439
+ return { ...part, state: providerVisibleToolState(part.state) };
3996
4440
  }
3997
- function buildInMemoryTailRawMessages(args) {
3998
- const { messages, lastCompartmentEnd, anchorMessageId } = args;
3999
- const filtered = messages.filter((m) => !(m.summary === true && m.finish === "stop"));
4000
- if (filtered.length === 0)
4001
- return null;
4002
- let startIndex = 0;
4003
- let baseOrdinal;
4004
- let anchorFound = false;
4005
- if (anchorMessageId) {
4006
- const anchorIndex = filtered.findIndex((m) => m.id === anchorMessageId);
4007
- if (anchorIndex >= 0) {
4008
- anchorFound = true;
4009
- startIndex = anchorIndex;
4010
- baseOrdinal = lastCompartmentEnd;
4011
- } else {
4012
- baseOrdinal = Math.max(1, lastCompartmentEnd + 1);
4013
- }
4014
- } else {
4015
- baseOrdinal = Math.max(1, lastCompartmentEnd + 1);
4016
- }
4017
- const out = [];
4018
- let ord = baseOrdinal;
4019
- for (let i = startIndex;i < filtered.length; i += 1) {
4020
- const m = filtered[i];
4021
- if (!m.id || typeof m.id !== "string") {
4022
- ord += 1;
4023
- continue;
4441
+ function providerVisibleMessage(message) {
4442
+ if (!isRecord2(message) || !Array.isArray(message.parts))
4443
+ return message;
4444
+ let parts;
4445
+ for (let index = 0;index < message.parts.length; index += 1) {
4446
+ const part = message.parts[index];
4447
+ const view = providerVisiblePart(part);
4448
+ if (view !== part) {
4449
+ parts ??= message.parts.slice(0, index);
4450
+ parts.push(view);
4451
+ } else if (parts) {
4452
+ parts.push(part);
4024
4453
  }
4025
- out.push({
4026
- ordinal: ord,
4027
- id: m.id,
4028
- role: typeof m.role === "string" ? m.role : "unknown",
4029
- parts: m.parts ?? [],
4030
- version: null
4031
- });
4032
- ord += 1;
4033
- }
4034
- return { messages: out, absoluteMessageCount: Math.max(0, ord - 1), anchorFound };
4035
- }
4036
- function readRawSessionMessageOrdinalByIdFromDb(db, sessionId, messageId) {
4037
- const row = db.prepare(`SELECT COUNT(candidate.id) AS ordinal
4038
- FROM message AS target
4039
- JOIN message AS candidate
4040
- ON candidate.session_id = target.session_id
4041
- AND NOT (
4042
- CASE WHEN json_valid(candidate.data) = 1
4043
- THEN COALESCE(json_extract(candidate.data, '$.summary'), 0)
4044
- ELSE 0 END = 1
4045
- AND CASE WHEN json_valid(candidate.data) = 1
4046
- THEN COALESCE(json_extract(candidate.data, '$.finish'), '')
4047
- ELSE '' END = 'stop'
4048
- )
4049
- AND (candidate.time_created < target.time_created
4050
- OR (candidate.time_created = target.time_created AND candidate.id <= target.id))
4051
- WHERE target.session_id = ?
4052
- AND target.id = ?
4053
- AND NOT (
4054
- CASE WHEN json_valid(target.data) = 1
4055
- THEN COALESCE(json_extract(target.data, '$.summary'), 0)
4056
- ELSE 0 END = 1
4057
- AND CASE WHEN json_valid(target.data) = 1
4058
- THEN COALESCE(json_extract(target.data, '$.finish'), '')
4059
- ELSE '' END = 'stop'
4060
- )`).get(sessionId, messageId);
4061
- const ordinal = row?.ordinal;
4062
- return typeof ordinal === "number" && ordinal > 0 ? ordinal : null;
4063
- }
4064
- function readRawSessionMessageByIdFromDb(db, sessionId, messageId) {
4065
- const row = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? AND id = ?").get(sessionId, messageId);
4066
- if (!row || !isRawMessageRow(row) || typeof row.time_created !== "number") {
4067
- return null;
4068
- }
4069
- const info = parseJsonRecord(row.data);
4070
- if (!info || isRawCompactionSummaryInfo(info)) {
4071
- return null;
4072
- }
4073
- const ordinalRow = db.prepare(`SELECT COUNT(*) AS ordinal FROM message
4074
- WHERE session_id = ?
4075
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
4076
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
4077
- AND (time_created < ? OR (time_created = ? AND id <= ?))`).get(sessionId, row.time_created, row.time_created, messageId);
4078
- const ordinal = typeof ordinalRow?.ordinal === "number" ? ordinalRow.ordinal : 0;
4079
- if (ordinal <= 0) {
4080
- return null;
4081
4454
  }
4082
- const partRows = db.prepare(RAW_MESSAGE_PARTS_BY_ID_SQL).all(sessionId, messageId).filter(isRawPartRow);
4083
- const role = typeof info.role === "string" ? info.role : "unknown";
4084
- return {
4085
- ordinal,
4086
- id: row.id,
4087
- role,
4088
- parts: partRows.map((part) => attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated)),
4089
- createdAt: row.time_created,
4090
- version: row.time_updated ?? null
4091
- };
4092
- }
4093
- function hasRawSessionMessageByIdFromDb(db, sessionId, messageId) {
4094
- const row = db.prepare("SELECT id, data, time_created FROM message WHERE session_id = ? AND id = ?").get(sessionId, messageId);
4095
- if (!row || !isRawMessageRow(row) || typeof row.time_created !== "number")
4096
- return false;
4097
- const info = parseJsonRecord(row.data);
4098
- if (!info || isRawCompactionSummaryInfo(info))
4099
- return false;
4100
- if (info.summary === 1 && info.finish === "stop")
4101
- return readRawSessionMessageByIdFromDb(db, sessionId, messageId) !== null;
4102
- return true;
4455
+ return parts ? { ...message, parts } : message;
4103
4456
  }
4104
4457
 
4105
4458
  // src/hooks/magic-context/read-session-true-raw-tokens.ts
@@ -4239,7 +4592,7 @@ function callIdFromPart2(part) {
4239
4592
  const state = isRecord(part.state) ? part.state : null;
4240
4593
  return state ? firstStringField(state, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
4241
4594
  }
4242
- function toolSignalFromPart(part) {
4595
+ function toolSignalFromPart(part, withText = true) {
4243
4596
  if (!isRecord(part))
4244
4597
  return null;
4245
4598
  const type = partType(part);
@@ -4258,8 +4611,8 @@ function toolSignalFromPart(part) {
4258
4611
  callId,
4259
4612
  hasInput: hasInput || openInvocation,
4260
4613
  hasOutput,
4261
- inputText: hasInput && state ? stringValue(state.input) : "",
4262
- outputText: hasOutput ? stringValue(outputValue) : ""
4614
+ inputText: withText && hasInput && state ? stringValue(state.input) : "",
4615
+ outputText: withText && hasOutput ? stringValue(outputValue) : ""
4263
4616
  };
4264
4617
  }
4265
4618
  if (type === "tool-invocation") {
@@ -4268,7 +4621,7 @@ function toolSignalFromPart(part) {
4268
4621
  callId,
4269
4622
  hasInput: args !== undefined,
4270
4623
  hasOutput: false,
4271
- inputText: args !== undefined ? stringValue(args) : "",
4624
+ inputText: withText && args !== undefined ? stringValue(args) : "",
4272
4625
  outputText: ""
4273
4626
  };
4274
4627
  }
@@ -4278,7 +4631,7 @@ function toolSignalFromPart(part) {
4278
4631
  callId,
4279
4632
  hasInput: input !== undefined,
4280
4633
  hasOutput: false,
4281
- inputText: input !== undefined ? stringValue(input) : "",
4634
+ inputText: withText && input !== undefined ? stringValue(input) : "",
4282
4635
  outputText: ""
4283
4636
  };
4284
4637
  }
@@ -4289,7 +4642,7 @@ function toolSignalFromPart(part) {
4289
4642
  hasInput: false,
4290
4643
  hasOutput: content !== undefined,
4291
4644
  inputText: "",
4292
- outputText: content !== undefined ? textFromToolResultContent(content) : ""
4645
+ outputText: withText && content !== undefined ? textFromToolResultContent(content) : ""
4293
4646
  };
4294
4647
  }
4295
4648
  return null;
@@ -4299,7 +4652,7 @@ function partCheapFingerprint(part) {
4299
4652
  return `${typeof part}:${recursiveByteLength(part)}`;
4300
4653
  const version = rawPartVersion(part);
4301
4654
  const type = typeof part.type === "string" ? part.type : "";
4302
- return `${type}:${String(version)}:${recursiveByteLength(part)}`;
4655
+ return `${type}:${String(version)}:${recursiveByteLength(providerVisiblePart(part))}`;
4303
4656
  }
4304
4657
  function messageCacheKey(message, options) {
4305
4658
  const namespace = "cacheNamespace" in options ? options.cacheNamespace : "estimate";
@@ -4419,7 +4772,7 @@ function buildToolArcs(messages) {
4419
4772
  const arcs = [];
4420
4773
  for (const message of messages) {
4421
4774
  for (const part of message.parts) {
4422
- const signal = toolSignalFromPart(part);
4775
+ const signal = toolSignalFromPart(part, false);
4423
4776
  if (!signal || signal.callId.length === 0)
4424
4777
  continue;
4425
4778
  if (signal.hasInput && signal.hasOutput) {
@@ -4787,11 +5140,11 @@ function containsDroppedInputPlaceholder(value) {
4787
5140
  };
4788
5141
  return visit(value);
4789
5142
  }
4790
- function isRecord2(value) {
5143
+ function isRecord3(value) {
4791
5144
  return value !== null && typeof value === "object";
4792
5145
  }
4793
5146
  function isOptionalZodField(field) {
4794
- if (!isRecord2(field))
5147
+ if (!isRecord3(field))
4795
5148
  return false;
4796
5149
  const isOptional = field.isOptional;
4797
5150
  if (typeof isOptional === "function") {
@@ -4803,10 +5156,10 @@ function isOptionalZodField(field) {
4803
5156
  return internals?.optin === "optional";
4804
5157
  }
4805
5158
  function toolParameterNames(schema) {
4806
- if (!isRecord2(schema))
5159
+ if (!isRecord3(schema))
4807
5160
  return;
4808
5161
  const properties = schema.properties;
4809
- if (isRecord2(properties) && !Array.isArray(properties)) {
5162
+ if (isRecord3(properties) && !Array.isArray(properties)) {
4810
5163
  const names = Object.keys(properties);
4811
5164
  const requiredList = Array.isArray(schema.required) ? schema.required : [];
4812
5165
  const required = new Set(requiredList.filter((name) => typeof name === "string"));
@@ -4821,7 +5174,7 @@ function toolParameterNames(schema) {
4821
5174
  } catch {
4822
5175
  shape = undefined;
4823
5176
  }
4824
- if (isRecord2(shape) && !Array.isArray(shape)) {
5177
+ if (isRecord3(shape) && !Array.isArray(shape)) {
4825
5178
  const result = { required: [], optional: [] };
4826
5179
  for (const [name, field] of Object.entries(shape)) {
4827
5180
  (isOptionalZodField(field) ? result.optional : result.required).push(name);
@@ -5680,6 +6033,15 @@ function makeWholeMessageSentinel(providerID) {
5680
6033
  text: modelAcceptsEmptyContent(providerID) ? "" : WHOLE_MESSAGE_PLACEHOLDER_TEXT
5681
6034
  };
5682
6035
  }
6036
+ function wholeMessageNeutralizationRemoves(message, providerID) {
6037
+ return message.info.role === "system" && modelAcceptsEmptyContent(providerID);
6038
+ }
6039
+ function neutralizeWholeMessage(message, providerID) {
6040
+ message.parts.length = 0;
6041
+ if (!wholeMessageNeutralizationRemoves(message, providerID)) {
6042
+ message.parts.push(makeWholeMessageSentinel(providerID));
6043
+ }
6044
+ }
5683
6045
  function isSentinel(part) {
5684
6046
  if (!isRecord(part))
5685
6047
  return false;
@@ -5707,8 +6069,9 @@ function replaySentinelByMessageIds(messages, ids, providerID, hiddenSeamIds = n
5707
6069
  }
5708
6070
  if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
5709
6071
  continue;
5710
- msg.parts.length = 0;
5711
- msg.parts.push(makeWholeMessageSentinel(providerID));
6072
+ if (wholeMessageNeutralizationRemoves(msg, providerID) && msg.parts.length === 0)
6073
+ continue;
6074
+ neutralizeWholeMessage(msg, providerID);
5712
6075
  replayed += 1;
5713
6076
  }
5714
6077
  const missingIds = [];
@@ -6149,6 +6512,10 @@ function createToolDropTarget(compositeKey, thinkingParts, index, batch, tagId)
6149
6512
  return false;
6150
6513
  return batch.wouldStrandConversationEnd(entry.occurrences);
6151
6514
  },
6515
+ prepareDrop: () => {
6516
+ const entry = index.get(compositeKey);
6517
+ return !!entry && entry.occurrences.length > 0 && entry.hasResult;
6518
+ },
6152
6519
  canDrop: () => {
6153
6520
  const entry = index.get(compositeKey);
6154
6521
  return !!entry && entry.occurrences.length > 0 && entry.hasResult && !entry.occurrences.some((occurrence) => toolPartHasUserAnswer(occurrence.part));
@@ -6422,6 +6789,14 @@ function readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal) {
6422
6789
  }
6423
6790
  readRawSessionMessages2.readPage = readRawSessionMessagePage2;
6424
6791
  readRawSessionMessages2.getCount = getRawSessionMessageOrdinalCount2;
6792
+ readRawSessionMessages2.prepare = prepareRawSessionOrdinals2;
6793
+ async function prepareRawSessionOrdinals2(sessionId) {
6794
+ if (sessionProviders.get(sessionId)?.provider)
6795
+ return true;
6796
+ if (!openCodeDbExists())
6797
+ return true;
6798
+ return withReadOnlySessionDb((db) => warmRawSessionOrdinalsForDb(db, sessionId));
6799
+ }
6425
6800
  function primeTailRawMessageCache2(args) {
6426
6801
  const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
6427
6802
  if (!activeRawMessageCache)
@@ -6573,6 +6948,7 @@ function readRawSessionMessageById2(sessionId, messageId) {
6573
6948
  return null;
6574
6949
  return withReadOnlySessionDb((db) => readRawSessionMessageByIdFromDb(db, sessionId, messageId));
6575
6950
  }
6951
+ readRawSessionMessageById2.prepare = prepareRawSessionOrdinals2;
6576
6952
  function readRawSessionMessagesFromSource(sessionId) {
6577
6953
  const provider = sessionProviders.get(sessionId)?.provider;
6578
6954
  if (provider)
@@ -6953,6 +7329,14 @@ function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdina
6953
7329
  pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
6954
7330
  }
6955
7331
  if (flushCurrentBlock() && pendingNoiseMeta.length > 0) {
7332
+ const lastNoise = pendingNoiseMeta[pendingNoiseMeta.length - 1];
7333
+ if (messagesProcessed > 0 && lastNoise) {
7334
+ lineMeta.push(...pendingNoiseMeta);
7335
+ messagesProcessed += pendingNoiseMeta.length;
7336
+ lastOrdinal = lastNoise.ordinal;
7337
+ lastMessageId = lastNoise.messageId;
7338
+ pendingNoiseMeta = [];
7339
+ }
6956
7340
  highestScannedOrdinal = Math.max(highestScannedOrdinal, pendingNoiseMeta[pendingNoiseMeta.length - 1]?.ordinal ?? highestScannedOrdinal);
6957
7341
  }
6958
7342
  const toolOnlyRanges = [];
@@ -6990,4 +7374,4 @@ function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdina
6990
7374
  toolResultBoundaries
6991
7375
  };
6992
7376
  }
6993
- export { toolTemplateError, DEFAULT_PROTECTED_TOOLS, normalizeProtectedToolName, mergeProtectedTools, isRecord, detectLatestTurnThinkingMismatch, isPrefixBoundThinkingModel, detectOverflow, protectedToolTagNumbers, protectedToolTokenCount, textMentionsRecentCommit, removeSystemReminders, hasMeaningfulUserText2, extractTexts2, getTokenizerNativeMemoryStats, preloadTokenizer, estimateTokens, estimateFixedPromptTokens, stripWellFormedLeadingTagPrefix, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, stableStringify, contentTagOwnerMessageId, estimateImageTokensFromDataUrl, estimateToolAttachmentImageTokens, normalizeTodoStateJson, buildSyntheticTodoPart, isSyntheticTodoPart, countRealUserMessages, tailHygieneStructuralSignature, sameTailHygieneStructuralSignature, formatTailHygienePrefixMismatch, refreshTailHygieneBaseline, effectiveTailHygiene, assertTailHygieneContentUnchangedIfEnabled, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, isDroppedToolOutput, toolOutputTokens, decideChannel1, evaluateChannel2, formatChannel1Evaluation, formatChannel2Evaluation, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, estimateEmergencyDropReclaimTokens, planEmergencyDrop, measureEmergencyTag, installV3PerfSchema, queuePendingOp, queuePendingDropForUnchangedTag, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, getAllStatusTagTokenTotalsFlat, getReasoningTokenEstimatesByMessage, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, markWhitespaceAssistantTagInert, getInertWhitespaceAssistantTags, updateTagDropMode, updateCavemanDepth, updateTagMessageId, foldShrunkPartTags, markTagsCompactedByMessageIds, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, TAG_SELECT_COLUMNS, getTagsBySession, getActiveTagsBySession, getTailHygieneTags, getTagsByNumbers, getNewestToolTagNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getTagById, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, expandToolPart, markHostUnservedRow, retreatPastHostUnservedRows, snapTerminalCompartmentToServedRow, isHostRenderedSystemMessage, isStrictGapHealingMessage, extractInMemoryMessageViews, buildInMemoryTailRawMessages, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, stripSystemInjection, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, toolPartHasUserAnswer, recordToolParameters, createDroppedInputGuard, assertExecutableToolInput, isEditTool, getCurrentToolSetHash, setDatabase, loadToolDefinitionMeasurements, recordToolDefinition, getMeasuredToolDefinitionTokens, describeFinalWireTail, estimateMessageTokens, wireContentBytes, createFinalWireUsageTracker, estimateFinalWireInputTokens, modelAcceptsEmptyContent, isAnthropicFamilyRoute, neutralizeDroppedReasoningPart, restoreNeutralizedReasoningPart, isNeutralizedReasoningPart, neutralizedReasoningSource, variantChangeBustsProviderCache, makeSentinel, makeWholeMessageSentinel, isSentinel, replaySentinelByMessageIds, SKELETON_REAL_INPUT_MAX_BYTES, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, resolveHostServedBoundaryId2, hasRawMessageProvider2, setBoundedRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, visitRawSessionMessages2, readRawSessionMessageRange2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageIdOrdinalsForRange2, hasRawSessionMessageById2, readRawSessionMessageOrdinalById2, compareRawSessionMessageOrder2, readRawSessionMessageById2, getRawSessionMessageCount2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, readSessionChunk2 };
7377
+ export { toolTemplateError, DEFAULT_PROTECTED_TOOLS, normalizeProtectedToolName, mergeProtectedTools, isRecord, protectedToolTagNumbers, protectedToolTokenCount, textMentionsRecentCommit, removeSystemReminders, hasMeaningfulUserText2, extractTexts2, getTokenizerNativeMemoryStats, preloadTokenizer, estimateTokens, estimateFixedPromptTokens, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, stableStringify, contentTagOwnerMessageId, estimateImageTokensFromDataUrl, estimateToolAttachmentImageTokens, normalizeTodoStateJson, buildSyntheticTodoPart, isSyntheticTodoPart, countRealUserMessages, tailHygieneStructuralSignature, sameTailHygieneStructuralSignature, formatTailHygienePrefixMismatch, refreshTailHygieneBaseline, effectiveTailHygiene, assertTailHygieneContentUnchangedIfEnabled, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, isDroppedToolOutput, toolOutputTokens, decideChannel1, evaluateChannel2, formatChannel1Evaluation, formatChannel2Evaluation, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, estimateEmergencyDropReclaimTokens, planEmergencyDrop, measureEmergencyTag, installV3PerfSchema, queuePendingOp, queuePendingDropForUnchangedTag, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, tagTombstoneOwnerRange, tagTombstoneOwnerKey, tagRevisionKey, tagIdentityRevisionKey, installTagIdentityRevisionTrigger, deleteTagIdentityRevisions, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, getAllStatusTagTokenTotalsFlat, getReasoningTokenEstimatesByMessage, tryGetReasoningTokenEstimatesByMessage, getMaxTagNumberByOwnerMessage, scanTagOwnerSummary, isTagOwnerSummaryReady, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, markWhitespaceAssistantTagInert, getInertWhitespaceAssistantTags, getInertWhitespaceAssistantTagsByNumbers, updateTagDropMode, updateCavemanDepth, updateTagMessageId, foldShrunkPartTags, markTagsCompactedByMessageIds, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, TAG_SELECT_COLUMNS, getTagsBySession, getActiveTagsBySession, getTailHygieneTags, getTagsByNumbers, getNewestToolTagNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getTagById, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, expandToolPart, markHostUnservedRow, retreatPastHostUnservedRows, snapTerminalCompartmentToServedRow, isHostRenderedSystemMessage, providerVisibleMessage, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, stripSystemInjection, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, toolPartHasUserAnswer, recordToolParameters, createDroppedInputGuard, assertExecutableToolInput, isEditTool, getCurrentToolSetHash, setDatabase, loadToolDefinitionMeasurements, recordToolDefinition, getMeasuredToolDefinitionTokens, describeFinalWireTail, estimateMessageTokens, wireContentBytes, createFinalWireUsageTracker, estimateFinalWireInputTokens, detectLatestTurnThinkingMismatch, isPrefixBoundThinkingModel, detectOverflow, modelAcceptsEmptyContent, isAnthropicFamilyRoute, neutralizeDroppedReasoningPart, restoreNeutralizedReasoningPart, isNeutralizedReasoningPart, neutralizedReasoningSource, variantChangeBustsProviderCache, makeSentinel, makeWholeMessageSentinel, neutralizeWholeMessage, isSentinel, replaySentinelByMessageIds, SKELETON_REAL_INPUT_MAX_BYTES, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, resolveHostServedBoundaryId2, hasRawMessageProvider2, setBoundedRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, visitRawSessionMessages2, readRawSessionMessageRange2, prepareRawSessionOrdinals2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageIdOrdinalsForRange2, hasRawSessionMessageById2, readRawSessionMessageOrdinalById2, compareRawSessionMessageOrder2, readRawSessionMessageById2, getRawSessionMessageCount2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, readSessionChunk2 };