@cortexkit/magic-context 0.36.1 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1414 -350
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3067,10 +3067,11 @@ function detectOmpBinary() {
|
|
|
3067
3067
|
const candidate = candidates.find((path2) => isExecutableFile(path2));
|
|
3068
3068
|
return candidate ? { path: candidate, source: "home" } : null;
|
|
3069
3069
|
}
|
|
3070
|
-
function runOmpCommand(ompPath, args, timeout = 30000) {
|
|
3070
|
+
function runOmpCommand(ompPath, args, timeout = 30000, overrides = {}) {
|
|
3071
|
+
const deps = { ...DEFAULT_COMMAND_EXECUTION_DEPS, ...overrides };
|
|
3071
3072
|
try {
|
|
3072
|
-
const invocation =
|
|
3073
|
-
const result =
|
|
3073
|
+
const invocation = deps.getInvocation(ompPath, args);
|
|
3074
|
+
const result = deps.spawnSync(invocation.command, invocation.args, {
|
|
3074
3075
|
encoding: "utf-8",
|
|
3075
3076
|
timeout,
|
|
3076
3077
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -3161,11 +3162,15 @@ function getOmpSetting(ompPath, key) {
|
|
|
3161
3162
|
return null;
|
|
3162
3163
|
}
|
|
3163
3164
|
}
|
|
3164
|
-
var OMP_PLUGIN_PACKAGE = "@cortexkit/pi-magic-context";
|
|
3165
|
+
var OMP_PLUGIN_PACKAGE = "@cortexkit/pi-magic-context", DEFAULT_COMMAND_EXECUTION_DEPS;
|
|
3165
3166
|
var init_omp_helpers = __esm(() => {
|
|
3166
3167
|
init_find_on_path();
|
|
3167
3168
|
init_paths();
|
|
3168
3169
|
init_pi_helpers();
|
|
3170
|
+
DEFAULT_COMMAND_EXECUTION_DEPS = {
|
|
3171
|
+
getInvocation: getOmpCommandInvocation,
|
|
3172
|
+
spawnSync: spawnSync2
|
|
3173
|
+
};
|
|
3169
3174
|
});
|
|
3170
3175
|
|
|
3171
3176
|
// src/adapters/omp.ts
|
|
@@ -3176,14 +3181,18 @@ class OmpAdapter {
|
|
|
3176
3181
|
kind = "omp";
|
|
3177
3182
|
displayName = "Oh My Pi (OMP)";
|
|
3178
3183
|
pluginPackageName = OMP_PLUGIN_PACKAGE;
|
|
3184
|
+
deps;
|
|
3185
|
+
constructor(deps = {}) {
|
|
3186
|
+
this.deps = { ...DEFAULT_DEPS, ...deps };
|
|
3187
|
+
}
|
|
3179
3188
|
isInstalled() {
|
|
3180
|
-
return detectOmpBinary() !== null;
|
|
3189
|
+
return this.deps.detectOmpBinary() !== null;
|
|
3181
3190
|
}
|
|
3182
3191
|
hasPluginEntry() {
|
|
3183
|
-
const omp = detectOmpBinary();
|
|
3192
|
+
const omp = this.deps.detectOmpBinary();
|
|
3184
3193
|
if (!omp)
|
|
3185
3194
|
return false;
|
|
3186
|
-
return listOmpPlugins(omp.path)?.some((plugin) => plugin.name === OMP_PLUGIN_PACKAGE && plugin.enabled) ?? false;
|
|
3195
|
+
return this.deps.listOmpPlugins(omp.path)?.some((plugin) => plugin.name === OMP_PLUGIN_PACKAGE && plugin.enabled) ?? false;
|
|
3187
3196
|
}
|
|
3188
3197
|
getConfigPaths() {
|
|
3189
3198
|
return {
|
|
@@ -3195,10 +3204,10 @@ class OmpAdapter {
|
|
|
3195
3204
|
}
|
|
3196
3205
|
async ensurePluginEntry() {
|
|
3197
3206
|
const configPath = getOmpPluginsLockPath();
|
|
3198
|
-
const omp = detectOmpBinary();
|
|
3207
|
+
const omp = this.deps.detectOmpBinary();
|
|
3199
3208
|
if (!omp)
|
|
3200
3209
|
return this.errorResult(configPath, "OMP binary not found");
|
|
3201
|
-
const plugins = listOmpPlugins(omp.path);
|
|
3210
|
+
const plugins = this.deps.listOmpPlugins(omp.path);
|
|
3202
3211
|
if (plugins === null) {
|
|
3203
3212
|
return this.errorResult(configPath, "`omp plugin list --json` failed");
|
|
3204
3213
|
}
|
|
@@ -3213,16 +3222,16 @@ class OmpAdapter {
|
|
|
3213
3222
|
}
|
|
3214
3223
|
const originalRuntimeEnabled = this.readRuntimeEnabled(configPath);
|
|
3215
3224
|
const args = installed ? ["plugin", "enable", OMP_PLUGIN_PACKAGE] : ["plugin", "install", OMP_PLUGIN_PACKAGE];
|
|
3216
|
-
const result = runOmpCommand(omp.path, args, 120000);
|
|
3225
|
+
const result = this.deps.runOmpCommand(omp.path, args, 120000);
|
|
3217
3226
|
if (!result.ok) {
|
|
3218
3227
|
return this.errorResult(configPath, result.stderr || result.stdout || `omp ${args.join(" ")} failed`);
|
|
3219
3228
|
}
|
|
3220
|
-
const enabledAfter = listOmpPlugins(omp.path)?.some((plugin) => plugin.name === OMP_PLUGIN_PACKAGE && plugin.enabled);
|
|
3229
|
+
const enabledAfter = this.deps.listOmpPlugins(omp.path)?.some((plugin) => plugin.name === OMP_PLUGIN_PACKAGE && plugin.enabled);
|
|
3221
3230
|
if (!enabledAfter) {
|
|
3222
3231
|
if (!installed) {
|
|
3223
|
-
runOmpCommand(omp.path, ["plugin", "uninstall", OMP_PLUGIN_PACKAGE], 120000);
|
|
3232
|
+
this.deps.runOmpCommand(omp.path, ["plugin", "uninstall", OMP_PLUGIN_PACKAGE], 120000);
|
|
3224
3233
|
} else if (originalRuntimeEnabled !== undefined) {
|
|
3225
|
-
runOmpCommand(omp.path, ["plugin", originalRuntimeEnabled ? "enable" : "disable", OMP_PLUGIN_PACKAGE], 120000);
|
|
3234
|
+
this.deps.runOmpCommand(omp.path, ["plugin", originalRuntimeEnabled ? "enable" : "disable", OMP_PLUGIN_PACKAGE], 120000);
|
|
3226
3235
|
}
|
|
3227
3236
|
return this.errorResult(configPath, `${OMP_PLUGIN_PACKAGE} is still disabled in the current project after \`omp ${args.join(" ")}\``);
|
|
3228
3237
|
}
|
|
@@ -3235,10 +3244,10 @@ class OmpAdapter {
|
|
|
3235
3244
|
}
|
|
3236
3245
|
async removePluginEntry() {
|
|
3237
3246
|
const configPath = getOmpPluginsLockPath();
|
|
3238
|
-
const omp = detectOmpBinary();
|
|
3247
|
+
const omp = this.deps.detectOmpBinary();
|
|
3239
3248
|
if (!omp)
|
|
3240
3249
|
return this.errorResult(configPath, "OMP binary not found");
|
|
3241
|
-
const plugins = listOmpPlugins(omp.path);
|
|
3250
|
+
const plugins = this.deps.listOmpPlugins(omp.path);
|
|
3242
3251
|
if (plugins === null) {
|
|
3243
3252
|
return this.errorResult(configPath, "`omp plugin list --json` failed");
|
|
3244
3253
|
}
|
|
@@ -3251,7 +3260,7 @@ class OmpAdapter {
|
|
|
3251
3260
|
configPath
|
|
3252
3261
|
};
|
|
3253
3262
|
}
|
|
3254
|
-
const result = runOmpCommand(omp.path, ["plugin", "uninstall", OMP_PLUGIN_PACKAGE], 120000);
|
|
3263
|
+
const result = this.deps.runOmpCommand(omp.path, ["plugin", "uninstall", OMP_PLUGIN_PACKAGE], 120000);
|
|
3255
3264
|
if (!result.ok) {
|
|
3256
3265
|
return this.errorResult(configPath, result.stderr || result.stdout || "OMP plugin uninstall failed");
|
|
3257
3266
|
}
|
|
@@ -3273,10 +3282,10 @@ class OmpAdapter {
|
|
|
3273
3282
|
return getMagicContextLogPath2("pi");
|
|
3274
3283
|
}
|
|
3275
3284
|
getInstalledPluginVersion() {
|
|
3276
|
-
const omp = detectOmpBinary();
|
|
3285
|
+
const omp = this.deps.detectOmpBinary();
|
|
3277
3286
|
if (!omp)
|
|
3278
3287
|
return null;
|
|
3279
|
-
return listOmpPlugins(omp.path)?.find((plugin) => plugin.name === OMP_PLUGIN_PACKAGE)?.version ?? null;
|
|
3288
|
+
return this.deps.listOmpPlugins(omp.path)?.find((plugin) => plugin.name === OMP_PLUGIN_PACKAGE)?.version ?? null;
|
|
3280
3289
|
}
|
|
3281
3290
|
readRuntimeEnabled(configPath) {
|
|
3282
3291
|
try {
|
|
@@ -3296,9 +3305,15 @@ class OmpAdapter {
|
|
|
3296
3305
|
};
|
|
3297
3306
|
}
|
|
3298
3307
|
}
|
|
3308
|
+
var DEFAULT_DEPS;
|
|
3299
3309
|
var init_omp = __esm(() => {
|
|
3300
3310
|
init_omp_helpers();
|
|
3301
3311
|
init_paths();
|
|
3312
|
+
DEFAULT_DEPS = {
|
|
3313
|
+
detectOmpBinary,
|
|
3314
|
+
listOmpPlugins,
|
|
3315
|
+
runOmpCommand
|
|
3316
|
+
};
|
|
3302
3317
|
});
|
|
3303
3318
|
|
|
3304
3319
|
// ../../node_modules/.bun/esprima@4.0.1/node_modules/esprima/dist/esprima.js
|
|
@@ -11160,14 +11175,16 @@ var init_atomic_write = () => {};
|
|
|
11160
11175
|
import { existsSync as existsSync7, realpathSync } from "node:fs";
|
|
11161
11176
|
import { homedir as homedir6 } from "node:os";
|
|
11162
11177
|
import { join as join8 } from "node:path";
|
|
11163
|
-
function defaultDeps() {
|
|
11178
|
+
function defaultDeps(overrides = {}) {
|
|
11179
|
+
const env = overrides.env ?? process.env;
|
|
11164
11180
|
return {
|
|
11165
|
-
exists: existsSync7,
|
|
11166
|
-
isExecutable: isExecutableFile,
|
|
11167
|
-
home:
|
|
11168
|
-
platform: process.platform,
|
|
11169
|
-
env
|
|
11170
|
-
onPath: findOnPath
|
|
11181
|
+
exists: overrides.exists ?? existsSync7,
|
|
11182
|
+
isExecutable: overrides.isExecutable ?? isExecutableFile,
|
|
11183
|
+
home: overrides.home ?? (env.HOME?.trim() || homedir6()),
|
|
11184
|
+
platform: overrides.platform ?? process.platform,
|
|
11185
|
+
env,
|
|
11186
|
+
onPath: overrides.onPath ?? findOnPath,
|
|
11187
|
+
realpath: overrides.realpath
|
|
11171
11188
|
};
|
|
11172
11189
|
}
|
|
11173
11190
|
function stockCliBinary(d) {
|
|
@@ -11246,7 +11263,7 @@ function desktopAppPaths(d) {
|
|
|
11246
11263
|
}
|
|
11247
11264
|
}
|
|
11248
11265
|
function detectOpenCodeInstallations(deps) {
|
|
11249
|
-
const d =
|
|
11266
|
+
const d = defaultDeps(deps);
|
|
11250
11267
|
const installations = [];
|
|
11251
11268
|
const seenRealpaths = new Set;
|
|
11252
11269
|
const onPath = d.onPath("opencode");
|
|
@@ -12736,31 +12753,28 @@ var init_setup_pi = __esm(() => {
|
|
|
12736
12753
|
});
|
|
12737
12754
|
|
|
12738
12755
|
// src/commands/setup-omp.ts
|
|
12739
|
-
|
|
12740
|
-
return
|
|
12741
|
-
...options,
|
|
12742
|
-
env: options.env ?? OMP_ENV,
|
|
12743
|
-
host: options.host ?? OMP_HOST
|
|
12744
|
-
});
|
|
12756
|
+
function resolveDeps(overrides = {}) {
|
|
12757
|
+
return { ...DEFAULT_DEPS2, ...overrides };
|
|
12745
12758
|
}
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
init_paths();
|
|
12752
|
-
init_setup_pi();
|
|
12753
|
-
OMP_ENV = {
|
|
12754
|
-
detectPiBinary: detectOmpBinary,
|
|
12755
|
-
getPiVersion: getOmpVersion,
|
|
12756
|
-
getAvailableModels: getOmpAvailableModels,
|
|
12759
|
+
function createOmpEnvironment(deps) {
|
|
12760
|
+
return {
|
|
12761
|
+
detectPiBinary: deps.detectOmpBinary,
|
|
12762
|
+
getPiVersion: deps.getOmpVersion,
|
|
12763
|
+
getAvailableModels: deps.getOmpAvailableModels,
|
|
12757
12764
|
paths: {
|
|
12758
12765
|
getPiAgentConfigDir: getOmpAgentDir,
|
|
12759
12766
|
getPiUserConfigPath: getOmpUserConfigPath,
|
|
12760
12767
|
getPiUserExtensionsPath: getOmpPluginsLockPath
|
|
12761
12768
|
}
|
|
12762
12769
|
};
|
|
12763
|
-
|
|
12770
|
+
}
|
|
12771
|
+
function createOmpHost(deps) {
|
|
12772
|
+
const adapterDeps = {
|
|
12773
|
+
detectOmpBinary: deps.detectOmpBinary,
|
|
12774
|
+
listOmpPlugins: deps.listOmpPlugins,
|
|
12775
|
+
runOmpCommand: deps.runOmpCommand
|
|
12776
|
+
};
|
|
12777
|
+
return {
|
|
12764
12778
|
displayName: "Oh My Pi (OMP)",
|
|
12765
12779
|
cliName: "omp",
|
|
12766
12780
|
packageSource: OMP_PLUGIN_PACKAGE,
|
|
@@ -12768,13 +12782,13 @@ var init_setup_omp = __esm(() => {
|
|
|
12768
12782
|
minimumVersion: "17.1.7",
|
|
12769
12783
|
versionWarning: (version, minimum) => `OMP ${version} is older than the tested minimum ${minimum}. ` + "Upgrade with `omp update` before enabling Magic Context.",
|
|
12770
12784
|
modelRefToCanonical: ompModelRefToCanonical,
|
|
12771
|
-
ensurePluginEntry: async () => new OmpAdapter().ensurePluginEntry(),
|
|
12785
|
+
ensurePluginEntry: async () => new OmpAdapter(adapterDeps).ensurePluginEntry(),
|
|
12772
12786
|
beforeWrite: async ({ binaryPath, cwd, prompts, dryRun, configureHost }) => {
|
|
12773
|
-
if (!configureHost && !new OmpAdapter().hasPluginEntry()) {
|
|
12787
|
+
if (!configureHost && !new OmpAdapter(adapterDeps).hasPluginEntry()) {
|
|
12774
12788
|
return async () => {};
|
|
12775
12789
|
}
|
|
12776
|
-
const compaction = getOmpSetting(binaryPath, "compaction.enabled");
|
|
12777
|
-
const memoryBackend = getOmpSetting(binaryPath, "memory.backend");
|
|
12790
|
+
const compaction = deps.getOmpSetting(binaryPath, "compaction.enabled");
|
|
12791
|
+
const memoryBackend = deps.getOmpSetting(binaryPath, "memory.backend");
|
|
12778
12792
|
if (compaction === null || memoryBackend === null) {
|
|
12779
12793
|
prompts.log.error("Could not read OMP compaction/memory settings; refusing to install two context managers blindly.");
|
|
12780
12794
|
return false;
|
|
@@ -12813,7 +12827,7 @@ Edit those files directly, then rerun setup.`);
|
|
|
12813
12827
|
const applied = [];
|
|
12814
12828
|
const rollback = async () => {
|
|
12815
12829
|
for (const change of [...applied].reverse()) {
|
|
12816
|
-
const result = runOmpCommand(binaryPath, ["config", "set", change.key, change.from], 1e4);
|
|
12830
|
+
const result = deps.runOmpCommand(binaryPath, ["config", "set", change.key, change.from], 1e4);
|
|
12817
12831
|
if (result.ok)
|
|
12818
12832
|
prompts.log.info(`Restored OMP ${change.key}=${change.from}`);
|
|
12819
12833
|
else
|
|
@@ -12821,7 +12835,7 @@ Edit those files directly, then rerun setup.`);
|
|
|
12821
12835
|
}
|
|
12822
12836
|
};
|
|
12823
12837
|
for (const change of changes) {
|
|
12824
|
-
const result = runOmpCommand(binaryPath, ["config", "set", change.key, change.to], 1e4);
|
|
12838
|
+
const result = deps.runOmpCommand(binaryPath, ["config", "set", change.key, change.to], 1e4);
|
|
12825
12839
|
if (!result.ok) {
|
|
12826
12840
|
prompts.log.error(result.stderr || `Could not set OMP ${change.key}`);
|
|
12827
12841
|
await rollback();
|
|
@@ -12835,27 +12849,55 @@ Edit those files directly, then rerun setup.`);
|
|
|
12835
12849
|
rollbackPluginEntry: async (registration) => {
|
|
12836
12850
|
if (registration.action === "already_present")
|
|
12837
12851
|
return;
|
|
12838
|
-
const omp = detectOmpBinary();
|
|
12852
|
+
const omp = deps.detectOmpBinary();
|
|
12839
12853
|
if (!omp)
|
|
12840
12854
|
return;
|
|
12841
12855
|
const action = registration.action === "added" ? "uninstall" : "disable";
|
|
12842
|
-
runOmpCommand(omp.path, ["plugin", action, OMP_PLUGIN_PACKAGE], 120000);
|
|
12856
|
+
deps.runOmpCommand(omp.path, ["plugin", action, OMP_PLUGIN_PACKAGE], 120000);
|
|
12843
12857
|
}
|
|
12844
12858
|
};
|
|
12859
|
+
}
|
|
12860
|
+
async function runSetup2(options = {}) {
|
|
12861
|
+
const { deps: overrides, ...setupOptions } = options;
|
|
12862
|
+
const deps = overrides ? resolveDeps(overrides) : DEFAULT_DEPS2;
|
|
12863
|
+
return runSetup({
|
|
12864
|
+
...setupOptions,
|
|
12865
|
+
env: setupOptions.env ?? (overrides ? createOmpEnvironment(deps) : OMP_ENV),
|
|
12866
|
+
host: setupOptions.host ?? (overrides ? createOmpHost(deps) : OMP_HOST)
|
|
12867
|
+
});
|
|
12868
|
+
}
|
|
12869
|
+
var DEFAULT_DEPS2, OMP_ENV, OMP_HOST;
|
|
12870
|
+
var init_setup_omp = __esm(() => {
|
|
12871
|
+
init_harness_provider_map();
|
|
12872
|
+
init_omp();
|
|
12873
|
+
init_omp_helpers();
|
|
12874
|
+
init_paths();
|
|
12875
|
+
init_setup_pi();
|
|
12876
|
+
DEFAULT_DEPS2 = {
|
|
12877
|
+
detectOmpBinary,
|
|
12878
|
+
getOmpVersion,
|
|
12879
|
+
getOmpAvailableModels,
|
|
12880
|
+
getOmpSetting,
|
|
12881
|
+
listOmpPlugins,
|
|
12882
|
+
runOmpCommand
|
|
12883
|
+
};
|
|
12884
|
+
OMP_ENV = createOmpEnvironment(DEFAULT_DEPS2);
|
|
12885
|
+
OMP_HOST = createOmpHost(DEFAULT_DEPS2);
|
|
12845
12886
|
});
|
|
12846
12887
|
|
|
12847
12888
|
// ../plugin/src/shared/logger.ts
|
|
12848
12889
|
import * as fs from "node:fs";
|
|
12849
12890
|
import * as path2 from "node:path";
|
|
12850
|
-
function
|
|
12851
|
-
const dir = path2.dirname(filePath);
|
|
12852
|
-
if (dir === lastEnsuredDir)
|
|
12853
|
-
return;
|
|
12891
|
+
function recordSwallowedWrite(error) {
|
|
12854
12892
|
try {
|
|
12855
|
-
|
|
12856
|
-
|
|
12893
|
+
swallowedWriteCount++;
|
|
12894
|
+
lastErrorMessage = error instanceof Error ? error.message : String(error);
|
|
12895
|
+
lastErrorTime = new Date().toISOString();
|
|
12857
12896
|
} catch {}
|
|
12858
12897
|
}
|
|
12898
|
+
function ensureDir4(filePath) {
|
|
12899
|
+
fs.mkdirSync(path2.dirname(filePath), { recursive: true });
|
|
12900
|
+
}
|
|
12859
12901
|
function flush() {
|
|
12860
12902
|
if (flushTimer) {
|
|
12861
12903
|
clearTimeout(flushTimer);
|
|
@@ -12869,7 +12911,9 @@ function flush() {
|
|
|
12869
12911
|
const logFile = getMagicContextLogPath();
|
|
12870
12912
|
ensureDir4(logFile);
|
|
12871
12913
|
fs.appendFileSync(logFile, data);
|
|
12872
|
-
} catch {
|
|
12914
|
+
} catch (error) {
|
|
12915
|
+
recordSwallowedWrite(error);
|
|
12916
|
+
}
|
|
12873
12917
|
}
|
|
12874
12918
|
function scheduleFlush() {
|
|
12875
12919
|
if (flushTimer)
|
|
@@ -12895,7 +12939,7 @@ ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
|
|
|
12895
12939
|
}
|
|
12896
12940
|
} catch {}
|
|
12897
12941
|
}
|
|
12898
|
-
var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50,
|
|
12942
|
+
var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, swallowedWriteCount = 0, lastErrorMessage = null, lastErrorTime = null;
|
|
12899
12943
|
var init_logger = __esm(() => {
|
|
12900
12944
|
init_data_path();
|
|
12901
12945
|
buffer = [];
|
|
@@ -12903,6 +12947,43 @@ var init_logger = __esm(() => {
|
|
|
12903
12947
|
process.on("exit", flush);
|
|
12904
12948
|
}
|
|
12905
12949
|
});
|
|
12950
|
+
// ../plugin/src/shared/window-geometry.ts
|
|
12951
|
+
function setWindowOverlayPath(path3) {
|
|
12952
|
+
configuredOverlayPath = path3;
|
|
12953
|
+
loadedOverlayPath = undefined;
|
|
12954
|
+
loadedOverlay = undefined;
|
|
12955
|
+
}
|
|
12956
|
+
var GRADES, UNITS, BOUNDARIES, UNKNOWN_REASONS, NUMERIC_FACT_KEYS, configuredOverlayPath, loadedOverlayPath, loadedOverlay, geometryClampLogSeen;
|
|
12957
|
+
var init_window_geometry = __esm(() => {
|
|
12958
|
+
init_data_path();
|
|
12959
|
+
init_harness_provider_map();
|
|
12960
|
+
init_logger();
|
|
12961
|
+
GRADES = new Set([
|
|
12962
|
+
"provider_asserted_runtime",
|
|
12963
|
+
"measured",
|
|
12964
|
+
"provider_asserted_doc",
|
|
12965
|
+
"catalog",
|
|
12966
|
+
"unknown"
|
|
12967
|
+
]);
|
|
12968
|
+
UNITS = new Set(["provider", "estimate"]);
|
|
12969
|
+
BOUNDARIES = new Set(["Observed", "Asserted", "Corrected"]);
|
|
12970
|
+
UNKNOWN_REASONS = new Set([
|
|
12971
|
+
"placeholder_output_equals_context",
|
|
12972
|
+
"placeholder_zero",
|
|
12973
|
+
"never_measured",
|
|
12974
|
+
"not_single_valued_at_key",
|
|
12975
|
+
"retracted"
|
|
12976
|
+
]);
|
|
12977
|
+
NUMERIC_FACT_KEYS = new Set([
|
|
12978
|
+
"window.advertised",
|
|
12979
|
+
"window.enforced",
|
|
12980
|
+
"output.advertised",
|
|
12981
|
+
"output.enforced",
|
|
12982
|
+
"output.default"
|
|
12983
|
+
]);
|
|
12984
|
+
geometryClampLogSeen = new Set;
|
|
12985
|
+
});
|
|
12986
|
+
|
|
12906
12987
|
// ../plugin/src/shared/models-dev-cache.ts
|
|
12907
12988
|
function setOutputReserveConfig(config) {
|
|
12908
12989
|
outputReserveConfig = config;
|
|
@@ -12912,6 +12993,7 @@ var init_models_dev_cache = __esm(() => {
|
|
|
12912
12993
|
init_data_path();
|
|
12913
12994
|
init_harness_provider_map();
|
|
12914
12995
|
init_logger();
|
|
12996
|
+
init_window_geometry();
|
|
12915
12997
|
SEPARATE_OUTPUT_QUOTA_PROVIDERS = new Set(["google", "google-antigravity"]);
|
|
12916
12998
|
reserveClampLogSeen = new Set;
|
|
12917
12999
|
});
|
|
@@ -27951,6 +28033,9 @@ function isValidPromptSurfaceModelKey(key) {
|
|
|
27951
28033
|
return true;
|
|
27952
28034
|
return modelID.length > 0 && !modelID.startsWith("/") && !modelID.endsWith("/") && !modelID.includes("//");
|
|
27953
28035
|
}
|
|
28036
|
+
var init_prompt_surface = __esm(() => {
|
|
28037
|
+
init_harness_provider_map();
|
|
28038
|
+
});
|
|
27954
28039
|
|
|
27955
28040
|
// ../plugin/src/config/schema/agent-overrides.ts
|
|
27956
28041
|
var PermissionValueSchema, PermissionSchema, AgentOverrideConfigSchema;
|
|
@@ -28005,6 +28090,7 @@ var init_magic_context = __esm(() => {
|
|
|
28005
28090
|
init_zod();
|
|
28006
28091
|
init_language_directive();
|
|
28007
28092
|
init_cron();
|
|
28093
|
+
init_prompt_surface();
|
|
28008
28094
|
init_agent_overrides();
|
|
28009
28095
|
PiThinkingLevelSchema = exports_external.enum(["off", "minimal", "low", "medium", "high", "xhigh", "max"]).optional();
|
|
28010
28096
|
PiConfigSchema = exports_external.object({
|
|
@@ -28200,7 +28286,10 @@ var init_magic_context = __esm(() => {
|
|
|
28200
28286
|
output_reserve: exports_external.union([
|
|
28201
28287
|
exports_external.number().min(0),
|
|
28202
28288
|
exports_external.object({ default: exports_external.number().min(0) }).catchall(exports_external.number().min(0))
|
|
28203
|
-
]).optional().describe('User-only output-token reservation override. Number or per-model object ({ default: 16384, "provider/model": 8192 }); 0 disables reservation. When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.'),
|
|
28289
|
+
]).optional().describe('User-only output-token reservation override. Number or per-model object ({ default: 16384, "provider/model": 8192 }); 0 disables reservation. Takes precedence over every derived source: an explicit value here always wins against catalog output limits, provider window-geometry facts, and the 25%-of-context fallback (usable window = context window minus this reserve). When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.'),
|
|
28290
|
+
models: exports_external.object({
|
|
28291
|
+
window_overlay_path: exports_external.string().trim().min(1).optional()
|
|
28292
|
+
}).optional().describe("User-only Fusiform window-overlay settings. The path defaults to <dataDir>/fusiform/window-overlay.json."),
|
|
28204
28293
|
toast_duration_ms: exports_external.number().min(0).max(60000).default(5000).describe("TUI toast lifetime in milliseconds for Magic Context notifications. Set to 0 to disable Magic Context toasts entirely (min: 0, max: 60000, default: 5000)"),
|
|
28205
28294
|
execute_threshold_percentage: exports_external.union([
|
|
28206
28295
|
exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE),
|
|
@@ -28252,7 +28341,7 @@ var init_magic_context = __esm(() => {
|
|
|
28252
28341
|
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
28253
28342
|
}).default({ enabled: true, overlay: true }).describe("Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart."),
|
|
28254
28343
|
pi: PiConfigSchema.describe("Pi-only child-process extension controls. This setting is user-level only; project configuration cannot choose which extensions a user's subagent children load."),
|
|
28255
|
-
smart_drops: exports_external.boolean().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent ctx_reduce (keep newest
|
|
28344
|
+
smart_drops: exports_external.boolean().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent ctx_reduce (keep newest 3), and zero-value meta (bash_status, bash_kill, ctx_note read/dismiss) outputs are dropped; older edits to a file are compressed to a filePath-preserving marker while the newest edit per file stays full. Only acts on passes already busting the cache, so it never originates a cache bust. Honors the protected-tag reserve. Experimental: opt-in, default off until cache stability is proven; when off the wire is byte-identical to the positional-only reclaim. Requires a restart."),
|
|
28256
28345
|
caveman_text_compression: exports_external.object({
|
|
28257
28346
|
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Active for primary sessions when enabled; never for subagents. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
|
|
28258
28347
|
min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
|
|
@@ -28407,6 +28496,11 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
28407
28496
|
delete projectRaw.output_reserve;
|
|
28408
28497
|
warnings.push("Ignoring output_reserve from project config (security: output-token reservation only honors user-level config).");
|
|
28409
28498
|
}
|
|
28499
|
+
const models = projectRaw.models;
|
|
28500
|
+
if (isPlainObject2(models) && "window_overlay_path" in models) {
|
|
28501
|
+
delete models.window_overlay_path;
|
|
28502
|
+
warnings.push("Ignoring models.window_overlay_path from project config (security: only user-level config may select model geometry metadata).");
|
|
28503
|
+
}
|
|
28410
28504
|
if ("language" in projectRaw) {
|
|
28411
28505
|
delete projectRaw.language;
|
|
28412
28506
|
warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
|
|
@@ -29085,6 +29179,7 @@ function loadPluginConfigDetailed(directory) {
|
|
|
29085
29179
|
const recoveredTopLevelKeys = [];
|
|
29086
29180
|
const config2 = parsePluginConfig(mergedRaw, recoveredTopLevelKeys);
|
|
29087
29181
|
setOutputReserveConfig(config2.output_reserve);
|
|
29182
|
+
setWindowOverlayPath(config2.models?.window_overlay_path);
|
|
29088
29183
|
if (config2.configWarnings?.length) {
|
|
29089
29184
|
allWarnings.push(...config2.configWarnings.map((w) => {
|
|
29090
29185
|
if (userLoaded && projectLoaded)
|
|
@@ -29126,6 +29221,7 @@ function loadPluginConfigDetailed(directory) {
|
|
|
29126
29221
|
var init_config = __esm(() => {
|
|
29127
29222
|
init_jsonc_parser();
|
|
29128
29223
|
init_models_dev_cache();
|
|
29224
|
+
init_window_geometry();
|
|
29129
29225
|
init_agent_disable();
|
|
29130
29226
|
init_migrate_config_location();
|
|
29131
29227
|
init_migrate_dreamer_v2();
|
|
@@ -29176,14 +29272,17 @@ function detectConflicts(directory, options) {
|
|
|
29176
29272
|
omoAnthropicRecovery: false
|
|
29177
29273
|
};
|
|
29178
29274
|
const reasons = [];
|
|
29179
|
-
|
|
29275
|
+
let compactionResult = options?.resolvedCompaction ?? checkCompaction(directory);
|
|
29276
|
+
if (process.env.OPENCODE_DISABLE_AUTOCOMPACT) {
|
|
29277
|
+
compactionResult = { auto: false, prune: false };
|
|
29278
|
+
}
|
|
29180
29279
|
if (compactionEnabled && compactionResult.auto) {
|
|
29181
29280
|
conflicts.compactionAuto = true;
|
|
29182
|
-
reasons.push("OpenCode auto-compaction is enabled (compaction.auto=true)");
|
|
29281
|
+
reasons.push(options?.resolvedCompaction ? "OpenCode auto-compaction is enabled (compaction.auto=true) (resolved config)" : "OpenCode auto-compaction is enabled (compaction.auto=true)");
|
|
29183
29282
|
}
|
|
29184
29283
|
if (compactionEnabled && compactionResult.prune) {
|
|
29185
29284
|
conflicts.compactionPrune = true;
|
|
29186
|
-
reasons.push("OpenCode prune is enabled (compaction.prune=true)");
|
|
29285
|
+
reasons.push(options?.resolvedCompaction ? "OpenCode prune is enabled (compaction.prune=true) (resolved config)" : "OpenCode prune is enabled (compaction.prune=true)");
|
|
29187
29286
|
}
|
|
29188
29287
|
const dcpFound = checkDcpPlugin(directory);
|
|
29189
29288
|
if (dcpFound) {
|
|
@@ -29371,6 +29470,7 @@ function readOmoDisabledHooks(directory) {
|
|
|
29371
29470
|
var DCP_PACKAGE_NAMES, OMO_PACKAGE_NAMES;
|
|
29372
29471
|
var init_conflict_detector = __esm(() => {
|
|
29373
29472
|
init_jsonc_parser();
|
|
29473
|
+
init_logger();
|
|
29374
29474
|
init_opencode_config_dir();
|
|
29375
29475
|
DCP_PACKAGE_NAMES = new Set(["@tarquinen/opencode-dcp"]);
|
|
29376
29476
|
OMO_PACKAGE_NAMES = new Set(["oh-my-opencode", "oh-my-openagent"]);
|
|
@@ -29823,10 +29923,11 @@ function runOpenCode(args, binary, timeoutMs) {
|
|
|
29823
29923
|
function getOpenCodeVersion(binary) {
|
|
29824
29924
|
return runOpenCode(["--version"], binary, OPENCODE_VERSION_PROBE_TIMEOUT_MS);
|
|
29825
29925
|
}
|
|
29826
|
-
function describeOpenCodeInstallations(installations) {
|
|
29926
|
+
function describeOpenCodeInstallations(installations, deps = {}) {
|
|
29927
|
+
const getVersion = deps.getVersion ?? getOpenCodeVersion;
|
|
29827
29928
|
return installations.map((installation, index) => ({
|
|
29828
29929
|
...installation,
|
|
29829
|
-
version: installation.kind === "cli" ?
|
|
29930
|
+
version: installation.kind === "cli" ? getVersion(installation.path) ?? "unknown" : "unknown",
|
|
29830
29931
|
active: index === 0
|
|
29831
29932
|
}));
|
|
29832
29933
|
}
|
|
@@ -30671,6 +30772,7 @@ function prepareMirrorPageStatements(db) {
|
|
|
30671
30772
|
return {
|
|
30672
30773
|
identityByModule: db.prepare("SELECT context_row_id FROM mirror_identity WHERE domain = ? AND module_project = ? AND module_row_id = ?"),
|
|
30673
30774
|
insertIdentity: db.prepare("INSERT OR IGNORE INTO mirror_identity(domain, module_project, module_row_id, context_row_id) VALUES (?, ?, ?, ?)"),
|
|
30775
|
+
deleteIdentityByContext: db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND context_row_id = ?"),
|
|
30674
30776
|
deleteLiveMemory: db.prepare("DELETE FROM mirror_live_memory_rows WHERE module_project = ? AND module_row_id = ?"),
|
|
30675
30777
|
deletePendingReferencesForMemory: db.prepare("DELETE FROM mirror_pending_references WHERE domain = ? AND module_project = ? AND (module_row_id = ? OR target_module_row_id = ?)"),
|
|
30676
30778
|
deleteIdentity: db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND module_project = ? AND module_row_id = ?"),
|
|
@@ -30722,7 +30824,7 @@ function prepareMirrorPageStatements(db) {
|
|
|
30722
30824
|
check_quarantined_until = ?, check_next_due_at = ?, check_compiled_at = ?, check_false_since_at = ?,
|
|
30723
30825
|
check_last_liveness_at = ?, last_checked_at = ?, check_status = ?, check_version = ?,
|
|
30724
30826
|
policy_version = ?, anchor_block_id = ?, anchor_ordinal = ?, created_at = ?, updated_at = ? WHERE id = ?`),
|
|
30725
|
-
upsertNoteRevision: db.prepare("INSERT INTO mirror_note_revisions(module_project, module_row_id, context_row_id, status_version) VALUES (?, ?, ?, ?)
|
|
30827
|
+
upsertNoteRevision: db.prepare("INSERT OR REPLACE INTO mirror_note_revisions(module_project, module_row_id, context_row_id, status_version) VALUES (?, ?, ?, ?)"),
|
|
30726
30828
|
translateMemoryReferences: db.prepare(`UPDATE memories
|
|
30727
30829
|
SET superseded_by_memory_id = (
|
|
30728
30830
|
SELECT target.context_row_id
|
|
@@ -30795,6 +30897,9 @@ function rememberIdentity(db, domain2, moduleProject, moduleRowId, contextRowId,
|
|
|
30795
30897
|
const existing = mirrorIdentity(db, domain2, moduleProject, moduleRowId, statements);
|
|
30796
30898
|
if (existing)
|
|
30797
30899
|
return;
|
|
30900
|
+
if (domain2 === "notes") {
|
|
30901
|
+
(statements?.deleteIdentityByContext ?? db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND context_row_id = ?")).run(domain2, contextRowId);
|
|
30902
|
+
}
|
|
30798
30903
|
(statements?.insertIdentity ?? db.prepare("INSERT OR IGNORE INTO mirror_identity(domain, module_project, module_row_id, context_row_id) VALUES (?, ?, ?, ?)")).run(domain2, moduleProject, moduleRowId, contextRowId);
|
|
30799
30904
|
}
|
|
30800
30905
|
function contextMemoryId(db, domain2, moduleProject, row, moduleRowId, statements) {
|
|
@@ -31427,11 +31532,12 @@ function gitRootInAncestorChain(startDirectory) {
|
|
|
31427
31532
|
function hasGitDirInAncestorChain(startDirectory) {
|
|
31428
31533
|
return gitRootInAncestorChain(startDirectory) !== null;
|
|
31429
31534
|
}
|
|
31430
|
-
var GIT_TIMEOUT_MS = 5000, TRANSIENT_FAILURE_COOLDOWN_MS, identityCache, lastKnownGitIdentityCache, directoryFallbackCache, transientFailureCooldown, dubiousOwnershipFallbackDirectories, dubiousOwnershipLoggedDirectories, dubiousOwnershipWarnedDirectories, transientGitIdentityReuseLoggedDirectories, execFileSyncForIdentity, nowMs = () => Date.now(), ProjectIdentityError;
|
|
31535
|
+
var GIT_TIMEOUT_MS = 5000, TRANSIENT_FAILURE_COOLDOWN_MS, identityCache, linkedGitWorktreeCache, lastKnownGitIdentityCache, directoryFallbackCache, transientFailureCooldown, dubiousOwnershipFallbackDirectories, dubiousOwnershipLoggedDirectories, dubiousOwnershipWarnedDirectories, transientGitIdentityReuseLoggedDirectories, execFileSyncForIdentity, nowMs = () => Date.now(), ProjectIdentityError;
|
|
31431
31536
|
var init_project_identity = __esm(() => {
|
|
31432
31537
|
init_logger();
|
|
31433
31538
|
TRANSIENT_FAILURE_COOLDOWN_MS = 5 * 60 * 1000;
|
|
31434
31539
|
identityCache = new Map;
|
|
31540
|
+
linkedGitWorktreeCache = new Map;
|
|
31435
31541
|
lastKnownGitIdentityCache = new Map;
|
|
31436
31542
|
directoryFallbackCache = new Map;
|
|
31437
31543
|
transientFailureCooldown = new Map;
|
|
@@ -33731,6 +33837,7 @@ class SubcModuleTransport {
|
|
|
33731
33837
|
return error51;
|
|
33732
33838
|
}
|
|
33733
33839
|
async beforeDeadline(operation, deadlineMs, detail) {
|
|
33840
|
+
operation.catch(() => {});
|
|
33734
33841
|
const remainingMs = deadlineMs - Date.now();
|
|
33735
33842
|
if (remainingMs <= 0)
|
|
33736
33843
|
throw this.deadlineError(detail);
|
|
@@ -34145,12 +34252,14 @@ import { execFileSync as execFileSync4 } from "node:child_process";
|
|
|
34145
34252
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
34146
34253
|
function isPidAlive(pid) {
|
|
34147
34254
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
34148
|
-
return
|
|
34255
|
+
return "dead";
|
|
34256
|
+
if (rpcIdentityPlatform === "win32")
|
|
34257
|
+
return readWindowsProcess(pid).state;
|
|
34149
34258
|
try {
|
|
34150
|
-
|
|
34151
|
-
return
|
|
34152
|
-
} catch (
|
|
34153
|
-
return
|
|
34259
|
+
rpcIdentityProcessKill(pid, 0);
|
|
34260
|
+
return "alive";
|
|
34261
|
+
} catch (error51) {
|
|
34262
|
+
return error51.code === "ESRCH" ? "dead" : "inconclusive";
|
|
34154
34263
|
}
|
|
34155
34264
|
}
|
|
34156
34265
|
function parseLinuxProcessStartTime(statContent, uptimeContent) {
|
|
@@ -34179,7 +34288,8 @@ function readPsProcessStartTime(pid) {
|
|
|
34179
34288
|
try {
|
|
34180
34289
|
const output = rpcIdentityExecFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
|
|
34181
34290
|
encoding: "utf8",
|
|
34182
|
-
timeout: PS_PROBE_TIMEOUT_MS
|
|
34291
|
+
timeout: PS_PROBE_TIMEOUT_MS,
|
|
34292
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34183
34293
|
});
|
|
34184
34294
|
const processStartTime = Date.parse(String(output).trim());
|
|
34185
34295
|
return Number.isFinite(processStartTime) ? processStartTime : null;
|
|
@@ -34187,6 +34297,70 @@ function readPsProcessStartTime(pid) {
|
|
|
34187
34297
|
return null;
|
|
34188
34298
|
}
|
|
34189
34299
|
}
|
|
34300
|
+
function parseCsvLine(line) {
|
|
34301
|
+
const fields = [];
|
|
34302
|
+
let field = "";
|
|
34303
|
+
let quoted = false;
|
|
34304
|
+
for (let index = 0;index < line.length; index += 1) {
|
|
34305
|
+
const character = line[index];
|
|
34306
|
+
if (character === '"') {
|
|
34307
|
+
if (quoted && line[index + 1] === '"') {
|
|
34308
|
+
field += '"';
|
|
34309
|
+
index += 1;
|
|
34310
|
+
} else {
|
|
34311
|
+
quoted = !quoted;
|
|
34312
|
+
}
|
|
34313
|
+
} else if (character === "," && !quoted) {
|
|
34314
|
+
fields.push(field);
|
|
34315
|
+
field = "";
|
|
34316
|
+
} else {
|
|
34317
|
+
field += character;
|
|
34318
|
+
}
|
|
34319
|
+
}
|
|
34320
|
+
if (quoted)
|
|
34321
|
+
return null;
|
|
34322
|
+
fields.push(field);
|
|
34323
|
+
return fields;
|
|
34324
|
+
}
|
|
34325
|
+
function parseTasklistOutput(output) {
|
|
34326
|
+
const entries = [];
|
|
34327
|
+
let sawHeader = false;
|
|
34328
|
+
for (const rawLine of output.split(/\r?\n/)) {
|
|
34329
|
+
const line = rawLine.trim();
|
|
34330
|
+
if (!line)
|
|
34331
|
+
continue;
|
|
34332
|
+
if (TASKLIST_NO_TASKS_PATTERN.test(line))
|
|
34333
|
+
return [];
|
|
34334
|
+
const fields = parseCsvLine(line);
|
|
34335
|
+
if (!fields)
|
|
34336
|
+
continue;
|
|
34337
|
+
if (fields[1]?.trim().toLowerCase() === "pid") {
|
|
34338
|
+
sawHeader = true;
|
|
34339
|
+
continue;
|
|
34340
|
+
}
|
|
34341
|
+
const pid = Number(fields[1]);
|
|
34342
|
+
if (!Number.isInteger(pid) || pid <= 0 || !fields[0])
|
|
34343
|
+
continue;
|
|
34344
|
+
entries.push({ pid, command: fields[0] });
|
|
34345
|
+
}
|
|
34346
|
+
return entries.length > 0 || sawHeader ? entries : null;
|
|
34347
|
+
}
|
|
34348
|
+
function readWindowsProcess(pid) {
|
|
34349
|
+
try {
|
|
34350
|
+
const output = rpcIdentityExecFileSync("tasklist", ["/FO", "CSV", "/FI", `PID eq ${pid}`], {
|
|
34351
|
+
encoding: "utf8",
|
|
34352
|
+
timeout: PS_PROBE_TIMEOUT_MS,
|
|
34353
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34354
|
+
});
|
|
34355
|
+
const entries = parseTasklistOutput(String(output));
|
|
34356
|
+
if (entries === null)
|
|
34357
|
+
return { state: "inconclusive" };
|
|
34358
|
+
const process3 = entries.find((entry) => entry.pid === pid);
|
|
34359
|
+
return process3 ? { state: "alive", command: process3.command } : { state: "dead" };
|
|
34360
|
+
} catch {
|
|
34361
|
+
return { state: "inconclusive" };
|
|
34362
|
+
}
|
|
34363
|
+
}
|
|
34190
34364
|
function readLinuxProcessCommand(pid) {
|
|
34191
34365
|
try {
|
|
34192
34366
|
return String(rpcIdentityReadFileSync(`/proc/${pid}/cmdline`, "utf8"));
|
|
@@ -34198,40 +34372,86 @@ function readPsProcessCommand(pid) {
|
|
|
34198
34372
|
try {
|
|
34199
34373
|
const output = rpcIdentityExecFileSync("ps", ["-p", String(pid), "-o", "command="], {
|
|
34200
34374
|
encoding: "utf8",
|
|
34201
|
-
timeout: PS_PROBE_TIMEOUT_MS
|
|
34375
|
+
timeout: PS_PROBE_TIMEOUT_MS,
|
|
34376
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34202
34377
|
});
|
|
34203
34378
|
return String(output);
|
|
34204
34379
|
} catch {
|
|
34205
34380
|
return null;
|
|
34206
34381
|
}
|
|
34207
34382
|
}
|
|
34383
|
+
function readProcessCommand(pid) {
|
|
34384
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
34385
|
+
return null;
|
|
34386
|
+
return rpcIdentityPlatform === "linux" ? readLinuxProcessCommand(pid) : rpcIdentityPlatform === "win32" ? readWindowsProcess(pid).command ?? null : readPsProcessCommand(pid);
|
|
34387
|
+
}
|
|
34388
|
+
function executableName(token) {
|
|
34389
|
+
return (token ?? "").replace(/^['"]|['"]$/g, "").split("/").at(-1) ?? "";
|
|
34390
|
+
}
|
|
34391
|
+
function commandTokens(command) {
|
|
34392
|
+
return command.toLowerCase().replaceAll("\\", "/").replaceAll("\x00", " ").split(/\s+/).map((token) => token.replace(/^['"]|['"]$/g, "")).filter(Boolean);
|
|
34393
|
+
}
|
|
34394
|
+
function commandHasOpenCodeExecutable(tokens) {
|
|
34395
|
+
return tokens.findIndex((token) => {
|
|
34396
|
+
const executable = executableName(token).replace(/\.(?:exe|cmd)$/, "");
|
|
34397
|
+
return executable === "opencode" || executable.endsWith("/opencode");
|
|
34398
|
+
});
|
|
34399
|
+
}
|
|
34400
|
+
function commandHasPiExecutable(tokens) {
|
|
34401
|
+
for (let index = 0;index < tokens.length; index += 1) {
|
|
34402
|
+
const executable = executableName(tokens[index]).replace(/\.(?:exe|cmd)$/, "");
|
|
34403
|
+
if (["pi", "omp", "oh-my-pi"].includes(executable))
|
|
34404
|
+
return true;
|
|
34405
|
+
if (["node", "bun", "deno"].includes(executable)) {
|
|
34406
|
+
const script = executableName(tokens[index + 1]).replace(/\.(?:exe|cmd)$/, "");
|
|
34407
|
+
if (["pi", "pi.js", "pi.mjs", "pi.cjs"].includes(script) || tokens[index + 1]?.includes("pi-coding-agent")) {
|
|
34408
|
+
return true;
|
|
34409
|
+
}
|
|
34410
|
+
}
|
|
34411
|
+
}
|
|
34412
|
+
return false;
|
|
34413
|
+
}
|
|
34414
|
+
function classifyProcessKind(command) {
|
|
34415
|
+
if (!command)
|
|
34416
|
+
return "process";
|
|
34417
|
+
const tokens = commandTokens(command);
|
|
34418
|
+
const openCodeIndex = commandHasOpenCodeExecutable(tokens);
|
|
34419
|
+
if (openCodeIndex >= 0) {
|
|
34420
|
+
const args = tokens.slice(openCodeIndex + 1);
|
|
34421
|
+
if (args.some((token) => token === "serve" || token === "--serve" || token.startsWith("--serve="))) {
|
|
34422
|
+
return "OpenCode server";
|
|
34423
|
+
}
|
|
34424
|
+
return "OpenCode instance (TUI/CLI)";
|
|
34425
|
+
}
|
|
34426
|
+
return commandHasPiExecutable(tokens) ? "Pi" : "process";
|
|
34427
|
+
}
|
|
34208
34428
|
function commandLooksLikeOpenCode(command) {
|
|
34209
34429
|
const normalized = command.toLowerCase();
|
|
34210
34430
|
return OPEN_CODE_COMMAND_MARKERS.some((marker) => normalized.includes(marker));
|
|
34211
34431
|
}
|
|
34212
34432
|
function isPidIdentityPlausible(record2) {
|
|
34213
34433
|
if (!Number.isInteger(record2.pid) || record2.pid <= 0)
|
|
34214
|
-
return
|
|
34434
|
+
return "implausible";
|
|
34215
34435
|
if (Number.isFinite(record2.started_at) && record2.started_at > 0) {
|
|
34216
|
-
const processStartTime = rpcIdentityPlatform === "linux" ? readLinuxProcessStartTime(record2.pid) : readPsProcessStartTime(record2.pid);
|
|
34436
|
+
const processStartTime = rpcIdentityPlatform === "linux" ? readLinuxProcessStartTime(record2.pid) : rpcIdentityPlatform === "win32" ? null : readPsProcessStartTime(record2.pid);
|
|
34217
34437
|
if (processStartTime === null)
|
|
34218
|
-
return
|
|
34219
|
-
return processStartTime <= record2.started_at + RPC_IDENTITY_SKEW_TOLERANCE_MS;
|
|
34438
|
+
return "inconclusive";
|
|
34439
|
+
return processStartTime <= record2.started_at + RPC_IDENTITY_SKEW_TOLERANCE_MS ? "plausible" : "implausible";
|
|
34220
34440
|
}
|
|
34221
|
-
const command = rpcIdentityPlatform === "linux" ? readLinuxProcessCommand(record2.pid) : readPsProcessCommand(record2.pid);
|
|
34441
|
+
const command = rpcIdentityPlatform === "linux" ? readLinuxProcessCommand(record2.pid) : rpcIdentityPlatform === "win32" ? readWindowsProcess(record2.pid).command ?? null : readPsProcessCommand(record2.pid);
|
|
34222
34442
|
if (command === null)
|
|
34223
|
-
return
|
|
34224
|
-
return commandLooksLikeOpenCode(command);
|
|
34443
|
+
return "inconclusive";
|
|
34444
|
+
return commandLooksLikeOpenCode(command) ? "plausible" : "implausible";
|
|
34225
34445
|
}
|
|
34226
34446
|
function commandLooksLikePi(command) {
|
|
34227
34447
|
const normalized = command.trim().toLowerCase().replaceAll("\\", "/");
|
|
34228
34448
|
const tokens = normalized.split(/\s+/).filter(Boolean);
|
|
34229
|
-
const
|
|
34230
|
-
const first =
|
|
34449
|
+
const executableName2 = (token) => (token ?? "").split("/").at(-1) ?? "";
|
|
34450
|
+
const first = executableName2(tokens[0]).replace(/\.exe$/, "");
|
|
34231
34451
|
if (["pi", "pi.cmd", "omp", "oh-my-pi"].includes(first))
|
|
34232
34452
|
return true;
|
|
34233
34453
|
if (["node", "bun", "deno"].includes(first)) {
|
|
34234
|
-
const script =
|
|
34454
|
+
const script = executableName2(tokens[1]);
|
|
34235
34455
|
return ["pi", "pi.js", "pi.mjs", "pi.cjs"].includes(script) || normalized.includes("pi-coding-agent");
|
|
34236
34456
|
}
|
|
34237
34457
|
return false;
|
|
@@ -34239,20 +34459,39 @@ function commandLooksLikePi(command) {
|
|
|
34239
34459
|
function inspectLivePiProcesses() {
|
|
34240
34460
|
if (false) {}
|
|
34241
34461
|
try {
|
|
34242
|
-
const
|
|
34462
|
+
const isWindows = rpcIdentityPlatform === "win32";
|
|
34463
|
+
const output = String(rpcProcessListExecFileSync(isWindows ? "tasklist" : "ps", isWindows ? ["/FO", "CSV"] : ["-axo", "pid=,command="], {
|
|
34243
34464
|
encoding: "utf8",
|
|
34244
|
-
timeout: PS_PROBE_TIMEOUT_MS
|
|
34465
|
+
timeout: PS_PROBE_TIMEOUT_MS,
|
|
34466
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34245
34467
|
}));
|
|
34246
34468
|
const pids = new Set;
|
|
34247
|
-
|
|
34248
|
-
const
|
|
34249
|
-
if (
|
|
34250
|
-
|
|
34251
|
-
|
|
34252
|
-
|
|
34253
|
-
|
|
34254
|
-
|
|
34255
|
-
|
|
34469
|
+
if (isWindows) {
|
|
34470
|
+
const entries = parseTasklistOutput(output);
|
|
34471
|
+
if (entries === null) {
|
|
34472
|
+
return {
|
|
34473
|
+
state: "unreadable",
|
|
34474
|
+
processIds: [],
|
|
34475
|
+
error: "tasklist output unavailable"
|
|
34476
|
+
};
|
|
34477
|
+
}
|
|
34478
|
+
for (const entry of entries) {
|
|
34479
|
+
if (entry.pid === process.pid)
|
|
34480
|
+
continue;
|
|
34481
|
+
if (commandLooksLikePi(entry.command))
|
|
34482
|
+
pids.add(entry.pid);
|
|
34483
|
+
}
|
|
34484
|
+
} else {
|
|
34485
|
+
for (const line of output.split(/\r?\n/)) {
|
|
34486
|
+
const match = /^\s*(\d+)\s+(.+)$/.exec(line);
|
|
34487
|
+
if (!match)
|
|
34488
|
+
continue;
|
|
34489
|
+
const pid = Number(match[1]);
|
|
34490
|
+
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid)
|
|
34491
|
+
continue;
|
|
34492
|
+
if (commandLooksLikePi(match[2]))
|
|
34493
|
+
pids.add(pid);
|
|
34494
|
+
}
|
|
34256
34495
|
}
|
|
34257
34496
|
return { state: "known", processIds: [...pids].sort((left, right) => left - right) };
|
|
34258
34497
|
} catch (error51) {
|
|
@@ -34282,6 +34521,8 @@ function parseRpcPortFile(content, fallbackPid = 0) {
|
|
|
34282
34521
|
port: port2,
|
|
34283
34522
|
pid,
|
|
34284
34523
|
started_at: Number.isFinite(startedAt) ? startedAt : 0,
|
|
34524
|
+
kind: typeof parsed.kind === "string" ? parsed.kind : undefined,
|
|
34525
|
+
harness: typeof parsed.harness === "string" ? parsed.harness : undefined,
|
|
34285
34526
|
token: typeof parsed.token === "string" ? parsed.token : undefined,
|
|
34286
34527
|
instance_id: typeof parsed.instance_id === "string" ? parsed.instance_id : undefined
|
|
34287
34528
|
};
|
|
@@ -34297,11 +34538,13 @@ function parseRpcPortFile(content, fallbackPid = 0) {
|
|
|
34297
34538
|
function isValidPort(port) {
|
|
34298
34539
|
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
34299
34540
|
}
|
|
34300
|
-
var RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000, LINUX_CLOCK_TICKS_PER_SECOND = 100, PS_PROBE_TIMEOUT_MS = 1000, OPEN_CODE_COMMAND_MARKERS, rpcIdentityReadFileSync, rpcIdentityExecFileSync, rpcProcessListExecFileSync, rpcIdentityPlatform, rpcIdentityNowMs = () => Date.now();
|
|
34541
|
+
var RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000, LINUX_CLOCK_TICKS_PER_SECOND = 100, PS_PROBE_TIMEOUT_MS = 1000, OPEN_CODE_COMMAND_MARKERS, TASKLIST_NO_TASKS_PATTERN, rpcIdentityReadFileSync, rpcIdentityExecFileSync, rpcIdentityProcessKill, rpcProcessListExecFileSync, rpcIdentityPlatform, rpcIdentityNowMs = () => Date.now();
|
|
34301
34542
|
var init_rpc_utils = __esm(() => {
|
|
34302
34543
|
OPEN_CODE_COMMAND_MARKERS = ["opencode", "node", "bun", "electron"];
|
|
34544
|
+
TASKLIST_NO_TASKS_PATTERN = /^INFO:\s+No tasks are running which match the specified criteria\.?$/im;
|
|
34303
34545
|
rpcIdentityReadFileSync = readFileSync12;
|
|
34304
34546
|
rpcIdentityExecFileSync = execFileSync4;
|
|
34547
|
+
rpcIdentityProcessKill = process.kill;
|
|
34305
34548
|
rpcProcessListExecFileSync = execFileSync4;
|
|
34306
34549
|
rpcIdentityPlatform = process.platform;
|
|
34307
34550
|
});
|
|
@@ -34528,6 +34771,8 @@ function healAllNullColumns(db) {
|
|
|
34528
34771
|
["stripped_placeholder_ids", ""],
|
|
34529
34772
|
["stale_reduce_stripped_ids", ""],
|
|
34530
34773
|
["processed_image_stripped_ids", ""],
|
|
34774
|
+
["merged_reasoning_stripped_ids", ""],
|
|
34775
|
+
["trailing_blank_decisions", ""],
|
|
34531
34776
|
["memory_block_cache", ""],
|
|
34532
34777
|
["memory_block_ids", ""],
|
|
34533
34778
|
["compaction_marker_state", ""],
|
|
@@ -34981,6 +35226,7 @@ var init_migrations = __esm(() => {
|
|
|
34981
35226
|
status TEXT NOT NULL DEFAULT 'active',
|
|
34982
35227
|
promoted_at INTEGER NOT NULL,
|
|
34983
35228
|
source_candidate_ids TEXT DEFAULT '[]',
|
|
35229
|
+
source_candidate_provenance TEXT,
|
|
34984
35230
|
created_at INTEGER NOT NULL,
|
|
34985
35231
|
updated_at INTEGER NOT NULL
|
|
34986
35232
|
);
|
|
@@ -36007,6 +36253,7 @@ var init_migrations = __esm(() => {
|
|
|
36007
36253
|
last_observed_at INTEGER,
|
|
36008
36254
|
answer_refreshed_at INTEGER,
|
|
36009
36255
|
source_candidate_ids TEXT NOT NULL DEFAULT '[]',
|
|
36256
|
+
source_candidate_provenance TEXT,
|
|
36010
36257
|
created_at INTEGER NOT NULL,
|
|
36011
36258
|
updated_at INTEGER NOT NULL
|
|
36012
36259
|
);
|
|
@@ -36816,6 +37063,37 @@ var init_migrations = __esm(() => {
|
|
|
36816
37063
|
ensureColumn(db, "notes", "compiled_at", "INTEGER");
|
|
36817
37064
|
ensureColumn(db, "notes", "compile_status", "TEXT CHECK(compile_status IN ('compiled', 'plain', 'refused'))");
|
|
36818
37065
|
}
|
|
37066
|
+
},
|
|
37067
|
+
{
|
|
37068
|
+
version: 77,
|
|
37069
|
+
description: "persist scoped provenance for promoted user memories and primers",
|
|
37070
|
+
up(db) {
|
|
37071
|
+
if (tableExists(db, "user_memories")) {
|
|
37072
|
+
ensureColumn(db, "user_memories", "source_candidate_provenance", "TEXT");
|
|
37073
|
+
}
|
|
37074
|
+
if (tableExists(db, "primers")) {
|
|
37075
|
+
ensureColumn(db, "primers", "source_candidate_provenance", "TEXT");
|
|
37076
|
+
}
|
|
37077
|
+
}
|
|
37078
|
+
},
|
|
37079
|
+
{
|
|
37080
|
+
version: 78,
|
|
37081
|
+
description: "add migration_pending journal for crash-safe cross-harness session migration",
|
|
37082
|
+
up(db) {
|
|
37083
|
+
db.exec(`
|
|
37084
|
+
CREATE TABLE IF NOT EXISTS migration_pending (
|
|
37085
|
+
migration_key TEXT PRIMARY KEY,
|
|
37086
|
+
source_session_id TEXT NOT NULL,
|
|
37087
|
+
target_harness TEXT NOT NULL,
|
|
37088
|
+
pi_session_id TEXT NOT NULL,
|
|
37089
|
+
final_path TEXT NOT NULL,
|
|
37090
|
+
stage_path TEXT NOT NULL,
|
|
37091
|
+
content_sha256 TEXT NOT NULL,
|
|
37092
|
+
phase TEXT NOT NULL CHECK (phase IN ('staged', 'db_committed')),
|
|
37093
|
+
created_at INTEGER NOT NULL
|
|
37094
|
+
);
|
|
37095
|
+
`);
|
|
37096
|
+
}
|
|
36819
37097
|
}
|
|
36820
37098
|
];
|
|
36821
37099
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m3) => Math.max(max, m3.version), 0);
|
|
@@ -36859,7 +37137,7 @@ import {
|
|
|
36859
37137
|
statSync as statSync7,
|
|
36860
37138
|
unlinkSync as unlinkSync2
|
|
36861
37139
|
} from "node:fs";
|
|
36862
|
-
import { basename as basename3, dirname as dirname10, join as join14 } from "node:path";
|
|
37140
|
+
import { basename as basename3, dirname as dirname10, join as join14, resolve as resolve5 } from "node:path";
|
|
36863
37141
|
function getPersistedSchemaVersion(db) {
|
|
36864
37142
|
const hasMigrationsTable = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'schema_migrations'").get();
|
|
36865
37143
|
if (!hasMigrationsTable) {
|
|
@@ -36891,6 +37169,28 @@ function invalidDiscoveryReason(raw) {
|
|
|
36891
37169
|
}
|
|
36892
37170
|
return "parse-invalid";
|
|
36893
37171
|
}
|
|
37172
|
+
function classifyDiscoveryRecordKind(record2) {
|
|
37173
|
+
for (const value of [record2.kind, record2.harness]) {
|
|
37174
|
+
const normalized = value?.trim().toLowerCase();
|
|
37175
|
+
if (!normalized)
|
|
37176
|
+
continue;
|
|
37177
|
+
if (normalized === "process")
|
|
37178
|
+
return "process";
|
|
37179
|
+
if (normalized === "opencode server" || normalized === "server") {
|
|
37180
|
+
return "OpenCode server";
|
|
37181
|
+
}
|
|
37182
|
+
if (normalized === "opencode instance" || normalized === "opencode instance (tui/cli)" || normalized === "opencode" || normalized === "tui" || normalized === "cli") {
|
|
37183
|
+
return "OpenCode instance (TUI/CLI)";
|
|
37184
|
+
}
|
|
37185
|
+
if (normalized === "pi" || normalized === "pi harness" || normalized === "omp" || normalized === "oh-my-pi") {
|
|
37186
|
+
return "Pi";
|
|
37187
|
+
}
|
|
37188
|
+
}
|
|
37189
|
+
return null;
|
|
37190
|
+
}
|
|
37191
|
+
function classifyRpcProcess(record2) {
|
|
37192
|
+
return classifyDiscoveryRecordKind(record2) ?? classifyProcessKind(readProcessCommand(record2.pid));
|
|
37193
|
+
}
|
|
36894
37194
|
function classifyJunkDiscovery(portFile, raw, staleFiles) {
|
|
36895
37195
|
let mtimeMs;
|
|
36896
37196
|
try {
|
|
@@ -36943,7 +37243,9 @@ function inspectRpcServerDiscovery(storageDir) {
|
|
|
36943
37243
|
return { state: "absent", serverPids: [], staleFiles: [] };
|
|
36944
37244
|
}
|
|
36945
37245
|
const pids = new Set;
|
|
37246
|
+
const processByPid = new Map;
|
|
36946
37247
|
const staleFiles = [];
|
|
37248
|
+
const inconclusivePids = new Set;
|
|
36947
37249
|
for (const portFile of portFiles) {
|
|
36948
37250
|
let raw;
|
|
36949
37251
|
try {
|
|
@@ -36963,10 +37265,23 @@ function inspectRpcServerDiscovery(storageDir) {
|
|
|
36963
37265
|
return junk;
|
|
36964
37266
|
continue;
|
|
36965
37267
|
}
|
|
36966
|
-
|
|
37268
|
+
const liveness = isPidAlive(record2.pid);
|
|
37269
|
+
const identity = liveness === "dead" ? "implausible" : isPidIdentityPlausible(record2);
|
|
37270
|
+
if (liveness === "alive" && identity === "plausible") {
|
|
36967
37271
|
pids.add(record2.pid);
|
|
36968
|
-
|
|
37272
|
+
const detected = {
|
|
37273
|
+
kind: classifyRpcProcess(record2),
|
|
37274
|
+
pid: record2.pid
|
|
37275
|
+
};
|
|
37276
|
+
const previous = processByPid.get(record2.pid);
|
|
37277
|
+
if (!previous || previous.kind === "process" && detected.kind !== "process") {
|
|
37278
|
+
processByPid.set(record2.pid, detected);
|
|
37279
|
+
}
|
|
37280
|
+
} else if (liveness === "dead" || identity === "implausible") {
|
|
36969
37281
|
staleFiles.push(portFile);
|
|
37282
|
+
} else {
|
|
37283
|
+
inconclusivePids.add(record2.pid);
|
|
37284
|
+
}
|
|
36970
37285
|
}
|
|
36971
37286
|
for (const staleFile of staleFiles) {
|
|
36972
37287
|
try {
|
|
@@ -36977,14 +37292,28 @@ function inspectRpcServerDiscovery(storageDir) {
|
|
|
36977
37292
|
}
|
|
36978
37293
|
const serverPids = [...pids].sort((a3, b2) => a3 - b2);
|
|
36979
37294
|
if (serverPids.length > 0) {
|
|
36980
|
-
return {
|
|
37295
|
+
return {
|
|
37296
|
+
state: "live",
|
|
37297
|
+
serverPids,
|
|
37298
|
+
serverProcesses: serverPids.map((pid) => processByPid.get(pid) ?? { kind: "process", pid }),
|
|
37299
|
+
staleFiles
|
|
37300
|
+
};
|
|
37301
|
+
}
|
|
37302
|
+
const uncertainPids = [...inconclusivePids].sort((a3, b2) => a3 - b2);
|
|
37303
|
+
if (uncertainPids.length > 0) {
|
|
37304
|
+
return {
|
|
37305
|
+
state: "inconclusive",
|
|
37306
|
+
serverPids: [],
|
|
37307
|
+
staleFiles,
|
|
37308
|
+
inconclusivePids: uncertainPids
|
|
37309
|
+
};
|
|
36981
37310
|
}
|
|
36982
37311
|
return { state: "stale", serverPids: [], staleFiles };
|
|
36983
37312
|
}
|
|
36984
37313
|
function getLiveMigrationBlockingProcesses(storageDir) {
|
|
36985
37314
|
const discovery = inspectRpcServerDiscovery(storageDir);
|
|
36986
|
-
const openCode = discovery.state === "live" ? discovery.
|
|
36987
|
-
const pi = discoverLivePiProcessIds().map((pid) => ({
|
|
37315
|
+
const openCode = discovery.state === "live" ? discovery.serverProcesses ?? [] : [];
|
|
37316
|
+
const pi = discoverLivePiProcessIds().map((pid) => ({ kind: "Pi", pid }));
|
|
36988
37317
|
return [...openCode, ...pi];
|
|
36989
37318
|
}
|
|
36990
37319
|
function applySqliteTuningPragmas(db) {
|
|
@@ -37163,6 +37492,7 @@ function initializeDatabase(db) {
|
|
|
37163
37492
|
last_observed_at INTEGER,
|
|
37164
37493
|
answer_refreshed_at INTEGER,
|
|
37165
37494
|
source_candidate_ids TEXT NOT NULL DEFAULT '[]',
|
|
37495
|
+
source_candidate_provenance TEXT,
|
|
37166
37496
|
created_at INTEGER NOT NULL,
|
|
37167
37497
|
updated_at INTEGER NOT NULL
|
|
37168
37498
|
);
|
|
@@ -37798,6 +38128,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
37798
38128
|
ensureColumn(db, "primer_candidates", "question_embedding", "BLOB");
|
|
37799
38129
|
ensureColumn(db, "primer_candidates", "question_embedding_model_id", "TEXT");
|
|
37800
38130
|
ensureColumn(db, "primers", "question_embedding_model_id", "TEXT");
|
|
38131
|
+
ensureColumn(db, "primers", "source_candidate_provenance", "TEXT");
|
|
38132
|
+
const hasUserMemoriesTable = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'user_memories'").get();
|
|
38133
|
+
if (hasUserMemoriesTable) {
|
|
38134
|
+
ensureColumn(db, "user_memories", "source_candidate_provenance", "TEXT");
|
|
38135
|
+
}
|
|
37801
38136
|
db.exec(`
|
|
37802
38137
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_primer_candidates_occurrence
|
|
37803
38138
|
ON primer_candidates(project_path, harness, session_id, source_start_message_id, source_end_message_id);
|
|
@@ -37871,6 +38206,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
37871
38206
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
37872
38207
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
37873
38208
|
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
38209
|
+
ensureColumn(db, "session_meta", "merged_reasoning_stripped_ids", "TEXT DEFAULT ''");
|
|
38210
|
+
ensureColumn(db, "session_meta", "trailing_blank_decisions", "TEXT DEFAULT ''");
|
|
37874
38211
|
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
37875
38212
|
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
37876
38213
|
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
@@ -38089,7 +38426,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
38089
38426
|
ensureColumn(db, "message_history_index", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
38090
38427
|
ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
38091
38428
|
}
|
|
38092
|
-
var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION =
|
|
38429
|
+
var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION = 78, PERMISSIONS_ENFORCEABLE, RPC_DISCOVERY_PARSE_GRACE_MS, defaultRpcDiscoveryFs, rpcDiscoveryFs, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS;
|
|
38093
38430
|
var init_storage_db = __esm(async () => {
|
|
38094
38431
|
init_data_path();
|
|
38095
38432
|
init_logger();
|
|
@@ -38119,6 +38456,7 @@ var init_storage_db = __esm(async () => {
|
|
|
38119
38456
|
cacheSizeMb: 64,
|
|
38120
38457
|
mmapSizeMb: 0
|
|
38121
38458
|
};
|
|
38459
|
+
CHANNEL2_CLAIM_TTL_MS = 10 * 60000;
|
|
38122
38460
|
});
|
|
38123
38461
|
|
|
38124
38462
|
// src/lib/database-access.ts
|
|
@@ -38224,8 +38562,44 @@ var init_database_access = __esm(async () => {
|
|
|
38224
38562
|
var exports_doctor_authority = {};
|
|
38225
38563
|
__export(exports_doctor_authority, {
|
|
38226
38564
|
runDoctorDrainAuthority: () => runDoctorDrainAuthority,
|
|
38227
|
-
reportAuthorityMarkers: () => reportAuthorityMarkers
|
|
38565
|
+
reportAuthorityMarkers: () => reportAuthorityMarkers,
|
|
38566
|
+
authorityDrainCommand: () => authorityDrainCommand,
|
|
38567
|
+
assertProjectsUseTsAuthority: () => assertProjectsUseTsAuthority
|
|
38228
38568
|
});
|
|
38569
|
+
function authorityDrainCommand(project) {
|
|
38570
|
+
return `magic-context doctor drain-authority ${project.projectRoot ?? `<${project.role} project root>`}`;
|
|
38571
|
+
}
|
|
38572
|
+
async function assertProjectsUseTsAuthority(args) {
|
|
38573
|
+
const markers = listAuthorityManagedMarkers(args.db);
|
|
38574
|
+
const markerByProject = new Map(markers.map((marker) => [marker.project_path, marker]));
|
|
38575
|
+
for (const project of args.projects) {
|
|
38576
|
+
const marker = markerByProject.get(project.projectPath);
|
|
38577
|
+
if (!marker)
|
|
38578
|
+
continue;
|
|
38579
|
+
const projectRoot = project.projectRoot;
|
|
38580
|
+
if (!projectRoot) {
|
|
38581
|
+
throw new Error(`Migration refused: durable module authority for ${project.role} project ${project.projectPath} cannot be checked because its project directory is unavailable. ` + `Writes remain fenced. Drain it first: ${authorityDrainCommand(project)}`);
|
|
38582
|
+
}
|
|
38583
|
+
let statuses;
|
|
38584
|
+
try {
|
|
38585
|
+
statuses = await Promise.all(AUTHORITY_DOMAINS.map((domain2) => args.module.authorityStatus({
|
|
38586
|
+
context_store_uuid: marker.context_store_uuid,
|
|
38587
|
+
project: project.projectPath,
|
|
38588
|
+
projectRoot,
|
|
38589
|
+
domain: domain2
|
|
38590
|
+
})));
|
|
38591
|
+
} catch (error51) {
|
|
38592
|
+
throw new Error(`Migration refused: module unreachable while checking ${project.role} project ${project.projectPath}; writes remain fenced. ` + `Drain it first: ${authorityDrainCommand(project)}. ` + `Module error: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
38593
|
+
}
|
|
38594
|
+
for (const [index, status] of statuses.entries()) {
|
|
38595
|
+
const state = status.authority?.state ?? "TS";
|
|
38596
|
+
if (state === "TS")
|
|
38597
|
+
continue;
|
|
38598
|
+
throw new Error(`Migration refused: ${project.role} project ${project.projectPath} has ${AUTHORITY_DOMAINS[index]} authority in ${state} mode; writes remain fenced. ` + `Drain it first: ${authorityDrainCommand(project)}`);
|
|
38599
|
+
}
|
|
38600
|
+
}
|
|
38601
|
+
return { markers };
|
|
38602
|
+
}
|
|
38229
38603
|
function authorityClient(transport, projectRoot) {
|
|
38230
38604
|
return {
|
|
38231
38605
|
authorityStatus: (request) => transport.authorityStatus({ ...request, projectRoot }),
|
|
@@ -38258,12 +38632,12 @@ async function reportAuthorityMarkers(args) {
|
|
|
38258
38632
|
}
|
|
38259
38633
|
try {
|
|
38260
38634
|
const module = authorityClient(transport, process.cwd());
|
|
38261
|
-
const statuses = await Promise.all(
|
|
38635
|
+
const statuses = await Promise.all(AUTHORITY_DOMAINS.map((domain2) => module.authorityStatus({
|
|
38262
38636
|
context_store_uuid: ensureContextStoreUuid(args.db),
|
|
38263
38637
|
project: marker.project_path,
|
|
38264
38638
|
domain: domain2
|
|
38265
38639
|
})));
|
|
38266
|
-
args.info(` ${marker.project_path}: ${statuses.map((status, index) => `${
|
|
38640
|
+
args.info(` ${marker.project_path}: ${statuses.map((status, index) => `${AUTHORITY_DOMAINS[index]}=${status.authority?.state ?? "TS"}`).join(", ")}`);
|
|
38267
38641
|
} catch {
|
|
38268
38642
|
args.warn(` ${marker.project_path}: module unreachable — writes fenced; run with rust mode or restore subc connectivity`);
|
|
38269
38643
|
}
|
|
@@ -38283,7 +38657,7 @@ async function runDoctorDrainAuthority(projectRoot, dbPath) {
|
|
|
38283
38657
|
}
|
|
38284
38658
|
const module = authorityClient(new SubcModuleTransport, projectRoot);
|
|
38285
38659
|
let drainedAny = false;
|
|
38286
|
-
for (const domain2 of
|
|
38660
|
+
for (const domain2 of AUTHORITY_DOMAINS) {
|
|
38287
38661
|
const status = await module.authorityStatus({
|
|
38288
38662
|
context_store_uuid: ensureContextStoreUuid(db),
|
|
38289
38663
|
project: projectPath,
|
|
@@ -38327,7 +38701,6 @@ async function runDoctorDrainAuthority(projectRoot, dbPath) {
|
|
|
38327
38701
|
db.close();
|
|
38328
38702
|
}
|
|
38329
38703
|
}
|
|
38330
|
-
var DOMAINS;
|
|
38331
38704
|
var init_doctor_authority = __esm(async () => {
|
|
38332
38705
|
init_project_identity();
|
|
38333
38706
|
init_storage_project_state();
|
|
@@ -38336,7 +38709,6 @@ var init_doctor_authority = __esm(async () => {
|
|
|
38336
38709
|
init_context_authority(),
|
|
38337
38710
|
init_database_access()
|
|
38338
38711
|
]);
|
|
38339
|
-
DOMAINS = ["memories", "notes"];
|
|
38340
38712
|
});
|
|
38341
38713
|
|
|
38342
38714
|
// ../plugin/src/features/magic-context/storage-identity-merge.ts
|
|
@@ -39005,7 +39377,7 @@ function printHelp() {
|
|
|
39005
39377
|
}
|
|
39006
39378
|
async function runRepairDb(options = {}) {
|
|
39007
39379
|
const prompts = options.prompts ?? promptIO;
|
|
39008
|
-
const deps = { ...
|
|
39380
|
+
const deps = { ...DEFAULT_DEPS3, ...options.deps };
|
|
39009
39381
|
const storageDir = options.storageDir ?? dirname11(options.dbPath ?? join16(getMagicContextStorageDir(), "context.db"));
|
|
39010
39382
|
const dbPath = options.dbPath ?? join16(storageDir, "context.db");
|
|
39011
39383
|
const stamp = timestamp(deps.now());
|
|
@@ -39175,7 +39547,7 @@ async function runRepairDbCli(args, options = {}) {
|
|
|
39175
39547
|
}
|
|
39176
39548
|
return runRepairDb(options);
|
|
39177
39549
|
}
|
|
39178
|
-
var ROW_COUNT_TABLES, DATABASE_SUFFIXES, RECOGNIZABLE_TABLES, REPAIR_DB_EXIT,
|
|
39550
|
+
var ROW_COUNT_TABLES, DATABASE_SUFFIXES, RECOGNIZABLE_TABLES, REPAIR_DB_EXIT, DEFAULT_DEPS3, RECOVER_UNAVAILABLE_PATTERNS;
|
|
39179
39551
|
var init_doctor_repair_db = __esm(async () => {
|
|
39180
39552
|
init_migrations();
|
|
39181
39553
|
init_data_path();
|
|
@@ -39195,7 +39567,7 @@ var init_doctor_repair_db = __esm(async () => {
|
|
|
39195
39567
|
unsalvageable: 2,
|
|
39196
39568
|
refused: 3
|
|
39197
39569
|
};
|
|
39198
|
-
|
|
39570
|
+
DEFAULT_DEPS3 = {
|
|
39199
39571
|
now: () => new Date,
|
|
39200
39572
|
sqliteExecutable: defaultSqliteExecutable(),
|
|
39201
39573
|
inspectHolders: defaultInspectHolders
|
|
@@ -39225,17 +39597,20 @@ var init_migration_paths = () => {};
|
|
|
39225
39597
|
// src/commands/migrate.ts
|
|
39226
39598
|
var exports_migrate = {};
|
|
39227
39599
|
__export(exports_migrate, {
|
|
39600
|
+
sweepPendingMigrations: () => sweepPendingMigrations,
|
|
39228
39601
|
runMigrateCli: () => runMigrateCli,
|
|
39229
39602
|
projectPathToPiDirSlug: () => projectPathToPiDirSlug,
|
|
39230
39603
|
printMigrateHelp: () => printMigrateHelp,
|
|
39231
39604
|
parseMigrateArgs: () => parseMigrateArgs,
|
|
39605
|
+
migrationKeyFor: () => migrationKeyFor,
|
|
39232
39606
|
migrateOpenCodeSessionToPi: () => migrateOpenCodeSessionToPi,
|
|
39233
39607
|
generateUuidV7: () => generateUuidV7,
|
|
39234
|
-
formatPiFilenameTimestamp: () => formatPiFilenameTimestamp
|
|
39608
|
+
formatPiFilenameTimestamp: () => formatPiFilenameTimestamp,
|
|
39609
|
+
formatMigrationSweepLines: () => formatMigrationSweepLines
|
|
39235
39610
|
});
|
|
39236
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
39237
|
-
import { unlinkSync as unlinkSync3 } from "node:fs";
|
|
39238
|
-
import { join as join18 } from "node:path";
|
|
39611
|
+
import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
|
|
39612
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync8, renameSync as renameSync4, unlinkSync as unlinkSync3 } from "node:fs";
|
|
39613
|
+
import { dirname as dirname12, join as join18 } from "node:path";
|
|
39239
39614
|
function defaultOpenCodeDbPath() {
|
|
39240
39615
|
return getOpenCodeDatabasePath();
|
|
39241
39616
|
}
|
|
@@ -39246,7 +39621,7 @@ function defaultPiSessionsRoot() {
|
|
|
39246
39621
|
return getPiSessionsRoot();
|
|
39247
39622
|
}
|
|
39248
39623
|
function defaultFs() {
|
|
39249
|
-
return { writeFileAtomic, unlinkSync: unlinkSync3 };
|
|
39624
|
+
return { writeFileAtomic, unlinkSync: unlinkSync3, existsSync: existsSync21, renameSync: renameSync4, mkdirSync: mkdirSync8 };
|
|
39250
39625
|
}
|
|
39251
39626
|
function stmt(db, sql) {
|
|
39252
39627
|
return db.prepare(sql);
|
|
@@ -39272,6 +39647,74 @@ function generateUuidV7(date5 = new Date) {
|
|
|
39272
39647
|
function shortId() {
|
|
39273
39648
|
return randomBytes2(4).toString("hex");
|
|
39274
39649
|
}
|
|
39650
|
+
function migrationKeyFor(sourceSessionId, targetHarness) {
|
|
39651
|
+
return createHash3("sha256").update(`${sourceSessionId}
|
|
39652
|
+
${targetHarness}`).digest("hex");
|
|
39653
|
+
}
|
|
39654
|
+
function hasMigrationJournal(db) {
|
|
39655
|
+
return Boolean(stmt(db, "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'migration_pending'").get());
|
|
39656
|
+
}
|
|
39657
|
+
function sweepPendingMigrations(db, fs3 = defaultFs()) {
|
|
39658
|
+
const report = {
|
|
39659
|
+
completed: 0,
|
|
39660
|
+
rolledForward: 0,
|
|
39661
|
+
rolledBack: 0,
|
|
39662
|
+
lost: []
|
|
39663
|
+
};
|
|
39664
|
+
if (!hasMigrationJournal(db))
|
|
39665
|
+
return report;
|
|
39666
|
+
const rows = stmt(db, `SELECT migration_key, source_session_id, target_harness, pi_session_id,
|
|
39667
|
+
final_path, stage_path, content_sha256, phase, created_at
|
|
39668
|
+
FROM migration_pending
|
|
39669
|
+
ORDER BY created_at ASC`).all();
|
|
39670
|
+
for (const row of rows) {
|
|
39671
|
+
if (fs3.existsSync(row.final_path)) {
|
|
39672
|
+
stmt(db, "DELETE FROM migration_pending WHERE migration_key = ?").run(row.migration_key);
|
|
39673
|
+
report.completed += 1;
|
|
39674
|
+
continue;
|
|
39675
|
+
}
|
|
39676
|
+
if (row.phase === "db_committed") {
|
|
39677
|
+
if (fs3.existsSync(row.stage_path)) {
|
|
39678
|
+
fs3.mkdirSync(dirname12(row.final_path), { recursive: true });
|
|
39679
|
+
fs3.renameSync(row.stage_path, row.final_path);
|
|
39680
|
+
stmt(db, "DELETE FROM migration_pending WHERE migration_key = ?").run(row.migration_key);
|
|
39681
|
+
report.rolledForward += 1;
|
|
39682
|
+
} else {
|
|
39683
|
+
report.lost.push(row);
|
|
39684
|
+
}
|
|
39685
|
+
continue;
|
|
39686
|
+
}
|
|
39687
|
+
try {
|
|
39688
|
+
fs3.unlinkSync(row.stage_path);
|
|
39689
|
+
} catch {}
|
|
39690
|
+
stmt(db, "DELETE FROM migration_pending WHERE migration_key = ?").run(row.migration_key);
|
|
39691
|
+
report.rolledBack += 1;
|
|
39692
|
+
}
|
|
39693
|
+
return report;
|
|
39694
|
+
}
|
|
39695
|
+
function readPendingMigration(db, migrationKey) {
|
|
39696
|
+
return stmt(db, JOURNAL_SELECT_SQL).get(migrationKey);
|
|
39697
|
+
}
|
|
39698
|
+
function claimJournalIdentity(args) {
|
|
39699
|
+
const existing = readPendingMigration(args.db, args.migrationKey);
|
|
39700
|
+
if (existing) {
|
|
39701
|
+
return { row: existing, resumed: true };
|
|
39702
|
+
}
|
|
39703
|
+
const piSessionId = generateUuidV7(new Date(args.now));
|
|
39704
|
+
stmt(args.db, `INSERT INTO migration_pending (
|
|
39705
|
+
migration_key, source_session_id, target_harness, pi_session_id,
|
|
39706
|
+
final_path, stage_path, content_sha256, phase, created_at
|
|
39707
|
+
) VALUES (?, ?, ?, ?, ?, ?, '', 'staged', ?)
|
|
39708
|
+
ON CONFLICT(migration_key) DO NOTHING`).run(args.migrationKey, args.sourceSessionId, args.targetHarness, piSessionId, args.finalPathFor(piSessionId), join18(args.stageDir, `${args.migrationKey}.jsonl`), args.now);
|
|
39709
|
+
const row = readPendingMigration(args.db, args.migrationKey);
|
|
39710
|
+
if (!row) {
|
|
39711
|
+
throw new Error("migration journal row disappeared during insert; aborting migration");
|
|
39712
|
+
}
|
|
39713
|
+
return { row, resumed: row.pi_session_id !== piSessionId };
|
|
39714
|
+
}
|
|
39715
|
+
function commitStagedChecksum(db, migrationKey, contentSha256) {
|
|
39716
|
+
stmt(db, "UPDATE migration_pending SET content_sha256 = ? WHERE migration_key = ?").run(contentSha256, migrationKey);
|
|
39717
|
+
}
|
|
39275
39718
|
function parseJsonObject(text3) {
|
|
39276
39719
|
const parsed = JSON.parse(text3);
|
|
39277
39720
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -39431,7 +39874,7 @@ function convertPartToEntries(ctx) {
|
|
|
39431
39874
|
}
|
|
39432
39875
|
}
|
|
39433
39876
|
function buildPiEntries(params) {
|
|
39434
|
-
const sessionUuid =
|
|
39877
|
+
const sessionUuid = params.piSessionId;
|
|
39435
39878
|
const nowIso = params.now.toISOString();
|
|
39436
39879
|
const entries = [
|
|
39437
39880
|
{
|
|
@@ -39467,6 +39910,7 @@ The following conversation was migrated from a different harness. Reasoning cont
|
|
|
39467
39910
|
list.push(part);
|
|
39468
39911
|
partsByMessage.set(part.message_id, list);
|
|
39469
39912
|
}
|
|
39913
|
+
const messageIdToFirstPiEntryId = new Map;
|
|
39470
39914
|
const messageIdToLastPiEntryId = new Map;
|
|
39471
39915
|
const orderedSourceMessageIds = [];
|
|
39472
39916
|
let parentId = boundary.id;
|
|
@@ -39477,6 +39921,7 @@ The following conversation was migrated from a different harness. Reasoning cont
|
|
|
39477
39921
|
const timestamp2 = isoFromMs(message.time_created, params.now);
|
|
39478
39922
|
const tokens = tokensFromMessage(message);
|
|
39479
39923
|
const usage = tokensToPiUsage(tokens);
|
|
39924
|
+
let firstEntryIdForMessage = null;
|
|
39480
39925
|
let lastEntryIdForMessage = null;
|
|
39481
39926
|
for (const part of partsByMessage.get(message.id) ?? []) {
|
|
39482
39927
|
const newEntries = convertPartToEntries({
|
|
@@ -39491,10 +39936,13 @@ The following conversation was migrated from a different harness. Reasoning cont
|
|
|
39491
39936
|
entry.parentId = parentId;
|
|
39492
39937
|
entries.push(entry);
|
|
39493
39938
|
parentId = entry.id;
|
|
39939
|
+
if (firstEntryIdForMessage === null)
|
|
39940
|
+
firstEntryIdForMessage = parentId;
|
|
39494
39941
|
lastEntryIdForMessage = parentId;
|
|
39495
39942
|
}
|
|
39496
39943
|
}
|
|
39497
|
-
if (lastEntryIdForMessage !== null) {
|
|
39944
|
+
if (lastEntryIdForMessage !== null && firstEntryIdForMessage !== null) {
|
|
39945
|
+
messageIdToFirstPiEntryId.set(message.id, firstEntryIdForMessage);
|
|
39498
39946
|
messageIdToLastPiEntryId.set(message.id, lastEntryIdForMessage);
|
|
39499
39947
|
orderedSourceMessageIds.push(message.id);
|
|
39500
39948
|
}
|
|
@@ -39502,6 +39950,7 @@ The following conversation was migrated from a different harness. Reasoning cont
|
|
|
39502
39950
|
return {
|
|
39503
39951
|
entries,
|
|
39504
39952
|
piSessionId: sessionUuid,
|
|
39953
|
+
messageIdToFirstPiEntryId,
|
|
39505
39954
|
messageIdToLastPiEntryId,
|
|
39506
39955
|
orderedSourceMessageIds
|
|
39507
39956
|
};
|
|
@@ -39539,8 +39988,9 @@ function fetchRows(db, sessionId, maxMessages) {
|
|
|
39539
39988
|
throw error51;
|
|
39540
39989
|
}
|
|
39541
39990
|
}
|
|
39542
|
-
function remapBoundaryId(openCodeMessageId, messageIdToLastPiEntryId, orderedSourceMessageIds) {
|
|
39543
|
-
const
|
|
39991
|
+
function remapBoundaryId(openCodeMessageId, edge, messageIdToFirstPiEntryId, messageIdToLastPiEntryId, orderedSourceMessageIds) {
|
|
39992
|
+
const directMap = edge === "start" ? messageIdToFirstPiEntryId : messageIdToLastPiEntryId;
|
|
39993
|
+
const direct = directMap.get(openCodeMessageId);
|
|
39544
39994
|
if (direct !== undefined)
|
|
39545
39995
|
return { piEntryId: direct, exact: true };
|
|
39546
39996
|
let nearestAtOrBefore;
|
|
@@ -39601,8 +40051,8 @@ function copyMagicContextState(args) {
|
|
|
39601
40051
|
let boundariesApproximated = 0;
|
|
39602
40052
|
const remappedCompartments = [];
|
|
39603
40053
|
for (const c3 of sourceCompartments) {
|
|
39604
|
-
const startRemap = remapBoundaryId(c3.start_message_id, args.messageIdToLastPiEntryId, args.orderedSourceMessageIds);
|
|
39605
|
-
const endRemap = remapBoundaryId(c3.end_message_id, args.messageIdToLastPiEntryId, args.orderedSourceMessageIds);
|
|
40054
|
+
const startRemap = remapBoundaryId(c3.start_message_id, "start", args.messageIdToFirstPiEntryId, args.messageIdToLastPiEntryId, args.orderedSourceMessageIds);
|
|
40055
|
+
const endRemap = remapBoundaryId(c3.end_message_id, "end", args.messageIdToFirstPiEntryId, args.messageIdToLastPiEntryId, args.orderedSourceMessageIds);
|
|
39606
40056
|
if (!startRemap || !endRemap)
|
|
39607
40057
|
continue;
|
|
39608
40058
|
if (!startRemap.exact || !endRemap.exact)
|
|
@@ -39631,9 +40081,9 @@ function copyMagicContextState(args) {
|
|
|
39631
40081
|
lastCompartmentEndPiEntryId: remappedCompartments.at(-1)?.end_message_id
|
|
39632
40082
|
};
|
|
39633
40083
|
if (args.dryRun) {
|
|
39634
|
-
return { ...result, commit: () => {} };
|
|
40084
|
+
return { ...result, remappedCompartments, commit: () => {} };
|
|
39635
40085
|
}
|
|
39636
|
-
const commit = () => {
|
|
40086
|
+
const commit = (journalKey) => {
|
|
39637
40087
|
const insertCompartment = stmt(args.cortexkitDb, `INSERT INTO compartments (
|
|
39638
40088
|
session_id, sequence, start_message, end_message,
|
|
39639
40089
|
start_message_id, end_message_id, title, content,
|
|
@@ -39645,19 +40095,72 @@ function copyMagicContextState(args) {
|
|
|
39645
40095
|
) VALUES (?, ?, ?, ?, ?, 'pi')`);
|
|
39646
40096
|
args.cortexkitDb.exec("BEGIN IMMEDIATE");
|
|
39647
40097
|
try {
|
|
40098
|
+
stmt(args.cortexkitDb, "DELETE FROM compartments WHERE session_id = ? AND harness = 'pi'").run(args.piSessionId);
|
|
40099
|
+
stmt(args.cortexkitDb, "DELETE FROM session_facts WHERE session_id = ? AND harness = 'pi'").run(args.piSessionId);
|
|
39648
40100
|
for (const c3 of remappedCompartments) {
|
|
39649
40101
|
insertCompartment.run(args.piSessionId, c3.sequence, c3.start_message, c3.end_message, c3.start_message_id, c3.end_message_id, c3.title, c3.content, c3.p1, c3.p2, c3.p3, c3.p4, typeof c3.importance === "number" ? c3.importance : 50, c3.episode_type, c3.legacy, args.now);
|
|
39650
40102
|
}
|
|
39651
40103
|
for (const f2 of sourceFacts) {
|
|
39652
40104
|
insertFact.run(args.piSessionId, f2.category, f2.content, f2.created_at, f2.updated_at);
|
|
39653
40105
|
}
|
|
40106
|
+
if (journalKey !== undefined) {
|
|
40107
|
+
stmt(args.cortexkitDb, "UPDATE migration_pending SET phase = 'db_committed' WHERE migration_key = ?").run(journalKey);
|
|
40108
|
+
}
|
|
39654
40109
|
args.cortexkitDb.exec("COMMIT");
|
|
39655
40110
|
} catch (error51) {
|
|
39656
40111
|
args.cortexkitDb.exec("ROLLBACK");
|
|
39657
40112
|
throw error51;
|
|
39658
40113
|
}
|
|
39659
40114
|
};
|
|
39660
|
-
return { ...result, commit };
|
|
40115
|
+
return { ...result, remappedCompartments, commit };
|
|
40116
|
+
}
|
|
40117
|
+
function derivePiRuntimeOrdinals(entries) {
|
|
40118
|
+
const ordinalByEntryId = new Map;
|
|
40119
|
+
let nextOrdinal = 1;
|
|
40120
|
+
const pendingToolResultIds = [];
|
|
40121
|
+
const foldPendingInto = (ordinal) => {
|
|
40122
|
+
for (const id of pendingToolResultIds)
|
|
40123
|
+
ordinalByEntryId.set(id, ordinal);
|
|
40124
|
+
pendingToolResultIds.length = 0;
|
|
40125
|
+
};
|
|
40126
|
+
for (const entry of entries) {
|
|
40127
|
+
const message = entry.message;
|
|
40128
|
+
if (entry.type !== "message" || typeof entry.id !== "string" || message === null || typeof message !== "object") {
|
|
40129
|
+
continue;
|
|
40130
|
+
}
|
|
40131
|
+
const role = message.role;
|
|
40132
|
+
if (role === "toolResult") {
|
|
40133
|
+
pendingToolResultIds.push(entry.id);
|
|
40134
|
+
continue;
|
|
40135
|
+
}
|
|
40136
|
+
if (role === "assistant" && pendingToolResultIds.length > 0) {
|
|
40137
|
+
foldPendingInto(nextOrdinal);
|
|
40138
|
+
nextOrdinal += 1;
|
|
40139
|
+
}
|
|
40140
|
+
const ordinal = nextOrdinal;
|
|
40141
|
+
nextOrdinal += 1;
|
|
40142
|
+
if (role === "user" && pendingToolResultIds.length > 0) {
|
|
40143
|
+
foldPendingInto(ordinal);
|
|
40144
|
+
}
|
|
40145
|
+
ordinalByEntryId.set(entry.id, ordinal);
|
|
40146
|
+
}
|
|
40147
|
+
if (pendingToolResultIds.length > 0) {
|
|
40148
|
+
foldPendingInto(nextOrdinal);
|
|
40149
|
+
}
|
|
40150
|
+
return ordinalByEntryId;
|
|
40151
|
+
}
|
|
40152
|
+
function applyRuntimeOrdinals(remappedCompartments, entries) {
|
|
40153
|
+
const ordinals = derivePiRuntimeOrdinals(entries);
|
|
40154
|
+
for (const compartment of remappedCompartments) {
|
|
40155
|
+
const startOrdinal = ordinals.get(compartment.start_message_id);
|
|
40156
|
+
const endOrdinal = ordinals.get(compartment.end_message_id);
|
|
40157
|
+
if (startOrdinal === undefined || endOrdinal === undefined) {
|
|
40158
|
+
const missing = startOrdinal === undefined ? compartment.start_message_id : compartment.end_message_id;
|
|
40159
|
+
throw new Error(`Migration boundary entry ${missing} has no runtime ordinal; migrator invariant violated`);
|
|
40160
|
+
}
|
|
40161
|
+
compartment.start_message = startOrdinal;
|
|
40162
|
+
compartment.end_message = endOrdinal;
|
|
40163
|
+
}
|
|
39661
40164
|
}
|
|
39662
40165
|
function ensureValidOptions(opts) {
|
|
39663
40166
|
if (!opts.from)
|
|
@@ -39707,52 +40210,88 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
39707
40210
|
const modelId = opts.modelId ?? model.modelId;
|
|
39708
40211
|
const cwd = session.directory ?? session.path ?? process.cwd();
|
|
39709
40212
|
const outputDir = join18(piSessionsRoot, projectPathToPiDirSlug(cwd));
|
|
40213
|
+
const targetHarness = opts.targetHarness ?? "pi";
|
|
40214
|
+
const journalActive = cortexkitDb !== null && !opts.dryRun;
|
|
40215
|
+
let recovery;
|
|
40216
|
+
let migrationKey;
|
|
40217
|
+
let journalResumed = false;
|
|
40218
|
+
let piSessionId;
|
|
40219
|
+
let finalPath;
|
|
40220
|
+
let stagePath;
|
|
40221
|
+
if (journalActive && cortexkitDb !== null) {
|
|
40222
|
+
if (!hasMigrationJournal(cortexkitDb)) {
|
|
40223
|
+
throw new Error("context.db has no migration_pending journal (shared schema older than v78). Run a harness session once so the plugin can upgrade the schema, then retry doctor migrate.");
|
|
40224
|
+
}
|
|
40225
|
+
recovery = sweepPendingMigrations(cortexkitDb, fs3);
|
|
40226
|
+
migrationKey = migrationKeyFor(session.id, targetHarness);
|
|
40227
|
+
const claimed = claimJournalIdentity({
|
|
40228
|
+
db: cortexkitDb,
|
|
40229
|
+
migrationKey,
|
|
40230
|
+
sourceSessionId: session.id,
|
|
40231
|
+
targetHarness,
|
|
40232
|
+
finalPathFor: (id) => join18(outputDir, `${formatPiFilenameTimestamp(now)}_${id}.jsonl`),
|
|
40233
|
+
stageDir: join18(dirname12(piSessionsRoot), MIGRATION_STAGE_DIRNAME),
|
|
40234
|
+
now: now.getTime()
|
|
40235
|
+
});
|
|
40236
|
+
piSessionId = claimed.row.pi_session_id;
|
|
40237
|
+
finalPath = claimed.row.final_path;
|
|
40238
|
+
stagePath = claimed.row.stage_path;
|
|
40239
|
+
journalResumed = claimed.resumed;
|
|
40240
|
+
} else {
|
|
40241
|
+
piSessionId = generateUuidV7(now);
|
|
40242
|
+
finalPath = join18(outputDir, `${formatPiFilenameTimestamp(now)}_${piSessionId}.jsonl`);
|
|
40243
|
+
stagePath = "";
|
|
40244
|
+
}
|
|
39710
40245
|
const buildResult = buildPiEntries({
|
|
39711
40246
|
session,
|
|
39712
40247
|
messages,
|
|
39713
40248
|
parts,
|
|
39714
40249
|
now,
|
|
39715
40250
|
provider,
|
|
39716
|
-
modelId
|
|
40251
|
+
modelId,
|
|
40252
|
+
piSessionId
|
|
39717
40253
|
});
|
|
39718
40254
|
let copyResult = {
|
|
39719
40255
|
compartmentsCopied: 0,
|
|
39720
40256
|
factsCopied: 0,
|
|
39721
40257
|
boundariesApproximated: 0
|
|
39722
40258
|
};
|
|
39723
|
-
let
|
|
40259
|
+
let plan = null;
|
|
39724
40260
|
if (cortexkitDb !== null) {
|
|
39725
|
-
|
|
40261
|
+
plan = copyMagicContextState({
|
|
39726
40262
|
cortexkitDb,
|
|
39727
40263
|
sourceSessionId: session.id,
|
|
39728
|
-
piSessionId
|
|
40264
|
+
piSessionId,
|
|
40265
|
+
messageIdToFirstPiEntryId: buildResult.messageIdToFirstPiEntryId,
|
|
39729
40266
|
messageIdToLastPiEntryId: buildResult.messageIdToLastPiEntryId,
|
|
39730
40267
|
orderedSourceMessageIds: buildResult.orderedSourceMessageIds,
|
|
39731
40268
|
now: now.getTime(),
|
|
39732
40269
|
dryRun: Boolean(opts.dryRun)
|
|
39733
40270
|
});
|
|
39734
40271
|
copyResult = plan;
|
|
39735
|
-
commitMagicContextState = plan.commit;
|
|
39736
40272
|
}
|
|
39737
40273
|
const compactionMarker = insertCompactionMarker(buildResult.entries, copyResult.lastCompartmentEndPiEntryId);
|
|
39738
|
-
|
|
40274
|
+
if (plan)
|
|
40275
|
+
applyRuntimeOrdinals(plan.remappedCompartments, buildResult.entries);
|
|
39739
40276
|
const jsonl = `${buildResult.entries.map((entry) => JSON.stringify(entry)).join(`
|
|
39740
40277
|
`)}
|
|
39741
40278
|
`;
|
|
39742
40279
|
if (!opts.dryRun) {
|
|
39743
|
-
|
|
39744
|
-
|
|
39745
|
-
|
|
39746
|
-
|
|
39747
|
-
|
|
39748
|
-
|
|
39749
|
-
|
|
39750
|
-
|
|
40280
|
+
if (journalActive && cortexkitDb !== null && migrationKey !== undefined && plan) {
|
|
40281
|
+
const contentSha256 = createHash3("sha256").update(jsonl, "utf8").digest("hex");
|
|
40282
|
+
commitStagedChecksum(cortexkitDb, migrationKey, contentSha256);
|
|
40283
|
+
fs3.writeFileAtomic(stagePath, jsonl);
|
|
40284
|
+
plan.commit(migrationKey);
|
|
40285
|
+
fs3.mkdirSync(dirname12(finalPath), { recursive: true });
|
|
40286
|
+
fs3.renameSync(stagePath, finalPath);
|
|
40287
|
+
stmt(cortexkitDb, "DELETE FROM migration_pending WHERE migration_key = ?").run(migrationKey);
|
|
40288
|
+
} else {
|
|
40289
|
+
fs3.writeFileAtomic(finalPath, jsonl);
|
|
39751
40290
|
}
|
|
39752
40291
|
}
|
|
39753
40292
|
return {
|
|
39754
|
-
outputPath,
|
|
39755
|
-
piSessionId
|
|
40293
|
+
outputPath: finalPath,
|
|
40294
|
+
piSessionId,
|
|
39756
40295
|
messageCount: buildResult.entries.length - 2,
|
|
39757
40296
|
byteCount: Buffer.byteLength(jsonl, "utf8"),
|
|
39758
40297
|
sourceMessageCount,
|
|
@@ -39762,6 +40301,9 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
39762
40301
|
compactionMarkerWritten: compactionMarker.written,
|
|
39763
40302
|
compactionBoundaryEntryId: compactionMarker.boundaryEntryId,
|
|
39764
40303
|
compactionFirstKeptEntryId: compactionMarker.firstKeptEntryId,
|
|
40304
|
+
...migrationKey !== undefined ? { migrationKey } : {},
|
|
40305
|
+
...journalActive ? { journalResumed } : {},
|
|
40306
|
+
...recovery !== undefined ? { recovery } : {},
|
|
39765
40307
|
...cortexkitSchemaVersionBefore !== null && cortexkitDb !== null ? {
|
|
39766
40308
|
cortexkitSchemaVersionBefore,
|
|
39767
40309
|
cortexkitSchemaVersionAfter: getPersistedSchemaVersion2(cortexkitDb)
|
|
@@ -39828,9 +40370,32 @@ function printMigrateHelp() {
|
|
|
39828
40370
|
- compartments + session_facts are copied to the new Pi session_id;
|
|
39829
40371
|
compartment boundary message IDs are remapped to the corresponding
|
|
39830
40372
|
Pi entry IDs (nearest-at-or-before for boundaries that don't have
|
|
39831
|
-
a direct message-level Pi entry)
|
|
40373
|
+
a direct message-level Pi entry), and compartment start/end ordinals
|
|
40374
|
+
are recomputed in the ordinal basis the Pi runtime reader produces
|
|
40375
|
+
|
|
40376
|
+
Crash safety:
|
|
40377
|
+
- each migration is tracked in the shared DB's migration_pending journal
|
|
40378
|
+
and staged outside the sessions tree; an interrupted run is reconciled
|
|
40379
|
+
by phase on the next 'doctor migrate' or plain 'doctor' run, reusing the
|
|
40380
|
+
original Pi session id instead of minting a second one
|
|
39832
40381
|
`);
|
|
39833
40382
|
}
|
|
40383
|
+
function formatMigrationSweepLines(report) {
|
|
40384
|
+
const lines = [];
|
|
40385
|
+
if (report.rolledForward > 0) {
|
|
40386
|
+
lines.push(`Recovered ${report.rolledForward} interrupted session migration(s) by completing the staged file rename.`);
|
|
40387
|
+
}
|
|
40388
|
+
if (report.rolledBack > 0) {
|
|
40389
|
+
lines.push(`Rolled back ${report.rolledBack} incomplete session migration(s) that never committed shared state.`);
|
|
40390
|
+
}
|
|
40391
|
+
if (report.completed > 0) {
|
|
40392
|
+
lines.push(`Cleared ${report.completed} finished session-migration journal row(s).`);
|
|
40393
|
+
}
|
|
40394
|
+
for (const row of report.lost) {
|
|
40395
|
+
lines.push(`LOST session migration content: source ${row.source_session_id} → ${row.target_harness} session ${row.pi_session_id}; expected file ${row.final_path} (sha256 ${row.content_sha256}). Re-run doctor migrate for this session to rebuild it.`);
|
|
40396
|
+
}
|
|
40397
|
+
return lines;
|
|
40398
|
+
}
|
|
39834
40399
|
async function runMigrateCli(args) {
|
|
39835
40400
|
try {
|
|
39836
40401
|
const parsed = parseMigrateArgs(args);
|
|
@@ -39840,8 +40405,14 @@ async function runMigrateCli(args) {
|
|
|
39840
40405
|
sessionId: parsed.session,
|
|
39841
40406
|
maxMessages: parsed.maxMessages,
|
|
39842
40407
|
dryRun: parsed.dryRun,
|
|
39843
|
-
piSessionsRoot: parsed.to === "omp" ? getOmpSessionsRoot() : undefined
|
|
40408
|
+
piSessionsRoot: parsed.to === "omp" ? getOmpSessionsRoot() : undefined,
|
|
40409
|
+
targetHarness: parsed.to === "omp" ? "omp" : "pi"
|
|
39844
40410
|
});
|
|
40411
|
+
if (result.recovery) {
|
|
40412
|
+
for (const line of formatMigrationSweepLines(result.recovery)) {
|
|
40413
|
+
console.log(line);
|
|
40414
|
+
}
|
|
40415
|
+
}
|
|
39845
40416
|
const action = result.dryRun ? "Would write" : "Wrote";
|
|
39846
40417
|
console.log(`${action} ${target} session JSONL:`);
|
|
39847
40418
|
console.log(` path: ${result.outputPath}`);
|
|
@@ -39858,6 +40429,9 @@ async function runMigrateCli(args) {
|
|
|
39858
40429
|
if (result.boundariesApproximated > 0) {
|
|
39859
40430
|
console.log(` boundaries approximated: ${result.boundariesApproximated} (nearest-at-or-before)`);
|
|
39860
40431
|
}
|
|
40432
|
+
if (result.migrationKey !== undefined) {
|
|
40433
|
+
console.log(` journal: ${result.migrationKey.slice(0, 12)}…${result.journalResumed ? " (resumed interrupted attempt)" : ""}`);
|
|
40434
|
+
}
|
|
39861
40435
|
if (!result.dryRun) {
|
|
39862
40436
|
console.log(`${target} may need to be restarted to pick up the new session file.`);
|
|
39863
40437
|
if (result.cortexkitSchemaVersionBefore !== undefined) {
|
|
@@ -39875,7 +40449,9 @@ async function runMigrateCli(args) {
|
|
|
39875
40449
|
return 1;
|
|
39876
40450
|
}
|
|
39877
40451
|
}
|
|
39878
|
-
var DEFAULT_PROVIDER = "openai-codex", DEFAULT_MODEL = "gpt-5.5", MIGRATION_COMPACTION_SUMMARY = "Magic Context compacted prior conversation. See <session-history> block for the structured summary.", PART_LOOKUP_CHUNK_SIZE = 900
|
|
40452
|
+
var DEFAULT_PROVIDER = "openai-codex", DEFAULT_MODEL = "gpt-5.5", MIGRATION_COMPACTION_SUMMARY = "Magic Context compacted prior conversation. See <session-history> block for the structured summary.", PART_LOOKUP_CHUNK_SIZE = 900, MIGRATION_STAGE_DIRNAME = ".mc-migrations", JOURNAL_SELECT_SQL = `SELECT migration_key, source_session_id, target_harness, pi_session_id,
|
|
40453
|
+
final_path, stage_path, content_sha256, phase, created_at
|
|
40454
|
+
FROM migration_pending WHERE migration_key = ?`;
|
|
39879
40455
|
var init_migrate = __esm(async () => {
|
|
39880
40456
|
init_data_path();
|
|
39881
40457
|
init_atomic_write();
|
|
@@ -39979,15 +40555,72 @@ var exports_migrate_session = {};
|
|
|
39979
40555
|
__export(exports_migrate_session, {
|
|
39980
40556
|
runMigrateSessionCli: () => runMigrateSessionCli,
|
|
39981
40557
|
planMigrateSession: () => planMigrateSession,
|
|
40558
|
+
assertMigrateSessionIsSafeToRehome: () => assertMigrateSessionIsSafeToRehome,
|
|
39982
40559
|
applyMigrateSession: () => applyMigrateSession
|
|
39983
40560
|
});
|
|
39984
|
-
import { existsSync as
|
|
40561
|
+
import { existsSync as existsSync22, realpathSync as realpathSync4 } from "node:fs";
|
|
39985
40562
|
import { homedir as homedir13 } from "node:os";
|
|
39986
40563
|
import path4, { join as join19 } from "node:path";
|
|
39987
40564
|
function existingSessionColumns(db) {
|
|
39988
40565
|
const rows = db.prepare("PRAGMA table_info(session)").all();
|
|
39989
40566
|
return new Set(rows.map((r2) => r2.name).filter((n2) => typeof n2 === "string"));
|
|
39990
40567
|
}
|
|
40568
|
+
function isModuleCacheStatePresent(status) {
|
|
40569
|
+
if (!status || typeof status !== "object")
|
|
40570
|
+
return false;
|
|
40571
|
+
const rowVersion = status.row_version;
|
|
40572
|
+
return typeof rowVersion === "number";
|
|
40573
|
+
}
|
|
40574
|
+
function drainCommandsForMarkers(markers, projects) {
|
|
40575
|
+
const byProject = new Map(projects.map((project) => [project.projectPath, project]));
|
|
40576
|
+
return [
|
|
40577
|
+
...new Set(markers.map((marker) => authorityDrainCommand(byProject.get(marker.project_path) ?? {
|
|
40578
|
+
role: "marked",
|
|
40579
|
+
projectPath: marker.project_path,
|
|
40580
|
+
projectRoot: null
|
|
40581
|
+
})))
|
|
40582
|
+
].join("; ");
|
|
40583
|
+
}
|
|
40584
|
+
async function assertMigrateSessionIsSafeToRehome(args) {
|
|
40585
|
+
const projects = [
|
|
40586
|
+
{
|
|
40587
|
+
role: "source",
|
|
40588
|
+
projectPath: args.plan.fromMcIdentity,
|
|
40589
|
+
projectRoot: args.plan.currentDirectory
|
|
40590
|
+
},
|
|
40591
|
+
{
|
|
40592
|
+
role: "target",
|
|
40593
|
+
projectPath: args.plan.toMcIdentity,
|
|
40594
|
+
projectRoot: args.plan.targetDirectory
|
|
40595
|
+
}
|
|
40596
|
+
];
|
|
40597
|
+
const authority = await assertProjectsUseTsAuthority({
|
|
40598
|
+
db: args.contextDb,
|
|
40599
|
+
projects,
|
|
40600
|
+
module: args.module
|
|
40601
|
+
});
|
|
40602
|
+
let sessionStatus;
|
|
40603
|
+
try {
|
|
40604
|
+
sessionStatus = await args.module.sessionStatus({
|
|
40605
|
+
sessionId: args.plan.sessionId,
|
|
40606
|
+
projectRoot: args.plan.currentDirectory ?? args.plan.targetDirectory
|
|
40607
|
+
});
|
|
40608
|
+
} catch (error51) {
|
|
40609
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
40610
|
+
if (authority.markers.length === 0) {
|
|
40611
|
+
return {
|
|
40612
|
+
warnings: [
|
|
40613
|
+
`Module session-cache state was not checked because the module is unreachable: ${message}. No durable authority markers exist, so continuing for this pure-TypeScript installation.`
|
|
40614
|
+
]
|
|
40615
|
+
};
|
|
40616
|
+
}
|
|
40617
|
+
throw new Error("Migration refused: module session-cache state is unreachable while durable authority markers exist; writes remain fenced. " + `Drain marked projects first: ${drainCommandsForMarkers(authority.markers, projects)}. ` + `Module error: ${message}`);
|
|
40618
|
+
}
|
|
40619
|
+
if (isModuleCacheStatePresent(sessionStatus)) {
|
|
40620
|
+
throw new Error(`Migration refused: the module still holds transform cache state for session ${args.plan.sessionId}. ` + "Use TypeScript transform mode for the session's project, or run `ck session delete` after preserving any needed state, then re-run this migration.");
|
|
40621
|
+
}
|
|
40622
|
+
return { warnings: [] };
|
|
40623
|
+
}
|
|
39991
40624
|
function planMigrateSession(sessionId, rawTargetDirectory, deps) {
|
|
39992
40625
|
const sessionRow = deps.opencodeDb.prepare("SELECT id, directory FROM session WHERE id = ?").get(sessionId);
|
|
39993
40626
|
if (!sessionRow) {
|
|
@@ -40144,7 +40777,7 @@ function realDeps(opencodeDb, contextDb) {
|
|
|
40144
40777
|
opencodeDb,
|
|
40145
40778
|
contextDb,
|
|
40146
40779
|
resolveIdentity: resolveProjectIdentity,
|
|
40147
|
-
hasGitDir: (dir) =>
|
|
40780
|
+
hasGitDir: (dir) => existsSync22(join19(dir, ".git")),
|
|
40148
40781
|
realpath: (p2) => realpathSync4(p2)
|
|
40149
40782
|
};
|
|
40150
40783
|
}
|
|
@@ -40223,7 +40856,7 @@ async function runMigrateSessionCli(args) {
|
|
|
40223
40856
|
return 1;
|
|
40224
40857
|
}
|
|
40225
40858
|
const expandedTo = toDir.startsWith("~") ? join19(homedir13(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
|
|
40226
|
-
if (!
|
|
40859
|
+
if (!existsSync22(expandedTo)) {
|
|
40227
40860
|
console.error(`Target directory does not exist: ${expandedTo}`);
|
|
40228
40861
|
return 1;
|
|
40229
40862
|
}
|
|
@@ -40249,6 +40882,27 @@ async function runMigrateSessionCli(args) {
|
|
|
40249
40882
|
} catch {}
|
|
40250
40883
|
const deps = realDeps(opencodeDb, contextDb);
|
|
40251
40884
|
const plan = planMigrateSession(sessionId, expandedTo, deps);
|
|
40885
|
+
const transport = new SubcModuleTransport;
|
|
40886
|
+
const safety = await assertMigrateSessionIsSafeToRehome({
|
|
40887
|
+
plan,
|
|
40888
|
+
contextDb,
|
|
40889
|
+
module: {
|
|
40890
|
+
authorityStatus: (request) => transport.authorityStatus(request),
|
|
40891
|
+
sessionStatus: ({ sessionId: statusSessionId, projectRoot }) => transport.call({
|
|
40892
|
+
sessionId: statusSessionId,
|
|
40893
|
+
projectRoot,
|
|
40894
|
+
method: "session.status",
|
|
40895
|
+
body: {
|
|
40896
|
+
method: "session.status",
|
|
40897
|
+
v: 1,
|
|
40898
|
+
session_id: statusSessionId
|
|
40899
|
+
}
|
|
40900
|
+
})
|
|
40901
|
+
}
|
|
40902
|
+
});
|
|
40903
|
+
for (const warning of safety.warnings) {
|
|
40904
|
+
promptIO.log.warn(warning);
|
|
40905
|
+
}
|
|
40252
40906
|
promptIO.note([
|
|
40253
40907
|
`session: ${plan.sessionId}`,
|
|
40254
40908
|
`from: ${plan.currentDirectory ?? "(unknown)"}`,
|
|
@@ -40332,10 +40986,14 @@ var init_migrate_session = __esm(async () => {
|
|
|
40332
40986
|
init_project_identity();
|
|
40333
40987
|
init_relocate_memory();
|
|
40334
40988
|
init_storage_project_state();
|
|
40989
|
+
init_module_transport();
|
|
40335
40990
|
init_data_path();
|
|
40336
40991
|
init_migration_paths();
|
|
40337
40992
|
init_prompts();
|
|
40338
|
-
await
|
|
40993
|
+
await __promiseAll([
|
|
40994
|
+
init_database_access(),
|
|
40995
|
+
init_doctor_authority()
|
|
40996
|
+
]);
|
|
40339
40997
|
VALID_MEMORY_ACTIONS = new Set([
|
|
40340
40998
|
"move-all",
|
|
40341
40999
|
"move-originated",
|
|
@@ -40346,7 +41004,7 @@ var init_migrate_session = __esm(async () => {
|
|
|
40346
41004
|
});
|
|
40347
41005
|
|
|
40348
41006
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
40349
|
-
import { createHash as
|
|
41007
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
40350
41008
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
40351
41009
|
import path5 from "node:path";
|
|
40352
41010
|
function readMeta(db, key) {
|
|
@@ -40395,7 +41053,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
|
40395
41053
|
} catch {
|
|
40396
41054
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
40397
41055
|
}
|
|
40398
|
-
return `dir:${
|
|
41056
|
+
return `dir:${createHash4("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
40399
41057
|
}
|
|
40400
41058
|
function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
|
|
40401
41059
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
@@ -40580,7 +41238,7 @@ var init_v22_backfill_commands = __esm(async () => {
|
|
|
40580
41238
|
});
|
|
40581
41239
|
|
|
40582
41240
|
// ../pi-plugin/src/config/index.ts
|
|
40583
|
-
import { existsSync as
|
|
41241
|
+
import { existsSync as existsSync23, readFileSync as readFileSync14 } from "node:fs";
|
|
40584
41242
|
function getProjectConfigPaths(cwd) {
|
|
40585
41243
|
const basePath = cortexKitProjectConfigBasePath(cwd);
|
|
40586
41244
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
@@ -40590,10 +41248,10 @@ function getUserConfigPaths() {
|
|
|
40590
41248
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
40591
41249
|
}
|
|
40592
41250
|
function resolveFirstExisting(paths) {
|
|
40593
|
-
return paths.find((path6) =>
|
|
41251
|
+
return paths.find((path6) => existsSync23(path6));
|
|
40594
41252
|
}
|
|
40595
41253
|
function resolvePiLegacyFallback(sources) {
|
|
40596
|
-
return sources.find((source) =>
|
|
41254
|
+
return sources.find((source) => existsSync23(source.path)) ?? null;
|
|
40597
41255
|
}
|
|
40598
41256
|
function loadConfigFile(path6, scope) {
|
|
40599
41257
|
try {
|
|
@@ -40750,7 +41408,7 @@ function loadPiConfig(opts = {}) {
|
|
|
40750
41408
|
if (loaded)
|
|
40751
41409
|
loadedFiles.push(loaded);
|
|
40752
41410
|
}
|
|
40753
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
41411
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync23(source.path));
|
|
40754
41412
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
40755
41413
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
40756
41414
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -40759,7 +41417,7 @@ function loadPiConfig(opts = {}) {
|
|
|
40759
41417
|
if (loaded)
|
|
40760
41418
|
loadedFiles.push(loaded);
|
|
40761
41419
|
}
|
|
40762
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
41420
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync23(source.path));
|
|
40763
41421
|
if (userLegacyFallback) {
|
|
40764
41422
|
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.`);
|
|
40765
41423
|
} else if (legacyUserUnmigrated) {
|
|
@@ -40803,6 +41461,7 @@ function loadPiConfig(opts = {}) {
|
|
|
40803
41461
|
}
|
|
40804
41462
|
const parsed = parsePiConfig(rawConfig);
|
|
40805
41463
|
setOutputReserveConfig(parsed.config.output_reserve);
|
|
41464
|
+
setWindowOverlayPath(parsed.config.models?.window_overlay_path);
|
|
40806
41465
|
warnings.push(...parsed.warnings.map((warning) => `[merged config] ${warning}`));
|
|
40807
41466
|
return {
|
|
40808
41467
|
config: parsed.config,
|
|
@@ -40821,6 +41480,7 @@ var init_config2 = __esm(() => {
|
|
|
40821
41480
|
init_variable();
|
|
40822
41481
|
init_jsonc_parser();
|
|
40823
41482
|
init_models_dev_cache();
|
|
41483
|
+
init_window_geometry();
|
|
40824
41484
|
import_comment_json7 = __toESM(require_src3(), 1);
|
|
40825
41485
|
});
|
|
40826
41486
|
|
|
@@ -41040,9 +41700,9 @@ var init_redaction2 = __esm(() => {
|
|
|
41040
41700
|
|
|
41041
41701
|
// src/commands/doctor-omp.ts
|
|
41042
41702
|
import { execFileSync as execFileSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
41043
|
-
import { existsSync as
|
|
41703
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync15 } from "node:fs";
|
|
41044
41704
|
import { createRequire as createRequire2 } from "node:module";
|
|
41045
|
-
import { dirname as
|
|
41705
|
+
import { dirname as dirname13, join as join20, resolve as resolve6 } from "node:path";
|
|
41046
41706
|
function parseSemver(value) {
|
|
41047
41707
|
const match = value?.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
41048
41708
|
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
@@ -41084,7 +41744,7 @@ function selfVersion() {
|
|
|
41084
41744
|
return "unknown";
|
|
41085
41745
|
}
|
|
41086
41746
|
function readConfig2(path6) {
|
|
41087
|
-
if (!
|
|
41747
|
+
if (!existsSync24(path6))
|
|
41088
41748
|
return {};
|
|
41089
41749
|
try {
|
|
41090
41750
|
const parsed = import_comment_json8.parse(readFileSync15(path6, "utf-8"));
|
|
@@ -41168,8 +41828,8 @@ async function runHealthChecks(options) {
|
|
|
41168
41828
|
if (!reportedAgentDir.ok) {
|
|
41169
41829
|
add(results, "warn", "Could not verify OMP active agent directory");
|
|
41170
41830
|
} else {
|
|
41171
|
-
const reportedPath =
|
|
41172
|
-
const expectedPath =
|
|
41831
|
+
const reportedPath = resolve6(reportedAgentDir.stdout);
|
|
41832
|
+
const expectedPath = resolve6(getOmpAgentDir());
|
|
41173
41833
|
if (reportedPath === expectedPath) {
|
|
41174
41834
|
add(results, "pass", `OMP agent directory resolved to ${getOmpAgentDir()}`);
|
|
41175
41835
|
} else {
|
|
@@ -41178,7 +41838,7 @@ async function runHealthChecks(options) {
|
|
|
41178
41838
|
}
|
|
41179
41839
|
}
|
|
41180
41840
|
const userConfigPath = getOmpUserConfigPath();
|
|
41181
|
-
if (!
|
|
41841
|
+
if (!existsSync24(userConfigPath)) {
|
|
41182
41842
|
add(results, "warn", `No Magic Context user config at ${userConfigPath}`);
|
|
41183
41843
|
repairPlan.writeUserConfig = true;
|
|
41184
41844
|
} else {
|
|
@@ -41195,7 +41855,7 @@ async function runHealthChecks(options) {
|
|
|
41195
41855
|
for (const warning of loaded.warnings.slice(0, 5))
|
|
41196
41856
|
add(results, "warn", warning);
|
|
41197
41857
|
const dbPath = join20(getMagicContextStorageDir(), "context.db");
|
|
41198
|
-
if (!
|
|
41858
|
+
if (!existsSync24(dbPath))
|
|
41199
41859
|
add(results, "info", `Shared context DB will be created at ${dbPath}`);
|
|
41200
41860
|
else {
|
|
41201
41861
|
let db = null;
|
|
@@ -41224,7 +41884,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41224
41884
|
add(results, "info", `OMP non-global config: ${source}`);
|
|
41225
41885
|
}
|
|
41226
41886
|
const logPath = getMagicContextLogPath2("pi");
|
|
41227
|
-
add(results, "info", `Pi-compatible runtime log: ${logPath}${
|
|
41887
|
+
add(results, "info", `Pi-compatible runtime log: ${logPath}${existsSync24(logPath) ? "" : " (not created yet)"}`);
|
|
41228
41888
|
if (!options.quiet)
|
|
41229
41889
|
for (const result of results)
|
|
41230
41890
|
printResult(options.prompts, result);
|
|
@@ -41237,7 +41897,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41237
41897
|
};
|
|
41238
41898
|
}
|
|
41239
41899
|
function writeDefaultConfig(path6) {
|
|
41240
|
-
|
|
41900
|
+
mkdirSync9(dirname13(path6), { recursive: true });
|
|
41241
41901
|
const config2 = {
|
|
41242
41902
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
41243
41903
|
...MagicContextConfigSchema.parse({})
|
|
@@ -41247,7 +41907,7 @@ function writeDefaultConfig(path6) {
|
|
|
41247
41907
|
}
|
|
41248
41908
|
async function repair(plan, deps, prompts, cwd) {
|
|
41249
41909
|
let fixed = 0;
|
|
41250
|
-
if (plan.writeUserConfig && !
|
|
41910
|
+
if (plan.writeUserConfig && !existsSync24(getOmpUserConfigPath())) {
|
|
41251
41911
|
writeDefaultConfig(getOmpUserConfigPath());
|
|
41252
41912
|
prompts.log.success(`Wrote default Magic Context config to ${getOmpUserConfigPath()}`);
|
|
41253
41913
|
fixed += 1;
|
|
@@ -41341,8 +42001,8 @@ async function runIssueFlow(options) {
|
|
|
41341
42001
|
}
|
|
41342
42002
|
async function runDoctor(options = {}) {
|
|
41343
42003
|
const deps = {
|
|
41344
|
-
...
|
|
41345
|
-
prompts: options.prompts ??
|
|
42004
|
+
...DEFAULT_DEPS4,
|
|
42005
|
+
prompts: options.prompts ?? DEFAULT_DEPS4.prompts,
|
|
41346
42006
|
...options.deps
|
|
41347
42007
|
};
|
|
41348
42008
|
const prompts = options.prompts ?? deps.prompts;
|
|
@@ -41368,7 +42028,7 @@ async function runDoctor(options = {}) {
|
|
|
41368
42028
|
prompts.log.message(`Summary: PASS ${second.pass} / WARN ${second.warn} / FAIL ${second.fail}`);
|
|
41369
42029
|
return second.fail === 0 ? 0 : 1;
|
|
41370
42030
|
}
|
|
41371
|
-
var import_comment_json8, MIN_OMP_VERSION = "17.1.7",
|
|
42031
|
+
var import_comment_json8, MIN_OMP_VERSION = "17.1.7", DEFAULT_DEPS4;
|
|
41372
42032
|
var init_doctor_omp = __esm(async () => {
|
|
41373
42033
|
init_magic_context();
|
|
41374
42034
|
init_data_path();
|
|
@@ -41382,7 +42042,7 @@ var init_doctor_omp = __esm(async () => {
|
|
|
41382
42042
|
init_redaction2();
|
|
41383
42043
|
await init_database_access();
|
|
41384
42044
|
import_comment_json8 = __toESM(require_src3(), 1);
|
|
41385
|
-
|
|
42045
|
+
DEFAULT_DEPS4 = {
|
|
41386
42046
|
prompts: promptIO,
|
|
41387
42047
|
detectOmpBinary,
|
|
41388
42048
|
getOmpVersion,
|
|
@@ -41510,14 +42170,14 @@ var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
|
|
|
41510
42170
|
// ../plugin/src/shared/tui-config.ts
|
|
41511
42171
|
import {
|
|
41512
42172
|
chmodSync as chmodSync4,
|
|
41513
|
-
existsSync as
|
|
41514
|
-
mkdirSync as
|
|
42173
|
+
existsSync as existsSync25,
|
|
42174
|
+
mkdirSync as mkdirSync10,
|
|
41515
42175
|
readFileSync as readFileSync16,
|
|
41516
|
-
renameSync as
|
|
42176
|
+
renameSync as renameSync5,
|
|
41517
42177
|
statSync as statSync9,
|
|
41518
42178
|
writeFileSync as writeFileSync6
|
|
41519
42179
|
} from "node:fs";
|
|
41520
|
-
import { dirname as
|
|
42180
|
+
import { dirname as dirname14, join as join21 } from "node:path";
|
|
41521
42181
|
function pluginEntryId(entry) {
|
|
41522
42182
|
if (typeof entry === "string")
|
|
41523
42183
|
return entry;
|
|
@@ -41554,15 +42214,15 @@ function writeTuiConfigAtomic(configPath, config2) {
|
|
|
41554
42214
|
chmodSync4(tmpPath, statSync9(configPath).mode & 511);
|
|
41555
42215
|
}
|
|
41556
42216
|
} catch {}
|
|
41557
|
-
|
|
42217
|
+
renameSync5(tmpPath, configPath);
|
|
41558
42218
|
}
|
|
41559
42219
|
function resolveTuiConfigPath(configDirOverride) {
|
|
41560
42220
|
const configDir = configDirOverride ?? getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
41561
42221
|
const jsoncPath = join21(configDir, "tui.jsonc");
|
|
41562
42222
|
const jsonPath = join21(configDir, "tui.json");
|
|
41563
|
-
if (
|
|
42223
|
+
if (existsSync25(jsoncPath))
|
|
41564
42224
|
return jsoncPath;
|
|
41565
|
-
if (
|
|
42225
|
+
if (existsSync25(jsonPath))
|
|
41566
42226
|
return jsonPath;
|
|
41567
42227
|
return jsoncPath;
|
|
41568
42228
|
}
|
|
@@ -41570,7 +42230,7 @@ function ensureTuiPluginEntry(options = {}) {
|
|
|
41570
42230
|
try {
|
|
41571
42231
|
const configPath = resolveTuiConfigPath(options.configDir);
|
|
41572
42232
|
let config2 = {};
|
|
41573
|
-
if (
|
|
42233
|
+
if (existsSync25(configPath)) {
|
|
41574
42234
|
const raw = readFileSync16(configPath, "utf-8");
|
|
41575
42235
|
config2 = import_comment_json9.parse(raw) ?? {};
|
|
41576
42236
|
}
|
|
@@ -41605,7 +42265,7 @@ function ensureTuiPluginEntry(options = {}) {
|
|
|
41605
42265
|
}
|
|
41606
42266
|
}
|
|
41607
42267
|
config2.plugin = plugins;
|
|
41608
|
-
|
|
42268
|
+
mkdirSync10(dirname14(configPath), { recursive: true });
|
|
41609
42269
|
writeTuiConfigAtomic(configPath, config2);
|
|
41610
42270
|
log3(`[magic-context] updated TUI plugin entry in ${configPath}`);
|
|
41611
42271
|
return true;
|
|
@@ -41623,7 +42283,7 @@ var init_tui_config = __esm(() => {
|
|
|
41623
42283
|
});
|
|
41624
42284
|
|
|
41625
42285
|
// src/lib/diagnostics-opencode.ts
|
|
41626
|
-
import { existsSync as
|
|
42286
|
+
import { existsSync as existsSync26, readdirSync as readdirSync3, readFileSync as readFileSync17, statSync as statSync10 } from "node:fs";
|
|
41627
42287
|
import { createRequire as createRequire3 } from "node:module";
|
|
41628
42288
|
import { homedir as homedir15 } from "node:os";
|
|
41629
42289
|
import { join as join22 } from "node:path";
|
|
@@ -41644,7 +42304,7 @@ function getPluginCacheInfo() {
|
|
|
41644
42304
|
let cached2;
|
|
41645
42305
|
for (const installedPkgPath of getOpenCodePluginPackageJsonPaths()) {
|
|
41646
42306
|
try {
|
|
41647
|
-
if (
|
|
42307
|
+
if (existsSync26(installedPkgPath)) {
|
|
41648
42308
|
const pkg = JSON.parse(readFileSync17(installedPkgPath, "utf-8"));
|
|
41649
42309
|
cached2 = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
41650
42310
|
if (cached2)
|
|
@@ -41662,7 +42322,7 @@ function getStorageDir() {
|
|
|
41662
42322
|
}
|
|
41663
42323
|
function fileSize(path6) {
|
|
41664
42324
|
try {
|
|
41665
|
-
return
|
|
42325
|
+
return existsSync26(path6) ? statSync10(path6).size : 0;
|
|
41666
42326
|
} catch {
|
|
41667
42327
|
return 0;
|
|
41668
42328
|
}
|
|
@@ -41674,7 +42334,7 @@ function sanitizeValue(value) {
|
|
|
41674
42334
|
return sanitizeConfigValue(value);
|
|
41675
42335
|
}
|
|
41676
42336
|
function readConfig3(path6) {
|
|
41677
|
-
if (!
|
|
42337
|
+
if (!existsSync26(path6))
|
|
41678
42338
|
return { value: null };
|
|
41679
42339
|
try {
|
|
41680
42340
|
const raw = readFileSync17(path6, "utf-8");
|
|
@@ -41735,7 +42395,7 @@ function parseHistorianDumpMeta(path6) {
|
|
|
41735
42395
|
}
|
|
41736
42396
|
}
|
|
41737
42397
|
function listDumpsInDir(dir, limit) {
|
|
41738
|
-
if (!
|
|
42398
|
+
if (!existsSync26(dir))
|
|
41739
42399
|
return { count: 0, recent: [] };
|
|
41740
42400
|
try {
|
|
41741
42401
|
const entries = readdirSync3(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
@@ -41805,7 +42465,7 @@ function collectHistorianDumps(recentSessions) {
|
|
|
41805
42465
|
async function collectRecentSessions() {
|
|
41806
42466
|
const dataHome = process.env.XDG_DATA_HOME || join22(process.env.HOME || homedir15(), ".local", "share");
|
|
41807
42467
|
const opencodeDbPath = join22(dataHome, "opencode", "opencode.db");
|
|
41808
|
-
if (!
|
|
42468
|
+
if (!existsSync26(opencodeDbPath))
|
|
41809
42469
|
return [];
|
|
41810
42470
|
if (typeof globalThis.Bun === "undefined") {
|
|
41811
42471
|
return [];
|
|
@@ -41840,7 +42500,7 @@ async function collectRecentSessions() {
|
|
|
41840
42500
|
}
|
|
41841
42501
|
async function collectHistorianFailures(storageDirPath) {
|
|
41842
42502
|
const contextDbPath = join22(storageDirPath, "context.db");
|
|
41843
|
-
if (!
|
|
42503
|
+
if (!existsSync26(contextDbPath))
|
|
41844
42504
|
return [];
|
|
41845
42505
|
if (typeof globalThis.Bun === "undefined") {
|
|
41846
42506
|
return [];
|
|
@@ -41874,7 +42534,7 @@ async function collectHistorianFailures(storageDirPath) {
|
|
|
41874
42534
|
}
|
|
41875
42535
|
async function collectHistorianRuns(storageDirPath) {
|
|
41876
42536
|
const contextDbPath = join22(storageDirPath, "context.db");
|
|
41877
|
-
if (!
|
|
42537
|
+
if (!existsSync26(contextDbPath))
|
|
41878
42538
|
return [];
|
|
41879
42539
|
if (typeof globalThis.Bun === "undefined")
|
|
41880
42540
|
return [];
|
|
@@ -41945,7 +42605,7 @@ async function collectDiagnostics() {
|
|
|
41945
42605
|
const storageDirPath = getStorageDir();
|
|
41946
42606
|
const contextDbPath = join22(storageDirPath, "context.db");
|
|
41947
42607
|
const logPath = getMagicContextLogPath2("opencode");
|
|
41948
|
-
const logFileSize =
|
|
42608
|
+
const logFileSize = existsSync26(logPath) ? statSync10(logPath).size : 0;
|
|
41949
42609
|
let compactionEnabled = false;
|
|
41950
42610
|
try {
|
|
41951
42611
|
compactionEnabled = isCompactionEnabled(loadPluginConfig(process.cwd()));
|
|
@@ -41973,14 +42633,14 @@ async function collectDiagnostics() {
|
|
|
41973
42633
|
opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
|
|
41974
42634
|
tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
|
|
41975
42635
|
magicContextConfig: {
|
|
41976
|
-
exists:
|
|
42636
|
+
exists: existsSync26(configPaths.magicContextConfig),
|
|
41977
42637
|
...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
|
|
41978
42638
|
flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
|
|
41979
42639
|
},
|
|
41980
42640
|
pluginCache: getPluginCacheInfo(),
|
|
41981
42641
|
storageDir: {
|
|
41982
42642
|
path: storageDirPath,
|
|
41983
|
-
exists:
|
|
42643
|
+
exists: existsSync26(storageDirPath),
|
|
41984
42644
|
contextDbSizeBytes: fileSize(contextDbPath)
|
|
41985
42645
|
},
|
|
41986
42646
|
conflicts: {
|
|
@@ -41991,7 +42651,7 @@ async function collectDiagnostics() {
|
|
|
41991
42651
|
},
|
|
41992
42652
|
logFile: {
|
|
41993
42653
|
path: logPath,
|
|
41994
|
-
exists:
|
|
42654
|
+
exists: existsSync26(logPath),
|
|
41995
42655
|
sizeKb: Math.round(logFileSize / 1024)
|
|
41996
42656
|
},
|
|
41997
42657
|
recentSessions,
|
|
@@ -42144,9 +42804,9 @@ var init_diagnostics_opencode = __esm(() => {
|
|
|
42144
42804
|
|
|
42145
42805
|
// src/lib/embedding-runtime.ts
|
|
42146
42806
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
42147
|
-
import { existsSync as
|
|
42807
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
42148
42808
|
import { createRequire as createRequire4 } from "node:module";
|
|
42149
|
-
import { dirname as
|
|
42809
|
+
import { dirname as dirname15, join as join23, sep } from "node:path";
|
|
42150
42810
|
function describeError(error51) {
|
|
42151
42811
|
const message = error51 instanceof Error ? error51.message : String(error51 ?? "unknown error");
|
|
42152
42812
|
const code = error51?.code;
|
|
@@ -42259,7 +42919,7 @@ function expectedBinaryRelPath(platform, arch) {
|
|
|
42259
42919
|
}
|
|
42260
42920
|
function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch) {
|
|
42261
42921
|
const packageDir = join23(installRoot, "node_modules", "onnxruntime-node");
|
|
42262
|
-
if (!
|
|
42922
|
+
if (!existsSync27(join23(packageDir, "package.json"))) {
|
|
42263
42923
|
return { state: "package-missing", packageDir };
|
|
42264
42924
|
}
|
|
42265
42925
|
const rel = expectedBinaryRelPath(platform, arch);
|
|
@@ -42267,13 +42927,13 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
42267
42927
|
return probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath: packageDir };
|
|
42268
42928
|
}
|
|
42269
42929
|
const binaryPath = join23(packageDir, rel);
|
|
42270
|
-
if (!
|
|
42930
|
+
if (!existsSync27(binaryPath)) {
|
|
42271
42931
|
return { state: "binary-missing", packageDir, expectedBinary: binaryPath };
|
|
42272
42932
|
}
|
|
42273
42933
|
return probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath };
|
|
42274
42934
|
}
|
|
42275
42935
|
function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch) {
|
|
42276
|
-
const existing = installRoots.filter((root) =>
|
|
42936
|
+
const existing = installRoots.filter((root) => existsSync27(root));
|
|
42277
42937
|
if (existing.length === 0) {
|
|
42278
42938
|
return {
|
|
42279
42939
|
state: "unknown",
|
|
@@ -42293,10 +42953,10 @@ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, a
|
|
|
42293
42953
|
function packageDirFromResolved(resolvedPath, packageName) {
|
|
42294
42954
|
const marker = `node_modules${sep}${packageName.split("/").join(sep)}`;
|
|
42295
42955
|
const idx = resolvedPath.indexOf(marker);
|
|
42296
|
-
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) :
|
|
42956
|
+
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname15(resolvedPath);
|
|
42297
42957
|
}
|
|
42298
42958
|
function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch) {
|
|
42299
|
-
if (!
|
|
42959
|
+
if (!existsSync27(join23(pluginDir, "package.json"))) {
|
|
42300
42960
|
return { state: "unknown", reason: "plugin package dir not found" };
|
|
42301
42961
|
}
|
|
42302
42962
|
let onnxDir = null;
|
|
@@ -42332,7 +42992,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
42332
42992
|
return probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
|
|
42333
42993
|
}
|
|
42334
42994
|
const binaryPath = join23(onnxDir, rel);
|
|
42335
|
-
if (!
|
|
42995
|
+
if (!existsSync27(binaryPath)) {
|
|
42336
42996
|
return { state: "binary-missing", packageDir: onnxDir, expectedBinary: binaryPath };
|
|
42337
42997
|
}
|
|
42338
42998
|
return probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath };
|
|
@@ -42818,25 +43478,391 @@ function migrateExperimentalPinKeyFilesForDoctor(mcConfig) {
|
|
|
42818
43478
|
return true;
|
|
42819
43479
|
}
|
|
42820
43480
|
|
|
43481
|
+
// ../plugin/src/hooks/auto-update-checker/constants.ts
|
|
43482
|
+
import { homedir as homedir16, platform } from "node:os";
|
|
43483
|
+
import { join as join25 } from "node:path";
|
|
43484
|
+
function getOpenCodeCacheRoot() {
|
|
43485
|
+
if (platform() === "win32") {
|
|
43486
|
+
return join25(process.env.LOCALAPPDATA ?? homedir16(), "opencode");
|
|
43487
|
+
}
|
|
43488
|
+
return join25(homedir16(), ".cache", "opencode");
|
|
43489
|
+
}
|
|
43490
|
+
function getOpenCodeConfigRoot() {
|
|
43491
|
+
if (platform() === "win32") {
|
|
43492
|
+
return join25(process.env.APPDATA ?? join25(homedir16(), "AppData", "Roaming"), "opencode");
|
|
43493
|
+
}
|
|
43494
|
+
return join25(process.env.XDG_CONFIG_HOME ?? join25(homedir16(), ".config"), "opencode");
|
|
43495
|
+
}
|
|
43496
|
+
var PACKAGE_NAME = "@cortexkit/opencode-magic-context", CACHE_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC;
|
|
43497
|
+
var init_constants2 = __esm(() => {
|
|
43498
|
+
CACHE_DIR = join25(getOpenCodeCacheRoot(), "packages");
|
|
43499
|
+
USER_OPENCODE_CONFIG = join25(getOpenCodeConfigRoot(), "opencode.json");
|
|
43500
|
+
USER_OPENCODE_CONFIG_JSONC = join25(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
43501
|
+
});
|
|
43502
|
+
// ../plugin/src/hooks/auto-update-checker/types.ts
|
|
43503
|
+
var NpmPackageEnvelopeSchema, OpencodePluginTupleSchema, OpencodeConfigSchema, PackageJsonSchema;
|
|
43504
|
+
var init_types = __esm(() => {
|
|
43505
|
+
init_zod();
|
|
43506
|
+
NpmPackageEnvelopeSchema = exports_external.object({
|
|
43507
|
+
"dist-tags": exports_external.record(exports_external.string(), exports_external.string()).optional().default({})
|
|
43508
|
+
});
|
|
43509
|
+
OpencodePluginTupleSchema = exports_external.tuple([exports_external.string(), exports_external.record(exports_external.string(), exports_external.unknown())]);
|
|
43510
|
+
OpencodeConfigSchema = exports_external.object({
|
|
43511
|
+
plugin: exports_external.array(exports_external.union([exports_external.string(), OpencodePluginTupleSchema])).optional()
|
|
43512
|
+
});
|
|
43513
|
+
PackageJsonSchema = exports_external.object({
|
|
43514
|
+
name: exports_external.string().optional(),
|
|
43515
|
+
version: exports_external.string().optional(),
|
|
43516
|
+
dependencies: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
43517
|
+
}).passthrough();
|
|
43518
|
+
});
|
|
43519
|
+
|
|
43520
|
+
// ../plugin/src/hooks/auto-update-checker/checker.ts
|
|
43521
|
+
import {
|
|
43522
|
+
accessSync as accessSync2,
|
|
43523
|
+
existsSync as existsSync28,
|
|
43524
|
+
constants as fsConstants,
|
|
43525
|
+
readFileSync as readFileSync19,
|
|
43526
|
+
renameSync as renameSync6,
|
|
43527
|
+
statSync as statSync11,
|
|
43528
|
+
writeFileSync as writeFileSync8
|
|
43529
|
+
} from "node:fs";
|
|
43530
|
+
import { dirname as dirname16, isAbsolute as isAbsolute4, join as join26, resolve as resolve7 } from "node:path";
|
|
43531
|
+
function warn(message) {
|
|
43532
|
+
log3(`WARN: ${message}`);
|
|
43533
|
+
}
|
|
43534
|
+
function isString(value) {
|
|
43535
|
+
return typeof value === "string";
|
|
43536
|
+
}
|
|
43537
|
+
function pluginSpecifier(entry) {
|
|
43538
|
+
return typeof entry === "string" ? entry : entry[0];
|
|
43539
|
+
}
|
|
43540
|
+
function getPluginEntries(config2) {
|
|
43541
|
+
const parsed = OpencodeConfigSchema.safeParse(config2);
|
|
43542
|
+
if (!parsed.success)
|
|
43543
|
+
return [];
|
|
43544
|
+
return (parsed.data.plugin ?? []).map(pluginSpecifier).filter(isString);
|
|
43545
|
+
}
|
|
43546
|
+
function parseJsonConfig(content) {
|
|
43547
|
+
try {
|
|
43548
|
+
return import_comment_json11.parse(content);
|
|
43549
|
+
} catch (err) {
|
|
43550
|
+
warn(`[auto-update-checker] Failed to parse OpenCode config: ${String(err)}`);
|
|
43551
|
+
return null;
|
|
43552
|
+
}
|
|
43553
|
+
}
|
|
43554
|
+
function getSurfaceConfigPaths(directory, surface) {
|
|
43555
|
+
const name = surface === "server" ? "opencode" : "tui";
|
|
43556
|
+
const globalDir = dirname16(USER_OPENCODE_CONFIG);
|
|
43557
|
+
const dirs = [
|
|
43558
|
+
globalDir,
|
|
43559
|
+
directory,
|
|
43560
|
+
join26(directory, ".opencode"),
|
|
43561
|
+
process.env.OPENCODE_CONFIG_DIR
|
|
43562
|
+
].filter((value) => Boolean(value));
|
|
43563
|
+
const paths = [];
|
|
43564
|
+
for (const dir of dirs) {
|
|
43565
|
+
for (const extension of ["json", "jsonc"]) {
|
|
43566
|
+
const path6 = join26(dir, `${name}.${extension}`);
|
|
43567
|
+
if (!paths.includes(path6))
|
|
43568
|
+
paths.push(path6);
|
|
43569
|
+
}
|
|
43570
|
+
}
|
|
43571
|
+
return paths;
|
|
43572
|
+
}
|
|
43573
|
+
function getWinningConfig(directory, surface) {
|
|
43574
|
+
let winner = null;
|
|
43575
|
+
for (const path6 of getSurfaceConfigPaths(directory, surface)) {
|
|
43576
|
+
try {
|
|
43577
|
+
if (!existsSync28(path6))
|
|
43578
|
+
continue;
|
|
43579
|
+
const parsed = parseJsonConfig(readFileSync19(path6, "utf-8"));
|
|
43580
|
+
const entries = getPluginEntries(parsed);
|
|
43581
|
+
if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
|
|
43582
|
+
if (winner) {
|
|
43583
|
+
log3(`[auto-update-checker] ${surface} config ${winner.path} is shadowed by ${path6}`);
|
|
43584
|
+
}
|
|
43585
|
+
winner = { path: path6, entries };
|
|
43586
|
+
}
|
|
43587
|
+
} catch {}
|
|
43588
|
+
}
|
|
43589
|
+
return winner;
|
|
43590
|
+
}
|
|
43591
|
+
function findPluginEntry(directory, surface = "server") {
|
|
43592
|
+
const winner = getWinningConfig(directory, surface);
|
|
43593
|
+
if (!winner)
|
|
43594
|
+
return null;
|
|
43595
|
+
const entry = winner.entries.find((value) => value === PACKAGE_NAME || value.startsWith(`${PACKAGE_NAME}@`));
|
|
43596
|
+
if (!entry)
|
|
43597
|
+
return null;
|
|
43598
|
+
const pinnedVersion = entry.startsWith(`${PACKAGE_NAME}@`) ? entry.slice(PACKAGE_NAME.length + 1) : null;
|
|
43599
|
+
return {
|
|
43600
|
+
entry,
|
|
43601
|
+
isPinned: pinnedVersion !== null && pinnedVersion !== "latest",
|
|
43602
|
+
pinnedVersion: pinnedVersion && pinnedVersion !== "latest" ? pinnedVersion : null,
|
|
43603
|
+
configPath: winner.path
|
|
43604
|
+
};
|
|
43605
|
+
}
|
|
43606
|
+
var import_comment_json11;
|
|
43607
|
+
var init_checker = __esm(() => {
|
|
43608
|
+
init_logger();
|
|
43609
|
+
init_constants2();
|
|
43610
|
+
init_types();
|
|
43611
|
+
import_comment_json11 = __toESM(require_src3(), 1);
|
|
43612
|
+
});
|
|
43613
|
+
|
|
43614
|
+
// src/lib/opencode-plugin-schema-fence.ts
|
|
43615
|
+
import { existsSync as existsSync29, readdirSync as readdirSync4, readFileSync as readFileSync20 } from "node:fs";
|
|
43616
|
+
import { join as join27 } from "node:path";
|
|
43617
|
+
import { gunzipSync } from "node:zlib";
|
|
43618
|
+
function readPackageVersion(packageJsonPath) {
|
|
43619
|
+
try {
|
|
43620
|
+
if (!existsSync29(packageJsonPath))
|
|
43621
|
+
return null;
|
|
43622
|
+
const packageJson = JSON.parse(readFileSync20(packageJsonPath, "utf-8"));
|
|
43623
|
+
if (packageJson.name !== OPENCODE_PLUGIN_NAME || typeof packageJson.version !== "string") {
|
|
43624
|
+
return null;
|
|
43625
|
+
}
|
|
43626
|
+
return packageJson.version;
|
|
43627
|
+
} catch {
|
|
43628
|
+
return null;
|
|
43629
|
+
}
|
|
43630
|
+
}
|
|
43631
|
+
function readFenceValue(text3) {
|
|
43632
|
+
const values = new Set;
|
|
43633
|
+
for (const match of text3.matchAll(FENCE_PATTERN)) {
|
|
43634
|
+
const version2 = Number.parseInt(match[1] ?? "", 10);
|
|
43635
|
+
if (Number.isFinite(version2))
|
|
43636
|
+
values.add(version2);
|
|
43637
|
+
}
|
|
43638
|
+
return values.size === 1 ? [...values][0] ?? null : null;
|
|
43639
|
+
}
|
|
43640
|
+
function readFenceFromDist(packageDirectory) {
|
|
43641
|
+
const distDirectory = join27(packageDirectory, "dist");
|
|
43642
|
+
if (!existsSync29(distDirectory))
|
|
43643
|
+
return null;
|
|
43644
|
+
const pending = [distDirectory];
|
|
43645
|
+
const fenceValues = new Set;
|
|
43646
|
+
while (pending.length > 0) {
|
|
43647
|
+
const directory = pending.pop();
|
|
43648
|
+
if (!directory)
|
|
43649
|
+
continue;
|
|
43650
|
+
try {
|
|
43651
|
+
for (const entry of readdirSync4(directory, { withFileTypes: true })) {
|
|
43652
|
+
const path6 = join27(directory, entry.name);
|
|
43653
|
+
if (entry.isDirectory()) {
|
|
43654
|
+
pending.push(path6);
|
|
43655
|
+
continue;
|
|
43656
|
+
}
|
|
43657
|
+
if (!entry.isFile() || !/\.(?:[cm]?js|ts)$/.test(entry.name))
|
|
43658
|
+
continue;
|
|
43659
|
+
const fence = readFenceValue(readFileSync20(path6, "utf-8"));
|
|
43660
|
+
if (fence !== null)
|
|
43661
|
+
fenceValues.add(fence);
|
|
43662
|
+
}
|
|
43663
|
+
} catch {
|
|
43664
|
+
return null;
|
|
43665
|
+
}
|
|
43666
|
+
}
|
|
43667
|
+
return fenceValues.size === 1 ? [...fenceValues][0] ?? null : null;
|
|
43668
|
+
}
|
|
43669
|
+
function findInstalledPluginPackage(cacheDirectory, specifier, requestedVersion) {
|
|
43670
|
+
const directCacheRoot = join27(cacheDirectory, specifier);
|
|
43671
|
+
const candidates = [directCacheRoot];
|
|
43672
|
+
try {
|
|
43673
|
+
for (const entry of readdirSync4(cacheDirectory, { withFileTypes: true })) {
|
|
43674
|
+
if (!entry.isDirectory())
|
|
43675
|
+
continue;
|
|
43676
|
+
const candidate = join27(cacheDirectory, entry.name);
|
|
43677
|
+
if (!candidates.includes(candidate))
|
|
43678
|
+
candidates.push(candidate);
|
|
43679
|
+
}
|
|
43680
|
+
} catch {}
|
|
43681
|
+
for (const cacheRoot of candidates) {
|
|
43682
|
+
const directory = join27(cacheRoot, "node_modules", ...PACKAGE_PATH_SEGMENTS);
|
|
43683
|
+
const version2 = readPackageVersion(join27(directory, "package.json"));
|
|
43684
|
+
if (!version2)
|
|
43685
|
+
continue;
|
|
43686
|
+
if (cacheRoot === directCacheRoot || EXACT_VERSION_PATTERN.test(requestedVersion) && version2 === requestedVersion) {
|
|
43687
|
+
return { directory, version: version2 };
|
|
43688
|
+
}
|
|
43689
|
+
}
|
|
43690
|
+
return null;
|
|
43691
|
+
}
|
|
43692
|
+
function readTarText(bytes, offset, length) {
|
|
43693
|
+
const end = Math.min(offset + length, bytes.length);
|
|
43694
|
+
let nul = offset;
|
|
43695
|
+
while (nul < end && bytes[nul] !== 0)
|
|
43696
|
+
nul++;
|
|
43697
|
+
return new TextDecoder().decode(bytes.subarray(offset, nul));
|
|
43698
|
+
}
|
|
43699
|
+
function readTarOctal(bytes, offset, length) {
|
|
43700
|
+
const value = readTarText(bytes, offset, length).trim();
|
|
43701
|
+
if (!/^[0-7]+$/.test(value))
|
|
43702
|
+
return null;
|
|
43703
|
+
const parsed = Number.parseInt(value, 8);
|
|
43704
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
43705
|
+
}
|
|
43706
|
+
function readFenceFromNpmTarball(tarball) {
|
|
43707
|
+
let archive;
|
|
43708
|
+
try {
|
|
43709
|
+
archive = gunzipSync(tarball);
|
|
43710
|
+
} catch {
|
|
43711
|
+
return null;
|
|
43712
|
+
}
|
|
43713
|
+
const fenceValues = new Set;
|
|
43714
|
+
for (let offset = 0;offset + 512 <= archive.length; ) {
|
|
43715
|
+
const name = readTarText(archive, offset, 100);
|
|
43716
|
+
if (!name)
|
|
43717
|
+
break;
|
|
43718
|
+
const prefix = readTarText(archive, offset + 345, 155);
|
|
43719
|
+
const path6 = prefix ? `${prefix}/${name}` : name;
|
|
43720
|
+
const size = readTarOctal(archive, offset + 124, 12);
|
|
43721
|
+
if (size === null)
|
|
43722
|
+
return null;
|
|
43723
|
+
const contentStart = offset + 512;
|
|
43724
|
+
const contentEnd = contentStart + size;
|
|
43725
|
+
if (contentEnd > archive.length)
|
|
43726
|
+
return null;
|
|
43727
|
+
if (/^package\/dist\/.+\.(?:[cm]?js|ts)$/.test(path6)) {
|
|
43728
|
+
const fence = readFenceValue(new TextDecoder().decode(archive.subarray(contentStart, contentEnd)));
|
|
43729
|
+
if (fence !== null)
|
|
43730
|
+
fenceValues.add(fence);
|
|
43731
|
+
}
|
|
43732
|
+
offset = contentStart + Math.ceil(size / 512) * 512;
|
|
43733
|
+
}
|
|
43734
|
+
return fenceValues.size === 1 ? [...fenceValues][0] ?? null : null;
|
|
43735
|
+
}
|
|
43736
|
+
function npmPackageVersionUrl(version2) {
|
|
43737
|
+
const packagePath = encodeURIComponent(OPENCODE_PLUGIN_NAME).replace("%2F", "/");
|
|
43738
|
+
return `https://registry.npmjs.org/${packagePath}/${encodeURIComponent(version2)}`;
|
|
43739
|
+
}
|
|
43740
|
+
async function resolveFenceFromNpmTarball(requestedVersion, fetchImpl) {
|
|
43741
|
+
const controller = new AbortController;
|
|
43742
|
+
const timeout = setTimeout(() => controller.abort(), NPM_TIMEOUT_MS);
|
|
43743
|
+
try {
|
|
43744
|
+
const metadataResponse = await fetchImpl(npmPackageVersionUrl(requestedVersion), {
|
|
43745
|
+
signal: controller.signal,
|
|
43746
|
+
headers: { Accept: "application/json" }
|
|
43747
|
+
});
|
|
43748
|
+
if (!metadataResponse.ok)
|
|
43749
|
+
return null;
|
|
43750
|
+
const metadata = await metadataResponse.json();
|
|
43751
|
+
if (typeof metadata.version !== "string" || typeof metadata.dist?.tarball !== "string") {
|
|
43752
|
+
return null;
|
|
43753
|
+
}
|
|
43754
|
+
const tarballUrl = new URL(metadata.dist.tarball);
|
|
43755
|
+
if (tarballUrl.protocol !== "https:")
|
|
43756
|
+
return null;
|
|
43757
|
+
const tarballResponse = await fetchImpl(tarballUrl, { signal: controller.signal });
|
|
43758
|
+
if (!tarballResponse.ok)
|
|
43759
|
+
return null;
|
|
43760
|
+
const contentLength = Number(tarballResponse.headers.get("content-length"));
|
|
43761
|
+
if (Number.isFinite(contentLength) && contentLength > MAX_TARBALL_BYTES)
|
|
43762
|
+
return null;
|
|
43763
|
+
const tarball = new Uint8Array(await tarballResponse.arrayBuffer());
|
|
43764
|
+
if (tarball.byteLength > MAX_TARBALL_BYTES)
|
|
43765
|
+
return null;
|
|
43766
|
+
const supportedVersion = readFenceFromNpmTarball(tarball);
|
|
43767
|
+
return supportedVersion === null ? null : { version: metadata.version, supportedVersion, source: "npm-tarball" };
|
|
43768
|
+
} catch {
|
|
43769
|
+
return null;
|
|
43770
|
+
} finally {
|
|
43771
|
+
clearTimeout(timeout);
|
|
43772
|
+
}
|
|
43773
|
+
}
|
|
43774
|
+
async function resolvePluginFence(specifier, requestedVersion, deps) {
|
|
43775
|
+
const installed = findInstalledPluginPackage(deps.getOpenCodePluginCacheDir(), specifier, requestedVersion);
|
|
43776
|
+
if (installed) {
|
|
43777
|
+
const supportedVersion = readFenceFromDist(installed.directory);
|
|
43778
|
+
if (supportedVersion !== null) {
|
|
43779
|
+
return { version: installed.version, supportedVersion, source: "installed" };
|
|
43780
|
+
}
|
|
43781
|
+
}
|
|
43782
|
+
return resolveFenceFromNpmTarball(requestedVersion, deps.fetch);
|
|
43783
|
+
}
|
|
43784
|
+
async function inspectPinnedOpenCodePluginSchemaFences(options, deps = {}) {
|
|
43785
|
+
const findEntry = deps.findPluginEntry ?? findPluginEntry;
|
|
43786
|
+
const resolutionDeps = {
|
|
43787
|
+
fetch: deps.fetch ?? globalThis.fetch,
|
|
43788
|
+
getOpenCodePluginCacheDir: deps.getOpenCodePluginCacheDir ?? getOpenCodePluginCacheDir
|
|
43789
|
+
};
|
|
43790
|
+
const resolvedBySpecifier = new Map;
|
|
43791
|
+
const findings = [];
|
|
43792
|
+
for (const surface of ["server", "tui"]) {
|
|
43793
|
+
const entry = findEntry(options.directory, surface);
|
|
43794
|
+
if (!entry?.isPinned || !entry.pinnedVersion)
|
|
43795
|
+
continue;
|
|
43796
|
+
let resolved = resolvedBySpecifier.get(entry.entry);
|
|
43797
|
+
if (!resolved) {
|
|
43798
|
+
resolved = resolvePluginFence(entry.entry, entry.pinnedVersion, resolutionDeps);
|
|
43799
|
+
resolvedBySpecifier.set(entry.entry, resolved);
|
|
43800
|
+
}
|
|
43801
|
+
const fence = await resolved;
|
|
43802
|
+
const supportedVersion = fence?.supportedVersion ?? null;
|
|
43803
|
+
findings.push({
|
|
43804
|
+
status: supportedVersion === null ? "unknown" : supportedVersion < options.databaseVersion ? "fail" : "pass",
|
|
43805
|
+
surface,
|
|
43806
|
+
specifier: entry.entry,
|
|
43807
|
+
configPath: entry.configPath,
|
|
43808
|
+
pinnedVersion: fence?.version ?? entry.pinnedVersion,
|
|
43809
|
+
databaseVersion: options.databaseVersion,
|
|
43810
|
+
supportedVersion,
|
|
43811
|
+
source: fence?.source ?? null
|
|
43812
|
+
});
|
|
43813
|
+
}
|
|
43814
|
+
return findings;
|
|
43815
|
+
}
|
|
43816
|
+
var PACKAGE_PATH_SEGMENTS, MAX_TARBALL_BYTES, NPM_TIMEOUT_MS = 5000, FENCE_PATTERN, EXACT_VERSION_PATTERN;
|
|
43817
|
+
var init_opencode_plugin_schema_fence = __esm(() => {
|
|
43818
|
+
init_checker();
|
|
43819
|
+
init_opencode_plugin_cache();
|
|
43820
|
+
init_paths();
|
|
43821
|
+
PACKAGE_PATH_SEGMENTS = OPENCODE_PLUGIN_NAME.split("/");
|
|
43822
|
+
MAX_TARBALL_BYTES = 25 * 1024 * 1024;
|
|
43823
|
+
FENCE_PATTERN = /\bLATEST_SUPPORTED_VERSION\s*=\s*(\d+)\b/g;
|
|
43824
|
+
EXACT_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
43825
|
+
});
|
|
43826
|
+
|
|
42821
43827
|
// ../plugin/src/features/magic-context/fail-closed-block.ts
|
|
43828
|
+
function normalizeFailClosedProcessKind(process3) {
|
|
43829
|
+
switch (process3.kind) {
|
|
43830
|
+
case "OpenCode server":
|
|
43831
|
+
case "OpenCode instance (TUI/CLI)":
|
|
43832
|
+
case "Pi":
|
|
43833
|
+
case "process":
|
|
43834
|
+
return process3.kind;
|
|
43835
|
+
}
|
|
43836
|
+
switch (process3.harness?.trim().toLowerCase()) {
|
|
43837
|
+
case "opencode server":
|
|
43838
|
+
return "OpenCode server";
|
|
43839
|
+
case "opencode instance (tui/cli)":
|
|
43840
|
+
case "opencode instance":
|
|
43841
|
+
return "OpenCode instance (TUI/CLI)";
|
|
43842
|
+
case "pi":
|
|
43843
|
+
case "pi harness":
|
|
43844
|
+
case "omp":
|
|
43845
|
+
return "Pi";
|
|
43846
|
+
default:
|
|
43847
|
+
return "process";
|
|
43848
|
+
}
|
|
43849
|
+
}
|
|
42822
43850
|
function formatFailClosedBlockingProcesses(processes) {
|
|
42823
43851
|
const uniqueProcesses = new Map;
|
|
42824
43852
|
for (const process3 of processes) {
|
|
42825
|
-
if (!
|
|
43853
|
+
if (!Number.isInteger(process3.pid) || process3.pid <= 0)
|
|
42826
43854
|
continue;
|
|
42827
|
-
|
|
42828
|
-
|
|
42829
|
-
pid: process3.pid
|
|
42830
|
-
});
|
|
43855
|
+
const kind = normalizeFailClosedProcessKind(process3);
|
|
43856
|
+
uniqueProcesses.set(`${kind}\x00${process3.pid}`, { kind, pid: process3.pid });
|
|
42831
43857
|
}
|
|
42832
43858
|
const entries = [...uniqueProcesses.values()];
|
|
42833
43859
|
const visible = entries.slice(0, MAX_FORMATTED_BLOCKING_PROCESSES);
|
|
42834
|
-
const rendered = visible.map(({
|
|
43860
|
+
const rendered = visible.map(({ kind, pid }) => `${kind} (PID ${pid})`);
|
|
42835
43861
|
const omitted = entries.length - visible.length;
|
|
42836
43862
|
if (omitted > 0)
|
|
42837
43863
|
rendered.push(`${omitted} more blocking process(es)`);
|
|
42838
43864
|
if (rendered.length === 0)
|
|
42839
|
-
return "a live
|
|
43865
|
+
return "a live process";
|
|
42840
43866
|
if (rendered.length === 1)
|
|
42841
43867
|
return rendered[0];
|
|
42842
43868
|
const last = rendered.pop();
|
|
@@ -42846,9 +43872,9 @@ function formatFailClosedBlockingMessage(reason) {
|
|
|
42846
43872
|
if (reason.kind === "migration_guard") {
|
|
42847
43873
|
if (reason.unreadableFile) {
|
|
42848
43874
|
const arm = reason.unreadableArm ?? "io";
|
|
42849
|
-
const recovery = arm === "io" ? `If
|
|
43875
|
+
const recovery = arm === "io" ? `If none of these processes are running, it is safe to delete ${reason.unreadableFile} and retry.` : `The file may be a recent incomplete write; retry after the file is older than the ten-minute grace window, or stop the relevant process before deleting it.`;
|
|
42850
43876
|
return [
|
|
42851
|
-
`Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live
|
|
43877
|
+
`Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live process cannot be proven.`,
|
|
42852
43878
|
recovery,
|
|
42853
43879
|
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
42854
43880
|
].join(" ");
|
|
@@ -42927,13 +43953,13 @@ var init_storage_versions = __esm(async () => {
|
|
|
42927
43953
|
});
|
|
42928
43954
|
|
|
42929
43955
|
// src/commands/doctor-opencode-cache.ts
|
|
42930
|
-
import { existsSync as
|
|
43956
|
+
import { existsSync as existsSync30, readFileSync as readFileSync21, rmSync as rmSync3 } from "node:fs";
|
|
42931
43957
|
function readCachedPluginVersion(pluginCacheDir) {
|
|
42932
43958
|
try {
|
|
42933
43959
|
const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
|
|
42934
|
-
if (!
|
|
43960
|
+
if (!existsSync30(installedPkgPath))
|
|
42935
43961
|
return;
|
|
42936
|
-
const pkg = JSON.parse(
|
|
43962
|
+
const pkg = JSON.parse(readFileSync21(installedPkgPath, "utf-8"));
|
|
42937
43963
|
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
42938
43964
|
} catch {
|
|
42939
43965
|
return;
|
|
@@ -42942,7 +43968,7 @@ function readCachedPluginVersion(pluginCacheDir) {
|
|
|
42942
43968
|
async function clearPluginCache(options = {}, deps = {}) {
|
|
42943
43969
|
const remove = deps.remove ?? ((path6) => rmSync3(path6, { recursive: true, force: true }));
|
|
42944
43970
|
const pluginCacheRoots = getOpenCodePluginCacheRoots();
|
|
42945
|
-
const existingRoots = pluginCacheRoots.filter((root) =>
|
|
43971
|
+
const existingRoots = pluginCacheRoots.filter((root) => existsSync30(root));
|
|
42946
43972
|
if (existingRoots.length === 0) {
|
|
42947
43973
|
return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
|
|
42948
43974
|
}
|
|
@@ -43010,10 +44036,10 @@ var init_doctor_opencode_cache = __esm(() => {
|
|
|
43010
44036
|
|
|
43011
44037
|
// src/commands/doctor-opencode.ts
|
|
43012
44038
|
import { execSync as execSync2, spawnSync as spawnSync6 } from "node:child_process";
|
|
43013
|
-
import { existsSync as
|
|
44039
|
+
import { existsSync as existsSync31, readFileSync as readFileSync22, statSync as statSync12 } from "node:fs";
|
|
43014
44040
|
import { createRequire as createRequire5 } from "node:module";
|
|
43015
|
-
import { homedir as
|
|
43016
|
-
import { join as
|
|
44041
|
+
import { homedir as homedir17 } from "node:os";
|
|
44042
|
+
import { join as join28 } from "node:path";
|
|
43017
44043
|
function resolveCompactionEnabledForDoctor() {
|
|
43018
44044
|
try {
|
|
43019
44045
|
const config2 = loadPluginConfig(process.cwd());
|
|
@@ -43112,15 +44138,15 @@ function getUserNpmrcPath() {
|
|
|
43112
44138
|
if (custom2)
|
|
43113
44139
|
return custom2;
|
|
43114
44140
|
const home = process.env.HOME?.trim();
|
|
43115
|
-
return
|
|
44141
|
+
return join28(home || homedir17(), ".npmrc");
|
|
43116
44142
|
}
|
|
43117
44143
|
function collectNpmReleaseAgeWarnings() {
|
|
43118
44144
|
const ageWarnings = [];
|
|
43119
44145
|
const npmrcPath = getUserNpmrcPath();
|
|
43120
|
-
if (!
|
|
44146
|
+
if (!existsSync31(npmrcPath))
|
|
43121
44147
|
return ageWarnings;
|
|
43122
44148
|
try {
|
|
43123
|
-
const npmrc =
|
|
44149
|
+
const npmrc = readFileSync22(npmrcPath, "utf-8");
|
|
43124
44150
|
for (const line of npmrc.split(`
|
|
43125
44151
|
`)) {
|
|
43126
44152
|
const trimmed = line.trim();
|
|
@@ -43259,12 +44285,12 @@ function checkLocalEmbeddingRuntimeForDoctor() {
|
|
|
43259
44285
|
return { issues: 0 };
|
|
43260
44286
|
}
|
|
43261
44287
|
async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
43262
|
-
if (!
|
|
44288
|
+
if (!existsSync31(magicContextConfigPath)) {
|
|
43263
44289
|
return checkLocalEmbeddingRuntimeForDoctor();
|
|
43264
44290
|
}
|
|
43265
44291
|
let rawText;
|
|
43266
44292
|
try {
|
|
43267
|
-
rawText =
|
|
44293
|
+
rawText = readFileSync22(magicContextConfigPath, "utf-8");
|
|
43268
44294
|
} catch {
|
|
43269
44295
|
log2.warn("Could not read magic-context.jsonc for embedding check");
|
|
43270
44296
|
return { issues: 1 };
|
|
@@ -43275,7 +44301,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
|
43275
44301
|
});
|
|
43276
44302
|
let parsedConfig;
|
|
43277
44303
|
try {
|
|
43278
|
-
parsedConfig =
|
|
44304
|
+
parsedConfig = import_comment_json12.parse(substituted.text);
|
|
43279
44305
|
} catch (error51) {
|
|
43280
44306
|
log2.warn(`Embedding check skipped — could not parse magic-context.jsonc: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
43281
44307
|
return { issues: 1 };
|
|
@@ -43387,7 +44413,7 @@ async function runDoctor2(options = {}) {
|
|
|
43387
44413
|
const v22Result = await runV22BackfillCommands({
|
|
43388
44414
|
name: "OpenCode",
|
|
43389
44415
|
openDatabase: (readonly2 = true) => {
|
|
43390
|
-
const dbPath2 =
|
|
44416
|
+
const dbPath2 = join28(getMagicContextStorageDir(), "context.db");
|
|
43391
44417
|
v22Db = readonly2 ? openExistingContextDatabase(dbPath2, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath2);
|
|
43392
44418
|
return v22Db;
|
|
43393
44419
|
},
|
|
@@ -43410,7 +44436,7 @@ async function runDoctor2(options = {}) {
|
|
|
43410
44436
|
log2.success(msg);
|
|
43411
44437
|
passCount++;
|
|
43412
44438
|
};
|
|
43413
|
-
const
|
|
44439
|
+
const warn2 = (msg) => {
|
|
43414
44440
|
log2.warn(msg);
|
|
43415
44441
|
warnCount++;
|
|
43416
44442
|
};
|
|
@@ -43419,17 +44445,17 @@ async function runDoctor2(options = {}) {
|
|
|
43419
44445
|
failCount++;
|
|
43420
44446
|
issues++;
|
|
43421
44447
|
};
|
|
43422
|
-
const authorityDbPath =
|
|
44448
|
+
const authorityDbPath = join28(getMagicContextStorageDir(), "context.db");
|
|
43423
44449
|
let authorityDb = null;
|
|
43424
44450
|
try {
|
|
43425
44451
|
authorityDb = openExistingContextDatabase(authorityDbPath, { readonly: true });
|
|
43426
44452
|
if (authorityDb) {
|
|
43427
|
-
await reportAuthorityMarkers({ db: authorityDb, info: log2.info, warn });
|
|
44453
|
+
await reportAuthorityMarkers({ db: authorityDb, info: log2.info, warn: warn2 });
|
|
43428
44454
|
} else {
|
|
43429
44455
|
log2.info("Authority: no context database found");
|
|
43430
44456
|
}
|
|
43431
44457
|
} catch (error51) {
|
|
43432
|
-
|
|
44458
|
+
warn2(`Authority check unavailable: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
43433
44459
|
} finally {
|
|
43434
44460
|
authorityDb?.close();
|
|
43435
44461
|
}
|
|
@@ -43460,7 +44486,7 @@ async function runDoctor2(options = {}) {
|
|
|
43460
44486
|
if (!npmLatest) {
|
|
43461
44487
|
log2.info(`Magic Context CLI v${selfVersion2}; npm latest check unavailable`);
|
|
43462
44488
|
} else if (compareVersions(selfVersion2, npmLatest) < 0) {
|
|
43463
|
-
|
|
44489
|
+
warn2(`Magic Context CLI v${selfVersion2} is older than npm latest v${npmLatest}`);
|
|
43464
44490
|
} else {
|
|
43465
44491
|
pass(`Magic Context CLI v${selfVersion2} is current (npm latest v${npmLatest})`);
|
|
43466
44492
|
}
|
|
@@ -43470,15 +44496,15 @@ async function runDoctor2(options = {}) {
|
|
|
43470
44496
|
} else {
|
|
43471
44497
|
pass(`OpenCode config: ${paths.opencodeConfig}`);
|
|
43472
44498
|
}
|
|
43473
|
-
if (
|
|
44499
|
+
if (existsSync31(paths.magicContextConfig)) {
|
|
43474
44500
|
pass(`Magic Context config: ${paths.magicContextConfig}`);
|
|
43475
44501
|
try {
|
|
43476
|
-
const raw =
|
|
44502
|
+
const raw = readFileSync22(paths.magicContextConfig, "utf-8");
|
|
43477
44503
|
const substituted = substituteConfigVariables({
|
|
43478
44504
|
text: raw,
|
|
43479
44505
|
configPath: paths.magicContextConfig
|
|
43480
44506
|
}).text;
|
|
43481
|
-
|
|
44507
|
+
import_comment_json12.parse(substituted);
|
|
43482
44508
|
pass("magic-context.jsonc parses as valid JSONC");
|
|
43483
44509
|
} catch (err) {
|
|
43484
44510
|
fail(`magic-context.jsonc parse failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -43487,7 +44513,7 @@ async function runDoctor2(options = {}) {
|
|
|
43487
44513
|
const result = loadPluginConfig(process.cwd());
|
|
43488
44514
|
const warnings = result.configWarnings ?? [];
|
|
43489
44515
|
if (warnings.length > 0) {
|
|
43490
|
-
|
|
44516
|
+
warn2(`Magic Context config has ${warnings.length} warning(s) — see 'magic-context doctor --issue' for details`);
|
|
43491
44517
|
} else {
|
|
43492
44518
|
pass("Magic Context config loads successfully");
|
|
43493
44519
|
}
|
|
@@ -43495,13 +44521,13 @@ async function runDoctor2(options = {}) {
|
|
|
43495
44521
|
fail(`Could not load Magic Context config: ${err instanceof Error ? err.message : String(err)}`);
|
|
43496
44522
|
}
|
|
43497
44523
|
} else {
|
|
43498
|
-
|
|
44524
|
+
warn2(`No magic-context.jsonc found — using defaults`);
|
|
43499
44525
|
log2.info(" Run 'setup' to create one with model recommendations");
|
|
43500
44526
|
}
|
|
43501
|
-
if (
|
|
44527
|
+
if (existsSync31(paths.magicContextConfig)) {
|
|
43502
44528
|
try {
|
|
43503
|
-
const mcRaw =
|
|
43504
|
-
const mcConfig =
|
|
44529
|
+
const mcRaw = readFileSync22(paths.magicContextConfig, "utf-8");
|
|
44530
|
+
const mcConfig = import_comment_json12.parse(mcRaw);
|
|
43505
44531
|
let mcChanged = false;
|
|
43506
44532
|
const experimental = mcConfig.experimental;
|
|
43507
44533
|
if (experimental && "compaction_markers" in experimental) {
|
|
@@ -43609,7 +44635,7 @@ async function runDoctor2(options = {}) {
|
|
|
43609
44635
|
fixed++;
|
|
43610
44636
|
}
|
|
43611
44637
|
if (mcChanged) {
|
|
43612
|
-
writeFileAtomic(paths.magicContextConfig, `${
|
|
44638
|
+
writeFileAtomic(paths.magicContextConfig, `${import_comment_json12.stringify(mcConfig, null, 2)}
|
|
43613
44639
|
`);
|
|
43614
44640
|
}
|
|
43615
44641
|
} catch {
|
|
@@ -43618,12 +44644,12 @@ async function runDoctor2(options = {}) {
|
|
|
43618
44644
|
}
|
|
43619
44645
|
if (paths.opencodeConfigFormat !== "none") {
|
|
43620
44646
|
try {
|
|
43621
|
-
const raw =
|
|
43622
|
-
const config2 =
|
|
44647
|
+
const raw = readFileSync22(paths.opencodeConfig, "utf-8");
|
|
44648
|
+
const config2 = import_comment_json12.parse(raw);
|
|
43623
44649
|
const rawPlugins = Array.isArray(config2?.plugin) ? config2.plugin : [];
|
|
43624
44650
|
const existingIdx = rawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
|
|
43625
44651
|
if (rawPlugins.some((entry) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry))) {
|
|
43626
|
-
|
|
44652
|
+
warn2("An unverifiable local OpenCode plugin path was ignored because its package name is not Magic Context");
|
|
43627
44653
|
}
|
|
43628
44654
|
const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
|
|
43629
44655
|
const entryAsString = (entry) => {
|
|
@@ -43643,7 +44669,7 @@ async function runDoctor2(options = {}) {
|
|
|
43643
44669
|
} else {
|
|
43644
44670
|
const isPinned = isPinnedOpenCodePluginSpecifier(oldEntryStr);
|
|
43645
44671
|
if (isPinned && !options.force) {
|
|
43646
|
-
|
|
44672
|
+
warn2(`Plugin pinned to ${oldEntryStr} in ${configName} — use 'doctor --force' to upgrade`);
|
|
43647
44673
|
} else {
|
|
43648
44674
|
if (Array.isArray(oldEntry) && oldEntry.length >= 1) {
|
|
43649
44675
|
const replacement = [...oldEntry];
|
|
@@ -43653,7 +44679,7 @@ async function runDoctor2(options = {}) {
|
|
|
43653
44679
|
rawPlugins[existingIdx] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
|
|
43654
44680
|
}
|
|
43655
44681
|
config2.plugin = rawPlugins;
|
|
43656
|
-
writeFileAtomic(paths.opencodeConfig, `${
|
|
44682
|
+
writeFileAtomic(paths.opencodeConfig, `${import_comment_json12.stringify(config2, null, 2)}
|
|
43657
44683
|
`);
|
|
43658
44684
|
pass(`Upgraded plugin entry in ${configName}: ${oldEntryStr} → ${OPENCODE_PLUGIN_ENTRY_WITH_VERSION}`);
|
|
43659
44685
|
fixed++;
|
|
@@ -43662,18 +44688,19 @@ async function runDoctor2(options = {}) {
|
|
|
43662
44688
|
} else {
|
|
43663
44689
|
rawPlugins.push(OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
|
|
43664
44690
|
config2.plugin = rawPlugins;
|
|
43665
|
-
writeFileAtomic(paths.opencodeConfig, `${
|
|
44691
|
+
writeFileAtomic(paths.opencodeConfig, `${import_comment_json12.stringify(config2, null, 2)}
|
|
43666
44692
|
`);
|
|
43667
44693
|
pass(`Added plugin to ${configName}`);
|
|
43668
44694
|
fixed++;
|
|
43669
44695
|
}
|
|
43670
44696
|
} catch {
|
|
43671
|
-
|
|
44697
|
+
warn2("Could not parse opencode config to verify plugin entry");
|
|
43672
44698
|
}
|
|
43673
44699
|
}
|
|
43674
44700
|
const cwd = process.cwd();
|
|
43675
44701
|
const compactionEnabled = resolveCompactionEnabledForDoctor();
|
|
43676
44702
|
const conflictResult = detectConflicts(cwd, { compactionEnabled });
|
|
44703
|
+
log2.info("Compaction check: file-based; the running server's resolved config may differ — `opencode debug config` is authoritative");
|
|
43677
44704
|
if (conflictResult.hasConflict) {
|
|
43678
44705
|
for (const reason of conflictResult.reasons) {
|
|
43679
44706
|
fail(`Conflict: ${reason}`);
|
|
@@ -43684,14 +44711,14 @@ async function runDoctor2(options = {}) {
|
|
|
43684
44711
|
fixed++;
|
|
43685
44712
|
}
|
|
43686
44713
|
if (actions.length > 0) {
|
|
43687
|
-
|
|
44714
|
+
warn2("Restart OpenCode for conflict fixes to take effect");
|
|
43688
44715
|
}
|
|
43689
44716
|
} else {
|
|
43690
44717
|
if (!compactionEnabled) {
|
|
43691
44718
|
if (conflictResult.nativeCompaction.auto || conflictResult.nativeCompaction.prune) {
|
|
43692
44719
|
pass("No conflicts detected (compaction, DCP, OMO hooks) — native compaction active (compaction-off mode)");
|
|
43693
44720
|
} else {
|
|
43694
|
-
|
|
44721
|
+
warn2("No compaction manager is active: Magic Context compaction is off and OpenCode auto-compaction is disabled");
|
|
43695
44722
|
}
|
|
43696
44723
|
} else {
|
|
43697
44724
|
pass("No conflicts detected (compaction, DCP, OMO hooks)");
|
|
@@ -43700,16 +44727,16 @@ async function runDoctor2(options = {}) {
|
|
|
43700
44727
|
const tuiAdded = ensureTuiPluginEntry();
|
|
43701
44728
|
if (tuiAdded) {
|
|
43702
44729
|
pass("Added TUI sidebar plugin to tui.json");
|
|
43703
|
-
|
|
44730
|
+
warn2("Restart OpenCode to see the sidebar");
|
|
43704
44731
|
fixed++;
|
|
43705
|
-
} else if (
|
|
44732
|
+
} else if (existsSync31(paths.tuiConfig)) {
|
|
43706
44733
|
try {
|
|
43707
|
-
const tuiRaw =
|
|
43708
|
-
const tuiConfig =
|
|
44734
|
+
const tuiRaw = readFileSync22(paths.tuiConfig, "utf-8");
|
|
44735
|
+
const tuiConfig = import_comment_json12.parse(tuiRaw);
|
|
43709
44736
|
const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
|
|
43710
44737
|
const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
|
|
43711
44738
|
if (tuiRawPlugins.some((entry) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry))) {
|
|
43712
|
-
|
|
44739
|
+
warn2("An unverifiable local TUI plugin path was ignored because its package name is not Magic Context");
|
|
43713
44740
|
}
|
|
43714
44741
|
const tuiEntryAsString = (entry) => {
|
|
43715
44742
|
if (typeof entry === "string")
|
|
@@ -43726,7 +44753,7 @@ async function runDoctor2(options = {}) {
|
|
|
43726
44753
|
} else {
|
|
43727
44754
|
const tuiPinned = isPinnedOpenCodePluginSpecifier(tuiEntryStr);
|
|
43728
44755
|
if (tuiPinned && !options.force) {
|
|
43729
|
-
|
|
44756
|
+
warn2(`TUI plugin pinned to ${tuiEntryStr} — use 'doctor --force' to upgrade`);
|
|
43730
44757
|
} else if (tuiPinned && options.force) {
|
|
43731
44758
|
if (Array.isArray(tuiEntry) && tuiEntry.length >= 1) {
|
|
43732
44759
|
const replacement = [...tuiEntry];
|
|
@@ -43736,7 +44763,7 @@ async function runDoctor2(options = {}) {
|
|
|
43736
44763
|
tuiRawPlugins[tuiIdx] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
|
|
43737
44764
|
}
|
|
43738
44765
|
tuiConfig.plugin = tuiRawPlugins;
|
|
43739
|
-
writeFileAtomic(paths.tuiConfig, `${
|
|
44766
|
+
writeFileAtomic(paths.tuiConfig, `${import_comment_json12.stringify(tuiConfig, null, 2)}
|
|
43740
44767
|
`);
|
|
43741
44768
|
pass(`Upgraded TUI plugin: ${tuiEntryStr} → ${OPENCODE_PLUGIN_ENTRY_WITH_VERSION}`);
|
|
43742
44769
|
fixed++;
|
|
@@ -43753,10 +44780,10 @@ async function runDoctor2(options = {}) {
|
|
|
43753
44780
|
} else {
|
|
43754
44781
|
fail("Could not create or verify the TUI sidebar config");
|
|
43755
44782
|
}
|
|
43756
|
-
if (
|
|
44783
|
+
if (existsSync31(paths.magicContextConfig)) {
|
|
43757
44784
|
try {
|
|
43758
|
-
const mcRaw =
|
|
43759
|
-
const mcConfig =
|
|
44785
|
+
const mcRaw = readFileSync22(paths.magicContextConfig, "utf-8");
|
|
44786
|
+
const mcConfig = import_comment_json12.parse(mcRaw);
|
|
43760
44787
|
const warning = checkUserMemoriesDreamerCompatibility(mcConfig);
|
|
43761
44788
|
if (warning) {
|
|
43762
44789
|
log2.warn(warning);
|
|
@@ -43772,8 +44799,8 @@ async function runDoctor2(options = {}) {
|
|
|
43772
44799
|
warnCount++;
|
|
43773
44800
|
else
|
|
43774
44801
|
passCount++;
|
|
43775
|
-
const dbPath =
|
|
43776
|
-
if (!
|
|
44802
|
+
const dbPath = join28(getMagicContextStorageDir(), "context.db");
|
|
44803
|
+
if (!existsSync31(dbPath)) {
|
|
43777
44804
|
log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
|
|
43778
44805
|
} else {
|
|
43779
44806
|
log2.info(`Shared context DB exists at ${dbPath}`);
|
|
@@ -43786,6 +44813,21 @@ async function runDoctor2(options = {}) {
|
|
|
43786
44813
|
pass("Opened the shared DB with a supported schema");
|
|
43787
44814
|
const storageVersions = readStorageVersions(db);
|
|
43788
44815
|
log2.info(formatStorageVersions(storageVersions));
|
|
44816
|
+
const pinnedPluginFenceFindings = await inspectPinnedOpenCodePluginSchemaFences({
|
|
44817
|
+
directory: process.cwd(),
|
|
44818
|
+
databaseVersion: storageVersions.context_db_schema_version
|
|
44819
|
+
});
|
|
44820
|
+
for (const finding of pinnedPluginFenceFindings) {
|
|
44821
|
+
const location = `${finding.surface} entry ${finding.specifier} in ${sanitizePathString(finding.configPath)}`;
|
|
44822
|
+
if (finding.status === "fail") {
|
|
44823
|
+
fail(`Pinned plugin schema fence mismatch: ${location} pins plugin v${finding.pinnedVersion}, which supports through schema v${finding.supportedVersion}; shared context.db is v${finding.databaseVersion}. Recovery: unpin the entry (use @latest), or upgrade the pin to a version released after this migration that supports v${finding.databaseVersion} or later.`);
|
|
44824
|
+
} else if (finding.status === "unknown") {
|
|
44825
|
+
warn2(`UNKNOWN: Pinned plugin schema fence could not be resolved for ${location}; shared context.db is v${finding.databaseVersion}, so doctor cannot verify the plugin that will run. Install the pinned package and rerun doctor, or unpin/upgrade it to a version released after this migration.`);
|
|
44826
|
+
issues++;
|
|
44827
|
+
} else {
|
|
44828
|
+
pass(`Pinned plugin schema fence: ${location} pins plugin v${finding.pinnedVersion}, which supports shared context.db v${finding.databaseVersion}.`);
|
|
44829
|
+
}
|
|
44830
|
+
}
|
|
43789
44831
|
const fenceCheck = checkStorageVersionFence(storageVersions, {
|
|
43790
44832
|
blockingProcesses: getLiveMigrationBlockingProcesses(getMagicContextStorageDir())
|
|
43791
44833
|
});
|
|
@@ -43852,9 +44894,9 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
43852
44894
|
} else if (cacheResult.action === "up_to_date") {
|
|
43853
44895
|
pass(`Plugin cache up to date (v${cacheResult.cached})`);
|
|
43854
44896
|
} else if (cacheResult.action === "check_unavailable") {
|
|
43855
|
-
|
|
44897
|
+
warn2(`Plugin cache version check unavailable; preserving cached plugin${cacheResult.cached ? ` (cached: ${cacheResult.cached})` : ""}. Use doctor --force to reinstall it.`);
|
|
43856
44898
|
} else if (cacheResult.action === "error") {
|
|
43857
|
-
|
|
44899
|
+
warn2(`Could not clear plugin cache: ${cacheResult.error}`);
|
|
43858
44900
|
if (cacheResult.clearedPaths && cacheResult.clearedPaths.length > 0) {
|
|
43859
44901
|
log2.info(` Cleared roots: ${cacheResult.clearedPaths.join(", ")}`);
|
|
43860
44902
|
}
|
|
@@ -43880,8 +44922,8 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
43880
44922
|
}
|
|
43881
44923
|
}
|
|
43882
44924
|
const logPath = getMagicContextLogPath2("opencode");
|
|
43883
|
-
if (
|
|
43884
|
-
const logStat =
|
|
44925
|
+
if (existsSync31(logPath)) {
|
|
44926
|
+
const logStat = statSync12(logPath);
|
|
43885
44927
|
const sizeKb = (logStat.size / 1024).toFixed(0);
|
|
43886
44928
|
log2.info(`Log file: ${logPath} (${sizeKb} KB)`);
|
|
43887
44929
|
} else {
|
|
@@ -43892,7 +44934,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
43892
44934
|
if (dumpBuckets.length > 0) {
|
|
43893
44935
|
const totalCount = dumpBuckets.reduce((sum, b2) => sum + b2.count, 0);
|
|
43894
44936
|
const sessionCount = dumpBuckets.length;
|
|
43895
|
-
|
|
44937
|
+
warn2(`Historian debug dumps: ${totalCount} file(s) across ${sessionCount} project(s)`);
|
|
43896
44938
|
for (const bucket of dumpBuckets) {
|
|
43897
44939
|
log2.info(` [${bucket.directory}] ${bucket.count} file(s)`);
|
|
43898
44940
|
for (const dump of bucket.recent.slice(0, 3)) {
|
|
@@ -43926,7 +44968,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
43926
44968
|
}
|
|
43927
44969
|
return 0;
|
|
43928
44970
|
}
|
|
43929
|
-
var
|
|
44971
|
+
var import_comment_json12, CLI_PACKAGE_NAME = "@cortexkit/magic-context";
|
|
43930
44972
|
var init_doctor_opencode = __esm(async () => {
|
|
43931
44973
|
init_config();
|
|
43932
44974
|
init_agent_disable();
|
|
@@ -43945,6 +44987,7 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
43945
44987
|
init_opencode_detect();
|
|
43946
44988
|
init_opencode_helpers();
|
|
43947
44989
|
init_opencode_plugin_cache();
|
|
44990
|
+
init_opencode_plugin_schema_fence();
|
|
43948
44991
|
init_paths();
|
|
43949
44992
|
init_prompts();
|
|
43950
44993
|
init_redaction2();
|
|
@@ -43956,15 +44999,15 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
43956
44999
|
init_v22_backfill_commands(),
|
|
43957
45000
|
init_doctor_authority()
|
|
43958
45001
|
]);
|
|
43959
|
-
|
|
45002
|
+
import_comment_json12 = __toESM(require_src3(), 1);
|
|
43960
45003
|
});
|
|
43961
45004
|
|
|
43962
45005
|
// src/lib/diagnostics-pi.ts
|
|
43963
|
-
import { createHash as
|
|
43964
|
-
import { existsSync as
|
|
45006
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
45007
|
+
import { existsSync as existsSync32, readdirSync as readdirSync5, readFileSync as readFileSync23, statSync as statSync13 } from "node:fs";
|
|
43965
45008
|
import { createRequire as createRequire6 } from "node:module";
|
|
43966
|
-
import { homedir as
|
|
43967
|
-
import { join as
|
|
45009
|
+
import { homedir as homedir18, userInfo as userInfo2 } from "node:os";
|
|
45010
|
+
import { join as join29 } from "node:path";
|
|
43968
45011
|
function getSelfVersion3() {
|
|
43969
45012
|
const req = createRequire6(import.meta.url);
|
|
43970
45013
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
@@ -43979,7 +45022,7 @@ function getSelfVersion3() {
|
|
|
43979
45022
|
}
|
|
43980
45023
|
function fileSize2(path6) {
|
|
43981
45024
|
try {
|
|
43982
|
-
return
|
|
45025
|
+
return existsSync32(path6) ? statSync13(path6).size : 0;
|
|
43983
45026
|
} catch {
|
|
43984
45027
|
return 0;
|
|
43985
45028
|
}
|
|
@@ -43989,13 +45032,13 @@ function escapeRegex3(value) {
|
|
|
43989
45032
|
}
|
|
43990
45033
|
function currentUserHash() {
|
|
43991
45034
|
const username = userInfo2().username || "unknown";
|
|
43992
|
-
return
|
|
45035
|
+
return createHash5("sha256").update(username).digest("hex").slice(0, 12);
|
|
43993
45036
|
}
|
|
43994
45037
|
function redactSecretString(value) {
|
|
43995
45038
|
return redactSecretText(value).replace(/Bearer\s+[A-Za-z0-9._~+\-/=]+/g, "Bearer <REDACTED>").replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-<REDACTED>").replace(/api[_-]?key=([^\s&]+)/gi, "api_key=<REDACTED>").replace(/token=([^\s&]+)/gi, "token=<REDACTED>");
|
|
43996
45039
|
}
|
|
43997
45040
|
function sanitizeString2(value) {
|
|
43998
|
-
const home = process.env.HOME ||
|
|
45041
|
+
const home = process.env.HOME || homedir18();
|
|
43999
45042
|
const username = userInfo2().username;
|
|
44000
45043
|
const userHash = `<USER:${currentUserHash()}>`;
|
|
44001
45044
|
let sanitized = redactSecretString(value);
|
|
@@ -44031,11 +45074,11 @@ function sanitizeValue2(value, key = "") {
|
|
|
44031
45074
|
return value;
|
|
44032
45075
|
}
|
|
44033
45076
|
function readJsonc(path6) {
|
|
44034
|
-
if (!
|
|
45077
|
+
if (!existsSync32(path6))
|
|
44035
45078
|
return { value: {} };
|
|
44036
45079
|
try {
|
|
44037
45080
|
return {
|
|
44038
|
-
value:
|
|
45081
|
+
value: import_comment_json13.parse(readFileSync23(path6, "utf-8"))
|
|
44039
45082
|
};
|
|
44040
45083
|
} catch (error51) {
|
|
44041
45084
|
return {
|
|
@@ -44051,7 +45094,7 @@ function readConfigDiagnostic(path6) {
|
|
|
44051
45094
|
const parsed = readJsonc(path6);
|
|
44052
45095
|
return {
|
|
44053
45096
|
path: path6,
|
|
44054
|
-
exists:
|
|
45097
|
+
exists: existsSync32(path6),
|
|
44055
45098
|
...parsed.parseError ? { parseError: parsed.parseError } : {},
|
|
44056
45099
|
flags: sanitizeValue2(parsed.value)
|
|
44057
45100
|
};
|
|
@@ -44069,25 +45112,25 @@ function reverseSlugToDirectory(slug) {
|
|
|
44069
45112
|
}
|
|
44070
45113
|
function collectPiRecentSessions() {
|
|
44071
45114
|
const sessionsRoot = getPiSessionsRoot();
|
|
44072
|
-
if (!
|
|
45115
|
+
if (!existsSync32(sessionsRoot))
|
|
44073
45116
|
return [];
|
|
44074
45117
|
try {
|
|
44075
|
-
const slugs =
|
|
45118
|
+
const slugs = readdirSync5(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
44076
45119
|
const candidates = [];
|
|
44077
45120
|
for (const slug of slugs) {
|
|
44078
45121
|
const directory = reverseSlugToDirectory(slug);
|
|
44079
45122
|
if (!directory)
|
|
44080
45123
|
continue;
|
|
44081
|
-
const slugDir =
|
|
45124
|
+
const slugDir = join29(sessionsRoot, slug);
|
|
44082
45125
|
let files;
|
|
44083
45126
|
try {
|
|
44084
|
-
files =
|
|
45127
|
+
files = readdirSync5(slugDir).filter((name) => name.endsWith(".jsonl"));
|
|
44085
45128
|
} catch {
|
|
44086
45129
|
continue;
|
|
44087
45130
|
}
|
|
44088
45131
|
for (const file2 of files) {
|
|
44089
45132
|
try {
|
|
44090
|
-
const mtime =
|
|
45133
|
+
const mtime = statSync13(join29(slugDir, file2)).mtimeMs;
|
|
44091
45134
|
const sessionId = file2.replace(/\.jsonl$/, "");
|
|
44092
45135
|
candidates.push({ sessionId, directory, mtime });
|
|
44093
45136
|
} catch {}
|
|
@@ -44105,7 +45148,7 @@ function collectPiRecentSessions() {
|
|
|
44105
45148
|
}
|
|
44106
45149
|
function parseHistorianDumpMeta2(path6) {
|
|
44107
45150
|
try {
|
|
44108
|
-
const xml =
|
|
45151
|
+
const xml = readFileSync23(path6, "utf-8");
|
|
44109
45152
|
const parsed = parseCompartmentOutput(xml);
|
|
44110
45153
|
const factCountByCategory = {};
|
|
44111
45154
|
for (const fact of parsed.facts) {
|
|
@@ -44138,11 +45181,11 @@ function parseHistorianDumpMeta2(path6) {
|
|
|
44138
45181
|
}
|
|
44139
45182
|
}
|
|
44140
45183
|
function listDumpsInDir2(dir, limit) {
|
|
44141
|
-
if (!
|
|
45184
|
+
if (!existsSync32(dir))
|
|
44142
45185
|
return { count: 0, recent: [] };
|
|
44143
45186
|
try {
|
|
44144
|
-
const entries =
|
|
44145
|
-
const stat =
|
|
45187
|
+
const entries = readdirSync5(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
45188
|
+
const stat = statSync13(join29(dir, name));
|
|
44146
45189
|
return {
|
|
44147
45190
|
name,
|
|
44148
45191
|
mtime: stat.mtimeMs,
|
|
@@ -44151,7 +45194,7 @@ function listDumpsInDir2(dir, limit) {
|
|
|
44151
45194
|
}).sort((a3, b2) => b2.mtime - a3.mtime);
|
|
44152
45195
|
const now = Date.now();
|
|
44153
45196
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
44154
|
-
const meta3 = parseHistorianDumpMeta2(
|
|
45197
|
+
const meta3 = parseHistorianDumpMeta2(join29(dir, entry.name));
|
|
44155
45198
|
const summary = {
|
|
44156
45199
|
name: entry.name,
|
|
44157
45200
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -44214,9 +45257,9 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
44214
45257
|
const projectConfigPath = getProjectConfigPath(cwd);
|
|
44215
45258
|
const loaded = loadPiConfig({ cwd });
|
|
44216
45259
|
const storageDirPath = getMagicContextStorageDir();
|
|
44217
|
-
const dbPath =
|
|
45260
|
+
const dbPath = join29(storageDirPath, "context.db");
|
|
44218
45261
|
const logPath = getMagicContextLogPath2("pi");
|
|
44219
|
-
const logFileSize =
|
|
45262
|
+
const logFileSize = existsSync32(logPath) ? statSync13(logPath).size : 0;
|
|
44220
45263
|
const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
|
|
44221
45264
|
const recentSessions = collectPiRecentSessions();
|
|
44222
45265
|
const historianDumps = collectPiHistorianDumps(recentSessions);
|
|
@@ -44231,7 +45274,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
44231
45274
|
piVersion: pi ? getPiVersion(pi.path) : null,
|
|
44232
45275
|
settings: {
|
|
44233
45276
|
path: settingsPath,
|
|
44234
|
-
exists:
|
|
45277
|
+
exists: existsSync32(settingsPath),
|
|
44235
45278
|
...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
|
|
44236
45279
|
hasMagicContextPackage: hasPiMagicContextPackage(packages),
|
|
44237
45280
|
packages: sanitizeValue2(packages)
|
|
@@ -44247,7 +45290,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
44247
45290
|
loadWarnings: loaded.warnings.map(sanitizeString2),
|
|
44248
45291
|
storageDir: {
|
|
44249
45292
|
path: storageDirPath,
|
|
44250
|
-
exists:
|
|
45293
|
+
exists: existsSync32(storageDirPath),
|
|
44251
45294
|
contextDbSizeBytes: fileSize2(dbPath)
|
|
44252
45295
|
},
|
|
44253
45296
|
conflicts: {
|
|
@@ -44256,7 +45299,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
44256
45299
|
},
|
|
44257
45300
|
logFile: {
|
|
44258
45301
|
path: logPath,
|
|
44259
|
-
exists:
|
|
45302
|
+
exists: existsSync32(logPath),
|
|
44260
45303
|
sizeKb: Math.round(logFileSize / 1024)
|
|
44261
45304
|
},
|
|
44262
45305
|
recentSessions,
|
|
@@ -44337,7 +45380,7 @@ function renderDiagnosticsMarkdown2(report) {
|
|
|
44337
45380
|
].join(`
|
|
44338
45381
|
`);
|
|
44339
45382
|
}
|
|
44340
|
-
var
|
|
45383
|
+
var import_comment_json13;
|
|
44341
45384
|
var init_diagnostics_pi = __esm(() => {
|
|
44342
45385
|
init_migrate_config_location();
|
|
44343
45386
|
init_compartment_parser();
|
|
@@ -44346,12 +45389,12 @@ var init_diagnostics_pi = __esm(() => {
|
|
|
44346
45389
|
init_paths();
|
|
44347
45390
|
init_pi_helpers();
|
|
44348
45391
|
init_redaction2();
|
|
44349
|
-
|
|
45392
|
+
import_comment_json13 = __toESM(require_src3(), 1);
|
|
44350
45393
|
});
|
|
44351
45394
|
|
|
44352
45395
|
// src/lib/logs-pi.ts
|
|
44353
|
-
import { readFileSync as
|
|
44354
|
-
import { join as
|
|
45396
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync9 } from "node:fs";
|
|
45397
|
+
import { join as join30 } from "node:path";
|
|
44355
45398
|
function sanitizeLogContent2(content) {
|
|
44356
45399
|
return sanitizeString2(content);
|
|
44357
45400
|
}
|
|
@@ -44380,7 +45423,7 @@ function filterLogLinesBySession2(lines, sessionId) {
|
|
|
44380
45423
|
}
|
|
44381
45424
|
async function bundleIssueReport2(report, description, title, options = {}) {
|
|
44382
45425
|
const LOG_TAIL_LINES = 400;
|
|
44383
|
-
const allLogLines = report.logFile.exists ?
|
|
45426
|
+
const allLogLines = report.logFile.exists ? readFileSync24(report.logFile.path, "utf-8").split(/\r?\n/) : [];
|
|
44384
45427
|
const logLines = filterLogLinesBySession2(allLogLines, options.sessionFilter ?? null);
|
|
44385
45428
|
const recentLog = sanitizeLogContent2(logLines.slice(-LOG_TAIL_LINES).join(`
|
|
44386
45429
|
`)).trim();
|
|
@@ -44416,8 +45459,8 @@ async function bundleIssueReport2(report, description, title, options = {}) {
|
|
|
44416
45459
|
`);
|
|
44417
45460
|
const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
|
|
44418
45461
|
const cwd = options.cwd ?? process.cwd();
|
|
44419
|
-
const path6 =
|
|
44420
|
-
|
|
45462
|
+
const path6 = join30(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
|
|
45463
|
+
writeFileSync9(path6, `${bodyMarkdown}
|
|
44421
45464
|
`);
|
|
44422
45465
|
return { path: path6, bodyMarkdown };
|
|
44423
45466
|
}
|
|
@@ -44428,14 +45471,14 @@ var init_logs_pi = __esm(() => {
|
|
|
44428
45471
|
|
|
44429
45472
|
// src/commands/doctor-pi.ts
|
|
44430
45473
|
import { execFileSync as execFileSync6, spawnSync as spawnSync7 } from "node:child_process";
|
|
44431
|
-
import { existsSync as
|
|
45474
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync11, readdirSync as readdirSync6, readFileSync as readFileSync25, rmSync as rmSync4, statSync as statSync14 } from "node:fs";
|
|
44432
45475
|
import { createRequire as createRequire7 } from "node:module";
|
|
44433
|
-
import { homedir as
|
|
44434
|
-
import { dirname as
|
|
45476
|
+
import { homedir as homedir19 } from "node:os";
|
|
45477
|
+
import { dirname as dirname17, isAbsolute as isAbsolute5, join as join31 } from "node:path";
|
|
44435
45478
|
function depsFrom(options) {
|
|
44436
45479
|
return {
|
|
44437
|
-
...
|
|
44438
|
-
prompts: options.prompts ??
|
|
45480
|
+
...DEFAULT_DEPS5,
|
|
45481
|
+
prompts: options.prompts ?? DEFAULT_DEPS5.prompts,
|
|
44439
45482
|
...options.deps
|
|
44440
45483
|
};
|
|
44441
45484
|
}
|
|
@@ -44521,7 +45564,7 @@ function summarize(results) {
|
|
|
44521
45564
|
function readJsonc2(path6) {
|
|
44522
45565
|
try {
|
|
44523
45566
|
return {
|
|
44524
|
-
value:
|
|
45567
|
+
value: import_comment_json14.parse(readFileSync25(path6, "utf-8"))
|
|
44525
45568
|
};
|
|
44526
45569
|
} catch (error51) {
|
|
44527
45570
|
return {
|
|
@@ -44540,28 +45583,28 @@ function piPluginDirCandidates(packages, cwd) {
|
|
|
44540
45583
|
const spec = typeof entry === "string" ? entry.trim() : "";
|
|
44541
45584
|
if (!spec || spec.startsWith("npm:"))
|
|
44542
45585
|
continue;
|
|
44543
|
-
const resolved =
|
|
45586
|
+
const resolved = isAbsolute5(spec) ? spec : join31(agentDir, spec);
|
|
44544
45587
|
dirs.push(resolved);
|
|
44545
45588
|
}
|
|
44546
|
-
dirs.push(
|
|
44547
|
-
dirs.push(
|
|
44548
|
-
return dirs.filter((dir) =>
|
|
45589
|
+
dirs.push(join31(agentDir, "npm", "node_modules", PACKAGE_NAME2));
|
|
45590
|
+
dirs.push(join31(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
|
|
45591
|
+
return dirs.filter((dir) => existsSync33(join31(dir, "package.json")));
|
|
44549
45592
|
}
|
|
44550
45593
|
function projectConfigPath(cwd) {
|
|
44551
45594
|
return resolveCortexKitProjectConfigPath(cwd);
|
|
44552
45595
|
}
|
|
44553
45596
|
function readConfigForEmbedding(path6, isProjectConfig) {
|
|
44554
|
-
if (!
|
|
45597
|
+
if (!existsSync33(path6))
|
|
44555
45598
|
return null;
|
|
44556
45599
|
try {
|
|
44557
|
-
const rawText =
|
|
45600
|
+
const rawText = readFileSync25(path6, "utf-8");
|
|
44558
45601
|
const substituted = substituteConfigVariables({
|
|
44559
45602
|
text: rawText,
|
|
44560
45603
|
configPath: path6,
|
|
44561
45604
|
isProjectConfig
|
|
44562
45605
|
});
|
|
44563
45606
|
const rejectedKeyPaths = [];
|
|
44564
|
-
const parsed = sanitizeParsedJson(
|
|
45607
|
+
const parsed = sanitizeParsedJson(import_comment_json14.parse(substituted.text), {
|
|
44565
45608
|
onRejectedKey: (keyPath) => rejectedKeyPaths.push(keyPath.join("."))
|
|
44566
45609
|
});
|
|
44567
45610
|
if (rejectedKeyPaths.length > 0) {
|
|
@@ -44632,38 +45675,38 @@ function pinnedVersionFromPackageSpecifier(specifier) {
|
|
|
44632
45675
|
}
|
|
44633
45676
|
function cacheRoots(cwd) {
|
|
44634
45677
|
const home = process.env.HOME?.trim();
|
|
44635
|
-
const cacheHome = process.env.XDG_CACHE_HOME ||
|
|
45678
|
+
const cacheHome = process.env.XDG_CACHE_HOME || join31(home || homedir19(), ".cache");
|
|
44636
45679
|
const piCacheRoot = getPiCacheRoot();
|
|
44637
45680
|
return [
|
|
44638
|
-
|
|
44639
|
-
|
|
44640
|
-
|
|
44641
|
-
|
|
44642
|
-
|
|
44643
|
-
|
|
44644
|
-
|
|
45681
|
+
join31(piCacheRoot, "extensions"),
|
|
45682
|
+
join31(piCacheRoot, "packages"),
|
|
45683
|
+
join31(cacheHome, "pi", "extensions"),
|
|
45684
|
+
join31(cacheHome, "pi", "packages"),
|
|
45685
|
+
join31(getPiAgentConfigDir(), "cache", "extensions"),
|
|
45686
|
+
join31(getPiAgentConfigDir(), "npm", "node_modules", PACKAGE_NAME2),
|
|
45687
|
+
join31(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2)
|
|
44645
45688
|
];
|
|
44646
45689
|
}
|
|
44647
45690
|
function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
44648
45691
|
const found = new Map;
|
|
44649
45692
|
const visit = (path6, depth) => {
|
|
44650
|
-
if (depth < 0 || !
|
|
45693
|
+
if (depth < 0 || !existsSync33(path6))
|
|
44651
45694
|
return;
|
|
44652
45695
|
let stat;
|
|
44653
45696
|
try {
|
|
44654
|
-
stat =
|
|
45697
|
+
stat = statSync14(path6);
|
|
44655
45698
|
} catch {
|
|
44656
45699
|
return;
|
|
44657
45700
|
}
|
|
44658
45701
|
if (!stat.isDirectory())
|
|
44659
45702
|
return;
|
|
44660
|
-
const packageJson =
|
|
44661
|
-
if (
|
|
45703
|
+
const packageJson = join31(path6, "package.json");
|
|
45704
|
+
if (existsSync33(packageJson)) {
|
|
44662
45705
|
try {
|
|
44663
|
-
const pkg = JSON.parse(
|
|
45706
|
+
const pkg = JSON.parse(readFileSync25(packageJson, "utf-8"));
|
|
44664
45707
|
const name = typeof pkg.name === "string" ? pkg.name : "";
|
|
44665
45708
|
const version2 = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
44666
|
-
if (name ===
|
|
45709
|
+
if (name === PACKAGE_NAME2) {
|
|
44667
45710
|
if (force || !version2 || expectedVersion && version2 !== expectedVersion) {
|
|
44668
45711
|
found.set(path6, { path: path6, version: version2 });
|
|
44669
45712
|
}
|
|
@@ -44675,12 +45718,12 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
|
44675
45718
|
}
|
|
44676
45719
|
let entries = [];
|
|
44677
45720
|
try {
|
|
44678
|
-
entries =
|
|
45721
|
+
entries = readdirSync6(path6);
|
|
44679
45722
|
} catch {
|
|
44680
45723
|
return;
|
|
44681
45724
|
}
|
|
44682
45725
|
for (const entry of entries)
|
|
44683
|
-
visit(
|
|
45726
|
+
visit(join31(path6, entry), depth - 1);
|
|
44684
45727
|
};
|
|
44685
45728
|
for (const root of cacheRoots(cwd))
|
|
44686
45729
|
visit(root, 5);
|
|
@@ -44725,7 +45768,7 @@ async function runHealthChecks2(options) {
|
|
|
44725
45768
|
}
|
|
44726
45769
|
const settingsPath = getPiUserExtensionsPath();
|
|
44727
45770
|
let packages = [];
|
|
44728
|
-
if (!
|
|
45771
|
+
if (!existsSync33(settingsPath)) {
|
|
44729
45772
|
add2(results, "fail", `Pi settings not found at ${settingsPath}`);
|
|
44730
45773
|
repairPlan.addPackageEntry = true;
|
|
44731
45774
|
} else {
|
|
@@ -44749,7 +45792,7 @@ async function runHealthChecks2(options) {
|
|
|
44749
45792
|
["user", userConfigPath, true],
|
|
44750
45793
|
["project", projectPath, false]
|
|
44751
45794
|
]) {
|
|
44752
|
-
if (!
|
|
45795
|
+
if (!existsSync33(path6)) {
|
|
44753
45796
|
if (required2) {
|
|
44754
45797
|
add2(results, "warn", `No ${label} magic-context.jsonc found at ${path6}`);
|
|
44755
45798
|
if (userConfigMigrationRefused) {
|
|
@@ -44786,8 +45829,8 @@ async function runHealthChecks2(options) {
|
|
|
44786
45829
|
add2(results, "pass", `historian.model "${historianModel}" has thinking_level "${historianThinkingLevel}" configured`);
|
|
44787
45830
|
}
|
|
44788
45831
|
const storageDir = getMagicContextStorageDir();
|
|
44789
|
-
const dbPath =
|
|
44790
|
-
const existedBeforeOpen =
|
|
45832
|
+
const dbPath = join31(storageDir, "context.db");
|
|
45833
|
+
const existedBeforeOpen = existsSync33(dbPath);
|
|
44791
45834
|
if (existedBeforeOpen)
|
|
44792
45835
|
add2(results, "pass", `Shared context DB exists at ${dbPath}`);
|
|
44793
45836
|
else
|
|
@@ -44924,10 +45967,10 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
44924
45967
|
add2(results, "pass", "Pi extension cache clean (no stale cached package found)");
|
|
44925
45968
|
}
|
|
44926
45969
|
const logPath = getMagicContextLogPath2("pi");
|
|
44927
|
-
if (
|
|
44928
|
-
const stat =
|
|
45970
|
+
if (existsSync33(logPath)) {
|
|
45971
|
+
const stat = statSync14(logPath);
|
|
44929
45972
|
const sizeKb = (stat.size / 1024).toFixed(0);
|
|
44930
|
-
const lines =
|
|
45973
|
+
const lines = readFileSync25(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
44931
45974
|
add2(results, "info", `Log file: ${logPath} (${sizeKb} KB)`);
|
|
44932
45975
|
const lastLine = lines.at(-1);
|
|
44933
45976
|
add2(results, "info", `Last plugin log line: ${lastLine ? sanitizeDiagnosticText(lastLine) : "<empty log>"}`);
|
|
@@ -44962,12 +46005,12 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
44962
46005
|
return { results, repairPlan, ...summarize(results) };
|
|
44963
46006
|
}
|
|
44964
46007
|
function writeDefaultMagicContextConfig(path6) {
|
|
44965
|
-
|
|
46008
|
+
mkdirSync11(dirname17(path6), { recursive: true });
|
|
44966
46009
|
const config2 = {
|
|
44967
46010
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
44968
46011
|
...MagicContextConfigSchema.parse({})
|
|
44969
46012
|
};
|
|
44970
|
-
writeFileAtomic(path6, `${
|
|
46013
|
+
writeFileAtomic(path6, `${import_comment_json14.stringify(config2, null, 2)}
|
|
44971
46014
|
`);
|
|
44972
46015
|
}
|
|
44973
46016
|
function repair2(plan, prompts) {
|
|
@@ -44984,7 +46027,7 @@ function repair2(plan, prompts) {
|
|
|
44984
46027
|
}
|
|
44985
46028
|
if (plan.writeUserConfig) {
|
|
44986
46029
|
const configPath = getPiUserConfigPath();
|
|
44987
|
-
if (!
|
|
46030
|
+
if (!existsSync33(configPath)) {
|
|
44988
46031
|
try {
|
|
44989
46032
|
writeDefaultMagicContextConfig(configPath);
|
|
44990
46033
|
prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
|
|
@@ -45104,7 +46147,7 @@ async function runDoctor3(options = {}) {
|
|
|
45104
46147
|
const v22Result = await runV22BackfillCommands({
|
|
45105
46148
|
name: "Pi",
|
|
45106
46149
|
openDatabase: (readonly2 = true) => {
|
|
45107
|
-
const dbPath =
|
|
46150
|
+
const dbPath = join31(getMagicContextStorageDir(), "context.db");
|
|
45108
46151
|
v22Db = readonly2 ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
45109
46152
|
return v22Db;
|
|
45110
46153
|
},
|
|
@@ -45169,7 +46212,7 @@ function parseDoctorArgs(args) {
|
|
|
45169
46212
|
function doctor(args = []) {
|
|
45170
46213
|
return runDoctor3(parseDoctorArgs(args));
|
|
45171
46214
|
}
|
|
45172
|
-
var
|
|
46215
|
+
var import_comment_json14, PACKAGE_NAME2 = "@cortexkit/pi-magic-context", MIN_PI_VERSION = "0.74.0", ROW_COUNT_TABLES2, DEFAULT_DEPS5;
|
|
45173
46216
|
var init_doctor_pi = __esm(async () => {
|
|
45174
46217
|
init_migrate_config_location();
|
|
45175
46218
|
init_project_security();
|
|
@@ -45194,14 +46237,14 @@ var init_doctor_pi = __esm(async () => {
|
|
|
45194
46237
|
init_storage_versions(),
|
|
45195
46238
|
init_v22_backfill_commands()
|
|
45196
46239
|
]);
|
|
45197
|
-
|
|
46240
|
+
import_comment_json14 = __toESM(require_src3(), 1);
|
|
45198
46241
|
ROW_COUNT_TABLES2 = ["tags", "compartments", "memories", "notes", "dream_runs"];
|
|
45199
|
-
|
|
46242
|
+
DEFAULT_DEPS5 = {
|
|
45200
46243
|
prompts: promptIO,
|
|
45201
46244
|
collectDiagnostics: collectDiagnostics2,
|
|
45202
46245
|
detectPiBinary,
|
|
45203
46246
|
getPiVersion,
|
|
45204
|
-
getLatestNpmVersion: () => getLatestNpmVersion(
|
|
46247
|
+
getLatestNpmVersion: () => getLatestNpmVersion(PACKAGE_NAME2),
|
|
45205
46248
|
selfVersion: selfVersion2,
|
|
45206
46249
|
probeEmbeddingEndpoint,
|
|
45207
46250
|
openExistingContextDatabase,
|
|
@@ -45216,8 +46259,8 @@ var exports_doctor = {};
|
|
|
45216
46259
|
__export(exports_doctor, {
|
|
45217
46260
|
runDoctor: () => runDoctor4
|
|
45218
46261
|
});
|
|
45219
|
-
import { existsSync as
|
|
45220
|
-
import { join as
|
|
46262
|
+
import { existsSync as existsSync34, rmSync as rmSync5 } from "node:fs";
|
|
46263
|
+
import { join as join32 } from "node:path";
|
|
45221
46264
|
async function runDoctor4(options) {
|
|
45222
46265
|
if (options.clear)
|
|
45223
46266
|
return runClear();
|
|
@@ -45235,7 +46278,7 @@ async function runDoctor4(options) {
|
|
|
45235
46278
|
const result = await runV22BackfillCommands({
|
|
45236
46279
|
name: "Magic Context",
|
|
45237
46280
|
openDatabase: (readonly2 = true) => {
|
|
45238
|
-
const dbPath =
|
|
46281
|
+
const dbPath = join32(getMagicContextStorageDir(), "context.db");
|
|
45239
46282
|
v22Db = readonly2 ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
45240
46283
|
return v22Db;
|
|
45241
46284
|
},
|
|
@@ -45248,6 +46291,27 @@ async function runDoctor4(options) {
|
|
|
45248
46291
|
if (result.handled)
|
|
45249
46292
|
return result.exitCode;
|
|
45250
46293
|
}
|
|
46294
|
+
const { sweepPendingMigrations: sweepPendingMigrations2, formatMigrationSweepLines: formatMigrationSweepLines2 } = await init_migrate().then(() => exports_migrate);
|
|
46295
|
+
const sweepDbPath = join32(getMagicContextStorageDir(), "context.db");
|
|
46296
|
+
let sweepDb = null;
|
|
46297
|
+
try {
|
|
46298
|
+
sweepDb = openExistingContextDatabaseForMutation(sweepDbPath);
|
|
46299
|
+
} catch {}
|
|
46300
|
+
if (sweepDb !== null) {
|
|
46301
|
+
try {
|
|
46302
|
+
const report = sweepPendingMigrations2(sweepDb);
|
|
46303
|
+
for (const line of formatMigrationSweepLines2(report)) {
|
|
46304
|
+
if (line.startsWith("LOST"))
|
|
46305
|
+
log2.error(line);
|
|
46306
|
+
else
|
|
46307
|
+
log2.info(line);
|
|
46308
|
+
}
|
|
46309
|
+
} catch (error51) {
|
|
46310
|
+
log2.warn(`Session-migration recovery sweep failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
46311
|
+
} finally {
|
|
46312
|
+
sweepDb.close();
|
|
46313
|
+
}
|
|
46314
|
+
}
|
|
45251
46315
|
let anyFailure = false;
|
|
45252
46316
|
for (const adapter of adapters) {
|
|
45253
46317
|
log2.step(`Running doctor for ${adapter.displayName}…`);
|
|
@@ -45324,7 +46388,7 @@ async function runClear() {
|
|
|
45324
46388
|
const s = spinner2();
|
|
45325
46389
|
s.start(`Clearing ${item.path}`);
|
|
45326
46390
|
try {
|
|
45327
|
-
if (
|
|
46391
|
+
if (existsSync34(item.path)) {
|
|
45328
46392
|
rmSync5(item.path, { recursive: true, force: true });
|
|
45329
46393
|
}
|
|
45330
46394
|
s.stop(`Cleared ${item.path}`);
|
|
@@ -45340,9 +46404,9 @@ async function runClear() {
|
|
|
45340
46404
|
function formatSize(bytes) {
|
|
45341
46405
|
if (bytes < 1024)
|
|
45342
46406
|
return `${bytes} B`;
|
|
45343
|
-
if (bytes <
|
|
46407
|
+
if (bytes < 1048576)
|
|
45344
46408
|
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
45345
|
-
if (bytes <
|
|
46409
|
+
if (bytes < 1073741824)
|
|
45346
46410
|
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
45347
46411
|
return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
45348
46412
|
}
|
|
@@ -45470,12 +46534,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
45470
46534
|
console.error("Usage: magic-context doctor drain-authority <project>");
|
|
45471
46535
|
return 1;
|
|
45472
46536
|
}
|
|
45473
|
-
const [{ runDoctorDrainAuthority: runDoctorDrainAuthority2 }, { getMagicContextStorageDir: getMagicContextStorageDir2 }, { join:
|
|
46537
|
+
const [{ runDoctorDrainAuthority: runDoctorDrainAuthority2 }, { getMagicContextStorageDir: getMagicContextStorageDir2 }, { join: join33 }] = await Promise.all([
|
|
45474
46538
|
init_doctor_authority().then(() => exports_doctor_authority),
|
|
45475
46539
|
Promise.resolve().then(() => (init_data_path(), exports_data_path)),
|
|
45476
46540
|
import("node:path")
|
|
45477
46541
|
]);
|
|
45478
|
-
return runDoctorDrainAuthority2(projectRoot,
|
|
46542
|
+
return runDoctorDrainAuthority2(projectRoot, join33(getMagicContextStorageDir2(), "context.db"));
|
|
45479
46543
|
}
|
|
45480
46544
|
if (rest[0] === "merge-identity") {
|
|
45481
46545
|
const { runMergeIdentityCli: runMergeIdentityCli2 } = await init_doctor_merge_identity().then(() => exports_doctor_merge_identity);
|