@cortexkit/pi-magic-context 0.42.6 → 0.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4653 @@
1
+ import {
2
+ getHarness,
3
+ log
4
+ } from "./index-bfd52y8p.js";
5
+
6
+ // ../plugin/src/features/magic-context/reclaim-protection.ts
7
+ var CTX_REDUCE_KEEP = 3;
8
+ function newestCtxReduceTagNumbers(tags) {
9
+ return new Set(tags.filter((tag) => tag.toolName === "ctx_reduce").sort((left, right) => right.tagNumber - left.tagNumber).slice(0, CTX_REDUCE_KEEP).map((tag) => tag.tagNumber));
10
+ }
11
+
12
+ // ../plugin/src/hooks/magic-context/read-session-formatting.ts
13
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
14
+ import { createRequire } from "node:module";
15
+ import { homedir } from "node:os";
16
+ import { dirname, join, resolve } from "node:path";
17
+ import { pathToFileURL } from "node:url";
18
+
19
+ // ../plugin/src/shared/commit-detection.ts
20
+ var HASH_HEX = "[0-9a-f]{7,12}";
21
+ var COMMIT_HASH_TEST_PATTERN = new RegExp(`\\b${HASH_HEX}\\b`, "i");
22
+ var COMMIT_VERB_PATTERN = /\b(?:commit(?:ted|ting|s)?|cherry-?pick(?:ed|ing|s)?|merge[ds]?|merging|rebas(?:e|ed|es|ing))\b/i;
23
+ function textMentionsRecentCommit(text) {
24
+ return COMMIT_HASH_TEST_PATTERN.test(text) && COMMIT_VERB_PATTERN.test(text);
25
+ }
26
+ function createCommitHashExtractPattern() {
27
+ return new RegExp(`\`?\\b(${HASH_HEX})\\b\`?`, "gi");
28
+ }
29
+
30
+ // ../plugin/src/shared/internal-initiator-marker.ts
31
+ var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
32
+
33
+ // ../plugin/src/shared/system-directive.ts
34
+ var SYSTEM_DIRECTIVE_PREFIX = "[SYSTEM DIRECTIVE: MAGIC-CONTEXT";
35
+ function isSystemDirective(text) {
36
+ return text.trimStart().startsWith(SYSTEM_DIRECTIVE_PREFIX);
37
+ }
38
+ function removeSystemReminders(text) {
39
+ return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
40
+ }
41
+
42
+ // ../plugin/src/hooks/magic-context/read-session-formatting.ts
43
+ var MAX_COMMITS_PER_BLOCK = 5;
44
+ function hasMeaningfulUserText2(parts) {
45
+ for (const part of parts) {
46
+ if (part === null || typeof part !== "object")
47
+ continue;
48
+ const candidate = part;
49
+ if (candidate.type !== "text" || typeof candidate.text !== "string")
50
+ continue;
51
+ if (candidate.ignored === true)
52
+ continue;
53
+ const cleaned = removeSystemReminders(candidate.text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
54
+ if (!cleaned)
55
+ continue;
56
+ if (isSystemDirective(cleaned))
57
+ continue;
58
+ return true;
59
+ }
60
+ return false;
61
+ }
62
+ function extractTexts2(parts) {
63
+ const texts = [];
64
+ for (const part of parts) {
65
+ if (part === null || typeof part !== "object")
66
+ continue;
67
+ const p = part;
68
+ if (p.type === "text" && typeof p.text === "string" && p.text.trim().length > 0) {
69
+ texts.push(p.text.trim());
70
+ }
71
+ }
72
+ return texts;
73
+ }
74
+ function extractToolResultBodyTokens(parts) {
75
+ let tokens = 0;
76
+ for (const part of parts) {
77
+ if (part === null || typeof part !== "object")
78
+ continue;
79
+ const p = part;
80
+ if (p.type !== "tool")
81
+ continue;
82
+ const state = p.state;
83
+ if (!state || typeof state !== "object")
84
+ continue;
85
+ const body = state.output ?? state.error;
86
+ if (body === undefined)
87
+ continue;
88
+ const text = typeof body === "string" ? body : JSON.stringify(body);
89
+ tokens += Math.ceil(text.length / 4);
90
+ }
91
+ return tokens;
92
+ }
93
+ function extractToolCallSummaries(parts) {
94
+ const summaries = [];
95
+ for (const part of parts) {
96
+ if (part === null || typeof part !== "object")
97
+ continue;
98
+ const p = part;
99
+ if (p.type !== "tool" || typeof p.tool !== "string")
100
+ continue;
101
+ const state = p.state;
102
+ if (!state || typeof state !== "object")
103
+ continue;
104
+ const input = state.input;
105
+ const metadata = state.metadata;
106
+ const description = input && typeof input.description === "string" && input.description || metadata && typeof metadata.description === "string" && metadata.description;
107
+ if (description) {
108
+ summaries.push(`TC: ${description}`);
109
+ continue;
110
+ }
111
+ const toolName = p.tool;
112
+ const keyArg = extractKeyArg(toolName, input);
113
+ summaries.push(keyArg ? `TC: ${toolName}(${keyArg})` : `TC: ${toolName}`);
114
+ }
115
+ return summaries;
116
+ }
117
+ function extractKeyArg(_toolName, input) {
118
+ if (!input)
119
+ return null;
120
+ if (typeof input.filePath === "string")
121
+ return truncateArg(input.filePath);
122
+ if (typeof input.path === "string")
123
+ return truncateArg(input.path);
124
+ if (typeof input.pattern === "string")
125
+ return truncateArg(input.pattern);
126
+ if (typeof input.query === "string")
127
+ return truncateArg(input.query);
128
+ if (typeof input.symbol === "string")
129
+ return input.symbol;
130
+ if (typeof input.module === "string")
131
+ return input.module;
132
+ if (typeof input.action === "string")
133
+ return input.action;
134
+ return null;
135
+ }
136
+ function truncateArg(value, maxLen = 60) {
137
+ if (value.length <= maxLen)
138
+ return value;
139
+ return `${value.slice(0, maxLen)}…`;
140
+ }
141
+ var TOKENIZER_PACKAGE_DIRS = [
142
+ ["@cortexkit", "opencode-magic-context"],
143
+ ["@cortexkit", "pi-magic-context"]
144
+ ];
145
+ var tokenizer;
146
+ var tokenizerLoadAttempted = false;
147
+ var tokenizerLoadPromise;
148
+ var tokenizerWarningSent = false;
149
+ var tokenizerEncodingPath;
150
+ var tokenizerSerializedTableBytes;
151
+ function tokenizerPackageRoots() {
152
+ const cwd = process.cwd();
153
+ const openCodeCache = join(process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "opencode");
154
+ const roots = [cwd, openCodeCache];
155
+ const candidates = [];
156
+ for (const root of roots) {
157
+ for (const packageDir of TOKENIZER_PACKAGE_DIRS) {
158
+ candidates.push(join(root, "node_modules", ...packageDir, "node_modules", "ai-tokenizer"));
159
+ }
160
+ candidates.push(join(root, "node_modules", "ai-tokenizer"));
161
+ }
162
+ let ancestor = process.argv[1] ? dirname(resolve(process.argv[1])) : cwd;
163
+ while (true) {
164
+ candidates.push(join(ancestor, "node_modules", "ai-tokenizer"));
165
+ const parent = dirname(ancestor);
166
+ if (parent === ancestor)
167
+ break;
168
+ ancestor = parent;
169
+ }
170
+ return [...new Set(candidates)];
171
+ }
172
+ function packageImportTarget(value) {
173
+ if (typeof value === "string")
174
+ return value;
175
+ if (!value || typeof value !== "object")
176
+ return;
177
+ const conditions = value;
178
+ return packageImportTarget(conditions.import) ?? packageImportTarget(conditions.default);
179
+ }
180
+ function findTokenizerImportPaths() {
181
+ for (const packageRoot of tokenizerPackageRoots()) {
182
+ const packageJsonPath = join(packageRoot, "package.json");
183
+ if (!existsSync(packageJsonPath))
184
+ continue;
185
+ try {
186
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
187
+ const tokenizerTarget = packageImportTarget(packageJson.exports?.["."]) ?? (typeof packageJson.module === "string" ? packageJson.module : undefined) ?? (typeof packageJson.main === "string" ? packageJson.main : undefined);
188
+ const encodingTarget = packageImportTarget(packageJson.exports?.["./encoding/claude"]);
189
+ if (!tokenizerTarget || !encodingTarget)
190
+ continue;
191
+ return {
192
+ tokenizerPath: realpathSync(join(packageRoot, tokenizerTarget)),
193
+ encodingPath: realpathSync(join(packageRoot, encodingTarget))
194
+ };
195
+ } catch {}
196
+ }
197
+ return;
198
+ }
199
+ function constructTokenizer(tokenizerModule, claudeEncoding) {
200
+ const typedModule = tokenizerModule;
201
+ const Tokenizer = typedModule.default ?? typedModule.Tokenizer;
202
+ if (!Tokenizer) {
203
+ throw new Error("ai-tokenizer does not expose a Tokenizer constructor");
204
+ }
205
+ return new Tokenizer(claudeEncoding);
206
+ }
207
+ function loadTokenizer() {
208
+ const requireFromThisModule = createRequire(import.meta.url);
209
+ const encodingSpecifier = "ai-tokenizer/encoding/" + "claude";
210
+ tokenizerEncodingPath = requireFromThisModule.resolve(encodingSpecifier);
211
+ tokenizerSerializedTableBytes = undefined;
212
+ return constructTokenizer(requireFromThisModule("ai-" + "tokenizer"), requireFromThisModule(encodingSpecifier));
213
+ }
214
+ async function loadTokenizerFromInstalledPackage() {
215
+ const installedPaths = findTokenizerImportPaths();
216
+ if (!installedPaths) {
217
+ throw new Error("ai-tokenizer was not found under the project, runtime, or OpenCode cache node_modules roots");
218
+ }
219
+ const [tokenizerModule, claudeEncoding] = await Promise.all([
220
+ import(pathToFileURL(installedPaths.tokenizerPath).href),
221
+ import(pathToFileURL(installedPaths.encodingPath).href)
222
+ ]);
223
+ tokenizerEncodingPath = installedPaths.encodingPath;
224
+ tokenizerSerializedTableBytes = undefined;
225
+ return constructTokenizer(tokenizerModule, claudeEncoding);
226
+ }
227
+ function warnTokenizerFallback(error) {
228
+ if (tokenizerWarningSent)
229
+ return;
230
+ tokenizerWarningSent = true;
231
+ const reason = error instanceof Error ? error.message : String(error);
232
+ console.warn("[magic-context] ai-tokenizer is unavailable; using approximate character-based token counts for this process. Token budgets, persisted per-message counts, and protected-tail/compartment boundaries may be less accurate until restart:", reason);
233
+ }
234
+ async function preloadTokenizer() {
235
+ if (tokenizer)
236
+ return true;
237
+ if (tokenizerLoadAttempted)
238
+ return false;
239
+ if (tokenizerLoadPromise)
240
+ return tokenizerLoadPromise;
241
+ tokenizerLoadPromise = (async () => {
242
+ try {
243
+ try {
244
+ tokenizer = loadTokenizer();
245
+ } catch {
246
+ tokenizer = await loadTokenizerFromInstalledPackage();
247
+ }
248
+ tokenizerLoadAttempted = true;
249
+ return true;
250
+ } catch (error) {
251
+ tokenizerLoadAttempted = true;
252
+ warnTokenizerFallback(error);
253
+ return false;
254
+ } finally {
255
+ tokenizerLoadPromise = undefined;
256
+ }
257
+ })();
258
+ return tokenizerLoadPromise;
259
+ }
260
+ function getTokenizer() {
261
+ if (tokenizer || tokenizerLoadAttempted)
262
+ return tokenizer;
263
+ tokenizerLoadAttempted = true;
264
+ try {
265
+ tokenizer = loadTokenizer();
266
+ } catch (error) {
267
+ warnTokenizerFallback(error);
268
+ }
269
+ return tokenizer;
270
+ }
271
+ function estimateTokensHeuristically(text) {
272
+ return Math.ceil(text.length / 3.5);
273
+ }
274
+ function estimateTokens(text) {
275
+ if (!text)
276
+ return 0;
277
+ const activeTokenizer = getTokenizer();
278
+ if (!activeTokenizer)
279
+ return estimateTokensHeuristically(text);
280
+ try {
281
+ return activeTokenizer.encode(text, "all").length;
282
+ } catch (error) {
283
+ tokenizer = undefined;
284
+ tokenizerLoadAttempted = true;
285
+ warnTokenizerFallback(error);
286
+ return estimateTokensHeuristically(text);
287
+ }
288
+ }
289
+ function normalizeText(text) {
290
+ return text.replace(/\s+/g, " ").trim();
291
+ }
292
+ function compactRole(role) {
293
+ if (role === "assistant")
294
+ return "A";
295
+ if (role === "user")
296
+ return "U";
297
+ return role.slice(0, 1).toUpperCase() || "M";
298
+ }
299
+ function formatBlock(block) {
300
+ const range = block.startOrdinal === block.endOrdinal ? `[${block.startOrdinal}]` : `[${block.startOrdinal}-${block.endOrdinal}]`;
301
+ const commitSuffix = block.commitHashes.length > 0 ? ` commits: ${block.commitHashes.join(", ")}` : "";
302
+ return `${range} ${block.role}:${commitSuffix} ${block.parts.join(" / ")}`;
303
+ }
304
+ function extractCommitHashes(text) {
305
+ const hashes = [];
306
+ const seen = new Set;
307
+ for (const match of text.matchAll(createCommitHashExtractPattern())) {
308
+ const hash = match[1]?.toLowerCase();
309
+ if (!hash || seen.has(hash))
310
+ continue;
311
+ seen.add(hash);
312
+ hashes.push(hash);
313
+ if (hashes.length >= MAX_COMMITS_PER_BLOCK)
314
+ break;
315
+ }
316
+ return hashes;
317
+ }
318
+ function compactTextForSummary(text, role) {
319
+ const commitHashes = role === "assistant" ? extractCommitHashes(text) : [];
320
+ if (commitHashes.length === 0 || !COMMIT_VERB_PATTERN.test(text)) {
321
+ return { text, commitHashes };
322
+ }
323
+ const withoutHashes = text.replace(createCommitHashExtractPattern(), "").replace(/\(\s*\)/g, "").replace(/\s+,/g, ",").replace(/,\s*,+/g, ", ").replace(/\s{2,}/g, " ").replace(/\s+([,.;:])/g, "$1").trim();
324
+ return {
325
+ text: withoutHashes.length > 0 ? withoutHashes : text,
326
+ commitHashes
327
+ };
328
+ }
329
+ function mergeCommitHashes(existing, next) {
330
+ if (next.length === 0)
331
+ return existing;
332
+ const merged = [...existing];
333
+ for (const hash of next) {
334
+ if (merged.includes(hash))
335
+ continue;
336
+ merged.push(hash);
337
+ if (merged.length >= MAX_COMMITS_PER_BLOCK)
338
+ break;
339
+ }
340
+ return merged;
341
+ }
342
+
343
+ // ../plugin/src/hooks/magic-context/tag-content-primitives.ts
344
+ var encoder = new TextEncoder;
345
+ var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
346
+ var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
347
+ var DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
348
+ var DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
349
+ var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
350
+ var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
351
+ var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
352
+ function stripWellFormedLeadingTagPrefix(value) {
353
+ return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
354
+ }
355
+ function stripCompleteTagPairsGlobally(value) {
356
+ return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
357
+ }
358
+ function stripMalformedTagNotationGlobally(value) {
359
+ return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
360
+ }
361
+ function stripDanglingTagNotationGlobally(value) {
362
+ return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
363
+ }
364
+ function stripTagSectionCharacters(value) {
365
+ return value.replace(STRAY_SECTION_CHAR_REGEX, "");
366
+ }
367
+ function stripPersistedAssistantText(value) {
368
+ let text = stripWellFormedLeadingTagPrefix(value);
369
+ text = stripCompleteTagPairsGlobally(text);
370
+ text = stripMalformedTagNotationGlobally(text);
371
+ text = stripDanglingTagNotationGlobally(text);
372
+ text = stripTagSectionCharacters(text);
373
+ return text.trim();
374
+ }
375
+ function byteSize(value) {
376
+ return encoder.encode(value).length;
377
+ }
378
+ function stripTagPrefix(value) {
379
+ let stripped = value;
380
+ for (let pass = 0;pass < 8; pass++) {
381
+ const prev = stripped;
382
+ stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
383
+ stripped = stripped.replace(TAG_PREFIX_REGEX, "");
384
+ stripped = stripped.replace(DANGLING_TAG_PREFIX_REGEX, "");
385
+ if (stripped === prev)
386
+ break;
387
+ }
388
+ return stripped;
389
+ }
390
+ function peelLeadingMcTagNotation(value) {
391
+ const body = stripTagPrefix(value);
392
+ if (body === value)
393
+ return { tagPrefix: "", body };
394
+ return { tagPrefix: value.slice(0, value.length - body.length), body };
395
+ }
396
+ function prependTag(tagId, value) {
397
+ const stripped = stripTagPrefix(value);
398
+ return `§${tagId}§ ${stripped}`;
399
+ }
400
+
401
+ // ../plugin/src/shared/record-type-guard.ts
402
+ function isRecord(value) {
403
+ return typeof value === "object" && value !== null && !Array.isArray(value);
404
+ }
405
+
406
+ // ../plugin/src/shared/stable-json.ts
407
+ function stableStringify(value, seen = new WeakSet) {
408
+ if (value === undefined)
409
+ return "undefined";
410
+ if (value === null || typeof value !== "object")
411
+ return JSON.stringify(value) ?? String(value);
412
+ if (seen.has(value))
413
+ return '"[Circular]"';
414
+ seen.add(value);
415
+ if (Array.isArray(value)) {
416
+ return `[${value.map((item) => stableStringify(item, seen)).join(",")}]`;
417
+ }
418
+ const entries = Object.entries(value).sort(([a], [b]) => {
419
+ if (a < b)
420
+ return -1;
421
+ if (a > b)
422
+ return 1;
423
+ return 0;
424
+ });
425
+ return `{${entries.map(([key, child]) => `${JSON.stringify(key)}:${stableStringify(child, seen)}`).join(",")}}`;
426
+ }
427
+
428
+ // ../plugin/src/hooks/magic-context/image-token-estimate.ts
429
+ var IMAGE_TOKEN_DIVISOR = 750;
430
+ var IMAGE_FALLBACK_TOKENS = 1200;
431
+ var IMAGE_TOKEN_CAP = 4500;
432
+ function estimateImageTokensFromDataUrl(url) {
433
+ const comma = url.indexOf(",");
434
+ if (comma < 0)
435
+ return IMAGE_FALLBACK_TOKENS;
436
+ const header = url.slice(0, comma);
437
+ const payload = url.slice(comma + 1);
438
+ const sliceLen = Math.min(512, payload.length);
439
+ const preview = payload.slice(0, sliceLen);
440
+ let bytes;
441
+ try {
442
+ bytes = base64Decode(preview);
443
+ } catch {
444
+ return IMAGE_FALLBACK_TOKENS;
445
+ }
446
+ if (header.includes("image/png")) {
447
+ const dims = parsePngDimensions(bytes);
448
+ if (dims)
449
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
450
+ } else if (header.includes("image/jpeg") || header.includes("image/jpg")) {
451
+ const dims = parseJpegDimensions(bytes);
452
+ if (dims)
453
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
454
+ } else if (header.includes("image/webp")) {
455
+ const dims = parseWebpDimensions(bytes);
456
+ if (dims)
457
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
458
+ } else if (header.includes("image/gif")) {
459
+ const dims = parseGifDimensions(bytes);
460
+ if (dims)
461
+ return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
462
+ }
463
+ return IMAGE_FALLBACK_TOKENS;
464
+ }
465
+ function clampImageTokens(n) {
466
+ if (n < 1)
467
+ return 1;
468
+ if (n > IMAGE_TOKEN_CAP)
469
+ return IMAGE_TOKEN_CAP;
470
+ return n;
471
+ }
472
+ function base64Decode(b64) {
473
+ const pad = b64.length % 4;
474
+ const padded = pad === 0 ? b64 : b64 + "=".repeat(4 - pad);
475
+ const binary = atob(padded);
476
+ const out = new Uint8Array(binary.length);
477
+ for (let i = 0;i < binary.length; i++)
478
+ out[i] = binary.charCodeAt(i);
479
+ return out;
480
+ }
481
+ function parsePngDimensions(b) {
482
+ if (b.length < 24)
483
+ return null;
484
+ if (b[0] !== 137 || b[1] !== 80 || b[2] !== 78 || b[3] !== 71 || b[4] !== 13 || b[5] !== 10 || b[6] !== 26 || b[7] !== 10)
485
+ return null;
486
+ const w = readUint32BE(b, 16);
487
+ const h = readUint32BE(b, 20);
488
+ if (!w || !h)
489
+ return null;
490
+ return { w, h };
491
+ }
492
+ function parseJpegDimensions(b) {
493
+ if (b.length < 4 || b[0] !== 255 || b[1] !== 216)
494
+ return null;
495
+ let i = 2;
496
+ while (i < b.length - 8) {
497
+ if (b[i] !== 255) {
498
+ i++;
499
+ continue;
500
+ }
501
+ const marker = b[i + 1];
502
+ if (marker === undefined)
503
+ break;
504
+ if (isSofMarker(marker)) {
505
+ const h = b[i + 5] << 8 | b[i + 6];
506
+ const w = b[i + 7] << 8 | b[i + 8];
507
+ if (w && h)
508
+ return { w, h };
509
+ return null;
510
+ }
511
+ if (marker === 216 || marker === 217 || marker === 1) {
512
+ i += 2;
513
+ continue;
514
+ }
515
+ const segLen = b[i + 2] << 8 | b[i + 3];
516
+ if (segLen < 2)
517
+ return null;
518
+ i += 2 + segLen;
519
+ }
520
+ return null;
521
+ }
522
+ function isSofMarker(m) {
523
+ if (m >= 192 && m <= 195)
524
+ return true;
525
+ if (m >= 197 && m <= 199)
526
+ return true;
527
+ if (m >= 201 && m <= 203)
528
+ return true;
529
+ if (m >= 205 && m <= 207)
530
+ return true;
531
+ return false;
532
+ }
533
+ function parseWebpDimensions(b) {
534
+ if (b.length < 30)
535
+ return null;
536
+ if (b[0] !== 82 || b[1] !== 73 || b[2] !== 70 || b[3] !== 70)
537
+ return null;
538
+ if (b[8] !== 87 || b[9] !== 69 || b[10] !== 66 || b[11] !== 80)
539
+ return null;
540
+ const variant = String.fromCharCode(b[12], b[13], b[14], b[15]);
541
+ if (variant === "VP8 ") {
542
+ const w = (b[26] | b[27] << 8) & 16383;
543
+ const h = (b[28] | b[29] << 8) & 16383;
544
+ if (w && h)
545
+ return { w, h };
546
+ } else if (variant === "VP8L") {
547
+ const b0 = b[21];
548
+ const b1 = b[22];
549
+ const b2 = b[23];
550
+ const b3 = b[24];
551
+ const w = 1 + ((b0 | b1 << 8) & 16383);
552
+ const h = 1 + ((b1 >> 6 | b2 << 2 | b3 << 10) & 16383);
553
+ if (w && h)
554
+ return { w, h };
555
+ } else if (variant === "VP8X") {
556
+ const w = 1 + (b[24] | b[25] << 8 | b[26] << 16);
557
+ const h = 1 + (b[27] | b[28] << 8 | b[29] << 16);
558
+ if (w && h)
559
+ return { w, h };
560
+ }
561
+ return null;
562
+ }
563
+ function parseGifDimensions(b) {
564
+ if (b.length < 10)
565
+ return null;
566
+ if (b[0] !== 71 || b[1] !== 73 || b[2] !== 70)
567
+ return null;
568
+ const w = b[6] | b[7] << 8;
569
+ const h = b[8] | b[9] << 8;
570
+ if (!w || !h)
571
+ return null;
572
+ return { w, h };
573
+ }
574
+ function readUint32BE(b, offset) {
575
+ return (b[offset] << 24 | b[offset + 1] << 16 | b[offset + 2] << 8 | b[offset + 3]) >>> 0;
576
+ }
577
+
578
+ // ../plugin/src/hooks/magic-context/todo-view.ts
579
+ import { createHash } from "node:crypto";
580
+ var TODO_STATUS_PENDING = "pending";
581
+ var TODO_STATUS_IN_PROGRESS = "in_progress";
582
+ var TODO_STATUS_COMPLETED = "completed";
583
+ var TODO_STATUS_CANCELLED = "cancelled";
584
+ var TODO_PRIORITY_HIGH = "high";
585
+ var TODO_PRIORITY_MEDIUM = "medium";
586
+ var TODO_PRIORITY_LOW = "low";
587
+ var TODO_STATUSES = [
588
+ TODO_STATUS_PENDING,
589
+ TODO_STATUS_IN_PROGRESS,
590
+ TODO_STATUS_COMPLETED,
591
+ TODO_STATUS_CANCELLED
592
+ ];
593
+ var TODO_PRIORITIES = [
594
+ TODO_PRIORITY_HIGH,
595
+ TODO_PRIORITY_MEDIUM,
596
+ TODO_PRIORITY_LOW
597
+ ];
598
+ var TODO_STATUS_SET = new Set(TODO_STATUSES);
599
+ var TODO_PRIORITY_SET = new Set(TODO_PRIORITIES);
600
+ var TERMINAL_STATUSES = new Set([
601
+ TODO_STATUS_COMPLETED,
602
+ TODO_STATUS_CANCELLED
603
+ ]);
604
+ var TITLE_DONE_STATUSES = new Set([TODO_STATUS_COMPLETED]);
605
+ var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
606
+ function normalizeTodoStateJson(todos) {
607
+ if (!Array.isArray(todos))
608
+ return null;
609
+ const normalized = [];
610
+ for (const todo of todos) {
611
+ if (!isTodoItem(todo))
612
+ return null;
613
+ normalized.push({
614
+ content: todo.content,
615
+ status: todo.status,
616
+ priority: todo.priority ?? TODO_PRIORITY_MEDIUM
617
+ });
618
+ }
619
+ return JSON.stringify(normalized);
620
+ }
621
+ function buildSyntheticTodoPart(stateJson) {
622
+ const todos = parseTodoState(stateJson);
623
+ if (todos === null || todos.length === 0)
624
+ return null;
625
+ if (todos.every((t) => TERMINAL_STATUSES.has(t.status)))
626
+ return null;
627
+ const callID = computeSyntheticCallId(stateJson);
628
+ const activeCount = todos.filter((t) => !TITLE_DONE_STATUSES.has(t.status)).length;
629
+ const output = JSON.stringify(todos, null, 2);
630
+ const ts = 0;
631
+ return {
632
+ type: "tool",
633
+ callID,
634
+ tool: "todowrite",
635
+ state: {
636
+ status: "completed",
637
+ input: { todos },
638
+ output,
639
+ title: `${activeCount} todos`,
640
+ metadata: { todos, truncated: false },
641
+ time: { start: ts, end: ts }
642
+ },
643
+ syntheticTodoMarker: true
644
+ };
645
+ }
646
+ function computeSyntheticCallId(stateJson) {
647
+ const hash = createHash("sha256").update(stateJson).digest("hex").slice(0, 16);
648
+ return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
649
+ }
650
+ function parseTodoState(stateJson) {
651
+ if (stateJson.length === 0)
652
+ return null;
653
+ try {
654
+ const parsed = JSON.parse(stateJson);
655
+ if (!Array.isArray(parsed))
656
+ return null;
657
+ const result = [];
658
+ for (const item of parsed) {
659
+ if (!isTodoItem(item))
660
+ return null;
661
+ result.push({
662
+ content: item.content,
663
+ status: item.status,
664
+ priority: item.priority ?? TODO_PRIORITY_MEDIUM
665
+ });
666
+ }
667
+ return result;
668
+ } catch {
669
+ return null;
670
+ }
671
+ }
672
+ function isTodoStatus(value) {
673
+ return typeof value === "string" && TODO_STATUS_SET.has(value);
674
+ }
675
+ function isTodoPriority(value) {
676
+ return typeof value === "string" && TODO_PRIORITY_SET.has(value);
677
+ }
678
+ function isTodoItem(value) {
679
+ if (value === null || typeof value !== "object")
680
+ return false;
681
+ const todo = value;
682
+ return typeof todo.content === "string" && isTodoStatus(todo.status) && (todo.priority === undefined || isTodoPriority(todo.priority));
683
+ }
684
+
685
+ // ../plugin/src/hooks/magic-context/tail-hygiene-walk.ts
686
+ var MAX_CONTENT_MEMO_BYTES = 64 * 1024 * 1024;
687
+ var contentMemo = new Map;
688
+ var CHANNEL1_REMINDER_OPEN = `
689
+
690
+ <system-reminder>
691
+ `;
692
+ var CHANNEL1_REMINDER_CLOSE = `
693
+ </system-reminder>`;
694
+ function stripChannel1ReminderSpans(output) {
695
+ let stripped = output;
696
+ while (stripped.endsWith(CHANNEL1_REMINDER_CLOSE)) {
697
+ const opener = stripped.lastIndexOf(CHANNEL1_REMINDER_OPEN);
698
+ if (opener < 0)
699
+ break;
700
+ stripped = stripped.slice(0, opener);
701
+ }
702
+ return stripped;
703
+ }
704
+ function messageIdFromPartKey(key) {
705
+ const separator = key.indexOf("\x00");
706
+ return separator > 0 ? key.slice(0, separator) : key;
707
+ }
708
+ function prefixMismatch(baseline, current, partIndex, field) {
709
+ return {
710
+ valid: false,
711
+ boundaryAdvanceU: 0,
712
+ queuedDropDeltaU: 0,
713
+ mismatch: {
714
+ partIndex,
715
+ messageId: messageIdFromPartKey(baseline[partIndex]?.key ?? ""),
716
+ field,
717
+ frozenParts: baseline.length,
718
+ measuredParts: current.length
719
+ }
720
+ };
721
+ }
722
+ function compareMeasuredTailPrefix(baseline, current) {
723
+ if (current.length < baseline.length) {
724
+ return prefixMismatch(baseline, current, current.length, "shorter");
725
+ }
726
+ let boundaryAdvanceU = 0;
727
+ let queuedDropDeltaU = 0;
728
+ for (let index = 0;index < baseline.length; index += 1) {
729
+ const before = baseline[index];
730
+ const after = current[index];
731
+ const changedField = comparedField(before, after);
732
+ if (changedField)
733
+ return prefixMismatch(baseline, current, index, changedField);
734
+ if (before.protected && !after.protected) {
735
+ boundaryAdvanceU += after.uTokens;
736
+ } else if (before.queuedForDrop !== after.queuedForDrop) {
737
+ queuedDropDeltaU += after.uTokens - before.uTokens;
738
+ }
739
+ }
740
+ return { valid: true, boundaryAdvanceU, queuedDropDeltaU };
741
+ }
742
+ function comparedField(before, after) {
743
+ if (before.key !== after.key)
744
+ return "key";
745
+ if (before.contentHash !== after.contentHash)
746
+ return "contentHash";
747
+ if (before.kind !== after.kind)
748
+ return "kind";
749
+ if (before.tokens !== after.tokens)
750
+ return "tokens";
751
+ if (before.tagNumber !== after.tagNumber)
752
+ return "tagNumber";
753
+ if (before.tagStatus !== after.tagStatus)
754
+ return "tagStatus";
755
+ if (!before.protected && after.protected)
756
+ return "protection-entered";
757
+ if (before.protected && !after.protected) {
758
+ return after.tagStatus === "active" ? null : "protection-exit-inactive";
759
+ }
760
+ if (before.queuedForDrop !== after.queuedForDrop) {
761
+ return before.tagStatus === "active" && after.tagStatus === "active" ? null : "queued-drop-inactive";
762
+ }
763
+ return before.uTokens === after.uTokens ? null : "uTokens";
764
+ }
765
+ function formatTailHygienePrefixMismatch(mismatch, baselineGeneration) {
766
+ return [
767
+ "tail hygiene prefix invalidated:",
768
+ `part_index=${mismatch.partIndex}`,
769
+ `message=${mismatch.messageId || "unknown"}`,
770
+ `field=${mismatch.field}`,
771
+ `frozen_parts=${mismatch.frozenParts}`,
772
+ `measured_parts=${mismatch.measuredParts}`,
773
+ "action=re-measured",
774
+ `generation=${baselineGeneration}`
775
+ ].join(" ");
776
+ }
777
+ var baselineMeasurementMemo = new Map;
778
+ var MAX_BASELINE_MEMO_SIZE = 32 * 1024 * 1024;
779
+ function freezeTailHygieneMeasurement(measured) {
780
+ const cut = Math.min(Math.max(0, measured.newestMessagePartStart), measured.parts.length);
781
+ let baselineT = 0;
782
+ let baselineU = 0;
783
+ for (let index = 0;index < cut; index += 1) {
784
+ baselineT += measured.parts[index].tokens;
785
+ baselineU += measured.parts[index].uTokens;
786
+ }
787
+ let turnDeltaT = 0;
788
+ let turnDeltaU = 0;
789
+ for (let index = cut;index < measured.parts.length; index += 1) {
790
+ const part = measured.parts[index];
791
+ turnDeltaT += part.tokens;
792
+ if (part.kind !== "toolOutput" || !part.protected)
793
+ turnDeltaU += part.uTokens;
794
+ }
795
+ baselineT = Math.max(0, baselineT);
796
+ return {
797
+ baselineU: Math.min(Math.max(0, baselineU), baselineT),
798
+ baselineT,
799
+ turnDeltaU,
800
+ turnDeltaT,
801
+ baselineParts: cut === measured.parts.length ? measured.parts : measured.parts.slice(0, cut)
802
+ };
803
+ }
804
+ function effectiveTailHygiene(baseline) {
805
+ const t = Math.ceil(Math.max(0, baseline.baselineT + baseline.turnDeltaT));
806
+ const u = Math.min(t, Math.ceil(Math.max(0, baseline.baselineU + baseline.turnDeltaU)));
807
+ return { u, t };
808
+ }
809
+
810
+ // ../plugin/src/hooks/magic-context/ctx-reduce-nudge.ts
811
+ var CHANNEL1_SENTINEL = "<system-reminder>";
812
+ var TOKENS_PER_BYTE = 0.25;
813
+ var CHANNEL1_MIN_TOKENS = 60000;
814
+ var CHANNEL1_FLOOR_TOKENS = 25000;
815
+ var CHANNEL1_REFIRE_FLOOR_TOKENS = 25000;
816
+ var S_GENTLE = 0.2;
817
+ var S_FIRM = 0.4;
818
+ var S_URGENT = 0.6;
819
+ var CHANNEL2_SEVERITY_THRESHOLD = 0.75;
820
+ var CHANNEL2_FLOOR_TOKENS = 50000;
821
+ var LEVEL_RANK = { gentle: 1, firm: 2, urgent: 3 };
822
+ function channel1RefireTokens(tailTokens) {
823
+ const scaled = Math.round(0.08 * Math.max(0, tailTokens));
824
+ return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
825
+ }
826
+ function channel1Band(undroppedTokens, tailTokens) {
827
+ if (tailTokens < CHANNEL1_MIN_TOKENS || undroppedTokens < CHANNEL1_FLOOR_TOKENS) {
828
+ return "quiet";
829
+ }
830
+ const severity = Math.min(1, Math.max(0, undroppedTokens / Math.max(tailTokens, 1)));
831
+ if (severity >= S_URGENT)
832
+ return "urgent";
833
+ if (severity >= S_FIRM)
834
+ return "firm";
835
+ if (severity >= S_GENTLE)
836
+ return "gentle";
837
+ return "quiet";
838
+ }
839
+ function nudgeBand(undroppedTokens, tailTokens) {
840
+ const base = channel1Band(undroppedTokens, tailTokens);
841
+ const severity = Math.min(1, Math.max(0, undroppedTokens / Math.max(tailTokens, 1)));
842
+ return base === "urgent" && undroppedTokens >= CHANNEL2_FLOOR_TOKENS && severity >= CHANNEL2_SEVERITY_THRESHOLD ? "channel2" : base;
843
+ }
844
+ function decideChannel1(input) {
845
+ const tailTokens = Math.max(0, input.baselineT + input.turnDeltaT);
846
+ const undroppedTokens = Math.min(tailTokens, Math.max(0, input.baselineU + input.turnDeltaU));
847
+ const severity = Math.min(1, Math.max(0, undroppedTokens / Math.max(tailTokens, 1)));
848
+ const previousLevel = input.lastNudgeLevel;
849
+ let lastNudge = Math.max(0, input.lastNudgeUndropped);
850
+ let nextLevel = previousLevel;
851
+ let clearPostReduceGrace = false;
852
+ const growthThreshold = channel1RefireTokens(tailTokens);
853
+ const graceBaselineU = input.postReduceGraceBaselineU === undefined ? null : Math.max(0, input.postReduceGraceBaselineU);
854
+ const graceGrowth = graceBaselineU === null ? 0 : undroppedTokens - graceBaselineU;
855
+ const cadenceGrowth = undroppedTokens - lastNudge;
856
+ const currentTurn = input.currentRealUserTurnCount;
857
+ const lastFireTurn = input.lastFireOrdinal;
858
+ const stickyTurnsRemaining = currentTurn === undefined || lastFireTurn === undefined || lastFireTurn > currentTurn ? 0 : Math.max(0, CHANNEL1_STICKY_REAL_USER_TURN_GAP - (currentTurn - lastFireTurn));
859
+ const measuredBand = channel1Band(undroppedTokens, tailTokens);
860
+ const quiet = (reason, dampeningState, level = measuredBand === "quiet" ? "gentle" : measuredBand) => ({
861
+ fire: false,
862
+ sticky: false,
863
+ level,
864
+ band: measuredBand,
865
+ undroppedTokens,
866
+ tailTokens,
867
+ severity,
868
+ graceBaselineU,
869
+ graceGrowth,
870
+ growthThreshold,
871
+ cadenceGrowth,
872
+ stickyTurnsRemaining,
873
+ dampeningState,
874
+ verdictReason: reason,
875
+ nextLastNudge: lastNudge,
876
+ nextLastNudgeLevel: nextLevel,
877
+ clearPostReduceGrace
878
+ });
879
+ if (input.evaluable === false || input.generationInvalidated === true) {
880
+ return quiet("baseline-unevaluable", "baseline-hold");
881
+ }
882
+ if (input.hasRecentReduce)
883
+ return quiet("recent-reduce-refresh", "baseline-hold");
884
+ if (input.agentDropsAppliedThisPass) {
885
+ return quiet("agent-drops-applied", "baseline-hold");
886
+ }
887
+ if (input.postReduceGracePending) {
888
+ return quiet("post-reduce-baseline-pending", "baseline-hold");
889
+ }
890
+ const level = measuredBand === "quiet" ? "" : measuredBand;
891
+ const previousRank = previousLevel === "" ? 0 : LEVEL_RANK[previousLevel];
892
+ const currentRank = level === "" ? 0 : LEVEL_RANK[level];
893
+ let graceReleaseReason = null;
894
+ if (graceBaselineU !== null) {
895
+ const preReduceLevel = input.postReduceGracePreLevel ?? previousLevel;
896
+ const preReduceRank = preReduceLevel === "" ? 0 : LEVEL_RANK[preReduceLevel];
897
+ const regrowthReached = graceGrowth >= growthThreshold;
898
+ const escalatedAbovePreReduceBand = currentRank > preReduceRank;
899
+ if (!regrowthReached && !escalatedAbovePreReduceBand) {
900
+ return quiet("post-reduce-compliance-grace", "post-reduce-grace");
901
+ }
902
+ clearPostReduceGrace = true;
903
+ graceReleaseReason = regrowthReached ? "post-reduce-regrowth-reached" : "post-reduce-band-escalation";
904
+ }
905
+ if (level === "") {
906
+ nextLevel = "";
907
+ lastNudge = 0;
908
+ if (tailTokens < CHANNEL1_MIN_TOKENS) {
909
+ return quiet("tail-below-minimum", "none");
910
+ }
911
+ if (undroppedTokens < CHANNEL1_FLOOR_TOKENS) {
912
+ return quiet("reclaimable-below-floor", "none");
913
+ }
914
+ return quiet("ratio-below-gentle", "none");
915
+ }
916
+ if (currentRank < previousRank) {
917
+ nextLevel = level;
918
+ lastNudge = undroppedTokens;
919
+ return quiet("band-deescalation", "band-hysteresis", level);
920
+ }
921
+ const crossedFromBelow = currentRank > previousRank;
922
+ const cadenceReached = currentRank === previousRank && cadenceGrowth >= growthThreshold;
923
+ const stickyTurnGapReached = stickyTurnsRemaining === 0;
924
+ if (!crossedFromBelow && !cadenceReached) {
925
+ return quiet("cadence-growth", "cadence", level);
926
+ }
927
+ if (!crossedFromBelow && !stickyTurnGapReached) {
928
+ return quiet("sticky-turn-floor", "sticky-floor", level);
929
+ }
930
+ return {
931
+ fire: true,
932
+ sticky: !crossedFromBelow,
933
+ level,
934
+ band: measuredBand,
935
+ undroppedTokens,
936
+ tailTokens,
937
+ severity,
938
+ graceBaselineU,
939
+ graceGrowth,
940
+ growthThreshold,
941
+ cadenceGrowth,
942
+ stickyTurnsRemaining,
943
+ dampeningState: "none",
944
+ verdictReason: graceReleaseReason ?? (crossedFromBelow ? "band-crossing" : "cadence-refire"),
945
+ nextLastNudge: undroppedTokens,
946
+ nextLastNudgeLevel: level,
947
+ clearPostReduceGrace
948
+ };
949
+ }
950
+ function evaluateChannel2(input) {
951
+ const unavailable = (reason) => ({
952
+ evaluable: false,
953
+ shouldTrigger: false,
954
+ reclaimableTokens: 0,
955
+ tailTokens: 0,
956
+ severity: 0,
957
+ band: "quiet",
958
+ verdictReason: reason
959
+ });
960
+ if (!input)
961
+ return unavailable("baseline-unavailable");
962
+ if (input.evaluable !== true)
963
+ return unavailable("baseline-unevaluable");
964
+ if (input.generationInvalidated === true)
965
+ return unavailable("generation-invalidated");
966
+ const values = [input.baselineU, input.baselineT, input.turnDeltaU, input.turnDeltaT];
967
+ if (values.some((value) => !Number.isFinite(value)))
968
+ return unavailable("non-finite-input");
969
+ const tailTokens = Math.max(0, input.baselineT + input.turnDeltaT);
970
+ const reclaimableTokens = Math.min(tailTokens, Math.max(0, input.baselineU + input.turnDeltaU));
971
+ const severity = Math.min(1, Math.max(0, reclaimableTokens / Math.max(tailTokens, 1)));
972
+ const band = nudgeBand(reclaimableTokens, tailTokens);
973
+ let verdictReason = "ceiling-threshold-met";
974
+ if (tailTokens < CHANNEL1_MIN_TOKENS)
975
+ verdictReason = "tail-below-minimum";
976
+ else if (reclaimableTokens < CHANNEL2_FLOOR_TOKENS) {
977
+ verdictReason = "reclaimable-below-floor";
978
+ } else if (severity < CHANNEL2_SEVERITY_THRESHOLD)
979
+ verdictReason = "ratio-below-ceiling";
980
+ return {
981
+ evaluable: true,
982
+ shouldTrigger: verdictReason === "ceiling-threshold-met",
983
+ reclaimableTokens,
984
+ tailTokens,
985
+ severity,
986
+ band,
987
+ verdictReason
988
+ };
989
+ }
990
+ function approxThousands(tokens) {
991
+ return `${Math.round(tokens / 1000)}k`;
992
+ }
993
+ function formatOldestReclaimableHint(hint) {
994
+ if (!hint || hint.length === 0)
995
+ return "";
996
+ const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
997
+ return rendered.length > 0 ? `
998
+ oldest reclaimable: ${rendered}.` : "";
999
+ }
1000
+ function reclaimableToolOutputCount(parts) {
1001
+ return parts.filter((part) => part.kind === "toolOutput" && part.uTokens > 0).length;
1002
+ }
1003
+ function formatReclaimableOutputSummary(count, tokens) {
1004
+ const outputCount = Math.max(0, Math.floor(count));
1005
+ const outputs = outputCount === 0 ? "spent tool outputs" : `${outputCount} spent tool output${outputCount === 1 ? "" : "s"}`;
1006
+ return `${outputs} (~${approxThousands(tokens)} tokens)`;
1007
+ }
1008
+ function buildChannel2Reminder(undroppedTokens, reclaimableToolOutputs, hint) {
1009
+ const summary = formatReclaimableOutputSummary(reclaimableToolOutputs, undroppedTokens);
1010
+ const hintText = formatOldestReclaimableHint(hint);
1011
+ return `<system-reminder>
1012
+ ` + `Routine housekeeping: ${summary} are reclaimable — make a ctx_reduce pass at a natural stopping point.${hintText}
1013
+ ` + `</system-reminder>`;
1014
+ }
1015
+ var CHANNEL1_STICKY_REAL_USER_TURN_GAP = 5;
1016
+ function buildChannel1Reminder(level, undroppedTokens, reclaimableToolOutputs, hint, sticky = false) {
1017
+ const summary = formatReclaimableOutputSummary(reclaimableToolOutputs, undroppedTokens);
1018
+ const hintText = formatOldestReclaimableHint(hint);
1019
+ if (sticky) {
1020
+ return `
1021
+
1022
+ <system-reminder>
1023
+ Reminder: ${summary} are still reclaimable — ctx_reduce them at a natural stopping point.${hintText}
1024
+ </system-reminder>`;
1025
+ }
1026
+ let body;
1027
+ switch (level) {
1028
+ case "gentle":
1029
+ body = `Housekeeping: ${summary} are reclaimable — drop the ones you have already processed with ctx_reduce at a natural stopping point.`;
1030
+ break;
1031
+ case "firm":
1032
+ body = `Housekeeping: ${summary} are reclaimable — make a ctx_reduce pass at a natural stopping point.`;
1033
+ break;
1034
+ case "urgent":
1035
+ body = `Housekeeping backlog: ${summary} are reclaimable — a ctx_reduce pass is due.`;
1036
+ break;
1037
+ }
1038
+ return `
1039
+
1040
+ <system-reminder>
1041
+ ${body}${hintText}
1042
+ </system-reminder>`;
1043
+ }
1044
+
1045
+ // ../plugin/src/hooks/magic-context/emergency-drop.ts
1046
+ var TARGET_FRACTION = 0.3;
1047
+ var TIER_RECENCY_RESERVE = 0.2;
1048
+ var EMERGENCY_REARM_MIN_TOKENS = 2000;
1049
+ var T1_TOOLS = new Set(["read", "todowrite", "task", "aft_outline", "aft_zoom"]);
1050
+ var T2_TOOLS = new Set(["edit", "write", "apply_patch", "grep", "glob", "aft_search"]);
1051
+ function normalizeToolName(toolName) {
1052
+ if (!toolName)
1053
+ return "";
1054
+ let name = toolName.toLowerCase();
1055
+ if (name.startsWith("mcp_"))
1056
+ name = name.slice(4);
1057
+ return name;
1058
+ }
1059
+ function resolveToolTier(toolName) {
1060
+ const name = normalizeToolName(toolName);
1061
+ if (T1_TOOLS.has(name))
1062
+ return 1;
1063
+ if (T2_TOOLS.has(name))
1064
+ return 2;
1065
+ return 3;
1066
+ }
1067
+ function tagReclaimBytes(tag) {
1068
+ return tag.byteSize + tag.inputByteSize + tag.reasoningByteSize;
1069
+ }
1070
+ function estimateEmergencyDropReclaimTokens(tag) {
1071
+ if (tag.reclaimableTokens !== undefined)
1072
+ return Number.isFinite(tag.reclaimableTokens) ? Math.max(0, tag.reclaimableTokens) : 0;
1073
+ return Math.round(tagReclaimBytes(tag) * TOKENS_PER_BYTE);
1074
+ }
1075
+ function planEmergencyDrop(input) {
1076
+ const {
1077
+ tags,
1078
+ floorTags,
1079
+ currentTotalInputTokens,
1080
+ ceilingTokens,
1081
+ priorInputSample,
1082
+ hasPriorDrop
1083
+ } = input;
1084
+ const noop = (reason) => ({
1085
+ shouldDrop: false,
1086
+ tagNumbers: [],
1087
+ reclaimTokens: 0,
1088
+ reason
1089
+ });
1090
+ if (!Number.isFinite(ceilingTokens) || ceilingTokens <= 0) {
1091
+ return noop("unknown-ceiling");
1092
+ }
1093
+ if (!Number.isFinite(currentTotalInputTokens) || currentTotalInputTokens <= 0) {
1094
+ return noop("unknown-usage");
1095
+ }
1096
+ const absoluteEmergency = (input.usagePercentage ?? 0) >= 95;
1097
+ if (hasPriorDrop && !absoluteEmergency) {
1098
+ return noop(`pressure-episode-latched (prior sample ${priorInputSample}; awaiting exit or independent bust)`);
1099
+ }
1100
+ let tailTokens = 0;
1101
+ for (const tag of floorTags) {
1102
+ if (tag.status !== "active")
1103
+ continue;
1104
+ tailTokens += tag.servedTokens ?? estimateEmergencyDropReclaimTokens(tag);
1105
+ }
1106
+ const fixedFloor = Math.max(currentTotalInputTokens - tailTokens, 0);
1107
+ const workingSpan = Math.max(ceilingTokens - fixedFloor, 0);
1108
+ const target = fixedFloor + TARGET_FRACTION * workingSpan;
1109
+ const reclaimTokens = Math.round(currentTotalInputTokens - target);
1110
+ if (reclaimTokens <= EMERGENCY_REARM_MIN_TOKENS) {
1111
+ return noop(`reclaim<=min (${reclaimTokens} <= ${EMERGENCY_REARM_MIN_TOKENS})`);
1112
+ }
1113
+ const cutoff = input.protectedCutoff;
1114
+ const windowYields = absoluteEmergency;
1115
+ const tierActive = { 1: [], 2: [] };
1116
+ for (const tag of tags) {
1117
+ if (tag.status !== "active" || tag.type !== "tool")
1118
+ continue;
1119
+ const tier = resolveToolTier(tag.toolName);
1120
+ if (tier === 1 || tier === 2)
1121
+ tierActive[tier].push(tag.tagNumber);
1122
+ }
1123
+ const reserved = new Set;
1124
+ for (const tier of [1, 2]) {
1125
+ const nums = tierActive[tier];
1126
+ if (nums.length === 0)
1127
+ continue;
1128
+ nums.sort((a, b) => b - a);
1129
+ const reserveCount = absoluteEmergency ? 0 : Math.ceil(TIER_RECENCY_RESERVE * nums.length);
1130
+ for (let i = 0;i < reserveCount && i < nums.length; i++) {
1131
+ reserved.add(nums[i]);
1132
+ }
1133
+ }
1134
+ const protectedCtxReduceTags = newestCtxReduceTagNumbers(floorTags.filter((tag) => tag.status === "active" && tag.type === "tool"));
1135
+ const byTier = { 1: [], 2: [], 3: [] };
1136
+ for (const tag of tags) {
1137
+ if (tag.status !== "active" || tag.type !== "tool")
1138
+ continue;
1139
+ if (!windowYields) {
1140
+ if (cutoff !== null) {
1141
+ if (tag.tagNumber >= cutoff)
1142
+ continue;
1143
+ }
1144
+ }
1145
+ if (protectedCtxReduceTags.has(tag.tagNumber))
1146
+ continue;
1147
+ const tier = resolveToolTier(tag.toolName);
1148
+ if ((tier === 1 || tier === 2) && reserved.has(tag.tagNumber))
1149
+ continue;
1150
+ byTier[tier].push(tag);
1151
+ }
1152
+ const selected = [];
1153
+ let reclaimed = 0;
1154
+ outer:
1155
+ for (const tier of [3, 2, 1]) {
1156
+ const group = byTier[tier];
1157
+ group.sort((a, b) => a.tagNumber - b.tagNumber);
1158
+ for (const tag of group) {
1159
+ selected.push(tag.tagNumber);
1160
+ reclaimed += estimateEmergencyDropReclaimTokens(tag);
1161
+ if (reclaimed >= reclaimTokens)
1162
+ break outer;
1163
+ }
1164
+ }
1165
+ if (selected.length === 0) {
1166
+ return noop("no-candidates");
1167
+ }
1168
+ return {
1169
+ shouldDrop: true,
1170
+ tagNumbers: selected,
1171
+ reclaimTokens,
1172
+ reason: `tiered drop: ${selected.length} tags, reclaim≈${reclaimed}/${reclaimTokens} tokens (floor≈${fixedFloor}, ceiling=${Math.round(ceilingTokens)})`
1173
+ };
1174
+ }
1175
+ function measureEmergencyTag(tag, target, calibration, skeleton) {
1176
+ const observation = target?.measureReclaim?.(skeleton);
1177
+ if (observation) {
1178
+ const before = observation.beforeTools * calibration.toolsRatio + observation.beforeProse * calibration.proseRatio;
1179
+ const after = observation.afterTools * calibration.toolsRatio + observation.afterProse * calibration.proseRatio;
1180
+ return { ...tag, servedTokens: before, reclaimableTokens: Math.max(0, before - after) };
1181
+ }
1182
+ const content = target?.getContent?.();
1183
+ const served = content ? estimateTokens(content) * (tag.type === "tool" ? calibration.toolsRatio : calibration.proseRatio) : 0;
1184
+ return { ...tag, servedTokens: served, reclaimableTokens: 0 };
1185
+ }
1186
+
1187
+ // ../plugin/src/features/magic-context/storage-tags.ts
1188
+ var insertTagStatements = new WeakMap;
1189
+ var updateTagStatusStatements = new WeakMap;
1190
+ var updateTagDropModeStatements = new WeakMap;
1191
+ var updateTagMessageIdStatements = new WeakMap;
1192
+ var getTagNumbersByMessageIdStatements = new WeakMap;
1193
+ var deleteTagsByMessageIdStatements = new WeakMap;
1194
+ var getMaxTagNumberBySessionStatements = new WeakMap;
1195
+ var getTagNumberByMessageIdStatements = new WeakMap;
1196
+ var getAssignableTagNumberByMessageIdStatements = new WeakMap;
1197
+ var hasPiFallbackMessageTagStatements = new WeakMap;
1198
+ var WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX = "__mc_whitespace_assistant_inert__:";
1199
+ var WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX = "mc:whitespace-assistant:";
1200
+ function getInsertTagStatement(db) {
1201
+ let stmt = insertTagStatements.get(db);
1202
+ if (!stmt) {
1203
+ stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness, tool_owner_message_id, entry_fingerprint, token_count, input_token_count, reasoning_token_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1204
+ insertTagStatements.set(db, stmt);
1205
+ }
1206
+ return stmt;
1207
+ }
1208
+ function getUpdateTagStatusStatement(db) {
1209
+ let stmt = updateTagStatusStatements.get(db);
1210
+ if (!stmt) {
1211
+ stmt = db.prepare("UPDATE tags SET status = ? WHERE session_id = ? AND tag_number = ?");
1212
+ updateTagStatusStatements.set(db, stmt);
1213
+ }
1214
+ return stmt;
1215
+ }
1216
+ function getUpdateTagDropModeStatement(db) {
1217
+ let stmt = updateTagDropModeStatements.get(db);
1218
+ if (!stmt) {
1219
+ stmt = db.prepare("UPDATE tags SET drop_mode = ? WHERE session_id = ? AND tag_number = ?");
1220
+ updateTagDropModeStatements.set(db, stmt);
1221
+ }
1222
+ return stmt;
1223
+ }
1224
+ var updateTagByteSizeStatements = new WeakMap;
1225
+ var updateTagInputByteSizeStatements = new WeakMap;
1226
+ function getUpdateTagByteSizeStatement(db) {
1227
+ let stmt = updateTagByteSizeStatements.get(db);
1228
+ if (!stmt) {
1229
+ stmt = db.prepare("UPDATE tags SET byte_size = ? WHERE session_id = ? AND tag_number = ?");
1230
+ updateTagByteSizeStatements.set(db, stmt);
1231
+ }
1232
+ return stmt;
1233
+ }
1234
+ function getUpdateTagInputByteSizeStatement(db) {
1235
+ let stmt = updateTagInputByteSizeStatements.get(db);
1236
+ if (!stmt) {
1237
+ stmt = db.prepare("UPDATE tags SET input_byte_size = ? WHERE session_id = ? AND tag_number = ?");
1238
+ updateTagInputByteSizeStatements.set(db, stmt);
1239
+ }
1240
+ return stmt;
1241
+ }
1242
+ function updateTagByteSize(db, sessionId, tagNumber, newByteSize) {
1243
+ getUpdateTagByteSizeStatement(db).run(newByteSize, sessionId, tagNumber);
1244
+ }
1245
+ var CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
1246
+ var RECENT_OWNER_SCAN_PAGE_SIZE = 128;
1247
+ var recentTagOwnerStatements = new WeakMap;
1248
+ function ownerMessageIdForTagRow(row) {
1249
+ if (row.type === "tool") {
1250
+ return row.tool_owner_message_id ?? row.message_id;
1251
+ }
1252
+ return row.message_id.replace(CONTENT_ID_SUFFIX, "");
1253
+ }
1254
+ function getRecentTagOwnerStatement(db) {
1255
+ let statement = recentTagOwnerStatements.get(db);
1256
+ if (!statement) {
1257
+ statement = db.prepare(`SELECT type, message_id, tool_owner_message_id
1258
+ FROM tags
1259
+ WHERE session_id = ?
1260
+ ORDER BY tag_number DESC, id DESC
1261
+ LIMIT ? OFFSET ?`);
1262
+ recentTagOwnerStatements.set(db, statement);
1263
+ }
1264
+ return statement;
1265
+ }
1266
+ function getRecentTagOwnerMessageIds(db, sessionId, maxOwners) {
1267
+ const recent = new Set;
1268
+ if (!Number.isFinite(maxOwners) || maxOwners <= 0)
1269
+ return recent;
1270
+ const statement = getRecentTagOwnerStatement(db);
1271
+ let offset = 0;
1272
+ while (recent.size < maxOwners) {
1273
+ const rows = statement.all(sessionId, RECENT_OWNER_SCAN_PAGE_SIZE, offset);
1274
+ for (const row of rows) {
1275
+ if (typeof row.type !== "string" || typeof row.message_id !== "string")
1276
+ continue;
1277
+ const ownerId = row.type === "tool" ? typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null : row.message_id.replace(CONTENT_ID_SUFFIX, "");
1278
+ if (!ownerId || recent.has(ownerId))
1279
+ continue;
1280
+ recent.add(ownerId);
1281
+ if (recent.size >= maxOwners)
1282
+ break;
1283
+ }
1284
+ if (rows.length < RECENT_OWNER_SCAN_PAGE_SIZE)
1285
+ break;
1286
+ offset += rows.length;
1287
+ }
1288
+ return recent;
1289
+ }
1290
+ var RECLAIM_HINT_EXCLUDED_TOOLS = new Set([
1291
+ "ask",
1292
+ "bash_kill",
1293
+ "bash_status",
1294
+ "board",
1295
+ "task",
1296
+ "todoread",
1297
+ "todowrite",
1298
+ "work"
1299
+ ]);
1300
+ var AGE_RECLAIM_MIN_TOKENS = 250;
1301
+ function isReclaimHintExcludedTool(toolName) {
1302
+ if (!toolName)
1303
+ return false;
1304
+ const normalized = toolName.toLowerCase().replace(/^mcp_/, "");
1305
+ return normalized.startsWith("ctx_") || RECLAIM_HINT_EXCLUDED_TOOLS.has(normalized);
1306
+ }
1307
+ function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTagNumbers = new Set, limit = 4) {
1308
+ if (limit <= 0)
1309
+ return [];
1310
+ const boundedLimit = Math.max(1, Math.min(10, Math.floor(limit)));
1311
+ const valueFloor = `AND (
1312
+ (token_count IS NULL AND input_token_count IS NULL)
1313
+ OR (COALESCE(token_count, 0) + COALESCE(input_token_count, 0)) >= ?
1314
+ )`;
1315
+ const params = [sessionId, AGE_RECLAIM_MIN_TOKENS];
1316
+ const rows = db.prepare(`SELECT tag_number, tool_name
1317
+ FROM tags
1318
+ WHERE session_id = ? AND status = 'active' AND type = 'tool'
1319
+ AND NOT EXISTS (
1320
+ SELECT 1 FROM pending_ops
1321
+ WHERE pending_ops.session_id = tags.session_id
1322
+ AND pending_ops.tag_id = tags.tag_number
1323
+ AND pending_ops.operation = 'drop'
1324
+ )
1325
+ ${valueFloor}
1326
+ ORDER BY tag_number ASC, id ASC`).all(...params);
1327
+ return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
1328
+ tagNumber: row.tag_number,
1329
+ toolName: typeof row.tool_name === "string" ? row.tool_name : null
1330
+ })).filter((tag) => !protectedTagNumbers.has(tag.tagNumber) && !isReclaimHintExcludedTool(tag.toolName)).sort((left, right) => resolveToolTier(right.toolName) - resolveToolTier(left.toolName) || left.tagNumber - right.tagNumber).slice(0, boundedLimit);
1331
+ }
1332
+ var getActiveToolTagsForAgeReclaimStatements = new WeakMap;
1333
+ function getActiveToolTagsForAgeReclaim(db, sessionId) {
1334
+ let stmt = getActiveToolTagsForAgeReclaimStatements.get(db);
1335
+ if (!stmt) {
1336
+ stmt = db.prepare(`SELECT tag_number, tool_name, token_count, input_token_count
1337
+ FROM tags
1338
+ WHERE session_id = ? AND status = 'active' AND type = 'tool'
1339
+ ORDER BY tag_number ASC, id ASC`);
1340
+ getActiveToolTagsForAgeReclaimStatements.set(db, stmt);
1341
+ }
1342
+ const rows = stmt.all(sessionId);
1343
+ const tags = rows.filter((row) => typeof row.tag_number === "number").map((row) => {
1344
+ const outputTokens = typeof row.token_count === "number" ? row.token_count : null;
1345
+ const inputTokens = typeof row.input_token_count === "number" ? row.input_token_count : null;
1346
+ return {
1347
+ tagNumber: row.tag_number,
1348
+ toolName: typeof row.tool_name === "string" ? row.tool_name : null,
1349
+ reclaimableTokens: outputTokens === null && inputTokens === null ? null : (outputTokens ?? 0) + (inputTokens ?? 0)
1350
+ };
1351
+ });
1352
+ const protectedCtxReduceTags = newestCtxReduceTagNumbers(tags);
1353
+ return tags.filter((tag) => !protectedCtxReduceTags.has(tag.tagNumber));
1354
+ }
1355
+ function getTriggerTagTokenUpperBound(db, sessionId, floor = 0) {
1356
+ const sql = floor > 0 ? `SELECT
1357
+ COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
1358
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
1359
+ FROM tags
1360
+ WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?` : `SELECT
1361
+ COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
1362
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
1363
+ FROM tags
1364
+ WHERE session_id = ? AND status IN ('active', 'dropped')`;
1365
+ const row = floor > 0 ? db.prepare(sql).get(sessionId, floor) : db.prepare(sql).get(sessionId);
1366
+ return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
1367
+ }
1368
+ function updateTagInputByteSize(db, sessionId, tagNumber, newInputByteSize) {
1369
+ getUpdateTagInputByteSizeStatement(db).run(newInputByteSize, sessionId, tagNumber);
1370
+ }
1371
+ var updateTagTokenCountStatements = new WeakMap;
1372
+ var updateTagInputTokenCountStatements = new WeakMap;
1373
+ function getUpdateTagTokenCountStatement(db) {
1374
+ let stmt = updateTagTokenCountStatements.get(db);
1375
+ if (!stmt) {
1376
+ stmt = db.prepare("UPDATE tags SET token_count = MAX(COALESCE(token_count, 0), ?) WHERE session_id = ? AND tag_number = ?");
1377
+ updateTagTokenCountStatements.set(db, stmt);
1378
+ }
1379
+ return stmt;
1380
+ }
1381
+ function getUpdateTagInputTokenCountStatement(db) {
1382
+ let stmt = updateTagInputTokenCountStatements.get(db);
1383
+ if (!stmt) {
1384
+ stmt = db.prepare("UPDATE tags SET input_token_count = ? WHERE session_id = ? AND tag_number = ?");
1385
+ updateTagInputTokenCountStatements.set(db, stmt);
1386
+ }
1387
+ return stmt;
1388
+ }
1389
+ function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
1390
+ getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
1391
+ }
1392
+ function getPersistedToolTagAccounting(db, sessionId, tagNumber) {
1393
+ const row = db.prepare(`SELECT byte_size AS byteSize,
1394
+ token_count AS tokenCount,
1395
+ input_byte_size AS inputByteSize,
1396
+ input_token_count AS inputTokenCount
1397
+ FROM tags
1398
+ WHERE session_id = ? AND tag_number = ? AND type = 'tool'`).get(sessionId, tagNumber);
1399
+ if (!row || typeof row.byteSize !== "number" || row.tokenCount !== null && typeof row.tokenCount !== "number" || typeof row.inputByteSize !== "number" || row.inputTokenCount !== null && typeof row.inputTokenCount !== "number") {
1400
+ return null;
1401
+ }
1402
+ return row;
1403
+ }
1404
+ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration = { proseRatio: 1, toolsRatio: 1 }) {
1405
+ const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
1406
+ FROM tags
1407
+ 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
1408
+ FROM tags
1409
+ WHERE session_id = ?`).all(sessionId);
1410
+ const totals = new Map;
1411
+ const nullMessageIds = new Set;
1412
+ for (const row of rows) {
1413
+ if (row.type === "tool" && row.tool_owner_message_id === null)
1414
+ continue;
1415
+ const owner = ownerMessageIdForTagRow(row);
1416
+ if (row.token_count === null) {
1417
+ nullMessageIds.add(owner);
1418
+ totals.delete(owner);
1419
+ continue;
1420
+ }
1421
+ if (nullMessageIds.has(owner))
1422
+ continue;
1423
+ const ratio = row.type === "tool" ? calibration.toolsRatio : calibration.proseRatio;
1424
+ const weight = ((row.token_count ?? 0) + (row.input_token_count ?? 0)) * ratio + (row.reasoning_token_count ?? 0) * calibration.proseRatio;
1425
+ totals.set(owner, (totals.get(owner) ?? 0) + weight);
1426
+ }
1427
+ return { totals, nullMessageIds };
1428
+ }
1429
+ function updateTagInputTokenCount(db, sessionId, tagNumber, newInputTokenCount) {
1430
+ getUpdateTagInputTokenCountStatement(db).run(newInputTokenCount, sessionId, tagNumber);
1431
+ }
1432
+ function tagTokenCountIsNull(db, sessionId, tagNumber) {
1433
+ const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
1434
+ return row != null && row.token_count === null;
1435
+ }
1436
+ function backfillTagTokenCounts(db, sessionId, tagNumber, counts) {
1437
+ db.prepare(`UPDATE tags
1438
+ SET token_count = CASE WHEN ? IS NOT NULL THEN MAX(COALESCE(token_count, 0), ?) ELSE token_count END,
1439
+ input_token_count = ?,
1440
+ reasoning_token_count = ?
1441
+ WHERE session_id = ? AND tag_number = ? AND token_count IS NULL`).run(counts.tokenCount ?? null, counts.tokenCount ?? null, counts.inputTokenCount ?? null, counts.reasoningTokenCount ?? null, sessionId, tagNumber);
1442
+ }
1443
+ function getMaxTagNumberBySessionStatement(db) {
1444
+ let stmt = getMaxTagNumberBySessionStatements.get(db);
1445
+ if (!stmt) {
1446
+ stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ?");
1447
+ getMaxTagNumberBySessionStatements.set(db, stmt);
1448
+ }
1449
+ return stmt;
1450
+ }
1451
+ function getTagNumberByMessageIdStatement(db) {
1452
+ let stmt = getTagNumberByMessageIdStatements.get(db);
1453
+ if (!stmt) {
1454
+ stmt = db.prepare("SELECT tag_number FROM tags WHERE session_id = ? AND message_id = ? ORDER BY tag_number ASC LIMIT 1");
1455
+ getTagNumberByMessageIdStatements.set(db, stmt);
1456
+ }
1457
+ return stmt;
1458
+ }
1459
+ function getAssignableTagNumberByMessageIdStatement(db) {
1460
+ let stmt = getAssignableTagNumberByMessageIdStatements.get(db);
1461
+ if (!stmt) {
1462
+ stmt = db.prepare(`SELECT tag_number FROM tags
1463
+ WHERE session_id = ?
1464
+ AND message_id = ?
1465
+ AND NOT (
1466
+ status = 'compacted'
1467
+ AND COALESCE(
1468
+ entry_fingerprint LIKE '${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%',
1469
+ 0
1470
+ ) = 1
1471
+ )
1472
+ ORDER BY tag_number ASC
1473
+ LIMIT 1`);
1474
+ getAssignableTagNumberByMessageIdStatements.set(db, stmt);
1475
+ }
1476
+ return stmt;
1477
+ }
1478
+ function isTagRow(row) {
1479
+ if (row === null || typeof row !== "object")
1480
+ return false;
1481
+ const r = row;
1482
+ return typeof r.id === "number" && typeof r.message_id === "string" && typeof r.type === "string" && typeof r.status === "string" && typeof r.byte_size === "number" && typeof r.session_id === "string" && typeof r.tag_number === "number";
1483
+ }
1484
+ function toTagEntry(row) {
1485
+ const type = row.type === "tool" ? "tool" : row.type === "file" ? "file" : "message";
1486
+ const status = row.status === "dropped" || row.status === "compacted" ? row.status : "active";
1487
+ return {
1488
+ id: row.id,
1489
+ tagNumber: row.tag_number,
1490
+ messageId: row.message_id,
1491
+ type,
1492
+ status,
1493
+ dropMode: row.drop_mode === "truncated" ? "truncated" : row.drop_mode === "edit_marker" ? "edit_marker" : "full",
1494
+ toolName: row.tool_name ?? null,
1495
+ inputByteSize: row.input_byte_size ?? 0,
1496
+ byteSize: row.byte_size,
1497
+ reasoningByteSize: row.reasoning_byte_size ?? 0,
1498
+ sessionId: row.session_id,
1499
+ cavemanDepth: typeof row.caveman_depth === "number" && Number.isFinite(row.caveman_depth) ? row.caveman_depth : 0,
1500
+ toolOwnerMessageId: typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null,
1501
+ tokenCount: typeof row.token_count === "number" ? row.token_count : null
1502
+ };
1503
+ }
1504
+ function isTagNumberRow(row) {
1505
+ if (row === null || typeof row !== "object")
1506
+ return false;
1507
+ const r = row;
1508
+ return typeof r.tag_number === "number";
1509
+ }
1510
+ function isMaxTagNumberRow(row) {
1511
+ if (row === null || typeof row !== "object")
1512
+ return false;
1513
+ const r = row;
1514
+ return typeof r.max_tag_number === "number";
1515
+ }
1516
+ function insertTag(db, sessionId, messageId, type, byteSize, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null, tokenCounts = null) {
1517
+ getInsertTagStatement(db).run(sessionId, messageId, type, byteSize, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId, entryFingerprint, tokenCounts?.tokenCount ?? null, tokenCounts?.inputTokenCount ?? null, tokenCounts?.reasoningTokenCount ?? null);
1518
+ return tagNumber;
1519
+ }
1520
+ function updateTagStatus(db, sessionId, tagId, status) {
1521
+ getUpdateTagStatusStatement(db).run(status, sessionId, tagId);
1522
+ }
1523
+ function getInertWhitespaceAssistantTags(db, sessionId) {
1524
+ const rows = db.prepare(`SELECT tag_number AS tagNumber, entry_fingerprint AS entryFingerprint
1525
+ FROM tags
1526
+ WHERE session_id = ?
1527
+ AND type = 'message'
1528
+ AND status = 'compacted'
1529
+ AND entry_fingerprint LIKE ?`).all(sessionId, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%`);
1530
+ return rows.flatMap((row) => {
1531
+ const contentId = row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length);
1532
+ return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
1533
+ });
1534
+ }
1535
+ function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
1536
+ getUpdateTagDropModeStatement(db).run(dropMode, sessionId, tagNumber);
1537
+ }
1538
+ function updateCavemanDepth(db, sessionId, tagNumber, depth) {
1539
+ db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
1540
+ }
1541
+ function hasPiFallbackMessageTags(db, sessionId) {
1542
+ let statement = hasPiFallbackMessageTagStatements.get(db);
1543
+ if (!statement) {
1544
+ statement = db.prepare(`SELECT 1
1545
+ FROM tags
1546
+ WHERE session_id = ?
1547
+ AND type = 'message'
1548
+ AND message_id LIKE 'pi-msg-%'
1549
+ LIMIT 1`);
1550
+ hasPiFallbackMessageTagStatements.set(db, statement);
1551
+ }
1552
+ return statement.get(sessionId) != null;
1553
+ }
1554
+ function findAdoptableFallbackTags(db, sessionId, entryFingerprint) {
1555
+ const rows = db.prepare(`SELECT tag_number AS tagNumber, message_id AS messageId
1556
+ FROM tags
1557
+ WHERE session_id = ?
1558
+ AND type = 'message'
1559
+ AND entry_fingerprint = ?
1560
+ AND message_id LIKE 'pi-msg-%'`).all(sessionId, entryFingerprint);
1561
+ return rows;
1562
+ }
1563
+ function isPiFallbackToolOwnerTag(row) {
1564
+ if (row === null || typeof row !== "object")
1565
+ return false;
1566
+ const r = row;
1567
+ return typeof r.tagNumber === "number" && typeof r.callId === "string" && typeof r.toolOwnerMessageId === "string" && typeof r.status === "string";
1568
+ }
1569
+ function isPiFallbackFoldTagRow(row) {
1570
+ if (row === null || typeof row !== "object")
1571
+ return false;
1572
+ const r = row;
1573
+ return typeof r.tagNumber === "number" && typeof r.messageId === "string" && (typeof r.toolOwnerMessageId === "string" || r.toolOwnerMessageId === null) && typeof r.type === "string" && typeof r.status === "string" && (typeof r.byteSize === "number" || r.byteSize === null) && (typeof r.reasoningByteSize === "number" || r.reasoningByteSize === null) && (typeof r.inputByteSize === "number" || r.inputByteSize === null) && (typeof r.tokenCount === "number" || r.tokenCount === null) && (typeof r.inputTokenCount === "number" || r.inputTokenCount === null) && (typeof r.reasoningTokenCount === "number" || r.reasoningTokenCount === null);
1574
+ }
1575
+ function isPendingOpIdentityRow(row) {
1576
+ if (row === null || typeof row !== "object")
1577
+ return false;
1578
+ const r = row;
1579
+ return typeof r.id === "number" && typeof r.operation === "string";
1580
+ }
1581
+ function maxNullableNumber(a, b) {
1582
+ if (typeof a === "number" && typeof b === "number")
1583
+ return Math.max(a, b);
1584
+ if (typeof a === "number")
1585
+ return a;
1586
+ if (typeof b === "number")
1587
+ return b;
1588
+ return null;
1589
+ }
1590
+ function getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber) {
1591
+ const row = db.prepare(`SELECT tag_number AS tagNumber,
1592
+ message_id AS messageId,
1593
+ tool_owner_message_id AS toolOwnerMessageId,
1594
+ type,
1595
+ status,
1596
+ byte_size AS byteSize,
1597
+ reasoning_byte_size AS reasoningByteSize,
1598
+ input_byte_size AS inputByteSize,
1599
+ token_count AS tokenCount,
1600
+ input_token_count AS inputTokenCount,
1601
+ reasoning_token_count AS reasoningTokenCount
1602
+ FROM tags
1603
+ WHERE session_id = ? AND tag_number = ?`).get(sessionId, tagNumber);
1604
+ return isPiFallbackFoldTagRow(row) ? row : null;
1605
+ }
1606
+ function getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, ownerMsgId) {
1607
+ const row = db.prepare(`SELECT tag_number AS tagNumber,
1608
+ message_id AS messageId,
1609
+ tool_owner_message_id AS toolOwnerMessageId,
1610
+ type,
1611
+ status,
1612
+ byte_size AS byteSize,
1613
+ reasoning_byte_size AS reasoningByteSize,
1614
+ input_byte_size AS inputByteSize,
1615
+ token_count AS tokenCount,
1616
+ input_token_count AS inputTokenCount,
1617
+ reasoning_token_count AS reasoningTokenCount
1618
+ FROM tags
1619
+ WHERE session_id = ?
1620
+ AND message_id = ?
1621
+ AND type = 'tool'
1622
+ AND tool_owner_message_id = ?
1623
+ LIMIT 1`).get(sessionId, callId, ownerMsgId);
1624
+ return isPiFallbackFoldTagRow(row) ? row : null;
1625
+ }
1626
+ function getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, messageId) {
1627
+ return db.prepare(`SELECT tag_number AS tagNumber,
1628
+ message_id AS messageId,
1629
+ tool_owner_message_id AS toolOwnerMessageId,
1630
+ type,
1631
+ status,
1632
+ byte_size AS byteSize,
1633
+ reasoning_byte_size AS reasoningByteSize,
1634
+ input_byte_size AS inputByteSize,
1635
+ token_count AS tokenCount,
1636
+ input_token_count AS inputTokenCount,
1637
+ reasoning_token_count AS reasoningTokenCount
1638
+ FROM tags
1639
+ WHERE session_id = ?
1640
+ AND message_id = ?
1641
+ AND type = 'message'
1642
+ ORDER BY tag_number ASC`).all(sessionId, messageId).filter(isPiFallbackFoldTagRow);
1643
+ }
1644
+ function mergeSizeAndTokenColumnsIntoSurvivor(db, sessionId, survivor, duplicate) {
1645
+ db.prepare(`UPDATE tags
1646
+ SET byte_size = ?,
1647
+ reasoning_byte_size = ?,
1648
+ input_byte_size = ?,
1649
+ token_count = ?,
1650
+ input_token_count = ?,
1651
+ reasoning_token_count = ?
1652
+ WHERE session_id = ? AND tag_number = ?`).run(maxNullableNumber(survivor.byteSize, duplicate.byteSize), maxNullableNumber(survivor.reasoningByteSize, duplicate.reasoningByteSize), maxNullableNumber(survivor.inputByteSize, duplicate.inputByteSize), maxNullableNumber(survivor.tokenCount, duplicate.tokenCount), maxNullableNumber(survivor.inputTokenCount, duplicate.inputTokenCount), maxNullableNumber(survivor.reasoningTokenCount, duplicate.reasoningTokenCount), sessionId, survivor.tagNumber);
1653
+ survivor.byteSize = maxNullableNumber(survivor.byteSize, duplicate.byteSize);
1654
+ survivor.reasoningByteSize = maxNullableNumber(survivor.reasoningByteSize, duplicate.reasoningByteSize);
1655
+ survivor.inputByteSize = maxNullableNumber(survivor.inputByteSize, duplicate.inputByteSize);
1656
+ survivor.tokenCount = maxNullableNumber(survivor.tokenCount, duplicate.tokenCount);
1657
+ survivor.inputTokenCount = maxNullableNumber(survivor.inputTokenCount, duplicate.inputTokenCount);
1658
+ survivor.reasoningTokenCount = maxNullableNumber(survivor.reasoningTokenCount, duplicate.reasoningTokenCount);
1659
+ }
1660
+ function applyDroppedStatusIfNeeded(db, sessionId, survivor, duplicate) {
1661
+ if (survivor.status === "dropped")
1662
+ return;
1663
+ if (duplicate.status !== "dropped")
1664
+ return;
1665
+ db.prepare("UPDATE tags SET status = 'dropped' WHERE session_id = ? AND tag_number = ?").run(sessionId, survivor.tagNumber);
1666
+ survivor.status = "dropped";
1667
+ }
1668
+ function retargetPendingOps(db, sessionId, fromTagNumber, toTagNumber) {
1669
+ const rows = db.prepare(`SELECT id, operation
1670
+ FROM pending_ops
1671
+ WHERE session_id = ? AND tag_id = ?
1672
+ ORDER BY id ASC`).all(sessionId, fromTagNumber).filter(isPendingOpIdentityRow);
1673
+ for (const row of rows) {
1674
+ const existing = db.prepare(`SELECT 1
1675
+ FROM pending_ops
1676
+ WHERE session_id = ? AND tag_id = ? AND operation = ?
1677
+ LIMIT 1`).get(sessionId, toTagNumber, row.operation);
1678
+ if (existing) {
1679
+ db.prepare("DELETE FROM pending_ops WHERE session_id = ? AND id = ?").run(sessionId, row.id);
1680
+ } else {
1681
+ db.prepare("UPDATE pending_ops SET tag_id = ? WHERE session_id = ? AND id = ?").run(toTagNumber, sessionId, row.id);
1682
+ }
1683
+ }
1684
+ db.prepare("DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?").run(sessionId, fromTagNumber);
1685
+ }
1686
+ function deleteFoldedDuplicateTag(db, sessionId, tagNumber) {
1687
+ db.prepare("DELETE FROM source_contents WHERE session_id = ? AND tag_id = ?").run(sessionId, tagNumber);
1688
+ db.prepare("DELETE FROM tags WHERE session_id = ? AND tag_number = ?").run(sessionId, tagNumber);
1689
+ db.prepare("DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?").run(sessionId, tagNumber);
1690
+ }
1691
+ function foldDuplicateIntoSurvivor(db, sessionId, survivor, duplicate) {
1692
+ mergeSizeAndTokenColumnsIntoSurvivor(db, sessionId, survivor, duplicate);
1693
+ applyDroppedStatusIfNeeded(db, sessionId, survivor, duplicate);
1694
+ retargetPendingOps(db, sessionId, duplicate.tagNumber, survivor.tagNumber);
1695
+ deleteFoldedDuplicateTag(db, sessionId, duplicate.tagNumber);
1696
+ }
1697
+ function hasPiFallbackToolOwnerTags(db, sessionId) {
1698
+ const row = db.prepare(`SELECT 1
1699
+ FROM tags
1700
+ WHERE session_id = ?
1701
+ AND type = 'tool'
1702
+ AND tool_owner_message_id LIKE 'pi-msg-%'
1703
+ LIMIT 1`).get(sessionId);
1704
+ return row != null;
1705
+ }
1706
+ function findPiFallbackToolOwnerTags(db, sessionId) {
1707
+ return db.prepare(`SELECT tag_number AS tagNumber,
1708
+ message_id AS callId,
1709
+ tool_owner_message_id AS toolOwnerMessageId,
1710
+ status
1711
+ FROM tags
1712
+ WHERE session_id = ?
1713
+ AND type = 'tool'
1714
+ AND tool_owner_message_id LIKE 'pi-msg-%'
1715
+ ORDER BY tag_number ASC`).all(sessionId).filter(isPiFallbackToolOwnerTag);
1716
+ }
1717
+ function adoptPiFallbackToolOwnerTag(db, sessionId, tagNumber, callId, oldOwnerMessageId, newOwnerMessageId) {
1718
+ const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
1719
+ if (survivor === null || survivor.type !== "tool" || survivor.messageId !== callId || survivor.toolOwnerMessageId !== oldOwnerMessageId) {
1720
+ return { action: "skipped" };
1721
+ }
1722
+ const existing = getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, newOwnerMessageId);
1723
+ if (existing === null) {
1724
+ const result = db.prepare(`UPDATE tags
1725
+ SET tool_owner_message_id = ?
1726
+ WHERE session_id = ?
1727
+ AND tag_number = ?
1728
+ AND type = 'tool'
1729
+ AND message_id = ?
1730
+ AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
1731
+ return (result.changes ?? 0) > 0 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
1732
+ }
1733
+ if (existing.tagNumber === tagNumber) {
1734
+ return { action: "skipped" };
1735
+ }
1736
+ foldDuplicateIntoSurvivor(db, sessionId, existing, survivor);
1737
+ return {
1738
+ action: "folded",
1739
+ tagNumber: existing.tagNumber,
1740
+ deletedTagNumbers: [tagNumber]
1741
+ };
1742
+ }
1743
+ function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageId, newRealMessageId) {
1744
+ if (oldFallbackMessageId.startsWith(WHITESPACE_ASSISTANT_INERT_MESSAGE_PREFIX)) {
1745
+ return { action: "skipped" };
1746
+ }
1747
+ const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
1748
+ if (survivor === null || survivor.type !== "message" || survivor.messageId !== oldFallbackMessageId) {
1749
+ return { action: "skipped" };
1750
+ }
1751
+ const duplicates = getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, newRealMessageId).filter((row) => row.tagNumber !== tagNumber);
1752
+ if (duplicates.length === 0) {
1753
+ const result = db.prepare(`UPDATE tags
1754
+ SET message_id = ?
1755
+ WHERE session_id = ?
1756
+ AND tag_number = ?
1757
+ AND type = 'message'
1758
+ AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
1759
+ return (result.changes ?? 0) > 0 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
1760
+ }
1761
+ const realSurvivor = duplicates[0];
1762
+ if (!realSurvivor)
1763
+ return { action: "skipped" };
1764
+ const deletedTagNumbers = [tagNumber];
1765
+ foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, survivor);
1766
+ for (const duplicate of duplicates.slice(1)) {
1767
+ foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, duplicate);
1768
+ deletedTagNumbers.push(duplicate.tagNumber);
1769
+ }
1770
+ return {
1771
+ action: "folded",
1772
+ tagNumber: realSurvivor.tagNumber,
1773
+ deletedTagNumbers
1774
+ };
1775
+ }
1776
+ var getOwnerScopedToolTagNumbersStatements = new WeakMap;
1777
+ function getMaxTagNumberBySession(db, sessionId) {
1778
+ const row = getMaxTagNumberBySessionStatement(db).get(sessionId);
1779
+ return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
1780
+ }
1781
+ function getTagNumberByMessageId(db, sessionId, messageId) {
1782
+ const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
1783
+ return isTagNumberRow(row) ? row.tag_number : null;
1784
+ }
1785
+ function getAssignableTagNumberByMessageId(db, sessionId, messageId) {
1786
+ const row = getAssignableTagNumberByMessageIdStatement(db).get(sessionId, messageId);
1787
+ return isTagNumberRow(row) ? row.tag_number : null;
1788
+ }
1789
+ var getMinMessageTagNumberForRawIdStatements = new WeakMap;
1790
+ function isMinTagNumberRow(row) {
1791
+ return row !== null && typeof row === "object" && "m" in row;
1792
+ }
1793
+ function getMinMessageTagNumberForRawId(db, sessionId, rawId) {
1794
+ if (rawId.includes(":"))
1795
+ return null;
1796
+ let stmt = getMinMessageTagNumberForRawIdStatements.get(db);
1797
+ if (!stmt) {
1798
+ stmt = db.prepare("SELECT MIN(tag_number) AS m FROM tags WHERE session_id = ? AND message_id >= ? AND message_id < ?");
1799
+ getMinMessageTagNumberForRawIdStatements.set(db, stmt);
1800
+ }
1801
+ const row = stmt.get(sessionId, `${rawId}:`, `${rawId};`);
1802
+ return isMinTagNumberRow(row) && typeof row.m === "number" ? row.m : null;
1803
+ }
1804
+ var TAGGER_FLOOR_SCAN_MESSAGES = 8;
1805
+ var TAGGER_FLOOR_MAX_PROBES = 64;
1806
+ var TAGGER_FLOOR_SAFETY_MARGIN = 256;
1807
+ var TAGGER_FLOOR_PER_SKIP_MARGIN = 64;
1808
+ function deriveTagLoadFloor(db, sessionId, rawIds) {
1809
+ let min = Number.POSITIVE_INFINITY;
1810
+ let probes = 0;
1811
+ let hits = 0;
1812
+ let skippedBeforeFirstHit = 0;
1813
+ for (const rawId of rawIds) {
1814
+ if (typeof rawId !== "string" || rawId.length === 0)
1815
+ continue;
1816
+ if (probes >= TAGGER_FLOOR_MAX_PROBES)
1817
+ break;
1818
+ probes++;
1819
+ const m = getMinMessageTagNumberForRawId(db, sessionId, rawId);
1820
+ if (m === null) {
1821
+ if (hits === 0)
1822
+ skippedBeforeFirstHit++;
1823
+ continue;
1824
+ }
1825
+ if (m < min)
1826
+ min = m;
1827
+ if (++hits >= TAGGER_FLOOR_SCAN_MESSAGES)
1828
+ break;
1829
+ }
1830
+ if (!Number.isFinite(min))
1831
+ return 0;
1832
+ const margin = TAGGER_FLOOR_SAFETY_MARGIN + skippedBeforeFirstHit * TAGGER_FLOOR_PER_SKIP_MARGIN;
1833
+ return Math.max(0, min - margin);
1834
+ }
1835
+ var TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id, token_count";
1836
+ function getTagsBySession(db, sessionId) {
1837
+ const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
1838
+ return rows.map(toTagEntry);
1839
+ }
1840
+ var getActiveTagsBySessionStatements = new WeakMap;
1841
+ var getNullOwnerToolTagsBySessionStatements = new WeakMap;
1842
+ var getDroppedTagsBySessionStatements = new WeakMap;
1843
+ var getMaxDroppedTagNumberStatements = new WeakMap;
1844
+ function getActiveTagsBySessionStatement(db) {
1845
+ let stmt = getActiveTagsBySessionStatements.get(db);
1846
+ if (!stmt) {
1847
+ stmt = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY tag_number ASC, id ASC`);
1848
+ getActiveTagsBySessionStatements.set(db, stmt);
1849
+ }
1850
+ return stmt;
1851
+ }
1852
+ function getMaxDroppedTagNumberStatement(db) {
1853
+ let stmt = getMaxDroppedTagNumberStatements.get(db);
1854
+ if (!stmt) {
1855
+ stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ? AND status = 'dropped'");
1856
+ getMaxDroppedTagNumberStatements.set(db, stmt);
1857
+ }
1858
+ return stmt;
1859
+ }
1860
+ function getActiveTagsBySession(db, sessionId) {
1861
+ const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
1862
+ return rows.map(toTagEntry);
1863
+ }
1864
+ function getTagsForPendingOperations(db, sessionId, pendingTagNumbers, protectedCount, recentToolWindow) {
1865
+ const byNumber = new Map;
1866
+ for (const tag of getTagsByNumbers(db, sessionId, pendingTagNumbers)) {
1867
+ byNumber.set(tag.tagNumber, tag);
1868
+ }
1869
+ const addRows = (sql, limit) => {
1870
+ if (limit <= 0)
1871
+ return;
1872
+ const rows = db.prepare(sql).all(sessionId, limit).filter(isTagRow);
1873
+ for (const row of rows) {
1874
+ const tag = toTagEntry(row);
1875
+ byNumber.set(tag.tagNumber, tag);
1876
+ }
1877
+ };
1878
+ addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
1879
+ WHERE session_id = ? AND status = 'active'
1880
+ ORDER BY tag_number DESC, id DESC LIMIT ?`, protectedCount);
1881
+ addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
1882
+ WHERE session_id = ? AND type = 'tool'
1883
+ ORDER BY tag_number DESC, id DESC LIMIT ?`, recentToolWindow);
1884
+ return [...byNumber.values()].sort((left, right) => left.tagNumber - right.tagNumber);
1885
+ }
1886
+ function getTagsByNumbers(db, sessionId, tagNumbers) {
1887
+ if (tagNumbers.length === 0)
1888
+ return [];
1889
+ if (tagNumbers.length > 900) {
1890
+ const all = [];
1891
+ for (let i = 0;i < tagNumbers.length; i += 900) {
1892
+ all.push(...getTagsByNumbers(db, sessionId, tagNumbers.slice(i, i + 900)));
1893
+ }
1894
+ return all;
1895
+ }
1896
+ const placeholders = tagNumbers.map(() => "?").join(",");
1897
+ const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
1898
+ return rows.map(toTagEntry);
1899
+ }
1900
+ function getDroppedTagsByNumbers(db, sessionId, tagNumbers) {
1901
+ if (tagNumbers.length === 0)
1902
+ return [];
1903
+ if (tagNumbers.length > 900) {
1904
+ const all = [];
1905
+ for (let i = 0;i < tagNumbers.length; i += 900) {
1906
+ all.push(...getDroppedTagsByNumbers(db, sessionId, tagNumbers.slice(i, i + 900)));
1907
+ }
1908
+ return all;
1909
+ }
1910
+ const placeholders = tagNumbers.map(() => "?").join(",");
1911
+ const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'dropped' AND tag_number IN (${placeholders}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
1912
+ return rows.map(toTagEntry);
1913
+ }
1914
+ function getMaxDroppedTagNumber(db, sessionId) {
1915
+ const row = getMaxDroppedTagNumberStatement(db).get(sessionId);
1916
+ return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
1917
+ }
1918
+ var getToolTagNumberByOwnerStatements = new WeakMap;
1919
+ var getNullOwnerToolTagStatements = new WeakMap;
1920
+ var adoptNullOwnerToolTagStatements = new WeakMap;
1921
+ var getToolOwnerByTagIdStatements = new WeakMap;
1922
+ var deleteToolTagsByOwnerStatements = new WeakMap;
1923
+ function getGetToolTagNumberByOwnerStatement(db) {
1924
+ let stmt = getToolTagNumberByOwnerStatements.get(db);
1925
+ if (!stmt) {
1926
+ stmt = db.prepare(`SELECT tag_number FROM tags
1927
+ WHERE session_id = ? AND message_id = ?
1928
+ AND type = 'tool' AND tool_owner_message_id = ?
1929
+ LIMIT 1`);
1930
+ getToolTagNumberByOwnerStatements.set(db, stmt);
1931
+ }
1932
+ return stmt;
1933
+ }
1934
+ function getToolTagNumberByOwner(db, sessionId, callId, ownerMsgId) {
1935
+ const row = getGetToolTagNumberByOwnerStatement(db).get(sessionId, callId, ownerMsgId);
1936
+ return isTagNumberRow(row) ? row.tag_number : null;
1937
+ }
1938
+ function isNullOwnerToolTagRow(row) {
1939
+ if (row === null || typeof row !== "object")
1940
+ return false;
1941
+ const r = row;
1942
+ return typeof r.id === "number" && typeof r.tag_number === "number";
1943
+ }
1944
+ function getGetNullOwnerToolTagStatement(db) {
1945
+ let stmt = getNullOwnerToolTagStatements.get(db);
1946
+ if (!stmt) {
1947
+ stmt = db.prepare(`SELECT id, tag_number FROM tags
1948
+ WHERE session_id = ? AND message_id = ?
1949
+ AND type = 'tool' AND tool_owner_message_id IS NULL
1950
+ ORDER BY tag_number ASC
1951
+ LIMIT 1`);
1952
+ getNullOwnerToolTagStatements.set(db, stmt);
1953
+ }
1954
+ return stmt;
1955
+ }
1956
+ function getNullOwnerToolTag(db, sessionId, callId) {
1957
+ const row = getGetNullOwnerToolTagStatement(db).get(sessionId, callId);
1958
+ if (!isNullOwnerToolTagRow(row))
1959
+ return null;
1960
+ return { id: row.id, tagNumber: row.tag_number };
1961
+ }
1962
+ function getAdoptNullOwnerToolTagStatement(db) {
1963
+ let stmt = adoptNullOwnerToolTagStatements.get(db);
1964
+ if (!stmt) {
1965
+ stmt = db.prepare(`UPDATE tags
1966
+ SET tool_owner_message_id = ?
1967
+ WHERE id = ? AND tool_owner_message_id IS NULL`);
1968
+ adoptNullOwnerToolTagStatements.set(db, stmt);
1969
+ }
1970
+ return stmt;
1971
+ }
1972
+ function getToolOwnerByTagIdStatement(db) {
1973
+ let stmt = getToolOwnerByTagIdStatements.get(db);
1974
+ if (!stmt) {
1975
+ stmt = db.prepare("SELECT tool_owner_message_id FROM tags WHERE id = ?");
1976
+ getToolOwnerByTagIdStatements.set(db, stmt);
1977
+ }
1978
+ return stmt;
1979
+ }
1980
+ function adoptNullOwnerToolTag(db, rowId, ownerMsgId) {
1981
+ return db.transaction(() => {
1982
+ const before = getToolOwnerByTagIdStatement(db).get(rowId);
1983
+ if (!before || before.tool_owner_message_id !== null)
1984
+ return false;
1985
+ getAdoptNullOwnerToolTagStatement(db).run(ownerMsgId, rowId);
1986
+ const after = getToolOwnerByTagIdStatement(db).get(rowId);
1987
+ return after?.tool_owner_message_id === ownerMsgId;
1988
+ }).immediate();
1989
+ }
1990
+ function getCandidateToolOwners(db, sessionId, callId) {
1991
+ const rows = db.prepare(`SELECT DISTINCT tool_owner_message_id
1992
+ FROM tags
1993
+ WHERE session_id = ?
1994
+ AND message_id = ?
1995
+ AND type = 'tool'
1996
+ AND tool_owner_message_id IS NOT NULL`).all(sessionId, callId);
1997
+ return rows.map((r) => r.tool_owner_message_id);
1998
+ }
1999
+ function pickNearestPriorOwner(candidates, currentMessageId, times) {
2000
+ const currentTime = times.get(currentMessageId);
2001
+ if (typeof currentTime !== "number")
2002
+ return null;
2003
+ let best = null;
2004
+ for (const id of candidates) {
2005
+ const t = times.get(id);
2006
+ if (typeof t !== "number")
2007
+ continue;
2008
+ if (t > currentTime)
2009
+ continue;
2010
+ if (t === currentTime && id >= currentMessageId)
2011
+ continue;
2012
+ if (best === null || t > best.time || t === best.time && id > best.id) {
2013
+ best = { id, time: t };
2014
+ }
2015
+ }
2016
+ return best?.id ?? null;
2017
+ }
2018
+
2019
+ // ../plugin/src/hooks/magic-context/host-served-rows.ts
2020
+ var HOST_UNSERVED_ROW = "hostUnservedRow";
2021
+ function markHostUnservedRow(target) {
2022
+ Object.defineProperty(target, HOST_UNSERVED_ROW, {
2023
+ value: true,
2024
+ enumerable: false,
2025
+ configurable: true
2026
+ });
2027
+ return target;
2028
+ }
2029
+ function isHostUnservedRow(value) {
2030
+ return typeof value === "object" && value !== null && value[HOST_UNSERVED_ROW] === true;
2031
+ }
2032
+ function retreatPastHostUnservedRows(messages, exclusiveEnd, floor) {
2033
+ if (!messages.some(isHostUnservedRow))
2034
+ return exclusiveEnd;
2035
+ const byOrdinal = new Map(messages.map((message) => [message.ordinal, message]));
2036
+ let end = exclusiveEnd;
2037
+ while (end - 1 >= floor && isHostUnservedRow(byOrdinal.get(end - 1)))
2038
+ end -= 1;
2039
+ return end;
2040
+ }
2041
+
2042
+ // ../plugin/src/shared/opencode-db-path.ts
2043
+ import { existsSync as existsSync2, readdirSync, statSync as statSync2 } from "node:fs";
2044
+ import { homedir as homedir2 } from "node:os";
2045
+ import { isAbsolute, join as join2 } from "node:path";
2046
+ var cachedResolution = null;
2047
+ var lastReadFailure = null;
2048
+ var claimedDiagnostics = new Set;
2049
+ function openCodeDataDir(env = process.env, dataHome) {
2050
+ return join2(dataHome ?? env.XDG_DATA_HOME ?? join2(homedir2(), ".local", "share"), "opencode");
2051
+ }
2052
+ function environmentKey(dataDir, hostGeneration, channel, env) {
2053
+ return [
2054
+ hostGeneration,
2055
+ dataDir,
2056
+ env.OPENCODE_DB ?? "",
2057
+ env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
2058
+ channel ?? env.OPENCODE_CHANNEL ?? ""
2059
+ ].join("\x00");
2060
+ }
2061
+ function channelPath(dataDir, channel) {
2062
+ return ["latest", "beta", "prod"].includes(channel) ? join2(dataDir, "opencode.db") : join2(dataDir, `opencode-${channel}.db`);
2063
+ }
2064
+ function discoveredCandidateNames(dataDir) {
2065
+ const names = ["opencode.db", "opencode-local.db", "opencode-dev.db"];
2066
+ try {
2067
+ const discovered = readdirSync(dataDir, { withFileTypes: true }).filter((entry) => /^opencode-.+\.db$/.test(entry.name) && !names.includes(entry.name)).map((entry) => entry.name).sort();
2068
+ names.push(...discovered);
2069
+ } catch {}
2070
+ return names;
2071
+ }
2072
+ function discoverOpenCodeDb(dataDir) {
2073
+ const candidates = discoveredCandidateNames(dataDir).map((name, order) => {
2074
+ const path = join2(dataDir, name);
2075
+ try {
2076
+ const metadata = statSync2(path);
2077
+ return metadata.isFile() ? { path, order, mtimeMs: metadata.mtimeMs } : null;
2078
+ } catch {
2079
+ return null;
2080
+ }
2081
+ });
2082
+ const existing = candidates.filter((candidate) => candidate !== null).sort((left, right) => right.mtimeMs - left.mtimeMs || left.order - right.order)[0];
2083
+ if (!existing) {
2084
+ return { path: join2(dataDir, "opencode.db"), source: "default", channel: null };
2085
+ }
2086
+ const name = existing.path.slice(dataDir.length + 1);
2087
+ const channel = name === "opencode.db" ? null : name.slice("opencode-".length, -".db".length) || null;
2088
+ return { path: existing.path, source: "discovered", channel };
2089
+ }
2090
+ function resolveV1Fresh(dataDir, env = process.env) {
2091
+ const explicit = env.OPENCODE_DB;
2092
+ if (explicit !== undefined && explicit.length > 0) {
2093
+ if (explicit === ":memory:") {
2094
+ return { path: explicit, source: "OPENCODE_DB", channel: null };
2095
+ }
2096
+ return {
2097
+ path: isAbsolute(explicit) ? explicit : join2(dataDir, explicit),
2098
+ source: "OPENCODE_DB",
2099
+ channel: null
2100
+ };
2101
+ }
2102
+ const disableChannelDb = env.OPENCODE_DISABLE_CHANNEL_DB;
2103
+ if (disableChannelDb === "1" || disableChannelDb === "true") {
2104
+ return { path: join2(dataDir, "opencode.db"), source: "default", channel: null };
2105
+ }
2106
+ const channel = env.OPENCODE_CHANNEL;
2107
+ if (channel !== undefined && channel.length > 0) {
2108
+ return { path: channelPath(dataDir, channel), source: "channel", channel };
2109
+ }
2110
+ return discoverOpenCodeDb(dataDir);
2111
+ }
2112
+ function sourceOpenCodeDatabaseFilename(hostGeneration, channel, env = process.env) {
2113
+ if (hostGeneration === "v1") {
2114
+ const explicit = env.OPENCODE_DB;
2115
+ if (explicit !== undefined && explicit.length > 0)
2116
+ return explicit;
2117
+ if (env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true") {
2118
+ return "opencode.db";
2119
+ }
2120
+ return ["latest", "beta", "prod"].includes(channel) ? "opencode.db" : `opencode-${channel}.db`;
2121
+ }
2122
+ return env.OPENCODE_DB ?? (["latest", "dev", "beta", "next", "prod"].includes(channel) || env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true" ? "opencode.db" : `opencode-${channel.replace(/[^a-zA-Z0-9._-]/g, "")}.db`);
2123
+ }
2124
+ function resolveV2Fresh(dataDir, channel, env) {
2125
+ const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
2126
+ const explicit = env.OPENCODE_DB !== undefined;
2127
+ return {
2128
+ path: filename === ":memory:" ? filename : join2(dataDir, filename),
2129
+ source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
2130
+ channel: explicit ? null : channel
2131
+ };
2132
+ }
2133
+ function resolveOpenCodeDbPath(hostGeneration = "v1", options = {}) {
2134
+ const env = options.env ?? process.env;
2135
+ const dataDir = openCodeDataDir(env, options.dataHome);
2136
+ const channel = options.channel ?? env.OPENCODE_CHANNEL;
2137
+ const key = environmentKey(dataDir, hostGeneration, channel, env);
2138
+ if (cachedResolution?.key === key && (!cachedResolution.existed || existsSync2(cachedResolution.resolution.path))) {
2139
+ if (cachedResolution.existed)
2140
+ return cachedResolution.resolution;
2141
+ }
2142
+ const resolution = hostGeneration === "v2" ? resolveV2Fresh(dataDir, channel ?? "latest", env) : resolveV1Fresh(dataDir, env);
2143
+ cachedResolution = {
2144
+ key,
2145
+ resolution,
2146
+ existed: resolution.path !== ":memory:" && existsSync2(resolution.path)
2147
+ };
2148
+ return resolution;
2149
+ }
2150
+ function schemaTableNames(db, schema = "main") {
2151
+ const rows = db.prepare(`SELECT name FROM ${schema}.sqlite_master WHERE type = 'table' AND name IN ('message', 'part', 'session', 'project', 'session_message', 'session_v2')`).all();
2152
+ return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
2153
+ }
2154
+ function hasV1MessageTables(db, schema = "main") {
2155
+ const tables = schemaTableNames(db, schema);
2156
+ return tables.has("message") && tables.has("part");
2157
+ }
2158
+ function detectOpenCodeStoreGeneration(db, schema = "main") {
2159
+ const tables = schemaTableNames(db, schema);
2160
+ const hasV1Messages = tables.has("message") && tables.has("part");
2161
+ if (hasV1Messages)
2162
+ return "v1";
2163
+ if (tables.has("session_message"))
2164
+ return "v2";
2165
+ if (tables.has("session") || tables.has("project"))
2166
+ return "v1";
2167
+ return "unknown";
2168
+ }
2169
+ function hasMigratedV2Schema(tables) {
2170
+ return tables.has("session_message") && tables.has("session_v2");
2171
+ }
2172
+ function isOpenCodeV2Store(db, schema = "main") {
2173
+ return detectOpenCodeStoreGeneration(db, schema) === "v2" || hasMigratedV2Schema(schemaTableNames(db, schema));
2174
+ }
2175
+ function assertOpenCodeStoreGeneration(db, expected, path, schema = "main") {
2176
+ const actual = detectOpenCodeStoreGeneration(db, schema);
2177
+ if (actual === expected)
2178
+ return;
2179
+ if (expected === "v2" && isOpenCodeV2Store(db, schema))
2180
+ return;
2181
+ if (actual === "unknown")
2182
+ return;
2183
+ throw new Error(`OpenCode store generation mismatch at ${path}: expected ${expected}, found ${actual}; refusing generation-specific database access`);
2184
+ }
2185
+ function openCodeDbPathExists(resolution = resolveOpenCodeDbPath()) {
2186
+ return resolution.path !== ":memory:" && existsSync2(resolution.path);
2187
+ }
2188
+ function getOpenCodeDbProbeDescriptions(resolution = resolveOpenCodeDbPath()) {
2189
+ if (resolution.source === "OPENCODE_DB")
2190
+ return [resolution.path];
2191
+ if (resolution.source === "channel" || process.env.OPENCODE_DISABLE_CHANNEL_DB === "1" || process.env.OPENCODE_DISABLE_CHANNEL_DB === "true") {
2192
+ return [resolution.path];
2193
+ }
2194
+ const dataDir = openCodeDataDir();
2195
+ return [
2196
+ join2(dataDir, "opencode.db"),
2197
+ join2(dataDir, "opencode-local.db"),
2198
+ join2(dataDir, "opencode-dev.db"),
2199
+ join2(dataDir, "opencode-<channel>.db")
2200
+ ];
2201
+ }
2202
+ function recordOpenCodeDbReadFailure(resolution, error) {
2203
+ const message = error instanceof Error ? error.message : String(error);
2204
+ lastReadFailure = { ...resolution, message };
2205
+ return lastReadFailure;
2206
+ }
2207
+ function clearOpenCodeDbReadFailure(path) {
2208
+ if (path === undefined || lastReadFailure?.path === path)
2209
+ lastReadFailure = null;
2210
+ }
2211
+ function claimOpenCodeDbDiagnosticOnce(surface, resolution) {
2212
+ const key = `${surface}\x00${resolution.path}\x00${resolution.source}`;
2213
+ if (claimedDiagnostics.has(key))
2214
+ return false;
2215
+ claimedDiagnostics.add(key);
2216
+ return true;
2217
+ }
2218
+
2219
+ // ../plugin/src/shared/sqlite.ts
2220
+ var reportSlowPrivilegedWrite;
2221
+ function registerSlowWriteReporter(reporter) {
2222
+ reportSlowPrivilegedWrite = reporter;
2223
+ }
2224
+ function detectSqliteRuntime() {
2225
+ const hasBunVersion = typeof process !== "undefined" && typeof process.versions?.bun === "string";
2226
+ const hasBunGlobal = typeof globalThis !== "undefined" && typeof globalThis.Bun !== "undefined";
2227
+ return hasBunVersion || hasBunGlobal ? "Bun" : "Node.js";
2228
+ }
2229
+ var bunSpec = "bun:" + "sqlite";
2230
+ var nodeSpec = "node:" + "sqlite";
2231
+ async function importSqliteModule(specifier) {
2232
+ return await import(specifier);
2233
+ }
2234
+ function isModuleNotFoundError(error, specifier) {
2235
+ const candidate = error;
2236
+ const code = typeof candidate?.code === "string" ? candidate.code : "";
2237
+ const name = typeof candidate?.name === "string" ? candidate.name : "";
2238
+ const message = error instanceof Error ? error.message : String(error ?? "");
2239
+ const details = `${code} ${name} ${message}`.toLowerCase();
2240
+ const mentionsSpecifier = details.includes(specifier.toLowerCase());
2241
+ if (!mentionsSpecifier)
2242
+ return false;
2243
+ return code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNKNOWN_BUILTIN_MODULE" || code === "MODULE_NOT_FOUND" || name === "ResolveMessage" || details.includes("module not found") || details.includes("cannot find module") || details.includes("cannot find package") || details.includes("no such built-in module");
2244
+ }
2245
+
2246
+ class SqliteRuntimeUnavailableError extends Error {
2247
+ runtime;
2248
+ specifier;
2249
+ constructor(runtime, specifier, cause) {
2250
+ const requirement = specifier === nodeSpec ? "Requires Node.js >= 24, or Bun with bun:sqlite — this Bun build lacks node:sqlite." : "Requires Bun with bun:sqlite, or Node.js >= 24 — this Bun build lacks bun:sqlite.";
2251
+ super(`Magic Context detected ${runtime}, but could not load ${specifier}. ${requirement}`, { cause });
2252
+ this.name = "SqliteRuntimeUnavailableError";
2253
+ this.runtime = runtime;
2254
+ this.specifier = specifier;
2255
+ }
2256
+ }
2257
+ async function loadSqliteModule(runtime = detectSqliteRuntime(), importer = importSqliteModule) {
2258
+ const specifier = runtime === "Bun" ? bunSpec : nodeSpec;
2259
+ try {
2260
+ return await importer(specifier);
2261
+ } catch (error) {
2262
+ if (isModuleNotFoundError(error, specifier)) {
2263
+ throw new SqliteRuntimeUnavailableError(runtime, specifier, error);
2264
+ }
2265
+ throw error;
2266
+ }
2267
+ }
2268
+ var detectedRuntime = detectSqliteRuntime();
2269
+ var isBun = detectedRuntime === "Bun";
2270
+ var sqliteModule = await loadSqliteModule(detectedRuntime);
2271
+ var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
2272
+ var trackedSqliteConnections = new Map;
2273
+ var nextSqliteConnectionSequence = 1;
2274
+ function trackSqliteConnection(db, filename, options) {
2275
+ const originalClose = db.close.bind(db);
2276
+ const sequence = nextSqliteConnectionSequence++;
2277
+ const metadata = {
2278
+ sequence,
2279
+ filename: typeof filename === "string" ? filename : Buffer.isBuffer(filename) ? "<buffer>" : ":memory:",
2280
+ readonly: Boolean(options) && typeof options === "object" && (options.readonly === true || options.readOnly === true)
2281
+ };
2282
+ Object.defineProperty(db, "close", {
2283
+ configurable: true,
2284
+ value: (...args) => {
2285
+ try {
2286
+ return originalClose(...args);
2287
+ } finally {
2288
+ trackedSqliteConnections.delete(sequence);
2289
+ }
2290
+ }
2291
+ });
2292
+ trackedSqliteConnections.set(sequence, {
2293
+ ...metadata,
2294
+ reference: new WeakRef(db)
2295
+ });
2296
+ return db;
2297
+ }
2298
+ var TrackedDatabase = new Proxy(DatabaseImpl, {
2299
+ construct(target, args) {
2300
+ const db = Reflect.construct(target, args, target);
2301
+ return trackSqliteConnection(db, args[0], args[1]);
2302
+ }
2303
+ });
2304
+ function buildNodeSqliteDatabaseClass(DatabaseSync) {
2305
+ const SAVEPOINT = "mc_tx_sp";
2306
+
2307
+ class NodeSqliteDatabase extends DatabaseSync {
2308
+ constructor(filename, options) {
2309
+ const translated = { ...options };
2310
+ if (options && "readonly" in options) {
2311
+ translated.readOnly = options.readonly;
2312
+ delete translated.readonly;
2313
+ }
2314
+ super(typeof filename === "string" ? filename : ":memory:", translated);
2315
+ }
2316
+ prepare(sql) {
2317
+ const stmt = super.prepare(sql);
2318
+ for (const method of ["run", "get", "all"]) {
2319
+ const original = stmt[method].bind(stmt);
2320
+ stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
2321
+ }
2322
+ return stmt;
2323
+ }
2324
+ transaction(fn) {
2325
+ const self = this;
2326
+ const execute = (mode, receiver, args) => {
2327
+ const nested = self.isTransaction === true;
2328
+ self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : `BEGIN${mode ? ` ${mode}` : ""}`);
2329
+ try {
2330
+ const result = fn.apply(receiver, args);
2331
+ self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
2332
+ return result;
2333
+ } catch (error) {
2334
+ if (nested) {
2335
+ self.exec(`ROLLBACK TO ${SAVEPOINT}`);
2336
+ self.exec(`RELEASE ${SAVEPOINT}`);
2337
+ } else {
2338
+ self.exec("ROLLBACK");
2339
+ }
2340
+ throw error;
2341
+ }
2342
+ };
2343
+ const wrapped = function(...args) {
2344
+ return execute("", this, args);
2345
+ };
2346
+ wrapped.default = function(...args) {
2347
+ return execute("", this, args);
2348
+ };
2349
+ wrapped.deferred = function(...args) {
2350
+ return execute("DEFERRED", this, args);
2351
+ };
2352
+ wrapped.immediate = function(...args) {
2353
+ return execute("IMMEDIATE", this, args);
2354
+ };
2355
+ wrapped.exclusive = function(...args) {
2356
+ return execute("EXCLUSIVE", this, args);
2357
+ };
2358
+ return wrapped;
2359
+ }
2360
+ }
2361
+ return NodeSqliteDatabase;
2362
+ }
2363
+ var Database = TrackedDatabase;
2364
+ var privilegeDepth = new WeakMap;
2365
+ function isInTransaction(db) {
2366
+ const candidate = db;
2367
+ return candidate.inTransaction === true || candidate.isTransaction === true;
2368
+ }
2369
+ function withPrivilegedWriter(db, operation) {
2370
+ const previousDepth = privilegeDepth.get(db) ?? 0;
2371
+ const nested = isInTransaction(db);
2372
+ const savepoint = "mc_privilege_scope";
2373
+ const transactionStartedAt = nested ? undefined : performance.now();
2374
+ if (nested) {
2375
+ db.exec(`SAVEPOINT ${savepoint}`);
2376
+ } else {
2377
+ db.exec("BEGIN IMMEDIATE");
2378
+ }
2379
+ privilegeDepth.set(db, previousDepth + 1);
2380
+ try {
2381
+ db.prepare("INSERT INTO context_privilege_state(id, enabled) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET enabled = 1").run();
2382
+ const result = operation();
2383
+ if (previousDepth === 0) {
2384
+ db.prepare("UPDATE context_privilege_state SET enabled = 0 WHERE id = 1").run();
2385
+ }
2386
+ if (nested) {
2387
+ db.exec(`RELEASE ${savepoint}`);
2388
+ } else {
2389
+ db.exec("COMMIT");
2390
+ if (transactionStartedAt !== undefined) {
2391
+ reportSlowPrivilegedWrite?.("privileged_writer", transactionStartedAt);
2392
+ }
2393
+ }
2394
+ if (previousDepth > 0)
2395
+ privilegeDepth.set(db, previousDepth);
2396
+ else
2397
+ privilegeDepth.delete(db);
2398
+ return result;
2399
+ } catch (error) {
2400
+ try {
2401
+ if (nested) {
2402
+ db.exec(`ROLLBACK TO ${savepoint}`);
2403
+ db.exec(`RELEASE ${savepoint}`);
2404
+ } else {
2405
+ db.exec("ROLLBACK");
2406
+ }
2407
+ } finally {
2408
+ if (previousDepth > 0)
2409
+ privilegeDepth.set(db, previousDepth);
2410
+ else
2411
+ privilegeDepth.delete(db);
2412
+ }
2413
+ throw error;
2414
+ }
2415
+ }
2416
+
2417
+ // ../plugin/src/shared/sqlite-helpers.ts
2418
+ function closeQuietly(db) {
2419
+ if (!db)
2420
+ return;
2421
+ try {
2422
+ db.close();
2423
+ } catch {}
2424
+ }
2425
+
2426
+ // ../plugin/src/hooks/magic-context/read-session-db.ts
2427
+ function openCodeDbExists() {
2428
+ return openCodeDbPathExists(resolveOpenCodeDbPath());
2429
+ }
2430
+ var cachedReadOnlyDb = null;
2431
+ function closeCachedReadOnlyDb() {
2432
+ if (!cachedReadOnlyDb) {
2433
+ return;
2434
+ }
2435
+ try {
2436
+ closeQuietly(cachedReadOnlyDb.db);
2437
+ } catch (error) {
2438
+ log("[magic-context] failed to close cached OpenCode read-only DB:", error);
2439
+ } finally {
2440
+ cachedReadOnlyDb = null;
2441
+ }
2442
+ }
2443
+ function getReadOnlySessionDb() {
2444
+ const resolution = resolveOpenCodeDbPath();
2445
+ const dbPath = resolution.path;
2446
+ if (!openCodeDbPathExists(resolution)) {
2447
+ throw new Error(`OpenCode session database is unavailable at ${dbPath} (source=${resolution.source})`);
2448
+ }
2449
+ if (cachedReadOnlyDb?.path === dbPath) {
2450
+ return cachedReadOnlyDb.db;
2451
+ }
2452
+ closeCachedReadOnlyDb();
2453
+ const db = new Database(dbPath, { readonly: true });
2454
+ try {
2455
+ assertOpenCodeStoreGeneration(db, "v1", dbPath);
2456
+ } catch (error) {
2457
+ closeQuietly(db);
2458
+ throw error;
2459
+ }
2460
+ cachedReadOnlyDb = { path: dbPath, db };
2461
+ clearOpenCodeDbReadFailure();
2462
+ return db;
2463
+ }
2464
+ function withReadOnlySessionDb(fn) {
2465
+ return fn(getReadOnlySessionDb());
2466
+ }
2467
+ function getRawSessionMessageCountFromDb(db, sessionId) {
2468
+ const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
2469
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
2470
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
2471
+ return typeof row?.count === "number" ? row.count : 0;
2472
+ }
2473
+ var trackedSessions = new Map;
2474
+ var pendingParts = new Map;
2475
+ var probeLogObserverForTests;
2476
+ function logProbeFailureOnce(resolution, error) {
2477
+ const failure = recordOpenCodeDbReadFailure(resolution, error);
2478
+ if (!claimOpenCodeDbDiagnosticOnce("session-state-probe", resolution))
2479
+ return;
2480
+ const message = `[magic-context] OpenCode DB probe failed: path=${resolution.path} source=${resolution.source} cause=${failure.message}`;
2481
+ probeLogObserverForTests?.(message);
2482
+ log(message);
2483
+ }
2484
+ function getMessageTimesFromOpenCodeDb(sessionId, messageIds) {
2485
+ const result = new Map;
2486
+ if (messageIds.length === 0)
2487
+ return result;
2488
+ try {
2489
+ withReadOnlySessionDb((db) => {
2490
+ const placeholders = messageIds.map(() => "?").join(",");
2491
+ const rows = db.prepare(`SELECT id, time_created FROM message WHERE session_id = ? AND id IN (${placeholders})`).all(sessionId, ...messageIds);
2492
+ for (const row of rows) {
2493
+ if (typeof row.id === "string" && typeof row.time_created === "number") {
2494
+ result.set(row.id, row.time_created);
2495
+ }
2496
+ }
2497
+ });
2498
+ } catch (error) {
2499
+ logProbeFailureOnce(resolveOpenCodeDbPath(), error);
2500
+ }
2501
+ return result;
2502
+ }
2503
+
2504
+ // ../plugin/src/hooks/magic-context/read-session-raw.ts
2505
+ 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";
2506
+ function isRawMessageRow(row) {
2507
+ if (row === null || typeof row !== "object")
2508
+ return false;
2509
+ const candidate = row;
2510
+ return typeof candidate.id === "string" && typeof candidate.data === "string";
2511
+ }
2512
+ function isRawPartRow(row) {
2513
+ if (row === null || typeof row !== "object")
2514
+ return false;
2515
+ const candidate = row;
2516
+ return typeof candidate.message_id === "string" && typeof candidate.data === "string";
2517
+ }
2518
+ function parseJsonRecord(value) {
2519
+ try {
2520
+ const parsed = JSON.parse(value);
2521
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
2522
+ return null;
2523
+ }
2524
+ return parsed;
2525
+ } catch {
2526
+ return null;
2527
+ }
2528
+ }
2529
+ function isRawCompactionSummaryInfo(info) {
2530
+ if (info === null || typeof info !== "object" || Array.isArray(info))
2531
+ return false;
2532
+ const candidate = info;
2533
+ return candidate.summary === true && candidate.finish === "stop";
2534
+ }
2535
+ function parseJsonUnknown(value) {
2536
+ try {
2537
+ return JSON.parse(value);
2538
+ } catch {
2539
+ return null;
2540
+ }
2541
+ }
2542
+ function attachRawPartVersion(value, timeUpdated) {
2543
+ if (value === null || typeof value !== "object" || Array.isArray(value))
2544
+ return value;
2545
+ if (typeof timeUpdated !== "number")
2546
+ return value;
2547
+ try {
2548
+ Object.defineProperty(value, "__magicContextPartUpdatedAt", {
2549
+ value: timeUpdated,
2550
+ enumerable: false,
2551
+ configurable: true
2552
+ });
2553
+ } catch {}
2554
+ return value;
2555
+ }
2556
+ function readRawSessionMessagesFromDb(db, sessionId) {
2557
+ 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);
2558
+ const partsByMessageId = new Map;
2559
+ const partMessageBatchSize = 128;
2560
+ for (let offset = 0;offset < messageRows.length; offset += partMessageBatchSize) {
2561
+ const messageIds = messageRows.slice(offset, offset + partMessageBatchSize).map((row) => row.id);
2562
+ if (messageIds.length === 0)
2563
+ continue;
2564
+ const placeholders = messageIds.map(() => "?").join(", ");
2565
+ const partRows = db.prepare(`SELECT message_id, data, time_updated
2566
+ FROM part
2567
+ WHERE +session_id = ?
2568
+ AND likelihood(message_id IN (${placeholders}), 0.000001)
2569
+ ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageIds).filter(isRawPartRow);
2570
+ for (const part of partRows) {
2571
+ const list = partsByMessageId.get(part.message_id) ?? [];
2572
+ list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
2573
+ partsByMessageId.set(part.message_id, list);
2574
+ }
2575
+ }
2576
+ const filtered = messageRows.filter((row) => !isRawCompactionSummaryInfo(parseJsonRecord(row.data)));
2577
+ return filtered.flatMap((row, index) => {
2578
+ const info = parseJsonRecord(row.data);
2579
+ if (!info)
2580
+ return [];
2581
+ const role = typeof info.role === "string" ? info.role : "unknown";
2582
+ return {
2583
+ ordinal: index + 1,
2584
+ id: row.id,
2585
+ role,
2586
+ parts: partsByMessageId.get(row.id) ?? [],
2587
+ createdAt: row.time_created ?? null,
2588
+ version: row.time_updated ?? null
2589
+ };
2590
+ });
2591
+ }
2592
+ function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER) {
2593
+ const remaining = Math.max(0, Math.floor(finalWatermark) - Math.floor(afterOrdinal));
2594
+ const pageSize = Math.min(Math.max(1, Math.floor(limit)), remaining);
2595
+ if (pageSize === 0)
2596
+ return [];
2597
+ const messageRows = db.prepare(`SELECT id, data, time_created, time_updated
2598
+ FROM message
2599
+ WHERE session_id = ?
2600
+ AND NOT (
2601
+ CASE WHEN json_valid(data) = 1
2602
+ THEN COALESCE(json_extract(data, '$.summary'), 0)
2603
+ ELSE 0 END = 1
2604
+ AND CASE WHEN json_valid(data) = 1
2605
+ THEN COALESCE(json_extract(data, '$.finish'), '')
2606
+ ELSE '' END = 'stop'
2607
+ )
2608
+ ORDER BY time_created ASC, id ASC
2609
+ LIMIT ? OFFSET ?`).all(sessionId, pageSize, Math.max(0, Math.floor(afterOrdinal))).filter(isRawMessageRow).map((row, index) => ({
2610
+ ...row,
2611
+ ordinal: Math.floor(afterOrdinal) + index + 1
2612
+ }));
2613
+ if (messageRows.length === 0)
2614
+ return [];
2615
+ const placeholders = messageRows.map(() => "?").join(", ");
2616
+ const partRows = db.prepare(`SELECT message_id, data, time_updated
2617
+ FROM part
2618
+ WHERE +session_id = ?
2619
+ AND likelihood(message_id IN (${placeholders}), 0.000001)
2620
+ ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
2621
+ const partsByMessageId = new Map;
2622
+ for (const part of partRows) {
2623
+ const list = partsByMessageId.get(part.message_id) ?? [];
2624
+ list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
2625
+ partsByMessageId.set(part.message_id, list);
2626
+ }
2627
+ return messageRows.map((row) => {
2628
+ const info = parseJsonRecord(row.data);
2629
+ return {
2630
+ ordinal: row.ordinal,
2631
+ id: row.id,
2632
+ role: typeof info?.role === "string" ? info.role : "unknown",
2633
+ parts: partsByMessageId.get(row.id) ?? [],
2634
+ createdAt: row.time_created ?? null,
2635
+ version: row.time_updated ?? null
2636
+ };
2637
+ });
2638
+ }
2639
+ function countRawSessionMessageOrdinalsFromDb(db, sessionId) {
2640
+ const row = db.prepare(`SELECT COUNT(*) AS count
2641
+ FROM message
2642
+ WHERE session_id = ?
2643
+ AND NOT (
2644
+ CASE WHEN json_valid(data) = 1
2645
+ THEN COALESCE(json_extract(data, '$.summary'), 0)
2646
+ ELSE 0 END = 1
2647
+ AND CASE WHEN json_valid(data) = 1
2648
+ THEN COALESCE(json_extract(data, '$.finish'), '')
2649
+ ELSE '' END = 'stop'
2650
+ )`).get(sessionId);
2651
+ return typeof row?.count === "number" ? row.count : 0;
2652
+ }
2653
+ function readRawSessionMessageIdOrdinalsFromDb(db, sessionId) {
2654
+ const messageRows = db.prepare("SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
2655
+ const ordinalById = new Map;
2656
+ let ordinal = 0;
2657
+ for (const row of messageRows) {
2658
+ const info = parseJsonRecord(row.data);
2659
+ if (isRawCompactionSummaryInfo(info))
2660
+ continue;
2661
+ ordinal += 1;
2662
+ if (info)
2663
+ ordinalById.set(row.id, ordinal);
2664
+ }
2665
+ return ordinalById;
2666
+ }
2667
+ function isAnchorRow(row) {
2668
+ return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
2669
+ }
2670
+ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
2671
+ const anchorRow = db.prepare("SELECT time_created, id, data FROM message WHERE id = ? AND session_id = ?").get(anchorMessageId, sessionId);
2672
+ if (!isAnchorRow(anchorRow))
2673
+ return null;
2674
+ const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
2675
+ if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
2676
+ return null;
2677
+ const messageRows = db.prepare(`SELECT id, data, time_created, time_updated FROM message
2678
+ WHERE session_id = ?
2679
+ AND (time_created > ? OR (time_created = ? AND id >= ?))
2680
+ ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
2681
+ const filtered = messageRows.filter((row) => {
2682
+ const info = parseJsonRecord(row.data);
2683
+ return !(info?.summary === true && info?.finish === "stop");
2684
+ });
2685
+ const ids = filtered.map((row) => row.id);
2686
+ const partsByMessageId = new Map;
2687
+ if (ids.length > 0) {
2688
+ const CHUNK = 800;
2689
+ for (let i = 0;i < ids.length; i += CHUNK) {
2690
+ const slice = ids.slice(i, i + CHUNK);
2691
+ const placeholders = slice.map(() => "?").join(",");
2692
+ 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);
2693
+ for (const part of partRows) {
2694
+ const list = partsByMessageId.get(part.message_id) ?? [];
2695
+ list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
2696
+ partsByMessageId.set(part.message_id, list);
2697
+ }
2698
+ }
2699
+ }
2700
+ const messages = [];
2701
+ let ord = baseOrdinal;
2702
+ for (const row of filtered) {
2703
+ const info = parseJsonRecord(row.data);
2704
+ if (!info) {
2705
+ ord += 1;
2706
+ continue;
2707
+ }
2708
+ messages.push({
2709
+ ordinal: ord,
2710
+ id: row.id,
2711
+ role: typeof info.role === "string" ? info.role : "unknown",
2712
+ parts: partsByMessageId.get(row.id) ?? [],
2713
+ createdAt: row.time_created ?? null,
2714
+ version: row.time_updated ?? null
2715
+ });
2716
+ ord += 1;
2717
+ }
2718
+ return { messages, absoluteMessageCount: Math.max(0, ord - 1) };
2719
+ }
2720
+ function readRawSessionMessageByIdFromDb(db, sessionId, messageId) {
2721
+ const row = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? AND id = ?").get(sessionId, messageId);
2722
+ if (!row || !isRawMessageRow(row) || typeof row.time_created !== "number") {
2723
+ return null;
2724
+ }
2725
+ const info = parseJsonRecord(row.data);
2726
+ if (!info || isRawCompactionSummaryInfo(info)) {
2727
+ return null;
2728
+ }
2729
+ const ordinalRow = db.prepare(`SELECT COUNT(*) AS ordinal FROM message
2730
+ WHERE session_id = ?
2731
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
2732
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
2733
+ AND (time_created < ? OR (time_created = ? AND id <= ?))`).get(sessionId, row.time_created, row.time_created, messageId);
2734
+ const ordinal = typeof ordinalRow?.ordinal === "number" ? ordinalRow.ordinal : 0;
2735
+ if (ordinal <= 0) {
2736
+ return null;
2737
+ }
2738
+ const partRows = db.prepare(RAW_MESSAGE_PARTS_BY_ID_SQL).all(sessionId, messageId).filter(isRawPartRow);
2739
+ const role = typeof info.role === "string" ? info.role : "unknown";
2740
+ return {
2741
+ ordinal,
2742
+ id: row.id,
2743
+ role,
2744
+ parts: partRows.map((part) => attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated)),
2745
+ createdAt: row.time_created,
2746
+ version: row.time_updated ?? null
2747
+ };
2748
+ }
2749
+
2750
+ // ../plugin/src/hooks/magic-context/read-session-true-raw-tokens.ts
2751
+ function completedToolArcCrossesBoundary(invOrdinal, resOrdinal, boundary) {
2752
+ return invOrdinal < boundary && boundary <= resOrdinal;
2753
+ }
2754
+ var MAX_MESSAGE_CACHE_ENTRIES = 1e5;
2755
+ var MAX_MESSAGE_CACHE_KEY_BYTES = 64 * 1024 * 1024;
2756
+ var FNV1A_32_OFFSET = 2166136261;
2757
+ var FNV1A_32_PRIME = 16777619;
2758
+ var messageEstimateCache = new Map;
2759
+ var messageEstimateCacheBytes = 0;
2760
+ var EMPTY_BREAKDOWN = {
2761
+ text: 0,
2762
+ reasoning: 0,
2763
+ toolInput: 0,
2764
+ toolOutput: 0,
2765
+ image: 0,
2766
+ other: 0,
2767
+ total: 0
2768
+ };
2769
+ function addBreakdown(target, kind, value) {
2770
+ if (kind === "total")
2771
+ return;
2772
+ const safeValue = Number.isFinite(value) && value > 0 ? Math.round(value) : 0;
2773
+ target[kind] += safeValue;
2774
+ target.total += safeValue;
2775
+ }
2776
+ function estimateStructured(value) {
2777
+ if (typeof value === "string")
2778
+ return estimateTokens(value);
2779
+ if (value === undefined || value === null)
2780
+ return 0;
2781
+ return estimateTokens(stableStringify(value));
2782
+ }
2783
+ function firstStringField(record, fields) {
2784
+ for (const field of fields) {
2785
+ const value = record[field];
2786
+ if (typeof value === "string" && value.length > 0)
2787
+ return value;
2788
+ }
2789
+ return null;
2790
+ }
2791
+ function stringValue(value) {
2792
+ if (typeof value === "string")
2793
+ return value;
2794
+ if (value === undefined || value === null)
2795
+ return "";
2796
+ return stableStringify(value);
2797
+ }
2798
+ function textFromToolResultContent(content) {
2799
+ if (typeof content === "string")
2800
+ return content;
2801
+ if (Array.isArray(content)) {
2802
+ const pieces = [];
2803
+ for (const entry of content) {
2804
+ if (typeof entry === "string") {
2805
+ pieces.push(entry);
2806
+ } else if (isRecord(entry)) {
2807
+ const text = firstStringField(entry, ["text", "content", "value"]);
2808
+ pieces.push(text ?? stableStringify(entry));
2809
+ } else if (entry !== null && entry !== undefined) {
2810
+ pieces.push(String(entry));
2811
+ }
2812
+ }
2813
+ return pieces.join(`
2814
+ `);
2815
+ }
2816
+ return stringValue(content);
2817
+ }
2818
+ function looksImageLike(part) {
2819
+ const type = typeof part.type === "string" ? part.type.toLowerCase() : "";
2820
+ const mime = typeof part.mime === "string" ? part.mime.toLowerCase() : "";
2821
+ const mediaType = typeof part.mediaType === "string" ? part.mediaType.toLowerCase() : "";
2822
+ return type.includes("image") || mime.startsWith("image/") || mediaType.startsWith("image/") || part.image_url !== undefined || part.imageUrl !== undefined || part.image !== undefined;
2823
+ }
2824
+ function defaultImageTokenHeuristic(part) {
2825
+ if (isRecord(part)) {
2826
+ const width = part.width;
2827
+ const height = part.height;
2828
+ if (typeof width === "number" && typeof height === "number" && width > 0 && height > 0) {
2829
+ return Math.max(256, Math.min(4096, Math.ceil(width * height / 750)));
2830
+ }
2831
+ }
2832
+ return 1024;
2833
+ }
2834
+ function partType(part) {
2835
+ return typeof part.type === "string" ? part.type : "";
2836
+ }
2837
+ function hasOwn(record, key) {
2838
+ return Object.hasOwn(record, key);
2839
+ }
2840
+ function recursiveByteLength(value) {
2841
+ if (value === null || value === undefined)
2842
+ return 0;
2843
+ if (typeof value === "string")
2844
+ return value.length;
2845
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
2846
+ return String(value).length;
2847
+ }
2848
+ if (Array.isArray(value)) {
2849
+ return value.reduce((sum, item) => sum + recursiveByteLength(item), value.length);
2850
+ }
2851
+ if (isRecord(value)) {
2852
+ let total = Object.keys(value).length;
2853
+ for (const [key, child] of Object.entries(value)) {
2854
+ total += key.length + recursiveByteLength(child);
2855
+ }
2856
+ return total;
2857
+ }
2858
+ return String(value).length;
2859
+ }
2860
+ function updateFnv1a32(hash, text) {
2861
+ let next = hash;
2862
+ for (let index = 0;index < text.length; index += 1) {
2863
+ next ^= text.charCodeAt(index);
2864
+ next = Math.imul(next, FNV1A_32_PRIME) >>> 0;
2865
+ }
2866
+ return next;
2867
+ }
2868
+ function contentStringsHash(fields) {
2869
+ let hash = FNV1A_32_OFFSET;
2870
+ for (const field of fields) {
2871
+ hash = updateFnv1a32(hash, `${field.length}:`);
2872
+ hash = updateFnv1a32(hash, field);
2873
+ hash = updateFnv1a32(hash, "\x00");
2874
+ }
2875
+ return hash.toString(16).padStart(8, "0");
2876
+ }
2877
+ function rawPartVersion(part) {
2878
+ return part.__magicContextPartUpdatedAt ?? part.updated_at ?? part.updatedAt ?? part.version ?? part.revision ?? "";
2879
+ }
2880
+ function callIdFromPart(part) {
2881
+ const direct = firstStringField(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
2882
+ if (direct)
2883
+ return direct;
2884
+ const state = isRecord(part.state) ? part.state : null;
2885
+ return state ? firstStringField(state, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
2886
+ }
2887
+ function toolSignalFromPart(part) {
2888
+ if (!isRecord(part))
2889
+ return null;
2890
+ const type = partType(part);
2891
+ const state = isRecord(part.state) ? part.state : null;
2892
+ const callId = callIdFromPart(part);
2893
+ if (!callId && type !== "tool")
2894
+ return null;
2895
+ if (type === "tool") {
2896
+ const hasInput = state !== null && hasOwn(state, "input");
2897
+ const outputKey = state ? hasOwn(state, "output") ? "output" : hasOwn(state, "error") ? "error" : hasOwn(state, "result") ? "result" : null : null;
2898
+ const hasOutput = outputKey !== null;
2899
+ const outputValue = outputKey && state ? state[outputKey] : undefined;
2900
+ const providerExecuted = part.providerExecuted === true;
2901
+ const openInvocation = !providerExecuted && !hasOutput;
2902
+ return {
2903
+ callId,
2904
+ hasInput: hasInput || openInvocation,
2905
+ hasOutput,
2906
+ inputText: hasInput && state ? stringValue(state.input) : "",
2907
+ outputText: hasOutput ? stringValue(outputValue) : ""
2908
+ };
2909
+ }
2910
+ if (type === "tool-invocation") {
2911
+ const args = part.args ?? part.input;
2912
+ return {
2913
+ callId,
2914
+ hasInput: args !== undefined,
2915
+ hasOutput: false,
2916
+ inputText: args !== undefined ? stringValue(args) : "",
2917
+ outputText: ""
2918
+ };
2919
+ }
2920
+ if (type === "tool_use") {
2921
+ const input = part.input;
2922
+ return {
2923
+ callId,
2924
+ hasInput: input !== undefined,
2925
+ hasOutput: false,
2926
+ inputText: input !== undefined ? stringValue(input) : "",
2927
+ outputText: ""
2928
+ };
2929
+ }
2930
+ if (type === "tool_result") {
2931
+ const content = part.content ?? part.output ?? part.result;
2932
+ return {
2933
+ callId,
2934
+ hasInput: false,
2935
+ hasOutput: content !== undefined,
2936
+ inputText: "",
2937
+ outputText: content !== undefined ? textFromToolResultContent(content) : ""
2938
+ };
2939
+ }
2940
+ return null;
2941
+ }
2942
+ function partCheapFingerprint(part) {
2943
+ if (!isRecord(part))
2944
+ return `${typeof part}:${recursiveByteLength(part)}`;
2945
+ const version = rawPartVersion(part);
2946
+ const type = typeof part.type === "string" ? part.type : "";
2947
+ return `${type}:${String(version)}:${recursiveByteLength(part)}`;
2948
+ }
2949
+ function messageCacheKey(message, options) {
2950
+ const namespace = "cacheNamespace" in options ? options.cacheNamespace : "estimate";
2951
+ const cheapFingerprint = message.parts.map(partCheapFingerprint).join("|");
2952
+ return [
2953
+ namespace,
2954
+ options.providerShapeVersion,
2955
+ message.id || `ordinal:${message.ordinal}`,
2956
+ message.role,
2957
+ message.parts.length,
2958
+ cheapFingerprint
2959
+ ].join("\x00");
2960
+ }
2961
+ function setCachedEstimate(key, breakdown) {
2962
+ const keyEstimateBytes = key.length * 2 + 64;
2963
+ const existing = messageEstimateCache.get(key);
2964
+ if (existing)
2965
+ messageEstimateCacheBytes -= existing.keyEstimateBytes;
2966
+ messageEstimateCache.set(key, { breakdown, keyEstimateBytes });
2967
+ messageEstimateCacheBytes += keyEstimateBytes;
2968
+ while (messageEstimateCache.size > MAX_MESSAGE_CACHE_ENTRIES || messageEstimateCacheBytes > MAX_MESSAGE_CACHE_KEY_BYTES) {
2969
+ const first = messageEstimateCache.keys().next().value;
2970
+ if (typeof first !== "string")
2971
+ break;
2972
+ const removed = messageEstimateCache.get(first);
2973
+ if (removed)
2974
+ messageEstimateCacheBytes -= removed.keyEstimateBytes;
2975
+ messageEstimateCache.delete(first);
2976
+ }
2977
+ }
2978
+ function cloneBreakdown(value) {
2979
+ return { ...value };
2980
+ }
2981
+ function estimateNonToolPart(part, options, breakdown) {
2982
+ if (!isRecord(part)) {
2983
+ if (part !== null && part !== undefined)
2984
+ addBreakdown(breakdown, "other", estimateStructured(part));
2985
+ return true;
2986
+ }
2987
+ const type = partType(part);
2988
+ if (type === "step-start" || type === "step-finish" || type === "meta" && Object.keys(part).length <= 1) {
2989
+ return true;
2990
+ }
2991
+ if (type === "text") {
2992
+ const text = firstStringField(part, ["text", "content"]);
2993
+ if (text)
2994
+ addBreakdown(breakdown, "text", estimateTokens(text));
2995
+ return true;
2996
+ }
2997
+ if (type === "reasoning" || type === "thinking" || type === "redacted_thinking") {
2998
+ const text = firstStringField(part, ["thinking", "text", "content", "reasoning"]);
2999
+ if (text) {
3000
+ addBreakdown(breakdown, "reasoning", estimateTokens(text));
3001
+ } else {
3002
+ addBreakdown(breakdown, "other", estimateStructured(part));
3003
+ }
3004
+ return true;
3005
+ }
3006
+ const reasoningText = firstStringField(part, ["thinking", "reasoning"]);
3007
+ if (reasoningText && type.length === 0) {
3008
+ addBreakdown(breakdown, "reasoning", estimateTokens(reasoningText));
3009
+ return true;
3010
+ }
3011
+ if (looksImageLike(part)) {
3012
+ addBreakdown(breakdown, "image", options.imageTokenHeuristic?.(part) ?? defaultImageTokenHeuristic(part));
3013
+ const altText = firstStringField(part, ["alt", "text", "description"]);
3014
+ if (altText)
3015
+ addBreakdown(breakdown, "text", estimateTokens(altText));
3016
+ return true;
3017
+ }
3018
+ if (type.includes("file") || type === "source") {
3019
+ const content = firstStringField(part, ["content", "text", "source"]);
3020
+ if (content)
3021
+ addBreakdown(breakdown, "text", estimateTokens(content));
3022
+ else
3023
+ addBreakdown(breakdown, "other", estimateStructured(part));
3024
+ return true;
3025
+ }
3026
+ return false;
3027
+ }
3028
+ function estimateTrueRawMessageTokens(message, options) {
3029
+ const breakdown = cloneBreakdown(EMPTY_BREAKDOWN);
3030
+ const countedInput = new Set;
3031
+ const countedOutput = new Set;
3032
+ let ordinalToolIndex = 0;
3033
+ for (const part of message.parts) {
3034
+ const signal = toolSignalFromPart(part);
3035
+ if (signal) {
3036
+ const localKey = `${signal.callId || "tool"}:${message.ordinal}:${ordinalToolIndex}`;
3037
+ ordinalToolIndex += 1;
3038
+ if (signal.hasInput) {
3039
+ const key = `${signal.callId}:input:${message.ordinal}`;
3040
+ if (!countedInput.has(key)) {
3041
+ countedInput.add(key);
3042
+ addBreakdown(breakdown, "toolInput", estimateTokens(signal.inputText));
3043
+ }
3044
+ }
3045
+ if (signal.hasOutput) {
3046
+ const key = `${signal.callId}:output:${message.ordinal}:${localKey}`;
3047
+ if (!countedOutput.has(key)) {
3048
+ countedOutput.add(key);
3049
+ addBreakdown(breakdown, "toolOutput", estimateTokens(signal.outputText));
3050
+ }
3051
+ }
3052
+ continue;
3053
+ }
3054
+ if (!estimateNonToolPart(part, options, breakdown)) {
3055
+ addBreakdown(breakdown, "other", estimateStructured(part));
3056
+ }
3057
+ }
3058
+ return breakdown;
3059
+ }
3060
+ function buildToolArcs(messages) {
3061
+ const openQueues = new Map;
3062
+ const arcs = [];
3063
+ for (const message of messages) {
3064
+ for (const part of message.parts) {
3065
+ const signal = toolSignalFromPart(part);
3066
+ if (!signal || signal.callId.length === 0)
3067
+ continue;
3068
+ if (signal.hasInput && signal.hasOutput) {
3069
+ arcs.push({
3070
+ callId: signal.callId,
3071
+ invOrdinal: message.ordinal,
3072
+ resOrdinal: message.ordinal
3073
+ });
3074
+ continue;
3075
+ }
3076
+ if (signal.hasInput) {
3077
+ const queue = openQueues.get(signal.callId) ?? [];
3078
+ queue.push(message.ordinal);
3079
+ openQueues.set(signal.callId, queue);
3080
+ continue;
3081
+ }
3082
+ if (signal.hasOutput) {
3083
+ const queue = openQueues.get(signal.callId) ?? [];
3084
+ const invOrdinal = queue.shift();
3085
+ if (queue.length === 0)
3086
+ openQueues.delete(signal.callId);
3087
+ else
3088
+ openQueues.set(signal.callId, queue);
3089
+ if (invOrdinal !== undefined) {
3090
+ arcs.push({ callId: signal.callId, invOrdinal, resOrdinal: message.ordinal });
3091
+ }
3092
+ }
3093
+ }
3094
+ }
3095
+ for (const [callId, queue] of openQueues) {
3096
+ for (const invOrdinal of queue) {
3097
+ arcs.push({ callId, invOrdinal, resOrdinal: null });
3098
+ }
3099
+ }
3100
+ return arcs.sort((a, b) => a.invOrdinal - b.invOrdinal || (a.resOrdinal ?? Number.MAX_SAFE_INTEGER) - (b.resOrdinal ?? Number.MAX_SAFE_INTEGER));
3101
+ }
3102
+ function fenceBoundaryForCompletedToolArcs(candidate, arcs, publicationFloorOrdinal, observeComponent) {
3103
+ const completed = arcs.filter((arc) => arc.resOrdinal !== null).map((arc) => ({ invocation: arc.invOrdinal, result: arc.resOrdinal }));
3104
+ const component = completed.filter((arc) => completedToolArcCrossesBoundary(arc.invocation, arc.result, candidate));
3105
+ if (component.length === 0)
3106
+ return candidate;
3107
+ for (let pass = 0;pass <= completed.length; pass += 1) {
3108
+ const minInvocation = Math.min(...component.map((arc) => arc.invocation));
3109
+ const maxResult = Math.max(...component.map((arc) => arc.result));
3110
+ const before = component.length;
3111
+ for (const arc of completed) {
3112
+ if (arc.invocation <= maxResult && arc.result >= minInvocation && !component.includes(arc)) {
3113
+ component.push(arc);
3114
+ }
3115
+ }
3116
+ if (component.length === before)
3117
+ break;
3118
+ }
3119
+ const minInvocation = Math.min(...component.map((arc) => arc.invocation));
3120
+ const maxResult = Math.max(...component.map((arc) => arc.result));
3121
+ observeComponent?.(component);
3122
+ return minInvocation < publicationFloorOrdinal ? maxResult + 1 : minInvocation;
3123
+ }
3124
+ function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal, recentOpenArcCutoff) {
3125
+ const boundary = fenceBoundaryForCompletedToolArcs(candidate, arcs, lastCompartmentEndOrdinal + 1);
3126
+ for (const arc of arcs) {
3127
+ if (arc.resOrdinal !== null)
3128
+ continue;
3129
+ if (arc.invOrdinal < recentOpenArcCutoff)
3130
+ continue;
3131
+ if (arc.invOrdinal >= lastCompartmentEndOrdinal + 1 && arc.invOrdinal < boundary) {
3132
+ return arc.invOrdinal;
3133
+ }
3134
+ if (arc.invOrdinal >= boundary) {
3135
+ return arc.invOrdinal;
3136
+ }
3137
+ }
3138
+ return boundary;
3139
+ }
3140
+ function tokenForMessage(message, options) {
3141
+ const key = messageCacheKey(message, options);
3142
+ const cached = messageEstimateCache.get(key);
3143
+ if (cached)
3144
+ return cloneBreakdown(cached.breakdown);
3145
+ const breakdown = estimateTrueRawMessageTokens(message, options);
3146
+ setCachedEstimate(key, breakdown);
3147
+ return cloneBreakdown(breakdown);
3148
+ }
3149
+ function buildTrueRawTokenIndex(sessionId, messages, options) {
3150
+ const ordered = [...messages].sort((a, b) => a.ordinal - b.ordinal);
3151
+ const sliceCount = ordered.length;
3152
+ const firstOrdinal = ordered.length > 0 ? ordered[0].ordinal : 1;
3153
+ const terminalOrdinal = ordered.length > 0 ? ordered[ordered.length - 1].ordinal : 0;
3154
+ const rawMessageCount = Math.max(sliceCount, terminalOrdinal, options.absoluteMessageCount ?? sliceCount);
3155
+ const ordinalSpan = terminalOrdinal >= firstOrdinal ? terminalOrdinal - firstOrdinal + 1 : 0;
3156
+ const tokensByOrdinal = new Map;
3157
+ const idsByOrdinal = new Map;
3158
+ const prefix = new Array(ordinalSpan + 1).fill(0);
3159
+ for (const message of ordered) {
3160
+ const stored = options.storedTotalForMessage?.(message);
3161
+ let total;
3162
+ if (stored !== undefined && stored !== null) {
3163
+ total = stored;
3164
+ } else {
3165
+ const raw = tokenForMessage(message, options);
3166
+ const seed = options.calibration;
3167
+ total = seed ? (raw.toolInput + raw.toolOutput) * seed.toolsRatio + (raw.text + raw.reasoning + raw.other) * seed.proseRatio + raw.image : raw.total;
3168
+ }
3169
+ tokensByOrdinal.set(message.ordinal, total);
3170
+ idsByOrdinal.set(message.ordinal, message.id);
3171
+ const relative = message.ordinal - firstOrdinal + 1;
3172
+ if (relative >= 1 && relative <= ordinalSpan) {
3173
+ prefix[relative] = total;
3174
+ }
3175
+ }
3176
+ for (let k = 1;k <= ordinalSpan; k += 1) {
3177
+ prefix[k] += prefix[k - 1];
3178
+ }
3179
+ const ordinalToIndex = (ordinal) => Math.max(0, Math.min(ordinalSpan, ordinal - firstOrdinal));
3180
+ return {
3181
+ sessionId,
3182
+ providerShapeVersion: options.providerShapeVersion,
3183
+ rawMessageCount,
3184
+ tokenForOrdinal(ordinal) {
3185
+ return tokensByOrdinal.get(ordinal) ?? 0;
3186
+ },
3187
+ messageIdAtOrdinal(ordinal) {
3188
+ return idsByOrdinal.get(ordinal) ?? null;
3189
+ },
3190
+ suffixTokensFromOrdinal(ordinal) {
3191
+ if (ordinal <= firstOrdinal)
3192
+ return prefix[ordinalSpan];
3193
+ if (ordinal > terminalOrdinal)
3194
+ return 0;
3195
+ return prefix[ordinalSpan] - prefix[ordinalToIndex(ordinal)];
3196
+ },
3197
+ rangeTokens(startInclusive, endExclusive) {
3198
+ const start = Math.max(firstOrdinal, startInclusive);
3199
+ const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
3200
+ return prefix[end - firstOrdinal] - prefix[start - firstOrdinal];
3201
+ },
3202
+ findSuffixStartForTokens(tokens) {
3203
+ if (!Number.isFinite(tokens) || tokens <= 0)
3204
+ return terminalOrdinal + 1;
3205
+ const target = Math.max(0, Math.floor(tokens));
3206
+ const total = prefix[ordinalSpan];
3207
+ if (total < target)
3208
+ return firstOrdinal;
3209
+ const cut = total - target;
3210
+ let lo = 0;
3211
+ let hi = ordinalSpan;
3212
+ let best = 0;
3213
+ while (lo <= hi) {
3214
+ const mid = lo + hi >> 1;
3215
+ if (prefix[mid] <= cut) {
3216
+ best = mid;
3217
+ lo = mid + 1;
3218
+ } else {
3219
+ hi = mid - 1;
3220
+ }
3221
+ }
3222
+ return firstOrdinal + best;
3223
+ },
3224
+ findHeadEndForCap(startInclusive, endExclusive, capTokens) {
3225
+ const start = Math.max(firstOrdinal, Math.min(terminalOrdinal + 1, startInclusive));
3226
+ const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
3227
+ if (!Number.isFinite(capTokens) || capTokens <= 0)
3228
+ return start;
3229
+ const startIndex = start - firstOrdinal;
3230
+ const endIndex = end - firstOrdinal;
3231
+ const cut = prefix[startIndex] + Math.floor(capTokens);
3232
+ let lo = startIndex + 1;
3233
+ let hi = endIndex;
3234
+ let bestEndIndex = startIndex;
3235
+ while (lo <= hi) {
3236
+ const mid = lo + hi >> 1;
3237
+ if (prefix[mid] <= cut) {
3238
+ bestEndIndex = mid;
3239
+ lo = mid + 1;
3240
+ } else {
3241
+ hi = mid - 1;
3242
+ }
3243
+ }
3244
+ let bestEnd = firstOrdinal + bestEndIndex;
3245
+ if (bestEnd === start && start < end)
3246
+ bestEnd = start + 1;
3247
+ return Math.min(bestEnd, end);
3248
+ }
3249
+ };
3250
+ }
3251
+ function partContentFingerprint(part) {
3252
+ if (!isRecord(part))
3253
+ return `${typeof part}:${recursiveByteLength(part)}`;
3254
+ const tool = toolSignalFromPart(part);
3255
+ if (tool) {
3256
+ return contentStringsHash([tool.inputText, tool.outputText]);
3257
+ }
3258
+ const text = firstStringField(part, ["text", "thinking", "reasoning", "content", "url"]) ?? "";
3259
+ return contentStringsHash([text]);
3260
+ }
3261
+ function computeRawRangeFingerprint(messages, startInclusive, endExclusive) {
3262
+ const pieces = [];
3263
+ for (const message of messages) {
3264
+ if (message.ordinal < startInclusive || message.ordinal >= endExclusive)
3265
+ continue;
3266
+ const partFingerprint = message.parts.map(partContentFingerprint).join(",");
3267
+ pieces.push(`${message.ordinal}:${message.id}:${message.parts.length}:${partFingerprint}`);
3268
+ }
3269
+ return pieces.join("|");
3270
+ }
3271
+ function invalidateTrueRawTokenCache(args) {
3272
+ const sessionNeedle = args.sessionId ? `${args.sessionId}` : null;
3273
+ const messageNeedle = args.messageId ? `\x00${args.messageId}\x00` : null;
3274
+ for (const [key, value] of messageEstimateCache) {
3275
+ const sessionMatches = sessionNeedle === null || key.includes(sessionNeedle);
3276
+ const messageMatches = messageNeedle === null || key.includes(messageNeedle);
3277
+ if (sessionMatches && messageMatches) {
3278
+ messageEstimateCache.delete(key);
3279
+ messageEstimateCacheBytes -= value.keyEstimateBytes;
3280
+ }
3281
+ }
3282
+ args.reason;
3283
+ }
3284
+
3285
+ // ../plugin/src/hooks/magic-context/tag-part-guards.ts
3286
+ function isTextPart(part) {
3287
+ if (part === null || typeof part !== "object")
3288
+ return false;
3289
+ const p = part;
3290
+ return p.type === "text" && typeof p.text === "string";
3291
+ }
3292
+ function isFilePart(part) {
3293
+ if (part === null || typeof part !== "object")
3294
+ return false;
3295
+ const p = part;
3296
+ return p.type === "file" && typeof p.url === "string";
3297
+ }
3298
+
3299
+ // ../plugin/src/hooks/magic-context/dropped-input-guard.ts
3300
+ var LEGACY_TRUNCATED_VALUE = /^[\s\S]{0,5}\.\.\.\[truncated\]$/;
3301
+ var MAX_QUOTED_ARGUMENTS = 160;
3302
+ var MAX_LISTED_PARAMETERS = 12;
3303
+ var MAX_TRACKED_SESSIONS = 1000;
3304
+ function isDroppedPlaceholderString(value) {
3305
+ return value.startsWith("[dropped §") && value.endsWith("§]") || LEGACY_TRUNCATED_VALUE.test(value) || value === "[object]" || /^\[\d+ items\]$/.test(value);
3306
+ }
3307
+ function droppedInputMarker(tagId) {
3308
+ return { dropped: `[dropped §${tagId}§]` };
3309
+ }
3310
+ function containsDroppedInputPlaceholder(value) {
3311
+ const seen = new WeakSet;
3312
+ const visit = (candidate) => {
3313
+ if (typeof candidate === "string")
3314
+ return isDroppedPlaceholderString(candidate);
3315
+ if (candidate === null || typeof candidate !== "object")
3316
+ return false;
3317
+ if (seen.has(candidate))
3318
+ return false;
3319
+ seen.add(candidate);
3320
+ if (Array.isArray(candidate))
3321
+ return candidate.some(visit);
3322
+ return Object.values(candidate).some(visit);
3323
+ };
3324
+ return visit(value);
3325
+ }
3326
+ function isRecord2(value) {
3327
+ return value !== null && typeof value === "object";
3328
+ }
3329
+ function isOptionalZodField(field) {
3330
+ if (!isRecord2(field))
3331
+ return false;
3332
+ const isOptional = field.isOptional;
3333
+ if (typeof isOptional === "function") {
3334
+ try {
3335
+ return isOptional.call(field) === true;
3336
+ } catch {}
3337
+ }
3338
+ const internals = field._zod;
3339
+ return internals?.optin === "optional";
3340
+ }
3341
+ function toolParameterNames(schema) {
3342
+ if (!isRecord2(schema))
3343
+ return;
3344
+ const properties = schema.properties;
3345
+ if (isRecord2(properties) && !Array.isArray(properties)) {
3346
+ const names = Object.keys(properties);
3347
+ const requiredList = Array.isArray(schema.required) ? schema.required : [];
3348
+ const required = new Set(requiredList.filter((name) => typeof name === "string"));
3349
+ return {
3350
+ required: names.filter((name) => required.has(name)),
3351
+ optional: names.filter((name) => !required.has(name))
3352
+ };
3353
+ }
3354
+ let shape;
3355
+ try {
3356
+ shape = schema.shape;
3357
+ } catch {
3358
+ shape = undefined;
3359
+ }
3360
+ if (isRecord2(shape) && !Array.isArray(shape)) {
3361
+ const result = { required: [], optional: [] };
3362
+ for (const [name, field] of Object.entries(shape)) {
3363
+ (isOptionalZodField(field) ? result.optional : result.required).push(name);
3364
+ }
3365
+ return result;
3366
+ }
3367
+ return;
3368
+ }
3369
+ var recordedToolParameters = new Map;
3370
+ function quoteArguments(input) {
3371
+ let text;
3372
+ try {
3373
+ text = JSON.stringify(input) ?? String(input);
3374
+ } catch {
3375
+ text = String(input);
3376
+ }
3377
+ return text.length > MAX_QUOTED_ARGUMENTS ? `${text.slice(0, MAX_QUOTED_ARGUMENTS - 1)}…` : text;
3378
+ }
3379
+ function ordinal(value) {
3380
+ const lastTwo = value % 100;
3381
+ if (lastTwo >= 11 && lastTwo <= 13)
3382
+ return `${value}th`;
3383
+ switch (value % 10) {
3384
+ case 1:
3385
+ return `${value}st`;
3386
+ case 2:
3387
+ return `${value}nd`;
3388
+ case 3:
3389
+ return `${value}rd`;
3390
+ default:
3391
+ return `${value}th`;
3392
+ }
3393
+ }
3394
+ function describeParameters(names) {
3395
+ if (!names || names.required.length + names.optional.length === 0) {
3396
+ return "the tool's own parameters";
3397
+ }
3398
+ const listed = [...names.required.map((name) => `${name} (required)`), ...names.optional];
3399
+ const shown = listed.slice(0, MAX_LISTED_PARAMETERS);
3400
+ const more = listed.length > shown.length ? ", …" : "";
3401
+ return `its parameters: ${shown.join(", ")}${more}`;
3402
+ }
3403
+ function droppedInputRefusalMessage(refusal) {
3404
+ const tool = refusal.toolName ? `\`${refusal.toolName}\`` : undefined;
3405
+ const names = toolParameterNames(refusal.parameters) ?? (refusal.toolName ? recordedToolParameters.get(refusal.toolName) : undefined);
3406
+ const lines = [];
3407
+ if (refusal.consecutive >= 2) {
3408
+ lines.push(`This is the ${ordinal(refusal.consecutive)} call in a row with placeholder arguments.`);
3409
+ }
3410
+ lines.push(`Not executed: your arguments${tool ? ` to ${tool}` : ""} were ${quoteArguments(refusal.input)}. That is the placeholder Magic Context shows in place of an earlier call's arguments, not a value to send. Nothing is wrong with the session or the tool.`, `Call ${tool ?? "the tool"} again with real values for ${describeParameters(names)}.`, "Only if you need the original arguments of an earlier dropped call, recover them with ctx_expand first.");
3411
+ return lines.join(`
3412
+ `);
3413
+ }
3414
+ function createDroppedInputGuard(options = {}) {
3415
+ const consecutiveBySession = new Map;
3416
+ return {
3417
+ check(call) {
3418
+ const session = call.sessionID ?? "";
3419
+ if (!containsDroppedInputPlaceholder(call.input)) {
3420
+ consecutiveBySession.delete(session);
3421
+ return;
3422
+ }
3423
+ const consecutive = (consecutiveBySession.get(session) ?? 0) + 1;
3424
+ consecutiveBySession.delete(session);
3425
+ consecutiveBySession.set(session, consecutive);
3426
+ if (consecutiveBySession.size > MAX_TRACKED_SESSIONS) {
3427
+ const oldest = consecutiveBySession.keys().next().value;
3428
+ if (oldest !== undefined)
3429
+ consecutiveBySession.delete(oldest);
3430
+ }
3431
+ let parameters;
3432
+ if (call.toolName && options.parametersFor) {
3433
+ try {
3434
+ parameters = options.parametersFor(call.toolName);
3435
+ } catch {
3436
+ parameters = undefined;
3437
+ }
3438
+ }
3439
+ return droppedInputRefusalMessage({
3440
+ toolName: call.toolName,
3441
+ input: call.input,
3442
+ parameters,
3443
+ consecutive
3444
+ });
3445
+ }
3446
+ };
3447
+ }
3448
+
3449
+ // ../plugin/src/hooks/magic-context/edit-marker.ts
3450
+ var TRUNCATION_SENTINEL = "...[truncated]";
3451
+ var EDIT_REGION_HINT_LEN = 40;
3452
+ var PATH_KEYS = new Set(["filePath", "file_path", "path"]);
3453
+ var DIFF_KEYS = new Set(["oldString", "newString", "content", "old_string", "new_string"]);
3454
+ function safeSlice(str, maxLen) {
3455
+ if (str.length <= maxLen)
3456
+ return str;
3457
+ const lastCharCode = str.charCodeAt(maxLen - 1);
3458
+ if (lastCharCode >= 55296 && lastCharCode <= 56319) {
3459
+ return str.slice(0, maxLen - 1);
3460
+ }
3461
+ return str.slice(0, maxLen);
3462
+ }
3463
+ function isEditTool(name) {
3464
+ return name === "edit" || name === "write";
3465
+ }
3466
+ function applyEditMarkerToInput(input) {
3467
+ for (const key of Object.keys(input)) {
3468
+ if (PATH_KEYS.has(key))
3469
+ continue;
3470
+ const value = input[key];
3471
+ if (typeof value !== "string" || !DIFF_KEYS.has(key))
3472
+ continue;
3473
+ if (value.endsWith(TRUNCATION_SENTINEL))
3474
+ continue;
3475
+ input[key] = value.length > EDIT_REGION_HINT_LEN ? `${safeSlice(value, EDIT_REGION_HINT_LEN)}${TRUNCATION_SENTINEL}` : value;
3476
+ }
3477
+ }
3478
+
3479
+ // ../plugin/src/features/magic-context/tool-definition-tokens.ts
3480
+ var measurements = new Map;
3481
+ var fingerprints = new Map;
3482
+ var persistenceDb = null;
3483
+ var cachedInsertStmt = null;
3484
+ function keyFor(providerID, modelID, agentName) {
3485
+ const agent = agentName && agentName.length > 0 ? agentName : "default";
3486
+ return `${providerID}/${modelID}/${agent}`;
3487
+ }
3488
+ function setDatabase(db) {
3489
+ persistenceDb = db;
3490
+ cachedInsertStmt = null;
3491
+ }
3492
+ function loadToolDefinitionMeasurements(db) {
3493
+ let rows = [];
3494
+ try {
3495
+ rows = db.prepare("SELECT provider_id, model_id, agent_name, tool_id, token_count FROM tool_definition_measurements").all();
3496
+ } catch {
3497
+ return;
3498
+ }
3499
+ for (const row of rows) {
3500
+ const key = keyFor(row.provider_id, row.model_id, row.agent_name);
3501
+ let inner = measurements.get(key);
3502
+ if (!inner) {
3503
+ inner = new Map;
3504
+ measurements.set(key, inner);
3505
+ }
3506
+ inner.set(row.tool_id, row.token_count);
3507
+ }
3508
+ }
3509
+
3510
+ // ../plugin/src/hooks/magic-context/tokenizer-calibration-seeds.json
3511
+ var tokenizer_calibration_seeds_default = [
3512
+ {
3513
+ prefix: "google/gemini-3.8-flash",
3514
+ systemRatio: 0.961167,
3515
+ toolsRatio: 0.967504,
3516
+ proseRatio: 1.006909
3517
+ },
3518
+ {
3519
+ prefix: "google/gemini-3.7-flash",
3520
+ systemRatio: 0.961167,
3521
+ toolsRatio: 0.967504,
3522
+ proseRatio: 1.006909
3523
+ },
3524
+ {
3525
+ prefix: "google/gemini-3.1-pro-preview",
3526
+ systemRatio: 0.961167,
3527
+ toolsRatio: 0.967504,
3528
+ proseRatio: 1.006909
3529
+ },
3530
+ {
3531
+ prefix: "anthropic/claude-fable-5-1",
3532
+ systemRatio: 1.511497,
3533
+ toolsRatio: 1.551639,
3534
+ proseRatio: 1.571778
3535
+ },
3536
+ {
3537
+ prefix: "anthropic/claude-opus-5",
3538
+ systemRatio: 1.511497,
3539
+ toolsRatio: 1.551639,
3540
+ proseRatio: 1.571778
3541
+ },
3542
+ {
3543
+ prefix: "anthropic/claude-sonnet-5",
3544
+ systemRatio: 1.511497,
3545
+ toolsRatio: 1.554814,
3546
+ proseRatio: 1.571815
3547
+ },
3548
+ {
3549
+ prefix: "openrouter/anthropic/claude-fable-5-1",
3550
+ systemRatio: 1.511497,
3551
+ toolsRatio: 1.551639,
3552
+ proseRatio: 1.571778
3553
+ },
3554
+ {
3555
+ prefix: "openrouter/anthropic/claude-opus-5",
3556
+ systemRatio: 1.511497,
3557
+ toolsRatio: 1.551639,
3558
+ proseRatio: 1.571778
3559
+ },
3560
+ {
3561
+ prefix: "openrouter/anthropic/claude-sonnet-5",
3562
+ systemRatio: 1.511497,
3563
+ toolsRatio: 1.554814,
3564
+ proseRatio: 1.571815
3565
+ },
3566
+ {
3567
+ prefix: "github-copilot/claude-fable-5-1",
3568
+ systemRatio: 1.511497,
3569
+ toolsRatio: 1.551639,
3570
+ proseRatio: 1.571778
3571
+ },
3572
+ {
3573
+ prefix: "github-copilot/claude-opus-5",
3574
+ systemRatio: 1.511497,
3575
+ toolsRatio: 1.551639,
3576
+ proseRatio: 1.571778
3577
+ },
3578
+ {
3579
+ prefix: "github-copilot/claude-sonnet-5",
3580
+ systemRatio: 1.511497,
3581
+ toolsRatio: 1.554814,
3582
+ proseRatio: 1.571815
3583
+ },
3584
+ {
3585
+ prefix: "anthropic/claude-opus-4-8",
3586
+ systemRatio: 1.51,
3587
+ toolsRatio: 1.57
3588
+ },
3589
+ {
3590
+ prefix: "anthropic/claude-opus-4.8",
3591
+ systemRatio: 1.51,
3592
+ toolsRatio: 1.57
3593
+ },
3594
+ {
3595
+ prefix: "anthropic/claude-opus-4-7",
3596
+ systemRatio: 1.51,
3597
+ toolsRatio: 1.57,
3598
+ proseRatio: 1.571778
3599
+ },
3600
+ {
3601
+ prefix: "anthropic/claude-opus-4.7",
3602
+ systemRatio: 1.51,
3603
+ toolsRatio: 1.57
3604
+ },
3605
+ {
3606
+ prefix: "anthropic/claude-opus-4-5",
3607
+ systemRatio: 1.02,
3608
+ toolsRatio: 1.16
3609
+ },
3610
+ {
3611
+ prefix: "anthropic/claude-opus-4.5",
3612
+ systemRatio: 1.02,
3613
+ toolsRatio: 1.16
3614
+ },
3615
+ {
3616
+ prefix: "anthropic/claude-opus-4-6",
3617
+ systemRatio: 1.02,
3618
+ toolsRatio: 1.16
3619
+ },
3620
+ {
3621
+ prefix: "anthropic/claude-opus-4.6",
3622
+ systemRatio: 1.02,
3623
+ toolsRatio: 1.16
3624
+ },
3625
+ {
3626
+ prefix: "anthropic/claude-sonnet-4-5",
3627
+ systemRatio: 1.02,
3628
+ toolsRatio: 1.16
3629
+ },
3630
+ {
3631
+ prefix: "anthropic/claude-sonnet-4.5",
3632
+ systemRatio: 1.02,
3633
+ toolsRatio: 1.16
3634
+ },
3635
+ {
3636
+ prefix: "anthropic/claude-sonnet-4-6",
3637
+ systemRatio: 1.02,
3638
+ toolsRatio: 1.14,
3639
+ proseRatio: 1.057976
3640
+ },
3641
+ {
3642
+ prefix: "anthropic/claude-sonnet-4.6",
3643
+ systemRatio: 1.02,
3644
+ toolsRatio: 1.14
3645
+ },
3646
+ {
3647
+ prefix: "anthropic/claude-haiku-4-5",
3648
+ systemRatio: 1.02,
3649
+ toolsRatio: 1.16
3650
+ },
3651
+ {
3652
+ prefix: "anthropic/claude-haiku-4.5",
3653
+ systemRatio: 1.02,
3654
+ toolsRatio: 1.16
3655
+ },
3656
+ {
3657
+ prefix: "openrouter/anthropic/claude-opus-4-8",
3658
+ systemRatio: 1.51,
3659
+ toolsRatio: 1.57
3660
+ },
3661
+ {
3662
+ prefix: "openrouter/anthropic/claude-opus-4.8",
3663
+ systemRatio: 1.51,
3664
+ toolsRatio: 1.57
3665
+ },
3666
+ {
3667
+ prefix: "github-copilot/claude-opus-4-8",
3668
+ systemRatio: 1.51,
3669
+ toolsRatio: 1.57
3670
+ },
3671
+ {
3672
+ prefix: "github-copilot/claude-opus-4.8",
3673
+ systemRatio: 1.51,
3674
+ toolsRatio: 1.57
3675
+ },
3676
+ {
3677
+ prefix: "openrouter/anthropic/claude-opus-4-7",
3678
+ systemRatio: 1.51,
3679
+ toolsRatio: 1.57
3680
+ },
3681
+ {
3682
+ prefix: "openrouter/anthropic/claude-opus-4.7",
3683
+ systemRatio: 1.51,
3684
+ toolsRatio: 1.57
3685
+ },
3686
+ {
3687
+ prefix: "github-copilot/claude-opus-4-7",
3688
+ systemRatio: 1.51,
3689
+ toolsRatio: 1.57
3690
+ },
3691
+ {
3692
+ prefix: "github-copilot/claude-opus-4.7",
3693
+ systemRatio: 1.51,
3694
+ toolsRatio: 1.57
3695
+ },
3696
+ {
3697
+ prefix: "openrouter/anthropic/claude-sonnet-4.6",
3698
+ systemRatio: 1.02,
3699
+ toolsRatio: 1.14
3700
+ },
3701
+ {
3702
+ prefix: "github-copilot/claude-sonnet-4.6",
3703
+ systemRatio: 1.02,
3704
+ toolsRatio: 1.14
3705
+ },
3706
+ {
3707
+ prefix: "github-copilot/claude-sonnet-4.5",
3708
+ systemRatio: 1.02,
3709
+ toolsRatio: 1.16
3710
+ },
3711
+ {
3712
+ prefix: "github-copilot/claude-opus-4.5",
3713
+ systemRatio: 1.02,
3714
+ toolsRatio: 1.16
3715
+ },
3716
+ {
3717
+ prefix: "github-copilot/claude-haiku-4.5",
3718
+ systemRatio: 1.02,
3719
+ toolsRatio: 1.16
3720
+ },
3721
+ {
3722
+ prefix: "openai/gpt-5.5",
3723
+ systemRatio: 1.000278,
3724
+ toolsRatio: 0.850953,
3725
+ proseRatio: 1.000017
3726
+ },
3727
+ {
3728
+ prefix: "openai/gpt-6-astra",
3729
+ systemRatio: 1.000278,
3730
+ toolsRatio: 0.850953,
3731
+ proseRatio: 1.000017
3732
+ },
3733
+ {
3734
+ prefix: "openai/gpt-5",
3735
+ systemRatio: 1,
3736
+ toolsRatio: 0.84
3737
+ },
3738
+ {
3739
+ prefix: "xai/grok-4-latest",
3740
+ systemRatio: 0.817751,
3741
+ toolsRatio: 0.880494,
3742
+ proseRatio: 0.880137
3743
+ },
3744
+ {
3745
+ prefix: "xai/grok-code-fast-1",
3746
+ systemRatio: 0.817751,
3747
+ toolsRatio: 0.880494,
3748
+ proseRatio: 0.880137
3749
+ },
3750
+ {
3751
+ prefix: "xai/grok-4",
3752
+ systemRatio: 0.82,
3753
+ toolsRatio: 0.88
3754
+ },
3755
+ {
3756
+ prefix: "xai/grok-code-fast",
3757
+ systemRatio: 0.82,
3758
+ toolsRatio: 0.89
3759
+ },
3760
+ {
3761
+ prefix: "cerebras/qwen-3-235b",
3762
+ systemRatio: 1,
3763
+ toolsRatio: 1.1
3764
+ },
3765
+ {
3766
+ prefix: "cerebras/zai-glm-4.7",
3767
+ systemRatio: 1,
3768
+ toolsRatio: 1.09
3769
+ },
3770
+ {
3771
+ prefix: "cerebras/gpt-oss-120b",
3772
+ systemRatio: 0.84,
3773
+ toolsRatio: 0.79
3774
+ },
3775
+ {
3776
+ prefix: "fireworks-ai/accounts/fireworks/models/glm-5p1",
3777
+ systemRatio: 1,
3778
+ toolsRatio: 1.06
3779
+ },
3780
+ {
3781
+ prefix: "fireworks-ai/accounts/fireworks/models/deepseek-v3p2",
3782
+ systemRatio: 1.05,
3783
+ toolsRatio: 1.09
3784
+ },
3785
+ {
3786
+ prefix: "opencode-go/glm-5.1",
3787
+ systemRatio: 1,
3788
+ toolsRatio: 1.06
3789
+ },
3790
+ {
3791
+ prefix: "opencode-go/glm-5",
3792
+ systemRatio: 1,
3793
+ toolsRatio: 1.06
3794
+ },
3795
+ {
3796
+ prefix: "opencode-go/kimi-k2.6",
3797
+ systemRatio: 0.87,
3798
+ toolsRatio: 0.86,
3799
+ proseRatio: 0.925501
3800
+ },
3801
+ {
3802
+ prefix: "moonshot/kimi-k2.6",
3803
+ systemRatio: 0.872126,
3804
+ toolsRatio: 0.863853,
3805
+ proseRatio: 0.925501
3806
+ },
3807
+ {
3808
+ prefix: "moonshot/kimi-for-coding",
3809
+ systemRatio: 0.872126,
3810
+ toolsRatio: 0.863853,
3811
+ proseRatio: 0.925501
3812
+ },
3813
+ {
3814
+ prefix: "zai/glm-4.7",
3815
+ systemRatio: 0.999721,
3816
+ toolsRatio: 1.056823,
3817
+ proseRatio: 1.000875
3818
+ },
3819
+ {
3820
+ prefix: "meta/muse-spark",
3821
+ systemRatio: 0.865949,
3822
+ toolsRatio: 1.024605,
3823
+ proseRatio: 0.923366
3824
+ },
3825
+ {
3826
+ prefix: "opencode/muse-spark",
3827
+ systemRatio: 0.865949,
3828
+ toolsRatio: 1.024605,
3829
+ proseRatio: 0.923366
3830
+ }
3831
+ ];
3832
+
3833
+ // ../plugin/src/hooks/magic-context/tokenizer-calibration.ts
3834
+ var CALIBRATION_TABLE = tokenizer_calibration_seeds_default;
3835
+ var NEUTRAL = { systemRatio: 1, toolsRatio: 1, proseRatio: 1 };
3836
+ var CALIBRATION_TABLE_REVISION = "2026-09-23-model-id-generation-v2";
3837
+ var UNKNOWN_FIT_RATIO = Math.max(2, ...CALIBRATION_TABLE.flatMap((entry) => [
3838
+ entry.systemRatio,
3839
+ entry.toolsRatio,
3840
+ entry.proseRatio ?? 1
3841
+ ]));
3842
+ function hasModelCalibration(providerId, modelId) {
3843
+ return resolveModelCalibration(providerId, modelId) !== NEUTRAL;
3844
+ }
3845
+ function resolveModelCalibration(providerId, modelId) {
3846
+ if (!providerId || !modelId)
3847
+ return NEUTRAL;
3848
+ const key = `${providerId}/${modelId}`.toLowerCase();
3849
+ let best = null;
3850
+ for (const entry of CALIBRATION_TABLE) {
3851
+ const prefix = entry.prefix.toLowerCase();
3852
+ if (!key.startsWith(prefix))
3853
+ continue;
3854
+ if (!best || prefix.length > best.prefix.length) {
3855
+ best = entry;
3856
+ }
3857
+ }
3858
+ if (best)
3859
+ return { ...best, proseRatio: best.proseRatio ?? 1 };
3860
+ const provider = providerId.toLowerCase();
3861
+ const model = modelId.toLowerCase();
3862
+ if (CALIBRATION_TABLE.some((entry) => entry.prefix.toLowerCase().startsWith(`${provider}/`))) {
3863
+ return resolveFamilyFallback(provider, model) ?? NEUTRAL;
3864
+ }
3865
+ const canonical = canonicalProvider(model);
3866
+ let modelMatch = null;
3867
+ for (const entry of CALIBRATION_TABLE) {
3868
+ const seedModel = entry.prefix.toLowerCase().split("/").slice(1).join("/");
3869
+ if (!model.startsWith(seedModel))
3870
+ continue;
3871
+ const oldModel = modelMatch?.prefix.toLowerCase().split("/").slice(1).join("/") ?? "";
3872
+ if (seedModel.length > oldModel.length || seedModel.length === oldModel.length && entry.prefix.toLowerCase().startsWith(`${canonical}/`) && !modelMatch?.prefix.toLowerCase().startsWith(`${canonical}/`))
3873
+ modelMatch = entry;
3874
+ }
3875
+ if (modelMatch)
3876
+ return {
3877
+ ...modelMatch,
3878
+ proseRatio: modelMatch.proseRatio ?? 1,
3879
+ derivedFrom: modelMatch.prefix,
3880
+ matchedByModelId: true
3881
+ };
3882
+ const inherited = canonical ? resolveFamilyFallback(canonical, model) : null;
3883
+ return inherited ? { ...inherited, matchedByModelId: true } : NEUTRAL;
3884
+ }
3885
+ function parseModelLineage(modelId) {
3886
+ const tokens = modelId.split("-");
3887
+ const versionAt = tokens.findIndex((token) => /^\d+(\.\d+)*$/.test(token));
3888
+ if (versionAt <= 0)
3889
+ return null;
3890
+ const version = [];
3891
+ let end = versionAt;
3892
+ while (end < tokens.length && /^\d+(\.\d+)*$/.test(tokens[end] ?? "")) {
3893
+ for (const part of (tokens[end] ?? "").split("."))
3894
+ version.push(Number(part));
3895
+ end += 1;
3896
+ }
3897
+ return {
3898
+ family: tokens.slice(0, versionAt).join("-"),
3899
+ version,
3900
+ variant: tokens.slice(end).join("-")
3901
+ };
3902
+ }
3903
+ function canonicalProvider(model) {
3904
+ if (model.startsWith("claude-"))
3905
+ return "anthropic";
3906
+ if (model.startsWith("gpt-"))
3907
+ return "openai";
3908
+ if (model.startsWith("gemini-"))
3909
+ return "google";
3910
+ return "";
3911
+ }
3912
+ function compareVersions(a, b) {
3913
+ const length = Math.max(a.length, b.length);
3914
+ for (let i = 0;i < length; i++) {
3915
+ const delta = (a[i] ?? 0) - (b[i] ?? 0);
3916
+ if (delta !== 0)
3917
+ return delta;
3918
+ }
3919
+ return 0;
3920
+ }
3921
+ function resolveFamilyFallback(providerId, modelId) {
3922
+ const wanted = parseModelLineage(modelId);
3923
+ if (!wanted)
3924
+ return null;
3925
+ let below = null;
3926
+ let above = null;
3927
+ for (const entry of CALIBRATION_TABLE) {
3928
+ const prefix = entry.prefix.toLowerCase();
3929
+ if (!prefix.startsWith(`${providerId}/`))
3930
+ continue;
3931
+ const lineage = parseModelLineage(prefix.slice(providerId.length + 1));
3932
+ if (!lineage || lineage.family !== wanted.family || lineage.variant !== wanted.variant)
3933
+ continue;
3934
+ const order = compareVersions(lineage.version, wanted.version);
3935
+ if (order === 0)
3936
+ continue;
3937
+ if (order < 0) {
3938
+ if (!below || compareVersions(lineage.version, below.version) > 0) {
3939
+ below = { entry, version: lineage.version };
3940
+ }
3941
+ } else if (!above || compareVersions(lineage.version, above.version) < 0) {
3942
+ above = { entry, version: lineage.version };
3943
+ }
3944
+ }
3945
+ let source = below ?? above;
3946
+ if (source?.version[0] !== wanted.version[0] && canonicalProvider(modelId) !== "") {
3947
+ let sibling = null;
3948
+ for (const entry of CALIBRATION_TABLE) {
3949
+ const prefix = entry.prefix.toLowerCase();
3950
+ if (!prefix.startsWith(`${providerId}/`))
3951
+ continue;
3952
+ const lineage = parseModelLineage(prefix.slice(providerId.length + 1));
3953
+ if (!lineage || lineage.version[0] !== wanted.version[0] || lineage.variant !== wanted.variant || lineage.family.split("-")[0] !== wanted.family.split("-")[0])
3954
+ continue;
3955
+ const candidate = { entry, version: lineage.version };
3956
+ if (!sibling || compareVersions(candidate.version, wanted.version) <= 0 && compareVersions(sibling.version, wanted.version) > 0 || compareVersions(candidate.version, wanted.version) <= 0 && compareVersions(candidate.version, sibling.version) > 0 || compareVersions(sibling.version, wanted.version) > 0 && compareVersions(candidate.version, sibling.version) < 0)
3957
+ sibling = candidate;
3958
+ }
3959
+ source = sibling ?? source;
3960
+ }
3961
+ if (!source)
3962
+ return null;
3963
+ return {
3964
+ systemRatio: source.entry.systemRatio,
3965
+ toolsRatio: source.entry.toolsRatio,
3966
+ proseRatio: source.entry.proseRatio ?? 1,
3967
+ derivedFrom: source.entry.prefix
3968
+ };
3969
+ }
3970
+
3971
+ // ../plugin/src/hooks/magic-context/decision-calibration.ts
3972
+ function resolveDecisionCalibration(providerId, modelId) {
3973
+ const ratios = resolveModelCalibration(providerId, modelId);
3974
+ return Object.freeze({
3975
+ ...ratios,
3976
+ modelKey: `${providerId ?? "unknown"}/${modelId ?? "unknown"}`.toLowerCase(),
3977
+ revision: CALIBRATION_TABLE_REVISION,
3978
+ matchedPrefix: ratios.derivedFrom ?? ratios.prefix,
3979
+ seeded: hasModelCalibration(providerId, modelId),
3980
+ source: ratios.matchedByModelId ? "model-id" : ratios.derivedFrom ? "family-fallback" : "seed"
3981
+ });
3982
+ }
3983
+ function providerMass(raw, seed, fit = false) {
3984
+ const { system = 0, tools = 0, prose = 0 } = raw;
3985
+ if ([system, tools, prose].some((count) => !Number.isFinite(count) || count < 0) || [seed.systemRatio, seed.toolsRatio, seed.proseRatio].some((ratio) => !Number.isFinite(ratio) || ratio <= 0)) {
3986
+ return Number.POSITIVE_INFINITY;
3987
+ }
3988
+ const total = fit && !seed.seeded ? (system + tools + prose) * UNKNOWN_FIT_RATIO : system * seed.systemRatio + tools * seed.toolsRatio + prose * seed.proseRatio;
3989
+ return Number.isFinite(total) ? Math.ceil(total) : Number.POSITIVE_INFINITY;
3990
+ }
3991
+ function localBudget(providerTokens, ratio) {
3992
+ if (!Number.isFinite(providerTokens) || providerTokens <= 0 || !Number.isFinite(ratio) || ratio <= 0)
3993
+ return 0;
3994
+ return Math.floor(providerTokens / ratio);
3995
+ }
3996
+ function calibrationForModelKey(modelKey) {
3997
+ const slash = modelKey?.indexOf("/") ?? -1;
3998
+ return modelKey != null && slash > 0 ? resolveDecisionCalibration(modelKey.slice(0, slash), modelKey.slice(slash + 1)) : resolveDecisionCalibration(undefined, undefined);
3999
+ }
4000
+ function historyLocalBudget(providerTokens, modelKey) {
4001
+ const ratio = calibrationForModelKey(modelKey).proseRatio;
4002
+ return ratio === 1 ? providerTokens : localBudget(providerTokens, ratio);
4003
+ }
4004
+
4005
+ // ../plugin/src/hooks/magic-context/tool-drop-target.ts
4006
+ var IGNORE_PART_TYPES = new Set([
4007
+ "thinking",
4008
+ "reasoning",
4009
+ "redacted_thinking",
4010
+ "meta",
4011
+ "step-start",
4012
+ "step-finish"
4013
+ ]);
4014
+ function isToolCallId(value) {
4015
+ return typeof value === "string" && value.length > 0;
4016
+ }
4017
+ function extractToolCallObservation(part) {
4018
+ if (!isRecord(part))
4019
+ return null;
4020
+ if (part.type === "tool" && isToolCallId(part.callID)) {
4021
+ return { callId: part.callID, kind: "result" };
4022
+ }
4023
+ if (part.type === "tool-invocation" && isToolCallId(part.callID)) {
4024
+ return { callId: part.callID, kind: "invocation" };
4025
+ }
4026
+ if (part.type === "tool_use" && isToolCallId(part.id)) {
4027
+ return { callId: part.id, kind: "invocation" };
4028
+ }
4029
+ if (part.type === "tool_result" && isToolCallId(part.tool_use_id)) {
4030
+ return { callId: part.tool_use_id, kind: "result" };
4031
+ }
4032
+ return null;
4033
+ }
4034
+
4035
+ // ../plugin/src/hooks/magic-context/read-session-chunk.ts
4036
+ var BLOCK_TOKEN_MEMO_MAX = 2048;
4037
+ var blockTokenMemo = new Map;
4038
+ function estimateBlockTokens(blockText) {
4039
+ const cached = blockTokenMemo.get(blockText);
4040
+ if (cached !== undefined) {
4041
+ blockTokenMemo.delete(blockText);
4042
+ blockTokenMemo.set(blockText, cached);
4043
+ return cached;
4044
+ }
4045
+ const count = estimateTokens(blockText);
4046
+ if (blockTokenMemo.size >= BLOCK_TOKEN_MEMO_MAX) {
4047
+ const oldest = blockTokenMemo.keys().next().value;
4048
+ if (oldest !== undefined)
4049
+ blockTokenMemo.delete(oldest);
4050
+ }
4051
+ blockTokenMemo.set(blockText, count);
4052
+ return count;
4053
+ }
4054
+ var activeRawMessageCache = null;
4055
+ var activeAbsoluteCountCache = null;
4056
+ var sessionProviders = new Map;
4057
+ function resolveHostServedBoundaryId2(sessionId, messageId) {
4058
+ if (messageId.length === 0)
4059
+ return messageId;
4060
+ return sessionProviders.get(sessionId)?.readServedBoundaryId?.(messageId) ?? messageId;
4061
+ }
4062
+ function hasRawMessageProvider2(sessionId) {
4063
+ return sessionProviders.has(sessionId);
4064
+ }
4065
+ function setRawMessageProvider2(sessionId, provider) {
4066
+ sessionProviders.set(sessionId, provider);
4067
+ return () => {
4068
+ const current = sessionProviders.get(sessionId);
4069
+ if (current === provider)
4070
+ sessionProviders.delete(sessionId);
4071
+ };
4072
+ }
4073
+ function withRawMessageProvider2(sessionId, provider, fn) {
4074
+ const cleanup = setRawMessageProvider2(sessionId, provider);
4075
+ let result;
4076
+ try {
4077
+ result = fn();
4078
+ } catch (error) {
4079
+ cleanup();
4080
+ throw error;
4081
+ }
4082
+ if (result !== null && typeof result === "object" && typeof result.then === "function") {
4083
+ return result.finally(cleanup);
4084
+ }
4085
+ cleanup();
4086
+ return result;
4087
+ }
4088
+ function cleanUserText2(text) {
4089
+ return removeSystemReminders(text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
4090
+ }
4091
+ function withRawSessionMessageCache2(fn) {
4092
+ const outerCache = activeRawMessageCache;
4093
+ if (!outerCache) {
4094
+ activeRawMessageCache = new Map;
4095
+ activeAbsoluteCountCache = new Map;
4096
+ }
4097
+ try {
4098
+ return fn();
4099
+ } finally {
4100
+ if (!outerCache) {
4101
+ activeRawMessageCache = null;
4102
+ activeAbsoluteCountCache = null;
4103
+ }
4104
+ }
4105
+ }
4106
+ function readRawSessionMessages2(sessionId) {
4107
+ if (activeRawMessageCache) {
4108
+ const cached = activeRawMessageCache.get(sessionId);
4109
+ if (cached?.coveredFromOrdinal === 1 && cached.coveredToOrdinal === null) {
4110
+ return cached.messages;
4111
+ }
4112
+ const messages = readRawSessionMessagesFromSource(sessionId);
4113
+ if (!cached) {
4114
+ activeRawMessageCache.set(sessionId, {
4115
+ messages,
4116
+ coveredFromOrdinal: 1,
4117
+ coveredToOrdinal: null
4118
+ });
4119
+ }
4120
+ return messages;
4121
+ }
4122
+ return readRawSessionMessagesFromSource(sessionId);
4123
+ }
4124
+ function readRawSessionMessagePage2(sessionId, afterOrdinal, limit, finalWatermark) {
4125
+ const provider = sessionProviders.get(sessionId);
4126
+ if (provider?.readMessagePage) {
4127
+ return provider.readMessagePage(afterOrdinal, limit, finalWatermark);
4128
+ }
4129
+ if (provider) {
4130
+ return provider.readMessages().filter((message) => message.ordinal > afterOrdinal && message.ordinal <= finalWatermark).slice(0, limit);
4131
+ }
4132
+ if (!openCodeDbExists())
4133
+ return [];
4134
+ return withReadOnlySessionDb((db) => readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark));
4135
+ }
4136
+ function getRawSessionMessageOrdinalCount2(sessionId) {
4137
+ const provider = sessionProviders.get(sessionId);
4138
+ if (provider) {
4139
+ if (provider.getMessageCount)
4140
+ return provider.getMessageCount();
4141
+ const messages = provider.readMessages();
4142
+ return messages.reduce((maximum, message) => Math.max(maximum, message.ordinal), messages.length);
4143
+ }
4144
+ if (!openCodeDbExists())
4145
+ return 0;
4146
+ return withReadOnlySessionDb((db) => countRawSessionMessageOrdinalsFromDb(db, sessionId));
4147
+ }
4148
+ var RAW_MESSAGE_RANGE_PAGE_SIZE = 100;
4149
+ function readRawSessionMessageRangeFromSource(sessionId, fromOrdinal, toOrdinal) {
4150
+ const provider = sessionProviders.get(sessionId);
4151
+ if (provider && !provider.readMessagePage) {
4152
+ return provider.readMessages().filter((message) => message.ordinal >= fromOrdinal && message.ordinal <= toOrdinal);
4153
+ }
4154
+ if (!provider && !openCodeDbExists())
4155
+ return [];
4156
+ const messages = [];
4157
+ let afterOrdinal = fromOrdinal - 1;
4158
+ while (afterOrdinal < toOrdinal) {
4159
+ const limit = Math.min(RAW_MESSAGE_RANGE_PAGE_SIZE, toOrdinal - afterOrdinal);
4160
+ const page = provider?.readMessagePage ? provider.readMessagePage(afterOrdinal, limit, toOrdinal) : withReadOnlySessionDb((db) => readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, toOrdinal));
4161
+ if (page.length === 0)
4162
+ break;
4163
+ let nextOrdinal = afterOrdinal;
4164
+ for (const message of page) {
4165
+ if (message.ordinal < fromOrdinal || message.ordinal > toOrdinal)
4166
+ continue;
4167
+ messages.push(message);
4168
+ nextOrdinal = Math.max(nextOrdinal, message.ordinal);
4169
+ }
4170
+ if (nextOrdinal <= afterOrdinal)
4171
+ break;
4172
+ afterOrdinal = nextOrdinal;
4173
+ }
4174
+ return messages;
4175
+ }
4176
+ function readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal) {
4177
+ const from = Math.max(1, Math.floor(fromOrdinal));
4178
+ const to = Math.floor(toOrdinal);
4179
+ if (to < from)
4180
+ return [];
4181
+ const cached = activeRawMessageCache?.get(sessionId);
4182
+ if (!cached)
4183
+ return readRawSessionMessageRangeFromSource(sessionId, from, to);
4184
+ const coveredTo = cached.coveredToOrdinal ?? Number.POSITIVE_INFINITY;
4185
+ const overlapFrom = Math.max(from, cached.coveredFromOrdinal);
4186
+ const overlapTo = Math.min(to, coveredTo);
4187
+ if (overlapTo < overlapFrom) {
4188
+ return readRawSessionMessageRangeFromSource(sessionId, from, to);
4189
+ }
4190
+ const messages = [];
4191
+ if (from < overlapFrom) {
4192
+ messages.push(...readRawSessionMessageRangeFromSource(sessionId, from, overlapFrom - 1));
4193
+ }
4194
+ messages.push(...cached.messages.filter((message) => message.ordinal >= overlapFrom && message.ordinal <= overlapTo));
4195
+ if (overlapTo < to) {
4196
+ messages.push(...readRawSessionMessageRangeFromSource(sessionId, overlapTo + 1, to));
4197
+ }
4198
+ return messages;
4199
+ }
4200
+ readRawSessionMessages2.readPage = readRawSessionMessagePage2;
4201
+ readRawSessionMessages2.getCount = getRawSessionMessageOrdinalCount2;
4202
+ function primeTailRawMessageCache2(args) {
4203
+ const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
4204
+ if (!activeRawMessageCache)
4205
+ return false;
4206
+ if (activeRawMessageCache.has(sessionId))
4207
+ return false;
4208
+ if (lastCompartmentEnd < 1 || !anchorMessageId)
4209
+ return false;
4210
+ const provider = sessionProviders.get(sessionId);
4211
+ if (provider) {
4212
+ if (!provider.readMessagePage || !provider.getMessageCount)
4213
+ return false;
4214
+ const absoluteMessageCount = provider.getMessageCount();
4215
+ const messages = readRawSessionMessageRange2(sessionId, lastCompartmentEnd, absoluteMessageCount);
4216
+ if (messages.find((message) => message.ordinal === lastCompartmentEnd)?.id !== anchorMessageId)
4217
+ return false;
4218
+ activeRawMessageCache.set(sessionId, {
4219
+ messages,
4220
+ coveredFromOrdinal: lastCompartmentEnd,
4221
+ coveredToOrdinal: lastCompartmentEnd === 1 ? null : absoluteMessageCount
4222
+ });
4223
+ activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
4224
+ return true;
4225
+ }
4226
+ if (!openCodeDbExists())
4227
+ return false;
4228
+ const result = withReadOnlySessionDb((db) => readRawSessionTailFromDb(db, sessionId, lastCompartmentEnd, anchorMessageId));
4229
+ if (!result)
4230
+ return false;
4231
+ activeRawMessageCache.set(sessionId, {
4232
+ messages: result.messages,
4233
+ coveredFromOrdinal: lastCompartmentEnd,
4234
+ coveredToOrdinal: lastCompartmentEnd === 1 ? null : result.absoluteMessageCount
4235
+ });
4236
+ activeAbsoluteCountCache?.set(sessionId, result.absoluteMessageCount);
4237
+ return true;
4238
+ }
4239
+ function getCachedAbsoluteMessageCount2(sessionId) {
4240
+ return activeAbsoluteCountCache?.get(sessionId) ?? null;
4241
+ }
4242
+ function primeInMemoryTailRawMessageCache2(args) {
4243
+ const { sessionId, messages, absoluteMessageCount } = args;
4244
+ if (!activeRawMessageCache)
4245
+ return false;
4246
+ if (activeRawMessageCache.has(sessionId))
4247
+ return false;
4248
+ const coveredFromOrdinal = messages[0]?.ordinal ?? absoluteMessageCount + 1;
4249
+ activeRawMessageCache.set(sessionId, {
4250
+ messages,
4251
+ coveredFromOrdinal,
4252
+ coveredToOrdinal: coveredFromOrdinal === 1 ? null : absoluteMessageCount
4253
+ });
4254
+ activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
4255
+ return true;
4256
+ }
4257
+ function readRawSessionMessageIdOrdinalsForRange2(sessionId, fromOrdinal, toOrdinal) {
4258
+ const from = Math.max(1, Math.floor(fromOrdinal));
4259
+ const to = Math.floor(toOrdinal);
4260
+ if (to < from)
4261
+ return new Map;
4262
+ const provider = sessionProviders.get(sessionId);
4263
+ if (provider?.readMessageIdOrdinalsForRange) {
4264
+ return provider.readMessageIdOrdinalsForRange(from, to);
4265
+ }
4266
+ const all = provider?.readMessageIdOrdinals ? provider.readMessageIdOrdinals() : provider ? new Map(provider.readMessages().map((message) => [message.id, message.ordinal])) : !openCodeDbExists() ? new Map : withReadOnlySessionDb((db) => readRawSessionMessageIdOrdinalsFromDb(db, sessionId));
4267
+ return new Map([...all].filter(([, ordinal]) => ordinal >= from && ordinal <= to));
4268
+ }
4269
+ function hasRawSessionMessageById2(sessionId, messageId) {
4270
+ const provider = sessionProviders.get(sessionId);
4271
+ if (provider?.hasMessageById)
4272
+ return provider.hasMessageById(messageId);
4273
+ return readRawSessionMessageById(sessionId, messageId) !== null;
4274
+ }
4275
+ function readRawSessionMessageById(sessionId, messageId) {
4276
+ const provider = sessionProviders.get(sessionId);
4277
+ if (provider?.readMessageById) {
4278
+ return provider.readMessageById(messageId);
4279
+ }
4280
+ if (provider) {
4281
+ return provider.readMessages().find((message) => message.id === messageId) ?? null;
4282
+ }
4283
+ if (!openCodeDbExists())
4284
+ return null;
4285
+ return withReadOnlySessionDb((db) => readRawSessionMessageByIdFromDb(db, sessionId, messageId));
4286
+ }
4287
+ function readRawSessionMessagesFromSource(sessionId) {
4288
+ const provider = sessionProviders.get(sessionId);
4289
+ if (provider)
4290
+ return provider.readMessages();
4291
+ if (!openCodeDbExists())
4292
+ return [];
4293
+ return withReadOnlySessionDb((db) => readRawSessionMessagesFromDb(db, sessionId));
4294
+ }
4295
+ function getRawSessionMessageCount2(sessionId) {
4296
+ const provider = sessionProviders.get(sessionId);
4297
+ if (provider) {
4298
+ if (provider.getMessageCount)
4299
+ return provider.getMessageCount();
4300
+ const messages = provider.readMessages();
4301
+ return messages.reduce((maximum, message) => Math.max(maximum, message.ordinal), messages.length);
4302
+ }
4303
+ if (!openCodeDbExists())
4304
+ return 0;
4305
+ return withReadOnlySessionDb((db) => getRawSessionMessageCountFromDb(db, sessionId));
4306
+ }
4307
+ var RAW_SESSION_TAG_KEY_PAGE_SIZE = 32;
4308
+ function yieldRawSessionTagKeyPage() {
4309
+ return new Promise((resolve) => {
4310
+ const immediate = globalThis.setImmediate;
4311
+ if (typeof immediate === "function") {
4312
+ immediate(resolve);
4313
+ return;
4314
+ }
4315
+ setTimeout(resolve, 0);
4316
+ });
4317
+ }
4318
+ async function getRawSessionTagKeysThrough2(sessionId, upToMessageIndex, options = {}) {
4319
+ const messageFileKeys = new Set;
4320
+ const toolObservations = new Map;
4321
+ const unpairedInvocations = new Map;
4322
+ const candidateOwnersByCallId = new Map;
4323
+ const messageTimesById = new Map;
4324
+ const finalWatermark = Number.isFinite(upToMessageIndex) ? Math.max(0, Math.floor(upToMessageIndex)) : getRawSessionMessageOrdinalCount2(sessionId);
4325
+ const pageSize = Number.isFinite(options.pageSize) ? Math.max(1, Math.floor(options.pageSize ?? RAW_SESSION_TAG_KEY_PAGE_SIZE)) : RAW_SESSION_TAG_KEY_PAGE_SIZE;
4326
+ const yieldToEventLoop = options.yieldToEventLoop ?? yieldRawSessionTagKeyPage;
4327
+ const nearestPersistedOwner = (callId, currentMessageId) => {
4328
+ if (!options.db)
4329
+ return null;
4330
+ let candidates = candidateOwnersByCallId.get(callId);
4331
+ if (!candidates) {
4332
+ candidates = getCandidateToolOwners(options.db, sessionId, callId);
4333
+ candidateOwnersByCallId.set(callId, candidates);
4334
+ }
4335
+ if (candidates.length === 0)
4336
+ return null;
4337
+ const ids = [...candidates, currentMessageId];
4338
+ const unresolved = ids.filter((id) => !messageTimesById.has(id));
4339
+ if (unresolved.length > 0) {
4340
+ const resolved = getMessageTimesFromOpenCodeDb(sessionId, unresolved);
4341
+ for (const id of unresolved) {
4342
+ messageTimesById.set(id, resolved.get(id) ?? null);
4343
+ }
4344
+ }
4345
+ const times = new Map;
4346
+ for (const id of ids) {
4347
+ const time = messageTimesById.get(id);
4348
+ if (typeof time === "number")
4349
+ times.set(id, time);
4350
+ }
4351
+ return pickNearestPriorOwner(candidates, currentMessageId, times);
4352
+ };
4353
+ const firstOrdinal = Number.isFinite(options.fromMessageIndex) ? Math.max(1, Math.floor(options.fromMessageIndex ?? 1)) : 1;
4354
+ let afterOrdinal = firstOrdinal - 1;
4355
+ while (afterOrdinal < finalWatermark) {
4356
+ const messages = readRawSessionMessages2.readPage(sessionId, afterOrdinal, pageSize, finalWatermark);
4357
+ if (messages.length === 0)
4358
+ break;
4359
+ let nextOrdinal = afterOrdinal;
4360
+ for (const message of messages) {
4361
+ if (message.ordinal <= afterOrdinal || message.ordinal > finalWatermark)
4362
+ continue;
4363
+ nextOrdinal = Math.max(nextOrdinal, message.ordinal);
4364
+ messageTimesById.set(message.id, typeof message.createdAt === "number" ? message.createdAt : null);
4365
+ for (const [partIndex, part] of message.parts.entries()) {
4366
+ if (isTextPart(part)) {
4367
+ messageFileKeys.add(`${message.id}:p${partIndex}`);
4368
+ continue;
4369
+ }
4370
+ if (isFilePart(part)) {
4371
+ messageFileKeys.add(`${message.id}:file${partIndex}`);
4372
+ continue;
4373
+ }
4374
+ const observation = extractToolCallObservation(part);
4375
+ if (!observation)
4376
+ continue;
4377
+ let ownerMessageId;
4378
+ if (observation.kind === "invocation") {
4379
+ ownerMessageId = message.id;
4380
+ const queue = unpairedInvocations.get(observation.callId) ?? [];
4381
+ queue.push(message.id);
4382
+ unpairedInvocations.set(observation.callId, queue);
4383
+ } else {
4384
+ const queue = unpairedInvocations.get(observation.callId);
4385
+ const pairedOwner = queue?.shift();
4386
+ if (queue?.length === 0)
4387
+ unpairedInvocations.delete(observation.callId);
4388
+ ownerMessageId = pairedOwner ?? nearestPersistedOwner(observation.callId, message.id) ?? message.id;
4389
+ }
4390
+ const owners = toolObservations.get(observation.callId) ?? new Set;
4391
+ owners.add(ownerMessageId);
4392
+ toolObservations.set(observation.callId, owners);
4393
+ }
4394
+ }
4395
+ if (nextOrdinal <= afterOrdinal)
4396
+ break;
4397
+ afterOrdinal = nextOrdinal;
4398
+ if (afterOrdinal < finalWatermark)
4399
+ await yieldToEventLoop();
4400
+ }
4401
+ return { messageFileKeys, toolObservations };
4402
+ }
4403
+ var PROTECTED_TAIL_USER_TURNS = 5;
4404
+ function getLegacyProtectedTailStartOrdinal2(sessionId) {
4405
+ const count = getRawSessionMessageOrdinalCount2(sessionId);
4406
+ const userOrdinals = [];
4407
+ let toOrdinal = count;
4408
+ while (toOrdinal >= 1 && userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
4409
+ const fromOrdinal = Math.max(1, toOrdinal - RAW_MESSAGE_RANGE_PAGE_SIZE + 1);
4410
+ const messages = readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal);
4411
+ for (let index = messages.length - 1;index >= 0; index--) {
4412
+ const message = messages[index];
4413
+ if (message?.role === "user" && hasMeaningfulUserText2(message.parts)) {
4414
+ userOrdinals.push(message.ordinal);
4415
+ if (userOrdinals.length === PROTECTED_TAIL_USER_TURNS)
4416
+ break;
4417
+ }
4418
+ }
4419
+ toOrdinal = fromOrdinal - 1;
4420
+ }
4421
+ return userOrdinals.length < PROTECTED_TAIL_USER_TURNS ? 1 : userOrdinals[PROTECTED_TAIL_USER_TURNS - 1] ?? 1;
4422
+ }
4423
+ function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal) {
4424
+ const totalMessageCount = getCachedAbsoluteMessageCount2(sessionId) ?? getRawSessionMessageOrdinalCount2(sessionId);
4425
+ const startOrdinal = Math.max(1, offset);
4426
+ const finalOrdinal = eligibleEndOrdinal === undefined ? totalMessageCount : Math.min(totalMessageCount, eligibleEndOrdinal - 1);
4427
+ const messages = readRawSessionMessageRange2(sessionId, Math.max(1, startOrdinal - 1), finalOrdinal);
4428
+ const completedToolArcs = buildToolArcs(messages).flatMap((arc) => arc.resOrdinal === null ? [] : [{ start: arc.invOrdinal, end: arc.resOrdinal }]);
4429
+ const completedToolComponents = [];
4430
+ for (const arc of completedToolArcs) {
4431
+ const component = completedToolComponents[completedToolComponents.length - 1];
4432
+ if (component && arc.start <= component.end)
4433
+ component.end = Math.max(component.end, arc.end);
4434
+ else
4435
+ completedToolComponents.push({ ...arc });
4436
+ }
4437
+ const lines = [];
4438
+ const lineMeta = [];
4439
+ const flushedToolOnlyBlocks = [];
4440
+ let totalTokens = 0;
4441
+ let messagesProcessed = 0;
4442
+ let lastOrdinal = startOrdinal - 1;
4443
+ let highestScannedOrdinal = startOrdinal - 1;
4444
+ let lastMessageId = "";
4445
+ let firstMessageId = "";
4446
+ let currentBlock = null;
4447
+ let pendingNoiseMeta = [];
4448
+ let commitClusters = 0;
4449
+ let lastFlushedRole = "";
4450
+ let admittedOversizeComponentEnd = null;
4451
+ let currentBlockApproxTokens = 0;
4452
+ let formattedBudgetCrossed = false;
4453
+ let sourceCharacters = 0;
4454
+ const toolResultBoundaries = [];
4455
+ function pinComponentWhenFormattedBudgetCrosses(ordinal, appendedText) {
4456
+ if (admittedOversizeComponentEnd !== null || formattedBudgetCrossed || !currentBlock)
4457
+ return;
4458
+ currentBlockApproxTokens += estimateTokens(appendedText) + (currentBlock.parts.length > 1 ? 1 : 0);
4459
+ if (totalTokens + currentBlockApproxTokens + 64 <= tokenBudget)
4460
+ return;
4461
+ const previewTokens = totalTokens + estimateTokens(formatBlock(currentBlock));
4462
+ if (previewTokens <= tokenBudget)
4463
+ return;
4464
+ formattedBudgetCrossed = true;
4465
+ const component = completedToolComponents.find((candidate) => candidate.start <= ordinal && candidate.end >= ordinal);
4466
+ if (component)
4467
+ admittedOversizeComponentEnd = component.end;
4468
+ }
4469
+ function recordFilteredNoise(meta) {
4470
+ pendingNoiseMeta.push(meta);
4471
+ if (!currentBlock) {
4472
+ highestScannedOrdinal = Math.max(highestScannedOrdinal, meta.ordinal);
4473
+ }
4474
+ }
4475
+ function flushCurrentBlock() {
4476
+ if (!currentBlock)
4477
+ return true;
4478
+ const blockText = formatBlock(currentBlock);
4479
+ const blockTokens = estimateBlockTokens(blockText);
4480
+ if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
4481
+ const splitsCompletedArc = completedToolArcs.some((arc) => arc.start <= lastOrdinal && arc.end > lastOrdinal);
4482
+ if (!splitsCompletedArc)
4483
+ return false;
4484
+ }
4485
+ if (currentBlock.role === "A" && currentBlock.commitHashes.length > 0 && lastFlushedRole !== "A") {
4486
+ commitClusters++;
4487
+ }
4488
+ lastFlushedRole = currentBlock.role;
4489
+ if (!firstMessageId)
4490
+ firstMessageId = currentBlock.meta[0]?.messageId ?? "";
4491
+ lastOrdinal = currentBlock.meta[currentBlock.meta.length - 1]?.ordinal ?? currentBlock.endOrdinal;
4492
+ highestScannedOrdinal = Math.max(highestScannedOrdinal, lastOrdinal);
4493
+ lastMessageId = currentBlock.meta[currentBlock.meta.length - 1]?.messageId ?? "";
4494
+ messagesProcessed += currentBlock.meta.length;
4495
+ const lineStart = sourceCharacters + (lines.length > 0 ? 1 : 0);
4496
+ const renderedParts = currentBlock.parts.join(" / ");
4497
+ let partOffset = lineStart + (blockText.length - renderedParts.length);
4498
+ for (let index = 0;index < currentBlock.parts.length; index++) {
4499
+ const part = currentBlock.parts[index] ?? "";
4500
+ const partMeta = currentBlock.partMeta[index];
4501
+ if (partMeta && partMeta.toolResultBodyTokens > 0) {
4502
+ toolResultBoundaries.push({
4503
+ ordinal: partMeta.ordinal,
4504
+ sourceOffset: partOffset,
4505
+ bodyTokens: partMeta.toolResultBodyTokens
4506
+ });
4507
+ }
4508
+ partOffset += part.length + (index + 1 < currentBlock.parts.length ? 3 : 0);
4509
+ }
4510
+ lines.push(blockText);
4511
+ sourceCharacters = lineStart + blockText.length;
4512
+ lineMeta.push(...currentBlock.meta);
4513
+ totalTokens += blockTokens;
4514
+ if (currentBlock.isToolOnly) {
4515
+ flushedToolOnlyBlocks.push({
4516
+ start: currentBlock.startOrdinal,
4517
+ end: currentBlock.endOrdinal
4518
+ });
4519
+ }
4520
+ currentBlock = null;
4521
+ currentBlockApproxTokens = 0;
4522
+ return true;
4523
+ }
4524
+ for (const msg of messages) {
4525
+ if (eligibleEndOrdinal !== undefined && msg.ordinal >= eligibleEndOrdinal)
4526
+ break;
4527
+ if (admittedOversizeComponentEnd !== null && msg.ordinal > admittedOversizeComponentEnd) {
4528
+ break;
4529
+ }
4530
+ if (msg.ordinal < startOrdinal)
4531
+ continue;
4532
+ const meta = { ordinal: msg.ordinal, messageId: msg.id };
4533
+ if (isHostUnservedRow(msg))
4534
+ markHostUnservedRow(meta);
4535
+ if (msg.role === "user" && !hasMeaningfulUserText2(msg.parts)) {
4536
+ const tcSummaries = extractToolCallSummaries(msg.parts);
4537
+ if (tcSummaries.length === 0) {
4538
+ recordFilteredNoise(meta);
4539
+ continue;
4540
+ }
4541
+ const tcText = tcSummaries.join(" / ");
4542
+ if (currentBlock && currentBlock.role === "A") {
4543
+ currentBlock.endOrdinal = msg.ordinal;
4544
+ currentBlock.parts.push(tcText);
4545
+ currentBlock.partMeta.push({
4546
+ ordinal: msg.ordinal,
4547
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
4548
+ });
4549
+ currentBlock.meta.push(...pendingNoiseMeta, meta);
4550
+ pendingNoiseMeta = [];
4551
+ } else {
4552
+ if (!flushCurrentBlock())
4553
+ break;
4554
+ currentBlock = {
4555
+ role: "A",
4556
+ startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
4557
+ endOrdinal: msg.ordinal,
4558
+ parts: [tcText],
4559
+ partMeta: [
4560
+ {
4561
+ ordinal: msg.ordinal,
4562
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
4563
+ }
4564
+ ],
4565
+ meta: [...pendingNoiseMeta, meta],
4566
+ commitHashes: [],
4567
+ isToolOnly: true
4568
+ };
4569
+ pendingNoiseMeta = [];
4570
+ }
4571
+ pinComponentWhenFormattedBudgetCrosses(msg.ordinal, tcText);
4572
+ continue;
4573
+ }
4574
+ const role = compactRole(msg.role);
4575
+ const textParts = extractTexts2(msg.parts).map((t) => msg.role === "user" ? cleanUserText2(t) : t).map(normalizeText).filter((value) => value.length > 0);
4576
+ const toolSummaries = textParts.length === 0 ? extractToolCallSummaries(msg.parts) : [];
4577
+ const allParts = [...textParts, ...toolSummaries];
4578
+ const compacted = compactTextForSummary(allParts.join(" / "), msg.role);
4579
+ const text = compacted.text;
4580
+ if (!text) {
4581
+ recordFilteredNoise(meta);
4582
+ continue;
4583
+ }
4584
+ const msgHasNarrative = textParts.length > 0;
4585
+ if (currentBlock && currentBlock.role === role) {
4586
+ currentBlock.endOrdinal = msg.ordinal;
4587
+ currentBlock.parts.push(text);
4588
+ currentBlock.partMeta.push({
4589
+ ordinal: msg.ordinal,
4590
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
4591
+ });
4592
+ currentBlock.meta.push(...pendingNoiseMeta, meta);
4593
+ currentBlock.commitHashes = mergeCommitHashes(currentBlock.commitHashes, compacted.commitHashes);
4594
+ if (msgHasNarrative)
4595
+ currentBlock.isToolOnly = false;
4596
+ pendingNoiseMeta = [];
4597
+ pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
4598
+ continue;
4599
+ }
4600
+ if (!flushCurrentBlock())
4601
+ break;
4602
+ currentBlock = {
4603
+ role,
4604
+ startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
4605
+ endOrdinal: msg.ordinal,
4606
+ parts: [text],
4607
+ partMeta: [
4608
+ {
4609
+ ordinal: msg.ordinal,
4610
+ toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
4611
+ }
4612
+ ],
4613
+ meta: [...pendingNoiseMeta, meta],
4614
+ commitHashes: [...compacted.commitHashes],
4615
+ isToolOnly: !msgHasNarrative
4616
+ };
4617
+ pendingNoiseMeta = [];
4618
+ pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
4619
+ }
4620
+ if (flushCurrentBlock() && pendingNoiseMeta.length > 0) {
4621
+ highestScannedOrdinal = Math.max(highestScannedOrdinal, pendingNoiseMeta[pendingNoiseMeta.length - 1]?.ordinal ?? highestScannedOrdinal);
4622
+ }
4623
+ const toolOnlyRanges = [];
4624
+ for (const range of flushedToolOnlyBlocks) {
4625
+ const last = toolOnlyRanges[toolOnlyRanges.length - 1];
4626
+ if (last && range.start === last.end + 1) {
4627
+ last.end = range.end;
4628
+ } else {
4629
+ toolOnlyRanges.push({ start: range.start, end: range.end });
4630
+ }
4631
+ }
4632
+ const text = lines.join(`
4633
+ `);
4634
+ const oversizeAtomicUnit = estimateBlockTokens(text) > tokenBudget && completedToolArcs.some((arc) => arc.start <= lastOrdinal && arc.end >= startOrdinal);
4635
+ return {
4636
+ startIndex: startOrdinal,
4637
+ endIndex: lastOrdinal,
4638
+ startMessageId: firstMessageId,
4639
+ endMessageId: lastMessageId,
4640
+ messageCount: messagesProcessed,
4641
+ tokenEstimate: totalTokens,
4642
+ ...oversizeAtomicUnit ? { oversizeAtomicUnit: true } : {},
4643
+ hasMore: Math.max(lastOrdinal, highestScannedOrdinal) < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, totalMessageCount) : totalMessageCount),
4644
+ text,
4645
+ lines: lineMeta,
4646
+ ...messagesProcessed === 0 && text.length === 0 ? { filteredNoiseLines: pendingNoiseMeta } : {},
4647
+ commitClusterCount: commitClusters,
4648
+ toolOnlyRanges,
4649
+ completedToolArcs,
4650
+ toolResultBoundaries
4651
+ };
4652
+ }
4653
+ export { CTX_REDUCE_KEEP, newestCtxReduceTagNumbers, textMentionsRecentCommit, removeSystemReminders, hasMeaningfulUserText2, extractTexts2, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isRecord, stableStringify, estimateImageTokensFromDataUrl, TODO_STATUSES, TODO_PRIORITIES, TITLE_DONE_STATUSES, normalizeTodoStateJson, buildSyntheticTodoPart, stripChannel1ReminderSpans, compareMeasuredTailPrefix, formatTailHygienePrefixMismatch, freezeTailHygieneMeasurement, effectiveTailHygiene, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, planEmergencyDrop, measureEmergencyTag, updateTagByteSize, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, updateTagInputByteSize, updateTagTokenCount, getPersistedToolTagAccounting, getAllStatusTagTokenTotalsFlat, updateTagInputTokenCount, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, getInertWhitespaceAssistantTags, updateTagDropMode, updateCavemanDepth, hasPiFallbackMessageTags, findAdoptableFallbackTags, hasPiFallbackToolOwnerTags, findPiFallbackToolOwnerTags, adoptPiFallbackToolOwnerTag, adoptPiFallbackMessageTag, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, TAG_SELECT_COLUMNS, getTagsBySession, getActiveTagsBySession, getTagsForPendingOperations, getTagsByNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, retreatPastHostUnservedRows, resolveOpenCodeDbPath, hasV1MessageTables, assertOpenCodeStoreGeneration, openCodeDbPathExists, getOpenCodeDbProbeDescriptions, recordOpenCodeDbReadFailure, clearOpenCodeDbReadFailure, claimOpenCodeDbDiagnosticOnce, registerSlowWriteReporter, detectSqliteRuntime, Database, withPrivilegedWriter, closeQuietly, withReadOnlySessionDb, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, droppedInputMarker, createDroppedInputGuard, isEditTool, applyEditMarkerToInput, setDatabase, loadToolDefinitionMeasurements, resolveDecisionCalibration, providerMass, localBudget, calibrationForModelKey, historyLocalBudget, resolveHostServedBoundaryId2, hasRawMessageProvider2, setRawMessageProvider2, withRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, readRawSessionMessageRange2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageIdOrdinalsForRange2, hasRawSessionMessageById2, getRawSessionMessageCount2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, readSessionChunk2 };