@cortexkit/magic-context 0.44.1 → 0.44.3
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 +1288 -464
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1647,6 +1647,7 @@ var init_prompts = __esm(() => {
|
|
|
1647
1647
|
});
|
|
1648
1648
|
|
|
1649
1649
|
// ../plugin/src/shared/sqlite.ts
|
|
1650
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
1650
1651
|
function registerSlowWriteReporter(reporter) {
|
|
1651
1652
|
reportSlowPrivilegedWrite = reporter;
|
|
1652
1653
|
}
|
|
@@ -1680,6 +1681,65 @@ async function loadSqliteModule(runtime = detectSqliteRuntime(), importer = impo
|
|
|
1680
1681
|
throw error;
|
|
1681
1682
|
}
|
|
1682
1683
|
}
|
|
1684
|
+
function installTransactionRouting(db, readonly) {
|
|
1685
|
+
const nativeExec = db.exec.bind(db);
|
|
1686
|
+
Object.defineProperty(db, "exec", {
|
|
1687
|
+
configurable: true,
|
|
1688
|
+
writable: true,
|
|
1689
|
+
value: (sql) => {
|
|
1690
|
+
if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
|
|
1691
|
+
if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore())
|
|
1692
|
+
acquireShort(db, () => nativeExec(sql), sql.trim());
|
|
1693
|
+
else
|
|
1694
|
+
nativeExec(sql);
|
|
1695
|
+
return db;
|
|
1696
|
+
}
|
|
1697
|
+
return nativeExec(sql);
|
|
1698
|
+
}
|
|
1699
|
+
});
|
|
1700
|
+
Object.defineProperty(db, "transaction", {
|
|
1701
|
+
configurable: true,
|
|
1702
|
+
writable: true,
|
|
1703
|
+
value: (fn) => {
|
|
1704
|
+
const make = (mode) => function(...args) {
|
|
1705
|
+
const nested = isInTransaction(db);
|
|
1706
|
+
const savepoint = "mc_tx_sp";
|
|
1707
|
+
db.exec(nested ? `SAVEPOINT ${savepoint}` : `BEGIN ${mode}`);
|
|
1708
|
+
try {
|
|
1709
|
+
const result = fn.apply(this, args);
|
|
1710
|
+
db.exec(nested ? `RELEASE ${savepoint}` : "COMMIT");
|
|
1711
|
+
return result;
|
|
1712
|
+
} catch (error) {
|
|
1713
|
+
if (isInTransaction(db)) {
|
|
1714
|
+
if (nested) {
|
|
1715
|
+
db.exec(`ROLLBACK TO ${savepoint}`);
|
|
1716
|
+
db.exec(`RELEASE ${savepoint}`);
|
|
1717
|
+
} else
|
|
1718
|
+
db.exec("ROLLBACK");
|
|
1719
|
+
}
|
|
1720
|
+
throw error;
|
|
1721
|
+
}
|
|
1722
|
+
};
|
|
1723
|
+
const defaultTransaction = make(readonly ? "DEFERRED" : "IMMEDIATE");
|
|
1724
|
+
const variants = {
|
|
1725
|
+
default: defaultTransaction,
|
|
1726
|
+
deferred: make("DEFERRED"),
|
|
1727
|
+
immediate: make("IMMEDIATE"),
|
|
1728
|
+
exclusive: make("EXCLUSIVE"),
|
|
1729
|
+
database: db
|
|
1730
|
+
};
|
|
1731
|
+
for (const transaction of [
|
|
1732
|
+
variants.default,
|
|
1733
|
+
variants.deferred,
|
|
1734
|
+
variants.immediate,
|
|
1735
|
+
variants.exclusive
|
|
1736
|
+
]) {
|
|
1737
|
+
Object.assign(transaction, variants);
|
|
1738
|
+
}
|
|
1739
|
+
return defaultTransaction;
|
|
1740
|
+
}
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1683
1743
|
function trackSqliteConnection(db, filename, options) {
|
|
1684
1744
|
const originalClose = db.close.bind(db);
|
|
1685
1745
|
const sequence = nextSqliteConnectionSequence++;
|
|
@@ -1688,6 +1748,7 @@ function trackSqliteConnection(db, filename, options) {
|
|
|
1688
1748
|
filename: typeof filename === "string" ? filename : Buffer.isBuffer(filename) ? "<buffer>" : ":memory:",
|
|
1689
1749
|
readonly: Boolean(options) && typeof options === "object" && (options.readonly === true || options.readOnly === true)
|
|
1690
1750
|
};
|
|
1751
|
+
installTransactionRouting(db, metadata.readonly);
|
|
1691
1752
|
Object.defineProperty(db, "close", {
|
|
1692
1753
|
configurable: true,
|
|
1693
1754
|
value: (...args) => {
|
|
@@ -1705,7 +1766,6 @@ function trackSqliteConnection(db, filename, options) {
|
|
|
1705
1766
|
return db;
|
|
1706
1767
|
}
|
|
1707
1768
|
function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
1708
|
-
const SAVEPOINT = "mc_tx_sp";
|
|
1709
1769
|
|
|
1710
1770
|
class NodeSqliteDatabase extends DatabaseSync {
|
|
1711
1771
|
constructor(filename, options) {
|
|
@@ -1724,45 +1784,50 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
1724
1784
|
}
|
|
1725
1785
|
return stmt;
|
|
1726
1786
|
}
|
|
1727
|
-
transaction(fn) {
|
|
1728
|
-
const self = this;
|
|
1729
|
-
const execute = (mode, receiver, args) => {
|
|
1730
|
-
const nested = self.isTransaction === true;
|
|
1731
|
-
self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : `BEGIN${mode ? ` ${mode}` : ""}`);
|
|
1732
|
-
try {
|
|
1733
|
-
const result = fn.apply(receiver, args);
|
|
1734
|
-
self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
|
|
1735
|
-
return result;
|
|
1736
|
-
} catch (error) {
|
|
1737
|
-
if (nested) {
|
|
1738
|
-
self.exec(`ROLLBACK TO ${SAVEPOINT}`);
|
|
1739
|
-
self.exec(`RELEASE ${SAVEPOINT}`);
|
|
1740
|
-
} else {
|
|
1741
|
-
self.exec("ROLLBACK");
|
|
1742
|
-
}
|
|
1743
|
-
throw error;
|
|
1744
|
-
}
|
|
1745
|
-
};
|
|
1746
|
-
const wrapped = function(...args) {
|
|
1747
|
-
return execute("", this, args);
|
|
1748
|
-
};
|
|
1749
|
-
wrapped.default = function(...args) {
|
|
1750
|
-
return execute("", this, args);
|
|
1751
|
-
};
|
|
1752
|
-
wrapped.deferred = function(...args) {
|
|
1753
|
-
return execute("DEFERRED", this, args);
|
|
1754
|
-
};
|
|
1755
|
-
wrapped.immediate = function(...args) {
|
|
1756
|
-
return execute("IMMEDIATE", this, args);
|
|
1757
|
-
};
|
|
1758
|
-
wrapped.exclusive = function(...args) {
|
|
1759
|
-
return execute("EXCLUSIVE", this, args);
|
|
1760
|
-
};
|
|
1761
|
-
return wrapped;
|
|
1762
|
-
}
|
|
1763
1787
|
}
|
|
1764
1788
|
return NodeSqliteDatabase;
|
|
1765
1789
|
}
|
|
1790
|
+
function pragmaValue(db, name) {
|
|
1791
|
+
const row = db.prepare(`PRAGMA ${name}`).get();
|
|
1792
|
+
if (!row)
|
|
1793
|
+
return;
|
|
1794
|
+
return row[name] ?? Object.values(row)[0];
|
|
1795
|
+
}
|
|
1796
|
+
function pragmaNumber(db, name) {
|
|
1797
|
+
try {
|
|
1798
|
+
const value = pragmaValue(db, name);
|
|
1799
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1800
|
+
} catch {
|
|
1801
|
+
return null;
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
function isTransientSqliteError(error) {
|
|
1805
|
+
if (!error || typeof error !== "object")
|
|
1806
|
+
return false;
|
|
1807
|
+
const value = error;
|
|
1808
|
+
return typeof value.code === "string" && /^(SQLITE_BUSY|SQLITE_LOCKED)(_|$)/.test(value.code) || typeof value.errcode === "number" && [5, 6].includes(value.errcode & 255);
|
|
1809
|
+
}
|
|
1810
|
+
function acquireShort(db, acquire, site) {
|
|
1811
|
+
const started = performance.now();
|
|
1812
|
+
const previous = pragmaNumber(db, "busy_timeout");
|
|
1813
|
+
let acquired = false;
|
|
1814
|
+
try {
|
|
1815
|
+
const timeout = transformPassScope.getStore()?.active && !admissionScope.getStore() && !backgroundWriterScope.getStore() ? FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS : SHORT_BUSY_TIMEOUT_MS;
|
|
1816
|
+
db.exec(`PRAGMA busy_timeout=${timeout}`);
|
|
1817
|
+
acquire();
|
|
1818
|
+
acquired = true;
|
|
1819
|
+
} catch (error) {
|
|
1820
|
+
if (transformPassScope.getStore()?.active && isTransientSqliteError(error))
|
|
1821
|
+
throw new SqliteAcquisitionBusyError(error, site);
|
|
1822
|
+
throw error;
|
|
1823
|
+
} finally {
|
|
1824
|
+
if (previous !== null)
|
|
1825
|
+
db.exec(`PRAGMA busy_timeout=${previous}`);
|
|
1826
|
+
const elapsed = performance.now() - started;
|
|
1827
|
+
if (elapsed >= 250)
|
|
1828
|
+
console.warn(`[${new Date().toISOString()}] [magic-context] sqlite acquisition site=${site} lane=${transformPassScope.getStore()?.active ? "foreground" : "background"} elapsed=${Math.round(elapsed)}ms attempts=1 outcome=${acquired ? "acquired" : "busy"}`);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1766
1831
|
function isInTransaction(db) {
|
|
1767
1832
|
const candidate = db;
|
|
1768
1833
|
return candidate.inTransaction === true || candidate.isTransaction === true;
|
|
@@ -1775,7 +1840,13 @@ function withPrivilegedWriter(db, operation) {
|
|
|
1775
1840
|
if (nested) {
|
|
1776
1841
|
db.exec(`SAVEPOINT ${savepoint}`);
|
|
1777
1842
|
} else {
|
|
1778
|
-
|
|
1843
|
+
try {
|
|
1844
|
+
db.exec("BEGIN IMMEDIATE");
|
|
1845
|
+
} catch (error) {
|
|
1846
|
+
if (transformPassScope.getStore()?.active && isTransientSqliteError(error))
|
|
1847
|
+
throw new SqliteAcquisitionBusyError(error);
|
|
1848
|
+
throw error;
|
|
1849
|
+
}
|
|
1779
1850
|
}
|
|
1780
1851
|
privilegeDepth.set(db, previousDepth + 1);
|
|
1781
1852
|
try {
|
|
@@ -1814,7 +1885,7 @@ function withPrivilegedWriter(db, operation) {
|
|
|
1814
1885
|
throw error;
|
|
1815
1886
|
}
|
|
1816
1887
|
}
|
|
1817
|
-
var reportSlowPrivilegedWrite, bunSpec, nodeSpec, SqliteRuntimeUnavailableError, detectedRuntime, isBun, sqliteModule, DatabaseImpl, trackedSqliteConnections, nextSqliteConnectionSequence = 1, TrackedDatabase, Database, privilegeDepth;
|
|
1888
|
+
var reportSlowPrivilegedWrite, bunSpec, nodeSpec, SqliteRuntimeUnavailableError, detectedRuntime, isBun, sqliteModule, DatabaseImpl, trackedSqliteConnections, nextSqliteConnectionSequence = 1, TrackedDatabase, Database, privilegeDepth, transformPassScope, admissionScope, backgroundWriterScope, SqliteAcquisitionBusyError, SHORT_BUSY_TIMEOUT_MS = 25, FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS = 250;
|
|
1818
1889
|
var init_sqlite = __esm(async () => {
|
|
1819
1890
|
bunSpec = "bun:" + "sqlite";
|
|
1820
1891
|
nodeSpec = "node:" + "sqlite";
|
|
@@ -1842,6 +1913,18 @@ var init_sqlite = __esm(async () => {
|
|
|
1842
1913
|
});
|
|
1843
1914
|
Database = TrackedDatabase;
|
|
1844
1915
|
privilegeDepth = new WeakMap;
|
|
1916
|
+
transformPassScope = new AsyncLocalStorage;
|
|
1917
|
+
admissionScope = new AsyncLocalStorage;
|
|
1918
|
+
backgroundWriterScope = new AsyncLocalStorage;
|
|
1919
|
+
SqliteAcquisitionBusyError = class SqliteAcquisitionBusyError extends Error {
|
|
1920
|
+
code = "SQLITE_BUSY";
|
|
1921
|
+
stage;
|
|
1922
|
+
constructor(cause, stage = "BEGIN IMMEDIATE") {
|
|
1923
|
+
super("SQLite writer acquisition remained busy", { cause });
|
|
1924
|
+
this.name = "SqliteAcquisitionBusyError";
|
|
1925
|
+
this.stage = stage;
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1845
1928
|
});
|
|
1846
1929
|
|
|
1847
1930
|
// src/lib/docs-proposal-gitignore.ts
|
|
@@ -4270,6 +4353,7 @@ function getPiVersion(piPath) {
|
|
|
4270
4353
|
try {
|
|
4271
4354
|
const invocation = getPiCommandInvocation(piPath, ["--version"]);
|
|
4272
4355
|
const result = spawnSync(invocation.command, invocation.args, {
|
|
4356
|
+
windowsHide: true,
|
|
4273
4357
|
encoding: "utf-8",
|
|
4274
4358
|
timeout: 1e4
|
|
4275
4359
|
});
|
|
@@ -4288,6 +4372,7 @@ function runPiCommand(piPath, args, timeout = 20000) {
|
|
|
4288
4372
|
try {
|
|
4289
4373
|
const invocation = getPiCommandInvocation(piPath, args);
|
|
4290
4374
|
return execFileSync(invocation.command, invocation.args, {
|
|
4375
|
+
windowsHide: true,
|
|
4291
4376
|
encoding: "utf-8",
|
|
4292
4377
|
stdio: ["ignore", "pipe", "ignore"],
|
|
4293
4378
|
timeout
|
|
@@ -4403,6 +4488,7 @@ function runOmpCommand(ompPath, args, timeout = 30000, overrides = {}) {
|
|
|
4403
4488
|
try {
|
|
4404
4489
|
const invocation = deps.getInvocation(ompPath, args);
|
|
4405
4490
|
const result = deps.spawnSync(invocation.command, invocation.args, {
|
|
4491
|
+
windowsHide: true,
|
|
4406
4492
|
encoding: "utf-8",
|
|
4407
4493
|
timeout,
|
|
4408
4494
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -12794,7 +12880,7 @@ var init_opencode_plugin_cache = __esm(() => {
|
|
|
12794
12880
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
12795
12881
|
import { existsSync as existsSync8, rmSync as rmSync2 } from "node:fs";
|
|
12796
12882
|
function runLsof(args, spawn) {
|
|
12797
|
-
const result = spawn("lsof", args, { encoding: "utf-8", timeout: 15000 });
|
|
12883
|
+
const result = spawn("lsof", args, { encoding: "utf-8", timeout: 15000, windowsHide: true });
|
|
12798
12884
|
if (result.error)
|
|
12799
12885
|
return { error: result.error.message };
|
|
12800
12886
|
if (result.status !== 0 && result.status !== 1) {
|
|
@@ -13160,7 +13246,11 @@ function getOpenCodeCommandInvocation(binary, args) {
|
|
|
13160
13246
|
}
|
|
13161
13247
|
function runOpenCode(args, binary, timeoutMs) {
|
|
13162
13248
|
try {
|
|
13163
|
-
const options = {
|
|
13249
|
+
const options = {
|
|
13250
|
+
stdio: "pipe",
|
|
13251
|
+
windowsHide: true,
|
|
13252
|
+
...timeoutMs ? { timeout: timeoutMs } : {}
|
|
13253
|
+
};
|
|
13164
13254
|
if (binary) {
|
|
13165
13255
|
const invocation = getOpenCodeCommandInvocation(binary, args);
|
|
13166
13256
|
return execFileSync2(invocation.command, invocation.args, {
|
|
@@ -14676,6 +14766,49 @@ function parseCron(expression) {
|
|
|
14676
14766
|
function isValidCron(expression) {
|
|
14677
14767
|
return parseCron(expression).ok;
|
|
14678
14768
|
}
|
|
14769
|
+
function matchesDay(cron, date) {
|
|
14770
|
+
const dom = cron.dom.has(date.getDate());
|
|
14771
|
+
const dow = cron.dow.has(date.getDay());
|
|
14772
|
+
if (cron.domRestricted && cron.dowRestricted)
|
|
14773
|
+
return dom || dow;
|
|
14774
|
+
if (cron.domRestricted)
|
|
14775
|
+
return dom;
|
|
14776
|
+
if (cron.dowRestricted)
|
|
14777
|
+
return dow;
|
|
14778
|
+
return true;
|
|
14779
|
+
}
|
|
14780
|
+
function matchesCron(cron, date) {
|
|
14781
|
+
return cron.minute.has(date.getMinutes()) && cron.hour.has(date.getHours()) && cron.month.has(date.getMonth() + 1) && matchesDay(cron, date);
|
|
14782
|
+
}
|
|
14783
|
+
function civilMinuteKey(date) {
|
|
14784
|
+
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
14785
|
+
return `${p(date.getFullYear(), 4)}-${p(date.getMonth() + 1)}-${p(date.getDate())} ${p(date.getHours())}:${p(date.getMinutes())}`;
|
|
14786
|
+
}
|
|
14787
|
+
function nextOccurrence(cron, after, excludeCivilMinute, maxSearchMs = MAX_SEARCH_MS) {
|
|
14788
|
+
const afterMs = after.getTime();
|
|
14789
|
+
let cursorMs = Math.floor(afterMs / MINUTE_MS) * MINUTE_MS + MINUTE_MS;
|
|
14790
|
+
const capMs = afterMs + Math.max(0, Math.min(MAX_SEARCH_MS, maxSearchMs));
|
|
14791
|
+
while (cursorMs <= capMs) {
|
|
14792
|
+
const candidate = new Date(cursorMs);
|
|
14793
|
+
if (matchesCron(cron, candidate)) {
|
|
14794
|
+
if (!excludeCivilMinute || civilMinuteKey(candidate) !== excludeCivilMinute) {
|
|
14795
|
+
return candidate;
|
|
14796
|
+
}
|
|
14797
|
+
}
|
|
14798
|
+
cursorMs += MINUTE_MS;
|
|
14799
|
+
}
|
|
14800
|
+
return null;
|
|
14801
|
+
}
|
|
14802
|
+
function nextDueAtMs(expression, afterMs, consumedScheduledAtMs, maxSearchMs = MAX_SEARCH_MS) {
|
|
14803
|
+
if (expression.trim().length === 0)
|
|
14804
|
+
return null;
|
|
14805
|
+
const parsed = parseCron(expression);
|
|
14806
|
+
if (!parsed.ok)
|
|
14807
|
+
return null;
|
|
14808
|
+
const exclude = consumedScheduledAtMs !== undefined ? civilMinuteKey(new Date(consumedScheduledAtMs)) : undefined;
|
|
14809
|
+
const next = nextOccurrence(parsed.cron, new Date(afterMs), exclude, maxSearchMs);
|
|
14810
|
+
return next ? next.getTime() : null;
|
|
14811
|
+
}
|
|
14679
14812
|
var FIELDS, MINUTE_MS = 60000, MAX_SEARCH_MS;
|
|
14680
14813
|
var init_cron = __esm(() => {
|
|
14681
14814
|
FIELDS = [
|
|
@@ -21156,9 +21289,9 @@ import { homedir as homedir9 } from "node:os";
|
|
|
21156
21289
|
function defaultTaskConfig(task) {
|
|
21157
21290
|
const base = { schedule: DEFAULT_TASK_SCHEDULES2[task] };
|
|
21158
21291
|
if (task === "review-user-memories")
|
|
21159
|
-
base.promotion_threshold =
|
|
21292
|
+
base.promotion_threshold = DREAM_TASK_PROMOTION_DEFAULTS["review-user-memories"];
|
|
21160
21293
|
if (task === "promote-primers")
|
|
21161
|
-
base.promotion_threshold =
|
|
21294
|
+
base.promotion_threshold = DREAM_TASK_PROMOTION_DEFAULTS["promote-primers"];
|
|
21162
21295
|
return base;
|
|
21163
21296
|
}
|
|
21164
21297
|
function expandConfigPath(value) {
|
|
@@ -21169,7 +21302,7 @@ function expandConfigPath(value) {
|
|
|
21169
21302
|
return `${homedir9()}/${trimmed.slice(2)}`;
|
|
21170
21303
|
return trimmed;
|
|
21171
21304
|
}
|
|
21172
|
-
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.", DEFAULT_HISTORIAN_TIMEOUT_MS = 600000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15, PROTECTED_TOKENS_MIN = 4000, DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2", PiThinkingLevelSchema, OmpThinkingLevelSchema, PiConfigSchema, PromptSurfacePresetSchema, PromptSurfaceModelKeySchema, PromptSurfaceToolKeySchema, PromptSurfaceConfigSchema, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, OcEntryObjectSchema, OcEntrySchema, PiEntryObjectSchema, PiEntrySchema, OmpEntryObjectSchema, OmpEntrySchema, OpenCodeHarnessBlockSchema, PiHarnessBlockSchema, OmpHarnessBlockSchema, OpenCodeTaskExecutionSchema, PiTaskExecutionSchema, OmpTaskExecutionSchema, DreamerOpenCodeHarnessBlockSchema, DreamerPiHarnessBlockSchema, DreamerOmpHarnessBlockSchema, ProfileOpenCodeModelBlockSchema, ProfilePiModelBlockSchema, ProfileOmpModelBlockSchema, ProfileHistorianSchema, ProfileDreamerSchema, ConfigProfileSchema, ConfigProfilesSchema, CronScheduleSchema, DreamTaskBaseConfigSchema, PromotionThresholdSchema, PrimerPromotionThresholdSchema, DreamTaskConfigSchema, ReviewUserMemoriesTaskConfigSchema, PromotePrimersTaskConfigSchema, RetrospectiveTaskConfigSchema, DEFAULT_TASK_SCHEDULES2, DreamTasksSchema, AgentMetadataSchema, DreamerConfigSchema, HistorianConfigSchema, EmbeddingFallbackProviderSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema, LIVE_RELOAD_CONFIG_PATHS;
|
|
21305
|
+
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.", DEFAULT_HISTORIAN_TIMEOUT_MS = 600000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15, PROTECTED_TOKENS_MIN = 4000, DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2", PiThinkingLevelSchema, OmpThinkingLevelSchema, PiConfigSchema, PromptSurfacePresetSchema, PromptSurfaceModelKeySchema, PromptSurfaceToolKeySchema, PromptSurfaceConfigSchema, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, OcEntryObjectSchema, OcEntrySchema, PiEntryObjectSchema, PiEntrySchema, OmpEntryObjectSchema, OmpEntrySchema, OpenCodeHarnessBlockSchema, PiHarnessBlockSchema, OmpHarnessBlockSchema, OpenCodeTaskExecutionSchema, PiTaskExecutionSchema, OmpTaskExecutionSchema, DreamerOpenCodeHarnessBlockSchema, DreamerPiHarnessBlockSchema, DreamerOmpHarnessBlockSchema, ProfileOpenCodeModelBlockSchema, ProfilePiModelBlockSchema, ProfileOmpModelBlockSchema, ProfileHistorianSchema, ProfileDreamerSchema, ConfigProfileSchema, ConfigProfilesSchema, CronScheduleSchema, DreamTaskBaseConfigSchema, DREAM_TASK_PROMOTION_DEFAULTS, PromotionThresholdSchema, PrimerPromotionThresholdSchema, DreamTaskConfigSchema, ReviewUserMemoriesTaskConfigSchema, PromotePrimersTaskConfigSchema, RetrospectiveTaskConfigSchema, DEFAULT_TASK_SCHEDULES2, DreamTasksSchema, AgentMetadataSchema, DreamerConfigSchema, HistorianConfigSchema, EmbeddingFallbackProviderSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema, LIVE_RELOAD_CONFIG_PATHS;
|
|
21173
21306
|
var init_magic_context = __esm(() => {
|
|
21174
21307
|
init_zod();
|
|
21175
21308
|
init_language_directive();
|
|
@@ -21346,10 +21479,15 @@ var init_magic_context = __esm(() => {
|
|
|
21346
21479
|
message: 'Invalid schedule: use a 5-field cron expression (e.g. "0 3 * * *" for 3am daily, "0 3 * * 0" for Sunday 3am, "0 */6 * * *" every 6h) or "" to disable.'
|
|
21347
21480
|
}).describe('5-field cron schedule (e.g. "0 3 * * *"), or "" to disable this task.');
|
|
21348
21481
|
DreamTaskBaseConfigSchema = object({
|
|
21349
|
-
schedule: CronScheduleSchema.default("")
|
|
21482
|
+
schedule: CronScheduleSchema.default(""),
|
|
21483
|
+
token_budget: number2().int().positive().optional().describe("Maximum cumulative prompt tokens (input + cache read + cache write) for one tool-loop child. Defaults vary by task.")
|
|
21350
21484
|
}).strict();
|
|
21351
|
-
|
|
21352
|
-
|
|
21485
|
+
DREAM_TASK_PROMOTION_DEFAULTS = {
|
|
21486
|
+
"review-user-memories": 3,
|
|
21487
|
+
"promote-primers": 2
|
|
21488
|
+
};
|
|
21489
|
+
PromotionThresholdSchema = number2().min(2).max(20).default(DREAM_TASK_PROMOTION_DEFAULTS["review-user-memories"]).describe("review-user-memories: min candidate observations before promotion is considered (default: 3)");
|
|
21490
|
+
PrimerPromotionThresholdSchema = number2().min(2).max(20).default(DREAM_TASK_PROMOTION_DEFAULTS["promote-primers"]).describe("promote-primers: min recurring source days before promotion is considered (default: 2)");
|
|
21353
21491
|
DreamTaskConfigSchema = DreamTaskBaseConfigSchema.extend({
|
|
21354
21492
|
promotion_threshold: PromotionThresholdSchema
|
|
21355
21493
|
});
|
|
@@ -21526,7 +21664,7 @@ var init_magic_context = __esm(() => {
|
|
|
21526
21664
|
});
|
|
21527
21665
|
MagicContextConfigSchema = object({
|
|
21528
21666
|
enabled: boolean2().default(true).describe("Enable magic context (default: true)"),
|
|
21529
|
-
allow_home_project: boolean2().default(false).describe("Allow Magic Context sessions launched from the exact canonical home directory.
|
|
21667
|
+
allow_home_project: boolean2().default(false).describe("Allow Magic Context sessions launched from the exact canonical home directory. A non-git home uses its deterministic dir: identity; a home repository uses its git: identity. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace."),
|
|
21530
21668
|
mural: object({
|
|
21531
21669
|
enabled: boolean2().default(false),
|
|
21532
21670
|
model: string2().trim().min(1).optional().describe("Model for the compress-cues task that compresses each memory into a mural cue. The mural image itself is rendered deterministically (no author model).")
|
|
@@ -24905,11 +25043,48 @@ var init_context_authority = __esm(async () => {
|
|
|
24905
25043
|
mirrorFlights = new WeakMap;
|
|
24906
25044
|
});
|
|
24907
25045
|
|
|
25046
|
+
// ../plugin/src/features/magic-context/memory/project-identity-cache.ts
|
|
25047
|
+
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
25048
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync14, renameSync as renameSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
25049
|
+
import path3 from "node:path";
|
|
25050
|
+
function projectDirectoryKey(directory) {
|
|
25051
|
+
const slashed = directory.replaceAll("\\", "/").replace(/^\/\/\?\/UNC\//i, "//").replace(/^\/\/\?\//, "");
|
|
25052
|
+
if (/^[a-z]:\//i.test(slashed) || slashed.startsWith("//")) {
|
|
25053
|
+
return path3.win32.normalize(slashed).replaceAll("\\", "/").replace(/\/$/, "").toLowerCase();
|
|
25054
|
+
}
|
|
25055
|
+
return path3.resolve(directory);
|
|
25056
|
+
}
|
|
25057
|
+
function cachePath(directory) {
|
|
25058
|
+
const hash = createHash2("sha256").update(projectDirectoryKey(directory)).digest("hex");
|
|
25059
|
+
return path3.join(getMagicContextStorageDir(), "project-identities", `${hash}.json`);
|
|
25060
|
+
}
|
|
25061
|
+
function rememberGitIdentity(directory, identity) {
|
|
25062
|
+
try {
|
|
25063
|
+
const destination = cachePath(directory);
|
|
25064
|
+
mkdirSync6(path3.dirname(destination), { recursive: true });
|
|
25065
|
+
const temporary = `${destination}.${randomUUID2()}.tmp`;
|
|
25066
|
+
writeFileSync5(temporary, JSON.stringify({ directory: projectDirectoryKey(directory), identity }), { mode: 384 });
|
|
25067
|
+
renameSync4(temporary, destination);
|
|
25068
|
+
} catch {}
|
|
25069
|
+
}
|
|
25070
|
+
function readRememberedGitIdentity(directory) {
|
|
25071
|
+
try {
|
|
25072
|
+
const record = JSON.parse(readFileSync14(cachePath(directory), "utf8"));
|
|
25073
|
+
if (record.directory === projectDirectoryKey(directory) && /^git:[0-9a-f]{7,64}$/.test(record.identity))
|
|
25074
|
+
return record.identity;
|
|
25075
|
+
} catch {}
|
|
25076
|
+
return;
|
|
25077
|
+
}
|
|
25078
|
+
var init_project_identity_cache = __esm(() => {
|
|
25079
|
+
init_data_path();
|
|
25080
|
+
});
|
|
25081
|
+
|
|
24908
25082
|
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
24909
25083
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
24910
|
-
import { createHash as
|
|
25084
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
24911
25085
|
import { existsSync as existsSync21, realpathSync as realpathSync2, statSync as statSync9 } from "node:fs";
|
|
24912
|
-
import
|
|
25086
|
+
import { homedir as homedir14 } from "node:os";
|
|
25087
|
+
import path4 from "node:path";
|
|
24913
25088
|
function asError(error) {
|
|
24914
25089
|
return error instanceof Error ? error : undefined;
|
|
24915
25090
|
}
|
|
@@ -24947,8 +25122,8 @@ function getErrorStderr(error) {
|
|
|
24947
25122
|
return "";
|
|
24948
25123
|
}
|
|
24949
25124
|
function directoryFallback(directory) {
|
|
24950
|
-
const canonical =
|
|
24951
|
-
const hash =
|
|
25125
|
+
const canonical = path4.resolve(directory);
|
|
25126
|
+
const hash = createHash3("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
|
|
24952
25127
|
return `dir:${hash}`;
|
|
24953
25128
|
}
|
|
24954
25129
|
function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
|
|
@@ -24993,8 +25168,9 @@ function classifyGitError(error, rawDirectory) {
|
|
|
24993
25168
|
}
|
|
24994
25169
|
return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
|
|
24995
25170
|
}
|
|
24996
|
-
function resolveProjectIdentityStrict(directory) {
|
|
24997
|
-
|
|
25171
|
+
function resolveProjectIdentityStrict(directory, allowHomeProject = homeProjectPermission) {
|
|
25172
|
+
assertProjectAllowed(directory, allowHomeProject);
|
|
25173
|
+
const canonical = path4.resolve(directory);
|
|
24998
25174
|
const cached = identityCache.get(canonical);
|
|
24999
25175
|
if (cached !== undefined) {
|
|
25000
25176
|
return cached;
|
|
@@ -25010,7 +25186,8 @@ function resolveProjectIdentityStrict(directory) {
|
|
|
25010
25186
|
encoding: "utf8",
|
|
25011
25187
|
env: { ...process.env, LC_ALL: "C", LANG: "C" },
|
|
25012
25188
|
stdio: ["ignore", "pipe", "pipe"],
|
|
25013
|
-
timeout: GIT_TIMEOUT_MS
|
|
25189
|
+
timeout: GIT_TIMEOUT_MS,
|
|
25190
|
+
windowsHide: true
|
|
25014
25191
|
});
|
|
25015
25192
|
} catch (error) {
|
|
25016
25193
|
throw classifyGitError(error, directory);
|
|
@@ -25023,13 +25200,17 @@ function resolveProjectIdentityStrict(directory) {
|
|
|
25023
25200
|
const identity = `git:${rootCommit}`;
|
|
25024
25201
|
identityCache.set(canonical, identity);
|
|
25025
25202
|
lastKnownGitIdentityCache.set(canonical, identity);
|
|
25203
|
+
rememberGitIdentity(canonical, identity);
|
|
25204
|
+
const root = gitRootDirectory(canonical);
|
|
25205
|
+
if (root && root !== canonical)
|
|
25206
|
+
rememberGitIdentity(root, identity);
|
|
25026
25207
|
transientFailureCooldown.delete(canonical);
|
|
25027
25208
|
dubiousOwnershipFallbackDirectories.delete(canonical);
|
|
25028
25209
|
transientGitIdentityReuseLoggedDirectories.delete(canonical);
|
|
25029
25210
|
return identity;
|
|
25030
25211
|
}
|
|
25031
25212
|
function shouldUseDirectoryFallback(error) {
|
|
25032
|
-
return error.errorClass !== "
|
|
25213
|
+
return error.errorClass !== "home_project_disabled";
|
|
25033
25214
|
}
|
|
25034
25215
|
function getActiveCooldown(canonical) {
|
|
25035
25216
|
const until = transientFailureCooldown.get(canonical);
|
|
@@ -25041,7 +25222,7 @@ function getActiveCooldown(canonical) {
|
|
|
25041
25222
|
return;
|
|
25042
25223
|
}
|
|
25043
25224
|
function lastKnownGitIdentity(canonical) {
|
|
25044
|
-
return lastKnownGitIdentityCache.get(canonical) ?? identityCache.get(canonical);
|
|
25225
|
+
return lastKnownGitIdentityCache.get(canonical) ?? identityCache.get(canonical) ?? readRememberedGitIdentity(canonical);
|
|
25045
25226
|
}
|
|
25046
25227
|
function nearestLastKnownGitIdentity(canonical) {
|
|
25047
25228
|
const visited = new Set;
|
|
@@ -25052,7 +25233,9 @@ function nearestLastKnownGitIdentity(canonical) {
|
|
|
25052
25233
|
const cached = lastKnownGitIdentity(current);
|
|
25053
25234
|
if (cached !== undefined)
|
|
25054
25235
|
return { identity: cached, source: current };
|
|
25055
|
-
|
|
25236
|
+
if (existsSync21(path4.join(current, ".git")))
|
|
25237
|
+
break;
|
|
25238
|
+
const parent = path4.dirname(current);
|
|
25056
25239
|
if (parent === current)
|
|
25057
25240
|
break;
|
|
25058
25241
|
current = parent;
|
|
@@ -25081,7 +25264,7 @@ function reuseLastKnownGitIdentity(canonical) {
|
|
|
25081
25264
|
return cached.identity;
|
|
25082
25265
|
}
|
|
25083
25266
|
function formatDubiousOwnershipWarning(canonical) {
|
|
25084
|
-
return `Magic Context: git refused to read ${canonical} (dubious ownership — the repo is owned by a different user).
|
|
25267
|
+
return `Magic Context: git refused to read ${canonical} (dubious ownership — the repo is owned by a different user). Memory features are paused unless a previous git identity is available. Fix: git config --global --add safe.directory ${canonical}`;
|
|
25085
25268
|
}
|
|
25086
25269
|
function recordDubiousOwnershipFallback(canonical) {
|
|
25087
25270
|
dubiousOwnershipFallbackDirectories.add(canonical);
|
|
@@ -25090,8 +25273,32 @@ function recordDubiousOwnershipFallback(canonical) {
|
|
|
25090
25273
|
dubiousOwnershipLoggedDirectories.add(canonical);
|
|
25091
25274
|
log3(`[magic-context] ${formatDubiousOwnershipWarning(canonical)}`);
|
|
25092
25275
|
}
|
|
25093
|
-
function
|
|
25094
|
-
const
|
|
25276
|
+
function canonicalUserHomeDirectory() {
|
|
25277
|
+
const homeDirectory = userHomeDirectoryForIdentity();
|
|
25278
|
+
try {
|
|
25279
|
+
return realpathSync2.native(homeDirectory);
|
|
25280
|
+
} catch {
|
|
25281
|
+
return homeDirectory;
|
|
25282
|
+
}
|
|
25283
|
+
}
|
|
25284
|
+
function isUserHomeDirectory(directory) {
|
|
25285
|
+
if (projectDirectoryKey(directory) === projectDirectoryKey(userHomeDirectoryForIdentity()))
|
|
25286
|
+
return true;
|
|
25287
|
+
try {
|
|
25288
|
+
return projectDirectoryKey(realpathSync2.native(path4.resolve(directory))) === projectDirectoryKey(canonicalUserHomeDirectory());
|
|
25289
|
+
} catch {
|
|
25290
|
+
return false;
|
|
25291
|
+
}
|
|
25292
|
+
}
|
|
25293
|
+
function assertProjectAllowed(directory, allowHomeProject) {
|
|
25294
|
+
const canonical = path4.resolve(directory);
|
|
25295
|
+
if (!allowHomeProject && (isUserHomeDirectory(directory) || isUserHomeDirectory(gitRootDirectory(canonical) ?? canonical))) {
|
|
25296
|
+
throw new ProjectIdentityError("home_project_disabled", directory, "Home project memory is disabled; set allow_home_project to opt in");
|
|
25297
|
+
}
|
|
25298
|
+
}
|
|
25299
|
+
function resolveProjectIdentity(directory, allowHomeProject = homeProjectPermission) {
|
|
25300
|
+
assertProjectAllowed(directory, allowHomeProject);
|
|
25301
|
+
const canonical = path4.resolve(directory);
|
|
25095
25302
|
const cachedFallback = directoryFallbackCache.get(canonical);
|
|
25096
25303
|
if (cachedFallback !== undefined) {
|
|
25097
25304
|
if (!hasGitDir(canonical)) {
|
|
@@ -25105,27 +25312,30 @@ function resolveProjectIdentity(directory) {
|
|
|
25105
25312
|
if (cachedGitIdentity !== undefined) {
|
|
25106
25313
|
return cachedGitIdentity;
|
|
25107
25314
|
}
|
|
25315
|
+
throw new ProjectIdentityError("git_identity_unavailable", directory, "Git identity unavailable; memory features paused until the retry cooldown expires");
|
|
25108
25316
|
}
|
|
25109
25317
|
return directoryFallback(canonical);
|
|
25110
25318
|
}
|
|
25111
25319
|
try {
|
|
25112
|
-
return resolveProjectIdentityStrict(directory);
|
|
25320
|
+
return resolveProjectIdentityStrict(directory, allowHomeProject);
|
|
25113
25321
|
} catch (error) {
|
|
25114
25322
|
if (error instanceof ProjectIdentityError && shouldUseDirectoryFallback(error)) {
|
|
25115
25323
|
const fallback = directoryFallback(canonical);
|
|
25116
25324
|
const hasGitMetadata = hasGitDir(canonical);
|
|
25117
25325
|
if (!hasGitMetadata) {
|
|
25326
|
+
if (error.errorClass === "permission_denied")
|
|
25327
|
+
throw error;
|
|
25118
25328
|
directoryFallbackCache.set(canonical, fallback);
|
|
25119
25329
|
transientFailureCooldown.delete(canonical);
|
|
25120
25330
|
} else {
|
|
25121
25331
|
transientFailureCooldown.set(canonical, nowMs() + TRANSIENT_FAILURE_COOLDOWN_MS);
|
|
25122
25332
|
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
25333
|
+
if (error.errorClass === "dubious_ownership")
|
|
25334
|
+
recordDubiousOwnershipFallback(canonical);
|
|
25123
25335
|
if (cachedGitIdentity !== undefined) {
|
|
25124
25336
|
return cachedGitIdentity;
|
|
25125
25337
|
}
|
|
25126
|
-
|
|
25127
|
-
if (error.errorClass === "dubious_ownership") {
|
|
25128
|
-
recordDubiousOwnershipFallback(canonical);
|
|
25338
|
+
throw error;
|
|
25129
25339
|
}
|
|
25130
25340
|
return fallback;
|
|
25131
25341
|
}
|
|
@@ -25146,14 +25356,14 @@ function hasGitDir(canonical) {
|
|
|
25146
25356
|
function gitRootInAncestorChain(startDirectory) {
|
|
25147
25357
|
let current = startDirectory;
|
|
25148
25358
|
while (true) {
|
|
25149
|
-
if (existsSync21(
|
|
25359
|
+
if (existsSync21(path4.join(current, ".git"))) {
|
|
25150
25360
|
try {
|
|
25151
25361
|
return realpathSync2.native(current);
|
|
25152
25362
|
} catch {
|
|
25153
|
-
return
|
|
25363
|
+
return path4.resolve(current);
|
|
25154
25364
|
}
|
|
25155
25365
|
}
|
|
25156
|
-
const parent =
|
|
25366
|
+
const parent = path4.dirname(current);
|
|
25157
25367
|
if (parent === current) {
|
|
25158
25368
|
return null;
|
|
25159
25369
|
}
|
|
@@ -25163,9 +25373,21 @@ function gitRootInAncestorChain(startDirectory) {
|
|
|
25163
25373
|
function hasGitDirInAncestorChain(startDirectory) {
|
|
25164
25374
|
return gitRootInAncestorChain(startDirectory) !== null;
|
|
25165
25375
|
}
|
|
25166
|
-
|
|
25376
|
+
function gitRootDirectory(canonical) {
|
|
25377
|
+
const direct = gitRootInAncestorChain(canonical);
|
|
25378
|
+
if (direct)
|
|
25379
|
+
return direct;
|
|
25380
|
+
try {
|
|
25381
|
+
const realCanonical = realpathSync2.native(canonical);
|
|
25382
|
+
return realCanonical === canonical ? null : gitRootInAncestorChain(realCanonical);
|
|
25383
|
+
} catch {
|
|
25384
|
+
return null;
|
|
25385
|
+
}
|
|
25386
|
+
}
|
|
25387
|
+
var GIT_TIMEOUT_MS = 5000, TRANSIENT_FAILURE_COOLDOWN_MS, identityCache, linkedGitWorktreeCache, lastKnownGitIdentityCache, directoryFallbackCache, transientFailureCooldown, dubiousOwnershipFallbackDirectories, dubiousOwnershipLoggedDirectories, dubiousOwnershipWarnedDirectories, transientGitIdentityReuseLoggedDirectories, sessionIdentityCache, homeProjectPermission = false, execFileSyncForIdentity, userHomeDirectoryForIdentity = () => homedir14(), nowMs = () => Date.now(), ProjectIdentityError;
|
|
25167
25388
|
var init_project_identity = __esm(() => {
|
|
25168
25389
|
init_logger();
|
|
25390
|
+
init_project_identity_cache();
|
|
25169
25391
|
TRANSIENT_FAILURE_COOLDOWN_MS = 5 * 60 * 1000;
|
|
25170
25392
|
identityCache = new Map;
|
|
25171
25393
|
linkedGitWorktreeCache = new Map;
|
|
@@ -26865,6 +27087,11 @@ var init_user_facing_codes = __esm(() => {
|
|
|
26865
27087
|
sentence: "Memory maintenance stopped at its hidden agent step limit.",
|
|
26866
27088
|
action: "This task needs less work per run; changing the model connection will not help."
|
|
26867
27089
|
},
|
|
27090
|
+
dream_token_budget: {
|
|
27091
|
+
code: "MC-D11",
|
|
27092
|
+
sentence: "Memory maintenance reached its prompt-token budget.",
|
|
27093
|
+
action: "The unfinished items will be retried on the next run."
|
|
27094
|
+
},
|
|
26868
27095
|
dream_empty_completion: {
|
|
26869
27096
|
code: "MC-D03",
|
|
26870
27097
|
sentence: "Memory maintenance received no usable response.",
|
|
@@ -27776,8 +28003,8 @@ var init_pi_executable = __esm(() => {
|
|
|
27776
28003
|
});
|
|
27777
28004
|
|
|
27778
28005
|
// ../plugin/src/shared/rpc-utils.ts
|
|
27779
|
-
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
27780
|
-
import { readFileSync as
|
|
28006
|
+
import { execFile, execFileSync as execFileSync4 } from "node:child_process";
|
|
28007
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
27781
28008
|
function isOwnRpcServerRecord(record) {
|
|
27782
28009
|
return record.pid === process.pid && record.instance_id !== undefined && ownRpcServerInstanceIds.has(record.instance_id);
|
|
27783
28010
|
}
|
|
@@ -27820,7 +28047,8 @@ function readPsProcessStartTime(pid) {
|
|
|
27820
28047
|
const output = rpcIdentityExecFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
|
|
27821
28048
|
encoding: "utf8",
|
|
27822
28049
|
timeout: PS_PROBE_TIMEOUT_MS,
|
|
27823
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
28050
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
28051
|
+
windowsHide: true
|
|
27824
28052
|
});
|
|
27825
28053
|
const processStartTime = Date.parse(String(output).trim());
|
|
27826
28054
|
return Number.isFinite(processStartTime) ? processStartTime : null;
|
|
@@ -27895,7 +28123,8 @@ function readWindowsProcess(pid) {
|
|
|
27895
28123
|
const output = rpcIdentityExecFileSync("tasklist", ["/FO", "CSV", "/FI", `PID eq ${pid}`], {
|
|
27896
28124
|
encoding: "utf8",
|
|
27897
28125
|
timeout: PS_PROBE_TIMEOUT_MS,
|
|
27898
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
28126
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
28127
|
+
windowsHide: true
|
|
27899
28128
|
});
|
|
27900
28129
|
const entries = parseTasklistOutput(String(output));
|
|
27901
28130
|
if (entries === null)
|
|
@@ -27928,7 +28157,8 @@ function readPsProcessCommand(pid) {
|
|
|
27928
28157
|
const output = rpcIdentityExecFileSync("ps", ["-p", String(pid), "-o", "command="], {
|
|
27929
28158
|
encoding: "utf8",
|
|
27930
28159
|
timeout: PS_PROBE_TIMEOUT_MS,
|
|
27931
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
28160
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
28161
|
+
windowsHide: true
|
|
27932
28162
|
});
|
|
27933
28163
|
return String(output);
|
|
27934
28164
|
} catch {
|
|
@@ -28039,7 +28269,8 @@ function execProcessList(exec, file, args, timeout = PS_PROBE_TIMEOUT_MS) {
|
|
|
28039
28269
|
return String(exec(file, [...args], {
|
|
28040
28270
|
encoding: "utf8",
|
|
28041
28271
|
timeout,
|
|
28042
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
28272
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
28273
|
+
windowsHide: true
|
|
28043
28274
|
}));
|
|
28044
28275
|
}
|
|
28045
28276
|
function parseWindowsCreationDate(value) {
|
|
@@ -28101,7 +28332,7 @@ function parseWindowsCimOutput(output) {
|
|
|
28101
28332
|
pid,
|
|
28102
28333
|
parentPid: Number.isInteger(parentPid) && parentPid > 0 ? parentPid : null,
|
|
28103
28334
|
commandLine,
|
|
28104
|
-
imageName: commandLine ? executableName(commandTokens(commandLine)[0]) : null,
|
|
28335
|
+
imageName: typeof record.Name === "string" ? record.Name : commandLine ? executableName(commandTokens(commandLine)[0]) : null,
|
|
28105
28336
|
startTime: parseWindowsCreationDate(record.CreationDate)
|
|
28106
28337
|
});
|
|
28107
28338
|
}
|
|
@@ -28179,14 +28410,14 @@ function readPosixParentPid(pid) {
|
|
|
28179
28410
|
return null;
|
|
28180
28411
|
}
|
|
28181
28412
|
}
|
|
28182
|
-
function collectAncestorPids(selfPid, parentByPid) {
|
|
28413
|
+
function collectAncestorPids(selfPid, parentByPid, probeParents = true) {
|
|
28183
28414
|
const ancestors = new Set;
|
|
28184
28415
|
let current = selfPid;
|
|
28185
28416
|
for (let depth = 0;depth < MAX_ANCESTOR_WALK_DEPTH; depth += 1) {
|
|
28186
28417
|
let ppid = null;
|
|
28187
28418
|
if (parentByPid.has(current)) {
|
|
28188
28419
|
ppid = parentByPid.get(current) ?? null;
|
|
28189
|
-
} else if (rpcIdentityPlatform !== "win32") {
|
|
28420
|
+
} else if (rpcIdentityPlatform !== "win32" && probeParents) {
|
|
28190
28421
|
ppid = readPosixParentPid(current);
|
|
28191
28422
|
if (ppid == null && current === process.pid && process.ppid > 0) {
|
|
28192
28423
|
ppid = process.ppid;
|
|
@@ -28203,8 +28434,8 @@ function collectAncestorPids(selfPid, parentByPid) {
|
|
|
28203
28434
|
}
|
|
28204
28435
|
return ancestors;
|
|
28205
28436
|
}
|
|
28206
|
-
function classifyLivePiSnapshot(snapshot) {
|
|
28207
|
-
const ancestors = collectAncestorPids(process.pid, snapshot.parentByPid);
|
|
28437
|
+
function classifyLivePiSnapshot(snapshot, probeParents = true) {
|
|
28438
|
+
const ancestors = collectAncestorPids(process.pid, snapshot.parentByPid, probeParents);
|
|
28208
28439
|
const processIds = new Set;
|
|
28209
28440
|
const inconclusivePids = new Set;
|
|
28210
28441
|
const skippedAncestorPids = [];
|
|
@@ -28249,8 +28480,9 @@ function inspectLivePiProcesses() {
|
|
|
28249
28480
|
if (false) {}
|
|
28250
28481
|
try {
|
|
28251
28482
|
if (rpcIdentityPlatform === "win32") {
|
|
28252
|
-
const
|
|
28253
|
-
const
|
|
28483
|
+
const now = rpcIdentityNowMs();
|
|
28484
|
+
const cached = windowsProcessSnapshotCache;
|
|
28485
|
+
const snapshot = cached && now >= cached.at && now - cached.at < WINDOWS_PROCESS_SNAPSHOT_TTL_MS ? cached.snapshot : tryReadWindowsCimSnapshot(rpcProcessListExecFileSync) ?? tryReadWindowsTasklistSnapshot();
|
|
28254
28486
|
if (!snapshot) {
|
|
28255
28487
|
return {
|
|
28256
28488
|
state: "unreadable",
|
|
@@ -28258,6 +28490,8 @@ function inspectLivePiProcesses() {
|
|
|
28258
28490
|
error: "process list unavailable"
|
|
28259
28491
|
};
|
|
28260
28492
|
}
|
|
28493
|
+
if (snapshot !== cached?.snapshot)
|
|
28494
|
+
windowsProcessSnapshotCache = { snapshot, at: now };
|
|
28261
28495
|
rememberWindowsProcessFacts(snapshot.facts);
|
|
28262
28496
|
return classifyLivePiSnapshot(snapshot);
|
|
28263
28497
|
}
|
|
@@ -28303,7 +28537,81 @@ function parseRpcPortFile(content, fallbackPid = 0) {
|
|
|
28303
28537
|
function isValidPort(port) {
|
|
28304
28538
|
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
28305
28539
|
}
|
|
28306
|
-
|
|
28540
|
+
function execProcessListAsync(file, args, timeout) {
|
|
28541
|
+
return new Promise((resolve, reject) => {
|
|
28542
|
+
execFile(file, args, { encoding: "utf8", timeout, windowsHide: true, maxBuffer: 8 * 1024 * 1024 }, (error, stdout) => {
|
|
28543
|
+
if (error)
|
|
28544
|
+
reject(error);
|
|
28545
|
+
else
|
|
28546
|
+
resolve(stdout);
|
|
28547
|
+
});
|
|
28548
|
+
});
|
|
28549
|
+
}
|
|
28550
|
+
function inspectProcessesAsync(forceFresh = false) {
|
|
28551
|
+
if (!forceFresh && asyncInspection && rpcIdentityNowMs() < asyncInspectionExpires)
|
|
28552
|
+
return asyncInspection;
|
|
28553
|
+
asyncInspectionExpires = Number.POSITIVE_INFINITY;
|
|
28554
|
+
asyncInspection = (async () => {
|
|
28555
|
+
let snapshot = null;
|
|
28556
|
+
try {
|
|
28557
|
+
if (rpcIdentityPlatform === "win32") {
|
|
28558
|
+
try {
|
|
28559
|
+
const output = await asyncProcessExec("powershell", ["-NoProfile", "-Command", WINDOWS_CIM_COMMAND], WINDOWS_CIM_PROBE_TIMEOUT_MS);
|
|
28560
|
+
const facts = parseWindowsCimOutput(output);
|
|
28561
|
+
if (facts)
|
|
28562
|
+
snapshot = snapshotFromFacts(facts, "cim");
|
|
28563
|
+
} catch {}
|
|
28564
|
+
if (!snapshot) {
|
|
28565
|
+
const entries = parseTasklistOutput(await asyncProcessExec("tasklist", ["/FO", "CSV"], PS_PROBE_TIMEOUT_MS));
|
|
28566
|
+
if (entries)
|
|
28567
|
+
snapshot = snapshotFromFacts(entries.map(({ pid, command }) => ({
|
|
28568
|
+
pid,
|
|
28569
|
+
parentPid: null,
|
|
28570
|
+
commandLine: null,
|
|
28571
|
+
imageName: command,
|
|
28572
|
+
startTime: null
|
|
28573
|
+
})), "tasklist");
|
|
28574
|
+
}
|
|
28575
|
+
} else {
|
|
28576
|
+
const output = await asyncProcessExec("ps", ["-axo", "pid=,ppid=,lstart=,command="], PS_PROBE_TIMEOUT_MS);
|
|
28577
|
+
const facts = [];
|
|
28578
|
+
for (const line of output.split(/\r?\n/)) {
|
|
28579
|
+
const match = /^\s*(\d+)\s+(\d+)\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+(.+)$/.exec(line);
|
|
28580
|
+
if (!match)
|
|
28581
|
+
continue;
|
|
28582
|
+
const startTime = Date.parse(match[3]);
|
|
28583
|
+
facts.push({
|
|
28584
|
+
pid: Number(match[1]),
|
|
28585
|
+
parentPid: Number(match[2]),
|
|
28586
|
+
commandLine: match[4],
|
|
28587
|
+
imageName: null,
|
|
28588
|
+
startTime: Number.isFinite(startTime) ? startTime : null
|
|
28589
|
+
});
|
|
28590
|
+
}
|
|
28591
|
+
snapshot = facts.length > 0 ? snapshotFromFacts(facts, "ps") : null;
|
|
28592
|
+
}
|
|
28593
|
+
} catch {}
|
|
28594
|
+
const fresh = snapshot !== null;
|
|
28595
|
+
if (snapshot)
|
|
28596
|
+
lastAsyncSnapshot = snapshot;
|
|
28597
|
+
else
|
|
28598
|
+
snapshot = lastAsyncSnapshot;
|
|
28599
|
+
const byPid = new Map(snapshot?.facts.map((fact) => [fact.pid, fact]));
|
|
28600
|
+
return {
|
|
28601
|
+
pi: snapshot ? classifyLivePiSnapshot(snapshot, false) : { state: "unreadable", processIds: [] },
|
|
28602
|
+
...fresh && snapshot ? { processSnapshot: { source: snapshot.source, facts: snapshot.facts } } : {},
|
|
28603
|
+
evidence: (pid) => ({
|
|
28604
|
+
startTime: byPid.get(pid)?.startTime ?? null,
|
|
28605
|
+
commandLine: byPid.get(pid)?.commandLine ?? byPid.get(pid)?.imageName ?? null
|
|
28606
|
+
}),
|
|
28607
|
+
liveness: (pid) => byPid.has(pid) ? "alive" : fresh ? "dead" : "inconclusive"
|
|
28608
|
+
};
|
|
28609
|
+
})().finally(() => {
|
|
28610
|
+
asyncInspectionExpires = rpcIdentityNowMs() + WINDOWS_PROCESS_SNAPSHOT_TTL_MS;
|
|
28611
|
+
});
|
|
28612
|
+
return asyncInspection;
|
|
28613
|
+
}
|
|
28614
|
+
var ownRpcServerInstanceIds, RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000, LINUX_CLOCK_TICKS_PER_SECOND = 100, PS_PROBE_TIMEOUT_MS = 1000, WINDOWS_CIM_PROBE_TIMEOUT_MS = 5000, WINDOWS_PROCESS_SNAPSHOT_TTL_MS = 2000, MAX_ANCESTOR_WALK_DEPTH = 16, OPEN_CODE_COMMAND_MARKERS, TASKLIST_NO_TASKS_PATTERN, WINDOWS_CIM_COMMAND = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,Name,CommandLine,CreationDate | ConvertTo-Json -Compress", PI_HARNESS_ARC_MARKERS, rpcIdentityReadFileSync, rpcIdentityExecFileSync, rpcIdentityProcessKill, rpcProcessListExecFileSync, rpcIdentityPlatform, rpcIdentityNowMs = () => Date.now(), windowsProcessFactsCache = null, windowsProcessSnapshotCache = null, asyncProcessExec, asyncInspection, asyncInspectionExpires = 0, lastAsyncSnapshot = null;
|
|
28307
28615
|
var init_rpc_utils = __esm(() => {
|
|
28308
28616
|
init_logger();
|
|
28309
28617
|
init_pi_executable();
|
|
@@ -28317,11 +28625,12 @@ var init_rpc_utils = __esm(() => {
|
|
|
28317
28625
|
"cljs/dist",
|
|
28318
28626
|
"dist/bundle/cli"
|
|
28319
28627
|
];
|
|
28320
|
-
rpcIdentityReadFileSync =
|
|
28628
|
+
rpcIdentityReadFileSync = readFileSync15;
|
|
28321
28629
|
rpcIdentityExecFileSync = execFileSync4;
|
|
28322
28630
|
rpcIdentityProcessKill = process.kill;
|
|
28323
28631
|
rpcProcessListExecFileSync = execFileSync4;
|
|
28324
28632
|
rpcIdentityPlatform = process.platform;
|
|
28633
|
+
asyncProcessExec = execProcessListAsync;
|
|
28325
28634
|
});
|
|
28326
28635
|
// ../plugin/src/features/magic-context/fail-closed-block.ts
|
|
28327
28636
|
function attachFailClosedBlockingProcessEvidence(process2, evidence) {
|
|
@@ -28463,11 +28772,11 @@ var init_fail_closed_block = __esm(() => {
|
|
|
28463
28772
|
});
|
|
28464
28773
|
|
|
28465
28774
|
// ../plugin/src/features/magic-context/message-fts-rowid-map.ts
|
|
28466
|
-
import { createHash as
|
|
28775
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
28467
28776
|
var EMPTY_INDEX_CONTENT_HASH, upsertMapStatements, rangeReadyStatements, updateTimeStatements, activeBackfills;
|
|
28468
28777
|
var init_message_fts_rowid_map = __esm(() => {
|
|
28469
28778
|
init_write_transaction_timing();
|
|
28470
|
-
EMPTY_INDEX_CONTENT_HASH =
|
|
28779
|
+
EMPTY_INDEX_CONTENT_HASH = createHash4("sha256").update("").digest("hex");
|
|
28471
28780
|
upsertMapStatements = new WeakMap;
|
|
28472
28781
|
rangeReadyStatements = new WeakMap;
|
|
28473
28782
|
updateTimeStatements = new WeakMap;
|
|
@@ -31651,9 +31960,9 @@ import {
|
|
|
31651
31960
|
copyFileSync,
|
|
31652
31961
|
cpSync,
|
|
31653
31962
|
existsSync as existsSync22,
|
|
31654
|
-
mkdirSync as
|
|
31963
|
+
mkdirSync as mkdirSync7,
|
|
31655
31964
|
readdirSync as readdirSync4,
|
|
31656
|
-
readFileSync as
|
|
31965
|
+
readFileSync as readFileSync16,
|
|
31657
31966
|
statSync as statSync10,
|
|
31658
31967
|
unlinkSync as unlinkSync3
|
|
31659
31968
|
} from "node:fs";
|
|
@@ -31736,7 +32045,7 @@ function classifyJunkDiscovery(portFile, raw, staleFiles) {
|
|
|
31736
32045
|
log3(`[magic-context] removing stale RPC discovery file ${portFile}: ${reason} record older than 10 minutes`);
|
|
31737
32046
|
return null;
|
|
31738
32047
|
}
|
|
31739
|
-
function inspectRpcServerDiscovery(storageDir) {
|
|
32048
|
+
function inspectRpcServerDiscovery(storageDir, processes) {
|
|
31740
32049
|
const rpcRoot = join18(storageDir, "rpc");
|
|
31741
32050
|
let projectEntries;
|
|
31742
32051
|
try {
|
|
@@ -31794,12 +32103,12 @@ function inspectRpcServerDiscovery(storageDir) {
|
|
|
31794
32103
|
}
|
|
31795
32104
|
if (isOwnRpcServerRecord(record))
|
|
31796
32105
|
continue;
|
|
31797
|
-
const liveness = isPidAlive(record.pid);
|
|
32106
|
+
const liveness = processes ? processes.liveness(record.pid) : isPidAlive(record.pid);
|
|
31798
32107
|
if (liveness === "dead") {
|
|
31799
32108
|
staleFiles.push(portFile);
|
|
31800
32109
|
continue;
|
|
31801
32110
|
}
|
|
31802
|
-
const evidence = readProcessProbeEvidence(record.pid);
|
|
32111
|
+
const evidence = processes ? processes.evidence(record.pid) : readProcessProbeEvidence(record.pid);
|
|
31803
32112
|
const identity = isPidIdentityPlausible(record, evidence);
|
|
31804
32113
|
if (identity === "plausible") {
|
|
31805
32114
|
pids.add(record.pid);
|
|
@@ -33108,7 +33417,7 @@ var init_storage_db = __esm(async () => {
|
|
|
33108
33417
|
RPC_DISCOVERY_PARSE_GRACE_MS = 10 * 60 * 1000;
|
|
33109
33418
|
defaultRpcDiscoveryFs = {
|
|
33110
33419
|
readdirSync: (path, options) => options?.withFileTypes ? readdirSync4(path, { withFileTypes: true }) : readdirSync4(path),
|
|
33111
|
-
readFileSync: (path, encoding) => String(
|
|
33420
|
+
readFileSync: (path, encoding) => String(readFileSync16(path, encoding)),
|
|
33112
33421
|
statSync: (path) => ({ mtimeMs: statSync10(path).mtimeMs }),
|
|
33113
33422
|
unlinkSync: (path) => unlinkSync3(path)
|
|
33114
33423
|
};
|
|
@@ -33121,7 +33430,7 @@ var init_storage_db = __esm(async () => {
|
|
|
33121
33430
|
});
|
|
33122
33431
|
|
|
33123
33432
|
// src/lib/database-access.ts
|
|
33124
|
-
import { existsSync as existsSync23, writeFileSync as
|
|
33433
|
+
import { existsSync as existsSync23, writeFileSync as writeFileSync6 } from "node:fs";
|
|
33125
33434
|
import { pathToFileURL } from "node:url";
|
|
33126
33435
|
function getPersistedSchemaVersion2(db) {
|
|
33127
33436
|
return getPersistedSchemaVersion(db);
|
|
@@ -33175,7 +33484,7 @@ function openExistingContextDatabaseForMutation(path) {
|
|
|
33175
33484
|
async function backupDatabaseSnapshot(db, destination) {
|
|
33176
33485
|
const serializable = db;
|
|
33177
33486
|
if (typeof serializable.serialize === "function") {
|
|
33178
|
-
|
|
33487
|
+
writeFileSync6(destination, serializable.serialize(), { flag: "wx" });
|
|
33179
33488
|
return;
|
|
33180
33489
|
}
|
|
33181
33490
|
const moduleName = "node:" + "sqlite";
|
|
@@ -33281,11 +33590,11 @@ async function reportAuthorityMarkers(args) {
|
|
|
33281
33590
|
args.info(" no authority_managed markers");
|
|
33282
33591
|
return;
|
|
33283
33592
|
}
|
|
33593
|
+
const loaded = loadPluginConfig(process.cwd());
|
|
33284
33594
|
let currentIdentity;
|
|
33285
33595
|
try {
|
|
33286
|
-
currentIdentity = resolveProjectIdentity(process.cwd());
|
|
33596
|
+
currentIdentity = resolveProjectIdentity(process.cwd(), loaded.allow_home_project);
|
|
33287
33597
|
} catch {}
|
|
33288
|
-
const loaded = loadPluginConfig(process.cwd());
|
|
33289
33598
|
const transport = new SubcModuleTransport(loaded.subc?.connection_file ?? getDefaultSubcConnectionFile());
|
|
33290
33599
|
for (const marker of markers) {
|
|
33291
33600
|
if (marker.project_path !== currentIdentity) {
|
|
@@ -33312,12 +33621,18 @@ async function runDoctorDrainAuthority(projectRoot, dbPath) {
|
|
|
33312
33621
|
return 1;
|
|
33313
33622
|
}
|
|
33314
33623
|
try {
|
|
33315
|
-
const
|
|
33624
|
+
const loaded = loadPluginConfig(projectRoot);
|
|
33625
|
+
let projectPath;
|
|
33626
|
+
try {
|
|
33627
|
+
projectPath = resolveProjectIdentity(projectRoot, loaded.allow_home_project);
|
|
33628
|
+
} catch (error) {
|
|
33629
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
33630
|
+
return 1;
|
|
33631
|
+
}
|
|
33316
33632
|
if (!getAuthorityManagedMarker(db, projectPath)) {
|
|
33317
33633
|
console.log(`No authority_managed marker exists for ${projectPath}.`);
|
|
33318
33634
|
return 0;
|
|
33319
33635
|
}
|
|
33320
|
-
const loaded = loadPluginConfig(projectRoot);
|
|
33321
33636
|
const module = authorityClient(new SubcModuleTransport(loaded.subc?.connection_file ?? getDefaultSubcConnectionFile()), projectRoot);
|
|
33322
33637
|
let drainedAny = false;
|
|
33323
33638
|
for (const domain of AUTHORITY_DOMAINS) {
|
|
@@ -33457,7 +33772,10 @@ function logRow(db, fromIdentity, toIdentity, tableName, rowId, action, targetRo
|
|
|
33457
33772
|
(from_identity, to_identity, table_name, row_id, action, target_row_id, merged_at)
|
|
33458
33773
|
VALUES (?, ?, ?, ?, ?, ?, ?)`).run(fromIdentity, toIdentity, tableName, rowId, action, targetRowId, mergedAt);
|
|
33459
33774
|
}
|
|
33460
|
-
function
|
|
33775
|
+
function normalizedContent(value) {
|
|
33776
|
+
return String(value).toLowerCase().replace(/\s+/g, " ").trim();
|
|
33777
|
+
}
|
|
33778
|
+
function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt, review) {
|
|
33461
33779
|
const sourceId = row.id;
|
|
33462
33780
|
if (typeof sourceId !== "number")
|
|
33463
33781
|
return false;
|
|
@@ -33465,10 +33783,13 @@ function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) {
|
|
|
33465
33783
|
FROM memories
|
|
33466
33784
|
WHERE project_path = ? AND category = ? AND normalized_hash = ? AND id <> ?
|
|
33467
33785
|
LIMIT 1`).get(toIdentity, row.category, row.normalized_hash, sourceId);
|
|
33468
|
-
if (collision &&
|
|
33786
|
+
if (collision && normalizedContent(collision.content) !== normalizedContent(row.content)) {
|
|
33787
|
+
db.prepare("UPDATE memories SET normalized_hash = ?, metadata_json = json_set(CASE WHEN json_valid(metadata_json) THEN metadata_json ELSE '{}' END, '$.identity_merge_original_hash', ?, '$.identity_merge_review', ?) WHERE id = ?").run(`${row.normalized_hash}:identity-conflict:${sourceId}`, row.normalized_hash, fromIdentity, sourceId);
|
|
33788
|
+
review = true;
|
|
33789
|
+
} else if (collision && typeof collision.id === "number") {
|
|
33469
33790
|
const targetId = collision.id;
|
|
33470
33791
|
const targetSeen = Number(collision.seen_count ?? 1);
|
|
33471
|
-
const mergedSeen =
|
|
33792
|
+
const mergedSeen = targetSeen + Number(row.seen_count ?? 1);
|
|
33472
33793
|
const sourceClassifiedAt = Number(row.classified_at ?? 0);
|
|
33473
33794
|
const targetClassifiedAt = Number(collision.classified_at ?? 0);
|
|
33474
33795
|
if (sourceClassifiedAt > targetClassifiedAt) {
|
|
@@ -33501,8 +33822,9 @@ function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) {
|
|
|
33501
33822
|
END`).run(targetId, sourceId);
|
|
33502
33823
|
db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?").run(sourceId);
|
|
33503
33824
|
if (mergedSeen !== targetSeen || collision.status === null || collision.status === undefined) {
|
|
33504
|
-
db.prepare("UPDATE memories SET seen_count = ?, status = COALESCE(status, 'active'), updated_at = ? WHERE id = ?").run(mergedSeen, mergedAt, targetId);
|
|
33825
|
+
db.prepare("UPDATE memories SET seen_count = ?, status = CASE WHEN ? = 'active' THEN 'active' ELSE COALESCE(status, 'active') END, updated_at = ? WHERE id = ?").run(mergedSeen, row.status, mergedAt, targetId);
|
|
33505
33826
|
}
|
|
33827
|
+
db.prepare(`UPDATE memories SET first_seen_at = MIN(first_seen_at, ?), last_seen_at = MAX(last_seen_at, ?), retrieval_count = COALESCE(retrieval_count, 0) + ?, merged_from = CASE WHEN merged_from IS NULL OR merged_from = '' THEN ? ELSE merged_from || ',' || ? END WHERE id = ?`).run(row.first_seen_at, row.last_seen_at, Number(row.retrieval_count ?? 0), String(sourceId), String(sourceId), targetId);
|
|
33506
33828
|
db.prepare(`UPDATE memories
|
|
33507
33829
|
SET status = 'archived',
|
|
33508
33830
|
superseded_by_memory_id = ?,
|
|
@@ -33518,6 +33840,9 @@ function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) {
|
|
|
33518
33840
|
logRow(db, fromIdentity, toIdentity, "memories", String(sourceId), "superseded", String(targetId), mergedAt);
|
|
33519
33841
|
return true;
|
|
33520
33842
|
}
|
|
33843
|
+
if (review) {
|
|
33844
|
+
db.prepare("UPDATE memories SET metadata_json = json_set(CASE WHEN json_valid(metadata_json) THEN metadata_json ELSE '{}' END, '$.identity_merge_review', ?) WHERE id = ?").run(fromIdentity, sourceId);
|
|
33845
|
+
}
|
|
33521
33846
|
const result = db.prepare("UPDATE memories SET project_path = ?, updated_at = ? WHERE id = ? AND project_path = ?").run(toIdentity, mergedAt, sourceId, fromIdentity);
|
|
33522
33847
|
if ((result.changes ?? 0) === 0)
|
|
33523
33848
|
return false;
|
|
@@ -33532,21 +33857,33 @@ function oldestOpenCycleStart(left, right) {
|
|
|
33532
33857
|
const values = [left, right].filter((value) => typeof value === "number" && value > 0);
|
|
33533
33858
|
return values.length > 0 ? Math.min(...values) : null;
|
|
33534
33859
|
}
|
|
33535
|
-
function reconcileTaskScheduleCollision(db, source, target) {
|
|
33536
|
-
const sourceIsNewer = typeof source.last_run_at === "number" && (typeof target.last_run_at !== "number" || source.last_run_at > target.last_run_at);
|
|
33860
|
+
function reconcileTaskScheduleCollision(db, source, target, mergedAt) {
|
|
33861
|
+
const sourceIsNewer = source.last_status === "completed" && (target.last_status !== "completed" || typeof source.last_run_at === "number" && (typeof target.last_run_at !== "number" || source.last_run_at > target.last_run_at));
|
|
33537
33862
|
const latest = sourceIsNewer ? source : target;
|
|
33538
33863
|
db.prepare(`UPDATE task_schedule_state
|
|
33539
33864
|
SET last_run_at = ?, next_due_at = ?, schedule = ?, last_status = ?,
|
|
33540
33865
|
last_error = ?, retry_count = ?, last_checked_commit = ?,
|
|
33541
33866
|
last_broad_run_at = ?, retrospective_watermark_ms = ?
|
|
33542
|
-
WHERE project_path = ? AND task = ?`).run(
|
|
33867
|
+
WHERE project_path = ? AND task = ?`).run(latest.last_run_at, nextDueAtMs(String(target.schedule ?? ""), Math.max(mergedAt, Number(source.last_run_at ?? 0), Number(target.last_run_at ?? 0))), target.schedule, latest.last_status, latest.last_error, latest.retry_count, latest.last_checked_commit, oldestOpenCycleStart(source.last_broad_run_at, target.last_broad_run_at), nullableMaximum(source.retrospective_watermark_ms, target.retrospective_watermark_ms), target.project_path, target.task);
|
|
33543
33868
|
}
|
|
33544
33869
|
function rekeyGenericRow(db, table, row, fromIdentity, toIdentity, mergedAt) {
|
|
33545
33870
|
const rowId = rowKey(db, table.name, row);
|
|
33546
33871
|
const collision = findUniqueCollision(db, table, row, fromIdentity, toIdentity);
|
|
33547
33872
|
if (collision) {
|
|
33548
33873
|
if (table.name === "task_schedule_state") {
|
|
33549
|
-
reconcileTaskScheduleCollision(db, row, collision);
|
|
33874
|
+
reconcileTaskScheduleCollision(db, row, collision, mergedAt);
|
|
33875
|
+
}
|
|
33876
|
+
const maximumColumns = {
|
|
33877
|
+
retrospective_processed_windows: ["processed_at"],
|
|
33878
|
+
embedding_identity_active: ["last_active_at"],
|
|
33879
|
+
memory_embedding_watermarks: ["written_memory_id", "embedded_memory_id", "updated_at"],
|
|
33880
|
+
project_state: ["project_memory_epoch", "project_user_profile_version", "updated_at"],
|
|
33881
|
+
project_key_files_version: ["version"]
|
|
33882
|
+
};
|
|
33883
|
+
const columns = maximumColumns[table.name];
|
|
33884
|
+
if (columns) {
|
|
33885
|
+
const targetPredicate = rowPredicate(db, table.name, collision);
|
|
33886
|
+
db.prepare(`UPDATE ${quoteIdentifier(table.name)} SET ${columns.map((column) => `${quoteIdentifier(column)} = ?`).join(", ")} WHERE ${targetPredicate.sql}`).run(...columns.map((column) => nullableMaximum(row[column], collision[column])), ...targetPredicate.values);
|
|
33550
33887
|
}
|
|
33551
33888
|
const sourcePredicate = rowPredicate(db, table.name, row);
|
|
33552
33889
|
const result = db.prepare(`DELETE FROM ${quoteIdentifier(table.name)} WHERE ${sourcePredicate.sql}`).run(...sourcePredicate.values);
|
|
@@ -33555,6 +33892,9 @@ function rekeyGenericRow(db, table, row, fromIdentity, toIdentity, mergedAt) {
|
|
|
33555
33892
|
logRow(db, fromIdentity, toIdentity, table.name, rowId, "collision_deleted", rowKey(db, table.name, collision), mergedAt);
|
|
33556
33893
|
return true;
|
|
33557
33894
|
}
|
|
33895
|
+
if (table.name === "task_schedule_state") {
|
|
33896
|
+
db.prepare("UPDATE task_schedule_state SET next_due_at = ? WHERE project_path = ? AND task = ?").run(nextDueAtMs(String(row.schedule ?? ""), Math.max(mergedAt, Number(row.last_run_at ?? 0))), fromIdentity, row.task);
|
|
33897
|
+
}
|
|
33558
33898
|
const predicate = rowPredicate(db, table.name, row);
|
|
33559
33899
|
const result = db.prepare(`UPDATE ${quoteIdentifier(table.name)}
|
|
33560
33900
|
SET ${quoteIdentifier(table.identityColumn)} = ?
|
|
@@ -33566,21 +33906,37 @@ function rekeyGenericRow(db, table, row, fromIdentity, toIdentity, mergedAt) {
|
|
|
33566
33906
|
return true;
|
|
33567
33907
|
}
|
|
33568
33908
|
function tableSourceRows(db, table, fromIdentity) {
|
|
33569
|
-
return db.prepare(`SELECT rowid, * FROM ${quoteIdentifier(table.name)} WHERE ${quoteIdentifier(table.identityColumn)} =
|
|
33909
|
+
return db.prepare(`SELECT rowid, * FROM ${quoteIdentifier(table.name)} WHERE ${quoteIdentifier(table.identityColumn)} = ?${table.name === "memories" ? " AND NOT (status = 'archived' AND superseded_by_memory_id IS NOT NULL AND EXISTS (SELECT 1 FROM identity_merge_log l WHERE l.table_name = 'memories' AND l.row_id = CAST(memories.id AS TEXT) AND l.from_identity = memories.project_path AND l.action = 'superseded'))" : ""}`).all(fromIdentity);
|
|
33570
33910
|
}
|
|
33571
33911
|
function assertMergeAllowed(db, fromIdentity, toIdentity) {
|
|
33912
|
+
const memberships = db.prepare(`SELECT m.project_path, w.id, w.name FROM workspace_members m JOIN workspaces w ON w.id = m.workspace_id WHERE m.project_path IN (?, ?)`).all(fromIdentity, toIdentity);
|
|
33913
|
+
if (memberships.length === 2 && memberships[0].id !== memberships[1].id) {
|
|
33914
|
+
throw new Error(`Refusing identity merge: different workspaces ${memberships[0].name} and ${memberships[1].name}. Choose membership before merging.`);
|
|
33915
|
+
}
|
|
33572
33916
|
if (!tableExists3(db, "authority_managed"))
|
|
33573
33917
|
return;
|
|
33574
33918
|
const source = db.prepare("SELECT 1 FROM authority_managed WHERE project_path = ? LIMIT 1").get(fromIdentity);
|
|
33575
33919
|
if (source) {
|
|
33576
|
-
throw new Error(`Refusing identity merge: ${fromIdentity} is managed by the Rust module
|
|
33920
|
+
throw new Error(`Refusing identity merge: ${fromIdentity} is managed by the Rust module: this project runs in Rust mode and its data lives in the module store. Merging will be possible once the single-store migration lands.`);
|
|
33577
33921
|
}
|
|
33578
33922
|
const target = db.prepare("SELECT 1 FROM authority_managed WHERE project_path = ? LIMIT 1").get(toIdentity);
|
|
33579
33923
|
if (target) {
|
|
33580
|
-
throw new Error(`Refusing identity merge: ${toIdentity} is managed by the Rust module
|
|
33924
|
+
throw new Error(`Refusing identity merge: ${toIdentity} is managed by the Rust module: this project runs in Rust mode and its data lives in the module store. Merging will be possible once the single-store migration lands.`);
|
|
33925
|
+
}
|
|
33926
|
+
}
|
|
33927
|
+
function memoryDisposition(db, from, to) {
|
|
33928
|
+
const duplicateMemoryIds = [];
|
|
33929
|
+
const reviewMemoryIds = [];
|
|
33930
|
+
for (const row of tableSourceRows(db, { name: "memories", identityColumn: "project_path", derived: false }, from)) {
|
|
33931
|
+
const collision = db.prepare("SELECT content FROM memories WHERE project_path = ? AND category = ? AND normalized_hash = ?").get(to, row.category, row.normalized_hash);
|
|
33932
|
+
if (collision && normalizedContent(collision.content) === normalizedContent(row.content))
|
|
33933
|
+
duplicateMemoryIds.push(Number(row.id));
|
|
33934
|
+
else if (db.prepare("SELECT 1 FROM memories WHERE project_path = ? AND category = ? LIMIT 1").get(to, row.category))
|
|
33935
|
+
reviewMemoryIds.push(Number(row.id));
|
|
33581
33936
|
}
|
|
33937
|
+
return { duplicateMemoryIds, reviewMemoryIds };
|
|
33582
33938
|
}
|
|
33583
|
-
function auditIdentityMerge(db, fromIdentity, toIdentity) {
|
|
33939
|
+
function auditIdentityMerge(db, fromIdentity, toIdentity, now = Date.now()) {
|
|
33584
33940
|
const auditedTables = discoverIdentityTables(db).map((table) => ({
|
|
33585
33941
|
tableName: table.name,
|
|
33586
33942
|
identityColumn: table.identityColumn,
|
|
@@ -33588,12 +33944,31 @@ function auditIdentityMerge(db, fromIdentity, toIdentity) {
|
|
|
33588
33944
|
sourceRows: table.derived ? 0 : tableSourceRows(db, table, fromIdentity).length,
|
|
33589
33945
|
changedRows: 0
|
|
33590
33946
|
}));
|
|
33947
|
+
const changes = [];
|
|
33948
|
+
for (const table of discoverIdentityTables(db).filter((table) => !table.derived && table.name !== "memories")) {
|
|
33949
|
+
for (const row of tableSourceRows(db, table, fromIdentity)) {
|
|
33950
|
+
const collision = findUniqueCollision(db, table, row, fromIdentity, toIdentity);
|
|
33951
|
+
if (collision)
|
|
33952
|
+
changes.push(`${table.name} ${rowKey(db, table.name, row)}: collapse into ${rowKey(db, table.name, collision)} (target content/configuration retained; progress counters reconciled)`);
|
|
33953
|
+
if (table.name === "workspace_members")
|
|
33954
|
+
changes.push(`workspace ${row.workspace_id}: ${collision ? "collapse aliases" : "transfer source membership"}`);
|
|
33955
|
+
if (table.name === "task_schedule_state") {
|
|
33956
|
+
const schedule = String((collision ?? row).schedule ?? "");
|
|
33957
|
+
changes.push(`task ${row.task}: schedule ${JSON.stringify(row.schedule)} → ${JSON.stringify(schedule)}; next_due_at → ${nextDueAtMs(schedule, Math.max(now, Number(row.last_run_at ?? 0), Number(collision?.last_run_at ?? 0)))}`);
|
|
33958
|
+
}
|
|
33959
|
+
}
|
|
33960
|
+
}
|
|
33961
|
+
const queues = db.prepare("SELECT reason, COUNT(*) AS n FROM dream_queue WHERE project_path IN (?, ?) GROUP BY reason HAVING COUNT(*) > 1").all(fromIdentity, toIdentity);
|
|
33962
|
+
for (const queue of queues)
|
|
33963
|
+
changes.push(`dream_queue ${JSON.stringify(queue.reason)}: ${queue.n} → 1 queued row`);
|
|
33591
33964
|
return {
|
|
33592
33965
|
fromIdentity,
|
|
33593
33966
|
toIdentity,
|
|
33967
|
+
changes,
|
|
33594
33968
|
auditedTables,
|
|
33595
33969
|
changedRows: auditedTables.reduce((total, table) => total + table.sourceRows, 0),
|
|
33596
|
-
dryRun: true
|
|
33970
|
+
dryRun: true,
|
|
33971
|
+
...memoryDisposition(db, fromIdentity, toIdentity)
|
|
33597
33972
|
};
|
|
33598
33973
|
}
|
|
33599
33974
|
function mergeProjectIdentities(db, fromIdentity, toIdentity, options = {}) {
|
|
@@ -33605,11 +33980,14 @@ function mergeProjectIdentities(db, fromIdentity, toIdentity, options = {}) {
|
|
|
33605
33980
|
}
|
|
33606
33981
|
assertMergeAllowed(db, fromIdentity, toIdentity);
|
|
33607
33982
|
const tables = discoverIdentityTables(db);
|
|
33608
|
-
const report = auditIdentityMerge(db, fromIdentity, toIdentity);
|
|
33983
|
+
const report = auditIdentityMerge(db, fromIdentity, toIdentity, options.now);
|
|
33609
33984
|
if (options.dryRun)
|
|
33610
33985
|
return report;
|
|
33986
|
+
if (report.changedRows === 0)
|
|
33987
|
+
return { ...report, dryRun: false };
|
|
33611
33988
|
const mergedAt = options.now ?? Date.now();
|
|
33612
33989
|
const run = db.transaction(() => {
|
|
33990
|
+
assertMergeAllowed(db, fromIdentity, toIdentity);
|
|
33613
33991
|
if (tableExists3(db, "v22_identity_rekey_map")) {
|
|
33614
33992
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
33615
33993
|
VALUES (?, ?, ?)
|
|
@@ -33624,11 +34002,15 @@ function mergeProjectIdentities(db, fromIdentity, toIdentity, options = {}) {
|
|
|
33624
34002
|
const rows = tableSourceRows(db, table, fromIdentity);
|
|
33625
34003
|
tableReport.sourceRows = rows.length;
|
|
33626
34004
|
for (const row of rows) {
|
|
33627
|
-
const changed = table.name === "memories" ? mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) : rekeyGenericRow(db, table, row, fromIdentity, toIdentity, mergedAt);
|
|
34005
|
+
const changed = table.name === "memories" ? mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt, report.reviewMemoryIds.includes(Number(row.id))) : rekeyGenericRow(db, table, row, fromIdentity, toIdentity, mergedAt);
|
|
33628
34006
|
if (changed)
|
|
33629
34007
|
tableReport.changedRows += 1;
|
|
33630
34008
|
}
|
|
33631
34009
|
}
|
|
34010
|
+
db.prepare(`DELETE FROM dream_queue WHERE project_path = ? AND id NOT IN (SELECT MIN(id) FROM dream_queue WHERE project_path = ? GROUP BY reason)`).run(toIdentity, toIdentity);
|
|
34011
|
+
db.prepare(`UPDATE dream_queue SET started_at = NULL WHERE project_path = ?`).run(toIdentity);
|
|
34012
|
+
db.prepare(`UPDATE git_sweep_coordinator SET lease_holder = NULL, lease_expires_at = NULL, last_swept_at = NULL WHERE project_path = ?`).run(toIdentity);
|
|
34013
|
+
db.prepare(`UPDATE session_meta SET cached_m0_bytes = NULL, cached_m0_project_identity = NULL WHERE cached_m0_project_identity IN (?, ?)`).run(fromIdentity, toIdentity);
|
|
33632
34014
|
db.prepare(`INSERT INTO project_state
|
|
33633
34015
|
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
33634
34016
|
VALUES (?, 1, 0, ?)
|
|
@@ -33645,6 +34027,7 @@ function mergeProjectIdentities(db, fromIdentity, toIdentity, options = {}) {
|
|
|
33645
34027
|
}
|
|
33646
34028
|
var IDENTITY_COLUMNS, DERIVED_TABLE_SUFFIXES;
|
|
33647
34029
|
var init_storage_identity_merge = __esm(() => {
|
|
34030
|
+
init_cron();
|
|
33648
34031
|
IDENTITY_COLUMNS = new Set(["project_path", "project_identity"]);
|
|
33649
34032
|
DERIVED_TABLE_SUFFIXES = [
|
|
33650
34033
|
"_fts",
|
|
@@ -33656,84 +34039,88 @@ var init_storage_identity_merge = __esm(() => {
|
|
|
33656
34039
|
];
|
|
33657
34040
|
});
|
|
33658
34041
|
|
|
33659
|
-
// src/commands/doctor-
|
|
34042
|
+
// src/commands/doctor-identity-splits.ts
|
|
34043
|
+
import { realpathSync as realpathSync4 } from "node:fs";
|
|
33660
34044
|
import { join as join19 } from "node:path";
|
|
33661
|
-
function
|
|
33662
|
-
|
|
33663
|
-
if (index < 0)
|
|
33664
|
-
return null;
|
|
33665
|
-
const value = args[index + 1];
|
|
33666
|
-
if (!value || value.startsWith("--")) {
|
|
33667
|
-
throw new Error(`${flag} requires a value`);
|
|
33668
|
-
}
|
|
33669
|
-
return value;
|
|
34045
|
+
function tableExists4(db, table) {
|
|
34046
|
+
return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);
|
|
33670
34047
|
}
|
|
33671
|
-
function
|
|
33672
|
-
|
|
33673
|
-
|
|
33674
|
-
|
|
33675
|
-
|
|
33676
|
-
|
|
33677
|
-
const knownFlags = new Set(["--from", "--to", "--db"]);
|
|
33678
|
-
for (let index = 0;index < args.length; index += 1) {
|
|
33679
|
-
const arg = args[index];
|
|
33680
|
-
if (knownFlags.has(arg)) {
|
|
33681
|
-
index += 1;
|
|
34048
|
+
function findIdentitySplits(db, host, includeSingles = false) {
|
|
34049
|
+
if (!tableExists4(db, "session_projects"))
|
|
34050
|
+
return [];
|
|
34051
|
+
const directories = new Map;
|
|
34052
|
+
for (const table of ["session", "session_v2"]) {
|
|
34053
|
+
if (!tableExists4(host, table))
|
|
33682
34054
|
continue;
|
|
34055
|
+
const rows = host.prepare(`SELECT id, directory FROM ${table} WHERE directory IS NOT NULL`).all();
|
|
34056
|
+
for (const row of rows) {
|
|
34057
|
+
if (!row.directory)
|
|
34058
|
+
continue;
|
|
34059
|
+
let canonical = row.directory;
|
|
34060
|
+
try {
|
|
34061
|
+
canonical = realpathSync4.native(canonical);
|
|
34062
|
+
} catch {}
|
|
34063
|
+
const key = `${table === "session" ? "opencode" : "opencode2"}\x00${row.id}`;
|
|
34064
|
+
const roots = directories.get(key) ?? new Set;
|
|
34065
|
+
roots.add(projectDirectoryKey(canonical));
|
|
34066
|
+
directories.set(key, roots);
|
|
33683
34067
|
}
|
|
33684
|
-
|
|
34068
|
+
}
|
|
34069
|
+
const byDirectory = new Map;
|
|
34070
|
+
const bindings = db.prepare("SELECT session_id, harness, project_path FROM session_projects WHERE harness IN ('opencode', 'opencode2')").all();
|
|
34071
|
+
for (const row of bindings) {
|
|
34072
|
+
if (!/^(git|dir):/.test(row.project_path))
|
|
33685
34073
|
continue;
|
|
33686
|
-
|
|
34074
|
+
for (const directory of directories.get(`${row.harness}\x00${row.session_id}`) ?? []) {
|
|
34075
|
+
const identities = byDirectory.get(directory) ?? new Set;
|
|
34076
|
+
identities.add(row.project_path);
|
|
34077
|
+
byDirectory.set(directory, identities);
|
|
34078
|
+
}
|
|
33687
34079
|
}
|
|
33688
|
-
|
|
33689
|
-
|
|
33690
|
-
|
|
33691
|
-
|
|
33692
|
-
|
|
33693
|
-
|
|
33694
|
-
|
|
34080
|
+
const count = (table, identity) => tableExists4(db, table) ? db.prepare(`SELECT COUNT(*) AS n FROM ${table} WHERE project_path = ?`).get(identity).n : 0;
|
|
34081
|
+
return [...byDirectory].filter(([, identities]) => includeSingles || identities.size > 1).sort(([a], [b]) => a.localeCompare(b)).map(([directory, identities]) => ({
|
|
34082
|
+
directory,
|
|
34083
|
+
identities: [...identities].sort().map((identity) => ({
|
|
34084
|
+
identity,
|
|
34085
|
+
sessions: count("session_projects", identity),
|
|
34086
|
+
memories: count("memories", identity),
|
|
34087
|
+
notes: count("notes", identity),
|
|
34088
|
+
dreamer: [
|
|
34089
|
+
"dream_queue",
|
|
34090
|
+
"dream_runs",
|
|
34091
|
+
"task_schedule_state",
|
|
34092
|
+
"retrospective_processed_windows"
|
|
34093
|
+
].reduce((n, table) => n + count(table, identity), 0)
|
|
34094
|
+
}))
|
|
34095
|
+
}));
|
|
33695
34096
|
}
|
|
33696
|
-
function
|
|
33697
|
-
|
|
33698
|
-
|
|
33699
|
-
|
|
33700
|
-
|
|
33701
|
-
for (const table of report.auditedTables) {
|
|
33702
|
-
const suffix = table.derived ? " (derived; updated by source triggers)" : "";
|
|
33703
|
-
console.log(` ${table.tableName} [${table.identityColumn}]${suffix}: ${report.dryRun ? table.sourceRows : table.changedRows} row(s)`);
|
|
33704
|
-
}
|
|
33705
|
-
console.log(` rows changed: ${report.changedRows}`);
|
|
33706
|
-
if (report.dryRun) {
|
|
33707
|
-
console.log(" no database writes performed");
|
|
33708
|
-
}
|
|
34097
|
+
function formatIdentitySplits(splits) {
|
|
34098
|
+
return splits.flatMap((split) => [
|
|
34099
|
+
`Project identity split: ${split.directory} (read-only; no merge performed)`,
|
|
34100
|
+
...split.identities.map((row) => ` ${row.identity}: ${row.sessions} sessions, ${row.memories} memories, ${row.notes} notes, ${row.dreamer} dreamer rows (identity-wide counts)`)
|
|
34101
|
+
]);
|
|
33709
34102
|
}
|
|
33710
|
-
function
|
|
33711
|
-
const db =
|
|
34103
|
+
function diagnoseIdentitySplits() {
|
|
34104
|
+
const db = openExistingContextDatabase(join19(getMagicContextStorageDir(), "context.db"), {
|
|
34105
|
+
readonly: true
|
|
34106
|
+
});
|
|
33712
34107
|
if (!db)
|
|
33713
|
-
|
|
33714
|
-
|
|
33715
|
-
}
|
|
33716
|
-
function runMergeIdentityCli(args) {
|
|
33717
|
-
const options = parseMergeIdentityArgs(args);
|
|
33718
|
-
if (!options.dryRun && !options.yes) {
|
|
33719
|
-
console.error("Refusing to mutate context.db without explicit --yes. Re-run with --yes, or use --dry-run to preview.");
|
|
33720
|
-
return 2;
|
|
33721
|
-
}
|
|
33722
|
-
const dbPath = options.dbPath ?? join19(getMagicContextStorageDir(), "context.db");
|
|
33723
|
-
const db = openMergeDatabase(dbPath, !options.dryRun);
|
|
34108
|
+
return [];
|
|
34109
|
+
let host = null;
|
|
33724
34110
|
try {
|
|
33725
|
-
|
|
33726
|
-
|
|
33727
|
-
|
|
33728
|
-
|
|
33729
|
-
return 0;
|
|
34111
|
+
host = openExistingDatabase(resolveOpenCodeDbPath().path, { readonly: true });
|
|
34112
|
+
if (!host)
|
|
34113
|
+
return ["Identity split check skipped: OpenCode session directories unavailable."];
|
|
34114
|
+
return formatIdentitySplits(findIdentitySplits(db, host));
|
|
33730
34115
|
} finally {
|
|
34116
|
+
host?.close();
|
|
33731
34117
|
db.close();
|
|
33732
34118
|
}
|
|
33733
34119
|
}
|
|
33734
|
-
var
|
|
33735
|
-
|
|
34120
|
+
var init_doctor_identity_splits = __esm(async () => {
|
|
34121
|
+
init_project_identity_cache();
|
|
33736
34122
|
init_data_path();
|
|
34123
|
+
init_opencode_db_path();
|
|
33737
34124
|
await init_database_access();
|
|
33738
34125
|
});
|
|
33739
34126
|
|
|
@@ -33746,7 +34133,7 @@ import {
|
|
|
33746
34133
|
copyFileSync as copyFileSync2,
|
|
33747
34134
|
existsSync as existsSync24,
|
|
33748
34135
|
openSync as openSync4,
|
|
33749
|
-
renameSync as
|
|
34136
|
+
renameSync as renameSync5,
|
|
33750
34137
|
rmSync as rmSync3,
|
|
33751
34138
|
statSync as statSync11
|
|
33752
34139
|
} from "node:fs";
|
|
@@ -34001,15 +34388,15 @@ function activateReplacement(dbPath, replacementPath, originalAsidePath) {
|
|
|
34001
34388
|
if (!existsSync24(from))
|
|
34002
34389
|
continue;
|
|
34003
34390
|
const to = `${originalAsidePath}${suffix}`;
|
|
34004
|
-
|
|
34391
|
+
renameSync5(from, to);
|
|
34005
34392
|
movedOriginals.push({ from, to });
|
|
34006
34393
|
}
|
|
34007
|
-
|
|
34394
|
+
renameSync5(replacementPath, dbPath);
|
|
34008
34395
|
return movedOriginals.map(({ to }) => to);
|
|
34009
34396
|
} catch (error) {
|
|
34010
34397
|
for (const moved of movedOriginals.reverse()) {
|
|
34011
34398
|
if (existsSync24(moved.to) && !existsSync24(moved.from))
|
|
34012
|
-
|
|
34399
|
+
renameSync5(moved.to, moved.from);
|
|
34013
34400
|
}
|
|
34014
34401
|
throw error;
|
|
34015
34402
|
}
|
|
@@ -34240,6 +34627,232 @@ var init_doctor_repair_db = __esm(async () => {
|
|
|
34240
34627
|
];
|
|
34241
34628
|
});
|
|
34242
34629
|
|
|
34630
|
+
// src/commands/doctor-merge-identity.ts
|
|
34631
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
34632
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
34633
|
+
import {
|
|
34634
|
+
cpSync as cpSync2,
|
|
34635
|
+
existsSync as existsSync25,
|
|
34636
|
+
mkdirSync as mkdirSync8,
|
|
34637
|
+
mkdtempSync,
|
|
34638
|
+
readdirSync as readdirSync5,
|
|
34639
|
+
readFileSync as readFileSync17,
|
|
34640
|
+
renameSync as renameSync6,
|
|
34641
|
+
writeFileSync as writeFileSync7
|
|
34642
|
+
} from "node:fs";
|
|
34643
|
+
import { dirname as dirname13, join as join21 } from "node:path";
|
|
34644
|
+
function parseMergeIdentityArgs(args) {
|
|
34645
|
+
const values = {};
|
|
34646
|
+
const switches = new Set(["--apply", "--force", "--dry-run", "--yes"]);
|
|
34647
|
+
for (let i = 0;i < args.length; i++) {
|
|
34648
|
+
const flag = args[i];
|
|
34649
|
+
if (["--from", "--to", "--db", "--host-db"].includes(flag)) {
|
|
34650
|
+
const value = args[++i];
|
|
34651
|
+
if (!value || value.startsWith("--"))
|
|
34652
|
+
throw new Error(`${flag} requires a value`);
|
|
34653
|
+
if (values[flag])
|
|
34654
|
+
throw new Error(`Repeated option: ${flag}`);
|
|
34655
|
+
values[flag] = value;
|
|
34656
|
+
} else if (!switches.has(flag))
|
|
34657
|
+
throw new Error(`Unknown doctor merge-identities option: ${flag}`);
|
|
34658
|
+
}
|
|
34659
|
+
if (Boolean(values["--from"]) !== Boolean(values["--to"]))
|
|
34660
|
+
throw new Error("Supply both --from and --to");
|
|
34661
|
+
const apply = args.includes("--apply") || args.includes("--yes");
|
|
34662
|
+
if (apply && (!values["--from"] || args.includes("--dry-run")))
|
|
34663
|
+
throw new Error("--apply requires --from/--to and cannot be combined with --dry-run");
|
|
34664
|
+
return {
|
|
34665
|
+
from: values["--from"],
|
|
34666
|
+
to: values["--to"],
|
|
34667
|
+
dbPath: values["--db"],
|
|
34668
|
+
hostPath: values["--host-db"],
|
|
34669
|
+
dryRun: !apply,
|
|
34670
|
+
yes: apply,
|
|
34671
|
+
force: args.includes("--force")
|
|
34672
|
+
};
|
|
34673
|
+
}
|
|
34674
|
+
function printReport(report) {
|
|
34675
|
+
console.log(`Identity merge ${report.dryRun ? "preview" : "complete"}: ${report.fromIdentity} → ${report.toIdentity}`);
|
|
34676
|
+
for (const table of report.auditedTables) {
|
|
34677
|
+
console.log(` ${table.tableName}: ${report.dryRun ? table.sourceRows : table.changedRows} row(s)${table.derived ? " (derived; maintained by triggers)" : ""}`);
|
|
34678
|
+
}
|
|
34679
|
+
for (const change of report.changes)
|
|
34680
|
+
console.log(` ${change}`);
|
|
34681
|
+
console.log(` identical memories collapsed: ${report.duplicateMemoryIds.join(", ") || "none"}`);
|
|
34682
|
+
console.log(` potential content conflicts kept for review (same category): ${report.reviewMemoryIds.join(", ") || "none"}`);
|
|
34683
|
+
console.log(" Workspace aliases collapse; source-only membership transfers. Target schedules win; next_due_at is recomputed. Queued reasons deduplicate; run history and processed windows remain.");
|
|
34684
|
+
console.log(" Git indexes move; sweep leases reset for rebuilding. Existing memory embeddings remain valid (content unchanged); FTS triggers rekey indexes.");
|
|
34685
|
+
if (!report.changedRows)
|
|
34686
|
+
console.log(" No-op: no source rows remain to move.");
|
|
34687
|
+
if (report.dryRun)
|
|
34688
|
+
console.log(" No writes. Review this preview, then repeat with --apply to confirm.");
|
|
34689
|
+
}
|
|
34690
|
+
function resolveReadOnly(directory) {
|
|
34691
|
+
if (!existsSync25(directory))
|
|
34692
|
+
return;
|
|
34693
|
+
try {
|
|
34694
|
+
const roots = execFileSync5("git", ["rev-list", "--max-parents=0", "HEAD"], {
|
|
34695
|
+
cwd: directory,
|
|
34696
|
+
windowsHide: true,
|
|
34697
|
+
encoding: "utf8",
|
|
34698
|
+
timeout: 5000,
|
|
34699
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34700
|
+
}).trim().split(/\s+/).filter((root) => /^[0-9a-f]{40,64}$/.test(root)).sort();
|
|
34701
|
+
if (roots[0])
|
|
34702
|
+
return `git:${roots[0]}`;
|
|
34703
|
+
} catch {}
|
|
34704
|
+
try {
|
|
34705
|
+
const result = execFileSync5("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
34706
|
+
cwd: directory,
|
|
34707
|
+
windowsHide: true,
|
|
34708
|
+
encoding: "utf8",
|
|
34709
|
+
timeout: 5000,
|
|
34710
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34711
|
+
});
|
|
34712
|
+
if (result.trim() === "true")
|
|
34713
|
+
return;
|
|
34714
|
+
} catch (error) {
|
|
34715
|
+
if (String(error.stderr).includes("not a git repository"))
|
|
34716
|
+
return `dir:${createHash5("md5").update(projectDirectoryKey(directory)).digest("hex").slice(0, 12)}`;
|
|
34717
|
+
}
|
|
34718
|
+
return;
|
|
34719
|
+
}
|
|
34720
|
+
function observations(db, hostPath, storageDir) {
|
|
34721
|
+
const host = openExistingDatabase(hostPath, { readonly: true });
|
|
34722
|
+
let rows = [];
|
|
34723
|
+
try {
|
|
34724
|
+
rows = host ? findIdentitySplits(db, host, true) : [];
|
|
34725
|
+
} finally {
|
|
34726
|
+
host?.close();
|
|
34727
|
+
}
|
|
34728
|
+
const add = (directory, identity) => {
|
|
34729
|
+
if (!/^(git|dir):/.test(identity))
|
|
34730
|
+
return;
|
|
34731
|
+
directory = projectDirectoryKey(directory);
|
|
34732
|
+
let row = rows.find((item) => item.directory === directory);
|
|
34733
|
+
if (!row) {
|
|
34734
|
+
row = { directory, identities: [] };
|
|
34735
|
+
rows.push(row);
|
|
34736
|
+
}
|
|
34737
|
+
if (!row.identities.some((item) => item.identity === identity))
|
|
34738
|
+
row.identities.push({ identity, sessions: 0, memories: 0, notes: 0, dreamer: 0 });
|
|
34739
|
+
};
|
|
34740
|
+
const sidecars = join21(storageDir, "project-identities");
|
|
34741
|
+
if (existsSync25(sidecars))
|
|
34742
|
+
for (const file of readdirSync5(sidecars)) {
|
|
34743
|
+
if (!file.endsWith(".json"))
|
|
34744
|
+
continue;
|
|
34745
|
+
try {
|
|
34746
|
+
const record = JSON.parse(readFileSync17(join21(sidecars, file), "utf8"));
|
|
34747
|
+
if (typeof record.directory === "string" && typeof record.identity === "string")
|
|
34748
|
+
add(record.directory, record.identity);
|
|
34749
|
+
} catch {}
|
|
34750
|
+
}
|
|
34751
|
+
for (const row of db.prepare("SELECT project_path, display_path FROM workspace_members").all())
|
|
34752
|
+
add(row.display_path, row.project_path);
|
|
34753
|
+
return rows;
|
|
34754
|
+
}
|
|
34755
|
+
function runMergeIdentityCli(args, deps = {}) {
|
|
34756
|
+
const options = parseMergeIdentityArgs(args);
|
|
34757
|
+
const dbPath = options.dbPath ?? join21(getMagicContextStorageDir(), "context.db");
|
|
34758
|
+
const storageDir = dirname13(dbPath);
|
|
34759
|
+
const hostPath = options.hostPath ?? (options.dbPath ? join21(storageDir, "host.db") : resolveOpenCodeDbPath().path);
|
|
34760
|
+
let db = openExistingContextDatabase(dbPath, {
|
|
34761
|
+
readonly: true,
|
|
34762
|
+
minimumSupportedVersion: CLI_SCHEMA_FLOOR_VERSION
|
|
34763
|
+
});
|
|
34764
|
+
if (!db)
|
|
34765
|
+
throw new Error(`Context database does not exist: ${dbPath}`);
|
|
34766
|
+
let directories = [];
|
|
34767
|
+
try {
|
|
34768
|
+
const observed = observations(db, hostPath, storageDir);
|
|
34769
|
+
if (!options.from || !options.to) {
|
|
34770
|
+
for (const split of observed.filter((row) => row.identities.length > 1)) {
|
|
34771
|
+
const target = resolveReadOnly(split.directory) ?? split.identities.map((row) => row.identity).filter((id) => id.startsWith("git:")).sort()[0];
|
|
34772
|
+
console.log(`Project identity split: ${split.directory}`);
|
|
34773
|
+
for (const row of split.identities)
|
|
34774
|
+
if (row.identity !== target)
|
|
34775
|
+
console.log(` ${row.identity} → ${target ?? "unresolved target"}`);
|
|
34776
|
+
}
|
|
34777
|
+
if (!observed.some((row) => row.identities.length > 1))
|
|
34778
|
+
console.log("No detected identity splits.");
|
|
34779
|
+
return 0;
|
|
34780
|
+
}
|
|
34781
|
+
if (options.from === options.to)
|
|
34782
|
+
throw new Error(`Source and target identities must differ: ${options.from}`);
|
|
34783
|
+
for (const identity of [options.from, options.to]) {
|
|
34784
|
+
const known = auditIdentityMerge(db, identity, options.to).changedRows > 0 || db.prepare("SELECT 1 FROM v22_identity_rekey_map WHERE old_project_path = ? OR new_project_path = ?").get(identity, identity);
|
|
34785
|
+
if (!known)
|
|
34786
|
+
throw new Error(`Unknown identity: ${identity}`);
|
|
34787
|
+
}
|
|
34788
|
+
const sourceDirs = observed.filter((row) => row.identities.some((item) => item.identity === options.from)).map((row) => row.directory);
|
|
34789
|
+
const targetDirs = observed.filter((row) => row.identities.some((item) => item.identity === options.to)).map((row) => row.directory);
|
|
34790
|
+
directories = [...new Set([...sourceDirs, ...targetDirs])];
|
|
34791
|
+
const alreadyMerged = auditIdentityMerge(db, options.from, options.to).changedRows === 0 && db.prepare("SELECT 1 FROM v22_identity_rekey_map WHERE old_project_path = ? AND new_project_path = ?").get(options.from, options.to);
|
|
34792
|
+
if (!alreadyMerged && options.from.startsWith("git:") && options.to.startsWith("git:") && (!sourceDirs.length || !targetDirs.length || sourceDirs.some((dir) => !targetDirs.includes(dir)) || targetDirs.some((dir) => !sourceDirs.includes(dir))))
|
|
34793
|
+
throw new Error(`Refusing different directories for ${options.from} (${sourceDirs.join(", ") || "unknown"}) and ${options.to} (${targetDirs.join(", ") || "unknown"})`);
|
|
34794
|
+
if (!options.force && !directories.some((directory) => resolveReadOnly(directory) === options.to))
|
|
34795
|
+
throw new Error(`Target ${options.to} does not resolve for any observed directory on this machine; use --force only after reviewing the identity.`);
|
|
34796
|
+
const preview = mergeProjectIdentities(db, options.from, options.to, { dryRun: true });
|
|
34797
|
+
printReport(preview);
|
|
34798
|
+
if (options.dryRun)
|
|
34799
|
+
return 0;
|
|
34800
|
+
} finally {
|
|
34801
|
+
db.close();
|
|
34802
|
+
}
|
|
34803
|
+
const { from, to } = options;
|
|
34804
|
+
if (!from || !to)
|
|
34805
|
+
return 0;
|
|
34806
|
+
const holders = (deps.inspectHolders ?? defaultInspectHolders)(storageDir);
|
|
34807
|
+
const probe = (deps.probe ?? probeHostProcessesUsing)({
|
|
34808
|
+
files: [dbPath, `${dbPath}-wal`, `${dbPath}-shm`],
|
|
34809
|
+
directories: []
|
|
34810
|
+
});
|
|
34811
|
+
if (!holders.safe || probe.status !== "free")
|
|
34812
|
+
throw new Error(`Refusing merge: close OpenCode, Pi, OpenCode 2 and ck-mc. ${holders.blockers.join(", ")} ${holders.uncertainty ?? ""} ${probe.status === "in_use" ? `context.db holders: ${probe.pids.join(", ")}` : probe.status === "unknown" ? probe.reason : ""}`);
|
|
34813
|
+
const backup = mkdtempSync(join21(storageDir, "identity-merge-backup-"));
|
|
34814
|
+
const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
34815
|
+
console.log(`Backup directory: ${backup}`);
|
|
34816
|
+
console.log(`Restore with hosts closed: rm -f ${quote(`${dbPath}-wal`)} ${quote(`${dbPath}-shm`)}; cp ${quote(join21(backup, "context.db"))} ${quote(dbPath)}; if test -f ${quote(join21(backup, "context.db-wal"))}; then cp ${quote(join21(backup, "context.db-wal"))} ${quote(`${dbPath}-wal`)}; fi`);
|
|
34817
|
+
const sidecarRoot = join21(storageDir, "project-identities");
|
|
34818
|
+
const sidecarBackup = join21(backup, "project-identities");
|
|
34819
|
+
mkdirSync8(sidecarBackup);
|
|
34820
|
+
if (existsSync25(sidecarRoot))
|
|
34821
|
+
cpSync2(sidecarRoot, sidecarBackup, { recursive: true });
|
|
34822
|
+
console.log(`Restore identity sidecars too: rm -rf ${quote(sidecarRoot)}; cp -R ${quote(sidecarBackup)} ${quote(sidecarRoot)}`);
|
|
34823
|
+
copyDatabaseBundle(dbPath, join21(backup, "context.db"));
|
|
34824
|
+
db = openExistingDatabase(dbPath, { readonly: false });
|
|
34825
|
+
if (!db)
|
|
34826
|
+
throw new Error(`Context database disappeared: ${dbPath}`);
|
|
34827
|
+
try {
|
|
34828
|
+
printReport(mergeProjectIdentities(db, from, to));
|
|
34829
|
+
} finally {
|
|
34830
|
+
db.close();
|
|
34831
|
+
}
|
|
34832
|
+
if (to.startsWith("git:"))
|
|
34833
|
+
for (const directory of directories) {
|
|
34834
|
+
const root = join21(storageDir, "project-identities");
|
|
34835
|
+
mkdirSync8(root, { recursive: true });
|
|
34836
|
+
const path = join21(root, `${createHash5("sha256").update(projectDirectoryKey(directory)).digest("hex")}.json`);
|
|
34837
|
+
const temporary = `${path}.merge.tmp`;
|
|
34838
|
+
writeFileSync7(temporary, JSON.stringify({ directory: projectDirectoryKey(directory), identity: options.to }), { mode: 384 });
|
|
34839
|
+
renameSync6(temporary, path);
|
|
34840
|
+
}
|
|
34841
|
+
return 0;
|
|
34842
|
+
}
|
|
34843
|
+
var init_doctor_merge_identity = __esm(async () => {
|
|
34844
|
+
init_project_identity_cache();
|
|
34845
|
+
init_storage_identity_merge();
|
|
34846
|
+
init_data_path();
|
|
34847
|
+
init_opencode_db_path();
|
|
34848
|
+
init_doctor_opencode2_cache();
|
|
34849
|
+
await __promiseAll([
|
|
34850
|
+
init_database_access(),
|
|
34851
|
+
init_doctor_identity_splits(),
|
|
34852
|
+
init_doctor_repair_db()
|
|
34853
|
+
]);
|
|
34854
|
+
});
|
|
34855
|
+
|
|
34243
34856
|
// src/commands/doctor-hidden-sessions.ts
|
|
34244
34857
|
function parseMetadata(value) {
|
|
34245
34858
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -34330,20 +34943,20 @@ var init_migration_paths = __esm(() => {
|
|
|
34330
34943
|
});
|
|
34331
34944
|
|
|
34332
34945
|
// src/commands/migrate.ts
|
|
34333
|
-
import { createHash as
|
|
34334
|
-
import { existsSync as
|
|
34335
|
-
import { dirname as
|
|
34946
|
+
import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
|
|
34947
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync9, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
|
|
34948
|
+
import { dirname as dirname14, join as join22 } from "node:path";
|
|
34336
34949
|
function defaultOpenCodeDbPath() {
|
|
34337
34950
|
return getOpenCodeDatabasePath();
|
|
34338
34951
|
}
|
|
34339
34952
|
function defaultCortexkitDbPath() {
|
|
34340
|
-
return
|
|
34953
|
+
return join22(getMagicContextStorageDir(), "context.db");
|
|
34341
34954
|
}
|
|
34342
34955
|
function defaultPiSessionsRoot() {
|
|
34343
34956
|
return getPiSessionsRoot();
|
|
34344
34957
|
}
|
|
34345
34958
|
function defaultFs() {
|
|
34346
|
-
return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync:
|
|
34959
|
+
return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync: existsSync26, renameSync: renameSync7, mkdirSync: mkdirSync9 };
|
|
34347
34960
|
}
|
|
34348
34961
|
function stmt(db, sql) {
|
|
34349
34962
|
return db.prepare(sql);
|
|
@@ -34370,7 +34983,7 @@ function shortId() {
|
|
|
34370
34983
|
return randomBytes2(4).toString("hex");
|
|
34371
34984
|
}
|
|
34372
34985
|
function migrationKeyFor(sourceSessionId, targetHarness) {
|
|
34373
|
-
return
|
|
34986
|
+
return createHash6("sha256").update(`${sourceSessionId}
|
|
34374
34987
|
${targetHarness}`).digest("hex");
|
|
34375
34988
|
}
|
|
34376
34989
|
function moduleManagedProjectForSession(db, sessionId) {
|
|
@@ -34409,7 +35022,7 @@ function sweepPendingMigrations(db, fs = defaultFs()) {
|
|
|
34409
35022
|
}
|
|
34410
35023
|
if (row.phase === "db_committed") {
|
|
34411
35024
|
if (fs.existsSync(row.stage_path)) {
|
|
34412
|
-
fs.mkdirSync(
|
|
35025
|
+
fs.mkdirSync(dirname14(row.final_path), { recursive: true });
|
|
34413
35026
|
fs.renameSync(row.stage_path, row.final_path);
|
|
34414
35027
|
stmt(db, "DELETE FROM migration_pending WHERE migration_key = ?").run(row.migration_key);
|
|
34415
35028
|
report.rolledForward += 1;
|
|
@@ -34439,7 +35052,7 @@ function claimJournalIdentity(args) {
|
|
|
34439
35052
|
migration_key, source_session_id, target_harness, pi_session_id,
|
|
34440
35053
|
final_path, stage_path, content_sha256, phase, created_at
|
|
34441
35054
|
) VALUES (?, ?, ?, ?, ?, ?, '', 'staged', ?)
|
|
34442
|
-
ON CONFLICT(migration_key) DO NOTHING`).run(args.migrationKey, args.sourceSessionId, args.targetHarness, piSessionId, args.finalPathFor(piSessionId),
|
|
35055
|
+
ON CONFLICT(migration_key) DO NOTHING`).run(args.migrationKey, args.sourceSessionId, args.targetHarness, piSessionId, args.finalPathFor(piSessionId), join22(args.stageDir, `${args.migrationKey}.jsonl`), args.now);
|
|
34443
35056
|
const row = readPendingMigration(args.db, args.migrationKey);
|
|
34444
35057
|
if (!row) {
|
|
34445
35058
|
throw new Error("migration journal row disappeared during insert; aborting migration");
|
|
@@ -34944,7 +35557,7 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
34944
35557
|
const provider = opts.provider ?? model.provider;
|
|
34945
35558
|
const modelId = opts.modelId ?? model.modelId;
|
|
34946
35559
|
const cwd = session.directory ?? session.path ?? process.cwd();
|
|
34947
|
-
const outputDir =
|
|
35560
|
+
const outputDir = join22(piSessionsRoot, projectPathToPiDirSlug(cwd));
|
|
34948
35561
|
const targetHarness = opts.targetHarness ?? "pi";
|
|
34949
35562
|
const moduleManagedProject = cortexkitDb === null ? null : moduleManagedProjectForSession(cortexkitDb, session.id);
|
|
34950
35563
|
if (moduleManagedProject) {
|
|
@@ -34968,8 +35581,8 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
34968
35581
|
migrationKey,
|
|
34969
35582
|
sourceSessionId: session.id,
|
|
34970
35583
|
targetHarness,
|
|
34971
|
-
finalPathFor: (id) =>
|
|
34972
|
-
stageDir:
|
|
35584
|
+
finalPathFor: (id) => join22(outputDir, `${formatPiFilenameTimestamp(now)}_${id}.jsonl`),
|
|
35585
|
+
stageDir: join22(dirname14(piSessionsRoot), MIGRATION_STAGE_DIRNAME),
|
|
34973
35586
|
now: now.getTime()
|
|
34974
35587
|
});
|
|
34975
35588
|
piSessionId = claimed.row.pi_session_id;
|
|
@@ -34978,7 +35591,7 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
34978
35591
|
journalResumed = claimed.resumed;
|
|
34979
35592
|
} else {
|
|
34980
35593
|
piSessionId = generateUuidV7(now);
|
|
34981
|
-
finalPath =
|
|
35594
|
+
finalPath = join22(outputDir, `${formatPiFilenameTimestamp(now)}_${piSessionId}.jsonl`);
|
|
34982
35595
|
stagePath = "";
|
|
34983
35596
|
}
|
|
34984
35597
|
const buildResult = buildPiEntries({
|
|
@@ -35017,11 +35630,11 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
35017
35630
|
`;
|
|
35018
35631
|
if (!opts.dryRun) {
|
|
35019
35632
|
if (journalActive && cortexkitDb !== null && migrationKey !== undefined && plan) {
|
|
35020
|
-
const contentSha256 =
|
|
35633
|
+
const contentSha256 = createHash6("sha256").update(jsonl, "utf8").digest("hex");
|
|
35021
35634
|
commitStagedChecksum(cortexkitDb, migrationKey, contentSha256);
|
|
35022
35635
|
fs.writeFileAtomic(stagePath, jsonl);
|
|
35023
35636
|
plan.commit(migrationKey);
|
|
35024
|
-
fs.mkdirSync(
|
|
35637
|
+
fs.mkdirSync(dirname14(finalPath), { recursive: true });
|
|
35025
35638
|
fs.renameSync(stagePath, finalPath);
|
|
35026
35639
|
stmt(cortexkitDb, "DELETE FROM migration_pending WHERE migration_key = ?").run(migrationKey);
|
|
35027
35640
|
} else {
|
|
@@ -35291,9 +35904,9 @@ var init_relocate_memory = __esm(() => {
|
|
|
35291
35904
|
});
|
|
35292
35905
|
|
|
35293
35906
|
// src/commands/migrate-session.ts
|
|
35294
|
-
import { existsSync as
|
|
35295
|
-
import { homedir as
|
|
35296
|
-
import
|
|
35907
|
+
import { existsSync as existsSync27, realpathSync as realpathSync5 } from "node:fs";
|
|
35908
|
+
import { homedir as homedir15 } from "node:os";
|
|
35909
|
+
import path5, { join as join23 } from "node:path";
|
|
35297
35910
|
function existingSessionColumns(db) {
|
|
35298
35911
|
const rows = db.prepare("PRAGMA table_info(session)").all();
|
|
35299
35912
|
return new Set(rows.map((r) => r.name).filter((n) => typeof n === "string"));
|
|
@@ -35377,7 +35990,7 @@ function planMigrateSession(sessionId, rawTargetDirectory, deps) {
|
|
|
35377
35990
|
ocProjectId = "global";
|
|
35378
35991
|
ocWorktree = globalRow.worktree || "/";
|
|
35379
35992
|
}
|
|
35380
|
-
const sessionPath =
|
|
35993
|
+
const sessionPath = path5.relative(ocWorktree, targetDirectory);
|
|
35381
35994
|
const ownershipRow = deps.contextDb.prepare("SELECT project_path FROM session_projects WHERE session_id = ? AND harness = 'opencode'").get(sessionId);
|
|
35382
35995
|
const fromMcIdentity = ownershipRow?.project_path ?? (sessionRow.directory ? deps.resolveIdentity(sessionRow.directory) : "");
|
|
35383
35996
|
const toMcIdentity = deps.resolveIdentity(targetDirectory);
|
|
@@ -35503,18 +36116,18 @@ function defaultOpenCodeDbPath2() {
|
|
|
35503
36116
|
return getOpenCodeDatabasePath();
|
|
35504
36117
|
}
|
|
35505
36118
|
function defaultContextDbPath() {
|
|
35506
|
-
return
|
|
36119
|
+
return join23(getMagicContextStorageDir(), "context.db");
|
|
35507
36120
|
}
|
|
35508
36121
|
function realDeps(opencodeDb, contextDb) {
|
|
35509
36122
|
return {
|
|
35510
36123
|
opencodeDb,
|
|
35511
36124
|
contextDb,
|
|
35512
36125
|
resolveIdentity: resolveProjectIdentity,
|
|
35513
|
-
hasGitDir: (dir) =>
|
|
35514
|
-
realpath: (p) =>
|
|
36126
|
+
hasGitDir: (dir) => existsSync27(join23(dir, ".git")),
|
|
36127
|
+
realpath: (p) => realpathSync5(p)
|
|
35515
36128
|
};
|
|
35516
36129
|
}
|
|
35517
|
-
function
|
|
36130
|
+
function valueAfter(args, flag) {
|
|
35518
36131
|
const index = args.indexOf(flag);
|
|
35519
36132
|
if (index === -1)
|
|
35520
36133
|
return null;
|
|
@@ -35568,11 +36181,11 @@ async function runMigrateSessionCli(args) {
|
|
|
35568
36181
|
printMigrateSessionHelp();
|
|
35569
36182
|
return 0;
|
|
35570
36183
|
}
|
|
35571
|
-
const sessionId =
|
|
35572
|
-
const toDir =
|
|
36184
|
+
const sessionId = valueAfter(args, "--session");
|
|
36185
|
+
const toDir = valueAfter(args, "--to");
|
|
35573
36186
|
const dryRun = args.includes("--dry-run");
|
|
35574
36187
|
const skipConfirm = args.includes("--yes");
|
|
35575
|
-
const memoriesFlag =
|
|
36188
|
+
const memoriesFlag = valueAfter(args, "--memories");
|
|
35576
36189
|
if (!sessionId) {
|
|
35577
36190
|
console.error("Missing required flag: --session <id>");
|
|
35578
36191
|
printMigrateSessionHelp();
|
|
@@ -35588,8 +36201,8 @@ async function runMigrateSessionCli(args) {
|
|
|
35588
36201
|
printMigrateSessionHelp();
|
|
35589
36202
|
return 1;
|
|
35590
36203
|
}
|
|
35591
|
-
const expandedTo = toDir.startsWith("~") ?
|
|
35592
|
-
if (!
|
|
36204
|
+
const expandedTo = toDir.startsWith("~") ? join23(homedir15(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
|
|
36205
|
+
if (!existsSync27(expandedTo)) {
|
|
35593
36206
|
console.error(`Target directory does not exist: ${expandedTo}`);
|
|
35594
36207
|
return 1;
|
|
35595
36208
|
}
|
|
@@ -35741,9 +36354,9 @@ var init_migrate_session = __esm(async () => {
|
|
|
35741
36354
|
});
|
|
35742
36355
|
|
|
35743
36356
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
35744
|
-
import { createHash as
|
|
35745
|
-
import { realpathSync as
|
|
35746
|
-
import
|
|
36357
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
36358
|
+
import { realpathSync as realpathSync6 } from "node:fs";
|
|
36359
|
+
import path6 from "node:path";
|
|
35747
36360
|
function readMeta(db, key) {
|
|
35748
36361
|
const row = db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(key);
|
|
35749
36362
|
return row?.value ?? null;
|
|
@@ -35764,7 +36377,7 @@ function countFailures(db) {
|
|
|
35764
36377
|
function classifyBackfillError(error) {
|
|
35765
36378
|
if (error instanceof ProjectIdentityError) {
|
|
35766
36379
|
return {
|
|
35767
|
-
errorClass: error.errorClass === "dubious_ownership" ? "unknown" : error.errorClass,
|
|
36380
|
+
errorClass: error.errorClass === "dubious_ownership" || error.errorClass === "home_project_disabled" || error.errorClass === "git_identity_unavailable" ? "unknown" : error.errorClass,
|
|
35768
36381
|
errorMessage: error.message
|
|
35769
36382
|
};
|
|
35770
36383
|
}
|
|
@@ -35786,11 +36399,11 @@ function resolveBackfillIdentity(rawProjectPath) {
|
|
|
35786
36399
|
function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
35787
36400
|
let canonical;
|
|
35788
36401
|
try {
|
|
35789
|
-
canonical =
|
|
36402
|
+
canonical = realpathSync6(rawProjectPath);
|
|
35790
36403
|
} catch {
|
|
35791
|
-
canonical =
|
|
36404
|
+
canonical = path6.isAbsolute(rawProjectPath) ? rawProjectPath : path6.join(process.cwd(), rawProjectPath);
|
|
35792
36405
|
}
|
|
35793
|
-
return `dir:${
|
|
36406
|
+
return `dir:${createHash7("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
35794
36407
|
}
|
|
35795
36408
|
function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
|
|
35796
36409
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
@@ -36011,7 +36624,7 @@ var init_tick_failure = __esm(() => {
|
|
|
36011
36624
|
});
|
|
36012
36625
|
|
|
36013
36626
|
// ../pi-plugin/src/config/index.ts
|
|
36014
|
-
import { existsSync as
|
|
36627
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
36015
36628
|
function getProjectConfigPaths(cwd) {
|
|
36016
36629
|
const basePath = cortexKitProjectConfigBasePath(cwd);
|
|
36017
36630
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
@@ -36021,10 +36634,10 @@ function getUserConfigPaths() {
|
|
|
36021
36634
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
36022
36635
|
}
|
|
36023
36636
|
function resolveFirstExisting(paths) {
|
|
36024
|
-
return paths.find((path) =>
|
|
36637
|
+
return paths.find((path) => existsSync28(path));
|
|
36025
36638
|
}
|
|
36026
36639
|
function resolvePiLegacyFallback(sources) {
|
|
36027
|
-
return sources.find((source) =>
|
|
36640
|
+
return sources.find((source) => existsSync28(source.path)) ?? null;
|
|
36028
36641
|
}
|
|
36029
36642
|
function loadConfigFile(path, scope) {
|
|
36030
36643
|
let raw;
|
|
@@ -36319,7 +36932,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
|
|
|
36319
36932
|
if (loaded)
|
|
36320
36933
|
loadedFiles.push(loaded);
|
|
36321
36934
|
}
|
|
36322
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
36935
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync28(source.path));
|
|
36323
36936
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
36324
36937
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
36325
36938
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -36328,7 +36941,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
|
|
|
36328
36941
|
if (loaded)
|
|
36329
36942
|
loadedFiles.push(loaded);
|
|
36330
36943
|
}
|
|
36331
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
36944
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync28(source.path));
|
|
36332
36945
|
if (userLegacyFallback) {
|
|
36333
36946
|
warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
|
|
36334
36947
|
} else if (legacyUserUnmigrated) {
|
|
@@ -36450,10 +37063,11 @@ var DATABASE_REPAIR_COMMAND = "bunx @cortexkit/magic-context@latest doctor repai
|
|
|
36450
37063
|
|
|
36451
37064
|
// src/lib/github-issue.ts
|
|
36452
37065
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
36453
|
-
import { readFileSync as
|
|
37066
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
36454
37067
|
function runGhCommand(args) {
|
|
36455
37068
|
try {
|
|
36456
37069
|
const result = spawnSync5("gh", args, {
|
|
37070
|
+
windowsHide: true,
|
|
36457
37071
|
encoding: "utf-8",
|
|
36458
37072
|
stdio: ["ignore", "pipe", "pipe"]
|
|
36459
37073
|
});
|
|
@@ -36476,7 +37090,7 @@ function failed(result) {
|
|
|
36476
37090
|
function submitGithubIssue(title, bodyPath, runner = runGhCommand) {
|
|
36477
37091
|
let body;
|
|
36478
37092
|
try {
|
|
36479
|
-
body =
|
|
37093
|
+
body = readFileSync18(bodyPath, "utf-8");
|
|
36480
37094
|
} catch (error) {
|
|
36481
37095
|
return {
|
|
36482
37096
|
ok: false,
|
|
@@ -36534,9 +37148,9 @@ var MAX_GITHUB_ISSUE_BODY_CHARS = 65536;
|
|
|
36534
37148
|
var init_github_issue = () => {};
|
|
36535
37149
|
|
|
36536
37150
|
// src/lib/log-lines.ts
|
|
36537
|
-
import { existsSync as
|
|
37151
|
+
import { existsSync as existsSync29, readFileSync as readFileSync19, statSync as statSync12 } from "node:fs";
|
|
36538
37152
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
36539
|
-
import { join as
|
|
37153
|
+
import { join as join24 } from "node:path";
|
|
36540
37154
|
function tokenize(input, limit = Number.POSITIVE_INFINITY) {
|
|
36541
37155
|
const tokens = [];
|
|
36542
37156
|
let index = 0;
|
|
@@ -36822,20 +37436,20 @@ function parseLogLine(line) {
|
|
|
36822
37436
|
}
|
|
36823
37437
|
function getMagicContextLogPaths(harness, options = {}) {
|
|
36824
37438
|
const override = options.override === undefined ? process.env.MAGIC_CONTEXT_LOG_PATH?.trim() : options.override?.trim();
|
|
36825
|
-
const storageLogs =
|
|
37439
|
+
const storageLogs = join24(options.storageDir ?? getMagicContextStorageDir(), "logs");
|
|
36826
37440
|
return [
|
|
36827
37441
|
...override ? [override] : [],
|
|
36828
|
-
|
|
36829
|
-
|
|
36830
|
-
|
|
37442
|
+
join24(options.tempDir ?? tmpdir2(), harness, "magic-context", "magic-context.log"),
|
|
37443
|
+
join24(storageLogs, `magic-context.${harness}.log`),
|
|
37444
|
+
join24(storageLogs, "magic-context.log")
|
|
36831
37445
|
].filter((path, index, paths) => paths.indexOf(path) === index);
|
|
36832
37446
|
}
|
|
36833
37447
|
function inspectLogFile(path) {
|
|
36834
|
-
if (!
|
|
37448
|
+
if (!existsSync29(path)) {
|
|
36835
37449
|
return { path, exists: false, sizeKb: 0, lineCount: 0, grammar: "unknown" };
|
|
36836
37450
|
}
|
|
36837
37451
|
try {
|
|
36838
|
-
const content =
|
|
37452
|
+
const content = readFileSync19(path, "utf8");
|
|
36839
37453
|
const lines = content.split(/\r?\n/).filter((line) => line.length > 0);
|
|
36840
37454
|
const grammars = new Set(lines.flatMap((line) => {
|
|
36841
37455
|
const parsed = parseLogLine(line);
|
|
@@ -36862,7 +37476,7 @@ function readLogLines(files) {
|
|
|
36862
37476
|
return [];
|
|
36863
37477
|
try {
|
|
36864
37478
|
let precedingTimestamp = "";
|
|
36865
|
-
return
|
|
37479
|
+
return readFileSync19(file.path, "utf8").split(/\r?\n/).filter((line) => line.length > 0).map((line, lineIndex) => {
|
|
36866
37480
|
precedingTimestamp = parseLogLine(line)?.ts ?? precedingTimestamp;
|
|
36867
37481
|
return { line, timestamp: precedingTimestamp, fileIndex, lineIndex };
|
|
36868
37482
|
});
|
|
@@ -36911,10 +37525,10 @@ var init_redaction2 = __esm(() => {
|
|
|
36911
37525
|
});
|
|
36912
37526
|
|
|
36913
37527
|
// src/commands/doctor-omp.ts
|
|
36914
|
-
import { execFileSync as
|
|
36915
|
-
import { existsSync as
|
|
37528
|
+
import { execFileSync as execFileSync6, spawnSync as spawnSync6 } from "node:child_process";
|
|
37529
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync10, readFileSync as readFileSync20 } from "node:fs";
|
|
36916
37530
|
import { createRequire as createRequire3 } from "node:module";
|
|
36917
|
-
import { dirname as
|
|
37531
|
+
import { dirname as dirname15, join as join25, resolve as resolve8 } from "node:path";
|
|
36918
37532
|
function parseSemver(value) {
|
|
36919
37533
|
const match = value?.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
36920
37534
|
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
@@ -36956,10 +37570,10 @@ function selfVersion() {
|
|
|
36956
37570
|
return "unknown";
|
|
36957
37571
|
}
|
|
36958
37572
|
function readConfig2(path) {
|
|
36959
|
-
if (!
|
|
37573
|
+
if (!existsSync30(path))
|
|
36960
37574
|
return {};
|
|
36961
37575
|
try {
|
|
36962
|
-
const parsed = import_comment_json7.parse(
|
|
37576
|
+
const parsed = import_comment_json7.parse(readFileSync20(path, "utf-8"));
|
|
36963
37577
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? {} : { error: "top level is not an object" };
|
|
36964
37578
|
} catch (error) {
|
|
36965
37579
|
return { error: error instanceof Error ? error.message : String(error) };
|
|
@@ -36969,7 +37583,7 @@ function pluginDeclaresOmp(path) {
|
|
|
36969
37583
|
if (!path)
|
|
36970
37584
|
return null;
|
|
36971
37585
|
try {
|
|
36972
|
-
const pkg = JSON.parse(
|
|
37586
|
+
const pkg = JSON.parse(readFileSync20(join25(path, "package.json"), "utf-8"));
|
|
36973
37587
|
return Array.isArray(pkg.omp?.extensions) || Array.isArray(pkg.pi?.extensions);
|
|
36974
37588
|
} catch {
|
|
36975
37589
|
return null;
|
|
@@ -37050,7 +37664,7 @@ async function runHealthChecks(options) {
|
|
|
37050
37664
|
}
|
|
37051
37665
|
}
|
|
37052
37666
|
const userConfigPath = getOmpUserConfigPath();
|
|
37053
|
-
if (!
|
|
37667
|
+
if (!existsSync30(userConfigPath)) {
|
|
37054
37668
|
add(results, "warn", `No Magic Context user config at ${userConfigPath}`);
|
|
37055
37669
|
repairPlan.writeUserConfig = true;
|
|
37056
37670
|
} else {
|
|
@@ -37067,9 +37681,9 @@ async function runHealthChecks(options) {
|
|
|
37067
37681
|
for (const warning of loaded.warnings.slice(0, 5))
|
|
37068
37682
|
add(results, "warn", warning);
|
|
37069
37683
|
const storage = getMagicContextStorageResolution();
|
|
37070
|
-
const dbPath =
|
|
37684
|
+
const dbPath = join25(storage.path, "context.db");
|
|
37071
37685
|
add(results, "info", `Shared storage: ${storage.path} (source: ${storage.source})`);
|
|
37072
|
-
if (!
|
|
37686
|
+
if (!existsSync30(dbPath))
|
|
37073
37687
|
add(results, "info", `Shared context DB will be created at ${dbPath}`);
|
|
37074
37688
|
else {
|
|
37075
37689
|
let db = null;
|
|
@@ -37123,7 +37737,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
37123
37737
|
};
|
|
37124
37738
|
}
|
|
37125
37739
|
function writeDefaultConfig(path) {
|
|
37126
|
-
|
|
37740
|
+
mkdirSync10(dirname15(path), { recursive: true });
|
|
37127
37741
|
const config = {
|
|
37128
37742
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
37129
37743
|
...MagicContextConfigSchema.parse({})
|
|
@@ -37133,7 +37747,7 @@ function writeDefaultConfig(path) {
|
|
|
37133
37747
|
}
|
|
37134
37748
|
async function repair(plan, deps, prompts, cwd) {
|
|
37135
37749
|
let fixed = 0;
|
|
37136
|
-
if (plan.writeUserConfig && !
|
|
37750
|
+
if (plan.writeUserConfig && !existsSync30(getOmpUserConfigPath())) {
|
|
37137
37751
|
writeDefaultConfig(getOmpUserConfigPath());
|
|
37138
37752
|
prompts.log.success(`Wrote default Magic Context config to ${getOmpUserConfigPath()}`);
|
|
37139
37753
|
fixed += 1;
|
|
@@ -37175,6 +37789,7 @@ function timestamp2(date) {
|
|
|
37175
37789
|
function runGhCommandWithDeps(deps, args) {
|
|
37176
37790
|
if (args[0] === "issue") {
|
|
37177
37791
|
const result = deps.spawnSync("gh", args, {
|
|
37792
|
+
windowsHide: true,
|
|
37178
37793
|
encoding: "utf-8",
|
|
37179
37794
|
stdio: ["ignore", "pipe", "pipe"]
|
|
37180
37795
|
});
|
|
@@ -37186,6 +37801,7 @@ function runGhCommandWithDeps(deps, args) {
|
|
|
37186
37801
|
}
|
|
37187
37802
|
try {
|
|
37188
37803
|
const output = deps.execFileSync("gh", args, {
|
|
37804
|
+
windowsHide: true,
|
|
37189
37805
|
encoding: "utf-8",
|
|
37190
37806
|
stdio: ["ignore", "pipe", "pipe"]
|
|
37191
37807
|
});
|
|
@@ -37218,7 +37834,7 @@ async function runIssueFlow(options) {
|
|
|
37218
37834
|
...report.results.map((result) => `- ${result.status.toUpperCase()}: ${sanitizeDiagnosticText(result.message)}`)
|
|
37219
37835
|
].join(`
|
|
37220
37836
|
`);
|
|
37221
|
-
const path =
|
|
37837
|
+
const path = join25(options.cwd, `magic-context-omp-issue-${timestamp2(options.deps.now())}.md`);
|
|
37222
37838
|
writeFileAtomic(path, `${body}
|
|
37223
37839
|
`);
|
|
37224
37840
|
options.prompts.log.success(`Sanitized report written to ${path}`);
|
|
@@ -37289,7 +37905,7 @@ var init_doctor_omp = __esm(async () => {
|
|
|
37289
37905
|
openExistingContextDatabase,
|
|
37290
37906
|
now: () => new Date,
|
|
37291
37907
|
inspectMagicContextLogs,
|
|
37292
|
-
execFileSync:
|
|
37908
|
+
execFileSync: execFileSync6,
|
|
37293
37909
|
spawnSync: spawnSync6
|
|
37294
37910
|
};
|
|
37295
37911
|
});
|
|
@@ -37406,7 +38022,7 @@ function truncate(text) {
|
|
|
37406
38022
|
var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
|
|
37407
38023
|
|
|
37408
38024
|
// ../plugin/src/features/magic-context/memory/embedding-synapse.ts
|
|
37409
|
-
import { createHash as
|
|
38025
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
37410
38026
|
function toSynapseLaneDescriptor(metadata) {
|
|
37411
38027
|
const tokenBudget = metadata.recommended_token_budget;
|
|
37412
38028
|
return {
|
|
@@ -37546,7 +38162,7 @@ function wait(ms) {
|
|
|
37546
38162
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
37547
38163
|
}
|
|
37548
38164
|
function sha256(value) {
|
|
37549
|
-
return
|
|
38165
|
+
return createHash8("sha256").update(value).digest("hex");
|
|
37550
38166
|
}
|
|
37551
38167
|
function stableJson2(value) {
|
|
37552
38168
|
if (Array.isArray(value))
|
|
@@ -38190,12 +38806,12 @@ function listShadowBackfillStalls(db, projectIdentity) {
|
|
|
38190
38806
|
var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
|
|
38191
38807
|
|
|
38192
38808
|
// ../plugin/src/shared/auto-update-provenance.ts
|
|
38193
|
-
import { existsSync as
|
|
38809
|
+
import { existsSync as existsSync31, readFileSync as readFileSync21 } from "node:fs";
|
|
38194
38810
|
function readAutoUpdateCheckState(path) {
|
|
38195
|
-
if (!
|
|
38811
|
+
if (!existsSync31(path))
|
|
38196
38812
|
return null;
|
|
38197
38813
|
try {
|
|
38198
|
-
const value = JSON.parse(
|
|
38814
|
+
const value = JSON.parse(readFileSync21(path, "utf-8"));
|
|
38199
38815
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
38200
38816
|
return null;
|
|
38201
38817
|
const raw = value;
|
|
@@ -38223,14 +38839,14 @@ var init_auto_update_provenance = () => {};
|
|
|
38223
38839
|
// ../plugin/src/shared/tui-config.ts
|
|
38224
38840
|
import {
|
|
38225
38841
|
chmodSync as chmodSync5,
|
|
38226
|
-
existsSync as
|
|
38227
|
-
mkdirSync as
|
|
38228
|
-
readFileSync as
|
|
38229
|
-
renameSync as
|
|
38842
|
+
existsSync as existsSync32,
|
|
38843
|
+
mkdirSync as mkdirSync11,
|
|
38844
|
+
readFileSync as readFileSync22,
|
|
38845
|
+
renameSync as renameSync8,
|
|
38230
38846
|
statSync as statSync13,
|
|
38231
|
-
writeFileSync as
|
|
38847
|
+
writeFileSync as writeFileSync8
|
|
38232
38848
|
} from "node:fs";
|
|
38233
|
-
import { dirname as
|
|
38849
|
+
import { dirname as dirname16, join as join26 } from "node:path";
|
|
38234
38850
|
function pluginEntryId(entry) {
|
|
38235
38851
|
if (typeof entry === "string")
|
|
38236
38852
|
return entry;
|
|
@@ -38261,21 +38877,21 @@ function writeTuiConfigAtomic(configPath, config) {
|
|
|
38261
38877
|
const body = `${import_comment_json8.stringify(config, null, 2)}
|
|
38262
38878
|
`;
|
|
38263
38879
|
const tmpPath = `${configPath}.tmp`;
|
|
38264
|
-
|
|
38880
|
+
writeFileSync8(tmpPath, body);
|
|
38265
38881
|
try {
|
|
38266
38882
|
if (statSync13(configPath, { throwIfNoEntry: false })?.isFile()) {
|
|
38267
38883
|
chmodSync5(tmpPath, statSync13(configPath).mode & 511);
|
|
38268
38884
|
}
|
|
38269
38885
|
} catch {}
|
|
38270
|
-
|
|
38886
|
+
renameSync8(tmpPath, configPath);
|
|
38271
38887
|
}
|
|
38272
38888
|
function resolveTuiConfigPath(configDirOverride) {
|
|
38273
38889
|
const configDir = configDirOverride ?? getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
38274
|
-
const jsoncPath =
|
|
38275
|
-
const jsonPath =
|
|
38276
|
-
if (
|
|
38890
|
+
const jsoncPath = join26(configDir, "tui.jsonc");
|
|
38891
|
+
const jsonPath = join26(configDir, "tui.json");
|
|
38892
|
+
if (existsSync32(jsoncPath))
|
|
38277
38893
|
return jsoncPath;
|
|
38278
|
-
if (
|
|
38894
|
+
if (existsSync32(jsonPath))
|
|
38279
38895
|
return jsonPath;
|
|
38280
38896
|
return jsoncPath;
|
|
38281
38897
|
}
|
|
@@ -38283,8 +38899,8 @@ function ensureTuiPluginEntry(options = {}) {
|
|
|
38283
38899
|
try {
|
|
38284
38900
|
const configPath = resolveTuiConfigPath(options.configDir);
|
|
38285
38901
|
let config = {};
|
|
38286
|
-
if (
|
|
38287
|
-
const raw =
|
|
38902
|
+
if (existsSync32(configPath)) {
|
|
38903
|
+
const raw = readFileSync22(configPath, "utf-8");
|
|
38288
38904
|
config = import_comment_json8.parse(raw) ?? {};
|
|
38289
38905
|
}
|
|
38290
38906
|
const plugins = Array.isArray(config.plugin) ? [...config.plugin] : [];
|
|
@@ -38318,7 +38934,7 @@ function ensureTuiPluginEntry(options = {}) {
|
|
|
38318
38934
|
}
|
|
38319
38935
|
}
|
|
38320
38936
|
config.plugin = plugins;
|
|
38321
|
-
|
|
38937
|
+
mkdirSync11(dirname16(configPath), { recursive: true });
|
|
38322
38938
|
writeTuiConfigAtomic(configPath, config);
|
|
38323
38939
|
log3(`[magic-context] updated TUI plugin entry in ${configPath}`);
|
|
38324
38940
|
return true;
|
|
@@ -38336,9 +38952,9 @@ var init_tui_config = __esm(() => {
|
|
|
38336
38952
|
});
|
|
38337
38953
|
|
|
38338
38954
|
// src/lib/diagnostics-opencode.ts
|
|
38339
|
-
import { existsSync as
|
|
38955
|
+
import { existsSync as existsSync33, readdirSync as readdirSync6, readFileSync as readFileSync23, statSync as statSync14 } from "node:fs";
|
|
38340
38956
|
import { createRequire as createRequire4 } from "node:module";
|
|
38341
|
-
import { join as
|
|
38957
|
+
import { join as join27 } from "node:path";
|
|
38342
38958
|
function getSelfVersion() {
|
|
38343
38959
|
const require2 = createRequire4(import.meta.url);
|
|
38344
38960
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
@@ -38353,7 +38969,7 @@ function getSelfVersion() {
|
|
|
38353
38969
|
}
|
|
38354
38970
|
function readLegacyCachedVersion(root) {
|
|
38355
38971
|
try {
|
|
38356
|
-
const pkg = JSON.parse(
|
|
38972
|
+
const pkg = JSON.parse(readFileSync23(getOpenCodePluginPackageJsonPath(root), "utf-8"));
|
|
38357
38973
|
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
38358
38974
|
} catch {
|
|
38359
38975
|
return;
|
|
@@ -38362,7 +38978,7 @@ function readLegacyCachedVersion(root) {
|
|
|
38362
38978
|
function collectOpenCodePluginCacheReport(hostGeneration, opencodeConfig) {
|
|
38363
38979
|
const installs = [];
|
|
38364
38980
|
for (const root of getOpenCodePluginCacheRoots()) {
|
|
38365
|
-
if (!
|
|
38981
|
+
if (!existsSync33(root))
|
|
38366
38982
|
continue;
|
|
38367
38983
|
const spec = root.endsWith("@latest") ? "latest" : "(bare)";
|
|
38368
38984
|
installs.push({
|
|
@@ -38396,7 +39012,7 @@ function getStorageResolution() {
|
|
|
38396
39012
|
}
|
|
38397
39013
|
function fileSize(path) {
|
|
38398
39014
|
try {
|
|
38399
|
-
return
|
|
39015
|
+
return existsSync33(path) ? statSync14(path).size : 0;
|
|
38400
39016
|
} catch {
|
|
38401
39017
|
return 0;
|
|
38402
39018
|
}
|
|
@@ -38408,10 +39024,10 @@ function sanitizeValue(value) {
|
|
|
38408
39024
|
return sanitizeConfigValue(value);
|
|
38409
39025
|
}
|
|
38410
39026
|
function readConfig3(path) {
|
|
38411
|
-
if (!
|
|
39027
|
+
if (!existsSync33(path))
|
|
38412
39028
|
return { value: null };
|
|
38413
39029
|
try {
|
|
38414
|
-
const raw =
|
|
39030
|
+
const raw = readFileSync23(path, "utf-8");
|
|
38415
39031
|
const value = import_comment_json9.parse(raw);
|
|
38416
39032
|
return { value };
|
|
38417
39033
|
} catch (error) {
|
|
@@ -38436,7 +39052,7 @@ function configHasPluginEntry(config) {
|
|
|
38436
39052
|
}
|
|
38437
39053
|
function parseHistorianDumpMeta(path) {
|
|
38438
39054
|
try {
|
|
38439
|
-
const xml =
|
|
39055
|
+
const xml = readFileSync23(path, "utf-8");
|
|
38440
39056
|
const parsed = parseCompartmentOutput(xml);
|
|
38441
39057
|
const factCountByCategory = {};
|
|
38442
39058
|
for (const fact of parsed.facts) {
|
|
@@ -38469,11 +39085,11 @@ function parseHistorianDumpMeta(path) {
|
|
|
38469
39085
|
}
|
|
38470
39086
|
}
|
|
38471
39087
|
function listDumpsInDir(dir, limit) {
|
|
38472
|
-
if (!
|
|
39088
|
+
if (!existsSync33(dir))
|
|
38473
39089
|
return { count: 0, recent: [] };
|
|
38474
39090
|
try {
|
|
38475
|
-
const entries =
|
|
38476
|
-
const stat = statSync14(
|
|
39091
|
+
const entries = readdirSync6(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
39092
|
+
const stat = statSync14(join27(dir, name));
|
|
38477
39093
|
return {
|
|
38478
39094
|
name,
|
|
38479
39095
|
mtime: stat.mtimeMs,
|
|
@@ -38482,7 +39098,7 @@ function listDumpsInDir(dir, limit) {
|
|
|
38482
39098
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
38483
39099
|
const now = Date.now();
|
|
38484
39100
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
38485
|
-
const meta = parseHistorianDumpMeta(
|
|
39101
|
+
const meta = parseHistorianDumpMeta(join27(dir, entry.name));
|
|
38486
39102
|
const summary = {
|
|
38487
39103
|
name: entry.name,
|
|
38488
39104
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -38620,8 +39236,8 @@ async function collectRecentSessions(resolution, hostGeneration) {
|
|
|
38620
39236
|
}
|
|
38621
39237
|
}
|
|
38622
39238
|
async function collectHistorianFailures(storageDirPath) {
|
|
38623
|
-
const contextDbPath =
|
|
38624
|
-
if (!
|
|
39239
|
+
const contextDbPath = join27(storageDirPath, "context.db");
|
|
39240
|
+
if (!existsSync33(contextDbPath))
|
|
38625
39241
|
return [];
|
|
38626
39242
|
if (typeof globalThis.Bun === "undefined") {
|
|
38627
39243
|
return [];
|
|
@@ -38654,8 +39270,8 @@ async function collectHistorianFailures(storageDirPath) {
|
|
|
38654
39270
|
}
|
|
38655
39271
|
}
|
|
38656
39272
|
async function collectHistorianRuns(storageDirPath) {
|
|
38657
|
-
const contextDbPath =
|
|
38658
|
-
if (!
|
|
39273
|
+
const contextDbPath = join27(storageDirPath, "context.db");
|
|
39274
|
+
if (!existsSync33(contextDbPath))
|
|
38659
39275
|
return [];
|
|
38660
39276
|
if (typeof globalThis.Bun === "undefined")
|
|
38661
39277
|
return [];
|
|
@@ -38728,7 +39344,7 @@ async function collectDiagnostics() {
|
|
|
38728
39344
|
const magicContextConfig = readConfig3(configPaths.magicContextConfig);
|
|
38729
39345
|
const storageResolution = getStorageResolution();
|
|
38730
39346
|
const storageDirPath = storageResolution.path;
|
|
38731
|
-
const contextDbPath =
|
|
39347
|
+
const contextDbPath = join27(storageDirPath, "context.db");
|
|
38732
39348
|
let compactionEnabled = false;
|
|
38733
39349
|
try {
|
|
38734
39350
|
compactionEnabled = isCompactionEnabled(loadPluginConfig(process.cwd()));
|
|
@@ -38760,7 +39376,7 @@ async function collectDiagnostics() {
|
|
|
38760
39376
|
opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
|
|
38761
39377
|
tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
|
|
38762
39378
|
magicContextConfig: {
|
|
38763
|
-
exists:
|
|
39379
|
+
exists: existsSync33(configPaths.magicContextConfig),
|
|
38764
39380
|
...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
|
|
38765
39381
|
flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
|
|
38766
39382
|
},
|
|
@@ -38768,7 +39384,7 @@ async function collectDiagnostics() {
|
|
|
38768
39384
|
storageDir: {
|
|
38769
39385
|
path: storageDirPath,
|
|
38770
39386
|
source: storageResolution.source,
|
|
38771
|
-
exists:
|
|
39387
|
+
exists: existsSync33(storageDirPath),
|
|
38772
39388
|
contextDbSizeBytes: fileSize(contextDbPath)
|
|
38773
39389
|
},
|
|
38774
39390
|
openCodeDatabase: {
|
|
@@ -39001,9 +39617,9 @@ var init_embedding_local = __esm(() => {
|
|
|
39001
39617
|
|
|
39002
39618
|
// src/lib/embedding-runtime.ts
|
|
39003
39619
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
39004
|
-
import { existsSync as
|
|
39620
|
+
import { existsSync as existsSync34, readFileSync as readFileSync24 } from "node:fs";
|
|
39005
39621
|
import { createRequire as createRequire5 } from "node:module";
|
|
39006
|
-
import { dirname as
|
|
39622
|
+
import { dirname as dirname17, join as join28, sep } from "node:path";
|
|
39007
39623
|
function describeError(error) {
|
|
39008
39624
|
const message = error instanceof Error ? error.message : String(error ?? "unknown error");
|
|
39009
39625
|
const code = error?.code;
|
|
@@ -39011,6 +39627,7 @@ function describeError(error) {
|
|
|
39011
39627
|
}
|
|
39012
39628
|
function runOnnxRuntimeNodeLoadProbeChild(packageDir) {
|
|
39013
39629
|
return spawnSync7(process.execPath, ["-e", ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT], {
|
|
39630
|
+
windowsHide: true,
|
|
39014
39631
|
encoding: "utf8",
|
|
39015
39632
|
env: { ...process.env, [ONNX_LOAD_PROBE_PACKAGE_DIR_ENV]: packageDir },
|
|
39016
39633
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -39144,11 +39761,11 @@ function expectedBinaryRelPath(platform, arch) {
|
|
|
39144
39761
|
const supportedArch = arch === "x64" || arch === "arm64";
|
|
39145
39762
|
if (!supportedPlatform || !supportedArch)
|
|
39146
39763
|
return null;
|
|
39147
|
-
return
|
|
39764
|
+
return join28("bin", "napi-v6", platform, arch, "onnxruntime_binding.node");
|
|
39148
39765
|
}
|
|
39149
39766
|
function onnxRuntimeNodeVersion(packageDir) {
|
|
39150
39767
|
try {
|
|
39151
|
-
const parsed = JSON.parse(
|
|
39768
|
+
const parsed = JSON.parse(readFileSync24(join28(packageDir, "package.json"), "utf8"));
|
|
39152
39769
|
return typeof parsed.version === "string" ? parsed.version : undefined;
|
|
39153
39770
|
} catch {
|
|
39154
39771
|
return;
|
|
@@ -39197,7 +39814,7 @@ function formatLocalEmbeddingRuntimeWasmSelected(status) {
|
|
|
39197
39814
|
function requireNodeWasmBundle(probe, candidates) {
|
|
39198
39815
|
if (probe.state === "failed")
|
|
39199
39816
|
return probe;
|
|
39200
|
-
const bundlePath = candidates.find((candidate) =>
|
|
39817
|
+
const bundlePath = candidates.find((candidate) => existsSync34(candidate));
|
|
39201
39818
|
return bundlePath ? probe : {
|
|
39202
39819
|
state: "failed",
|
|
39203
39820
|
reason: `functional Node WASM Transformers bundle is missing (checked ${candidates.join(", ")})`
|
|
@@ -39205,13 +39822,13 @@ function requireNodeWasmBundle(probe, candidates) {
|
|
|
39205
39822
|
}
|
|
39206
39823
|
function nodeWasmBundleCandidates(installRoot) {
|
|
39207
39824
|
return [
|
|
39208
|
-
|
|
39209
|
-
|
|
39210
|
-
|
|
39825
|
+
join28(installRoot, "dist", "transformers-node-wasm.js"),
|
|
39826
|
+
join28(installRoot, "node_modules", "@cortexkit", "opencode-magic-context", "dist", "transformers-node-wasm.js"),
|
|
39827
|
+
join28(installRoot, "node_modules", "@cortexkit", "pi-magic-context", "dist", "transformers-node-wasm.js")
|
|
39211
39828
|
];
|
|
39212
39829
|
}
|
|
39213
39830
|
function probeWasmRuntimeAt(installRoot) {
|
|
39214
|
-
const requireFn = createRequire5(
|
|
39831
|
+
const requireFn = createRequire5(join28(installRoot, "package.json"));
|
|
39215
39832
|
return requireNodeWasmBundle(probeWasmRuntimeFromRequire(requireFn), nodeWasmBundleCandidates(installRoot));
|
|
39216
39833
|
}
|
|
39217
39834
|
function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
|
|
@@ -39220,9 +39837,9 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
39220
39837
|
const wasm = probeWasmRuntimeAt(installRoot);
|
|
39221
39838
|
return wasm.state === "ok" ? { state: "wasm-selected", wasmPath: wasm.wasmPath } : { state: "wasm-broken", wasmReason: wasm.reason };
|
|
39222
39839
|
}
|
|
39223
|
-
const packageDir =
|
|
39840
|
+
const packageDir = join28(installRoot, "node_modules", "onnxruntime-node");
|
|
39224
39841
|
let native;
|
|
39225
|
-
if (!
|
|
39842
|
+
if (!existsSync34(join28(packageDir, "package.json"))) {
|
|
39226
39843
|
native = { state: "package-missing", packageDir };
|
|
39227
39844
|
} else {
|
|
39228
39845
|
const rel = expectedBinaryRelPath(platform, arch);
|
|
@@ -39232,8 +39849,8 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
39232
39849
|
binaryPath: packageDir
|
|
39233
39850
|
};
|
|
39234
39851
|
} else {
|
|
39235
|
-
const binaryPath =
|
|
39236
|
-
native =
|
|
39852
|
+
const binaryPath = join28(packageDir, rel);
|
|
39853
|
+
native = existsSync34(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
|
|
39237
39854
|
state: "binary-missing",
|
|
39238
39855
|
packageDir,
|
|
39239
39856
|
expectedBinary: binaryPath,
|
|
@@ -39244,7 +39861,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
39244
39861
|
return withWasmFallback(native, () => probeWasmRuntimeAt(installRoot));
|
|
39245
39862
|
}
|
|
39246
39863
|
function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
|
|
39247
|
-
const existing = installRoots.filter((root) =>
|
|
39864
|
+
const existing = installRoots.filter((root) => existsSync34(root));
|
|
39248
39865
|
if (existing.length === 0) {
|
|
39249
39866
|
return {
|
|
39250
39867
|
state: "unknown",
|
|
@@ -39270,19 +39887,19 @@ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, a
|
|
|
39270
39887
|
function packageDirFromResolved(resolvedPath, packageName) {
|
|
39271
39888
|
const marker = `node_modules${sep}${packageName.split("/").join(sep)}`;
|
|
39272
39889
|
const idx = resolvedPath.indexOf(marker);
|
|
39273
|
-
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) :
|
|
39890
|
+
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname17(resolvedPath);
|
|
39274
39891
|
}
|
|
39275
39892
|
function probeWasmRuntimeByResolution(pluginDir) {
|
|
39276
39893
|
try {
|
|
39277
|
-
const reqPlugin = createRequire5(
|
|
39894
|
+
const reqPlugin = createRequire5(join28(pluginDir, "package.json"));
|
|
39278
39895
|
const direct = probeWasmRuntimeFromRequire(reqPlugin);
|
|
39279
39896
|
let probe = direct;
|
|
39280
39897
|
if (direct.state === "failed" && direct.reason.startsWith("onnxruntime-web is not resolvable")) {
|
|
39281
39898
|
const tfResolved = reqPlugin.resolve("@huggingface/transformers");
|
|
39282
39899
|
const tfDir = packageDirFromResolved(tfResolved, "@huggingface/transformers");
|
|
39283
|
-
probe = probeWasmRuntimeFromRequire(createRequire5(
|
|
39900
|
+
probe = probeWasmRuntimeFromRequire(createRequire5(join28(tfDir, "package.json")));
|
|
39284
39901
|
}
|
|
39285
|
-
return requireNodeWasmBundle(probe, [
|
|
39902
|
+
return requireNodeWasmBundle(probe, [join28(pluginDir, "dist", "transformers-node-wasm.js")]);
|
|
39286
39903
|
} catch (error) {
|
|
39287
39904
|
return {
|
|
39288
39905
|
state: "failed",
|
|
@@ -39291,7 +39908,7 @@ function probeWasmRuntimeByResolution(pluginDir) {
|
|
|
39291
39908
|
}
|
|
39292
39909
|
}
|
|
39293
39910
|
function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
|
|
39294
|
-
if (!
|
|
39911
|
+
if (!existsSync34(join28(pluginDir, "package.json"))) {
|
|
39295
39912
|
return { state: "unknown", reason: "plugin package dir not found" };
|
|
39296
39913
|
}
|
|
39297
39914
|
const selectedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, host);
|
|
@@ -39302,13 +39919,13 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
39302
39919
|
let onnxDir = null;
|
|
39303
39920
|
let resolveError;
|
|
39304
39921
|
try {
|
|
39305
|
-
const reqPlugin = createRequire5(
|
|
39922
|
+
const reqPlugin = createRequire5(join28(pluginDir, "package.json"));
|
|
39306
39923
|
try {
|
|
39307
39924
|
onnxDir = packageDirFromResolved(reqPlugin.resolve("onnxruntime-node"), "onnxruntime-node");
|
|
39308
39925
|
} catch {
|
|
39309
39926
|
const tfResolved = reqPlugin.resolve("@huggingface/transformers");
|
|
39310
39927
|
const tfDir = packageDirFromResolved(tfResolved, "@huggingface/transformers");
|
|
39311
|
-
const reqTf = createRequire5(
|
|
39928
|
+
const reqTf = createRequire5(join28(tfDir, "package.json"));
|
|
39312
39929
|
onnxDir = packageDirFromResolved(reqTf.resolve("onnxruntime-node"), "onnxruntime-node");
|
|
39313
39930
|
}
|
|
39314
39931
|
} catch (error) {
|
|
@@ -39316,7 +39933,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
39316
39933
|
if (resolveError === "ERR_MODULE_NOT_FOUND" || resolveError === "MODULE_NOT_FOUND") {
|
|
39317
39934
|
return withWasmFallback({
|
|
39318
39935
|
state: "package-missing",
|
|
39319
|
-
packageDir:
|
|
39936
|
+
packageDir: join28(pluginDir, "node_modules", "onnxruntime-node")
|
|
39320
39937
|
}, () => probeWasmRuntimeByResolution(pluginDir));
|
|
39321
39938
|
}
|
|
39322
39939
|
return {
|
|
@@ -39332,8 +39949,8 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
39332
39949
|
if (rel === null) {
|
|
39333
39950
|
native = probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
|
|
39334
39951
|
} else {
|
|
39335
|
-
const binaryPath =
|
|
39336
|
-
native =
|
|
39952
|
+
const binaryPath = join28(onnxDir, rel);
|
|
39953
|
+
native = existsSync34(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
|
|
39337
39954
|
state: "binary-missing",
|
|
39338
39955
|
packageDir: onnxDir,
|
|
39339
39956
|
expectedBinary: binaryPath,
|
|
@@ -39475,8 +40092,8 @@ var init_issue_body = __esm(() => {
|
|
|
39475
40092
|
});
|
|
39476
40093
|
|
|
39477
40094
|
// src/lib/logs-opencode.ts
|
|
39478
|
-
import { writeFileSync as
|
|
39479
|
-
import { join as
|
|
40095
|
+
import { writeFileSync as writeFileSync9 } from "node:fs";
|
|
40096
|
+
import { join as join29 } from "node:path";
|
|
39480
40097
|
function sanitizeLogContent(content) {
|
|
39481
40098
|
return sanitizeDiagnosticText(content);
|
|
39482
40099
|
}
|
|
@@ -39583,12 +40200,12 @@ async function bundleIssueReport(report, description, title, sessionFilter = nul
|
|
|
39583
40200
|
const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
|
|
39584
40201
|
const truncated = bodyMarkdown !== rawBodyMarkdown;
|
|
39585
40202
|
const timestamp = formatTimestamp(new Date);
|
|
39586
|
-
const path =
|
|
39587
|
-
|
|
40203
|
+
const path = join29(process.cwd(), `magic-context-issue-${timestamp}.md`);
|
|
40204
|
+
writeFileSync9(path, `${bodyMarkdown}
|
|
39588
40205
|
`);
|
|
39589
|
-
const fullPath = truncated ?
|
|
40206
|
+
const fullPath = truncated ? join29(process.cwd(), `magic-context-issue-${timestamp}-full.md`) : undefined;
|
|
39590
40207
|
if (fullPath)
|
|
39591
|
-
|
|
40208
|
+
writeFileSync9(fullPath, `${rawBodyMarkdown}
|
|
39592
40209
|
`);
|
|
39593
40210
|
return { path, bodyMarkdown, ...fullPath ? { fullPath } : {}, truncated };
|
|
39594
40211
|
}
|
|
@@ -39852,25 +40469,25 @@ function migrateExperimentalPinKeyFilesForDoctor(mcConfig) {
|
|
|
39852
40469
|
}
|
|
39853
40470
|
|
|
39854
40471
|
// ../plugin/src/hooks/auto-update-checker/constants.ts
|
|
39855
|
-
import { homedir as
|
|
39856
|
-
import { join as
|
|
40472
|
+
import { homedir as homedir16, platform } from "node:os";
|
|
40473
|
+
import { join as join30 } from "node:path";
|
|
39857
40474
|
function getOpenCodeCacheRoot() {
|
|
39858
40475
|
if (platform() === "win32") {
|
|
39859
|
-
return
|
|
40476
|
+
return join30(process.env.LOCALAPPDATA ?? homedir16(), "opencode");
|
|
39860
40477
|
}
|
|
39861
|
-
return
|
|
40478
|
+
return join30(homedir16(), ".cache", "opencode");
|
|
39862
40479
|
}
|
|
39863
40480
|
function getOpenCodeConfigRoot() {
|
|
39864
40481
|
if (platform() === "win32") {
|
|
39865
|
-
return
|
|
40482
|
+
return join30(process.env.APPDATA ?? join30(homedir16(), "AppData", "Roaming"), "opencode");
|
|
39866
40483
|
}
|
|
39867
|
-
return
|
|
40484
|
+
return join30(process.env.XDG_CONFIG_HOME ?? join30(homedir16(), ".config"), "opencode");
|
|
39868
40485
|
}
|
|
39869
40486
|
var PACKAGE_NAME = "@cortexkit/opencode-magic-context", CACHE_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC;
|
|
39870
40487
|
var init_constants2 = __esm(() => {
|
|
39871
|
-
CACHE_DIR =
|
|
39872
|
-
USER_OPENCODE_CONFIG =
|
|
39873
|
-
USER_OPENCODE_CONFIG_JSONC =
|
|
40488
|
+
CACHE_DIR = join30(getOpenCodeCacheRoot(), "packages");
|
|
40489
|
+
USER_OPENCODE_CONFIG = join30(getOpenCodeConfigRoot(), "opencode.json");
|
|
40490
|
+
USER_OPENCODE_CONFIG_JSONC = join30(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
39874
40491
|
});
|
|
39875
40492
|
|
|
39876
40493
|
// ../plugin/src/hooks/auto-update-checker/types.ts
|
|
@@ -39894,14 +40511,14 @@ var init_types = __esm(() => {
|
|
|
39894
40511
|
// ../plugin/src/hooks/auto-update-checker/checker.ts
|
|
39895
40512
|
import {
|
|
39896
40513
|
accessSync as accessSync2,
|
|
39897
|
-
existsSync as
|
|
40514
|
+
existsSync as existsSync35,
|
|
39898
40515
|
constants as fsConstants,
|
|
39899
|
-
readFileSync as
|
|
39900
|
-
renameSync as
|
|
40516
|
+
readFileSync as readFileSync25,
|
|
40517
|
+
renameSync as renameSync9,
|
|
39901
40518
|
statSync as statSync15,
|
|
39902
|
-
writeFileSync as
|
|
40519
|
+
writeFileSync as writeFileSync10
|
|
39903
40520
|
} from "node:fs";
|
|
39904
|
-
import { dirname as
|
|
40521
|
+
import { dirname as dirname18, isAbsolute as isAbsolute7, join as join31, resolve as resolve9 } from "node:path";
|
|
39905
40522
|
function warn(message) {
|
|
39906
40523
|
log3(`WARN: ${message}`);
|
|
39907
40524
|
}
|
|
@@ -39927,17 +40544,17 @@ function parseJsonConfig(content) {
|
|
|
39927
40544
|
}
|
|
39928
40545
|
function getSurfaceConfigPaths(directory, surface) {
|
|
39929
40546
|
const name = surface === "server" ? "opencode" : "tui";
|
|
39930
|
-
const globalDir =
|
|
40547
|
+
const globalDir = dirname18(USER_OPENCODE_CONFIG);
|
|
39931
40548
|
const dirs = [
|
|
39932
40549
|
globalDir,
|
|
39933
40550
|
directory,
|
|
39934
|
-
|
|
40551
|
+
join31(directory, ".opencode"),
|
|
39935
40552
|
process.env.OPENCODE_CONFIG_DIR
|
|
39936
40553
|
].filter((value) => Boolean(value));
|
|
39937
40554
|
const paths = [];
|
|
39938
40555
|
for (const dir of dirs) {
|
|
39939
40556
|
for (const extension of ["json", "jsonc"]) {
|
|
39940
|
-
const path =
|
|
40557
|
+
const path = join31(dir, `${name}.${extension}`);
|
|
39941
40558
|
if (!paths.includes(path))
|
|
39942
40559
|
paths.push(path);
|
|
39943
40560
|
}
|
|
@@ -39948,9 +40565,9 @@ function getWinningConfig(directory, surface) {
|
|
|
39948
40565
|
let winner = null;
|
|
39949
40566
|
for (const path of getSurfaceConfigPaths(directory, surface)) {
|
|
39950
40567
|
try {
|
|
39951
|
-
if (!
|
|
40568
|
+
if (!existsSync35(path))
|
|
39952
40569
|
continue;
|
|
39953
|
-
const parsed = parseJsonConfig(
|
|
40570
|
+
const parsed = parseJsonConfig(readFileSync25(path, "utf-8"));
|
|
39954
40571
|
const entries = getPluginEntries(parsed);
|
|
39955
40572
|
if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
|
|
39956
40573
|
if (winner) {
|
|
@@ -39986,14 +40603,14 @@ var init_checker = __esm(() => {
|
|
|
39986
40603
|
});
|
|
39987
40604
|
|
|
39988
40605
|
// src/lib/opencode-plugin-schema-fence.ts
|
|
39989
|
-
import { existsSync as
|
|
39990
|
-
import { join as
|
|
40606
|
+
import { existsSync as existsSync36, readdirSync as readdirSync7, readFileSync as readFileSync26 } from "node:fs";
|
|
40607
|
+
import { join as join32 } from "node:path";
|
|
39991
40608
|
import { gunzipSync } from "node:zlib";
|
|
39992
40609
|
function readPackageVersion(packageJsonPath) {
|
|
39993
40610
|
try {
|
|
39994
|
-
if (!
|
|
40611
|
+
if (!existsSync36(packageJsonPath))
|
|
39995
40612
|
return null;
|
|
39996
|
-
const packageJson = JSON.parse(
|
|
40613
|
+
const packageJson = JSON.parse(readFileSync26(packageJsonPath, "utf-8"));
|
|
39997
40614
|
if (packageJson.name !== OPENCODE_PLUGIN_NAME || typeof packageJson.version !== "string") {
|
|
39998
40615
|
return null;
|
|
39999
40616
|
}
|
|
@@ -40012,8 +40629,8 @@ function readFenceValue(text) {
|
|
|
40012
40629
|
return values.size === 1 ? [...values][0] ?? null : null;
|
|
40013
40630
|
}
|
|
40014
40631
|
function readFenceFromDist(packageDirectory) {
|
|
40015
|
-
const distDirectory =
|
|
40016
|
-
if (!
|
|
40632
|
+
const distDirectory = join32(packageDirectory, "dist");
|
|
40633
|
+
if (!existsSync36(distDirectory))
|
|
40017
40634
|
return null;
|
|
40018
40635
|
const pending = [distDirectory];
|
|
40019
40636
|
const fenceValues = new Set;
|
|
@@ -40022,15 +40639,15 @@ function readFenceFromDist(packageDirectory) {
|
|
|
40022
40639
|
if (!directory)
|
|
40023
40640
|
continue;
|
|
40024
40641
|
try {
|
|
40025
|
-
for (const entry of
|
|
40026
|
-
const path =
|
|
40642
|
+
for (const entry of readdirSync7(directory, { withFileTypes: true })) {
|
|
40643
|
+
const path = join32(directory, entry.name);
|
|
40027
40644
|
if (entry.isDirectory()) {
|
|
40028
40645
|
pending.push(path);
|
|
40029
40646
|
continue;
|
|
40030
40647
|
}
|
|
40031
40648
|
if (!entry.isFile() || !/\.(?:[cm]?js|ts)$/.test(entry.name))
|
|
40032
40649
|
continue;
|
|
40033
|
-
const fence = readFenceValue(
|
|
40650
|
+
const fence = readFenceValue(readFileSync26(path, "utf-8"));
|
|
40034
40651
|
if (fence !== null)
|
|
40035
40652
|
fenceValues.add(fence);
|
|
40036
40653
|
}
|
|
@@ -40041,20 +40658,20 @@ function readFenceFromDist(packageDirectory) {
|
|
|
40041
40658
|
return fenceValues.size === 1 ? [...fenceValues][0] ?? null : null;
|
|
40042
40659
|
}
|
|
40043
40660
|
function findInstalledPluginPackage(cacheDirectory, specifier, requestedVersion) {
|
|
40044
|
-
const directCacheRoot =
|
|
40661
|
+
const directCacheRoot = join32(cacheDirectory, specifier);
|
|
40045
40662
|
const candidates = [directCacheRoot];
|
|
40046
40663
|
try {
|
|
40047
|
-
for (const entry of
|
|
40664
|
+
for (const entry of readdirSync7(cacheDirectory, { withFileTypes: true })) {
|
|
40048
40665
|
if (!entry.isDirectory())
|
|
40049
40666
|
continue;
|
|
40050
|
-
const candidate =
|
|
40667
|
+
const candidate = join32(cacheDirectory, entry.name);
|
|
40051
40668
|
if (!candidates.includes(candidate))
|
|
40052
40669
|
candidates.push(candidate);
|
|
40053
40670
|
}
|
|
40054
40671
|
} catch {}
|
|
40055
40672
|
for (const cacheRoot of candidates) {
|
|
40056
|
-
const directory =
|
|
40057
|
-
const version = readPackageVersion(
|
|
40673
|
+
const directory = join32(cacheRoot, "node_modules", ...PACKAGE_PATH_SEGMENTS);
|
|
40674
|
+
const version = readPackageVersion(join32(directory, "package.json"));
|
|
40058
40675
|
if (!version)
|
|
40059
40676
|
continue;
|
|
40060
40677
|
if (cacheRoot === directCacheRoot || EXACT_VERSION_PATTERN.test(requestedVersion) && version === requestedVersion) {
|
|
@@ -40248,13 +40865,13 @@ var init_storage_versions = __esm(async () => {
|
|
|
40248
40865
|
});
|
|
40249
40866
|
|
|
40250
40867
|
// src/commands/doctor-opencode-cache.ts
|
|
40251
|
-
import { existsSync as
|
|
40868
|
+
import { existsSync as existsSync37, readFileSync as readFileSync27, rmSync as rmSync4 } from "node:fs";
|
|
40252
40869
|
function readCachedPluginVersion(pluginCacheDir) {
|
|
40253
40870
|
try {
|
|
40254
40871
|
const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
|
|
40255
|
-
if (!
|
|
40872
|
+
if (!existsSync37(installedPkgPath))
|
|
40256
40873
|
return;
|
|
40257
|
-
const pkg = JSON.parse(
|
|
40874
|
+
const pkg = JSON.parse(readFileSync27(installedPkgPath, "utf-8"));
|
|
40258
40875
|
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
40259
40876
|
} catch {
|
|
40260
40877
|
return;
|
|
@@ -40263,7 +40880,7 @@ function readCachedPluginVersion(pluginCacheDir) {
|
|
|
40263
40880
|
async function clearPluginCache(options = {}, deps = {}) {
|
|
40264
40881
|
const remove = deps.remove ?? ((path) => rmSync4(path, { recursive: true, force: true }));
|
|
40265
40882
|
const pluginCacheRoots = getOpenCodePluginCacheRoots();
|
|
40266
|
-
const existingRoots = pluginCacheRoots.filter((root) =>
|
|
40883
|
+
const existingRoots = pluginCacheRoots.filter((root) => existsSync37(root));
|
|
40267
40884
|
if (existingRoots.length === 0) {
|
|
40268
40885
|
return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
|
|
40269
40886
|
}
|
|
@@ -40330,19 +40947,19 @@ var init_doctor_opencode_cache = __esm(() => {
|
|
|
40330
40947
|
});
|
|
40331
40948
|
|
|
40332
40949
|
// src/commands/doctor-cached-plugin-fence.ts
|
|
40333
|
-
import { existsSync as
|
|
40334
|
-
import { dirname as
|
|
40950
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
40951
|
+
import { dirname as dirname19 } from "node:path";
|
|
40335
40952
|
function listCachedOpenCodePluginFences(sources = {}) {
|
|
40336
40953
|
const fences = [];
|
|
40337
40954
|
for (const root of sources.openCodeV1Roots ?? getOpenCodePluginCacheRoots()) {
|
|
40338
40955
|
const packageJson = getOpenCodePluginPackageJsonPath(root);
|
|
40339
|
-
if (!
|
|
40956
|
+
if (!existsSync38(packageJson))
|
|
40340
40957
|
continue;
|
|
40341
40958
|
fences.push({
|
|
40342
40959
|
host: "opencode1",
|
|
40343
40960
|
directory: root,
|
|
40344
40961
|
version: readCachedPluginVersion(root),
|
|
40345
|
-
supportedVersion: readFenceFromDist(
|
|
40962
|
+
supportedVersion: readFenceFromDist(dirname19(packageJson))
|
|
40346
40963
|
});
|
|
40347
40964
|
}
|
|
40348
40965
|
for (const slot of listOpenCodeV2PluginCacheSlots(sources.openCodeV2NpmCacheDir)) {
|
|
@@ -40356,7 +40973,7 @@ function listCachedOpenCodePluginFences(sources = {}) {
|
|
|
40356
40973
|
directory: slot.slot,
|
|
40357
40974
|
spec: slot.spec,
|
|
40358
40975
|
version: slot.version,
|
|
40359
|
-
supportedVersion: readFenceFromDist(
|
|
40976
|
+
supportedVersion: readFenceFromDist(dirname19(getOpenCodePluginPackageJsonPath(generation)))
|
|
40360
40977
|
});
|
|
40361
40978
|
}
|
|
40362
40979
|
return fences;
|
|
@@ -40431,11 +41048,11 @@ function mcMarkerPredicate(column = "data") {
|
|
|
40431
41048
|
AND json_extract(${data}, '$.summary') = 1
|
|
40432
41049
|
AND json_extract(${data}, '$.providerID') = 'magic-context'`;
|
|
40433
41050
|
}
|
|
40434
|
-
function
|
|
41051
|
+
function tableExists5(db, table) {
|
|
40435
41052
|
return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1").get(table) != null;
|
|
40436
41053
|
}
|
|
40437
41054
|
function countMissingCompleted(db) {
|
|
40438
|
-
if (!
|
|
41055
|
+
if (!tableExists5(db, "message"))
|
|
40439
41056
|
return 0;
|
|
40440
41057
|
const row = db.prepare(`SELECT COUNT(*) AS count
|
|
40441
41058
|
FROM message
|
|
@@ -40444,7 +41061,7 @@ function countMissingCompleted(db) {
|
|
|
40444
41061
|
return Number(row?.count ?? 0);
|
|
40445
41062
|
}
|
|
40446
41063
|
function migrationV1ToV2Completed(db) {
|
|
40447
|
-
if (!
|
|
41064
|
+
if (!tableExists5(db, "kv"))
|
|
40448
41065
|
return false;
|
|
40449
41066
|
const columns = db.prepare("PRAGMA table_info(kv)").all();
|
|
40450
41067
|
const names = new Set(columns.flatMap((column) => typeof column.name === "string" ? [column.name] : []));
|
|
@@ -40461,7 +41078,7 @@ function migrationV1ToV2Completed(db) {
|
|
|
40461
41078
|
}
|
|
40462
41079
|
}
|
|
40463
41080
|
function countUnmatchedConvertedMarkers(db, migratedV2Schema) {
|
|
40464
|
-
if (!migratedV2Schema || !
|
|
41081
|
+
if (!migratedV2Schema || !tableExists5(db, "message"))
|
|
40465
41082
|
return 0;
|
|
40466
41083
|
const row = db.prepare(`SELECT COUNT(DISTINCT json_extract(${safeData("marker.data")}, '$.parentID')) AS count
|
|
40467
41084
|
FROM message marker
|
|
@@ -40476,7 +41093,7 @@ function countUnmatchedConvertedMarkers(db, migratedV2Schema) {
|
|
|
40476
41093
|
return Number(row?.count ?? 0);
|
|
40477
41094
|
}
|
|
40478
41095
|
function countPostConversionMessages(db, migratedV2Schema) {
|
|
40479
|
-
if (!migratedV2Schema || !
|
|
41096
|
+
if (!migratedV2Schema || !tableExists5(db, "message") || !tableExists5(db, "session")) {
|
|
40480
41097
|
return { messages: 0, sessions: 0 };
|
|
40481
41098
|
}
|
|
40482
41099
|
const row = db.prepare(`SELECT COUNT(*) AS messages, COUNT(DISTINCT converted.session_id) AS sessions
|
|
@@ -40493,7 +41110,7 @@ function countPostConversionMessages(db, migratedV2Schema) {
|
|
|
40493
41110
|
function checkOpenCodeCompactionMarkerConversion(db, options = {}) {
|
|
40494
41111
|
const missingBefore = countMissingCompleted(db);
|
|
40495
41112
|
let repaired = 0;
|
|
40496
|
-
if (options.fix && missingBefore > 0 &&
|
|
41113
|
+
if (options.fix && missingBefore > 0 && tableExists5(db, "message")) {
|
|
40497
41114
|
repaired = db.transaction(() => {
|
|
40498
41115
|
const result = db.prepare(`UPDATE message
|
|
40499
41116
|
SET data = json_set(
|
|
@@ -40507,7 +41124,7 @@ function checkOpenCodeCompactionMarkerConversion(db, options = {}) {
|
|
|
40507
41124
|
})();
|
|
40508
41125
|
}
|
|
40509
41126
|
const missingAfter = countMissingCompleted(db);
|
|
40510
|
-
const migratedV2Schema =
|
|
41127
|
+
const migratedV2Schema = tableExists5(db, "session_v2") && tableExists5(db, "session_message");
|
|
40511
41128
|
const migrationCompleted = migrationV1ToV2Completed(db);
|
|
40512
41129
|
const unmatchedConvertedMarkers = countUnmatchedConvertedMarkers(db, migratedV2Schema);
|
|
40513
41130
|
const postConversion = countPostConversionMessages(db, migratedV2Schema);
|
|
@@ -40618,6 +41235,182 @@ var init_doctor_harness_relabel = __esm(async () => {
|
|
|
40618
41235
|
await init_opencode2_relabel();
|
|
40619
41236
|
});
|
|
40620
41237
|
|
|
41238
|
+
// src/commands/doctor-hidden-children.ts
|
|
41239
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
41240
|
+
import { existsSync as existsSync39, realpathSync as realpathSync7 } from "node:fs";
|
|
41241
|
+
import { dirname as dirname20 } from "node:path";
|
|
41242
|
+
async function assertHiddenChildStoresClosed(contextDbPath, hostDbPath, platform = process.platform, processProbe = () => inspectProcessesAsync(true)) {
|
|
41243
|
+
if (platform === "win32") {
|
|
41244
|
+
const processes = await processProbe();
|
|
41245
|
+
if (processes.pi.state !== "known" || processes.pi.processIds.length > 0 || (processes.pi.inconclusivePids?.length ?? 0) > 0 || processes.processSnapshot?.source !== "cim") {
|
|
41246
|
+
throw new Error("Windows process probe could not rule out OpenCode, Pi or ck-mc holders");
|
|
41247
|
+
}
|
|
41248
|
+
const unknown = processes.processSnapshot.facts.filter(({ pid, imageName, commandLine }) => pid !== process.pid && (!imageName && !commandLine || /^(?:bun|node|deno)(?:\.exe)?$/i.test(imageName ?? "") && !commandLine));
|
|
41249
|
+
if (unknown.length)
|
|
41250
|
+
throw new Error(`Windows process identity is unavailable (PID ${unknown.map(({ pid }) => pid).join(", ")})`);
|
|
41251
|
+
const blockers = processes.processSnapshot.facts.filter(({ pid, imageName, commandLine }) => {
|
|
41252
|
+
if (pid === process.pid)
|
|
41253
|
+
return false;
|
|
41254
|
+
const image = (imageName ?? "").toLowerCase().replaceAll("\\", "/").split("/").at(-1) ?? "";
|
|
41255
|
+
return /^(?:opencode|opencode2|pi|omp|ck-mc)(?:\.exe)?$/.test(image) || /(?:^|[\\/\s"'])(?:ck-mc|opencode2?)(?:\.exe|\.js|\.mjs)?(?:$|[\s"'])/i.test(commandLine ?? "");
|
|
41256
|
+
});
|
|
41257
|
+
if (blockers.length)
|
|
41258
|
+
throw new Error(`OpenCode, Pi or ck-mc process is running (PID ${blockers.map(({ pid }) => pid).join(", ")})`);
|
|
41259
|
+
return;
|
|
41260
|
+
}
|
|
41261
|
+
const inspection = defaultInspectHolders(dirname20(contextDbPath));
|
|
41262
|
+
if (!inspection.safe) {
|
|
41263
|
+
throw new Error(`database holders cannot be ruled out: ${[...inspection.blockers, inspection.uncertainty].filter(Boolean).join("; ")}`);
|
|
41264
|
+
}
|
|
41265
|
+
const paths = [contextDbPath, hostDbPath].flatMap((path) => [path, `${path}-wal`, `${path}-shm`].filter(existsSync39).map((file) => realpathSync7(file)));
|
|
41266
|
+
const result = spawnSync8("lsof", ["-Fn", "--", ...paths], {
|
|
41267
|
+
encoding: "utf8",
|
|
41268
|
+
timeout: 30000,
|
|
41269
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
41270
|
+
windowsHide: true
|
|
41271
|
+
});
|
|
41272
|
+
if (result.error || result.stderr?.trim() || result.status !== 0 && !(result.status === 1 && !result.stdout?.trim())) {
|
|
41273
|
+
throw new Error(`lsof could not inspect database holders: ${result.error?.message ?? result.stderr ?? result.status}`);
|
|
41274
|
+
}
|
|
41275
|
+
const opened = result.stdout.split(`
|
|
41276
|
+
`).filter((line) => line.startsWith("n"));
|
|
41277
|
+
if (opened.length)
|
|
41278
|
+
throw new Error(`database holder is present: ${opened.map((line) => line.slice(1)).join(", ")}`);
|
|
41279
|
+
if (result.status === 0)
|
|
41280
|
+
throw new Error("lsof returned success without any file evidence");
|
|
41281
|
+
}
|
|
41282
|
+
function assertVerifiedV2Schema(db) {
|
|
41283
|
+
const table = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all();
|
|
41284
|
+
const names = new Set(table.map((row) => row.name));
|
|
41285
|
+
if (!names.has("session_v2") || !names.has("session_message") || names.has("message") || names.has("part")) {
|
|
41286
|
+
throw new Error("OpenCode store is not the verified OpenCode 2 session_v2 schema");
|
|
41287
|
+
}
|
|
41288
|
+
const fields = db.prepare("PRAGMA table_info('session_v2')").all();
|
|
41289
|
+
if (!fields.some((field) => field.name === "id" && field.pk === 1) || !fields.some((field) => field.name === "metadata") || !fields.some((field) => field.name === "directory")) {
|
|
41290
|
+
throw new Error("OpenCode session_v2 columns differ from the verified schema");
|
|
41291
|
+
}
|
|
41292
|
+
const dependents = table.flatMap(({ name }) => {
|
|
41293
|
+
const foreignKeys = db.prepare(`PRAGMA foreign_key_list('${name.replaceAll("'", "''")}')`).all();
|
|
41294
|
+
return foreignKeys.filter((key) => key.table === "session_v2").map((key) => ({ name, ...key }));
|
|
41295
|
+
});
|
|
41296
|
+
if (dependents.length !== CASCADE_TABLES.length || dependents.some((key) => !CASCADE_TABLES.includes(key.name) || key.from !== "session_id" || key.to !== "id" || key.on_delete !== "CASCADE")) {
|
|
41297
|
+
throw new Error("OpenCode session_v2 cascade schema differs from the verified 2.0.18 host");
|
|
41298
|
+
}
|
|
41299
|
+
}
|
|
41300
|
+
async function cleanupRetiredHiddenChildren(options) {
|
|
41301
|
+
const { contextDbPath, hostDbPath, fix = false } = options;
|
|
41302
|
+
if (!existsSync39(contextDbPath) || !existsSync39(hostDbPath))
|
|
41303
|
+
return { waiting: 0, deleted: 0 };
|
|
41304
|
+
const context = new Database(contextDbPath, { readonly: true, fileMustExist: true });
|
|
41305
|
+
const host = new Database(hostDbPath, { readonly: true, fileMustExist: true });
|
|
41306
|
+
let states;
|
|
41307
|
+
let candidates;
|
|
41308
|
+
let waiting;
|
|
41309
|
+
try {
|
|
41310
|
+
assertVerifiedV2Schema(host);
|
|
41311
|
+
const rows = context.prepare("SELECT key, value FROM schema_migrations_meta WHERE substr(key, 1, ?) = ?").all(PREFIX.length, PREFIX);
|
|
41312
|
+
states = rows.map(({ key, value }) => {
|
|
41313
|
+
const state = JSON.parse(value);
|
|
41314
|
+
if (state.version !== 1 || !Array.isArray(state.retired_children) || state.retired_children.some((child) => typeof child.id !== "string")) {
|
|
41315
|
+
throw new Error(`Invalid hidden-child state at ${key}`);
|
|
41316
|
+
}
|
|
41317
|
+
return { key, state };
|
|
41318
|
+
});
|
|
41319
|
+
const ids = [
|
|
41320
|
+
...new Set(states.flatMap(({ state }) => state.retired_children.map((child) => child.id)))
|
|
41321
|
+
];
|
|
41322
|
+
waiting = ids.length;
|
|
41323
|
+
candidates = ids.filter((id) => {
|
|
41324
|
+
const row = host.prepare("SELECT metadata FROM session_v2 WHERE id = ?").get(id);
|
|
41325
|
+
if (!row)
|
|
41326
|
+
return false;
|
|
41327
|
+
let marker;
|
|
41328
|
+
try {
|
|
41329
|
+
marker = JSON.parse(row.metadata ?? "null");
|
|
41330
|
+
} catch {
|
|
41331
|
+
return false;
|
|
41332
|
+
}
|
|
41333
|
+
return marker?.magic_context === "hidden-run";
|
|
41334
|
+
});
|
|
41335
|
+
} finally {
|
|
41336
|
+
context.close();
|
|
41337
|
+
host.close();
|
|
41338
|
+
}
|
|
41339
|
+
options.report?.(`${waiting} retired hidden sessions are waiting for deletion${fix ? "" : "; run `doctor --fix` with OpenCode closed"}`);
|
|
41340
|
+
if (!fix || candidates.length === 0)
|
|
41341
|
+
return { waiting, deleted: 0 };
|
|
41342
|
+
const inspect = options.inspectHolders ?? ((context, host) => assertHiddenChildStoresClosed(context, host, options.platform, options.processProbe));
|
|
41343
|
+
await inspect(contextDbPath, hostDbPath);
|
|
41344
|
+
const backup = `${hostDbPath}.hidden-child-backup-${new Date().toISOString().replace(/[:.]/g, "-")}-${process.pid}`;
|
|
41345
|
+
copyDatabaseBundle(hostDbPath, backup);
|
|
41346
|
+
options.report?.(`OpenCode store backup: ${backup}`);
|
|
41347
|
+
await inspect(contextDbPath, hostDbPath);
|
|
41348
|
+
const writableHost = new Database(hostDbPath);
|
|
41349
|
+
let writableContext;
|
|
41350
|
+
const deletedIds = [];
|
|
41351
|
+
let hostLocked = false;
|
|
41352
|
+
let contextLocked = false;
|
|
41353
|
+
try {
|
|
41354
|
+
writableHost.exec("PRAGMA busy_timeout = 250");
|
|
41355
|
+
writableHost.exec("PRAGMA foreign_keys = ON");
|
|
41356
|
+
writableContext = new Database(contextDbPath);
|
|
41357
|
+
writableContext.exec("PRAGMA busy_timeout = 250");
|
|
41358
|
+
try {
|
|
41359
|
+
writableHost.exec("BEGIN EXCLUSIVE");
|
|
41360
|
+
hostLocked = true;
|
|
41361
|
+
writableContext.exec("BEGIN EXCLUSIVE");
|
|
41362
|
+
contextLocked = true;
|
|
41363
|
+
} catch (error) {
|
|
41364
|
+
throw new Error(`Cannot acquire exclusive locks on ${hostDbPath} and ${contextDbPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
41365
|
+
}
|
|
41366
|
+
assertVerifiedV2Schema(writableHost);
|
|
41367
|
+
for (const id of candidates) {
|
|
41368
|
+
const result = writableHost.prepare("DELETE FROM session_v2 WHERE id = ? AND json_valid(metadata) AND json_extract(metadata, '$.magic_context') = 'hidden-run'").run(id);
|
|
41369
|
+
if (result.changes > 0)
|
|
41370
|
+
deletedIds.push(id);
|
|
41371
|
+
}
|
|
41372
|
+
for (const { key } of states) {
|
|
41373
|
+
const current = writableContext.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(key);
|
|
41374
|
+
if (!current)
|
|
41375
|
+
throw new Error(`Hidden-child state ${key} disappeared during repair`);
|
|
41376
|
+
const state = JSON.parse(current.value);
|
|
41377
|
+
if (state.version !== 1 || !Array.isArray(state.retired_children)) {
|
|
41378
|
+
throw new Error(`Hidden-child state ${key} changed during repair`);
|
|
41379
|
+
}
|
|
41380
|
+
state.retired_children = state.retired_children.filter((child) => !deletedIds.includes(child.id));
|
|
41381
|
+
writableContext.prepare("UPDATE schema_migrations_meta SET value = ? WHERE key = ?").run(JSON.stringify(state), key);
|
|
41382
|
+
}
|
|
41383
|
+
writableHost.exec("COMMIT");
|
|
41384
|
+
hostLocked = false;
|
|
41385
|
+
writableContext.exec("COMMIT");
|
|
41386
|
+
contextLocked = false;
|
|
41387
|
+
} finally {
|
|
41388
|
+
if (contextLocked)
|
|
41389
|
+
writableContext?.exec("ROLLBACK");
|
|
41390
|
+
if (hostLocked)
|
|
41391
|
+
writableHost.exec("ROLLBACK");
|
|
41392
|
+
writableContext?.close();
|
|
41393
|
+
writableHost.close();
|
|
41394
|
+
}
|
|
41395
|
+
options.report?.(`Deleted ${deletedIds.length} marked, recorded hidden sessions`);
|
|
41396
|
+
return { waiting, deleted: deletedIds.length, backup };
|
|
41397
|
+
}
|
|
41398
|
+
var PREFIX = "opencode2_hidden_children:", CASCADE_TABLES;
|
|
41399
|
+
var init_doctor_hidden_children = __esm(async () => {
|
|
41400
|
+
init_rpc_utils();
|
|
41401
|
+
await __promiseAll([
|
|
41402
|
+
init_sqlite(),
|
|
41403
|
+
init_doctor_repair_db()
|
|
41404
|
+
]);
|
|
41405
|
+
CASCADE_TABLES = [
|
|
41406
|
+
"instruction_entry",
|
|
41407
|
+
"instruction_state",
|
|
41408
|
+
"session_inbox",
|
|
41409
|
+
"session_message",
|
|
41410
|
+
"session_pending"
|
|
41411
|
+
];
|
|
41412
|
+
});
|
|
41413
|
+
|
|
40621
41414
|
// src/commands/doctor-opencode-plugin-duplicates.ts
|
|
40622
41415
|
import { isDeepStrictEqual } from "node:util";
|
|
40623
41416
|
function entryOptions(entry) {
|
|
@@ -40844,11 +41637,11 @@ function formatUnresolvedCompartmentSession(session) {
|
|
|
40844
41637
|
}
|
|
40845
41638
|
|
|
40846
41639
|
// src/commands/doctor-opencode.ts
|
|
40847
|
-
import { spawnSync as
|
|
40848
|
-
import { existsSync as
|
|
41640
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
41641
|
+
import { existsSync as existsSync40, mkdtempSync as mkdtempSync2, readFileSync as readFileSync28, rmSync as rmSync5 } from "node:fs";
|
|
40849
41642
|
import { createRequire as createRequire6 } from "node:module";
|
|
40850
|
-
import { homedir as
|
|
40851
|
-
import { join as
|
|
41643
|
+
import { homedir as homedir17, tmpdir as tmpdir3 } from "node:os";
|
|
41644
|
+
import { join as join33 } from "node:path";
|
|
40852
41645
|
function formatSharedDbRowCounts(db) {
|
|
40853
41646
|
return SHARED_DB_ROW_COUNT_TABLES.map((table) => {
|
|
40854
41647
|
try {
|
|
@@ -40879,7 +41672,8 @@ function findUnknownConfiguredModels(configured, catalog) {
|
|
|
40879
41672
|
return [];
|
|
40880
41673
|
});
|
|
40881
41674
|
}
|
|
40882
|
-
function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) =>
|
|
41675
|
+
function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) => spawnSync9("opencode", args, {
|
|
41676
|
+
windowsHide: true,
|
|
40883
41677
|
cwd,
|
|
40884
41678
|
encoding: "utf8",
|
|
40885
41679
|
timeout: hostGeneration === "v2" ? 90000 : 45000,
|
|
@@ -40916,7 +41710,7 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
|
|
|
40916
41710
|
}
|
|
40917
41711
|
if (models.length === 0)
|
|
40918
41712
|
return;
|
|
40919
|
-
const tempRoot =
|
|
41713
|
+
const tempRoot = mkdtempSync2(join33(tmpdir3(), "magic-context-opencode-catalog-"));
|
|
40920
41714
|
try {
|
|
40921
41715
|
const command = hostGeneration === "v2" ? ["api", "model.list", "--param", `directory=${projectDir}`] : ["models", "--verbose"];
|
|
40922
41716
|
const guidance = `opencode ${command.join(" ")}`;
|
|
@@ -41092,7 +41886,7 @@ function getSelfVersion2() {
|
|
|
41092
41886
|
function describeAutoUpdateStall(specifier, autoUpdateEnabled, storageDir = getMagicContextStorageDir()) {
|
|
41093
41887
|
if (!autoUpdateEnabled || !isPinnedOpenCodePluginSpecifier(specifier))
|
|
41094
41888
|
return null;
|
|
41095
|
-
const state = readAutoUpdateCheckState(
|
|
41889
|
+
const state = readAutoUpdateCheckState(join33(storageDir, AUTO_UPDATE_CHECK_STATE_FILENAME));
|
|
41096
41890
|
const owner = isUpdaterPinnedSpec(state, specifier) ? "updater" : "you";
|
|
41097
41891
|
return `auto-update: stalled — config pinned to ${specifier} (by ${owner})`;
|
|
41098
41892
|
}
|
|
@@ -41101,15 +41895,15 @@ function getUserNpmrcPath() {
|
|
|
41101
41895
|
if (custom)
|
|
41102
41896
|
return custom;
|
|
41103
41897
|
const home = process.env.HOME?.trim();
|
|
41104
|
-
return
|
|
41898
|
+
return join33(home || homedir17(), ".npmrc");
|
|
41105
41899
|
}
|
|
41106
41900
|
function collectNpmReleaseAgeWarnings() {
|
|
41107
41901
|
const ageWarnings = [];
|
|
41108
41902
|
const npmrcPath = getUserNpmrcPath();
|
|
41109
|
-
if (!
|
|
41903
|
+
if (!existsSync40(npmrcPath))
|
|
41110
41904
|
return ageWarnings;
|
|
41111
41905
|
try {
|
|
41112
|
-
const npmrc =
|
|
41906
|
+
const npmrc = readFileSync28(npmrcPath, "utf-8");
|
|
41113
41907
|
for (const line of npmrc.split(`
|
|
41114
41908
|
`)) {
|
|
41115
41909
|
const trimmed = line.trim();
|
|
@@ -41142,15 +41936,18 @@ function compareVersions(a, b) {
|
|
|
41142
41936
|
function openBrowser(url) {
|
|
41143
41937
|
try {
|
|
41144
41938
|
if (process.platform === "darwin") {
|
|
41145
|
-
const child =
|
|
41939
|
+
const child = spawnSync9("open", [url], { windowsHide: true, stdio: "ignore" });
|
|
41146
41940
|
if (child.status === 0)
|
|
41147
41941
|
return;
|
|
41148
41942
|
} else if (process.platform === "linux") {
|
|
41149
|
-
const child =
|
|
41943
|
+
const child = spawnSync9("xdg-open", [url], { windowsHide: true, stdio: "ignore" });
|
|
41150
41944
|
if (child.status === 0)
|
|
41151
41945
|
return;
|
|
41152
41946
|
} else if (process.platform === "win32") {
|
|
41153
|
-
const child =
|
|
41947
|
+
const child = spawnSync9("cmd", ["/c", "start", "", url], {
|
|
41948
|
+
windowsHide: true,
|
|
41949
|
+
stdio: "ignore"
|
|
41950
|
+
});
|
|
41154
41951
|
if (child.status === 0)
|
|
41155
41952
|
return;
|
|
41156
41953
|
}
|
|
@@ -41243,7 +42040,7 @@ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
|
|
|
41243
42040
|
return { issues: 0 };
|
|
41244
42041
|
}
|
|
41245
42042
|
async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
41246
|
-
if (!
|
|
42043
|
+
if (!existsSync40(magicContextConfigPath)) {
|
|
41247
42044
|
return checkLocalEmbeddingRuntimeForDoctor();
|
|
41248
42045
|
}
|
|
41249
42046
|
let rawText;
|
|
@@ -41400,7 +42197,7 @@ async function runDoctor2(options = {}) {
|
|
|
41400
42197
|
const v22Result = await runV22BackfillCommands({
|
|
41401
42198
|
name: "OpenCode",
|
|
41402
42199
|
openDatabase: (readonly = true) => {
|
|
41403
|
-
const dbPath =
|
|
42200
|
+
const dbPath = join33(getMagicContextStorageDir(), "context.db");
|
|
41404
42201
|
v22Db = readonly ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
41405
42202
|
return v22Db;
|
|
41406
42203
|
},
|
|
@@ -41432,7 +42229,7 @@ async function runDoctor2(options = {}) {
|
|
|
41432
42229
|
failCount++;
|
|
41433
42230
|
issues++;
|
|
41434
42231
|
};
|
|
41435
|
-
const authorityDbPath =
|
|
42232
|
+
const authorityDbPath = join33(getMagicContextStorageDir(), "context.db");
|
|
41436
42233
|
let authorityDb = null;
|
|
41437
42234
|
try {
|
|
41438
42235
|
authorityDb = openExistingContextDatabase(authorityDbPath, { readonly: true });
|
|
@@ -41486,6 +42283,19 @@ async function runDoctor2(options = {}) {
|
|
|
41486
42283
|
else
|
|
41487
42284
|
fail(openCodeDbCheck.message);
|
|
41488
42285
|
if (openCodeDbCheck.ok) {
|
|
42286
|
+
if (storeGeneration === "v2") {
|
|
42287
|
+
try {
|
|
42288
|
+
const cleanup = await cleanupRetiredHiddenChildren({
|
|
42289
|
+
contextDbPath: authorityDbPath,
|
|
42290
|
+
hostDbPath: openCodeDbResolution.path,
|
|
42291
|
+
fix: options.fix,
|
|
42292
|
+
report: (line) => log2.info(line)
|
|
42293
|
+
});
|
|
42294
|
+
fixed += cleanup.deleted;
|
|
42295
|
+
} catch (error) {
|
|
42296
|
+
fail(`Retired hidden-child cleanup refused: ${error instanceof Error ? error.message : String(error)}`);
|
|
42297
|
+
}
|
|
42298
|
+
}
|
|
41489
42299
|
let markerDb = null;
|
|
41490
42300
|
try {
|
|
41491
42301
|
markerDb = new Database(openCodeDbResolution.path, {
|
|
@@ -41593,7 +42403,7 @@ async function runDoctor2(options = {}) {
|
|
|
41593
42403
|
pass(`OpenCode config: ${paths.opencodeConfig}`);
|
|
41594
42404
|
}
|
|
41595
42405
|
let autoUpdateEnabled = true;
|
|
41596
|
-
if (
|
|
42406
|
+
if (existsSync40(paths.magicContextConfig)) {
|
|
41597
42407
|
pass(`Magic Context config: ${paths.magicContextConfig}`);
|
|
41598
42408
|
try {
|
|
41599
42409
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
@@ -41629,7 +42439,7 @@ async function runDoctor2(options = {}) {
|
|
|
41629
42439
|
warn(`No magic-context.jsonc found — using defaults`);
|
|
41630
42440
|
log2.info(" Run 'setup' to create one with model recommendations");
|
|
41631
42441
|
}
|
|
41632
|
-
if (
|
|
42442
|
+
if (existsSync40(paths.magicContextConfig)) {
|
|
41633
42443
|
try {
|
|
41634
42444
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
41635
42445
|
if (!raw)
|
|
@@ -41759,7 +42569,7 @@ async function runDoctor2(options = {}) {
|
|
|
41759
42569
|
};
|
|
41760
42570
|
if (paths.opencodeConfigFormat !== "none") {
|
|
41761
42571
|
try {
|
|
41762
|
-
const raw =
|
|
42572
|
+
const raw = readFileSync28(paths.opencodeConfig, "utf-8");
|
|
41763
42573
|
const config = import_comment_json11.parse(raw);
|
|
41764
42574
|
const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
|
|
41765
42575
|
if (checkPluginDuplicates(config, configName, options, {
|
|
@@ -41828,9 +42638,9 @@ async function runDoctor2(options = {}) {
|
|
|
41828
42638
|
pass("Added TUI sidebar plugin to tui.json");
|
|
41829
42639
|
warn("Restart OpenCode to see the sidebar");
|
|
41830
42640
|
fixed++;
|
|
41831
|
-
} else if (
|
|
42641
|
+
} else if (existsSync40(paths.tuiConfig)) {
|
|
41832
42642
|
try {
|
|
41833
|
-
const tuiRaw =
|
|
42643
|
+
const tuiRaw = readFileSync28(paths.tuiConfig, "utf-8");
|
|
41834
42644
|
const tuiConfig = import_comment_json11.parse(tuiRaw);
|
|
41835
42645
|
const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
|
|
41836
42646
|
const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
|
|
@@ -41868,7 +42678,7 @@ async function runDoctor2(options = {}) {
|
|
|
41868
42678
|
fail("Could not create or verify the TUI sidebar config");
|
|
41869
42679
|
}
|
|
41870
42680
|
}
|
|
41871
|
-
if (
|
|
42681
|
+
if (existsSync40(paths.magicContextConfig)) {
|
|
41872
42682
|
try {
|
|
41873
42683
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
41874
42684
|
if (!raw)
|
|
@@ -41890,9 +42700,9 @@ async function runDoctor2(options = {}) {
|
|
|
41890
42700
|
else
|
|
41891
42701
|
passCount++;
|
|
41892
42702
|
const storage = getMagicContextStorageResolution();
|
|
41893
|
-
const dbPath =
|
|
42703
|
+
const dbPath = join33(storage.path, "context.db");
|
|
41894
42704
|
log2.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
|
|
41895
|
-
if (!
|
|
42705
|
+
if (!existsSync40(dbPath)) {
|
|
41896
42706
|
log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
|
|
41897
42707
|
} else {
|
|
41898
42708
|
log2.info(`Shared context DB exists at ${dbPath}`);
|
|
@@ -41994,7 +42804,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41994
42804
|
let v2DistTag;
|
|
41995
42805
|
if (paths.opencodeConfigFormat !== "none") {
|
|
41996
42806
|
try {
|
|
41997
|
-
v2DistTag = configuredOpenCodeV2DistTag(import_comment_json11.parse(
|
|
42807
|
+
v2DistTag = configuredOpenCodeV2DistTag(import_comment_json11.parse(readFileSync28(paths.opencodeConfig, "utf-8")));
|
|
41998
42808
|
} catch {}
|
|
41999
42809
|
}
|
|
42000
42810
|
const v2Cache = reportOpenCodeV2PluginCache(checkOpenCodeV2PluginCache({
|
|
@@ -42121,16 +42931,17 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
42121
42931
|
init_v22_backfill_commands(),
|
|
42122
42932
|
init_doctor_authority(),
|
|
42123
42933
|
init_doctor_cached_plugin_fence(),
|
|
42124
|
-
init_doctor_harness_relabel()
|
|
42934
|
+
init_doctor_harness_relabel(),
|
|
42935
|
+
init_doctor_hidden_children()
|
|
42125
42936
|
]);
|
|
42126
42937
|
import_comment_json11 = __toESM(require_src3(), 1);
|
|
42127
42938
|
SHARED_DB_ROW_COUNT_TABLES = ["tags", "compartments", "memories", "notes", "dream_runs"];
|
|
42128
42939
|
});
|
|
42129
42940
|
|
|
42130
42941
|
// src/lib/diagnostics-pi.ts
|
|
42131
|
-
import { existsSync as
|
|
42942
|
+
import { existsSync as existsSync41, readdirSync as readdirSync8, readFileSync as readFileSync29, statSync as statSync16 } from "node:fs";
|
|
42132
42943
|
import { createRequire as createRequire7 } from "node:module";
|
|
42133
|
-
import { join as
|
|
42944
|
+
import { join as join34 } from "node:path";
|
|
42134
42945
|
function getSelfVersion3() {
|
|
42135
42946
|
const req = createRequire7(import.meta.url);
|
|
42136
42947
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
@@ -42145,7 +42956,7 @@ function getSelfVersion3() {
|
|
|
42145
42956
|
}
|
|
42146
42957
|
function fileSize2(path) {
|
|
42147
42958
|
try {
|
|
42148
|
-
return
|
|
42959
|
+
return existsSync41(path) ? statSync16(path).size : 0;
|
|
42149
42960
|
} catch {
|
|
42150
42961
|
return 0;
|
|
42151
42962
|
}
|
|
@@ -42157,11 +42968,11 @@ function sanitizeValue2(value) {
|
|
|
42157
42968
|
return sanitizeConfigValue(value);
|
|
42158
42969
|
}
|
|
42159
42970
|
function readJsonc(path) {
|
|
42160
|
-
if (!
|
|
42971
|
+
if (!existsSync41(path))
|
|
42161
42972
|
return { value: {} };
|
|
42162
42973
|
try {
|
|
42163
42974
|
return {
|
|
42164
|
-
value: import_comment_json12.parse(
|
|
42975
|
+
value: import_comment_json12.parse(readFileSync29(path, "utf-8"))
|
|
42165
42976
|
};
|
|
42166
42977
|
} catch (error) {
|
|
42167
42978
|
return {
|
|
@@ -42177,7 +42988,7 @@ function readConfigDiagnostic(path) {
|
|
|
42177
42988
|
const parsed = readJsonc(path);
|
|
42178
42989
|
return {
|
|
42179
42990
|
path,
|
|
42180
|
-
exists:
|
|
42991
|
+
exists: existsSync41(path),
|
|
42181
42992
|
...parsed.parseError ? { parseError: parsed.parseError } : {},
|
|
42182
42993
|
flags: sanitizeValue2(parsed.value)
|
|
42183
42994
|
};
|
|
@@ -42195,25 +43006,25 @@ function reverseSlugToDirectory(slug) {
|
|
|
42195
43006
|
}
|
|
42196
43007
|
function collectPiRecentSessions() {
|
|
42197
43008
|
const sessionsRoot = getPiSessionsRoot();
|
|
42198
|
-
if (!
|
|
43009
|
+
if (!existsSync41(sessionsRoot))
|
|
42199
43010
|
return [];
|
|
42200
43011
|
try {
|
|
42201
|
-
const slugs =
|
|
43012
|
+
const slugs = readdirSync8(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
42202
43013
|
const candidates = [];
|
|
42203
43014
|
for (const slug of slugs) {
|
|
42204
43015
|
const directory = reverseSlugToDirectory(slug);
|
|
42205
43016
|
if (!directory)
|
|
42206
43017
|
continue;
|
|
42207
|
-
const slugDir =
|
|
43018
|
+
const slugDir = join34(sessionsRoot, slug);
|
|
42208
43019
|
let files;
|
|
42209
43020
|
try {
|
|
42210
|
-
files =
|
|
43021
|
+
files = readdirSync8(slugDir).filter((name) => name.endsWith(".jsonl"));
|
|
42211
43022
|
} catch {
|
|
42212
43023
|
continue;
|
|
42213
43024
|
}
|
|
42214
43025
|
for (const file of files) {
|
|
42215
43026
|
try {
|
|
42216
|
-
const mtime = statSync16(
|
|
43027
|
+
const mtime = statSync16(join34(slugDir, file)).mtimeMs;
|
|
42217
43028
|
const sessionId = file.replace(/\.jsonl$/, "");
|
|
42218
43029
|
candidates.push({ sessionId, directory, mtime });
|
|
42219
43030
|
} catch {}
|
|
@@ -42231,7 +43042,7 @@ function collectPiRecentSessions() {
|
|
|
42231
43042
|
}
|
|
42232
43043
|
function parseHistorianDumpMeta2(path) {
|
|
42233
43044
|
try {
|
|
42234
|
-
const xml =
|
|
43045
|
+
const xml = readFileSync29(path, "utf-8");
|
|
42235
43046
|
const parsed = parseCompartmentOutput(xml);
|
|
42236
43047
|
const factCountByCategory = {};
|
|
42237
43048
|
for (const fact of parsed.facts) {
|
|
@@ -42264,11 +43075,11 @@ function parseHistorianDumpMeta2(path) {
|
|
|
42264
43075
|
}
|
|
42265
43076
|
}
|
|
42266
43077
|
function listDumpsInDir2(dir, limit) {
|
|
42267
|
-
if (!
|
|
43078
|
+
if (!existsSync41(dir))
|
|
42268
43079
|
return { count: 0, recent: [] };
|
|
42269
43080
|
try {
|
|
42270
|
-
const entries =
|
|
42271
|
-
const stat = statSync16(
|
|
43081
|
+
const entries = readdirSync8(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
43082
|
+
const stat = statSync16(join34(dir, name));
|
|
42272
43083
|
return {
|
|
42273
43084
|
name,
|
|
42274
43085
|
mtime: stat.mtimeMs,
|
|
@@ -42277,7 +43088,7 @@ function listDumpsInDir2(dir, limit) {
|
|
|
42277
43088
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
42278
43089
|
const now = Date.now();
|
|
42279
43090
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
42280
|
-
const meta = parseHistorianDumpMeta2(
|
|
43091
|
+
const meta = parseHistorianDumpMeta2(join34(dir, entry.name));
|
|
42281
43092
|
const summary = {
|
|
42282
43093
|
name: entry.name,
|
|
42283
43094
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -42341,7 +43152,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
42341
43152
|
const loaded = loadPiConfig({ cwd });
|
|
42342
43153
|
const storageResolution = getMagicContextStorageResolution();
|
|
42343
43154
|
const storageDirPath = storageResolution.path;
|
|
42344
|
-
const dbPath =
|
|
43155
|
+
const dbPath = join34(storageDirPath, "context.db");
|
|
42345
43156
|
const logFiles = inspectMagicContextLogs("pi");
|
|
42346
43157
|
const primaryLog = logFiles.find((file) => file.exists) ?? logFiles[0];
|
|
42347
43158
|
const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
|
|
@@ -42358,7 +43169,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
42358
43169
|
piVersion: pi ? getPiVersion(pi.path) : null,
|
|
42359
43170
|
settings: {
|
|
42360
43171
|
path: settingsPath,
|
|
42361
|
-
exists:
|
|
43172
|
+
exists: existsSync41(settingsPath),
|
|
42362
43173
|
...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
|
|
42363
43174
|
hasMagicContextPackage: hasPiMagicContextPackage(packages),
|
|
42364
43175
|
packages: sanitizeValue2(packages)
|
|
@@ -42375,7 +43186,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
42375
43186
|
storageDir: {
|
|
42376
43187
|
path: storageDirPath,
|
|
42377
43188
|
source: storageResolution.source,
|
|
42378
|
-
exists:
|
|
43189
|
+
exists: existsSync41(storageDirPath),
|
|
42379
43190
|
contextDbSizeBytes: fileSize2(dbPath)
|
|
42380
43191
|
},
|
|
42381
43192
|
conflicts: {
|
|
@@ -42480,8 +43291,8 @@ var init_diagnostics_pi = __esm(() => {
|
|
|
42480
43291
|
});
|
|
42481
43292
|
|
|
42482
43293
|
// src/lib/logs-pi.ts
|
|
42483
|
-
import { mkdirSync as
|
|
42484
|
-
import { dirname as
|
|
43294
|
+
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
43295
|
+
import { dirname as dirname21, join as join35 } from "node:path";
|
|
42485
43296
|
function sanitizeLogContent2(content) {
|
|
42486
43297
|
return sanitizeString2(content);
|
|
42487
43298
|
}
|
|
@@ -42551,13 +43362,13 @@ async function bundleIssueReport2(report, description, title, options = {}) {
|
|
|
42551
43362
|
const truncated = bodyMarkdown !== rawBodyMarkdown;
|
|
42552
43363
|
const cwd = options.cwd ?? process.cwd();
|
|
42553
43364
|
const timestamp = formatTimestamp2(options.now ?? new Date);
|
|
42554
|
-
const path = options.outputPath ??
|
|
42555
|
-
|
|
42556
|
-
|
|
43365
|
+
const path = options.outputPath ?? join35(cwd, `magic-context-pi-issue-${timestamp}.md`);
|
|
43366
|
+
mkdirSync12(dirname21(path), { recursive: true });
|
|
43367
|
+
writeFileSync11(path, `${bodyMarkdown}
|
|
42557
43368
|
`);
|
|
42558
|
-
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` :
|
|
43369
|
+
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` : join35(cwd, `magic-context-pi-issue-${timestamp}-full.md`) : undefined;
|
|
42559
43370
|
if (fullPath)
|
|
42560
|
-
|
|
43371
|
+
writeFileSync11(fullPath, `${rawBodyMarkdown}
|
|
42561
43372
|
`);
|
|
42562
43373
|
return { path, bodyMarkdown, ...fullPath ? { fullPath } : {}, truncated };
|
|
42563
43374
|
}
|
|
@@ -42568,11 +43379,11 @@ var init_logs_pi = __esm(() => {
|
|
|
42568
43379
|
});
|
|
42569
43380
|
|
|
42570
43381
|
// src/commands/doctor-pi.ts
|
|
42571
|
-
import { execFileSync as
|
|
42572
|
-
import { existsSync as
|
|
43382
|
+
import { execFileSync as execFileSync7, spawnSync as spawnSync10 } from "node:child_process";
|
|
43383
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync13, readdirSync as readdirSync9, readFileSync as readFileSync30, rmSync as rmSync6, statSync as statSync17 } from "node:fs";
|
|
42573
43384
|
import { createRequire as createRequire8 } from "node:module";
|
|
42574
|
-
import { homedir as
|
|
42575
|
-
import { dirname as
|
|
43385
|
+
import { homedir as homedir18 } from "node:os";
|
|
43386
|
+
import { dirname as dirname22, isAbsolute as isAbsolute8, join as join36 } from "node:path";
|
|
42576
43387
|
function depsFrom(options) {
|
|
42577
43388
|
return {
|
|
42578
43389
|
...DEFAULT_DEPS5,
|
|
@@ -42609,7 +43420,8 @@ function selfVersion2() {
|
|
|
42609
43420
|
}
|
|
42610
43421
|
function getLatestNpmVersion(packageName) {
|
|
42611
43422
|
try {
|
|
42612
|
-
return
|
|
43423
|
+
return execFileSync7("npm", ["view", packageName, "version"], {
|
|
43424
|
+
windowsHide: true,
|
|
42613
43425
|
encoding: "utf-8",
|
|
42614
43426
|
stdio: ["ignore", "pipe", "ignore"],
|
|
42615
43427
|
timeout: 1e4
|
|
@@ -42663,7 +43475,7 @@ function summarize(results) {
|
|
|
42663
43475
|
function readJsonc2(path) {
|
|
42664
43476
|
try {
|
|
42665
43477
|
return {
|
|
42666
|
-
value: import_comment_json13.parse(
|
|
43478
|
+
value: import_comment_json13.parse(readFileSync30(path, "utf-8"))
|
|
42667
43479
|
};
|
|
42668
43480
|
} catch (error) {
|
|
42669
43481
|
return {
|
|
@@ -42713,15 +43525,15 @@ function piPluginDirCandidates(packages, cwd) {
|
|
|
42713
43525
|
if (resolved)
|
|
42714
43526
|
dirs.push(resolved);
|
|
42715
43527
|
}
|
|
42716
|
-
dirs.push(
|
|
42717
|
-
dirs.push(
|
|
42718
|
-
return dirs.filter((dir) =>
|
|
43528
|
+
dirs.push(join36(agentDir, "npm", "node_modules", PACKAGE_NAME2));
|
|
43529
|
+
dirs.push(join36(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
|
|
43530
|
+
return dirs.filter((dir) => existsSync42(join36(dir, "package.json")));
|
|
42719
43531
|
}
|
|
42720
43532
|
function projectConfigPath(cwd) {
|
|
42721
43533
|
return resolveCortexKitProjectConfigPath(cwd);
|
|
42722
43534
|
}
|
|
42723
43535
|
function readConfigForEmbedding(path, isProjectConfig) {
|
|
42724
|
-
if (!
|
|
43536
|
+
if (!existsSync42(path))
|
|
42725
43537
|
return null;
|
|
42726
43538
|
try {
|
|
42727
43539
|
const raw = loadRawConfigFile({
|
|
@@ -42807,22 +43619,22 @@ function pinnedVersionFromPackageSpecifier(specifier) {
|
|
|
42807
43619
|
}
|
|
42808
43620
|
function cacheRoots(cwd) {
|
|
42809
43621
|
const home = process.env.HOME?.trim();
|
|
42810
|
-
const cacheHome = process.env.XDG_CACHE_HOME ||
|
|
43622
|
+
const cacheHome = process.env.XDG_CACHE_HOME || join36(home || homedir18(), ".cache");
|
|
42811
43623
|
const piCacheRoot = getPiCacheRoot();
|
|
42812
43624
|
return [
|
|
42813
|
-
|
|
42814
|
-
|
|
42815
|
-
|
|
42816
|
-
|
|
42817
|
-
|
|
42818
|
-
|
|
42819
|
-
|
|
43625
|
+
join36(piCacheRoot, "extensions"),
|
|
43626
|
+
join36(piCacheRoot, "packages"),
|
|
43627
|
+
join36(cacheHome, "pi", "extensions"),
|
|
43628
|
+
join36(cacheHome, "pi", "packages"),
|
|
43629
|
+
join36(getPiAgentConfigDir(), "cache", "extensions"),
|
|
43630
|
+
join36(getPiAgentConfigDir(), "npm", "node_modules", PACKAGE_NAME2),
|
|
43631
|
+
join36(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2)
|
|
42820
43632
|
];
|
|
42821
43633
|
}
|
|
42822
43634
|
function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
42823
43635
|
const found = new Map;
|
|
42824
43636
|
const visit = (path, depth) => {
|
|
42825
|
-
if (depth < 0 || !
|
|
43637
|
+
if (depth < 0 || !existsSync42(path))
|
|
42826
43638
|
return;
|
|
42827
43639
|
let stat;
|
|
42828
43640
|
try {
|
|
@@ -42832,10 +43644,10 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
|
42832
43644
|
}
|
|
42833
43645
|
if (!stat.isDirectory())
|
|
42834
43646
|
return;
|
|
42835
|
-
const packageJson =
|
|
42836
|
-
if (
|
|
43647
|
+
const packageJson = join36(path, "package.json");
|
|
43648
|
+
if (existsSync42(packageJson)) {
|
|
42837
43649
|
try {
|
|
42838
|
-
const pkg = JSON.parse(
|
|
43650
|
+
const pkg = JSON.parse(readFileSync30(packageJson, "utf-8"));
|
|
42839
43651
|
const name = typeof pkg.name === "string" ? pkg.name : "";
|
|
42840
43652
|
const version = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
42841
43653
|
if (name === PACKAGE_NAME2) {
|
|
@@ -42850,12 +43662,12 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
|
42850
43662
|
}
|
|
42851
43663
|
let entries = [];
|
|
42852
43664
|
try {
|
|
42853
|
-
entries =
|
|
43665
|
+
entries = readdirSync9(path);
|
|
42854
43666
|
} catch {
|
|
42855
43667
|
return;
|
|
42856
43668
|
}
|
|
42857
43669
|
for (const entry of entries)
|
|
42858
|
-
visit(
|
|
43670
|
+
visit(join36(path, entry), depth - 1);
|
|
42859
43671
|
};
|
|
42860
43672
|
for (const root of cacheRoots(cwd))
|
|
42861
43673
|
visit(root, 5);
|
|
@@ -42900,7 +43712,7 @@ async function runHealthChecks2(options) {
|
|
|
42900
43712
|
}
|
|
42901
43713
|
const settingsPath = getPiUserExtensionsPath();
|
|
42902
43714
|
let packages = [];
|
|
42903
|
-
if (!
|
|
43715
|
+
if (!existsSync42(settingsPath)) {
|
|
42904
43716
|
add2(results, "fail", `Pi settings not found at ${settingsPath}`);
|
|
42905
43717
|
repairPlan.addPackageEntry = true;
|
|
42906
43718
|
} else {
|
|
@@ -42924,7 +43736,7 @@ async function runHealthChecks2(options) {
|
|
|
42924
43736
|
["user", userConfigPath, true],
|
|
42925
43737
|
["project", projectPath, false]
|
|
42926
43738
|
]) {
|
|
42927
|
-
if (!
|
|
43739
|
+
if (!existsSync42(path)) {
|
|
42928
43740
|
if (required) {
|
|
42929
43741
|
add2(results, "warn", `No ${label} magic-context.jsonc found at ${path}`);
|
|
42930
43742
|
if (userConfigMigrationRefused) {
|
|
@@ -42964,9 +43776,9 @@ async function runHealthChecks2(options) {
|
|
|
42964
43776
|
}
|
|
42965
43777
|
const storage = getMagicContextStorageResolution();
|
|
42966
43778
|
const storageDir = storage.path;
|
|
42967
|
-
const dbPath =
|
|
43779
|
+
const dbPath = join36(storageDir, "context.db");
|
|
42968
43780
|
add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
|
|
42969
|
-
const existedBeforeOpen =
|
|
43781
|
+
const existedBeforeOpen = existsSync42(dbPath);
|
|
42970
43782
|
if (existedBeforeOpen)
|
|
42971
43783
|
add2(results, "pass", `Shared context DB exists at ${dbPath}`);
|
|
42972
43784
|
else
|
|
@@ -43184,7 +43996,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
43184
43996
|
return { results, repairPlan, ...summarize(results) };
|
|
43185
43997
|
}
|
|
43186
43998
|
function writeDefaultMagicContextConfig(path) {
|
|
43187
|
-
|
|
43999
|
+
mkdirSync13(dirname22(path), { recursive: true });
|
|
43188
44000
|
const config = {
|
|
43189
44001
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
43190
44002
|
...MagicContextConfigSchema.parse({})
|
|
@@ -43206,7 +44018,7 @@ function repair2(plan, prompts) {
|
|
|
43206
44018
|
}
|
|
43207
44019
|
if (plan.writeUserConfig) {
|
|
43208
44020
|
const configPath = getPiUserConfigPath();
|
|
43209
|
-
if (!
|
|
44021
|
+
if (!existsSync42(configPath)) {
|
|
43210
44022
|
try {
|
|
43211
44023
|
writeDefaultMagicContextConfig(configPath);
|
|
43212
44024
|
prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
|
|
@@ -43230,6 +44042,7 @@ function repair2(plan, prompts) {
|
|
|
43230
44042
|
function runGhCommandWithDeps2(deps, args) {
|
|
43231
44043
|
if (args[0] === "issue") {
|
|
43232
44044
|
const result = deps.spawnSync("gh", args, {
|
|
44045
|
+
windowsHide: true,
|
|
43233
44046
|
encoding: "utf-8",
|
|
43234
44047
|
stdio: ["ignore", "pipe", "pipe"]
|
|
43235
44048
|
});
|
|
@@ -43241,6 +44054,7 @@ function runGhCommandWithDeps2(deps, args) {
|
|
|
43241
44054
|
}
|
|
43242
44055
|
try {
|
|
43243
44056
|
const output = deps.execFileSync("gh", args, {
|
|
44057
|
+
windowsHide: true,
|
|
43244
44058
|
encoding: "utf-8",
|
|
43245
44059
|
stdio: ["ignore", "pipe", "pipe"]
|
|
43246
44060
|
});
|
|
@@ -43258,7 +44072,7 @@ async function runIssueFlow3(options) {
|
|
|
43258
44072
|
if (options.reportPath) {
|
|
43259
44073
|
try {
|
|
43260
44074
|
const report = await options.deps.collectDiagnostics(options.cwd);
|
|
43261
|
-
const outputPath = isAbsolute8(options.reportPath) ? options.reportPath :
|
|
44075
|
+
const outputPath = isAbsolute8(options.reportPath) ? options.reportPath : join36(options.cwd, options.reportPath);
|
|
43262
44076
|
const bundled = await bundleIssueReport2(report, "Generated non-interactively by `doctor --issue --report`.", "Magic Context diagnostic report", { cwd: options.cwd, now: options.deps.now(), outputPath });
|
|
43263
44077
|
options.prompts.log.info(`Report written to ${bundled.path}`);
|
|
43264
44078
|
return 0;
|
|
@@ -43342,7 +44156,7 @@ async function runDoctor3(options = {}) {
|
|
|
43342
44156
|
const v22Result = await runV22BackfillCommands({
|
|
43343
44157
|
name: "Pi",
|
|
43344
44158
|
openDatabase: (readonly = true) => {
|
|
43345
|
-
const dbPath =
|
|
44159
|
+
const dbPath = join36(getMagicContextStorageDir(), "context.db");
|
|
43346
44160
|
v22Db = readonly ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
43347
44161
|
return v22Db;
|
|
43348
44162
|
},
|
|
@@ -43384,7 +44198,7 @@ async function runDoctor3(options = {}) {
|
|
|
43384
44198
|
prompts.outro(first.fail > 0 ? "Doctor found failures" : "Doctor complete");
|
|
43385
44199
|
return first.fail > 0 ? 1 : 0;
|
|
43386
44200
|
}
|
|
43387
|
-
function
|
|
44201
|
+
function valueAfter2(args, flag) {
|
|
43388
44202
|
const index = args.indexOf(flag);
|
|
43389
44203
|
if (index === -1)
|
|
43390
44204
|
return null;
|
|
@@ -43394,8 +44208,8 @@ function valueAfter3(args, flag) {
|
|
|
43394
44208
|
return next;
|
|
43395
44209
|
}
|
|
43396
44210
|
function parseDoctorArgs(args) {
|
|
43397
|
-
const rekeyV22DirIdentity =
|
|
43398
|
-
const report =
|
|
44211
|
+
const rekeyV22DirIdentity = valueAfter2(args, "--rekey-v22-dir-identity");
|
|
44212
|
+
const report = valueAfter2(args, "--report");
|
|
43399
44213
|
return {
|
|
43400
44214
|
force: args.includes("--force"),
|
|
43401
44215
|
issue: args.includes("--issue") || report !== null,
|
|
@@ -43452,14 +44266,14 @@ var init_doctor_pi = __esm(async () => {
|
|
|
43452
44266
|
probeEmbeddingEndpoint,
|
|
43453
44267
|
openExistingContextDatabase,
|
|
43454
44268
|
now: () => new Date,
|
|
43455
|
-
execFileSync:
|
|
43456
|
-
spawnSync:
|
|
44269
|
+
execFileSync: execFileSync7,
|
|
44270
|
+
spawnSync: spawnSync10
|
|
43457
44271
|
};
|
|
43458
44272
|
});
|
|
43459
44273
|
|
|
43460
44274
|
// src/commands/doctor.ts
|
|
43461
|
-
import { existsSync as
|
|
43462
|
-
import { join as
|
|
44275
|
+
import { existsSync as existsSync43, rmSync as rmSync7 } from "node:fs";
|
|
44276
|
+
import { join as join37 } from "node:path";
|
|
43463
44277
|
async function runDoctor4(options) {
|
|
43464
44278
|
if (options.clear)
|
|
43465
44279
|
return runClear();
|
|
@@ -43477,7 +44291,7 @@ async function runDoctor4(options) {
|
|
|
43477
44291
|
const result = await runV22BackfillCommands({
|
|
43478
44292
|
name: "Magic Context",
|
|
43479
44293
|
openDatabase: (readonly = true) => {
|
|
43480
|
-
const dbPath =
|
|
44294
|
+
const dbPath = join37(getMagicContextStorageDir(), "context.db");
|
|
43481
44295
|
v22Db = readonly ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
43482
44296
|
return v22Db;
|
|
43483
44297
|
},
|
|
@@ -43490,8 +44304,14 @@ async function runDoctor4(options) {
|
|
|
43490
44304
|
if (result.handled)
|
|
43491
44305
|
return result.exitCode;
|
|
43492
44306
|
}
|
|
44307
|
+
try {
|
|
44308
|
+
for (const line of diagnoseIdentitySplits())
|
|
44309
|
+
log2.warn(line);
|
|
44310
|
+
} catch (error) {
|
|
44311
|
+
log2.warn(`Identity split check unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
44312
|
+
}
|
|
43493
44313
|
await init_migrate();
|
|
43494
|
-
const sweepDbPath =
|
|
44314
|
+
const sweepDbPath = join37(getMagicContextStorageDir(), "context.db");
|
|
43495
44315
|
let sweepDb = null;
|
|
43496
44316
|
try {
|
|
43497
44317
|
sweepDb = openExistingContextDatabaseForMutation(sweepDbPath);
|
|
@@ -43605,7 +44425,7 @@ async function runClear() {
|
|
|
43605
44425
|
failed += 1;
|
|
43606
44426
|
continue;
|
|
43607
44427
|
}
|
|
43608
|
-
} else if (
|
|
44428
|
+
} else if (existsSync43(item.path)) {
|
|
43609
44429
|
rmSync7(item.path, { recursive: true, force: true });
|
|
43610
44430
|
}
|
|
43611
44431
|
s.stop(`Cleared ${item.path}`);
|
|
@@ -43635,6 +44455,7 @@ var init_doctor = __esm(async () => {
|
|
|
43635
44455
|
await __promiseAll([
|
|
43636
44456
|
init_database_access(),
|
|
43637
44457
|
init_v22_backfill_commands(),
|
|
44458
|
+
init_doctor_identity_splits(),
|
|
43638
44459
|
init_doctor_omp(),
|
|
43639
44460
|
init_doctor_opencode(),
|
|
43640
44461
|
init_doctor_pi()
|
|
@@ -43696,7 +44517,7 @@ var DOCTOR_HELP = [
|
|
|
43696
44517
|
" drain-authority <project> Drain module memory/note authority back to TypeScript",
|
|
43697
44518
|
" migrate Migrate an OpenCode session to Pi or OMP JSONL",
|
|
43698
44519
|
" migrate-session Re-home an OpenCode session to another directory",
|
|
43699
|
-
" merge-
|
|
44520
|
+
" merge-identities Preview or explicitly merge split identities",
|
|
43700
44521
|
" repair-db Back up and salvage a corrupted shared database",
|
|
43701
44522
|
" list-hidden-sessions List Magic Context OpenCode 2 roots",
|
|
43702
44523
|
""
|
|
@@ -43712,16 +44533,19 @@ var DRAIN_AUTHORITY_HELP = [
|
|
|
43712
44533
|
`);
|
|
43713
44534
|
var MERGE_IDENTITY_HELP = [
|
|
43714
44535
|
"",
|
|
43715
|
-
" Usage: magic-context doctor merge-
|
|
44536
|
+
" Usage: magic-context doctor merge-identities [--from <identity> --to <identity>] [--apply] [--force] [--db <path>]",
|
|
43716
44537
|
"",
|
|
43717
44538
|
" Merge every project-scoped row from one project identity into another.",
|
|
43718
44539
|
"",
|
|
43719
44540
|
" Options:",
|
|
43720
44541
|
" --from <identity> Identity whose rows are moved",
|
|
43721
44542
|
" --to <identity> Identity that receives them",
|
|
43722
|
-
"
|
|
43723
|
-
" --
|
|
44543
|
+
" (no flags) List splits; --from/--to previews without writing",
|
|
44544
|
+
" --apply Confirm the reviewed preview; hosts must be closed",
|
|
44545
|
+
" --force Permit a target not resolving on this machine",
|
|
43724
44546
|
" --db <path> Use this context.db instead of the shared one",
|
|
44547
|
+
" --host-db <path> Read session directories from this host database",
|
|
44548
|
+
" Legacy alias: doctor merge-identity; --dry-run previews, --yes applies",
|
|
43725
44549
|
""
|
|
43726
44550
|
].join(`
|
|
43727
44551
|
`);
|
|
@@ -43745,7 +44569,7 @@ function subcommandHelp(argv) {
|
|
|
43745
44569
|
const subcommand = rest[0];
|
|
43746
44570
|
if (subcommand === "drain-authority")
|
|
43747
44571
|
return DRAIN_AUTHORITY_HELP;
|
|
43748
|
-
if (subcommand === "merge-identity")
|
|
44572
|
+
if (subcommand === "merge-identity" || subcommand === "merge-identities")
|
|
43749
44573
|
return MERGE_IDENTITY_HELP;
|
|
43750
44574
|
if (subcommand === "list-hidden-sessions")
|
|
43751
44575
|
return LIST_HIDDEN_SESSIONS_HELP;
|
|
@@ -43794,7 +44618,7 @@ function getVersion() {
|
|
|
43794
44618
|
}
|
|
43795
44619
|
return "0.0.0";
|
|
43796
44620
|
}
|
|
43797
|
-
function
|
|
44621
|
+
function valueAfter3(args, flag) {
|
|
43798
44622
|
const index = args.indexOf(flag);
|
|
43799
44623
|
if (index === -1)
|
|
43800
44624
|
return null;
|
|
@@ -43879,7 +44703,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
43879
44703
|
]);
|
|
43880
44704
|
return runDoctorDrainAuthority(projectRoot, join(getMagicContextStorageDir(), "context.db"));
|
|
43881
44705
|
}
|
|
43882
|
-
if (rest[0] === "merge-identity") {
|
|
44706
|
+
if (rest[0] === "merge-identities" || rest[0] === "merge-identity") {
|
|
43883
44707
|
await init_doctor_merge_identity();
|
|
43884
44708
|
return runMergeIdentityCli(rest.slice(1));
|
|
43885
44709
|
}
|
|
@@ -43900,8 +44724,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
43900
44724
|
return runMigrateSessionCli(rest.slice(1));
|
|
43901
44725
|
}
|
|
43902
44726
|
await init_doctor();
|
|
43903
|
-
const rekeyV22DirIdentity =
|
|
43904
|
-
const report =
|
|
44727
|
+
const rekeyV22DirIdentity = valueAfter3(rest, "--rekey-v22-dir-identity");
|
|
44728
|
+
const report = valueAfter3(rest, "--report");
|
|
43905
44729
|
return runDoctor4({
|
|
43906
44730
|
force: rest.includes("--force"),
|
|
43907
44731
|
fix: rest.includes("--fix"),
|