@retaw106/mmc-pi 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -4981,6 +4981,15 @@ var HistorianModelEntryObjectSchema = object({
4981
4981
  thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for this entry.")
4982
4982
  }).strict();
4983
4983
  var HistorianModelEntrySchema = union([string2(), HistorianModelEntryObjectSchema]);
4984
+ var MaintenanceModelEntrySchema = HistorianModelEntrySchema.superRefine((entry, ctx) => {
4985
+ const model = typeof entry === "string" ? entry : entry.model;
4986
+ if (typeof model !== "string" || model.trim().length === 0) {
4987
+ ctx.addIssue({
4988
+ code: "custom",
4989
+ message: "maintenance model entries must be non-empty: a bare provider/model string or { model, variant?, thinking_level? }"
4990
+ });
4991
+ }
4992
+ });
4984
4993
  var ProfileHistorianSchema = object({
4985
4994
  model: HistorianModelEntrySchema.optional().describe("Primary historian model entry."),
4986
4995
  fallback_models: array(HistorianModelEntrySchema).optional().describe("Ordered fallback historian model entries."),
@@ -5034,8 +5043,8 @@ var MagicContextConfigSchema = object({
5034
5043
  object({ default: number2().min(0) }).catchall(number2().min(0))
5035
5044
  ]).optional().describe('User-only output-token reservation override. Number or per-model object ({ default: 16384, "provider/model": 8192 }); 0 disables reservation. Takes precedence over every derived source: an explicit value here always wins against catalog output limits, provider window-geometry facts, and the 25%-of-context fallback (usable window = context window minus this reserve). When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.'),
5036
5045
  models: object({
5037
- window_overlay_path: string2().trim().min(1).optional()
5038
- }).optional().describe("User-only Fusiform window-overlay settings. The path defaults to <dataDir>/fusiform/window-overlay.json."),
5046
+ window_overlay_path: unknown().optional().describe("Deprecated: ignored. Fusiform no longer publishes window-overlay data, so this setting no longer changes model window geometry. Remove this key.").meta({ deprecated: true })
5047
+ }).optional().describe("Deprecated user-only Fusiform window-overlay settings; ignored."),
5039
5048
  toast_duration_ms: number2().min(0).max(60000).default(5000).describe("TUI toast lifetime in milliseconds for Magic Context notifications. Set to 0 to disable Magic Context toasts entirely (min: 0, max: 60000, default: 5000)"),
5040
5049
  execute_threshold_percentage: union([
5041
5050
  number2().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE),
@@ -5107,6 +5116,8 @@ var MagicContextConfigSchema = object({
5107
5116
  }).describe("Cross-session memory configuration"),
5108
5117
  maintenance: object({
5109
5118
  enabled: boolean2().default(true).describe("Enable the automatic memory-maintenance task (default: true). USER-LEVEL ONLY — the whole maintenance group is stripped from project-tier config."),
5119
+ model: MaintenanceModelEntrySchema.optional().describe("Primary maintenance model entry: a bare provider/model string or { model, variant? (OpenCode), thinking_level? (Pi) }. USER-LEVEL ONLY. When absent, inherit historian model configuration. If neither has a primary, automatic passes skip and manual runs refuse. The main-session model is never inherited."),
5120
+ fallback_models: array(MaintenanceModelEntrySchema).optional().describe("Ordered fallback maintenance model entries, tried after CALL failures only. When absent and the primary is inherited, inherit historian fallbacks; explicit [] disables fallbacks. Illegal manifests, permission refusals, and exhausted budgets never switch models."),
5110
5121
  budgets: object({
5111
5122
  inputTokens: number2().int().min(1).default(400000).describe("Per-run input-token budget (input + cacheRead + cacheWrite pricing dimensions). Default 400000."),
5112
5123
  outputTokens: number2().int().min(1).default(32000).describe("Per-run output-token budget. Default 32000."),
@@ -5148,7 +5159,7 @@ var MagicContextConfigSchema = object({
5148
5159
  maxRetries: 3
5149
5160
  },
5150
5161
  anomalyThreshold: { absoluteRows: 10, poolFraction: 0.25 }
5151
- }).describe("Automatic memory-maintenance run controls (dreamer replacement). USER-LEVEL ONLY: the whole group is stripped from project-tier config so a cloned repository cannot raise budgets, relax cooldowns, or loosen the anomaly guard.")
5162
+ }).describe("Automatic memory-maintenance run controls (dreamer replacement). USER-LEVEL ONLY: project-tier config cannot pick maintenance models or change run controls. An absent model inherits historian model configuration, never the session model.")
5152
5163
  });
5153
5164
  var LIVE_RELOAD_CONFIG_PATHS = [
5154
5165
  "cache_ttl",
@@ -4998,6 +4998,15 @@ var HistorianModelEntryObjectSchema = object({
4998
4998
  thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for this entry.")
4999
4999
  }).strict();
5000
5000
  var HistorianModelEntrySchema = union([string2(), HistorianModelEntryObjectSchema]);
5001
+ var MaintenanceModelEntrySchema = HistorianModelEntrySchema.superRefine((entry, ctx) => {
5002
+ const model = typeof entry === "string" ? entry : entry.model;
5003
+ if (typeof model !== "string" || model.trim().length === 0) {
5004
+ ctx.addIssue({
5005
+ code: "custom",
5006
+ message: "maintenance model entries must be non-empty: a bare provider/model string or { model, variant?, thinking_level? }"
5007
+ });
5008
+ }
5009
+ });
5001
5010
  var ProfileHistorianSchema = object({
5002
5011
  model: HistorianModelEntrySchema.optional().describe("Primary historian model entry."),
5003
5012
  fallback_models: array(HistorianModelEntrySchema).optional().describe("Ordered fallback historian model entries."),
@@ -5051,8 +5060,8 @@ var MagicContextConfigSchema = object({
5051
5060
  object({ default: number2().min(0) }).catchall(number2().min(0))
5052
5061
  ]).optional().describe('User-only output-token reservation override. Number or per-model object ({ default: 16384, "provider/model": 8192 }); 0 disables reservation. Takes precedence over every derived source: an explicit value here always wins against catalog output limits, provider window-geometry facts, and the 25%-of-context fallback (usable window = context window minus this reserve). When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.'),
5053
5062
  models: object({
5054
- window_overlay_path: string2().trim().min(1).optional()
5055
- }).optional().describe("User-only Fusiform window-overlay settings. The path defaults to <dataDir>/fusiform/window-overlay.json."),
5063
+ window_overlay_path: unknown().optional().describe("Deprecated: ignored. Fusiform no longer publishes window-overlay data, so this setting no longer changes model window geometry. Remove this key.").meta({ deprecated: true })
5064
+ }).optional().describe("Deprecated user-only Fusiform window-overlay settings; ignored."),
5056
5065
  toast_duration_ms: number2().min(0).max(60000).default(5000).describe("TUI toast lifetime in milliseconds for Magic Context notifications. Set to 0 to disable Magic Context toasts entirely (min: 0, max: 60000, default: 5000)"),
5057
5066
  execute_threshold_percentage: union([
5058
5067
  number2().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE),
@@ -5124,6 +5133,8 @@ var MagicContextConfigSchema = object({
5124
5133
  }).describe("Cross-session memory configuration"),
5125
5134
  maintenance: object({
5126
5135
  enabled: boolean2().default(true).describe("Enable the automatic memory-maintenance task (default: true). USER-LEVEL ONLY — the whole maintenance group is stripped from project-tier config."),
5136
+ model: MaintenanceModelEntrySchema.optional().describe("Primary maintenance model entry: a bare provider/model string or { model, variant? (OpenCode), thinking_level? (Pi) }. USER-LEVEL ONLY. When absent, inherit historian model configuration. If neither has a primary, automatic passes skip and manual runs refuse. The main-session model is never inherited."),
5137
+ fallback_models: array(MaintenanceModelEntrySchema).optional().describe("Ordered fallback maintenance model entries, tried after CALL failures only. When absent and the primary is inherited, inherit historian fallbacks; explicit [] disables fallbacks. Illegal manifests, permission refusals, and exhausted budgets never switch models."),
5127
5138
  budgets: object({
5128
5139
  inputTokens: number2().int().min(1).default(400000).describe("Per-run input-token budget (input + cacheRead + cacheWrite pricing dimensions). Default 400000."),
5129
5140
  outputTokens: number2().int().min(1).default(32000).describe("Per-run output-token budget. Default 32000."),
@@ -5165,7 +5176,7 @@ var MagicContextConfigSchema = object({
5165
5176
  maxRetries: 3
5166
5177
  },
5167
5178
  anomalyThreshold: { absoluteRows: 10, poolFraction: 0.25 }
5168
- }).describe("Automatic memory-maintenance run controls (dreamer replacement). USER-LEVEL ONLY: the whole group is stripped from project-tier config so a cloned repository cannot raise budgets, relax cooldowns, or loosen the anomaly guard.")
5179
+ }).describe("Automatic memory-maintenance run controls (dreamer replacement). USER-LEVEL ONLY: project-tier config cannot pick maintenance models or change run controls. An absent model inherits historian model configuration, never the session model.")
5169
5180
  });
5170
5181
  var LIVE_RELOAD_CONFIG_PATHS = [
5171
5182
  "cache_ttl",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  log
3
- } from "./index-54cgx9gm.js";
3
+ } from "./index-83p1tc98.js";
4
4
 
5
5
  // ../plugin/src/shared/safe-notification-target.ts
6
6
  var DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  log
3
- } from "./index-54cgx9gm.js";
3
+ } from "./index-83p1tc98.js";
4
4
 
5
5
  // ../plugin/src/shared/write-transaction-timing.ts
6
6
  var SLOW_WRITE_TRANSACTION_THRESHOLD_MS = 1000;
@@ -431,8 +431,12 @@ function flush() {
431
431
  let currentSize = getCurrentLogSize(logFile);
432
432
  const dataSize = Buffer.byteLength(data);
433
433
  if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
434
- rotateLogFile(logFile, currentSize);
435
- currentSize = 0;
434
+ flushesSinceSizeCheck = SIZE_CHECK_INTERVAL_FLUSHES;
435
+ currentSize = getCurrentLogSize(logFile);
436
+ if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
437
+ rotateLogFile(logFile, currentSize);
438
+ currentSize = 0;
439
+ }
436
440
  }
437
441
  fs.appendFileSync(logFile, data, { encoding: "utf8", mode: 384 });
438
442
  buffer = [];
@@ -1,16 +1,23 @@
1
1
  // ../plugin/src/shared/sqlite.ts
2
- import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
3
+ var resourceRoot = new AsyncResource("magic-context:root");
4
+ function inRootAsyncContext(operation) {
5
+ return resourceRoot.runInAsyncScope(operation);
6
+ }
3
7
  var reportSlowPrivilegedWrite;
4
8
  function registerSlowWriteReporter(reporter) {
5
9
  reportSlowPrivilegedWrite = reporter;
6
10
  }
7
11
  var sqliteDiagnosticSink;
8
- function registerSqliteDiagnosticSink(sink) {
12
+ var sqliteDiagnosticHost = () => "unknown";
13
+ function registerSqliteDiagnosticSink(sink, host) {
9
14
  sqliteDiagnosticSink = sink;
15
+ if (host)
16
+ sqliteDiagnosticHost = host;
10
17
  }
11
18
  function reportSqliteDiagnostic(message) {
12
19
  try {
13
- sqliteDiagnosticSink?.(`[magic-context] ${message}`);
20
+ sqliteDiagnosticSink?.(`[magic-context] ${message} pid=${process.pid} host=${sqliteDiagnosticHost()}`);
14
21
  } catch {}
15
22
  }
16
23
  function detectSqliteRuntime() {
@@ -46,10 +53,31 @@ class SqliteRuntimeUnavailableError extends Error {
46
53
  this.specifier = specifier;
47
54
  }
48
55
  }
56
+ function isNodeSqliteExperimentalWarning(args) {
57
+ const [warning, options] = args;
58
+ const message = warning instanceof Error ? warning.message : warning;
59
+ const type = typeof options === "string" ? options : options && typeof options === "object" ? options.type : undefined;
60
+ return type === "ExperimentalWarning" && typeof message === "string" && message.startsWith("SQLite is an experimental feature");
61
+ }
62
+ async function importSqliteModuleForRuntime(runtime, specifier, importer) {
63
+ if (runtime !== "Node.js")
64
+ return importer(specifier);
65
+ const originalEmitWarning = process.emitWarning;
66
+ process.emitWarning = function(...args) {
67
+ if (isNodeSqliteExperimentalWarning(args))
68
+ return;
69
+ Reflect.apply(originalEmitWarning, this, args);
70
+ };
71
+ try {
72
+ return await importer(specifier);
73
+ } finally {
74
+ process.emitWarning = originalEmitWarning;
75
+ }
76
+ }
49
77
  async function loadSqliteModule(runtime = detectSqliteRuntime(), importer = importSqliteModule) {
50
78
  const specifier = runtime === "Bun" ? bunSpec : nodeSpec;
51
79
  try {
52
- return await importer(specifier);
80
+ return await importSqliteModuleForRuntime(runtime, specifier, importer);
53
81
  } catch (error) {
54
82
  if (isModuleNotFoundError(error, specifier)) {
55
83
  throw new SqliteRuntimeUnavailableError(runtime, specifier, error);
@@ -63,6 +91,81 @@ var sqliteModule = await loadSqliteModule(detectedRuntime);
63
91
  var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
64
92
  var trackedSqliteConnections = new Map;
65
93
  var nextSqliteConnectionSequence = 1;
94
+ var TAG_COLUMNS_OUTSIDE_IDENTITY = new Set([
95
+ "status",
96
+ "drop_mode",
97
+ "byte_size",
98
+ "input_byte_size",
99
+ "reasoning_byte_size",
100
+ "token_count",
101
+ "input_token_count",
102
+ "caveman_depth",
103
+ "entry_fingerprint",
104
+ "tool_name",
105
+ "harness"
106
+ ]);
107
+ var tagIdentityWriteGeneration = 0;
108
+ function mayChangeTagIdentity(sql) {
109
+ if (!/\btags\b/i.test(sql) || /^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql))
110
+ return false;
111
+ if (/^\s*WITH\b/i.test(sql) && !/\b(?:INSERT|UPDATE|DELETE|REPLACE)\b/i.test(sql))
112
+ return false;
113
+ if (/;\s*\S/.test(sql) || /\bREPLACE\b/i.test(sql) || /\bON\s+CONFLICT\b/i.test(sql))
114
+ return true;
115
+ const insert = /^\s*INSERT\s+INTO\s+(?:main\.)?["`]?tags["`]?\s*\(([^)]*)\)/i.exec(sql);
116
+ if (insert) {
117
+ const columns = (insert[1] ?? "").split(",").map((column) => column.trim().replace(/["`[\]]/g, "").toLowerCase());
118
+ return columns.includes("id") || columns.includes("rowid");
119
+ }
120
+ const update = /^\s*UPDATE\s+(?:main\.)?["`]?tags["`]?\s+SET\s+([\s\S]*?)\bWHERE\b/i.exec(sql);
121
+ if (update && !/\bSELECT\b/i.test(sql)) {
122
+ const assignments = topLevelCommaSegments(update[1] ?? "");
123
+ if (!assignments)
124
+ return true;
125
+ return !assignments.every((assignment) => {
126
+ const column = /^\s*["`]?(\w+)["`]?\s*=(?!=)/.exec(assignment)?.[1];
127
+ return column !== undefined && TAG_COLUMNS_OUTSIDE_IDENTITY.has(column.toLowerCase());
128
+ });
129
+ }
130
+ return true;
131
+ }
132
+ function topLevelCommaSegments(text) {
133
+ const segments = [];
134
+ let depth = 0;
135
+ let quote = null;
136
+ let start = 0;
137
+ for (let index = 0;index < text.length; index += 1) {
138
+ const char = text[index];
139
+ if (quote) {
140
+ if (char === quote) {
141
+ if (text[index + 1] === quote)
142
+ index += 1;
143
+ else
144
+ quote = null;
145
+ }
146
+ continue;
147
+ }
148
+ if (char === "'" || char === '"' || char === "`")
149
+ quote = char;
150
+ else if (char === "(")
151
+ depth += 1;
152
+ else if (char === ")") {
153
+ depth -= 1;
154
+ if (depth < 0)
155
+ return null;
156
+ } else if (char === "," && depth === 0) {
157
+ segments.push(text.slice(start, index));
158
+ start = index + 1;
159
+ }
160
+ }
161
+ if (quote || depth !== 0)
162
+ return null;
163
+ segments.push(text.slice(start));
164
+ return segments;
165
+ }
166
+ function getTagIdentityWriteGeneration() {
167
+ return tagIdentityWriteGeneration;
168
+ }
66
169
  function installTransactionRouting(db, readonly) {
67
170
  const nativeExec = db.exec.bind(db);
68
171
  Object.defineProperty(db, "exec", {
@@ -73,16 +176,30 @@ function installTransactionRouting(db, readonly) {
73
176
  assertTransformWrite();
74
177
  if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
75
178
  openWriterTransactions.delete(db);
76
- if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore())
179
+ if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore()) {
77
180
  acquireShort(db, () => nativeExec(sql), sql.trim());
78
- else
181
+ } else {
79
182
  nativeExec(sql);
183
+ openWriterTransactions.set(db, {
184
+ site: sql.trim(),
185
+ lane: "background",
186
+ acquireMs: 0,
187
+ attempts: 1,
188
+ acquiredAt: performance.now()
189
+ });
190
+ }
80
191
  return db;
81
192
  }
82
193
  if (WRITER_TRANSACTION_END.test(sql) && openWriterTransactions.has(db))
83
194
  return endWriterTransaction(db, () => nativeExec(sql), sql);
84
- if (!/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql))
85
- return withAutocommitTimeout(db, () => nativeExec(sql));
195
+ if (!/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql)) {
196
+ try {
197
+ return withAutocommitTimeout(db, () => nativeExec(sql), false);
198
+ } finally {
199
+ if (mayChangeTagIdentity(sql))
200
+ tagIdentityWriteGeneration += 1;
201
+ }
202
+ }
86
203
  return nativeExec(sql);
87
204
  }
88
205
  });
@@ -93,13 +210,23 @@ function installTransactionRouting(db, readonly) {
93
210
  value: (sql) => {
94
211
  const statement = nativePrepare(sql);
95
212
  if (!readonly && !/^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql)) {
213
+ const changesTagIdentity = mayChangeTagIdentity(sql);
96
214
  for (const method of ["run", "get", "all"]) {
97
215
  const execute = statement[method].bind(statement);
98
216
  Object.defineProperty(statement, method, {
99
217
  configurable: true,
100
- value: (...args) => withAutocommitTimeout(db, () => execute(...args))
218
+ value: (...args) => {
219
+ try {
220
+ return withAutocommitTimeout(db, () => execute(...args));
221
+ } finally {
222
+ if (changesTagIdentity)
223
+ tagIdentityWriteGeneration += 1;
224
+ }
225
+ }
101
226
  });
102
227
  }
228
+ if (changesTagIdentity)
229
+ wrapRemainingTagWriteForms(statement);
103
230
  }
104
231
  return statement;
105
232
  }
@@ -147,6 +274,35 @@ function installTransactionRouting(db, readonly) {
147
274
  }
148
275
  });
149
276
  }
277
+ function wrapRemainingTagWriteForms(statement) {
278
+ if (typeof statement.iterate === "function") {
279
+ const iterate = statement.iterate.bind(statement);
280
+ Object.defineProperty(statement, "iterate", {
281
+ configurable: true,
282
+ value: function* (...args) {
283
+ tagIdentityWriteGeneration += 1;
284
+ try {
285
+ yield* iterate(...args);
286
+ } finally {
287
+ tagIdentityWriteGeneration += 1;
288
+ }
289
+ }
290
+ });
291
+ }
292
+ if (typeof statement.values === "function") {
293
+ const values = statement.values.bind(statement);
294
+ Object.defineProperty(statement, "values", {
295
+ configurable: true,
296
+ value: (...args) => {
297
+ try {
298
+ return values(...args);
299
+ } finally {
300
+ tagIdentityWriteGeneration += 1;
301
+ }
302
+ }
303
+ });
304
+ }
305
+ }
150
306
  function trackSqliteConnection(db, filename, options) {
151
307
  const originalClose = db.close.bind(db);
152
308
  const sequence = nextSqliteConnectionSequence++;
@@ -180,7 +336,7 @@ function trackSqliteConnection(db, filename, options) {
180
336
  }
181
337
  var TrackedDatabase = new Proxy(DatabaseImpl, {
182
338
  construct(target, args) {
183
- const db = Reflect.construct(target, args, target);
339
+ const db = inRootAsyncContext(() => Reflect.construct(target, args, target));
184
340
  return trackSqliteConnection(db, args[0], args[1]);
185
341
  }
186
342
  });
@@ -207,6 +363,18 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
207
363
  return NodeSqliteDatabase;
208
364
  }
209
365
  var Database = TrackedDatabase;
366
+ function getSqliteDatabasePath(db) {
367
+ for (const connection of trackedSqliteConnections.values()) {
368
+ if (connection.reference.deref() === db) {
369
+ return connection.filename === ":memory:" || connection.filename === "<buffer>" ? null : connection.filename;
370
+ }
371
+ }
372
+ const native = db;
373
+ const path = native.filename ?? native.name;
374
+ if (typeof path === "string" && path !== ":memory:" && path !== "")
375
+ return path;
376
+ return null;
377
+ }
210
378
  function pragmaValue(db, name) {
211
379
  const row = db.prepare(`PRAGMA ${name}`).get();
212
380
  if (!row)
@@ -289,22 +457,29 @@ function withSqliteTransformPass(operation) {
289
457
  const existing = transformPassScope.getStore();
290
458
  if (existing?.active)
291
459
  return operation();
292
- const lease = { active: true, remainingWaitMs: FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS };
293
- return transformPassScope.run(lease, () => {
294
- try {
295
- const result = operation();
296
- if (result && typeof result.then === "function") {
297
- return Promise.resolve(result).finally(() => {
298
- lease.active = false;
299
- });
460
+ const reservation = reserveForegroundSqliteTurn();
461
+ const run = (release) => {
462
+ const lease = { active: true, remainingWaitMs: FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS };
463
+ return transformPassScope.run(lease, () => {
464
+ try {
465
+ const result = operation();
466
+ if (result && typeof result.then === "function") {
467
+ return Promise.resolve(result).finally(() => {
468
+ lease.active = false;
469
+ release();
470
+ });
471
+ }
472
+ lease.active = false;
473
+ release();
474
+ return result;
475
+ } catch (error) {
476
+ lease.active = false;
477
+ release();
478
+ throw error;
300
479
  }
301
- lease.active = false;
302
- return result;
303
- } catch (error) {
304
- lease.active = false;
305
- throw error;
306
- }
307
- });
480
+ });
481
+ };
482
+ return typeof reservation === "function" ? run(reservation) : reservation.then(run);
308
483
  }
309
484
  function withoutSqliteTransformPass(operation) {
310
485
  return transformPassScope.run(undefined, operation);
@@ -335,9 +510,9 @@ class SqliteAcquisitionBusyError extends Error {
335
510
  }
336
511
  }
337
512
  var SHORT_BUSY_TIMEOUT_MS = 25;
338
- var FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS = 250;
513
+ var FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS = 2000;
339
514
  var FOREGROUND_ACQUISITION_BUDGET_MS = 16500;
340
- var SLOW_WRITER_LOG_MS = 250;
515
+ var SLOW_WRITER_LOG_MS = 100;
341
516
  var WRITER_TRANSACTION_END = /^\s*(?:COMMIT|END|ROLLBACK)(?:\s+TRANSACTION)?\s*;?\s*$/i;
342
517
  var writerAcquisitionScope = new AsyncLocalStorage;
343
518
  var openWriterTransactions = new WeakMap;
@@ -345,25 +520,52 @@ function foregroundWaitLease() {
345
520
  const lease = transformPassScope.getStore();
346
521
  return lease?.active && !admissionScope.getStore() && !backgroundWriterScope.getStore() ? lease : undefined;
347
522
  }
348
- function withAutocommitTimeout(db, operation) {
523
+ function withAutocommitTimeout(db, operation, singleStatement = true) {
349
524
  assertTransformWrite();
350
525
  const lease = foregroundWaitLease();
351
- if (isInTransaction(db) || !lease && !backgroundWriterScope.getStore())
526
+ if (isInTransaction(db))
352
527
  return operation();
353
- const previous = pragmaNumber(db, "busy_timeout");
354
- db.exec(`PRAGMA busy_timeout=${lease ? Math.floor(lease.remainingWaitMs) : SHORT_BUSY_TIMEOUT_MS}`);
528
+ const scoped = lease || backgroundWriterScope.getStore();
529
+ const previous = scoped ? pragmaNumber(db, "busy_timeout") : null;
355
530
  const started = performance.now();
531
+ let completed = false;
532
+ const execute = () => {
533
+ const result = operation();
534
+ completed = true;
535
+ return result;
536
+ };
356
537
  try {
357
- return operation();
538
+ if (!scoped)
539
+ return execute();
540
+ if (singleStatement) {
541
+ db.exec("PRAGMA busy_timeout=0");
542
+ try {
543
+ return execute();
544
+ } catch (error) {
545
+ if (!isTransientSqliteError(error) || isInTransaction(db))
546
+ throw error;
547
+ }
548
+ assertTransformWrite();
549
+ }
550
+ const timeout = Math.floor(Math.min(lease?.remainingWaitMs ?? SHORT_BUSY_TIMEOUT_MS, lease?.guard?.remainingMs() ?? Infinity));
551
+ db.exec(`PRAGMA busy_timeout=${timeout}`);
552
+ const waitStarted = performance.now();
553
+ try {
554
+ return execute();
555
+ } finally {
556
+ if (lease)
557
+ lease.remainingWaitMs = Math.max(0, lease.remainingWaitMs - (performance.now() - waitStarted));
558
+ }
358
559
  } catch (error) {
359
560
  if (lease && isTransientSqliteError(error))
360
561
  throw new SqliteAcquisitionBusyError(error, "autocommit");
361
562
  throw error;
362
563
  } finally {
363
- if (lease)
364
- lease.remainingWaitMs = Math.max(0, lease.remainingWaitMs - (performance.now() - started));
564
+ const elapsed = performance.now() - started;
365
565
  if (previous !== null)
366
566
  db.exec(`PRAGMA busy_timeout=${previous}`);
567
+ if (elapsed >= SLOW_WRITER_LOG_MS)
568
+ reportSqliteDiagnostic(`sqlite writer site=autocommit lane=${lease ? "foreground" : "background"} elapsed_ms=${Math.round(elapsed)} timing=statement_including_acquisition outcome=${completed ? "completed" : "failed"} caller=${writerCaller()}`);
367
569
  }
368
570
  }
369
571
  function acquireShort(db, acquire, site) {
@@ -420,11 +622,15 @@ function endWriterTransaction(db, end, sql) {
420
622
  const holdMs = performance.now() - open.acquiredAt;
421
623
  if (open.acquireMs >= SLOW_WRITER_LOG_MS || holdMs >= SLOW_WRITER_LOG_MS) {
422
624
  const outcome = /^\s*ROLLBACK/i.test(sql) ? "rolled_back" : ended ? "committed" : "failed";
423
- reportSqliteDiagnostic(`sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} attempts=${open.attempts} outcome=${outcome}`);
625
+ reportSqliteDiagnostic(`sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} attempts=${open.attempts} outcome=${outcome} timing=through_commit_upper_bound caller=${writerCaller()}`);
424
626
  }
425
627
  }
426
628
  }
427
629
  }
630
+ function writerCaller() {
631
+ return new Error().stack?.split(`
632
+ `).find((line) => line.includes(" at ") && !/[/\\]sqlite\.[tj]s[:)]/.test(line) && !/\b(?:writerCaller|endWriterTransaction|withAutocommitTimeout|value)\b/.test(line))?.trim().replace(/\s+/g, "_") ?? "unknown";
633
+ }
428
634
  async function withAsyncPrivilegedWriter(db, operation, options = {}) {
429
635
  const started = performance.now();
430
636
  const budgetMs = Math.max(0, Math.min(FOREGROUND_ACQUISITION_BUDGET_MS, options.budgetMs ?? Infinity));
@@ -533,5 +739,56 @@ function withPrivilegedWriter(db, operation) {
533
739
  throw error;
534
740
  }
535
741
  }
742
+ var indexCoordinationKey = Symbol.for("magic-context.index-foreground-coordination.v1");
743
+ var indexCoordinationHeap = globalThis;
744
+ var indexCoordinationBuffer = indexCoordinationHeap[indexCoordinationKey] ?? new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);
745
+ indexCoordinationHeap[indexCoordinationKey] = indexCoordinationBuffer;
746
+ var indexCoordinationState = new Int32Array(indexCoordinationBuffer);
747
+ function indexCoordinationInput() {
748
+ return {
749
+ indexCoordination: indexCoordinationBuffer,
750
+ indexOwner: Atomics.add(indexCoordinationState, 2, 1) + 1
751
+ };
752
+ }
753
+ var yieldIndexTurn = () => new Promise((resolve) => setTimeout(resolve, 1));
754
+ function reserveForegroundSqliteTurn() {
755
+ Atomics.add(indexCoordinationState, 0, 1);
756
+ const release = () => {
757
+ Atomics.sub(indexCoordinationState, 0, 1);
758
+ Atomics.notify(indexCoordinationState, 0);
759
+ };
760
+ if (Atomics.load(indexCoordinationState, 1) === 0)
761
+ return release;
762
+ return (async () => {
763
+ while (Atomics.load(indexCoordinationState, 1) !== 0)
764
+ await yieldIndexTurn();
765
+ return release;
766
+ })();
767
+ }
768
+ function releaseIndexOwner(input) {
769
+ if (!input.indexCoordination || !input.indexOwner)
770
+ return;
771
+ const shared = new Int32Array(input.indexCoordination);
772
+ Atomics.compareExchange(shared, 1, input.indexOwner, 0);
773
+ Atomics.notify(shared, 1);
774
+ }
775
+ async function withIndexChunk(input, operation) {
776
+ if (!input.indexCoordination || !input.indexOwner)
777
+ return operation();
778
+ const shared = new Int32Array(input.indexCoordination);
779
+ for (;; ) {
780
+ if (Atomics.load(shared, 0) === 0 && Atomics.compareExchange(shared, 1, 0, input.indexOwner) === 0) {
781
+ if (Atomics.load(shared, 0) === 0)
782
+ break;
783
+ releaseIndexOwner(input);
784
+ }
785
+ await yieldIndexTurn();
786
+ }
787
+ try {
788
+ return await operation();
789
+ } finally {
790
+ releaseIndexOwner(input);
791
+ }
792
+ }
536
793
 
537
- export { registerSlowWriteReporter, registerSqliteDiagnosticSink, detectSqliteRuntime, Database, prepareCachedStatement, withSqliteBackgroundWriter, withSqliteTransformPass, withoutSqliteTransformPass, guardSqliteTransformPass, isTransientSqliteError, withAsyncPrivilegedWriter, withPrivilegedWriter };
794
+ export { inRootAsyncContext, registerSlowWriteReporter, registerSqliteDiagnosticSink, detectSqliteRuntime, getTagIdentityWriteGeneration, Database, getSqliteDatabasePath, prepareCachedStatement, withSqliteBackgroundWriter, withSqliteTransformPass, withoutSqliteTransformPass, guardSqliteTransformPass, isTransientSqliteError, withAsyncPrivilegedWriter, withPrivilegedWriter, indexCoordinationInput, withIndexChunk };