@cortexkit/opencode-magic-context 0.30.6 → 0.30.7

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/index.js CHANGED
@@ -15446,6 +15446,340 @@ var init_magic_context = __esm(() => {
15446
15446
  });
15447
15447
  });
15448
15448
 
15449
+ // src/shared/error-message.ts
15450
+ function getErrorMessage(error51) {
15451
+ return error51 instanceof Error ? error51.message : String(error51);
15452
+ }
15453
+ function readString(value) {
15454
+ if (typeof value === "string" && value.length > 0)
15455
+ return value;
15456
+ if (typeof value === "number")
15457
+ return String(value);
15458
+ return;
15459
+ }
15460
+ function clip(value, max) {
15461
+ if (value.length <= max)
15462
+ return value;
15463
+ return `${value.slice(0, max)}…`;
15464
+ }
15465
+ function describeError(error51) {
15466
+ const stringForm = clip(safeString(error51), 400);
15467
+ if (!(error51 instanceof Error) && !(error51 && typeof error51 === "object")) {
15468
+ return {
15469
+ name: typeof error51,
15470
+ message: "",
15471
+ stringForm,
15472
+ brief: stringForm || "<empty>"
15473
+ };
15474
+ }
15475
+ const obj = error51;
15476
+ const nameFromField = readString(obj.name);
15477
+ const nameFromCtor = error51?.constructor?.name;
15478
+ const name = nameFromField ?? nameFromCtor ?? "Error";
15479
+ const message = readString(obj.message) ?? "";
15480
+ const status = readString(obj.status) ?? readString(obj.statusCode);
15481
+ const code = readString(obj.code);
15482
+ let causeName;
15483
+ const cause = obj.cause;
15484
+ if (cause && typeof cause === "object") {
15485
+ const causeRecord = cause;
15486
+ causeName = readString(causeRecord.name) ?? cause.constructor?.name;
15487
+ }
15488
+ const stack = readString(obj.stack);
15489
+ const stackHead = stack ? stack.split(`
15490
+ `).slice(0, 4).map((l) => l.trim()).filter((l) => l.length > 0).join(" | ") : undefined;
15491
+ const briefParts = [];
15492
+ if (name)
15493
+ briefParts.push(name);
15494
+ if (message)
15495
+ briefParts.push(`message="${clip(message, 200)}"`);
15496
+ if (status)
15497
+ briefParts.push(`status=${status}`);
15498
+ if (code)
15499
+ briefParts.push(`code=${code}`);
15500
+ if (causeName)
15501
+ briefParts.push(`cause=${causeName}`);
15502
+ if (!message && stringForm && stringForm !== name) {
15503
+ briefParts.push(`str="${clip(stringForm, 200)}"`);
15504
+ }
15505
+ const brief = briefParts.join(" ") || stringForm || name;
15506
+ return {
15507
+ name,
15508
+ message,
15509
+ ...status ? { status } : {},
15510
+ ...code ? { code } : {},
15511
+ ...causeName ? { causeName } : {},
15512
+ ...stackHead ? { stackHead } : {},
15513
+ stringForm,
15514
+ brief
15515
+ };
15516
+ }
15517
+ function safeString(value) {
15518
+ try {
15519
+ return String(value);
15520
+ } catch {
15521
+ return "<unstringifiable>";
15522
+ }
15523
+ }
15524
+
15525
+ // src/shared/sqlite.ts
15526
+ function buildNodeSqliteDatabaseClass(DatabaseSync) {
15527
+ const SAVEPOINT = "mc_tx_sp";
15528
+
15529
+ class NodeSqliteDatabase extends DatabaseSync {
15530
+ constructor(filename, options) {
15531
+ const translated = { ...options };
15532
+ if (options && "readonly" in options) {
15533
+ translated.readOnly = options.readonly;
15534
+ delete translated.readonly;
15535
+ }
15536
+ super(typeof filename === "string" ? filename : ":memory:", translated);
15537
+ }
15538
+ prepare(sql) {
15539
+ const stmt = super.prepare(sql);
15540
+ for (const method of ["run", "get", "all"]) {
15541
+ const original = stmt[method].bind(stmt);
15542
+ stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
15543
+ }
15544
+ return stmt;
15545
+ }
15546
+ transaction(fn) {
15547
+ const self2 = this;
15548
+ const wrapped = function(...args) {
15549
+ const nested = self2.isTransaction === true;
15550
+ self2.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
15551
+ try {
15552
+ const result = fn.apply(this, args);
15553
+ self2.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
15554
+ return result;
15555
+ } catch (error51) {
15556
+ if (nested) {
15557
+ self2.exec(`ROLLBACK TO ${SAVEPOINT}`);
15558
+ self2.exec(`RELEASE ${SAVEPOINT}`);
15559
+ } else {
15560
+ self2.exec("ROLLBACK");
15561
+ }
15562
+ throw error51;
15563
+ }
15564
+ };
15565
+ return wrapped;
15566
+ }
15567
+ }
15568
+ return NodeSqliteDatabase;
15569
+ }
15570
+ var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
15571
+ var init_sqlite = __esm(async () => {
15572
+ isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
15573
+ bunSpec = "bun:" + "sqlite";
15574
+ nodeSpec = "node:" + "sqlite";
15575
+ sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
15576
+ DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
15577
+ Database = DatabaseImpl;
15578
+ });
15579
+
15580
+ // src/shared/sqlite-helpers.ts
15581
+ function closeQuietly(db) {
15582
+ if (!db)
15583
+ return;
15584
+ try {
15585
+ db.close();
15586
+ } catch {}
15587
+ }
15588
+
15589
+ // src/features/magic-context/compaction-marker.ts
15590
+ import { existsSync as existsSync6 } from "node:fs";
15591
+ import { join as join3 } from "node:path";
15592
+ function randomBase62(length) {
15593
+ const chars = [];
15594
+ for (let i = 0;i < length; i++) {
15595
+ chars.push(BASE62_CHARS[Math.floor(Math.random() * BASE62_CHARS.length)]);
15596
+ }
15597
+ return chars.join("");
15598
+ }
15599
+ function generateId(prefix, timestampMs, counter = 0n) {
15600
+ const encoded = BigInt(timestampMs) * 0x1000n + counter;
15601
+ const hex3 = encoded.toString(16).padStart(14, "0");
15602
+ return `${prefix}_${hex3}${randomBase62(14)}`;
15603
+ }
15604
+ function generateMessageId(timestampMs, counter = 0n) {
15605
+ return generateId("msg", timestampMs, counter);
15606
+ }
15607
+ function generatePartId(timestampMs, counter = 0n) {
15608
+ return generateId("prt", timestampMs, counter);
15609
+ }
15610
+ function getOpenCodeDbPath() {
15611
+ return join3(getDataDir(), "opencode", "opencode.db");
15612
+ }
15613
+ function isOpenCodeSchemaCompatible(db, dbPath) {
15614
+ if (cachedSchemaCompatible?.path === dbPath) {
15615
+ return cachedSchemaCompatible.compatible;
15616
+ }
15617
+ try {
15618
+ const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
15619
+ const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
15620
+ const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
15621
+ const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
15622
+ if (missingMessage.length > 0 || missingPart.length > 0) {
15623
+ log(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
15624
+ cachedSchemaCompatible = { path: dbPath, compatible: false };
15625
+ return false;
15626
+ }
15627
+ cachedSchemaCompatible = { path: dbPath, compatible: true };
15628
+ return true;
15629
+ } catch (error51) {
15630
+ log(`[magic-context] compaction-marker: schema probe failed: ${error51 instanceof Error ? error51.message : String(error51)}. ` + `Marker injection disabled until next process restart.`);
15631
+ cachedSchemaCompatible = { path: dbPath, compatible: false };
15632
+ return false;
15633
+ }
15634
+ }
15635
+ function getWritableOpenCodeDb() {
15636
+ const dbPath = getOpenCodeDbPath();
15637
+ if (cachedWriteDb?.path === dbPath) {
15638
+ return cachedWriteDb.db;
15639
+ }
15640
+ if (cachedWriteDb) {
15641
+ try {
15642
+ closeQuietly(cachedWriteDb.db);
15643
+ } catch {}
15644
+ }
15645
+ if (!existsSync6(dbPath)) {
15646
+ throw new Error(`OpenCode database not found at ${dbPath} (is OpenCode installed?)`);
15647
+ }
15648
+ const db = new Database(dbPath);
15649
+ db.exec("PRAGMA busy_timeout=5000");
15650
+ db.exec("PRAGMA journal_mode=WAL");
15651
+ cachedWriteDb = { path: dbPath, db };
15652
+ return db;
15653
+ }
15654
+ function getNonSummaryMessageSortKey(sessionId, messageId) {
15655
+ const db = getWritableOpenCodeDb();
15656
+ const row = db.prepare(`SELECT time_created, id
15657
+ FROM message
15658
+ WHERE session_id = ?
15659
+ AND id = ?
15660
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
15661
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
15662
+ LIMIT 1`).get(sessionId, messageId);
15663
+ if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
15664
+ return null;
15665
+ }
15666
+ return { id: row.id, timeCreated: row.time_created };
15667
+ }
15668
+ function findBoundaryUserMessage(sessionId, endMessageId) {
15669
+ const db = getWritableOpenCodeDb();
15670
+ const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
15671
+ if (!target)
15672
+ return null;
15673
+ const boundary = db.prepare(`SELECT id, time_created, data
15674
+ FROM message
15675
+ WHERE session_id = ?
15676
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
15677
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
15678
+ AND COALESCE(json_extract(data, '$.role'), '') = 'user'
15679
+ AND (time_created < ? OR (time_created = ? AND id <= ?))
15680
+ ORDER BY time_created DESC, id DESC
15681
+ LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
15682
+ if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
15683
+ return null;
15684
+ }
15685
+ return { id: boundary.id, timeCreated: boundary.time_created };
15686
+ }
15687
+ function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
15688
+ const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
15689
+ const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
15690
+ if (!left || !right)
15691
+ return null;
15692
+ if (left.timeCreated < right.timeCreated)
15693
+ return -1;
15694
+ if (left.timeCreated > right.timeCreated)
15695
+ return 1;
15696
+ if (left.id < right.id)
15697
+ return -1;
15698
+ if (left.id > right.id)
15699
+ return 1;
15700
+ return 0;
15701
+ }
15702
+ function getOpenCodeMessageById(sessionId, messageId) {
15703
+ const db = getWritableOpenCodeDb();
15704
+ const row = db.prepare(`SELECT id FROM message WHERE session_id = ? AND id = ? LIMIT 1`).get(sessionId, messageId);
15705
+ return row ?? null;
15706
+ }
15707
+ function injectCompactionMarker(args) {
15708
+ const db = getWritableOpenCodeDb();
15709
+ if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
15710
+ return null;
15711
+ }
15712
+ const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
15713
+ if (!boundary) {
15714
+ log(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
15715
+ return null;
15716
+ }
15717
+ const boundaryTime = boundary.timeCreated;
15718
+ const summaryMsgId = generateMessageId(boundaryTime + 1, 1n);
15719
+ const compactionPartId = generatePartId(boundaryTime, 1n);
15720
+ const summaryPartId = generatePartId(boundaryTime + 1, 2n);
15721
+ const summaryMsgData = JSON.stringify({
15722
+ role: "assistant",
15723
+ parentID: boundary.id,
15724
+ summary: true,
15725
+ finish: "stop",
15726
+ mode: "compaction",
15727
+ agent: "compaction",
15728
+ path: { cwd: args.directory, root: args.directory },
15729
+ cost: 0,
15730
+ tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
15731
+ modelID: "magic-context",
15732
+ providerID: "magic-context",
15733
+ time: { created: boundaryTime + 1 }
15734
+ });
15735
+ try {
15736
+ db.transaction(() => {
15737
+ db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
15738
+ db.prepare("INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)").run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
15739
+ db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
15740
+ })();
15741
+ log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
15742
+ return {
15743
+ boundaryMessageId: boundary.id,
15744
+ summaryMessageId: summaryMsgId,
15745
+ compactionPartId,
15746
+ summaryPartId
15747
+ };
15748
+ } catch (error51) {
15749
+ log(`[magic-context] compaction-marker: injection failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
15750
+ return null;
15751
+ }
15752
+ }
15753
+ function removeCompactionMarker(state) {
15754
+ try {
15755
+ const db = getWritableOpenCodeDb();
15756
+ db.transaction(() => {
15757
+ db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
15758
+ db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
15759
+ db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
15760
+ })();
15761
+ return true;
15762
+ } catch (error51) {
15763
+ log(`[magic-context] compaction-marker: removal failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
15764
+ return false;
15765
+ }
15766
+ }
15767
+ var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", cachedWriteDb = null, REQUIRED_MESSAGE_COLUMNS, REQUIRED_PART_COLUMNS, cachedSchemaCompatible = null;
15768
+ var init_compaction_marker = __esm(async () => {
15769
+ init_data_path();
15770
+ init_logger();
15771
+ await init_sqlite();
15772
+ REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
15773
+ REQUIRED_PART_COLUMNS = [
15774
+ "id",
15775
+ "message_id",
15776
+ "session_id",
15777
+ "time_created",
15778
+ "time_updated",
15779
+ "data"
15780
+ ];
15781
+ });
15782
+
15449
15783
  // src/features/magic-context/memory/project-identity.ts
15450
15784
  import { execFileSync } from "node:child_process";
15451
15785
  import { createHash } from "node:crypto";
@@ -15625,6 +15959,80 @@ var init_project_identity = __esm(() => {
15625
15959
  };
15626
15960
  });
15627
15961
 
15962
+ // src/features/magic-context/session-project-storage.ts
15963
+ function getUpsertSessionProjectStatement(db) {
15964
+ let stmt = upsertSessionProjectStatements.get(db);
15965
+ if (!stmt) {
15966
+ stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
15967
+ VALUES (?, ?, ?, ?)
15968
+ ON CONFLICT(session_id, harness) DO UPDATE SET
15969
+ project_path = excluded.project_path,
15970
+ updated_at = excluded.updated_at
15971
+ WHERE session_projects.project_path <> excluded.project_path`);
15972
+ upsertSessionProjectStatements.set(db, stmt);
15973
+ }
15974
+ return stmt;
15975
+ }
15976
+ function getRepairSessionChunkProjectStatement(db) {
15977
+ let stmt = repairSessionChunkProjectStatements.get(db);
15978
+ if (!stmt) {
15979
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
15980
+ SET project_path = ?
15981
+ WHERE session_id = ?
15982
+ AND harness = ?
15983
+ AND project_path <> ?`);
15984
+ repairSessionChunkProjectStatements.set(db, stmt);
15985
+ }
15986
+ return stmt;
15987
+ }
15988
+ function getRepairProjectChunkProjectStatement(db) {
15989
+ let stmt = repairProjectChunkProjectStatements.get(db);
15990
+ if (!stmt) {
15991
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
15992
+ SET project_path = (
15993
+ SELECT sp.project_path
15994
+ FROM session_projects sp
15995
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
15996
+ AND sp.harness = compartment_chunk_embeddings.harness
15997
+ LIMIT 1
15998
+ )
15999
+ WHERE EXISTS (
16000
+ SELECT 1
16001
+ FROM session_projects sp
16002
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
16003
+ AND sp.harness = compartment_chunk_embeddings.harness
16004
+ AND sp.project_path <> compartment_chunk_embeddings.project_path
16005
+ AND (
16006
+ sp.project_path = ?
16007
+ OR compartment_chunk_embeddings.project_path = ?
16008
+ )
16009
+ )`);
16010
+ repairProjectChunkProjectStatements.set(db, stmt);
16011
+ }
16012
+ return stmt;
16013
+ }
16014
+ function recordSessionProjectIdentity(db, sessionId, projectPath) {
16015
+ if (!sessionId || !projectPath)
16016
+ return;
16017
+ const harness = getHarness();
16018
+ const now = Date.now();
16019
+ db.transaction(() => {
16020
+ getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
16021
+ getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
16022
+ })();
16023
+ }
16024
+ function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
16025
+ if (!projectPath)
16026
+ return 0;
16027
+ return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
16028
+ }
16029
+ var upsertSessionProjectStatements, repairSessionChunkProjectStatements, repairProjectChunkProjectStatements;
16030
+ var init_session_project_storage = __esm(() => {
16031
+ upsertSessionProjectStatements = new WeakMap;
16032
+ repairSessionChunkProjectStatements = new WeakMap;
16033
+ repairProjectChunkProjectStatements = new WeakMap;
16034
+ });
16035
+
15628
16036
  // src/features/magic-context/overflow-detection.ts
15629
16037
  function extractErrorMessage(error51) {
15630
16038
  if (!error51)
@@ -16735,78 +17143,14 @@ function removeSystemReminders(text) {
16735
17143
  }
16736
17144
  var SYSTEM_DIRECTIVE_PREFIX = "[SYSTEM DIRECTIVE: MAGIC-CONTEXT";
16737
17145
 
16738
- // src/shared/sqlite.ts
16739
- function buildNodeSqliteDatabaseClass(DatabaseSync) {
16740
- const SAVEPOINT = "mc_tx_sp";
16741
-
16742
- class NodeSqliteDatabase extends DatabaseSync {
16743
- constructor(filename, options) {
16744
- const translated = { ...options };
16745
- if (options && "readonly" in options) {
16746
- translated.readOnly = options.readonly;
16747
- delete translated.readonly;
16748
- }
16749
- super(typeof filename === "string" ? filename : ":memory:", translated);
16750
- }
16751
- prepare(sql) {
16752
- const stmt = super.prepare(sql);
16753
- for (const method of ["run", "get", "all"]) {
16754
- const original = stmt[method].bind(stmt);
16755
- stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
16756
- }
16757
- return stmt;
16758
- }
16759
- transaction(fn) {
16760
- const self2 = this;
16761
- const wrapped = function(...args) {
16762
- const nested = self2.isTransaction === true;
16763
- self2.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
16764
- try {
16765
- const result = fn.apply(this, args);
16766
- self2.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
16767
- return result;
16768
- } catch (error51) {
16769
- if (nested) {
16770
- self2.exec(`ROLLBACK TO ${SAVEPOINT}`);
16771
- self2.exec(`RELEASE ${SAVEPOINT}`);
16772
- } else {
16773
- self2.exec("ROLLBACK");
16774
- }
16775
- throw error51;
16776
- }
16777
- };
16778
- return wrapped;
16779
- }
16780
- }
16781
- return NodeSqliteDatabase;
16782
- }
16783
- var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
16784
- var init_sqlite = __esm(async () => {
16785
- isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
16786
- bunSpec = "bun:" + "sqlite";
16787
- nodeSpec = "node:" + "sqlite";
16788
- sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
16789
- DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
16790
- Database = DatabaseImpl;
16791
- });
16792
-
16793
- // src/shared/sqlite-helpers.ts
16794
- function closeQuietly(db) {
16795
- if (!db)
16796
- return;
16797
- try {
16798
- db.close();
16799
- } catch {}
16800
- }
16801
-
16802
17146
  // src/hooks/magic-context/read-session-db.ts
16803
- import { existsSync as existsSync6 } from "node:fs";
16804
- import { join as join3 } from "node:path";
16805
- function getOpenCodeDbPath() {
16806
- return join3(getDataDir(), "opencode", "opencode.db");
17147
+ import { existsSync as existsSync9 } from "node:fs";
17148
+ import { join as join4 } from "node:path";
17149
+ function getOpenCodeDbPath2() {
17150
+ return join4(getDataDir(), "opencode", "opencode.db");
16807
17151
  }
16808
17152
  function openCodeDbExists() {
16809
- return existsSync6(getOpenCodeDbPath());
17153
+ return existsSync9(getOpenCodeDbPath2());
16810
17154
  }
16811
17155
  function closeCachedReadOnlyDb() {
16812
17156
  if (!cachedReadOnlyDb) {
@@ -16821,7 +17165,7 @@ function closeCachedReadOnlyDb() {
16821
17165
  }
16822
17166
  }
16823
17167
  function getReadOnlySessionDb() {
16824
- const dbPath = getOpenCodeDbPath();
17168
+ const dbPath = getOpenCodeDbPath2();
16825
17169
  if (cachedReadOnlyDb?.path === dbPath) {
16826
17170
  return cachedReadOnlyDb.db;
16827
17171
  }
@@ -152555,82 +152899,6 @@ var init_project_docs_hash = __esm(() => {
152555
152899
  docsCache = new Map;
152556
152900
  });
152557
152901
 
152558
- // src/shared/error-message.ts
152559
- function getErrorMessage(error51) {
152560
- return error51 instanceof Error ? error51.message : String(error51);
152561
- }
152562
- function readString(value) {
152563
- if (typeof value === "string" && value.length > 0)
152564
- return value;
152565
- if (typeof value === "number")
152566
- return String(value);
152567
- return;
152568
- }
152569
- function clip(value, max) {
152570
- if (value.length <= max)
152571
- return value;
152572
- return `${value.slice(0, max)}…`;
152573
- }
152574
- function describeError(error51) {
152575
- const stringForm = clip(safeString(error51), 400);
152576
- if (!(error51 instanceof Error) && !(error51 && typeof error51 === "object")) {
152577
- return {
152578
- name: typeof error51,
152579
- message: "",
152580
- stringForm,
152581
- brief: stringForm || "<empty>"
152582
- };
152583
- }
152584
- const obj = error51;
152585
- const nameFromField = readString(obj.name);
152586
- const nameFromCtor = error51?.constructor?.name;
152587
- const name2 = nameFromField ?? nameFromCtor ?? "Error";
152588
- const message = readString(obj.message) ?? "";
152589
- const status = readString(obj.status) ?? readString(obj.statusCode);
152590
- const code = readString(obj.code);
152591
- let causeName;
152592
- const cause = obj.cause;
152593
- if (cause && typeof cause === "object") {
152594
- const causeRecord = cause;
152595
- causeName = readString(causeRecord.name) ?? cause.constructor?.name;
152596
- }
152597
- const stack = readString(obj.stack);
152598
- const stackHead = stack ? stack.split(`
152599
- `).slice(0, 4).map((l) => l.trim()).filter((l) => l.length > 0).join(" | ") : undefined;
152600
- const briefParts = [];
152601
- if (name2)
152602
- briefParts.push(name2);
152603
- if (message)
152604
- briefParts.push(`message="${clip(message, 200)}"`);
152605
- if (status)
152606
- briefParts.push(`status=${status}`);
152607
- if (code)
152608
- briefParts.push(`code=${code}`);
152609
- if (causeName)
152610
- briefParts.push(`cause=${causeName}`);
152611
- if (!message && stringForm && stringForm !== name2) {
152612
- briefParts.push(`str="${clip(stringForm, 200)}"`);
152613
- }
152614
- const brief = briefParts.join(" ") || stringForm || name2;
152615
- return {
152616
- name: name2,
152617
- message,
152618
- ...status ? { status } : {},
152619
- ...code ? { code } : {},
152620
- ...causeName ? { causeName } : {},
152621
- ...stackHead ? { stackHead } : {},
152622
- stringForm,
152623
- brief
152624
- };
152625
- }
152626
- function safeString(value) {
152627
- try {
152628
- return String(value);
152629
- } catch {
152630
- return "<unstringifiable>";
152631
- }
152632
- }
152633
-
152634
152902
  // src/shared/stable-json.ts
152635
152903
  function stableStringify(value, seen = new WeakSet) {
152636
152904
  if (value === undefined)
@@ -152742,12 +153010,12 @@ var init_tool_definition_tokens = __esm(() => {
152742
153010
  });
152743
153011
 
152744
153012
  // src/features/magic-context/tool-owner-backfill.ts
152745
- import { existsSync as existsSync7 } from "node:fs";
152746
- import { join as join4 } from "node:path";
153013
+ import { existsSync as existsSync10 } from "node:fs";
153014
+ import { join as join5 } from "node:path";
152747
153015
  function resolveOpencodeDbPath() {
152748
- return join4(getDataDir(), "opencode", "opencode.db");
153016
+ return join5(getDataDir(), "opencode", "opencode.db");
152749
153017
  }
152750
- function ensureBackfillStateTable(db) {
153018
+ function ensureBackfillStateTable2(db) {
152751
153019
  db.exec(`
152752
153020
  CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
152753
153021
  session_id TEXT PRIMARY KEY,
@@ -152763,7 +153031,7 @@ function ensureBackfillStateTable(db) {
152763
153031
  }
152764
153032
  function runToolOwnerBackfill(db) {
152765
153033
  const startedAt = performance.now();
152766
- ensureBackfillStateTable(db);
153034
+ ensureBackfillStateTable2(db);
152767
153035
  const result = {
152768
153036
  sessionsProcessed: 0,
152769
153037
  sessionsSkippedNoOcDb: 0,
@@ -152780,7 +153048,7 @@ function runToolOwnerBackfill(db) {
152780
153048
  return result;
152781
153049
  }
152782
153050
  const opencodeDbPath = resolveOpencodeDbPath();
152783
- if (!existsSync7(opencodeDbPath)) {
153051
+ if (!existsSync10(opencodeDbPath)) {
152784
153052
  log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
152785
153053
  markAllUnbackfilledSessionsSkipped(db);
152786
153054
  result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
@@ -152803,7 +153071,7 @@ function runToolOwnerBackfill(db) {
152803
153071
  return result;
152804
153072
  }
152805
153073
  function isToolOwnerBackfillNeeded(db) {
152806
- ensureBackfillStateTable(db);
153074
+ ensureBackfillStateTable2(db);
152807
153075
  const row = db.prepare(`SELECT 1 AS hit
152808
153076
  FROM tags
152809
153077
  WHERE type = 'tool' AND tool_owner_message_id IS NULL
@@ -153004,8 +153272,8 @@ var init_tool_owner_backfill = __esm(() => {
153004
153272
  });
153005
153273
 
153006
153274
  // src/features/magic-context/storage-db.ts
153007
- import { chmodSync, copyFileSync, cpSync, existsSync as existsSync8, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
153008
- import { dirname as dirname4, join as join5 } from "node:path";
153275
+ import { chmodSync, copyFileSync, cpSync, existsSync as existsSync11, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
153276
+ import { dirname as dirname4, join as join6 } from "node:path";
153009
153277
  function getSchemaFenceRejection() {
153010
153278
  return lastSchemaFenceRejection;
153011
153279
  }
@@ -153024,7 +153292,7 @@ function restrictDatabaseFilePermissions(dbPath) {
153024
153292
  return;
153025
153293
  for (const suffix of ["", "-wal", "-shm"]) {
153026
153294
  const file2 = `${dbPath}${suffix}`;
153027
- if (!existsSync8(file2))
153295
+ if (!existsSync11(file2))
153028
153296
  continue;
153029
153297
  try {
153030
153298
  chmodSync(file2, 384);
@@ -153039,22 +153307,22 @@ function resolveDatabasePath(dbPathOverride) {
153039
153307
  }
153040
153308
  const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
153041
153309
  if (testDataDir && !process.env.XDG_DATA_HOME) {
153042
- const dbDir2 = join5(testDataDir, "cortexkit", "magic-context");
153043
- return { dbDir: dbDir2, dbPath: join5(dbDir2, "context.db") };
153310
+ const dbDir2 = join6(testDataDir, "cortexkit", "magic-context");
153311
+ return { dbDir: dbDir2, dbPath: join6(dbDir2, "context.db") };
153044
153312
  }
153045
153313
  if (false) {}
153046
153314
  const dbDir = getMagicContextStorageDir();
153047
- return { dbDir, dbPath: join5(dbDir, "context.db") };
153315
+ return { dbDir, dbPath: join6(dbDir, "context.db") };
153048
153316
  }
153049
153317
  function getDatabasePath(db) {
153050
153318
  return pathByDatabase.get(db) ?? null;
153051
153319
  }
153052
153320
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
153053
- if (existsSync8(targetDbPath))
153321
+ if (existsSync11(targetDbPath))
153054
153322
  return;
153055
153323
  const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
153056
- const legacyDbPath = join5(legacyDir, "context.db");
153057
- if (!existsSync8(legacyDbPath))
153324
+ const legacyDbPath = join6(legacyDir, "context.db");
153325
+ if (!existsSync11(legacyDbPath))
153058
153326
  return;
153059
153327
  log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
153060
153328
  ensureSecureStorageDir(targetDbDir);
@@ -153070,8 +153338,8 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
153070
153338
  }
153071
153339
  for (const suffix of ["", "-wal", "-shm"]) {
153072
153340
  const src = `${legacyDbPath}${suffix}`;
153073
- const dst = join5(targetDbDir, `context.db${suffix}`);
153074
- if (existsSync8(src)) {
153341
+ const dst = join6(targetDbDir, `context.db${suffix}`);
153342
+ if (existsSync11(src)) {
153075
153343
  try {
153076
153344
  copyFileSync(src, dst);
153077
153345
  } catch (error51) {
@@ -153079,9 +153347,9 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
153079
153347
  }
153080
153348
  }
153081
153349
  }
153082
- const legacyModelsDir = join5(legacyDir, "models");
153083
- const targetModelsDir = join5(targetDbDir, "models");
153084
- if (existsSync8(legacyModelsDir) && !existsSync8(targetModelsDir)) {
153350
+ const legacyModelsDir = join6(legacyDir, "models");
153351
+ const targetModelsDir = join6(targetDbDir, "models");
153352
+ if (existsSync11(legacyModelsDir) && !existsSync11(targetModelsDir)) {
153085
153353
  try {
153086
153354
  cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
153087
153355
  } catch (error51) {
@@ -164181,10 +164449,10 @@ var require_stringify = __commonJS((exports, module) => {
164181
164449
  replacer = null;
164182
164450
  indent = EMPTY;
164183
164451
  };
164184
- var join6 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
164452
+ var join7 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
164185
164453
  var join_content = (inside, value, gap) => {
164186
164454
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
164187
- return join6(comment, inside, gap);
164455
+ return join7(comment, inside, gap);
164188
164456
  };
164189
164457
  var stringify_string = (holder, key, value) => {
164190
164458
  const raw = get_raw_string_literal(holder, key);
@@ -164206,13 +164474,13 @@ var require_stringify = __commonJS((exports, module) => {
164206
164474
  if (i !== 0) {
164207
164475
  inside += COMMA;
164208
164476
  }
164209
- const before = join6(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
164477
+ const before = join7(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
164210
164478
  inside += before || LF + deeper_gap;
164211
164479
  inside += stringify(i, value, deeper_gap) || STR_NULL;
164212
164480
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
164213
164481
  after_comma = process_comments(value, AFTER(i), deeper_gap);
164214
164482
  }
164215
- inside += join6(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164483
+ inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164216
164484
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
164217
164485
  };
164218
164486
  var object_stringify = (value, gap) => {
@@ -164233,13 +164501,13 @@ var require_stringify = __commonJS((exports, module) => {
164233
164501
  inside += COMMA;
164234
164502
  }
164235
164503
  first = false;
164236
- const before = join6(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
164504
+ const before = join7(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
164237
164505
  inside += before || LF + deeper_gap;
164238
164506
  inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
164239
164507
  after_comma = process_comments(value, AFTER(key), deeper_gap);
164240
164508
  };
164241
164509
  keys.forEach(iteratee);
164242
- inside += join6(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164510
+ inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164243
164511
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
164244
164512
  };
164245
164513
  function stringify(key, holder, gap) {
@@ -165239,16 +165507,16 @@ var init_compartment_prompt = () => {};
165239
165507
 
165240
165508
  // src/shared/opencode-config-dir.ts
165241
165509
  import { homedir as homedir6 } from "node:os";
165242
- import { join as join10, resolve as resolve3 } from "node:path";
165510
+ import { join as join11, resolve as resolve3 } from "node:path";
165243
165511
  function getCliConfigDir() {
165244
165512
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
165245
165513
  if (envConfigDir) {
165246
165514
  return resolve3(envConfigDir);
165247
165515
  }
165248
165516
  if (process.platform === "win32") {
165249
- return join10(homedir6(), ".config", "opencode");
165517
+ return join11(homedir6(), ".config", "opencode");
165250
165518
  }
165251
- return join10(process.env.XDG_CONFIG_HOME || join10(homedir6(), ".config"), "opencode");
165519
+ return join11(process.env.XDG_CONFIG_HOME || join11(homedir6(), ".config"), "opencode");
165252
165520
  }
165253
165521
  function getOpenCodeConfigDir(_options) {
165254
165522
  return getCliConfigDir();
@@ -165257,16 +165525,16 @@ function getOpenCodeConfigPaths(options) {
165257
165525
  const configDir = getOpenCodeConfigDir(options);
165258
165526
  return {
165259
165527
  configDir,
165260
- configJson: join10(configDir, "opencode.json"),
165261
- configJsonc: join10(configDir, "opencode.jsonc"),
165262
- packageJson: join10(configDir, "package.json"),
165263
- omoConfig: join10(configDir, "magic-context.jsonc")
165528
+ configJson: join11(configDir, "opencode.json"),
165529
+ configJsonc: join11(configDir, "opencode.jsonc"),
165530
+ packageJson: join11(configDir, "package.json"),
165531
+ omoConfig: join11(configDir, "magic-context.jsonc")
165264
165532
  };
165265
165533
  }
165266
165534
  var init_opencode_config_dir = () => {};
165267
165535
 
165268
165536
  // src/shared/conflict-detector.ts
165269
- import { join as join11 } from "node:path";
165537
+ import { join as join12 } from "node:path";
165270
165538
  function detectConflicts(directory) {
165271
165539
  const conflicts = {
165272
165540
  compactionAuto: false,
@@ -165323,8 +165591,8 @@ function checkCompaction(directory) {
165323
165591
  return { auto: true, prune: false };
165324
165592
  }
165325
165593
  function readProjectCompaction(directory) {
165326
- const dotOcJsonc = join11(directory, ".opencode", "opencode.jsonc");
165327
- const dotOcJson = join11(directory, ".opencode", "opencode.json");
165594
+ const dotOcJsonc = join12(directory, ".opencode", "opencode.jsonc");
165595
+ const dotOcJson = join12(directory, ".opencode", "opencode.json");
165328
165596
  const dotOcConfig = readJsoncFile(dotOcJsonc) ?? readJsoncFile(dotOcJson);
165329
165597
  if (dotOcConfig?.compaction) {
165330
165598
  const c = dotOcConfig.compaction;
@@ -165332,8 +165600,8 @@ function readProjectCompaction(directory) {
165332
165600
  return { auto: c.auto === true, prune: c.prune === true, resolved: true };
165333
165601
  }
165334
165602
  }
165335
- const rootJsonc = join11(directory, "opencode.jsonc");
165336
- const rootJson = join11(directory, "opencode.json");
165603
+ const rootJsonc = join12(directory, "opencode.jsonc");
165604
+ const rootJson = join12(directory, "opencode.json");
165337
165605
  const rootConfig = readJsoncFile(rootJsonc) ?? readJsoncFile(rootJson);
165338
165606
  if (rootConfig?.compaction) {
165339
165607
  const c = rootConfig.compaction;
@@ -165387,10 +165655,10 @@ function collectPluginEntries(directory) {
165387
165655
  }
165388
165656
  };
165389
165657
  for (const configPath of [
165390
- join11(directory, ".opencode", "opencode.jsonc"),
165391
- join11(directory, ".opencode", "opencode.json"),
165392
- join11(directory, "opencode.jsonc"),
165393
- join11(directory, "opencode.json")
165658
+ join12(directory, ".opencode", "opencode.jsonc"),
165659
+ join12(directory, ".opencode", "opencode.json"),
165660
+ join12(directory, "opencode.jsonc"),
165661
+ join12(directory, "opencode.json")
165394
165662
  ]) {
165395
165663
  const config2 = readJsoncFile(configPath);
165396
165664
  pushFrom(config2?.plugin);
@@ -165431,7 +165699,7 @@ function readOmoDisabledHooks(directory) {
165431
165699
  try {
165432
165700
  const paths = getOpenCodeConfigPaths({ binary: "opencode" });
165433
165701
  for (const name2 of configNames) {
165434
- const configPath = join11(paths.configDir, name2);
165702
+ const configPath = join12(paths.configDir, name2);
165435
165703
  const config2 = readJsoncFile(configPath);
165436
165704
  if (config2?.disabled_hooks) {
165437
165705
  for (const hook of config2.disabled_hooks) {
@@ -165441,7 +165709,7 @@ function readOmoDisabledHooks(directory) {
165441
165709
  }
165442
165710
  } catch {}
165443
165711
  for (const name2 of configNames) {
165444
- const config2 = readJsoncFile(join11(directory, name2));
165712
+ const config2 = readJsoncFile(join12(directory, name2));
165445
165713
  if (config2?.disabled_hooks) {
165446
165714
  for (const hook of config2.disabled_hooks) {
165447
165715
  disabled.add(hook);
@@ -165592,28 +165860,28 @@ __export(exports_conflict_warning_hook, {
165592
165860
  sendConflictWarning: () => sendConflictWarning,
165593
165861
  cleanupConflictWarnings: () => cleanupConflictWarnings
165594
165862
  });
165595
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
165863
+ import { existsSync as existsSync15, readFileSync as readFileSync10 } from "node:fs";
165596
165864
  import { homedir as homedir7, platform as platform2 } from "node:os";
165597
- import { join as join12 } from "node:path";
165865
+ import { join as join13 } from "node:path";
165598
165866
  function getDesktopStatePath() {
165599
165867
  const os2 = platform2();
165600
165868
  const home = homedir7();
165601
165869
  if (os2 === "darwin") {
165602
- return join12(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
165870
+ return join13(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
165603
165871
  }
165604
165872
  if (os2 === "linux") {
165605
- const xdgConfig = process.env.XDG_CONFIG_HOME || join12(home, ".config");
165606
- return join12(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
165873
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join13(home, ".config");
165874
+ return join13(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
165607
165875
  }
165608
165876
  if (os2 === "win32") {
165609
- const appData = process.env.APPDATA || join12(home, "AppData", "Roaming");
165610
- return join12(appData, "ai.opencode.desktop", "opencode.global.dat");
165877
+ const appData = process.env.APPDATA || join13(home, "AppData", "Roaming");
165878
+ return join13(appData, "ai.opencode.desktop", "opencode.global.dat");
165611
165879
  }
165612
165880
  return null;
165613
165881
  }
165614
165882
  function readDesktopState(directory) {
165615
165883
  const statePath = getDesktopStatePath();
165616
- if (!statePath || !existsSync12(statePath)) {
165884
+ if (!statePath || !existsSync15(statePath)) {
165617
165885
  log(`[magic-context] conflict-warning: Desktop state file not found at ${statePath}`);
165618
165886
  return { sessionId: null, sidecarUrl: null };
165619
165887
  }
@@ -165915,196 +166183,6 @@ var init_conflict_warning_hook = __esm(() => {
165915
166183
  cachedDesktopStateByDir = new Map;
165916
166184
  });
165917
166185
 
165918
- // src/features/magic-context/compaction-marker.ts
165919
- import { join as join13 } from "node:path";
165920
- function randomBase62(length) {
165921
- const chars = [];
165922
- for (let i = 0;i < length; i++) {
165923
- chars.push(BASE62_CHARS[Math.floor(Math.random() * BASE62_CHARS.length)]);
165924
- }
165925
- return chars.join("");
165926
- }
165927
- function generateId(prefix, timestampMs, counter = 0n) {
165928
- const encoded = BigInt(timestampMs) * 0x1000n + counter;
165929
- const hex3 = encoded.toString(16).padStart(14, "0");
165930
- return `${prefix}_${hex3}${randomBase62(14)}`;
165931
- }
165932
- function generateMessageId(timestampMs, counter = 0n) {
165933
- return generateId("msg", timestampMs, counter);
165934
- }
165935
- function generatePartId(timestampMs, counter = 0n) {
165936
- return generateId("prt", timestampMs, counter);
165937
- }
165938
- function getOpenCodeDbPath2() {
165939
- return join13(getDataDir(), "opencode", "opencode.db");
165940
- }
165941
- function isOpenCodeSchemaCompatible(db, dbPath) {
165942
- if (cachedSchemaCompatible?.path === dbPath) {
165943
- return cachedSchemaCompatible.compatible;
165944
- }
165945
- try {
165946
- const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
165947
- const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
165948
- const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
165949
- const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
165950
- if (missingMessage.length > 0 || missingPart.length > 0) {
165951
- log(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
165952
- cachedSchemaCompatible = { path: dbPath, compatible: false };
165953
- return false;
165954
- }
165955
- cachedSchemaCompatible = { path: dbPath, compatible: true };
165956
- return true;
165957
- } catch (error51) {
165958
- log(`[magic-context] compaction-marker: schema probe failed: ${error51 instanceof Error ? error51.message : String(error51)}. ` + `Marker injection disabled until next process restart.`);
165959
- cachedSchemaCompatible = { path: dbPath, compatible: false };
165960
- return false;
165961
- }
165962
- }
165963
- function getWritableOpenCodeDb() {
165964
- const dbPath = getOpenCodeDbPath2();
165965
- if (cachedWriteDb?.path === dbPath) {
165966
- return cachedWriteDb.db;
165967
- }
165968
- if (cachedWriteDb) {
165969
- try {
165970
- closeQuietly(cachedWriteDb.db);
165971
- } catch {}
165972
- }
165973
- const db = new Database(dbPath);
165974
- db.exec("PRAGMA busy_timeout=5000");
165975
- db.exec("PRAGMA journal_mode=WAL");
165976
- cachedWriteDb = { path: dbPath, db };
165977
- return db;
165978
- }
165979
- function getNonSummaryMessageSortKey(sessionId, messageId) {
165980
- const db = getWritableOpenCodeDb();
165981
- const row = db.prepare(`SELECT time_created, id
165982
- FROM message
165983
- WHERE session_id = ?
165984
- AND id = ?
165985
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
165986
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
165987
- LIMIT 1`).get(sessionId, messageId);
165988
- if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
165989
- return null;
165990
- }
165991
- return { id: row.id, timeCreated: row.time_created };
165992
- }
165993
- function findBoundaryUserMessage(sessionId, endMessageId) {
165994
- const db = getWritableOpenCodeDb();
165995
- const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
165996
- if (!target)
165997
- return null;
165998
- const boundary = db.prepare(`SELECT id, time_created, data
165999
- FROM message
166000
- WHERE session_id = ?
166001
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
166002
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
166003
- AND COALESCE(json_extract(data, '$.role'), '') = 'user'
166004
- AND (time_created < ? OR (time_created = ? AND id <= ?))
166005
- ORDER BY time_created DESC, id DESC
166006
- LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
166007
- if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
166008
- return null;
166009
- }
166010
- return { id: boundary.id, timeCreated: boundary.time_created };
166011
- }
166012
- function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
166013
- const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
166014
- const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
166015
- if (!left || !right)
166016
- return null;
166017
- if (left.timeCreated < right.timeCreated)
166018
- return -1;
166019
- if (left.timeCreated > right.timeCreated)
166020
- return 1;
166021
- if (left.id < right.id)
166022
- return -1;
166023
- if (left.id > right.id)
166024
- return 1;
166025
- return 0;
166026
- }
166027
- function getOpenCodeMessageById(sessionId, messageId) {
166028
- const db = getWritableOpenCodeDb();
166029
- const row = db.prepare(`SELECT id FROM message WHERE session_id = ? AND id = ? LIMIT 1`).get(sessionId, messageId);
166030
- return row ?? null;
166031
- }
166032
- function injectCompactionMarker(args) {
166033
- const db = getWritableOpenCodeDb();
166034
- if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath2())) {
166035
- return null;
166036
- }
166037
- const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
166038
- if (!boundary) {
166039
- log(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
166040
- return null;
166041
- }
166042
- const boundaryTime = boundary.timeCreated;
166043
- const summaryMsgId = generateMessageId(boundaryTime + 1, 1n);
166044
- const compactionPartId = generatePartId(boundaryTime, 1n);
166045
- const summaryPartId = generatePartId(boundaryTime + 1, 2n);
166046
- const summaryMsgData = JSON.stringify({
166047
- role: "assistant",
166048
- parentID: boundary.id,
166049
- summary: true,
166050
- finish: "stop",
166051
- mode: "compaction",
166052
- agent: "compaction",
166053
- path: { cwd: args.directory, root: args.directory },
166054
- cost: 0,
166055
- tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
166056
- modelID: "magic-context",
166057
- providerID: "magic-context",
166058
- time: { created: boundaryTime + 1 }
166059
- });
166060
- try {
166061
- db.transaction(() => {
166062
- db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
166063
- db.prepare("INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)").run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
166064
- db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
166065
- })();
166066
- log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
166067
- return {
166068
- boundaryMessageId: boundary.id,
166069
- summaryMessageId: summaryMsgId,
166070
- compactionPartId,
166071
- summaryPartId
166072
- };
166073
- } catch (error51) {
166074
- log(`[magic-context] compaction-marker: injection failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
166075
- return null;
166076
- }
166077
- }
166078
- function removeCompactionMarker(state) {
166079
- try {
166080
- const db = getWritableOpenCodeDb();
166081
- db.transaction(() => {
166082
- db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
166083
- db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
166084
- db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
166085
- })();
166086
- return true;
166087
- } catch (error51) {
166088
- log(`[magic-context] compaction-marker: removal failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
166089
- return false;
166090
- }
166091
- }
166092
- var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", cachedWriteDb = null, REQUIRED_MESSAGE_COLUMNS, REQUIRED_PART_COLUMNS, cachedSchemaCompatible = null;
166093
- var init_compaction_marker = __esm(async () => {
166094
- init_data_path();
166095
- init_logger();
166096
- await init_sqlite();
166097
- REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
166098
- REQUIRED_PART_COLUMNS = [
166099
- "id",
166100
- "message_id",
166101
- "session_id",
166102
- "time_created",
166103
- "time_updated",
166104
- "data"
166105
- ];
166106
- });
166107
-
166108
166186
  // src/features/magic-context/dreamer/task-config.ts
166109
166187
  var exports_task_config = {};
166110
166188
  __export(exports_task_config, {
@@ -168072,80 +168150,6 @@ var init_embedding_cache = __esm(() => {
168072
168150
  embeddingCacheTtlMs = DEFAULT_EMBEDDING_CACHE_TTL_MS;
168073
168151
  });
168074
168152
 
168075
- // src/features/magic-context/session-project-storage.ts
168076
- function getUpsertSessionProjectStatement(db) {
168077
- let stmt = upsertSessionProjectStatements.get(db);
168078
- if (!stmt) {
168079
- stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
168080
- VALUES (?, ?, ?, ?)
168081
- ON CONFLICT(session_id, harness) DO UPDATE SET
168082
- project_path = excluded.project_path,
168083
- updated_at = excluded.updated_at
168084
- WHERE session_projects.project_path <> excluded.project_path`);
168085
- upsertSessionProjectStatements.set(db, stmt);
168086
- }
168087
- return stmt;
168088
- }
168089
- function getRepairSessionChunkProjectStatement(db) {
168090
- let stmt = repairSessionChunkProjectStatements.get(db);
168091
- if (!stmt) {
168092
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
168093
- SET project_path = ?
168094
- WHERE session_id = ?
168095
- AND harness = ?
168096
- AND project_path <> ?`);
168097
- repairSessionChunkProjectStatements.set(db, stmt);
168098
- }
168099
- return stmt;
168100
- }
168101
- function getRepairProjectChunkProjectStatement(db) {
168102
- let stmt = repairProjectChunkProjectStatements.get(db);
168103
- if (!stmt) {
168104
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
168105
- SET project_path = (
168106
- SELECT sp.project_path
168107
- FROM session_projects sp
168108
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
168109
- AND sp.harness = compartment_chunk_embeddings.harness
168110
- LIMIT 1
168111
- )
168112
- WHERE EXISTS (
168113
- SELECT 1
168114
- FROM session_projects sp
168115
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
168116
- AND sp.harness = compartment_chunk_embeddings.harness
168117
- AND sp.project_path <> compartment_chunk_embeddings.project_path
168118
- AND (
168119
- sp.project_path = ?
168120
- OR compartment_chunk_embeddings.project_path = ?
168121
- )
168122
- )`);
168123
- repairProjectChunkProjectStatements.set(db, stmt);
168124
- }
168125
- return stmt;
168126
- }
168127
- function recordSessionProjectIdentity(db, sessionId, projectPath) {
168128
- if (!sessionId || !projectPath)
168129
- return;
168130
- const harness = getHarness();
168131
- const now = Date.now();
168132
- db.transaction(() => {
168133
- getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
168134
- getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
168135
- })();
168136
- }
168137
- function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
168138
- if (!projectPath)
168139
- return 0;
168140
- return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
168141
- }
168142
- var upsertSessionProjectStatements, repairSessionChunkProjectStatements, repairProjectChunkProjectStatements;
168143
- var init_session_project_storage = __esm(() => {
168144
- upsertSessionProjectStatements = new WeakMap;
168145
- repairSessionChunkProjectStatements = new WeakMap;
168146
- repairProjectChunkProjectStatements = new WeakMap;
168147
- });
168148
-
168149
168153
  // src/features/magic-context/project-embedding-registry.ts
168150
168154
  import { createHash as createHash8, randomUUID } from "node:crypto";
168151
168155
  function markProjectLoadUntrusted(projectIdentity) {
@@ -169782,7 +169786,7 @@ function getMemoryVerifications(db, memoryIds) {
169782
169786
  var MEMORY_VERIFICATION_SENTINEL = "";
169783
169787
  // src/features/magic-context/memory/verification-paths.ts
169784
169788
  import { execFile } from "node:child_process";
169785
- import { existsSync as existsSync14, realpathSync as realpathSync2, statSync as statSync5 } from "node:fs";
169789
+ import { existsSync as existsSync16, realpathSync as realpathSync2, statSync as statSync5 } from "node:fs";
169786
169790
  import path6 from "node:path";
169787
169791
  import { promisify } from "node:util";
169788
169792
  async function runGit(cwd, args) {
@@ -169885,7 +169889,7 @@ function verificationFileExists(baseRoot, filePath) {
169885
169889
  return false;
169886
169890
  const root = path6.resolve(baseRoot);
169887
169891
  const candidate = path6.resolve(root, filePath);
169888
- return isWithin(root, candidate) && existsSync14(candidate);
169892
+ return isWithin(root, candidate) && existsSync16(candidate);
169889
169893
  }
169890
169894
  async function normalizeVerificationFiles(args) {
169891
169895
  const cwd = path6.resolve(args.cwd);
@@ -169918,7 +169922,7 @@ async function normalizeVerificationFiles(args) {
169918
169922
  warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
169919
169923
  continue;
169920
169924
  }
169921
- if (existsSync14(candidate)) {
169925
+ if (existsSync16(candidate)) {
169922
169926
  try {
169923
169927
  if (statSync5(candidate).isDirectory()) {
169924
169928
  warnings.push(`Skipped verification path "${value}" because it is a directory.`);
@@ -169949,7 +169953,7 @@ async function normalizeVerificationFiles(args) {
169949
169953
  }
169950
169954
  normalized.push(tracked);
169951
169955
  } else {
169952
- if (!existsSync14(candidate)) {
169956
+ if (!existsSync16(candidate)) {
169953
169957
  warnings.push(`Skipped verification path "${value}" because it does not exist.`);
169954
169958
  continue;
169955
169959
  }
@@ -177293,6 +177297,9 @@ function applyDeferredCompactionMarker(db, sessionId, pending, directory) {
177293
177297
  }
177294
177298
  }
177295
177299
  function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
177300
+ if (getHarness() !== "opencode") {
177301
+ return true;
177302
+ }
177296
177303
  const targetEndMessageId = getCompartmentEndMessageIdForOrdinal(db, sessionId, lastCompartmentEnd);
177297
177304
  if (!targetEndMessageId) {
177298
177305
  sessionLog(sessionId, `compaction-marker: no compartment endMessageId for ordinal ${lastCompartmentEnd}; preserving existing marker`);
@@ -186349,6 +186356,29 @@ function getMagicContextBuiltinCommands() {
186349
186356
  };
186350
186357
  }
186351
186358
 
186359
+ // src/features/magic-context/dreamer/open-opencode-db.ts
186360
+ init_logger();
186361
+ await __promiseAll([
186362
+ init_sqlite(),
186363
+ init_compaction_marker()
186364
+ ]);
186365
+ import { existsSync as existsSync7 } from "node:fs";
186366
+ function openOpenCodeDb() {
186367
+ const dbPath = getOpenCodeDbPath();
186368
+ if (!existsSync7(dbPath)) {
186369
+ log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
186370
+ return null;
186371
+ }
186372
+ try {
186373
+ const db = new Database(dbPath, { readonly: true });
186374
+ db.exec("PRAGMA busy_timeout = 5000");
186375
+ return db;
186376
+ } catch (error51) {
186377
+ log(`[dreamer] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error51)}`);
186378
+ return null;
186379
+ }
186380
+ }
186381
+
186352
186382
  // src/features/magic-context/dreamer/task-prompts.ts
186353
186383
  var DREAMER_SYSTEM_PROMPT = `You are a background maintenance agent for the magic-context system, running during a scheduled dream window. Your task and its full instructions arrive in the message below. Never read or quote secrets from .env, credentials, or key files, and never commit — the user handles git.`;
186354
186384
  var PROJECT_MEMORY_TAXONOMY = `## Memory taxonomy (5 categories)
@@ -186658,6 +186688,192 @@ function buildDreamTaskPrompt(task, args) {
186658
186688
  // src/index.ts
186659
186689
  init_project_identity();
186660
186690
 
186691
+ // src/features/magic-context/session-project-backfill.ts
186692
+ init_logger();
186693
+ init_project_identity();
186694
+ init_session_project_storage();
186695
+ import { existsSync as existsSync8 } from "node:fs";
186696
+ var LEASE_TTL_MS = 10 * 60 * 1000;
186697
+ var SESSION_QUERY_CHUNK_SIZE = 250;
186698
+ var YIELD_EVERY_NEW_DIRECTORIES = 10;
186699
+ function ensureBackfillStateTable(db) {
186700
+ db.exec(`
186701
+ CREATE TABLE IF NOT EXISTS session_project_backfill_state (
186702
+ harness TEXT PRIMARY KEY,
186703
+ status TEXT NOT NULL CHECK (status IN ('running', 'completed')),
186704
+ started_at INTEGER,
186705
+ lease_expires_at INTEGER,
186706
+ completed_at INTEGER
186707
+ );
186708
+ `);
186709
+ }
186710
+ function withImmediateTransaction(db, fn) {
186711
+ db.exec("BEGIN IMMEDIATE");
186712
+ try {
186713
+ const result = fn();
186714
+ db.exec("COMMIT");
186715
+ return result;
186716
+ } catch (error51) {
186717
+ try {
186718
+ db.exec("ROLLBACK");
186719
+ } catch {}
186720
+ throw error51;
186721
+ }
186722
+ }
186723
+ function defaultYieldFn() {
186724
+ return new Promise((resolve2) => setTimeout(resolve2, 0));
186725
+ }
186726
+ function acquireBackfillLease(db, harness, now) {
186727
+ ensureBackfillStateTable(db);
186728
+ return withImmediateTransaction(db, () => {
186729
+ const current = db.prepare(`SELECT harness, status, started_at, lease_expires_at, completed_at
186730
+ FROM session_project_backfill_state
186731
+ WHERE harness = ?`).get(harness);
186732
+ if (current?.status === "completed") {
186733
+ return "already_completed";
186734
+ }
186735
+ if (current?.status === "running" && current.lease_expires_at !== null && current.lease_expires_at > now) {
186736
+ return "blocked_by_lease";
186737
+ }
186738
+ db.prepare(`INSERT INTO session_project_backfill_state(
186739
+ harness,
186740
+ status,
186741
+ started_at,
186742
+ lease_expires_at,
186743
+ completed_at
186744
+ )
186745
+ VALUES (?, 'running', ?, ?, NULL)
186746
+ ON CONFLICT(harness) DO UPDATE SET
186747
+ status = 'running',
186748
+ started_at = excluded.started_at,
186749
+ lease_expires_at = excluded.lease_expires_at,
186750
+ completed_at = NULL`).run(harness, now, now + LEASE_TTL_MS);
186751
+ return "completed";
186752
+ });
186753
+ }
186754
+ function renewBackfillLease(db, harness, now) {
186755
+ ensureBackfillStateTable(db);
186756
+ db.prepare(`UPDATE session_project_backfill_state
186757
+ SET lease_expires_at = ?
186758
+ WHERE harness = ? AND status = 'running'`).run(now + LEASE_TTL_MS, harness);
186759
+ }
186760
+ function markBackfillCompleted(db, harness, now) {
186761
+ ensureBackfillStateTable(db);
186762
+ db.prepare(`INSERT INTO session_project_backfill_state(
186763
+ harness,
186764
+ status,
186765
+ started_at,
186766
+ lease_expires_at,
186767
+ completed_at
186768
+ )
186769
+ VALUES (?, 'completed', ?, NULL, ?)
186770
+ ON CONFLICT(harness) DO UPDATE SET
186771
+ status = 'completed',
186772
+ lease_expires_at = NULL,
186773
+ completed_at = excluded.completed_at`).run(harness, now, now);
186774
+ }
186775
+ function dedupeSessions(sessions) {
186776
+ const sessionsById = new Map;
186777
+ for (const session of sessions) {
186778
+ if (!session.sessionId)
186779
+ continue;
186780
+ const existing = sessionsById.get(session.sessionId);
186781
+ if (!existing) {
186782
+ sessionsById.set(session.sessionId, {
186783
+ sessionId: session.sessionId,
186784
+ directory: session.directory
186785
+ });
186786
+ continue;
186787
+ }
186788
+ if (!existing.directory && session.directory) {
186789
+ sessionsById.set(session.sessionId, {
186790
+ sessionId: session.sessionId,
186791
+ directory: session.directory
186792
+ });
186793
+ }
186794
+ }
186795
+ return [...sessionsById.values()];
186796
+ }
186797
+ function getMappedSessionIds(db, harness, sessions) {
186798
+ const mapped = new Set;
186799
+ for (let index = 0;index < sessions.length; index += SESSION_QUERY_CHUNK_SIZE) {
186800
+ const chunk = sessions.slice(index, index + SESSION_QUERY_CHUNK_SIZE);
186801
+ if (chunk.length === 0)
186802
+ continue;
186803
+ const placeholders = chunk.map(() => "?").join(", ");
186804
+ const rows = db.prepare(`SELECT session_id
186805
+ FROM session_projects
186806
+ WHERE harness = ?
186807
+ AND session_id IN (${placeholders})`).all(harness, ...chunk.map((session) => session.sessionId));
186808
+ for (const row of rows) {
186809
+ mapped.add(row.session_id);
186810
+ }
186811
+ }
186812
+ return mapped;
186813
+ }
186814
+ async function runSessionProjectBackfill(db, sessions, options = {}) {
186815
+ const startedAt = performance.now();
186816
+ const harness = getHarness();
186817
+ const now = options.now ?? Date.now;
186818
+ const resolveIdentity = options.resolveIdentity ?? resolveProjectIdentity;
186819
+ const yieldFn = options.yieldFn ?? defaultYieldFn;
186820
+ const dedupedSessions = dedupeSessions(sessions);
186821
+ const result = {
186822
+ status: "completed",
186823
+ totalSessions: dedupedSessions.length,
186824
+ alreadyMappedSessions: 0,
186825
+ unmappedSessions: 0,
186826
+ backfilledSessions: 0,
186827
+ skippedDeadDirectories: 0,
186828
+ skippedEmptyDirectories: 0,
186829
+ durationMs: 0
186830
+ };
186831
+ const leaseStatus = acquireBackfillLease(db, harness, now());
186832
+ if (leaseStatus !== "completed") {
186833
+ result.status = leaseStatus;
186834
+ result.durationMs = performance.now() - startedAt;
186835
+ return result;
186836
+ }
186837
+ const mappedSessionIds = getMappedSessionIds(db, harness, dedupedSessions);
186838
+ result.alreadyMappedSessions = mappedSessionIds.size;
186839
+ const existenceCache = new Map;
186840
+ const identityCache2 = new Map;
186841
+ let newDirectoryResolutions = 0;
186842
+ for (const session of dedupedSessions) {
186843
+ if (mappedSessionIds.has(session.sessionId)) {
186844
+ continue;
186845
+ }
186846
+ result.unmappedSessions += 1;
186847
+ if (!session.directory) {
186848
+ result.skippedEmptyDirectories += 1;
186849
+ continue;
186850
+ }
186851
+ const stillExists = existenceCache.get(session.directory) ?? existsSync8(session.directory);
186852
+ existenceCache.set(session.directory, stillExists);
186853
+ if (!stillExists) {
186854
+ result.skippedDeadDirectories += 1;
186855
+ continue;
186856
+ }
186857
+ let identity = identityCache2.get(session.directory);
186858
+ if (!identity) {
186859
+ identity = resolveIdentity(session.directory);
186860
+ identityCache2.set(session.directory, identity);
186861
+ newDirectoryResolutions += 1;
186862
+ if (newDirectoryResolutions % YIELD_EVERY_NEW_DIRECTORIES === 0) {
186863
+ renewBackfillLease(db, harness, now());
186864
+ await yieldFn();
186865
+ renewBackfillLease(db, harness, now());
186866
+ }
186867
+ }
186868
+ recordSessionProjectIdentity(db, session.sessionId, identity);
186869
+ result.backfilledSessions += 1;
186870
+ }
186871
+ markBackfillCompleted(db, harness, now());
186872
+ result.durationMs = performance.now() - startedAt;
186873
+ log(`[session-projects] backfilled ${result.backfilledSessions} of ${result.unmappedSessions} unmapped sessions (skipped ${result.skippedDeadDirectories} dead dirs) in ${Math.round(result.durationMs)}ms`);
186874
+ return result;
186875
+ }
186876
+
186661
186877
  // src/features/magic-context/sidekick/agent.ts
186662
186878
  init_language_directive();
186663
186879
 
@@ -187048,45 +187264,45 @@ async function runDeferredV22Backfill(db, options = {}) {
187048
187264
 
187049
187265
  // src/hooks/auto-update-checker/index.ts
187050
187266
  init_logger();
187051
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync9, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
187052
- import { dirname as dirname7, join as join9 } from "node:path";
187267
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync9, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
187268
+ import { dirname as dirname7, join as join10 } from "node:path";
187053
187269
 
187054
187270
  // src/hooks/auto-update-checker/cache.ts
187055
187271
  init_logger();
187056
187272
  var import_comment_json2 = __toESM(require_src2(), 1);
187057
187273
  import { spawn } from "node:child_process";
187058
- import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
187059
- import { basename as basename2, dirname as dirname6, join as join8 } from "node:path";
187274
+ import { existsSync as existsSync13, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
187275
+ import { basename as basename2, dirname as dirname6, join as join9 } from "node:path";
187060
187276
 
187061
187277
  // src/hooks/auto-update-checker/checker.ts
187062
187278
  init_logger();
187063
187279
  var import_comment_json = __toESM(require_src2(), 1);
187064
- import { existsSync as existsSync9, readFileSync as readFileSync7, renameSync as renameSync2, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
187280
+ import { existsSync as existsSync12, readFileSync as readFileSync7, renameSync as renameSync2, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
187065
187281
  import { homedir as homedir5 } from "node:os";
187066
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join7, resolve as resolve2 } from "node:path";
187282
+ import { dirname as dirname5, isAbsolute as isAbsolute3, join as join8, resolve as resolve2 } from "node:path";
187067
187283
  import { fileURLToPath } from "node:url";
187068
187284
 
187069
187285
  // src/hooks/auto-update-checker/constants.ts
187070
187286
  import { homedir as homedir4, platform } from "node:os";
187071
- import { join as join6 } from "node:path";
187287
+ import { join as join7 } from "node:path";
187072
187288
  var PACKAGE_NAME = "@cortexkit/opencode-magic-context";
187073
187289
  var NPM_REGISTRY_URL = "https://registry.npmjs.org";
187074
187290
  var NPM_FETCH_TIMEOUT = 1e4;
187075
187291
  function getOpenCodeCacheRoot() {
187076
187292
  if (platform() === "win32") {
187077
- return join6(process.env.LOCALAPPDATA ?? homedir4(), "opencode");
187293
+ return join7(process.env.LOCALAPPDATA ?? homedir4(), "opencode");
187078
187294
  }
187079
- return join6(homedir4(), ".cache", "opencode");
187295
+ return join7(homedir4(), ".cache", "opencode");
187080
187296
  }
187081
187297
  function getOpenCodeConfigRoot() {
187082
187298
  if (platform() === "win32") {
187083
- return join6(process.env.APPDATA ?? join6(homedir4(), "AppData", "Roaming"), "opencode");
187299
+ return join7(process.env.APPDATA ?? join7(homedir4(), "AppData", "Roaming"), "opencode");
187084
187300
  }
187085
- return join6(process.env.XDG_CONFIG_HOME ?? join6(homedir4(), ".config"), "opencode");
187301
+ return join7(process.env.XDG_CONFIG_HOME ?? join7(homedir4(), ".config"), "opencode");
187086
187302
  }
187087
- var CACHE_DIR = join6(getOpenCodeCacheRoot(), "packages");
187088
- var USER_OPENCODE_CONFIG = join6(getOpenCodeConfigRoot(), "opencode.json");
187089
- var USER_OPENCODE_CONFIG_JSONC = join6(getOpenCodeConfigRoot(), "opencode.jsonc");
187303
+ var CACHE_DIR = join7(getOpenCodeCacheRoot(), "packages");
187304
+ var USER_OPENCODE_CONFIG = join7(getOpenCodeConfigRoot(), "opencode.json");
187305
+ var USER_OPENCODE_CONFIG_JSONC = join7(getOpenCodeConfigRoot(), "opencode.jsonc");
187090
187306
  // src/hooks/auto-update-checker/types.ts
187091
187307
  init_zod();
187092
187308
  var NpmPackageEnvelopeSchema = exports_external.object({
@@ -187147,8 +187363,8 @@ function extractChannel(version2) {
187147
187363
  }
187148
187364
  function getConfigPaths(directory) {
187149
187365
  return [
187150
- join7(directory, ".opencode", "opencode.json"),
187151
- join7(directory, ".opencode", "opencode.jsonc"),
187366
+ join8(directory, ".opencode", "opencode.json"),
187367
+ join8(directory, ".opencode", "opencode.jsonc"),
187152
187368
  USER_OPENCODE_CONFIG,
187153
187369
  USER_OPENCODE_CONFIG_JSONC
187154
187370
  ];
@@ -187170,8 +187386,8 @@ function findPackageJsonUp(startPath) {
187170
187386
  const stat = statSync4(startPath);
187171
187387
  let dir = stat.isDirectory() ? startPath : dirname5(startPath);
187172
187388
  for (let i = 0;i < 10; i++) {
187173
- const pkgPath = join7(dir, "package.json");
187174
- if (existsSync9(pkgPath)) {
187389
+ const pkgPath = join8(dir, "package.json");
187390
+ if (existsSync12(pkgPath)) {
187175
187391
  try {
187176
187392
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync7(pkgPath, "utf-8")));
187177
187393
  if (pkg.success && pkg.data.name === PACKAGE_NAME)
@@ -187189,7 +187405,7 @@ function findPackageJsonUp(startPath) {
187189
187405
  function getLocalDevPath(directory) {
187190
187406
  for (const configPath of getConfigPaths(directory)) {
187191
187407
  try {
187192
- if (!existsSync9(configPath))
187408
+ if (!existsSync12(configPath))
187193
187409
  continue;
187194
187410
  const rawConfig = parseJsonConfig(readFileSync7(configPath, "utf-8"));
187195
187411
  const plugins = getPluginEntries(rawConfig);
@@ -187235,7 +187451,7 @@ function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
187235
187451
  function findPluginEntry(directory) {
187236
187452
  for (const configPath of getConfigPaths(directory)) {
187237
187453
  try {
187238
- if (!existsSync9(configPath))
187454
+ if (!existsSync12(configPath))
187239
187455
  continue;
187240
187456
  const rawConfig = parseJsonConfig(readFileSync7(configPath, "utf-8"));
187241
187457
  const plugins = getPluginEntries(rawConfig);
@@ -187260,7 +187476,7 @@ function findPluginEntry(directory) {
187260
187476
  }
187261
187477
  var cachedPackageVersion = null;
187262
187478
  function getSpecCachePackageJsonPath(spec) {
187263
- return join7(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
187479
+ return join8(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
187264
187480
  }
187265
187481
  function getCachedVersion(spec) {
187266
187482
  if (!spec && cachedPackageVersion)
@@ -187269,11 +187485,11 @@ function getCachedVersion(spec) {
187269
187485
  getCurrentRuntimePackageJsonPath(),
187270
187486
  spec ? getSpecCachePackageJsonPath(spec) : null,
187271
187487
  getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
187272
- join7(homedir5(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
187488
+ join8(homedir5(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
187273
187489
  ].filter(isString);
187274
187490
  for (const packageJsonPath of candidates) {
187275
187491
  try {
187276
- if (!existsSync9(packageJsonPath))
187492
+ if (!existsSync12(packageJsonPath))
187277
187493
  continue;
187278
187494
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync7(packageJsonPath, "utf-8")));
187279
187495
  if (pkg.success && pkg.data.version) {
@@ -187327,8 +187543,8 @@ function stripPackageNameFromPath(pathValue, packageName) {
187327
187543
  return current;
187328
187544
  }
187329
187545
  function removeFromPackageLock(installDir, packageName) {
187330
- const lockPath = join8(installDir, "package-lock.json");
187331
- if (!existsSync10(lockPath))
187546
+ const lockPath = join9(installDir, "package-lock.json");
187547
+ if (!existsSync13(lockPath))
187332
187548
  return false;
187333
187549
  try {
187334
187550
  const lock = import_comment_json2.parse(readFileSync8(lockPath, "utf-8"));
@@ -187354,7 +187570,7 @@ function removeFromPackageLock(installDir, packageName) {
187354
187570
  }
187355
187571
  }
187356
187572
  function ensureDependencyVersion(packageJsonPath, packageName, version2) {
187357
- if (!existsSync10(packageJsonPath))
187573
+ if (!existsSync13(packageJsonPath))
187358
187574
  return false;
187359
187575
  try {
187360
187576
  const raw = import_comment_json2.parse(readFileSync8(packageJsonPath, "utf-8"));
@@ -187376,8 +187592,8 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
187376
187592
  }
187377
187593
  }
187378
187594
  function removeInstalledPackage(installDir, packageName) {
187379
- const packageDir = join8(installDir, "node_modules", packageName);
187380
- if (!existsSync10(packageDir))
187595
+ const packageDir = join9(installDir, "node_modules", packageName);
187596
+ if (!existsSync13(packageDir))
187381
187597
  return false;
187382
187598
  try {
187383
187599
  rmSync2(packageDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
@@ -187398,8 +187614,8 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
187398
187614
  const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
187399
187615
  if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
187400
187616
  const installDir = dirname6(nodeModulesDir);
187401
- const packageJsonPath = join8(installDir, "package.json");
187402
- if (!existsSync10(packageJsonPath)) {
187617
+ const packageJsonPath = join9(installDir, "package.json");
187618
+ if (!existsSync13(packageJsonPath)) {
187403
187619
  try {
187404
187620
  writeFileSync4(packageJsonPath, `${JSON.stringify({ private: true, dependencies: {} }, null, 2)}
187405
187621
  `);
@@ -187413,8 +187629,8 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
187413
187629
  }
187414
187630
  return null;
187415
187631
  }
187416
- const legacyPackageJsonPath = join8(dirname6(CACHE_DIR), "package.json");
187417
- if (existsSync10(legacyPackageJsonPath)) {
187632
+ const legacyPackageJsonPath = join9(dirname6(CACHE_DIR), "package.json");
187633
+ if (existsSync13(legacyPackageJsonPath)) {
187418
187634
  return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
187419
187635
  }
187420
187636
  return null;
@@ -187538,8 +187754,8 @@ function claimCheckSlot(storageDir, intervalMs) {
187538
187754
  if (!storageDir)
187539
187755
  return true;
187540
187756
  try {
187541
- const file2 = join9(storageDir, TIMESTAMP_FILENAME);
187542
- if (existsSync11(file2)) {
187757
+ const file2 = join10(storageDir, TIMESTAMP_FILENAME);
187758
+ if (existsSync14(file2)) {
187543
187759
  try {
187544
187760
  const raw = JSON.parse(readFileSync9(file2, "utf-8"));
187545
187761
  const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
@@ -187845,29 +188061,6 @@ function releaseLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
187845
188061
  });
187846
188062
  }
187847
188063
 
187848
- // src/features/magic-context/dreamer/open-opencode-db.ts
187849
- init_logger();
187850
- await __promiseAll([
187851
- init_sqlite(),
187852
- init_compaction_marker()
187853
- ]);
187854
- import { existsSync as existsSync13 } from "node:fs";
187855
- function openOpenCodeDb() {
187856
- const dbPath = getOpenCodeDbPath2();
187857
- if (!existsSync13(dbPath)) {
187858
- log(`[key-files] OpenCode DB not found at ${dbPath} — skipping`);
187859
- return null;
187860
- }
187861
- try {
187862
- const db = new Database(dbPath, { readonly: true });
187863
- db.exec("PRAGMA busy_timeout = 5000");
187864
- return db;
187865
- } catch (error51) {
187866
- log(`[key-files] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error51)}`);
187867
- return null;
187868
- }
187869
- }
187870
-
187871
188064
  // src/features/magic-context/dreamer/retrospective-orphan-sweep.ts
187872
188065
  init_logger();
187873
188066
  var RETROSPECTIVE_CHILD_TITLE = "magic-context-dream-retrospective";
@@ -188290,7 +188483,7 @@ init_task_config();
188290
188483
 
188291
188484
  // src/features/magic-context/dreamer/task-executor.ts
188292
188485
  import { createHash as createHash10 } from "node:crypto";
188293
- import { existsSync as existsSync17 } from "node:fs";
188486
+ import { existsSync as existsSync19 } from "node:fs";
188294
188487
 
188295
188488
  // src/agents/dreamer.ts
188296
188489
  var DREAMER_AGENT = "dreamer";
@@ -190377,7 +190570,7 @@ Output exactly JSON: {"met": false}`;
190377
190570
 
190378
190571
  // src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
190379
190572
  init_logger();
190380
- import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
190573
+ import { existsSync as existsSync17, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
190381
190574
  import { join as join15 } from "node:path";
190382
190575
 
190383
190576
  // src/features/magic-context/dreamer/protected-regions.ts
@@ -190481,7 +190674,7 @@ function snapshotMaintainDocsFiles(docsDir) {
190481
190674
  for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
190482
190675
  const path8 = join15(docsDir, name2);
190483
190676
  try {
190484
- if (existsSync15(path8)) {
190677
+ if (existsSync17(path8)) {
190485
190678
  snapshot.set(name2, readFileSync11(path8, "utf8"));
190486
190679
  }
190487
190680
  } catch {}
@@ -190513,7 +190706,7 @@ init_memory();
190513
190706
  init_subagent_token_capture();
190514
190707
 
190515
190708
  // src/features/magic-context/dreamer/map-memories-prompt.ts
190516
- import { existsSync as existsSync16, statSync as statSync6 } from "node:fs";
190709
+ import { existsSync as existsSync18, statSync as statSync6 } from "node:fs";
190517
190710
  import path8 from "node:path";
190518
190711
  var MAP_MEMORIES_SYSTEM_PROMPT = `You are a memory mapper for the magic-context system. You map project memories to the repository files that back them.
190519
190712
 
@@ -190551,7 +190744,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
190551
190744
  if (!abs.startsWith(`${root}/`))
190552
190745
  continue;
190553
190746
  try {
190554
- if (existsSync16(abs) && statSync6(abs).isFile())
190747
+ if (existsSync18(abs) && statSync6(abs).isFile())
190555
190748
  found.add(rel);
190556
190749
  } catch {}
190557
190750
  if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
@@ -192380,8 +192573,8 @@ async function runAgenticTask(config2, ctx, helpers) {
192380
192573
  const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
192381
192574
  const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
192382
192575
  const existingDocs = task === "maintain-docs" ? {
192383
- architecture: existsSync17(`${docsDir}/ARCHITECTURE.md`),
192384
- structure: existsSync17(`${docsDir}/STRUCTURE.md`)
192576
+ architecture: existsSync19(`${docsDir}/ARCHITECTURE.md`),
192577
+ structure: existsSync19(`${docsDir}/STRUCTURE.md`)
192385
192578
  } : undefined;
192386
192579
  const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
192387
192580
  let curateMemories;
@@ -204973,6 +205166,31 @@ var server = async (ctx) => {
204973
205166
  log(`[v22-backfill] failed to start background runner: ${err}`);
204974
205167
  }
204975
205168
  }
205169
+ if (pluginConfig.enabled && hooks.magicContext) {
205170
+ setTimeout(() => {
205171
+ try {
205172
+ const db = openDatabase();
205173
+ if (!db || !isDatabasePersisted(db))
205174
+ return;
205175
+ const ocDb = openOpenCodeDb();
205176
+ if (!ocDb)
205177
+ return;
205178
+ try {
205179
+ const sessions = ocDb.prepare("SELECT id, COALESCE(directory, '') AS directory FROM session ORDER BY id ASC").all();
205180
+ runSessionProjectBackfill(db, sessions.map((session) => ({
205181
+ sessionId: session.id,
205182
+ directory: session.directory
205183
+ }))).catch((err) => {
205184
+ log(`[session-projects] background runner failed: ${err}`);
205185
+ });
205186
+ } finally {
205187
+ closeQuietly(ocDb);
205188
+ }
205189
+ } catch (err) {
205190
+ log(`[session-projects] failed to start background runner: ${err}`);
205191
+ }
205192
+ }, 0);
205193
+ }
204976
205194
  const storageDir = getMagicContextStorageDir();
204977
205195
  let rpcServer = null;
204978
205196
  let stopDreamTimerRegistration;