@cortexkit/magic-context 0.43.2 → 0.44.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 +1162 -692
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -13037,6 +13037,15 @@ function extraCliCandidates(d) {
|
|
|
13037
13037
|
join11(d.home, ".volta", "bin", "opencode")
|
|
13038
13038
|
];
|
|
13039
13039
|
}
|
|
13040
|
+
function openChamberCliCandidates(d) {
|
|
13041
|
+
if (d.platform !== "darwin")
|
|
13042
|
+
return [];
|
|
13043
|
+
const bundled = ["Contents", "Resources", "opencode-cli", "opencode"];
|
|
13044
|
+
return [
|
|
13045
|
+
join11("/Applications", "OpenChamber.app", ...bundled),
|
|
13046
|
+
join11(d.home, "Applications", "OpenChamber.app", ...bundled)
|
|
13047
|
+
];
|
|
13048
|
+
}
|
|
13040
13049
|
function canonicalPath(d, path) {
|
|
13041
13050
|
try {
|
|
13042
13051
|
return d.realpath ? d.realpath(path) : realpathSync(path);
|
|
@@ -13098,6 +13107,11 @@ function detectOpenCodeInstallations(deps) {
|
|
|
13098
13107
|
addCandidate(installations, seenRealpaths, d, candidate, "PATH", "cli");
|
|
13099
13108
|
}
|
|
13100
13109
|
}
|
|
13110
|
+
for (const candidate of openChamberCliCandidates(d)) {
|
|
13111
|
+
if (d.isExecutable(candidate)) {
|
|
13112
|
+
addCandidate(installations, seenRealpaths, d, candidate, "openchamber", "cli");
|
|
13113
|
+
}
|
|
13114
|
+
}
|
|
13101
13115
|
for (const appId of OPENCODE_DESKTOP_APP_IDS) {
|
|
13102
13116
|
const marker = join11(desktopUserDataDir(d, appId), OPENCODE_DESKTOP_SETTINGS_FILE);
|
|
13103
13117
|
if (d.exists(marker)) {
|
|
@@ -13171,6 +13185,17 @@ function describeOpenCodeInstallations(installations, deps = {}) {
|
|
|
13171
13185
|
active: index === 0
|
|
13172
13186
|
}));
|
|
13173
13187
|
}
|
|
13188
|
+
function selectOpenCodeStoreHost(reports, generationOf) {
|
|
13189
|
+
const active = reports[0];
|
|
13190
|
+
if (!active)
|
|
13191
|
+
return null;
|
|
13192
|
+
const hasVersion = (report) => /\d/.test(report.version);
|
|
13193
|
+
if (!hasVersion(active) || generationOf(active.version) === "v2") {
|
|
13194
|
+
return { host: active, shadowed: false };
|
|
13195
|
+
}
|
|
13196
|
+
const v2 = reports.find((report) => report.kind === "cli" && hasVersion(report) && generationOf(report.version) === "v2");
|
|
13197
|
+
return v2 ? { host: v2, shadowed: true } : { host: active, shadowed: false };
|
|
13198
|
+
}
|
|
13174
13199
|
function getAvailableModels2(binary) {
|
|
13175
13200
|
const output = runOpenCode(["models"], binary);
|
|
13176
13201
|
if (output === null)
|
|
@@ -15523,6 +15548,12 @@ var init_redaction = __esm(() => {
|
|
|
15523
15548
|
// ../plugin/src/shared/logger.ts
|
|
15524
15549
|
import * as fs from "node:fs";
|
|
15525
15550
|
import * as path2 from "node:path";
|
|
15551
|
+
function boundBuffer() {
|
|
15552
|
+
while (bufferedBytes > MAX_BUFFERED_BYTES && buffer.length > 0) {
|
|
15553
|
+
bufferedBytes -= Buffer.byteLength(buffer.shift() ?? "");
|
|
15554
|
+
droppedLines++;
|
|
15555
|
+
}
|
|
15556
|
+
}
|
|
15526
15557
|
function recordSwallowedWrite(error) {
|
|
15527
15558
|
try {
|
|
15528
15559
|
swallowedWriteCount++;
|
|
@@ -15605,12 +15636,12 @@ function flush() {
|
|
|
15605
15636
|
clearTimeout(flushTimer);
|
|
15606
15637
|
flushTimer = null;
|
|
15607
15638
|
}
|
|
15608
|
-
if (buffer.length === 0)
|
|
15639
|
+
if (buffer.length === 0 && droppedLines === 0)
|
|
15609
15640
|
return;
|
|
15610
|
-
const
|
|
15611
|
-
|
|
15641
|
+
const notice = droppedLines ? `[${new Date().toISOString()}] [magic-context][global] logger dropped ${droppedLines} ${droppedLines === 1 ? "line" : "lines"}: buffer exceeded ${MAX_BUFFERED_BYTES} bytes while writes were pending
|
|
15642
|
+
` : "";
|
|
15612
15643
|
try {
|
|
15613
|
-
const data = capLogData(
|
|
15644
|
+
const data = capLogData(notice + buffer.join(""));
|
|
15614
15645
|
const logFile = getMagicContextLogPath();
|
|
15615
15646
|
ensureDir4(logFile);
|
|
15616
15647
|
let currentSize = getCurrentLogSize(logFile);
|
|
@@ -15620,6 +15651,9 @@ function flush() {
|
|
|
15620
15651
|
currentSize = 0;
|
|
15621
15652
|
}
|
|
15622
15653
|
fs.appendFileSync(logFile, data, { encoding: "utf8", mode: 384 });
|
|
15654
|
+
buffer = [];
|
|
15655
|
+
bufferedBytes = 0;
|
|
15656
|
+
droppedLines = 0;
|
|
15623
15657
|
activeLogFile = logFile;
|
|
15624
15658
|
activeLogSize = currentSize + dataSize;
|
|
15625
15659
|
flushesSinceSizeCheck++;
|
|
@@ -15628,6 +15662,7 @@ function flush() {
|
|
|
15628
15662
|
activeLogSize = null;
|
|
15629
15663
|
flushesSinceSizeCheck = 0;
|
|
15630
15664
|
recordSwallowedWrite(error);
|
|
15665
|
+
boundBuffer();
|
|
15631
15666
|
}
|
|
15632
15667
|
}
|
|
15633
15668
|
function scheduleFlush() {
|
|
@@ -15645,8 +15680,11 @@ function log3(message, data) {
|
|
|
15645
15680
|
const timestamp = new Date().toISOString();
|
|
15646
15681
|
const serialized = data === undefined ? "" : data instanceof Error ? ` ${sanitizeDiagnosticText(`${data.message}${data.stack ? `
|
|
15647
15682
|
${data.stack}` : ""}`)}` : ` ${JSON.stringify(sanitizeConfigValue(data))}`;
|
|
15648
|
-
|
|
15649
|
-
|
|
15683
|
+
const line = `[${timestamp}] ${sanitizeDiagnosticText(message)}${serialized}
|
|
15684
|
+
`;
|
|
15685
|
+
buffer.push(line);
|
|
15686
|
+
bufferedBytes += Buffer.byteLength(line);
|
|
15687
|
+
boundBuffer();
|
|
15650
15688
|
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
15651
15689
|
flush();
|
|
15652
15690
|
} else {
|
|
@@ -15654,11 +15692,12 @@ ${data.stack}` : ""}`)}` : ` ${JSON.stringify(sanitizeConfigValue(data))}`;
|
|
|
15654
15692
|
}
|
|
15655
15693
|
} catch {}
|
|
15656
15694
|
}
|
|
15657
|
-
var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, MAX_LOG_FILE_BYTES, SIZE_CHECK_INTERVAL_FLUSHES = 64, activeLogFile = null, activeLogSize = null, flushesSinceSizeCheck = 0, swallowedWriteCount = 0, lastErrorMessage = null, lastErrorTime = null;
|
|
15695
|
+
var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, MAX_BUFFERED_BYTES, bufferedBytes = 0, droppedLines = 0, MAX_LOG_FILE_BYTES, SIZE_CHECK_INTERVAL_FLUSHES = 64, activeLogFile = null, activeLogSize = null, flushesSinceSizeCheck = 0, swallowedWriteCount = 0, lastErrorMessage = null, lastErrorTime = null;
|
|
15658
15696
|
var init_logger = __esm(() => {
|
|
15659
15697
|
init_data_path();
|
|
15660
15698
|
init_redaction();
|
|
15661
15699
|
buffer = [];
|
|
15700
|
+
MAX_BUFFERED_BYTES = 1024 * 1024;
|
|
15662
15701
|
MAX_LOG_FILE_BYTES = 32 * 1024 * 1024;
|
|
15663
15702
|
if (!isTestEnv) {
|
|
15664
15703
|
process.on("exit", flush);
|
|
@@ -21370,6 +21409,7 @@ var init_magic_context = __esm(() => {
|
|
|
21370
21409
|
maxTokens: true
|
|
21371
21410
|
});
|
|
21372
21411
|
DreamerConfigSchema = AgentMetadataSchema.extend({
|
|
21412
|
+
runner: _enum(["broca", "host"]).optional().describe(`Which side runs the dreamer completions the Rust module routes (classify-memories) in Rust transform mode: "host" runs them on this process's carrier, "broca" routes them to the Broca module. When unset, historian.runner applies, and when that is unset too the harness decides the same way it does for the historian. User-level config only.`),
|
|
21373
21413
|
opencode: DreamerOpenCodeHarnessBlockSchema.optional(),
|
|
21374
21414
|
pi: DreamerPiHarnessBlockSchema.optional(),
|
|
21375
21415
|
omp: DreamerOmpHarnessBlockSchema.optional(),
|
|
@@ -21380,12 +21420,16 @@ var init_magic_context = __esm(() => {
|
|
|
21380
21420
|
opencode: OpenCodeHarnessBlockSchema.optional(),
|
|
21381
21421
|
pi: PiHarnessBlockSchema.optional(),
|
|
21382
21422
|
omp: OmpHarnessBlockSchema.optional(),
|
|
21423
|
+
runner: _enum(["broca", "host"]).optional().describe('Which side runs the historian completion in Rust transform mode: "host" queues it for this process to run on the configured historian model, "broca" routes it to the Broca module. When unset the harness decides: OpenCode 1 and OpenCode 2 use "host", Claude Code (through the Thalamus gateway, which has no host to run a completion) uses "broca". User-level config only — it decides whose provider account pays for the call.'),
|
|
21424
|
+
host_runner: object({
|
|
21425
|
+
enabled: boolean2().optional().describe("Whether this process answers historian runs queued for a claimant (default true). Setting it to false stops the pull loop without changing historian.runner, so an operator can take one machine out of the lane and leave the queued runs for another claimant or for the runner setting to be changed deliberately.")
|
|
21426
|
+
}).optional().describe("Controls for this process's historian pull loop, which answers runs the Rust module queues for the host runner (`historian.runner: \"host\"`, or unset on OpenCode 1 and OpenCode 2). User-level config only — it decides whether this machine's provider account is spent on folds."),
|
|
21383
21427
|
two_pass: boolean2().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
|
|
21384
21428
|
disallowed_tools: array(_enum(["*", "read", "aft_outline", "aft_zoom", "aft_search"])).default([]).describe(`OpenCode only. Tools to REMOVE from the historian's default allow-list [read, aft_outline, aft_zoom, aft_search]. Applies to both historian and historian-editor agents. Use ["*"] to strip all tool definitions from the model request — this prevents weak instruction-following models (e.g. mistral-small-latest) from entering tool-calling loops. Individual tool names remove just that tool. Note: a user-supplied historian.permission override can re-allow a tool that disallowed_tools removed — disallowed_tools sets the baseline, permission overrides take precedence. (default: [])`)
|
|
21385
21429
|
}).optional();
|
|
21386
21430
|
EmbeddingFallbackProviderSchema = _enum(["local", "openai-compatible", "off"]);
|
|
21387
21431
|
BaseEmbeddingConfigSchema = object({
|
|
21388
|
-
provider: _enum(["local", "openai-compatible", "off", "synapse"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'synapse' uses the certified local Synapse lane with an explicit fallback provider, and 'off' disables embeddings."),
|
|
21432
|
+
provider: _enum(["local", "openai-compatible", "off", "synapse"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'synapse' uses the certified local Synapse lane with an explicit fallback provider, and 'off' disables embeddings. Session history is embedded for semantic ctx_search whenever the provider is not 'off', regardless of memory.enabled; memories are embedded only while memory.enabled is true."),
|
|
21389
21433
|
fallback_provider: EmbeddingFallbackProviderSchema.optional().describe("Fallback provider for the Synapse lane. Required when provider is 'synapse'; local, openai-compatible, and off are valid."),
|
|
21390
21434
|
model: string2().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
|
|
21391
21435
|
endpoint: string2().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
@@ -21566,7 +21610,7 @@ var init_magic_context = __esm(() => {
|
|
|
21566
21610
|
min_chars: number2().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
|
|
21567
21611
|
}).default({ enabled: false, min_chars: 500 }).describe("Age-tier caveman compression for long user/assistant text parts. Active for primary sessions when enabled; never for subagents. Oldest 20% of eligible tags (outside protected tail) go to ultra, next 20% to full, next 20% to lite, newest 40% untouched. Graduated from experimental.caveman_text_compression; opt-in, default off (lossy)."),
|
|
21568
21612
|
memory: object({
|
|
21569
|
-
enabled: boolean2().default(true).describe("Enable cross-session memory (default: true)"),
|
|
21613
|
+
enabled: boolean2().default(true).describe("Enable cross-session memory (default: true). Does not affect history embedding or semantic ctx_search over session history; set embedding.provider to 'off' to stop all embedding."),
|
|
21570
21614
|
injection_budget_tokens: number2().min(500).max(20000).default(4000).describe("Token budget for memory injection on session start (min: 500, max: 20000, default: 4000)"),
|
|
21571
21615
|
auto_promote: boolean2().default(true).describe("Automatically promote eligible session facts into memory (default: true)"),
|
|
21572
21616
|
retrieval_count_promotion_threshold: number2().min(1).default(3).describe("retrieval_count threshold for promoting memory to permanent status (min: 1, default: 3)"),
|
|
@@ -22015,6 +22059,11 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
22015
22059
|
warnings.push(`Ignoring ${removed.map((path) => `historian.${path}`).join(", ")} from project config ` + "(security: historian model selection is user-level only; a repository cannot force extra compaction cost).");
|
|
22016
22060
|
}
|
|
22017
22061
|
}
|
|
22062
|
+
const dreamer = projectRaw.dreamer;
|
|
22063
|
+
if (isPlainObject3(dreamer) && "runner" in dreamer) {
|
|
22064
|
+
delete dreamer.runner;
|
|
22065
|
+
warnings.push("Ignoring dreamer.runner from project config (security: which process and provider account run dreamer completions is a user-level setting).");
|
|
22066
|
+
}
|
|
22018
22067
|
const mural = projectRaw.mural;
|
|
22019
22068
|
if (isPlainObject3(mural) && "model" in mural) {
|
|
22020
22069
|
delete mural.model;
|
|
@@ -22196,7 +22245,11 @@ var init_project_security = __esm(() => {
|
|
|
22196
22245
|
init_magic_context();
|
|
22197
22246
|
HIDDEN_AGENT_KEYS = ["historian", "dreamer"];
|
|
22198
22247
|
HARNESS_KEYS = PER_HARNESS_MODEL_KEYS;
|
|
22199
|
-
HISTORIAN_USER_ONLY_FIELDS =
|
|
22248
|
+
HISTORIAN_USER_ONLY_FIELDS = [
|
|
22249
|
+
...PER_HARNESS_MIGRATION_INVENTORY.historian.migrated_execution,
|
|
22250
|
+
"runner",
|
|
22251
|
+
"host_runner"
|
|
22252
|
+
];
|
|
22200
22253
|
PROMPT_SURFACE_USER_ONLY_FIELDS = ["guidance_override_path", "tool_descriptions"];
|
|
22201
22254
|
AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools"];
|
|
22202
22255
|
EMBEDDING_USER_ONLY_FIELDS = [
|
|
@@ -22511,6 +22564,25 @@ function redactConfigValue(value) {
|
|
|
22511
22564
|
function formatProtectedTokensBelowMinWarning(value) {
|
|
22512
22565
|
return `protected_tokens is a token floor (minimum ${PROTECTED_TOKENS_MIN}, default derived from the context window); ${value} looks like the old protected_tags count. Remove the key to use the default, or set a token count such as 16000.`;
|
|
22513
22566
|
}
|
|
22567
|
+
function misplacedAgentModelWarnings(rawConfig) {
|
|
22568
|
+
const warnings = [];
|
|
22569
|
+
for (const agent of ["historian", "dreamer"]) {
|
|
22570
|
+
const block = rawConfig[agent];
|
|
22571
|
+
if (!block || typeof block !== "object" || Array.isArray(block))
|
|
22572
|
+
continue;
|
|
22573
|
+
const record = block;
|
|
22574
|
+
if (!Object.hasOwn(record, "model"))
|
|
22575
|
+
continue;
|
|
22576
|
+
const harnessWithModel = MODEL_HARNESS_BLOCKS.find((harness) => {
|
|
22577
|
+
const sub = record[harness];
|
|
22578
|
+
return sub !== null && typeof sub === "object" && !Array.isArray(sub) && Object.hasOwn(sub, "model");
|
|
22579
|
+
});
|
|
22580
|
+
if (harnessWithModel)
|
|
22581
|
+
continue;
|
|
22582
|
+
warnings.push(`${agent}.model is not read: the ${agent} model is resolved per harness, so it has to be ${agent}.opencode.model (OpenCode 1 and 2), ${agent}.pi.model, or ${agent}.omp.model. As written the ${agent} resolves to no models and never runs.`);
|
|
22583
|
+
}
|
|
22584
|
+
return warnings;
|
|
22585
|
+
}
|
|
22514
22586
|
function warnProtectedTagsDeprecationOnce() {
|
|
22515
22587
|
if (!warnedProtectedTagsDeprecation) {
|
|
22516
22588
|
warnedProtectedTagsDeprecation = true;
|
|
@@ -22524,6 +22596,7 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
22524
22596
|
warnProtectedTagsDeprecationOnce();
|
|
22525
22597
|
preMigrationWarnings.push("protected_tags is deprecated and ignored; use protected_tokens instead.");
|
|
22526
22598
|
}
|
|
22599
|
+
preMigrationWarnings.push(...misplacedAgentModelWarnings(rawConfig));
|
|
22527
22600
|
const migratedExperimental = migrateLegacyExperimental(configWithoutRemovedAgent, preMigrationWarnings);
|
|
22528
22601
|
const migratedDreamer = migrateDreamerV2(migratedExperimental, preMigrationWarnings);
|
|
22529
22602
|
const migrated = migrateLegacyAgentEnabledInMemory(migratedDreamer, preMigrationWarnings);
|
|
@@ -22804,7 +22877,7 @@ function loadPluginConfigDetailed(directory, applyRuntimeGlobals = true) {
|
|
|
22804
22877
|
cacheTtlConfigured
|
|
22805
22878
|
};
|
|
22806
22879
|
}
|
|
22807
|
-
var warnedProtectedTagsDeprecation = false;
|
|
22880
|
+
var warnedProtectedTagsDeprecation = false, MODEL_HARNESS_BLOCKS;
|
|
22808
22881
|
var init_config = __esm(() => {
|
|
22809
22882
|
init_config_diagnostics();
|
|
22810
22883
|
init_jsonc_parser();
|
|
@@ -22819,6 +22892,7 @@ var init_config = __esm(() => {
|
|
|
22819
22892
|
init_removed_agent_config();
|
|
22820
22893
|
init_magic_context();
|
|
22821
22894
|
init_variable();
|
|
22895
|
+
MODEL_HARNESS_BLOCKS = ["opencode", "pi", "omp"];
|
|
22822
22896
|
});
|
|
22823
22897
|
|
|
22824
22898
|
// ../plugin/src/shared/opencode-config-dir.ts
|
|
@@ -26747,232 +26821,523 @@ function isRecord3(value) {
|
|
|
26747
26821
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26748
26822
|
}
|
|
26749
26823
|
|
|
26750
|
-
// ../plugin/src/
|
|
26751
|
-
|
|
26752
|
-
|
|
26753
|
-
function getDefaultSubcConnectionFile() {
|
|
26754
|
-
return join17(getDataDir(), "cortexkit", "run", "subc-connection.json");
|
|
26755
|
-
}
|
|
26756
|
-
function errorChainSome(error, predicate) {
|
|
26757
|
-
let current = error;
|
|
26758
|
-
const seen = new Set;
|
|
26759
|
-
while (isRecord3(current) && !seen.has(current)) {
|
|
26760
|
-
seen.add(current);
|
|
26761
|
-
if (predicate(current))
|
|
26762
|
-
return true;
|
|
26763
|
-
current = current.cause;
|
|
26764
|
-
}
|
|
26765
|
-
return false;
|
|
26766
|
-
}
|
|
26767
|
-
function isStaleOrDeadRouteFailure(error) {
|
|
26768
|
-
return errorChainSome(error, (current) => {
|
|
26769
|
-
const code = typeof current.code === "string" ? current.code : "";
|
|
26770
|
-
const name = typeof current.name === "string" ? current.name : "";
|
|
26771
|
-
const message = typeof current.message === "string" ? current.message : "";
|
|
26772
|
-
return [
|
|
26773
|
-
"stale_route_handle",
|
|
26774
|
-
"route_closed",
|
|
26775
|
-
"unknown_channel",
|
|
26776
|
-
"unrecognized_channel",
|
|
26777
|
-
"route_gone"
|
|
26778
|
-
].includes(code) || name === "StaleRouteHandleError" || /route handle \(\d+,\s*\d+\) is not live on the current connection/i.test(message) || /\b(?:unknown|unrecognized) channel\b/i.test(message);
|
|
26779
|
-
});
|
|
26780
|
-
}
|
|
26781
|
-
function isDeadlineFailure(error) {
|
|
26782
|
-
if (error instanceof SocketTimeoutError)
|
|
26783
|
-
return true;
|
|
26784
|
-
return errorChainSome(error, (current) => {
|
|
26785
|
-
const code = typeof current.code === "string" ? current.code : "";
|
|
26786
|
-
return ["ETIMEDOUT", "request_deadline", "deadline_exceeded_no_drop_observed"].includes(code);
|
|
26787
|
-
});
|
|
26788
|
-
}
|
|
26789
|
-
function isConnectionFailure(error) {
|
|
26790
|
-
if (error instanceof SocketClosedError || error instanceof SocketTimeoutError || error instanceof StaleRouteHandleError || isConsumerReconnectTransient(error) || isStaleOrDeadRouteFailure(error)) {
|
|
26791
|
-
return true;
|
|
26792
|
-
}
|
|
26793
|
-
return errorChainSome(error, (current) => {
|
|
26794
|
-
const code = typeof current.code === "string" ? current.code : "";
|
|
26795
|
-
const message = typeof current.message === "string" ? current.message : "";
|
|
26796
|
-
return [
|
|
26797
|
-
"ENOENT",
|
|
26798
|
-
"ECONNREFUSED",
|
|
26799
|
-
"ECONNRESET",
|
|
26800
|
-
"EPIPE",
|
|
26801
|
-
"ETIMEDOUT",
|
|
26802
|
-
"request_deadline",
|
|
26803
|
-
"deadline_exceeded_no_drop_observed",
|
|
26804
|
-
"connection_dropped",
|
|
26805
|
-
"SUBC_CONNECTION_BACKOFF"
|
|
26806
|
-
].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
|
|
26807
|
-
});
|
|
26808
|
-
}
|
|
26809
|
-
function routeOpenWithoutAmbientConsumerIdentity(client, target, identity, options = {}) {
|
|
26810
|
-
return client.routeOpen(target, identity, {
|
|
26811
|
-
...options,
|
|
26812
|
-
consumerIdentity: null
|
|
26813
|
-
});
|
|
26824
|
+
// ../plugin/src/shared/user-facing-codes.ts
|
|
26825
|
+
function userFacingFailureCode(key) {
|
|
26826
|
+
return USER_FACING_FAILURES[key].code;
|
|
26814
26827
|
}
|
|
26815
|
-
|
|
26816
|
-
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
|
|
26839
|
-
|
|
26840
|
-
|
|
26841
|
-
|
|
26842
|
-
|
|
26843
|
-
|
|
26844
|
-
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
|
|
26849
|
-
|
|
26850
|
-
|
|
26851
|
-
|
|
26852
|
-
|
|
26853
|
-
|
|
26854
|
-
|
|
26855
|
-
|
|
26856
|
-
|
|
26857
|
-
|
|
26858
|
-
|
|
26859
|
-
|
|
26860
|
-
|
|
26861
|
-
|
|
26862
|
-
|
|
26863
|
-
|
|
26864
|
-
|
|
26865
|
-
|
|
26866
|
-
|
|
26867
|
-
|
|
26868
|
-
|
|
26869
|
-
|
|
26870
|
-
|
|
26871
|
-
|
|
26872
|
-
|
|
26873
|
-
|
|
26874
|
-
|
|
26875
|
-
|
|
26876
|
-
|
|
26877
|
-
|
|
26878
|
-
|
|
26879
|
-
|
|
26880
|
-
|
|
26881
|
-
|
|
26882
|
-
|
|
26883
|
-
|
|
26884
|
-
|
|
26885
|
-
|
|
26886
|
-
|
|
26887
|
-
|
|
26888
|
-
|
|
26889
|
-
|
|
26890
|
-
|
|
26891
|
-
|
|
26892
|
-
|
|
26893
|
-
|
|
26894
|
-
|
|
26895
|
-
|
|
26896
|
-
|
|
26897
|
-
|
|
26898
|
-
|
|
26899
|
-
|
|
26900
|
-
|
|
26901
|
-
|
|
26902
|
-
|
|
26903
|
-
|
|
26904
|
-
|
|
26905
|
-
|
|
26906
|
-
|
|
26907
|
-
|
|
26908
|
-
|
|
26909
|
-
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
26917
|
-
|
|
26918
|
-
|
|
26919
|
-
|
|
26920
|
-
|
|
26921
|
-
|
|
26922
|
-
|
|
26923
|
-
|
|
26924
|
-
|
|
26925
|
-
|
|
26926
|
-
|
|
26927
|
-
|
|
26928
|
-
|
|
26929
|
-
|
|
26930
|
-
|
|
26931
|
-
|
|
26932
|
-
|
|
26933
|
-
|
|
26934
|
-
|
|
26935
|
-
|
|
26936
|
-
|
|
26937
|
-
|
|
26938
|
-
|
|
26939
|
-
|
|
26940
|
-
|
|
26941
|
-
|
|
26942
|
-
|
|
26943
|
-
|
|
26944
|
-
|
|
26945
|
-
|
|
26946
|
-
|
|
26947
|
-
|
|
26948
|
-
|
|
26949
|
-
|
|
26950
|
-
|
|
26951
|
-
|
|
26952
|
-
|
|
26953
|
-
|
|
26954
|
-
|
|
26955
|
-
|
|
26956
|
-
|
|
26957
|
-
|
|
26958
|
-
|
|
26959
|
-
|
|
26960
|
-
|
|
26961
|
-
|
|
26962
|
-
|
|
26963
|
-
|
|
26964
|
-
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
26969
|
-
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
26973
|
-
|
|
26974
|
-
|
|
26975
|
-
|
|
26828
|
+
var USER_FACING_FAILURES;
|
|
26829
|
+
var init_user_facing_codes = __esm(() => {
|
|
26830
|
+
USER_FACING_FAILURES = {
|
|
26831
|
+
historian_unavailable: {
|
|
26832
|
+
code: "MC-H01",
|
|
26833
|
+
sentence: "History compression could not finish this turn.",
|
|
26834
|
+
action: "It will retry automatically."
|
|
26835
|
+
},
|
|
26836
|
+
hidden_cleanup_unbound: {
|
|
26837
|
+
code: "MC-H02",
|
|
26838
|
+
sentence: "Some finished background sessions could not be removed from this host.",
|
|
26839
|
+
action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
|
|
26840
|
+
},
|
|
26841
|
+
historian_saved_history_misaligned: {
|
|
26842
|
+
code: "MC-H03",
|
|
26843
|
+
sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
|
|
26844
|
+
action: "Run /ctx-recomp to rebuild them."
|
|
26845
|
+
},
|
|
26846
|
+
recomp_unavailable: {
|
|
26847
|
+
code: "MC-R01",
|
|
26848
|
+
sentence: "History compression could not be rebuilt.",
|
|
26849
|
+
action: "Run /ctx-recomp again."
|
|
26850
|
+
},
|
|
26851
|
+
dream_provider_timeout: {
|
|
26852
|
+
code: "MC-D01",
|
|
26853
|
+
sentence: "Memory maintenance took too long to respond.",
|
|
26854
|
+
action: "Run /ctx-dream again."
|
|
26855
|
+
},
|
|
26856
|
+
dream_provider_error: {
|
|
26857
|
+
code: "MC-D02",
|
|
26858
|
+
sentence: "Memory maintenance could not reach its model.",
|
|
26859
|
+
action: "Check the model connection, then run /ctx-dream again."
|
|
26860
|
+
},
|
|
26861
|
+
dream_step_limit: {
|
|
26862
|
+
code: "MC-D10",
|
|
26863
|
+
sentence: "Memory maintenance stopped at its hidden agent step limit.",
|
|
26864
|
+
action: "This task needs less work per run; changing the model connection will not help."
|
|
26865
|
+
},
|
|
26866
|
+
dream_empty_completion: {
|
|
26867
|
+
code: "MC-D03",
|
|
26868
|
+
sentence: "Memory maintenance received no usable response.",
|
|
26869
|
+
action: "Run /ctx-dream again."
|
|
26870
|
+
},
|
|
26871
|
+
dream_no_models: {
|
|
26872
|
+
code: "MC-D04",
|
|
26873
|
+
sentence: "Memory maintenance has no model available.",
|
|
26874
|
+
action: "Check the model settings, then run /ctx-dream again."
|
|
26875
|
+
},
|
|
26876
|
+
dream_child_aborted: {
|
|
26877
|
+
code: "MC-D05",
|
|
26878
|
+
sentence: "Memory maintenance was interrupted.",
|
|
26879
|
+
action: "Run /ctx-dream again."
|
|
26880
|
+
},
|
|
26881
|
+
dream_parse_failed: {
|
|
26882
|
+
code: "MC-D06",
|
|
26883
|
+
sentence: "Memory maintenance could not use the model response.",
|
|
26884
|
+
action: "Run /ctx-dream again."
|
|
26885
|
+
},
|
|
26886
|
+
dream_unknown: {
|
|
26887
|
+
code: "MC-D07",
|
|
26888
|
+
sentence: "Memory maintenance could not finish.",
|
|
26889
|
+
action: "Run /ctx-dream again."
|
|
26890
|
+
},
|
|
26891
|
+
dreamer_tick_blocked: {
|
|
26892
|
+
code: "MC-D09",
|
|
26893
|
+
sentence: "Background maintenance is not running: its last pass stopped before it reached the scheduled tasks.",
|
|
26894
|
+
action: "It is retried automatically; if it keeps happening, check the Magic Context log for the stage that stopped and run `npx @cortexkit/magic-context doctor`."
|
|
26895
|
+
},
|
|
26896
|
+
dream_task_needs_tool_loop: {
|
|
26897
|
+
code: "MC-D08",
|
|
26898
|
+
sentence: "Some memory maintenance tasks need a tool loop this host does not provide.",
|
|
26899
|
+
action: "The remaining tasks still run; the listed ones are skipped on this host."
|
|
26900
|
+
},
|
|
26901
|
+
embedding_substitution_rejected: {
|
|
26902
|
+
code: "MC-E01",
|
|
26903
|
+
sentence: "Search indexing could not use the selected model.",
|
|
26904
|
+
action: "Check the embedding model setting, then run /ctx-embed start again."
|
|
26905
|
+
},
|
|
26906
|
+
embedding_http_error: {
|
|
26907
|
+
code: "MC-E02",
|
|
26908
|
+
sentence: "The search indexing provider refused the request.",
|
|
26909
|
+
action: "Check the provider connection and credentials, then run /ctx-embed start again."
|
|
26910
|
+
},
|
|
26911
|
+
embedding_transport_error: {
|
|
26912
|
+
code: "MC-E03",
|
|
26913
|
+
sentence: "Search indexing could not reach its provider.",
|
|
26914
|
+
action: "Check the connection, then run /ctx-embed start again."
|
|
26915
|
+
},
|
|
26916
|
+
embedding_invalid_envelope: {
|
|
26917
|
+
code: "MC-E04",
|
|
26918
|
+
sentence: "Search indexing received an unsupported response.",
|
|
26919
|
+
action: "Check the embedding endpoint, then run /ctx-embed start again."
|
|
26920
|
+
},
|
|
26921
|
+
embedding_empty_result: {
|
|
26922
|
+
code: "MC-E05",
|
|
26923
|
+
sentence: "Search indexing received no usable result.",
|
|
26924
|
+
action: "Run /ctx-embed start again."
|
|
26925
|
+
},
|
|
26926
|
+
embedding_certification_refusal: {
|
|
26927
|
+
code: "MC-E06",
|
|
26928
|
+
sentence: "Search indexing is not ready for this provider.",
|
|
26929
|
+
action: "Finish the provider setup, or set a fallback provider in the embedding settings, then run /ctx-embed start again."
|
|
26930
|
+
},
|
|
26931
|
+
embedding_credential_required: {
|
|
26932
|
+
code: "MC-E07",
|
|
26933
|
+
sentence: "Search indexing needs provider credentials.",
|
|
26934
|
+
action: "Sign in to the provider, then run /ctx-embed start again."
|
|
26935
|
+
},
|
|
26936
|
+
embedding_local_binding_missing: {
|
|
26937
|
+
code: "MC-E08",
|
|
26938
|
+
sentence: "Local search indexing is unavailable on this system.",
|
|
26939
|
+
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
26940
|
+
},
|
|
26941
|
+
embedding_local_fs_unavailable: {
|
|
26942
|
+
code: "MC-E09",
|
|
26943
|
+
sentence: "Local search indexing cannot save its model files.",
|
|
26944
|
+
action: "Update or reinstall Magic Context, then retry."
|
|
26945
|
+
},
|
|
26946
|
+
embedding_local_download_failure: {
|
|
26947
|
+
code: "MC-E10",
|
|
26948
|
+
sentence: "Local search indexing could not download its model.",
|
|
26949
|
+
action: "Check the network connection, then retry."
|
|
26950
|
+
},
|
|
26951
|
+
embedding_local_runtime_error: {
|
|
26952
|
+
code: "MC-E11",
|
|
26953
|
+
sentence: "Local search indexing could not start.",
|
|
26954
|
+
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
26955
|
+
},
|
|
26956
|
+
embedding_unavailable: {
|
|
26957
|
+
code: "MC-E12",
|
|
26958
|
+
sentence: "Search indexing could not finish.",
|
|
26959
|
+
action: "Run /ctx-embed start again."
|
|
26960
|
+
},
|
|
26961
|
+
status_unavailable: {
|
|
26962
|
+
code: "MC-S01",
|
|
26963
|
+
sentence: "Magic Context status is temporarily unavailable.",
|
|
26964
|
+
action: "Retry /ctx-status in a moment."
|
|
26965
|
+
},
|
|
26966
|
+
transform_update_failed: {
|
|
26967
|
+
code: "MC-S02",
|
|
26968
|
+
sentence: "The last context update did not finish.",
|
|
26969
|
+
action: "Send another message to retry."
|
|
26970
|
+
},
|
|
26971
|
+
configuration_warning: {
|
|
26972
|
+
code: "MC-S03",
|
|
26973
|
+
sentence: "Some configuration settings could not be applied.",
|
|
26974
|
+
action: "Fix the configuration warning shown in /ctx-status, then restart."
|
|
26975
|
+
},
|
|
26976
|
+
status_log_unavailable: {
|
|
26977
|
+
code: "MC-S04",
|
|
26978
|
+
sentence: "Some diagnostic details could not be saved.",
|
|
26979
|
+
action: "Retry /ctx-status in a moment."
|
|
26980
|
+
},
|
|
26981
|
+
memory_writes_paused: {
|
|
26982
|
+
code: "MC-C01",
|
|
26983
|
+
sentence: "Memory writes are paused while the engine syncs.",
|
|
26984
|
+
action: "Retry in a moment."
|
|
26985
|
+
},
|
|
26986
|
+
memory_access_unavailable: {
|
|
26987
|
+
code: "MC-C02",
|
|
26988
|
+
sentence: "Memory access is temporarily unavailable.",
|
|
26989
|
+
action: "Retry in a moment."
|
|
26990
|
+
},
|
|
26991
|
+
note_changes_paused: {
|
|
26992
|
+
code: "MC-C03",
|
|
26993
|
+
sentence: "Note changes are paused while the engine syncs.",
|
|
26994
|
+
action: "Retry in a moment."
|
|
26995
|
+
},
|
|
26996
|
+
note_access_unavailable: {
|
|
26997
|
+
code: "MC-C04",
|
|
26998
|
+
sentence: "Notes are temporarily unavailable.",
|
|
26999
|
+
action: "Retry in a moment."
|
|
27000
|
+
},
|
|
27001
|
+
context_cleanup_paused: {
|
|
27002
|
+
code: "MC-C05",
|
|
27003
|
+
sentence: "Context cleanup is paused while the engine syncs.",
|
|
27004
|
+
action: "Retry in a moment."
|
|
27005
|
+
},
|
|
27006
|
+
partial_history_unavailable: {
|
|
27007
|
+
code: "MC-C06",
|
|
27008
|
+
sentence: "Partial history compression is not available in the current mode.",
|
|
27009
|
+
action: "Run /ctx-recomp without a range."
|
|
27010
|
+
},
|
|
27011
|
+
smart_note_conditions_unavailable: {
|
|
27012
|
+
code: "MC-C08",
|
|
27013
|
+
sentence: "Conditional notes are not available in the current mode.",
|
|
27014
|
+
action: "Save a regular note without a condition."
|
|
27015
|
+
},
|
|
27016
|
+
history_compression_paused: {
|
|
27017
|
+
code: "MC-C09",
|
|
27018
|
+
sentence: "History compression is paused while the engine syncs.",
|
|
27019
|
+
action: "Retry in a moment."
|
|
27020
|
+
},
|
|
27021
|
+
history_compression_needs_message: {
|
|
27022
|
+
code: "MC-C12",
|
|
27023
|
+
sentence: "History compression has not seen this session since Magic Context reconnected.",
|
|
27024
|
+
action: "Send a message in this session first, then run /ctx-wrapup again."
|
|
27025
|
+
},
|
|
27026
|
+
context_service_unavailable: {
|
|
27027
|
+
code: "MC-C10",
|
|
27028
|
+
sentence: "Magic Context is temporarily unavailable.",
|
|
27029
|
+
action: "Retry in a moment."
|
|
27030
|
+
},
|
|
27031
|
+
store_ahead_of_binary: {
|
|
27032
|
+
code: "MC-C13",
|
|
27033
|
+
sentence: "Magic Context refused to start: its store (store.db) was migrated by a newer ck-mc build than the one running.",
|
|
27034
|
+
action: "Update ck-mc, or roll back by restoring ck-mc together with context.db and store.db from the same backup."
|
|
27035
|
+
},
|
|
27036
|
+
compaction_marker_missing: {
|
|
27037
|
+
code: "MC-C11",
|
|
27038
|
+
sentence: "The history boundary marker is missing from the OpenCode store, so requests carry the full session.",
|
|
27039
|
+
action: "It is retried on every message; if this persists, run `/ctx-flush`."
|
|
27040
|
+
},
|
|
27041
|
+
memory_mirror_stalled: {
|
|
27042
|
+
code: "MC-M01",
|
|
27043
|
+
sentence: "Memory synchronization stopped before the host mirror caught up.",
|
|
27044
|
+
action: "Send another message to resume it, or run `ck doctor drain-authority`."
|
|
27045
|
+
},
|
|
27046
|
+
memory_authority_mismatch: {
|
|
27047
|
+
code: "MC-M02",
|
|
27048
|
+
sentence: "Memory authority is inconsistent between the host and module.",
|
|
27049
|
+
action: "Run `ck doctor drain-authority` before changing Rust mode."
|
|
27050
|
+
},
|
|
27051
|
+
dreamer_task_failing: {
|
|
27052
|
+
code: "MC-S05",
|
|
27053
|
+
sentence: "A background maintenance task keeps failing on its schedule.",
|
|
27054
|
+
action: "Check the Magic Context log for the failing task and its error."
|
|
27055
|
+
}
|
|
27056
|
+
};
|
|
27057
|
+
});
|
|
27058
|
+
|
|
27059
|
+
// ../plugin/src/hooks/magic-context/store-ahead-refusal.ts
|
|
27060
|
+
function renderStoreAheadOfBinaryRefusal(versions) {
|
|
27061
|
+
const failure = USER_FACING_FAILURES.store_ahead_of_binary;
|
|
27062
|
+
const sentence = versions ? `Magic Context refused to start: its store (store.db) is at schema v${versions.dbVersion} but this ck-mc build only knows up to v${versions.binaryMax}.` : failure.sentence;
|
|
27063
|
+
return `${sentence} ${failure.action} (${failure.code})`;
|
|
27064
|
+
}
|
|
27065
|
+
function isRecord4(value) {
|
|
27066
|
+
return value !== null && typeof value === "object";
|
|
27067
|
+
}
|
|
27068
|
+
function nonNegativeInteger(value) {
|
|
27069
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
27070
|
+
}
|
|
27071
|
+
function versionsFromDetail(detail) {
|
|
27072
|
+
if (!isRecord4(detail))
|
|
27073
|
+
return null;
|
|
27074
|
+
const dbVersion = nonNegativeInteger(detail.db_version);
|
|
27075
|
+
const binaryMax = nonNegativeInteger(detail.binary_max);
|
|
27076
|
+
return dbVersion !== null && binaryMax !== null ? { dbVersion, binaryMax } : null;
|
|
27077
|
+
}
|
|
27078
|
+
function versionsFromMessage(message) {
|
|
27079
|
+
if (typeof message !== "string")
|
|
27080
|
+
return null;
|
|
27081
|
+
const match = /db_version=(\d+) binary_max=(\d+)/.exec(message) ?? /schema v(\d+) but this ck-mc build only knows up to v(\d+)/.exec(message);
|
|
27082
|
+
if (!match)
|
|
27083
|
+
return null;
|
|
27084
|
+
return { dbVersion: Number(match[1]), binaryMax: Number(match[2]) };
|
|
27085
|
+
}
|
|
27086
|
+
function storeAheadOfBinaryFailure(error) {
|
|
27087
|
+
let current = error;
|
|
27088
|
+
const seen = new Set;
|
|
27089
|
+
while (isRecord4(current) && !seen.has(current)) {
|
|
27090
|
+
seen.add(current);
|
|
27091
|
+
if (current instanceof StoreAheadOfBinaryError)
|
|
27092
|
+
return current;
|
|
27093
|
+
if (current.code === STORE_AHEAD_OF_BINARY_CODE) {
|
|
27094
|
+
const versions = versionsFromDetail(current.detail) ?? versionsFromMessage(current.message);
|
|
27095
|
+
return new StoreAheadOfBinaryError(versions, { cause: error });
|
|
27096
|
+
}
|
|
27097
|
+
current = current.cause;
|
|
27098
|
+
}
|
|
27099
|
+
return null;
|
|
27100
|
+
}
|
|
27101
|
+
var STORE_AHEAD_OF_BINARY_CODE = "store_ahead_of_binary", StoreAheadOfBinaryError;
|
|
27102
|
+
var init_store_ahead_refusal = __esm(() => {
|
|
27103
|
+
init_user_facing_codes();
|
|
27104
|
+
StoreAheadOfBinaryError = class StoreAheadOfBinaryError extends Error {
|
|
27105
|
+
code = STORE_AHEAD_OF_BINARY_CODE;
|
|
27106
|
+
versions;
|
|
27107
|
+
constructor(versions, options) {
|
|
27108
|
+
super(renderStoreAheadOfBinaryRefusal(versions), options);
|
|
27109
|
+
this.name = "StoreAheadOfBinaryError";
|
|
27110
|
+
this.versions = versions;
|
|
27111
|
+
}
|
|
27112
|
+
};
|
|
27113
|
+
});
|
|
27114
|
+
|
|
27115
|
+
// ../plugin/src/hooks/magic-context/module-transport.ts
|
|
27116
|
+
import { realpathSync as realpathSync3 } from "node:fs";
|
|
27117
|
+
import { join as join17 } from "node:path";
|
|
27118
|
+
function getDefaultSubcConnectionFile() {
|
|
27119
|
+
return join17(getDataDir(), "cortexkit", "run", "subc-connection.json");
|
|
27120
|
+
}
|
|
27121
|
+
function errorChainSome(error, predicate) {
|
|
27122
|
+
let current = error;
|
|
27123
|
+
const seen = new Set;
|
|
27124
|
+
while (isRecord3(current) && !seen.has(current)) {
|
|
27125
|
+
seen.add(current);
|
|
27126
|
+
if (predicate(current))
|
|
27127
|
+
return true;
|
|
27128
|
+
current = current.cause;
|
|
27129
|
+
}
|
|
27130
|
+
return false;
|
|
27131
|
+
}
|
|
27132
|
+
function isStaleOrDeadRouteFailure(error) {
|
|
27133
|
+
return errorChainSome(error, (current) => {
|
|
27134
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
27135
|
+
const name = typeof current.name === "string" ? current.name : "";
|
|
27136
|
+
const message = typeof current.message === "string" ? current.message : "";
|
|
27137
|
+
return [
|
|
27138
|
+
"stale_route_handle",
|
|
27139
|
+
"route_closed",
|
|
27140
|
+
"unknown_channel",
|
|
27141
|
+
"unrecognized_channel",
|
|
27142
|
+
"route_gone"
|
|
27143
|
+
].includes(code) || name === "StaleRouteHandleError" || /route handle \(\d+,\s*\d+\) is not live on the current connection/i.test(message) || /\b(?:unknown|unrecognized) channel\b/i.test(message);
|
|
27144
|
+
});
|
|
27145
|
+
}
|
|
27146
|
+
function isDeadlineFailure(error) {
|
|
27147
|
+
if (error instanceof SocketTimeoutError)
|
|
27148
|
+
return true;
|
|
27149
|
+
return errorChainSome(error, (current) => {
|
|
27150
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
27151
|
+
return ["ETIMEDOUT", "request_deadline", "deadline_exceeded_no_drop_observed"].includes(code);
|
|
27152
|
+
});
|
|
27153
|
+
}
|
|
27154
|
+
function isConnectionFailure(error) {
|
|
27155
|
+
if (error instanceof SocketClosedError || error instanceof SocketTimeoutError || error instanceof StaleRouteHandleError || isConsumerReconnectTransient(error) || isStaleOrDeadRouteFailure(error)) {
|
|
27156
|
+
return true;
|
|
27157
|
+
}
|
|
27158
|
+
return errorChainSome(error, (current) => {
|
|
27159
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
27160
|
+
const message = typeof current.message === "string" ? current.message : "";
|
|
27161
|
+
return [
|
|
27162
|
+
"ENOENT",
|
|
27163
|
+
"ECONNREFUSED",
|
|
27164
|
+
"ECONNRESET",
|
|
27165
|
+
"EPIPE",
|
|
27166
|
+
"ETIMEDOUT",
|
|
27167
|
+
"request_deadline",
|
|
27168
|
+
"deadline_exceeded_no_drop_observed",
|
|
27169
|
+
"connection_dropped",
|
|
27170
|
+
"SUBC_CONNECTION_BACKOFF"
|
|
27171
|
+
].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
|
|
27172
|
+
});
|
|
27173
|
+
}
|
|
27174
|
+
function routeOpenWithoutAmbientConsumerIdentity(client, target, identity, options = {}) {
|
|
27175
|
+
return client.routeOpen(target, identity, {
|
|
27176
|
+
...options,
|
|
27177
|
+
consumerIdentity: null
|
|
27178
|
+
});
|
|
27179
|
+
}
|
|
27180
|
+
|
|
27181
|
+
class SubcModuleTransport {
|
|
27182
|
+
connectionFile;
|
|
27183
|
+
moduleId;
|
|
27184
|
+
requestTimeoutMs;
|
|
27185
|
+
routeSessionPrefix;
|
|
27186
|
+
client = null;
|
|
27187
|
+
routes = new Map;
|
|
27188
|
+
routeOpenings = new Map;
|
|
27189
|
+
canonicalRootCache = new Map;
|
|
27190
|
+
sessionLanes = new Map;
|
|
27191
|
+
queuedLaneWaiters = 0;
|
|
27192
|
+
wrapupSessions = new Map;
|
|
27193
|
+
nextProbeMs = 0;
|
|
27194
|
+
connectionPromise = null;
|
|
27195
|
+
authorityProjectRoot = "";
|
|
27196
|
+
authorityBindRoot = "";
|
|
27197
|
+
backoffMs = CONNECT_BACKOFF_INITIAL_MS;
|
|
27198
|
+
connectionGeneration = 0;
|
|
27199
|
+
stateSyncCapabilityCache = null;
|
|
27200
|
+
getCachedStateSyncCapabilities() {
|
|
27201
|
+
const cached = this.stateSyncCapabilityCache;
|
|
27202
|
+
if (!cached || cached.generation !== this.connectionGeneration)
|
|
27203
|
+
return;
|
|
27204
|
+
return cached.capabilities;
|
|
27205
|
+
}
|
|
27206
|
+
invalidateStateSyncCapabilities() {
|
|
27207
|
+
this.stateSyncCapabilityCache = null;
|
|
27208
|
+
}
|
|
27209
|
+
async stateSyncCapabilities(args) {
|
|
27210
|
+
const cached = this.getCachedStateSyncCapabilities();
|
|
27211
|
+
if (cached)
|
|
27212
|
+
return cached;
|
|
27213
|
+
const response = await this.call({
|
|
27214
|
+
sessionId: args.sessionId,
|
|
27215
|
+
projectRoot: args.projectRoot,
|
|
27216
|
+
method: "session.status",
|
|
27217
|
+
body: { method: "session.status", v: 1, session_id: args.sessionId }
|
|
27218
|
+
});
|
|
27219
|
+
const raw = isRecord3(response) ? response : {};
|
|
27220
|
+
const value = isRecord3(raw.result) ? raw.result : raw;
|
|
27221
|
+
const epochs = isRecord3(value.epochs) ? value.epochs : {};
|
|
27222
|
+
const capabilities = {
|
|
27223
|
+
state_sync_deltas: epochs.state_sync_deltas === true,
|
|
27224
|
+
...epochs.state_sync_resume === true ? { state_sync_resume: true } : {}
|
|
27225
|
+
};
|
|
27226
|
+
this.stateSyncCapabilityCache = { generation: this.connectionGeneration, capabilities };
|
|
27227
|
+
return capabilities;
|
|
27228
|
+
}
|
|
27229
|
+
constructor(connectionFile, moduleId = DEFAULT_MODULE_ID, requestTimeoutMs = MODULE_SEND_TIMEOUT_MS, routeSessionPrefix = "") {
|
|
27230
|
+
this.connectionFile = connectionFile;
|
|
27231
|
+
this.moduleId = moduleId;
|
|
27232
|
+
this.requestTimeoutMs = requestTimeoutMs;
|
|
27233
|
+
this.routeSessionPrefix = routeSessionPrefix;
|
|
27234
|
+
}
|
|
27235
|
+
deadlineError(detail) {
|
|
27236
|
+
const error = new Error(`module transport deadline expired ${detail}`);
|
|
27237
|
+
error.code = "ETIMEDOUT";
|
|
27238
|
+
return error;
|
|
27239
|
+
}
|
|
27240
|
+
laneTimeoutError() {
|
|
27241
|
+
return this.deadlineError("while queued");
|
|
27242
|
+
}
|
|
27243
|
+
connectionChangedError(detail) {
|
|
27244
|
+
const error = new Error(detail);
|
|
27245
|
+
error.code = "ECONNRESET";
|
|
27246
|
+
return error;
|
|
27247
|
+
}
|
|
27248
|
+
async beforeDeadline(operation, deadlineMs, detail) {
|
|
27249
|
+
operation.catch(() => {});
|
|
27250
|
+
const remainingMs = deadlineMs - Date.now();
|
|
27251
|
+
if (remainingMs <= 0)
|
|
27252
|
+
throw this.deadlineError(detail);
|
|
27253
|
+
let timer;
|
|
27254
|
+
try {
|
|
27255
|
+
return await Promise.race([
|
|
27256
|
+
operation,
|
|
27257
|
+
new Promise((_resolve, reject) => {
|
|
27258
|
+
timer = setTimeout(() => reject(this.deadlineError(detail)), remainingMs);
|
|
27259
|
+
})
|
|
27260
|
+
]);
|
|
27261
|
+
} finally {
|
|
27262
|
+
if (timer)
|
|
27263
|
+
clearTimeout(timer);
|
|
27264
|
+
}
|
|
27265
|
+
}
|
|
27266
|
+
cleanupLane(sessionId, lane) {
|
|
27267
|
+
if (!lane.active && lane.waiters.length === 0 && this.sessionLanes.get(sessionId) === lane) {
|
|
27268
|
+
this.sessionLanes.delete(sessionId);
|
|
27269
|
+
}
|
|
27270
|
+
}
|
|
27271
|
+
laneRelease(sessionId, lane) {
|
|
27272
|
+
let released = false;
|
|
27273
|
+
return () => {
|
|
27274
|
+
if (released)
|
|
27275
|
+
return;
|
|
27276
|
+
released = true;
|
|
27277
|
+
lane.active = false;
|
|
27278
|
+
this.dispatchNextLaneWaiter(sessionId, lane);
|
|
27279
|
+
};
|
|
27280
|
+
}
|
|
27281
|
+
dispatchNextLaneWaiter(sessionId, lane) {
|
|
27282
|
+
if (lane.active)
|
|
27283
|
+
return;
|
|
27284
|
+
while (lane.waiters.length > 0) {
|
|
27285
|
+
const waiter = lane.waiters.shift();
|
|
27286
|
+
if (!waiter)
|
|
27287
|
+
continue;
|
|
27288
|
+
this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
|
|
27289
|
+
if (waiter.settled)
|
|
27290
|
+
continue;
|
|
27291
|
+
waiter.settled = true;
|
|
27292
|
+
clearTimeout(waiter.timer);
|
|
27293
|
+
waiter.signal?.removeEventListener("abort", waiter.onAbort);
|
|
27294
|
+
if (waiter.signal?.aborted) {
|
|
27295
|
+
waiter.reject(waiter.signal.reason ?? new Error("module transport call aborted"));
|
|
27296
|
+
continue;
|
|
27297
|
+
}
|
|
27298
|
+
if (waiter.deadlineMs - Date.now() < SERIAL_LANE_MIN_REMAINING_MS) {
|
|
27299
|
+
waiter.reject(this.laneTimeoutError());
|
|
27300
|
+
continue;
|
|
27301
|
+
}
|
|
27302
|
+
lane.active = true;
|
|
27303
|
+
waiter.resolve(this.laneRelease(sessionId, lane));
|
|
27304
|
+
return;
|
|
27305
|
+
}
|
|
27306
|
+
this.cleanupLane(sessionId, lane);
|
|
27307
|
+
}
|
|
27308
|
+
queueFullError() {
|
|
27309
|
+
const error = new Error("module transport queue is full");
|
|
27310
|
+
error.code = "EBUSY";
|
|
27311
|
+
return error;
|
|
27312
|
+
}
|
|
27313
|
+
acquireCorrectnessLane(sessionId, signal, deadlineMs) {
|
|
27314
|
+
if (signal?.aborted) {
|
|
27315
|
+
return Promise.reject(signal.reason ?? new Error("module transport call aborted"));
|
|
27316
|
+
}
|
|
27317
|
+
if (deadlineMs - Date.now() < SERIAL_LANE_MIN_REMAINING_MS) {
|
|
27318
|
+
return Promise.reject(this.laneTimeoutError());
|
|
27319
|
+
}
|
|
27320
|
+
const lane = this.sessionLanes.get(sessionId) ?? { active: false, waiters: [] };
|
|
27321
|
+
this.sessionLanes.set(sessionId, lane);
|
|
27322
|
+
if (!lane.active && lane.waiters.length === 0) {
|
|
27323
|
+
lane.active = true;
|
|
27324
|
+
return Promise.resolve(this.laneRelease(sessionId, lane));
|
|
27325
|
+
}
|
|
27326
|
+
if (this.queuedLaneWaiters >= SERIAL_LANE_MAX_WAITERS || lane.waiters.length >= SERIAL_LANE_MAX_WAITERS_PER_SESSION) {
|
|
27327
|
+
return Promise.reject(this.queueFullError());
|
|
27328
|
+
}
|
|
27329
|
+
return new Promise((resolve, reject) => {
|
|
27330
|
+
const waiter = {};
|
|
27331
|
+
const removeAndReject = (error) => {
|
|
27332
|
+
if (waiter.settled)
|
|
27333
|
+
return;
|
|
27334
|
+
waiter.settled = true;
|
|
27335
|
+
clearTimeout(waiter.timer);
|
|
27336
|
+
signal?.removeEventListener("abort", waiter.onAbort);
|
|
27337
|
+
const index = lane.waiters.indexOf(waiter);
|
|
27338
|
+
if (index >= 0) {
|
|
27339
|
+
lane.waiters.splice(index, 1);
|
|
27340
|
+
this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
|
|
26976
27341
|
}
|
|
26977
27342
|
reject(error);
|
|
26978
27343
|
this.cleanupLane(sessionId, lane);
|
|
@@ -27017,7 +27382,8 @@ class SubcModuleTransport {
|
|
|
27017
27382
|
const laneDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
27018
27383
|
let releaseLane = () => {};
|
|
27019
27384
|
try {
|
|
27020
|
-
|
|
27385
|
+
const outsideSessionOrder = args.method.startsWith("historian.");
|
|
27386
|
+
if (!args.bypassSessionLane && !outsideSessionOrder) {
|
|
27021
27387
|
releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
|
|
27022
27388
|
}
|
|
27023
27389
|
} catch (error) {
|
|
@@ -27077,6 +27443,9 @@ class SubcModuleTransport {
|
|
|
27077
27443
|
} catch (error) {
|
|
27078
27444
|
if (args.signal?.aborted)
|
|
27079
27445
|
throw args.signal.reason ?? error;
|
|
27446
|
+
const storeAhead = storeAheadOfBinaryFailure(error);
|
|
27447
|
+
if (storeAhead)
|
|
27448
|
+
throw storeAhead;
|
|
27080
27449
|
if (args.method === "state_sync" && isDeadlineFailure(error)) {
|
|
27081
27450
|
const body = isRecord3(args.body) ? args.body : {};
|
|
27082
27451
|
throw Object.assign(new Error(`state_sync timeout stage=module_ack page=${body.seed_batch_index ?? 0}/${body.seed_batch_total ?? 1} series=${body.seed_id ?? "delta"} budget_ms=${attemptTimeoutMs}`), {
|
|
@@ -27390,6 +27759,7 @@ var DEFAULT_MODULE_ID = "magic-context", CONNECT_BACKOFF_INITIAL_MS = 1000, CONN
|
|
|
27390
27759
|
var init_module_transport = __esm(() => {
|
|
27391
27760
|
init_dist5();
|
|
27392
27761
|
init_data_path();
|
|
27762
|
+
init_store_ahead_refusal();
|
|
27393
27763
|
});
|
|
27394
27764
|
// ../plugin/src/shared/pi-executable.ts
|
|
27395
27765
|
function piHarnessKindFromExecutable(value) {
|
|
@@ -27406,6 +27776,9 @@ var init_pi_executable = __esm(() => {
|
|
|
27406
27776
|
// ../plugin/src/shared/rpc-utils.ts
|
|
27407
27777
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
27408
27778
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
27779
|
+
function isOwnRpcServerRecord(record) {
|
|
27780
|
+
return record.pid === process.pid && record.instance_id !== undefined && ownRpcServerInstanceIds.has(record.instance_id);
|
|
27781
|
+
}
|
|
27409
27782
|
function isPidAlive(pid) {
|
|
27410
27783
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
27411
27784
|
return "dead";
|
|
@@ -27928,10 +28301,11 @@ function parseRpcPortFile(content, fallbackPid = 0) {
|
|
|
27928
28301
|
function isValidPort(port) {
|
|
27929
28302
|
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
27930
28303
|
}
|
|
27931
|
-
var RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000, LINUX_CLOCK_TICKS_PER_SECOND = 100, PS_PROBE_TIMEOUT_MS = 1000, WINDOWS_CIM_PROBE_TIMEOUT_MS = 5000, MAX_ANCESTOR_WALK_DEPTH = 16, OPEN_CODE_COMMAND_MARKERS, TASKLIST_NO_TASKS_PATTERN, WINDOWS_CIM_COMMAND = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine,CreationDate | ConvertTo-Json -Compress", PI_HARNESS_ARC_MARKERS, rpcIdentityReadFileSync, rpcIdentityExecFileSync, rpcIdentityProcessKill, rpcProcessListExecFileSync, rpcIdentityPlatform, rpcIdentityNowMs = () => Date.now(), windowsProcessFactsCache = null;
|
|
28304
|
+
var ownRpcServerInstanceIds, RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000, LINUX_CLOCK_TICKS_PER_SECOND = 100, PS_PROBE_TIMEOUT_MS = 1000, WINDOWS_CIM_PROBE_TIMEOUT_MS = 5000, MAX_ANCESTOR_WALK_DEPTH = 16, OPEN_CODE_COMMAND_MARKERS, TASKLIST_NO_TASKS_PATTERN, WINDOWS_CIM_COMMAND = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine,CreationDate | ConvertTo-Json -Compress", PI_HARNESS_ARC_MARKERS, rpcIdentityReadFileSync, rpcIdentityExecFileSync, rpcIdentityProcessKill, rpcProcessListExecFileSync, rpcIdentityPlatform, rpcIdentityNowMs = () => Date.now(), windowsProcessFactsCache = null;
|
|
27932
28305
|
var init_rpc_utils = __esm(() => {
|
|
27933
28306
|
init_logger();
|
|
27934
28307
|
init_pi_executable();
|
|
28308
|
+
ownRpcServerInstanceIds = new Set;
|
|
27935
28309
|
OPEN_CODE_COMMAND_MARKERS = ["opencode", "node", "bun", "electron"];
|
|
27936
28310
|
TASKLIST_NO_TASKS_PATTERN = /^INFO:\s+No tasks are running which match the specified criteria\.?$/im;
|
|
27937
28311
|
PI_HARNESS_ARC_MARKERS = [
|
|
@@ -28061,7 +28435,9 @@ function formatFailClosedBlockingMessage(reason) {
|
|
|
28061
28435
|
}
|
|
28062
28436
|
return [
|
|
28063
28437
|
`Magic Context cannot migrate the shared database (one database serves every project on this machine) because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
|
|
28438
|
+
`The database is at upstream migration v${reason.persistedVersion}; this build needs v${reason.supportedVersion}.`,
|
|
28064
28439
|
"Restart the blocking process — even one from a different project — and it will pick up the new build and migrate on start; or shut it down and retry.",
|
|
28440
|
+
"If that host loads a pinned or cached older Magic Context build, a restart alone is not enough: stop it or update its Magic Context build, then start this host once so it migrates the database with nothing older attached.",
|
|
28065
28441
|
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
28066
28442
|
].join(" ");
|
|
28067
28443
|
}
|
|
@@ -28096,6 +28472,47 @@ var init_message_fts_rowid_map = __esm(() => {
|
|
|
28096
28472
|
activeBackfills = new WeakMap;
|
|
28097
28473
|
});
|
|
28098
28474
|
|
|
28475
|
+
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
28476
|
+
var V2_MEMORY_CATEGORIES, PROMOTABLE_CATEGORIES, CATEGORY_PRIORITY, MEMORY_CATEGORY_ORDER_UNKNOWN = 99, MEMORY_CATEGORY_ORDER_PRIORITY, MEMORY_CATEGORY_ORDER_SQL, CATEGORY_DEFAULT_TTL;
|
|
28477
|
+
var init_constants = __esm(() => {
|
|
28478
|
+
V2_MEMORY_CATEGORIES = [
|
|
28479
|
+
"PROJECT_RULES",
|
|
28480
|
+
"ARCHITECTURE",
|
|
28481
|
+
"CONSTRAINTS",
|
|
28482
|
+
"CONFIG_VALUES",
|
|
28483
|
+
"NAMING"
|
|
28484
|
+
];
|
|
28485
|
+
PROMOTABLE_CATEGORIES = [
|
|
28486
|
+
...V2_MEMORY_CATEGORIES,
|
|
28487
|
+
"ARCHITECTURE_DECISIONS",
|
|
28488
|
+
"CONFIG_DEFAULTS",
|
|
28489
|
+
"USER_PREFERENCES",
|
|
28490
|
+
"USER_DIRECTIVES",
|
|
28491
|
+
"ENVIRONMENT",
|
|
28492
|
+
"WORKFLOW_RULES",
|
|
28493
|
+
"KNOWN_ISSUES"
|
|
28494
|
+
];
|
|
28495
|
+
CATEGORY_PRIORITY = [
|
|
28496
|
+
...V2_MEMORY_CATEGORIES,
|
|
28497
|
+
"USER_DIRECTIVES",
|
|
28498
|
+
"USER_PREFERENCES",
|
|
28499
|
+
"CONFIG_DEFAULTS",
|
|
28500
|
+
"ARCHITECTURE_DECISIONS",
|
|
28501
|
+
"ENVIRONMENT",
|
|
28502
|
+
"WORKFLOW_RULES",
|
|
28503
|
+
"KNOWN_ISSUES"
|
|
28504
|
+
];
|
|
28505
|
+
MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
28506
|
+
acc[category] = index;
|
|
28507
|
+
return acc;
|
|
28508
|
+
}, {});
|
|
28509
|
+
MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
28510
|
+
CATEGORY_DEFAULT_TTL = {
|
|
28511
|
+
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
28512
|
+
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
28513
|
+
};
|
|
28514
|
+
});
|
|
28515
|
+
|
|
28099
28516
|
// ../plugin/src/hooks/magic-context/compartment-parser.ts
|
|
28100
28517
|
function makeTierOpenRegex(n) {
|
|
28101
28518
|
return new RegExp(`<p${n}\\s*(/?)>`);
|
|
@@ -28125,6 +28542,8 @@ function extractTiersFromInner(inner) {
|
|
|
28125
28542
|
function parseCompartmentOutput(text) {
|
|
28126
28543
|
const compartments = [];
|
|
28127
28544
|
const facts = [];
|
|
28545
|
+
let droppedFactBlocks = 0;
|
|
28546
|
+
let droppedFacts = 0;
|
|
28128
28547
|
for (const match of text.matchAll(COMPARTMENT_REGEX)) {
|
|
28129
28548
|
const attrs = match[1];
|
|
28130
28549
|
const inner = match[2];
|
|
@@ -28174,16 +28593,21 @@ function parseCompartmentOutput(text) {
|
|
|
28174
28593
|
}
|
|
28175
28594
|
}
|
|
28176
28595
|
const factsBlockMatch = text.match(FACTS_BLOCK_REGEX);
|
|
28177
|
-
const factsScope = factsBlockMatch ? factsBlockMatch[1] : text.replace(EVENTS_BLOCK_REGEX, "").replace(/<compartment\s+[^>]*?\s*>.*?<\/compartment>/gs, "");
|
|
28596
|
+
const factsScope = factsBlockMatch ? factsBlockMatch[1] : text.replace(EVENTS_BLOCK_REGEX, "").replace(/<compartment\s+[^>]*?\s*>.*?<\/compartment>/gs, "").replace(/<(meta|user_observations|primer_candidates)>.*?<\/\1>/gs, "").replace(/<\/?(?:output|compartments)>/g, "");
|
|
28178
28597
|
for (const categoryMatch of factsScope.matchAll(CATEGORY_BLOCK_REGEX)) {
|
|
28179
28598
|
const category = categoryMatch[1];
|
|
28180
28599
|
const blockContent = categoryMatch[2];
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
if (
|
|
28184
|
-
|
|
28185
|
-
|
|
28600
|
+
const items = [...blockContent.matchAll(FACT_ITEM_REGEX)].map((match) => unescapeXml(match[1].trim())).filter(Boolean);
|
|
28601
|
+
if (!HISTORIAN_CATEGORIES.has(category)) {
|
|
28602
|
+
if (items.length === 0)
|
|
28603
|
+
continue;
|
|
28604
|
+
droppedFactBlocks++;
|
|
28605
|
+
droppedFacts += items.length;
|
|
28606
|
+
log3(`[historian] Dropped <facts> category ${category} (${items.length} facts)`);
|
|
28607
|
+
continue;
|
|
28186
28608
|
}
|
|
28609
|
+
for (const content of items)
|
|
28610
|
+
facts.push({ category, content });
|
|
28187
28611
|
}
|
|
28188
28612
|
const unprocessedMatch = text.match(UNPROCESSED_REGEX);
|
|
28189
28613
|
const unprocessedFrom = unprocessedMatch ? parseInt(unprocessedMatch[1], 10) : null;
|
|
@@ -28221,7 +28645,16 @@ function parseCompartmentOutput(text) {
|
|
|
28221
28645
|
}
|
|
28222
28646
|
const events = parseEvents(text);
|
|
28223
28647
|
compartments.sort((a, b) => a.startMessage - b.startMessage);
|
|
28224
|
-
return {
|
|
28648
|
+
return {
|
|
28649
|
+
compartments,
|
|
28650
|
+
facts,
|
|
28651
|
+
droppedFactBlocks,
|
|
28652
|
+
droppedFacts,
|
|
28653
|
+
events,
|
|
28654
|
+
unprocessedFrom,
|
|
28655
|
+
userObservations,
|
|
28656
|
+
primerCandidates
|
|
28657
|
+
};
|
|
28225
28658
|
}
|
|
28226
28659
|
function parseEvents(text) {
|
|
28227
28660
|
const blockMatch = text.match(EVENTS_BLOCK_REGEX);
|
|
@@ -28247,8 +28680,10 @@ function parseEvents(text) {
|
|
|
28247
28680
|
function unescapeXml(s) {
|
|
28248
28681
|
return s.replace(/&/g, "&").replace(/'/g, "'").replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">");
|
|
28249
28682
|
}
|
|
28250
|
-
var COMPARTMENT_REGEX, ATTR_START_REGEX, ATTR_END_REGEX, ATTR_TITLE_REGEX, ATTR_EPISODE_REGEX, ATTR_IMPORTANCE_REGEX, TIER_OPEN_REGEXES, TIER_CLOSE_ANY_REGEX, TIER_OPEN_ANY_REGEX, CATEGORY_BLOCK_REGEX, FACT_ITEM_REGEX, UNPROCESSED_REGEX, USER_OBSERVATIONS_REGEX, USER_OBS_ITEM_REGEX, PRIMER_CANDIDATES_REGEX, PRIMER_ELEMENT_REGEX, PRIMER_ITEM_REGEX, FACTS_BLOCK_REGEX, EVENTS_BLOCK_REGEX, EVENT_ELEMENT_REGEX, EVENT_FIELD_REGEX;
|
|
28683
|
+
var COMPARTMENT_REGEX, ATTR_START_REGEX, ATTR_END_REGEX, ATTR_TITLE_REGEX, ATTR_EPISODE_REGEX, ATTR_IMPORTANCE_REGEX, TIER_OPEN_REGEXES, TIER_CLOSE_ANY_REGEX, TIER_OPEN_ANY_REGEX, CATEGORY_BLOCK_REGEX, HISTORIAN_CATEGORIES, FACT_ITEM_REGEX, UNPROCESSED_REGEX, USER_OBSERVATIONS_REGEX, USER_OBS_ITEM_REGEX, PRIMER_CANDIDATES_REGEX, PRIMER_ELEMENT_REGEX, PRIMER_ITEM_REGEX, FACTS_BLOCK_REGEX, EVENTS_BLOCK_REGEX, EVENT_ELEMENT_REGEX, EVENT_FIELD_REGEX;
|
|
28251
28684
|
var init_compartment_parser = __esm(() => {
|
|
28685
|
+
init_constants();
|
|
28686
|
+
init_logger();
|
|
28252
28687
|
COMPARTMENT_REGEX = /<compartment\s+([^>]*?)\s*>(.*?)<\/compartment>/gs;
|
|
28253
28688
|
ATTR_START_REGEX = /\bstart="(\d+)"/;
|
|
28254
28689
|
ATTR_END_REGEX = /\bend="(\d+)"/;
|
|
@@ -28263,7 +28698,8 @@ var init_compartment_parser = __esm(() => {
|
|
|
28263
28698
|
];
|
|
28264
28699
|
TIER_CLOSE_ANY_REGEX = /<\/p\d/;
|
|
28265
28700
|
TIER_OPEN_ANY_REGEX = /<p\d/;
|
|
28266
|
-
CATEGORY_BLOCK_REGEX = /<(
|
|
28701
|
+
CATEGORY_BLOCK_REGEX = /<([A-Za-z_][A-Za-z0-9_-]*)>(.*?)<\/\1>/gs;
|
|
28702
|
+
HISTORIAN_CATEGORIES = new Set(V2_MEMORY_CATEGORIES);
|
|
28267
28703
|
FACT_ITEM_REGEX = /^\s*\*\s*(.+)$/gm;
|
|
28268
28704
|
UNPROCESSED_REGEX = /<unprocessed_from>(\d+)<\/unprocessed_from>/;
|
|
28269
28705
|
USER_OBSERVATIONS_REGEX = /<user_observations>(.*?)<\/user_observations>/s;
|
|
@@ -28617,53 +29053,18 @@ function healAllNullColumns(db) {
|
|
|
28617
29053
|
const nullPredicate = presentFallbacks.map(([column]) => `${column} IS NULL`).join(" OR ");
|
|
28618
29054
|
db.prepare(`UPDATE session_meta SET ${assignments} WHERE ${nullPredicate}`).run(...presentFallbacks.map(([, fallback]) => fallback));
|
|
28619
29055
|
}
|
|
28620
|
-
healMissingMemoryBlockIds(db, existingColumns);
|
|
28621
|
-
}
|
|
28622
|
-
function getSessionMetaColumns(db) {
|
|
28623
|
-
const rows = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
28624
|
-
return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
|
|
28625
|
-
}
|
|
28626
|
-
function healMissingMemoryBlockIds(db, columns) {
|
|
28627
|
-
if (!columns.has("memory_block_cache") || !columns.has("memory_block_ids") || !columns.has("memory_block_count")) {
|
|
28628
|
-
return;
|
|
28629
|
-
}
|
|
28630
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE memory_block_cache != '' AND (memory_block_ids IS NULL OR memory_block_ids = '') AND memory_block_count > 0").run();
|
|
28631
|
-
}
|
|
28632
|
-
|
|
28633
|
-
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
28634
|
-
var V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, MEMORY_CATEGORY_ORDER_UNKNOWN = 99, MEMORY_CATEGORY_ORDER_PRIORITY, MEMORY_CATEGORY_ORDER_SQL, CATEGORY_DEFAULT_TTL;
|
|
28635
|
-
var init_constants = __esm(() => {
|
|
28636
|
-
V2_MEMORY_CATEGORIES = [
|
|
28637
|
-
"PROJECT_RULES",
|
|
28638
|
-
"ARCHITECTURE",
|
|
28639
|
-
"CONSTRAINTS",
|
|
28640
|
-
"CONFIG_VALUES",
|
|
28641
|
-
"NAMING"
|
|
28642
|
-
];
|
|
28643
|
-
CATEGORY_PRIORITY = [
|
|
28644
|
-
"PROJECT_RULES",
|
|
28645
|
-
"ARCHITECTURE",
|
|
28646
|
-
"CONSTRAINTS",
|
|
28647
|
-
"CONFIG_VALUES",
|
|
28648
|
-
"NAMING",
|
|
28649
|
-
"USER_DIRECTIVES",
|
|
28650
|
-
"USER_PREFERENCES",
|
|
28651
|
-
"CONFIG_DEFAULTS",
|
|
28652
|
-
"ARCHITECTURE_DECISIONS",
|
|
28653
|
-
"ENVIRONMENT",
|
|
28654
|
-
"WORKFLOW_RULES",
|
|
28655
|
-
"KNOWN_ISSUES"
|
|
28656
|
-
];
|
|
28657
|
-
MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
28658
|
-
acc[category] = index;
|
|
28659
|
-
return acc;
|
|
28660
|
-
}, {});
|
|
28661
|
-
MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
28662
|
-
CATEGORY_DEFAULT_TTL = {
|
|
28663
|
-
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
28664
|
-
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
28665
|
-
};
|
|
28666
|
-
});
|
|
29056
|
+
healMissingMemoryBlockIds(db, existingColumns);
|
|
29057
|
+
}
|
|
29058
|
+
function getSessionMetaColumns(db) {
|
|
29059
|
+
const rows = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
29060
|
+
return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
|
|
29061
|
+
}
|
|
29062
|
+
function healMissingMemoryBlockIds(db, columns) {
|
|
29063
|
+
if (!columns.has("memory_block_cache") || !columns.has("memory_block_ids") || !columns.has("memory_block_count")) {
|
|
29064
|
+
return;
|
|
29065
|
+
}
|
|
29066
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE memory_block_cache != '' AND (memory_block_ids IS NULL OR memory_block_ids = '') AND memory_block_count > 0").run();
|
|
29067
|
+
}
|
|
28667
29068
|
|
|
28668
29069
|
// ../plugin/src/features/magic-context/project-identity.ts
|
|
28669
29070
|
var init_project_identity2 = __esm(() => {
|
|
@@ -31144,6 +31545,20 @@ var init_migrations = __esm(async () => {
|
|
|
31144
31545
|
return;
|
|
31145
31546
|
ensureColumn(db, "compartment_state_lease", "owner_pid", "INTEGER");
|
|
31146
31547
|
}
|
|
31548
|
+
},
|
|
31549
|
+
{
|
|
31550
|
+
version: 91,
|
|
31551
|
+
description: "per-project embedding high-water mark for memories written outside this host",
|
|
31552
|
+
up(db) {
|
|
31553
|
+
db.exec(`
|
|
31554
|
+
CREATE TABLE IF NOT EXISTS memory_embedding_watermarks (
|
|
31555
|
+
project_path TEXT PRIMARY KEY,
|
|
31556
|
+
written_memory_id INTEGER NOT NULL DEFAULT 0,
|
|
31557
|
+
embedded_memory_id INTEGER NOT NULL DEFAULT 0,
|
|
31558
|
+
updated_at INTEGER NOT NULL DEFAULT 0
|
|
31559
|
+
);
|
|
31560
|
+
`);
|
|
31561
|
+
}
|
|
31147
31562
|
}
|
|
31148
31563
|
];
|
|
31149
31564
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -31375,6 +31790,8 @@ function inspectRpcServerDiscovery(storageDir) {
|
|
|
31375
31790
|
return junk;
|
|
31376
31791
|
continue;
|
|
31377
31792
|
}
|
|
31793
|
+
if (isOwnRpcServerRecord(record))
|
|
31794
|
+
continue;
|
|
31378
31795
|
const liveness = isPidAlive(record.pid);
|
|
31379
31796
|
if (liveness === "dead") {
|
|
31380
31797
|
staleFiles.push(portFile);
|
|
@@ -31996,6 +32413,15 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
31996
32413
|
(id, cursor_session_id, cursor_ordinal, completed, updated_at)
|
|
31997
32414
|
VALUES (1, '', 0, 0, 0);
|
|
31998
32415
|
|
|
32416
|
+
-- Highest memory id another writer (the Rust module in single-store mode) put
|
|
32417
|
+
-- into memories for a project, and how far this host has embedded. Migration v91.
|
|
32418
|
+
CREATE TABLE IF NOT EXISTS memory_embedding_watermarks (
|
|
32419
|
+
project_path TEXT PRIMARY KEY,
|
|
32420
|
+
written_memory_id INTEGER NOT NULL DEFAULT 0,
|
|
32421
|
+
embedded_memory_id INTEGER NOT NULL DEFAULT 0,
|
|
32422
|
+
updated_at INTEGER NOT NULL DEFAULT 0
|
|
32423
|
+
);
|
|
32424
|
+
|
|
31999
32425
|
CREATE TABLE IF NOT EXISTS message_history_index (
|
|
32000
32426
|
session_id TEXT PRIMARY KEY,
|
|
32001
32427
|
last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
|
|
@@ -32655,7 +33081,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
32655
33081
|
`);
|
|
32656
33082
|
ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
32657
33083
|
}
|
|
32658
|
-
var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION =
|
|
33084
|
+
var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION = 91, BOOT_SQLITE_BUSY_TIMEOUT_MS = 5000, PERMISSIONS_ENFORCEABLE, RPC_DISCOVERY_PARSE_GRACE_MS, defaultRpcDiscoveryFs, rpcDiscoveryFs, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS;
|
|
32659
33085
|
var init_storage_db = __esm(async () => {
|
|
32660
33086
|
init_data_path();
|
|
32661
33087
|
init_logger();
|
|
@@ -35440,7 +35866,7 @@ async function doctorRetryV22Backfill(db) {
|
|
|
35440
35866
|
bumpProjectMemoryEpochInTransaction(db, identity, now);
|
|
35441
35867
|
succeeded += 1;
|
|
35442
35868
|
}
|
|
35443
|
-
})();
|
|
35869
|
+
}).immediate();
|
|
35444
35870
|
} catch (error) {
|
|
35445
35871
|
const classified = classifyBackfillError(error);
|
|
35446
35872
|
db.prepare(`UPDATE v22_backfill_failures
|
|
@@ -35473,7 +35899,7 @@ async function doctorRekeyV22DirIdentity(db, rawProjectPath) {
|
|
|
35473
35899
|
if (changedRows > 0) {
|
|
35474
35900
|
bumpProjectMemoryEpochInTransaction(db, newIdentity, now);
|
|
35475
35901
|
}
|
|
35476
|
-
})();
|
|
35902
|
+
}).immediate();
|
|
35477
35903
|
return { oldIdentity, newIdentity, changedRows };
|
|
35478
35904
|
}
|
|
35479
35905
|
var BACKFILL_META_KEY = "v22_legacy_memory_backfill", BACKFILL_CURSOR_META_KEY = "v22_legacy_memory_backfill_cursor", MEMORIES_TABLE = "memories";
|
|
@@ -35546,236 +35972,6 @@ var init_v22_backfill_commands = __esm(async () => {
|
|
|
35546
35972
|
await init_storage_db();
|
|
35547
35973
|
});
|
|
35548
35974
|
|
|
35549
|
-
// ../plugin/src/shared/user-facing-codes.ts
|
|
35550
|
-
function userFacingFailureCode(key) {
|
|
35551
|
-
return USER_FACING_FAILURES[key].code;
|
|
35552
|
-
}
|
|
35553
|
-
var USER_FACING_FAILURES;
|
|
35554
|
-
var init_user_facing_codes = __esm(() => {
|
|
35555
|
-
USER_FACING_FAILURES = {
|
|
35556
|
-
historian_unavailable: {
|
|
35557
|
-
code: "MC-H01",
|
|
35558
|
-
sentence: "History compression could not finish this turn.",
|
|
35559
|
-
action: "It will retry automatically."
|
|
35560
|
-
},
|
|
35561
|
-
hidden_cleanup_unbound: {
|
|
35562
|
-
code: "MC-H02",
|
|
35563
|
-
sentence: "Some finished background sessions could not be removed from this host.",
|
|
35564
|
-
action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
|
|
35565
|
-
},
|
|
35566
|
-
historian_saved_history_misaligned: {
|
|
35567
|
-
code: "MC-H03",
|
|
35568
|
-
sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
|
|
35569
|
-
action: "Run /ctx-recomp to rebuild them."
|
|
35570
|
-
},
|
|
35571
|
-
recomp_unavailable: {
|
|
35572
|
-
code: "MC-R01",
|
|
35573
|
-
sentence: "History compression could not be rebuilt.",
|
|
35574
|
-
action: "Run /ctx-recomp again."
|
|
35575
|
-
},
|
|
35576
|
-
dream_provider_timeout: {
|
|
35577
|
-
code: "MC-D01",
|
|
35578
|
-
sentence: "Memory maintenance took too long to respond.",
|
|
35579
|
-
action: "Run /ctx-dream again."
|
|
35580
|
-
},
|
|
35581
|
-
dream_provider_error: {
|
|
35582
|
-
code: "MC-D02",
|
|
35583
|
-
sentence: "Memory maintenance could not reach its model.",
|
|
35584
|
-
action: "Check the model connection, then run /ctx-dream again."
|
|
35585
|
-
},
|
|
35586
|
-
dream_empty_completion: {
|
|
35587
|
-
code: "MC-D03",
|
|
35588
|
-
sentence: "Memory maintenance received no usable response.",
|
|
35589
|
-
action: "Run /ctx-dream again."
|
|
35590
|
-
},
|
|
35591
|
-
dream_no_models: {
|
|
35592
|
-
code: "MC-D04",
|
|
35593
|
-
sentence: "Memory maintenance has no model available.",
|
|
35594
|
-
action: "Check the model settings, then run /ctx-dream again."
|
|
35595
|
-
},
|
|
35596
|
-
dream_child_aborted: {
|
|
35597
|
-
code: "MC-D05",
|
|
35598
|
-
sentence: "Memory maintenance was interrupted.",
|
|
35599
|
-
action: "Run /ctx-dream again."
|
|
35600
|
-
},
|
|
35601
|
-
dream_parse_failed: {
|
|
35602
|
-
code: "MC-D06",
|
|
35603
|
-
sentence: "Memory maintenance could not use the model response.",
|
|
35604
|
-
action: "Run /ctx-dream again."
|
|
35605
|
-
},
|
|
35606
|
-
dream_unknown: {
|
|
35607
|
-
code: "MC-D07",
|
|
35608
|
-
sentence: "Memory maintenance could not finish.",
|
|
35609
|
-
action: "Run /ctx-dream again."
|
|
35610
|
-
},
|
|
35611
|
-
dreamer_tick_blocked: {
|
|
35612
|
-
code: "MC-D09",
|
|
35613
|
-
sentence: "Background maintenance is not running: its last pass stopped before it reached the scheduled tasks.",
|
|
35614
|
-
action: "It is retried automatically; if it keeps happening, check the Magic Context log for the stage that stopped and run `npx @cortexkit/magic-context doctor`."
|
|
35615
|
-
},
|
|
35616
|
-
dream_task_needs_tool_loop: {
|
|
35617
|
-
code: "MC-D08",
|
|
35618
|
-
sentence: "Some memory maintenance tasks need a tool loop this host does not provide.",
|
|
35619
|
-
action: "The remaining tasks still run; the listed ones are skipped on this host."
|
|
35620
|
-
},
|
|
35621
|
-
embedding_substitution_rejected: {
|
|
35622
|
-
code: "MC-E01",
|
|
35623
|
-
sentence: "Search indexing could not use the selected model.",
|
|
35624
|
-
action: "Check the embedding model setting, then run /ctx-embed start again."
|
|
35625
|
-
},
|
|
35626
|
-
embedding_http_error: {
|
|
35627
|
-
code: "MC-E02",
|
|
35628
|
-
sentence: "The search indexing provider refused the request.",
|
|
35629
|
-
action: "Check the provider connection and credentials, then run /ctx-embed start again."
|
|
35630
|
-
},
|
|
35631
|
-
embedding_transport_error: {
|
|
35632
|
-
code: "MC-E03",
|
|
35633
|
-
sentence: "Search indexing could not reach its provider.",
|
|
35634
|
-
action: "Check the connection, then run /ctx-embed start again."
|
|
35635
|
-
},
|
|
35636
|
-
embedding_invalid_envelope: {
|
|
35637
|
-
code: "MC-E04",
|
|
35638
|
-
sentence: "Search indexing received an unsupported response.",
|
|
35639
|
-
action: "Check the embedding endpoint, then run /ctx-embed start again."
|
|
35640
|
-
},
|
|
35641
|
-
embedding_empty_result: {
|
|
35642
|
-
code: "MC-E05",
|
|
35643
|
-
sentence: "Search indexing received no usable result.",
|
|
35644
|
-
action: "Run /ctx-embed start again."
|
|
35645
|
-
},
|
|
35646
|
-
embedding_certification_refusal: {
|
|
35647
|
-
code: "MC-E06",
|
|
35648
|
-
sentence: "Search indexing is not ready for this provider.",
|
|
35649
|
-
action: "Finish the provider setup, or set a fallback provider in the embedding settings, then run /ctx-embed start again."
|
|
35650
|
-
},
|
|
35651
|
-
embedding_credential_required: {
|
|
35652
|
-
code: "MC-E07",
|
|
35653
|
-
sentence: "Search indexing needs provider credentials.",
|
|
35654
|
-
action: "Sign in to the provider, then run /ctx-embed start again."
|
|
35655
|
-
},
|
|
35656
|
-
embedding_local_binding_missing: {
|
|
35657
|
-
code: "MC-E08",
|
|
35658
|
-
sentence: "Local search indexing is unavailable on this system.",
|
|
35659
|
-
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
35660
|
-
},
|
|
35661
|
-
embedding_local_fs_unavailable: {
|
|
35662
|
-
code: "MC-E09",
|
|
35663
|
-
sentence: "Local search indexing cannot save its model files.",
|
|
35664
|
-
action: "Update or reinstall Magic Context, then retry."
|
|
35665
|
-
},
|
|
35666
|
-
embedding_local_download_failure: {
|
|
35667
|
-
code: "MC-E10",
|
|
35668
|
-
sentence: "Local search indexing could not download its model.",
|
|
35669
|
-
action: "Check the network connection, then retry."
|
|
35670
|
-
},
|
|
35671
|
-
embedding_local_runtime_error: {
|
|
35672
|
-
code: "MC-E11",
|
|
35673
|
-
sentence: "Local search indexing could not start.",
|
|
35674
|
-
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
35675
|
-
},
|
|
35676
|
-
embedding_unavailable: {
|
|
35677
|
-
code: "MC-E12",
|
|
35678
|
-
sentence: "Search indexing could not finish.",
|
|
35679
|
-
action: "Run /ctx-embed start again."
|
|
35680
|
-
},
|
|
35681
|
-
status_unavailable: {
|
|
35682
|
-
code: "MC-S01",
|
|
35683
|
-
sentence: "Magic Context status is temporarily unavailable.",
|
|
35684
|
-
action: "Retry /ctx-status in a moment."
|
|
35685
|
-
},
|
|
35686
|
-
transform_update_failed: {
|
|
35687
|
-
code: "MC-S02",
|
|
35688
|
-
sentence: "The last context update did not finish.",
|
|
35689
|
-
action: "Send another message to retry."
|
|
35690
|
-
},
|
|
35691
|
-
configuration_warning: {
|
|
35692
|
-
code: "MC-S03",
|
|
35693
|
-
sentence: "Some configuration settings could not be applied.",
|
|
35694
|
-
action: "Fix the configuration warning shown in /ctx-status, then restart."
|
|
35695
|
-
},
|
|
35696
|
-
status_log_unavailable: {
|
|
35697
|
-
code: "MC-S04",
|
|
35698
|
-
sentence: "Some diagnostic details could not be saved.",
|
|
35699
|
-
action: "Retry /ctx-status in a moment."
|
|
35700
|
-
},
|
|
35701
|
-
memory_writes_paused: {
|
|
35702
|
-
code: "MC-C01",
|
|
35703
|
-
sentence: "Memory writes are paused while the engine syncs.",
|
|
35704
|
-
action: "Retry in a moment."
|
|
35705
|
-
},
|
|
35706
|
-
memory_access_unavailable: {
|
|
35707
|
-
code: "MC-C02",
|
|
35708
|
-
sentence: "Memory access is temporarily unavailable.",
|
|
35709
|
-
action: "Retry in a moment."
|
|
35710
|
-
},
|
|
35711
|
-
note_changes_paused: {
|
|
35712
|
-
code: "MC-C03",
|
|
35713
|
-
sentence: "Note changes are paused while the engine syncs.",
|
|
35714
|
-
action: "Retry in a moment."
|
|
35715
|
-
},
|
|
35716
|
-
note_access_unavailable: {
|
|
35717
|
-
code: "MC-C04",
|
|
35718
|
-
sentence: "Notes are temporarily unavailable.",
|
|
35719
|
-
action: "Retry in a moment."
|
|
35720
|
-
},
|
|
35721
|
-
context_cleanup_paused: {
|
|
35722
|
-
code: "MC-C05",
|
|
35723
|
-
sentence: "Context cleanup is paused while the engine syncs.",
|
|
35724
|
-
action: "Retry in a moment."
|
|
35725
|
-
},
|
|
35726
|
-
partial_history_unavailable: {
|
|
35727
|
-
code: "MC-C06",
|
|
35728
|
-
sentence: "Partial history compression is not available in the current mode.",
|
|
35729
|
-
action: "Run /ctx-recomp without a range."
|
|
35730
|
-
},
|
|
35731
|
-
smart_note_conditions_unavailable: {
|
|
35732
|
-
code: "MC-C08",
|
|
35733
|
-
sentence: "Conditional notes are not available in the current mode.",
|
|
35734
|
-
action: "Save a regular note without a condition."
|
|
35735
|
-
},
|
|
35736
|
-
history_compression_paused: {
|
|
35737
|
-
code: "MC-C09",
|
|
35738
|
-
sentence: "History compression is paused while the engine syncs.",
|
|
35739
|
-
action: "Retry in a moment."
|
|
35740
|
-
},
|
|
35741
|
-
history_compression_needs_message: {
|
|
35742
|
-
code: "MC-C12",
|
|
35743
|
-
sentence: "History compression has not seen this session since Magic Context reconnected.",
|
|
35744
|
-
action: "Send a message in this session first, then run /ctx-wrapup again."
|
|
35745
|
-
},
|
|
35746
|
-
context_service_unavailable: {
|
|
35747
|
-
code: "MC-C10",
|
|
35748
|
-
sentence: "Magic Context is temporarily unavailable.",
|
|
35749
|
-
action: "Retry in a moment."
|
|
35750
|
-
},
|
|
35751
|
-
compaction_marker_missing: {
|
|
35752
|
-
code: "MC-C11",
|
|
35753
|
-
sentence: "The history boundary marker is missing from the OpenCode store, so requests carry the full session.",
|
|
35754
|
-
action: "It is retried on every message; if this persists, run `/ctx-flush`."
|
|
35755
|
-
},
|
|
35756
|
-
memory_mirror_stalled: {
|
|
35757
|
-
code: "MC-M01",
|
|
35758
|
-
sentence: "Memory synchronization stopped before the host mirror caught up.",
|
|
35759
|
-
action: "Send another message to resume it, or run `ck doctor drain-authority`."
|
|
35760
|
-
},
|
|
35761
|
-
memory_authority_mismatch: {
|
|
35762
|
-
code: "MC-M02",
|
|
35763
|
-
sentence: "Memory authority is inconsistent between the host and module.",
|
|
35764
|
-
action: "Run `ck doctor drain-authority` before changing Rust mode."
|
|
35765
|
-
},
|
|
35766
|
-
rust_mode_unsupported: {
|
|
35767
|
-
code: "MC-S06",
|
|
35768
|
-
sentence: "Experimental Rust transform mode is not available on this OpenCode host.",
|
|
35769
|
-
action: 'Magic Context is running its TypeScript mode instead; set `transform_mode` to "ts" to stop requesting Rust.'
|
|
35770
|
-
},
|
|
35771
|
-
dreamer_task_failing: {
|
|
35772
|
-
code: "MC-S05",
|
|
35773
|
-
sentence: "A background maintenance task keeps failing on its schedule.",
|
|
35774
|
-
action: "Check the Magic Context log for the failing task and its error."
|
|
35775
|
-
}
|
|
35776
|
-
};
|
|
35777
|
-
});
|
|
35778
|
-
|
|
35779
35975
|
// ../plugin/src/features/magic-context/dreamer/tick-failure.ts
|
|
35780
35976
|
function parseFailure(value) {
|
|
35781
35977
|
if (!value)
|
|
@@ -38519,6 +38715,9 @@ async function collectHistorianRuns(storageDirPath) {
|
|
|
38519
38715
|
} catch {}
|
|
38520
38716
|
}
|
|
38521
38717
|
}
|
|
38718
|
+
function openCodeIssueLogHarnesses(hostGeneration) {
|
|
38719
|
+
return hostGeneration === "v2" ? ["opencode2", "opencode"] : ["opencode"];
|
|
38720
|
+
}
|
|
38522
38721
|
async function collectDiagnostics() {
|
|
38523
38722
|
const pluginVersion = getSelfVersion();
|
|
38524
38723
|
const configPaths = detectConfigPaths();
|
|
@@ -38528,8 +38727,6 @@ async function collectDiagnostics() {
|
|
|
38528
38727
|
const storageResolution = getStorageResolution();
|
|
38529
38728
|
const storageDirPath = storageResolution.path;
|
|
38530
38729
|
const contextDbPath = join26(storageDirPath, "context.db");
|
|
38531
|
-
const logFiles = inspectMagicContextLogs("opencode");
|
|
38532
|
-
const primaryLog = logFiles.find((file) => file.exists) ?? logFiles[0];
|
|
38533
38730
|
let compactionEnabled = false;
|
|
38534
38731
|
try {
|
|
38535
38732
|
compactionEnabled = isCompactionEnabled(loadPluginConfig(process.cwd()));
|
|
@@ -38539,6 +38736,8 @@ async function collectDiagnostics() {
|
|
|
38539
38736
|
const opencodeInstallations = describeOpenCodeInstallations(detectOpenCodeInstallations());
|
|
38540
38737
|
const activeInstallation = opencodeInstallations[0];
|
|
38541
38738
|
const hostGeneration = openCodeHostGenerationFromVersion(activeInstallation?.version);
|
|
38739
|
+
const logFiles = openCodeIssueLogHarnesses(hostGeneration).flatMap((harness) => inspectMagicContextLogs(harness)).filter((file, index, all) => all.findIndex((other) => other.path === file.path) === index);
|
|
38740
|
+
const primaryLog = logFiles.find((file) => file.exists) ?? logFiles[0];
|
|
38542
38741
|
const conflictResult = detectConflicts(process.cwd(), { compactionEnabled, hostGeneration });
|
|
38543
38742
|
const openCodeDatabaseResolution = resolveOpenCodeDbPath(hostGeneration);
|
|
38544
38743
|
const recentSessions = await collectRecentSessions(openCodeDatabaseResolution, hostGeneration);
|
|
@@ -40046,6 +40245,179 @@ var init_storage_versions = __esm(async () => {
|
|
|
40046
40245
|
await init_storage_db();
|
|
40047
40246
|
});
|
|
40048
40247
|
|
|
40248
|
+
// src/commands/doctor-opencode-cache.ts
|
|
40249
|
+
import { existsSync as existsSync36, readFileSync as readFileSync25, rmSync as rmSync4 } from "node:fs";
|
|
40250
|
+
function readCachedPluginVersion(pluginCacheDir) {
|
|
40251
|
+
try {
|
|
40252
|
+
const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
|
|
40253
|
+
if (!existsSync36(installedPkgPath))
|
|
40254
|
+
return;
|
|
40255
|
+
const pkg = JSON.parse(readFileSync25(installedPkgPath, "utf-8"));
|
|
40256
|
+
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
40257
|
+
} catch {
|
|
40258
|
+
return;
|
|
40259
|
+
}
|
|
40260
|
+
}
|
|
40261
|
+
async function clearPluginCache(options = {}, deps = {}) {
|
|
40262
|
+
const remove = deps.remove ?? ((path) => rmSync4(path, { recursive: true, force: true }));
|
|
40263
|
+
const pluginCacheRoots = getOpenCodePluginCacheRoots();
|
|
40264
|
+
const existingRoots = pluginCacheRoots.filter((root) => existsSync36(root));
|
|
40265
|
+
if (existingRoots.length === 0) {
|
|
40266
|
+
return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
|
|
40267
|
+
}
|
|
40268
|
+
const latestVersion = options.latestVersion ?? undefined;
|
|
40269
|
+
const cacheEntries = existingRoots.map((path) => ({
|
|
40270
|
+
path,
|
|
40271
|
+
cached: readCachedPluginVersion(path)
|
|
40272
|
+
}));
|
|
40273
|
+
if (options.force !== true && latestVersion === undefined) {
|
|
40274
|
+
const firstEntry = cacheEntries[0];
|
|
40275
|
+
return {
|
|
40276
|
+
action: "check_unavailable",
|
|
40277
|
+
path: firstEntry?.path ?? pluginCacheRoots[0] ?? "",
|
|
40278
|
+
paths: cacheEntries.map((entry) => entry.path),
|
|
40279
|
+
cached: firstEntry?.cached
|
|
40280
|
+
};
|
|
40281
|
+
}
|
|
40282
|
+
const clearTargets = cacheEntries.filter((entry) => options.force === true || entry.cached === undefined || entry.cached !== latestVersion);
|
|
40283
|
+
if (clearTargets.length === 0) {
|
|
40284
|
+
const firstEntry = cacheEntries[0];
|
|
40285
|
+
return {
|
|
40286
|
+
action: "up_to_date",
|
|
40287
|
+
path: firstEntry?.path ?? pluginCacheRoots[0] ?? "",
|
|
40288
|
+
paths: cacheEntries.map((entry) => entry.path),
|
|
40289
|
+
cached: firstEntry?.cached,
|
|
40290
|
+
latest: latestVersion
|
|
40291
|
+
};
|
|
40292
|
+
}
|
|
40293
|
+
const cleared = [];
|
|
40294
|
+
const failed = [];
|
|
40295
|
+
for (const entry of clearTargets) {
|
|
40296
|
+
try {
|
|
40297
|
+
remove(entry.path);
|
|
40298
|
+
cleared.push(entry);
|
|
40299
|
+
} catch (err) {
|
|
40300
|
+
failed.push({
|
|
40301
|
+
path: entry.path,
|
|
40302
|
+
error: err instanceof Error ? err.message : String(err)
|
|
40303
|
+
});
|
|
40304
|
+
}
|
|
40305
|
+
}
|
|
40306
|
+
if (failed.length > 0) {
|
|
40307
|
+
const firstFailure = failed[0];
|
|
40308
|
+
return {
|
|
40309
|
+
action: "error",
|
|
40310
|
+
path: firstFailure?.path ?? clearTargets[0]?.path ?? existingRoots[0] ?? "",
|
|
40311
|
+
paths: failed.map((entry) => entry.path),
|
|
40312
|
+
clearedPaths: cleared.map((entry) => entry.path),
|
|
40313
|
+
failedPaths: failed.map((entry) => entry.path),
|
|
40314
|
+
error: firstFailure?.error
|
|
40315
|
+
};
|
|
40316
|
+
}
|
|
40317
|
+
const firstTarget = cleared[0];
|
|
40318
|
+
return {
|
|
40319
|
+
action: "cleared",
|
|
40320
|
+
path: firstTarget?.path ?? pluginCacheRoots[0] ?? "",
|
|
40321
|
+
paths: cleared.map((entry) => entry.path),
|
|
40322
|
+
cached: firstTarget?.cached,
|
|
40323
|
+
latest: latestVersion
|
|
40324
|
+
};
|
|
40325
|
+
}
|
|
40326
|
+
var init_doctor_opencode_cache = __esm(() => {
|
|
40327
|
+
init_opencode_plugin_cache();
|
|
40328
|
+
});
|
|
40329
|
+
|
|
40330
|
+
// src/commands/doctor-cached-plugin-fence.ts
|
|
40331
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
40332
|
+
import { dirname as dirname18 } from "node:path";
|
|
40333
|
+
function listCachedOpenCodePluginFences(sources = {}) {
|
|
40334
|
+
const fences = [];
|
|
40335
|
+
for (const root of sources.openCodeV1Roots ?? getOpenCodePluginCacheRoots()) {
|
|
40336
|
+
const packageJson = getOpenCodePluginPackageJsonPath(root);
|
|
40337
|
+
if (!existsSync37(packageJson))
|
|
40338
|
+
continue;
|
|
40339
|
+
fences.push({
|
|
40340
|
+
host: "opencode1",
|
|
40341
|
+
directory: root,
|
|
40342
|
+
version: readCachedPluginVersion(root),
|
|
40343
|
+
supportedVersion: readFenceFromDist(dirname18(packageJson))
|
|
40344
|
+
});
|
|
40345
|
+
}
|
|
40346
|
+
for (const slot of listOpenCodeV2PluginCacheSlots(sources.openCodeV2NpmCacheDir)) {
|
|
40347
|
+
if (!isOpenCodePluginDistTag(slot.spec))
|
|
40348
|
+
continue;
|
|
40349
|
+
const generation = getOpenCodeV2ActiveGeneration(slot.slot);
|
|
40350
|
+
if (!generation)
|
|
40351
|
+
continue;
|
|
40352
|
+
fences.push({
|
|
40353
|
+
host: "opencode2",
|
|
40354
|
+
directory: slot.slot,
|
|
40355
|
+
spec: slot.spec,
|
|
40356
|
+
version: slot.version,
|
|
40357
|
+
supportedVersion: readFenceFromDist(dirname18(getOpenCodePluginPackageJsonPath(generation)))
|
|
40358
|
+
});
|
|
40359
|
+
}
|
|
40360
|
+
return fences;
|
|
40361
|
+
}
|
|
40362
|
+
function readContextDbSchemaVersion(path) {
|
|
40363
|
+
let db = null;
|
|
40364
|
+
try {
|
|
40365
|
+
db = openExistingDatabase(path, { readonly: true });
|
|
40366
|
+
return db === null ? null : getPersistedSchemaVersion(db);
|
|
40367
|
+
} catch {
|
|
40368
|
+
return null;
|
|
40369
|
+
} finally {
|
|
40370
|
+
db?.close();
|
|
40371
|
+
}
|
|
40372
|
+
}
|
|
40373
|
+
function compareCachedPluginFences(fences, databaseVersion) {
|
|
40374
|
+
return fences.map((fence) => ({
|
|
40375
|
+
...fence,
|
|
40376
|
+
databaseVersion,
|
|
40377
|
+
status: fence.supportedVersion === null ? "unknown" : fence.supportedVersion < databaseVersion ? "behind" : "supported"
|
|
40378
|
+
}));
|
|
40379
|
+
}
|
|
40380
|
+
function hostLabel(fence) {
|
|
40381
|
+
if (fence.host === "opencode1")
|
|
40382
|
+
return "OpenCode 1";
|
|
40383
|
+
return fence.spec && fence.spec !== "latest" ? `OpenCode 2 (@${fence.spec})` : "OpenCode 2";
|
|
40384
|
+
}
|
|
40385
|
+
function reportCachedPluginFences(findings, report) {
|
|
40386
|
+
const supported = [];
|
|
40387
|
+
let behind = 0;
|
|
40388
|
+
for (const finding of findings) {
|
|
40389
|
+
const label = hostLabel(finding);
|
|
40390
|
+
const version = finding.version ?? "unknown version";
|
|
40391
|
+
if (finding.status === "supported") {
|
|
40392
|
+
supported.push(`${label} ${version} (fence v${finding.supportedVersion})`);
|
|
40393
|
+
continue;
|
|
40394
|
+
}
|
|
40395
|
+
if (finding.status === "unknown") {
|
|
40396
|
+
report.info(`${label} plugin cache: could not read the schema fence of Magic Context ${version}, so doctor cannot tell whether it supports context.db v${finding.databaseVersion}`);
|
|
40397
|
+
report.info(` ${finding.directory}`);
|
|
40398
|
+
continue;
|
|
40399
|
+
}
|
|
40400
|
+
behind++;
|
|
40401
|
+
report.fail(`${label} has Magic Context ${version} cached, which supports context.db only through schema v${finding.supportedVersion}, but the shared context.db is at v${finding.databaseVersion}. A newer Magic Context (usually the other OpenCode host) migrated it, so ${label} fails closed on every prompt; an @latest entry does not refresh this cached copy.`);
|
|
40402
|
+
report.info(` ${finding.directory}`);
|
|
40403
|
+
report.info(finding.host === "opencode1" ? " To fix: quit OpenCode 1 and delete that directory; OpenCode 1 installs the current release on its next start." : ` To fix, ${OPENCODE_V2_PLUGIN_UPDATE_HINT}, then restart OpenCode 2.`);
|
|
40404
|
+
}
|
|
40405
|
+
if (supported.length > 0) {
|
|
40406
|
+
report.pass(`Cached Magic Context copies support context.db v${findings[0]?.databaseVersion}: ${supported.join(", ")}`);
|
|
40407
|
+
}
|
|
40408
|
+
return { behind };
|
|
40409
|
+
}
|
|
40410
|
+
var init_doctor_cached_plugin_fence = __esm(async () => {
|
|
40411
|
+
init_opencode_plugin_cache();
|
|
40412
|
+
init_opencode_plugin_schema_fence();
|
|
40413
|
+
init_doctor_opencode_cache();
|
|
40414
|
+
init_doctor_opencode2_cache();
|
|
40415
|
+
await __promiseAll([
|
|
40416
|
+
init_storage_db(),
|
|
40417
|
+
init_database_access()
|
|
40418
|
+
]);
|
|
40419
|
+
});
|
|
40420
|
+
|
|
40049
40421
|
// src/commands/doctor-compaction-markers.ts
|
|
40050
40422
|
function safeData(column = "data") {
|
|
40051
40423
|
return `CASE WHEN json_valid(${column}) THEN ${column} ELSE '{}' END`;
|
|
@@ -40101,6 +40473,21 @@ function countUnmatchedConvertedMarkers(db, migratedV2Schema) {
|
|
|
40101
40473
|
)`).get();
|
|
40102
40474
|
return Number(row?.count ?? 0);
|
|
40103
40475
|
}
|
|
40476
|
+
function countPostConversionMessages(db, migratedV2Schema) {
|
|
40477
|
+
if (!migratedV2Schema || !tableExists4(db, "message") || !tableExists4(db, "session")) {
|
|
40478
|
+
return { messages: 0, sessions: 0 };
|
|
40479
|
+
}
|
|
40480
|
+
const row = db.prepare(`SELECT COUNT(*) AS messages, COUNT(DISTINCT converted.session_id) AS sessions
|
|
40481
|
+
FROM session_message converted
|
|
40482
|
+
WHERE EXISTS (SELECT 1 FROM session legacy WHERE legacy.id = converted.session_id)
|
|
40483
|
+
AND NOT EXISTS (
|
|
40484
|
+
SELECT 1
|
|
40485
|
+
FROM message source
|
|
40486
|
+
WHERE source.session_id = converted.session_id
|
|
40487
|
+
AND source.time_created = converted.time_created
|
|
40488
|
+
)`).get();
|
|
40489
|
+
return { messages: Number(row?.messages ?? 0), sessions: Number(row?.sessions ?? 0) };
|
|
40490
|
+
}
|
|
40104
40491
|
function checkOpenCodeCompactionMarkerConversion(db, options = {}) {
|
|
40105
40492
|
const missingBefore = countMissingCompleted(db);
|
|
40106
40493
|
let repaired = 0;
|
|
@@ -40121,6 +40508,7 @@ function checkOpenCodeCompactionMarkerConversion(db, options = {}) {
|
|
|
40121
40508
|
const migratedV2Schema = tableExists4(db, "session_v2") && tableExists4(db, "session_message");
|
|
40122
40509
|
const migrationCompleted = migrationV1ToV2Completed(db);
|
|
40123
40510
|
const unmatchedConvertedMarkers = countUnmatchedConvertedMarkers(db, migratedV2Schema);
|
|
40511
|
+
const postConversion = countPostConversionMessages(db, migratedV2Schema);
|
|
40124
40512
|
return {
|
|
40125
40513
|
missingBefore,
|
|
40126
40514
|
missingAfter,
|
|
@@ -40128,21 +40516,23 @@ function checkOpenCodeCompactionMarkerConversion(db, options = {}) {
|
|
|
40128
40516
|
migrationCompleted,
|
|
40129
40517
|
migratedV2Schema,
|
|
40130
40518
|
unmatchedConvertedMarkers,
|
|
40131
|
-
|
|
40519
|
+
postConversionMessages: postConversion.messages,
|
|
40520
|
+
postConversionSessions: postConversion.sessions
|
|
40132
40521
|
};
|
|
40133
40522
|
}
|
|
40134
40523
|
function formatOpenCodeCompactionMarkerConversion(report) {
|
|
40135
40524
|
return `OpenCode compaction markers are convertible to OpenCode 2: before=${report.missingBefore} missing time.completed; after=${report.missingAfter}`;
|
|
40136
40525
|
}
|
|
40137
|
-
function
|
|
40138
|
-
|
|
40139
|
-
|
|
40140
|
-
|
|
40141
|
-
|
|
40142
|
-
|
|
40143
|
-
"
|
|
40144
|
-
'Wait until `SELECT value FROM kv WHERE key = \'migration.v1-v2\';` reads `{"phase":"completed"}` before stopping that manual server'
|
|
40526
|
+
function formatOpenCodeV2MissingMarkerNotice(report) {
|
|
40527
|
+
if (!report.migrationCompleted || !report.migratedV2Schema || report.unmatchedConvertedMarkers === 0) {
|
|
40528
|
+
return null;
|
|
40529
|
+
}
|
|
40530
|
+
const lines = [
|
|
40531
|
+
`OpenCode 2's conversion did not carry over ${report.unmatchedConvertedMarkers} Magic Context compaction marker(s). No action is needed.`,
|
|
40532
|
+
"Magic Context on OpenCode 2 does not use host compaction rows: it keeps its own boundary and re-derives compartment positions from the messages that survived. OpenCode reads these sessions' full history on each turn, as it does for any Magic Context session started on OpenCode 2."
|
|
40145
40533
|
];
|
|
40534
|
+
lines.push(report.postConversionMessages > 0 ? `Do not clear kv.migration.v1-v2 to reconvert: OpenCode 2 would rebuild every converted session from its OpenCode 1 rows and delete the ${report.postConversionMessages} message(s) it added after the conversion, in ${report.postConversionSessions} session(s).` : "Do not clear kv.migration.v1-v2 to reconvert: OpenCode 2 would rebuild every converted session from its OpenCode 1 rows, deleting anything added on OpenCode 2 since.", "If you already reconverted, restore opencode.db (with its -wal and -shm files) from a backup taken before the reconversion.");
|
|
40535
|
+
return lines;
|
|
40146
40536
|
}
|
|
40147
40537
|
|
|
40148
40538
|
// src/commands/doctor-compartment-boundaries.ts
|
|
@@ -40226,88 +40616,6 @@ var init_doctor_harness_relabel = __esm(async () => {
|
|
|
40226
40616
|
await init_opencode2_relabel();
|
|
40227
40617
|
});
|
|
40228
40618
|
|
|
40229
|
-
// src/commands/doctor-opencode-cache.ts
|
|
40230
|
-
import { existsSync as existsSync36, readFileSync as readFileSync25, rmSync as rmSync4 } from "node:fs";
|
|
40231
|
-
function readCachedPluginVersion(pluginCacheDir) {
|
|
40232
|
-
try {
|
|
40233
|
-
const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
|
|
40234
|
-
if (!existsSync36(installedPkgPath))
|
|
40235
|
-
return;
|
|
40236
|
-
const pkg = JSON.parse(readFileSync25(installedPkgPath, "utf-8"));
|
|
40237
|
-
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
40238
|
-
} catch {
|
|
40239
|
-
return;
|
|
40240
|
-
}
|
|
40241
|
-
}
|
|
40242
|
-
async function clearPluginCache(options = {}, deps = {}) {
|
|
40243
|
-
const remove = deps.remove ?? ((path) => rmSync4(path, { recursive: true, force: true }));
|
|
40244
|
-
const pluginCacheRoots = getOpenCodePluginCacheRoots();
|
|
40245
|
-
const existingRoots = pluginCacheRoots.filter((root) => existsSync36(root));
|
|
40246
|
-
if (existingRoots.length === 0) {
|
|
40247
|
-
return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
|
|
40248
|
-
}
|
|
40249
|
-
const latestVersion = options.latestVersion ?? undefined;
|
|
40250
|
-
const cacheEntries = existingRoots.map((path) => ({
|
|
40251
|
-
path,
|
|
40252
|
-
cached: readCachedPluginVersion(path)
|
|
40253
|
-
}));
|
|
40254
|
-
if (options.force !== true && latestVersion === undefined) {
|
|
40255
|
-
const firstEntry = cacheEntries[0];
|
|
40256
|
-
return {
|
|
40257
|
-
action: "check_unavailable",
|
|
40258
|
-
path: firstEntry?.path ?? pluginCacheRoots[0] ?? "",
|
|
40259
|
-
paths: cacheEntries.map((entry) => entry.path),
|
|
40260
|
-
cached: firstEntry?.cached
|
|
40261
|
-
};
|
|
40262
|
-
}
|
|
40263
|
-
const clearTargets = cacheEntries.filter((entry) => options.force === true || entry.cached === undefined || entry.cached !== latestVersion);
|
|
40264
|
-
if (clearTargets.length === 0) {
|
|
40265
|
-
const firstEntry = cacheEntries[0];
|
|
40266
|
-
return {
|
|
40267
|
-
action: "up_to_date",
|
|
40268
|
-
path: firstEntry?.path ?? pluginCacheRoots[0] ?? "",
|
|
40269
|
-
paths: cacheEntries.map((entry) => entry.path),
|
|
40270
|
-
cached: firstEntry?.cached,
|
|
40271
|
-
latest: latestVersion
|
|
40272
|
-
};
|
|
40273
|
-
}
|
|
40274
|
-
const cleared = [];
|
|
40275
|
-
const failed = [];
|
|
40276
|
-
for (const entry of clearTargets) {
|
|
40277
|
-
try {
|
|
40278
|
-
remove(entry.path);
|
|
40279
|
-
cleared.push(entry);
|
|
40280
|
-
} catch (err) {
|
|
40281
|
-
failed.push({
|
|
40282
|
-
path: entry.path,
|
|
40283
|
-
error: err instanceof Error ? err.message : String(err)
|
|
40284
|
-
});
|
|
40285
|
-
}
|
|
40286
|
-
}
|
|
40287
|
-
if (failed.length > 0) {
|
|
40288
|
-
const firstFailure = failed[0];
|
|
40289
|
-
return {
|
|
40290
|
-
action: "error",
|
|
40291
|
-
path: firstFailure?.path ?? clearTargets[0]?.path ?? existingRoots[0] ?? "",
|
|
40292
|
-
paths: failed.map((entry) => entry.path),
|
|
40293
|
-
clearedPaths: cleared.map((entry) => entry.path),
|
|
40294
|
-
failedPaths: failed.map((entry) => entry.path),
|
|
40295
|
-
error: firstFailure?.error
|
|
40296
|
-
};
|
|
40297
|
-
}
|
|
40298
|
-
const firstTarget = cleared[0];
|
|
40299
|
-
return {
|
|
40300
|
-
action: "cleared",
|
|
40301
|
-
path: firstTarget?.path ?? pluginCacheRoots[0] ?? "",
|
|
40302
|
-
paths: cleared.map((entry) => entry.path),
|
|
40303
|
-
cached: firstTarget?.cached,
|
|
40304
|
-
latest: latestVersion
|
|
40305
|
-
};
|
|
40306
|
-
}
|
|
40307
|
-
var init_doctor_opencode_cache = __esm(() => {
|
|
40308
|
-
init_opencode_plugin_cache();
|
|
40309
|
-
});
|
|
40310
|
-
|
|
40311
40619
|
// src/commands/doctor-opencode-plugin-duplicates.ts
|
|
40312
40620
|
import { isDeepStrictEqual } from "node:util";
|
|
40313
40621
|
function entryOptions(entry) {
|
|
@@ -40535,10 +40843,21 @@ function formatUnresolvedCompartmentSession(session) {
|
|
|
40535
40843
|
|
|
40536
40844
|
// src/commands/doctor-opencode.ts
|
|
40537
40845
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
40538
|
-
import { existsSync as
|
|
40846
|
+
import { existsSync as existsSync38, mkdtempSync, readFileSync as readFileSync26, rmSync as rmSync5 } from "node:fs";
|
|
40539
40847
|
import { createRequire as createRequire6 } from "node:module";
|
|
40540
40848
|
import { homedir as homedir16, tmpdir as tmpdir3 } from "node:os";
|
|
40541
40849
|
import { join as join32 } from "node:path";
|
|
40850
|
+
function formatSharedDbRowCounts(db) {
|
|
40851
|
+
return SHARED_DB_ROW_COUNT_TABLES.map((table) => {
|
|
40852
|
+
try {
|
|
40853
|
+
const row = db.prepare(`SELECT COUNT(*) AS c FROM ${table}`).get();
|
|
40854
|
+
return `${table}=${typeof row?.c === "number" ? row.c : "n/a"}`;
|
|
40855
|
+
} catch (error) {
|
|
40856
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
40857
|
+
return `${table}=n/a (${sanitizeDiagnosticText(reason)})`;
|
|
40858
|
+
}
|
|
40859
|
+
}).join(", ");
|
|
40860
|
+
}
|
|
40542
40861
|
function findUndeclaredConfiguredVariants(configured, catalog) {
|
|
40543
40862
|
return configured.filter((entry) => {
|
|
40544
40863
|
const [providerID, id] = entry.model.split("/", 2);
|
|
@@ -40546,6 +40865,18 @@ function findUndeclaredConfiguredVariants(configured, catalog) {
|
|
|
40546
40865
|
return model !== undefined && !Object.hasOwn(model.variants, entry.variant);
|
|
40547
40866
|
});
|
|
40548
40867
|
}
|
|
40868
|
+
function findUnknownConfiguredModels(configured, catalog) {
|
|
40869
|
+
return configured.flatMap((entry) => {
|
|
40870
|
+
const [providerID, id] = entry.model.split("/", 2);
|
|
40871
|
+
if (!catalog.some((item) => item.providerID === providerID)) {
|
|
40872
|
+
return [{ ...entry, unknown: "provider" }];
|
|
40873
|
+
}
|
|
40874
|
+
if (!catalog.some((item) => item.providerID === providerID && item.id === id)) {
|
|
40875
|
+
return [{ ...entry, unknown: "model" }];
|
|
40876
|
+
}
|
|
40877
|
+
return [];
|
|
40878
|
+
});
|
|
40879
|
+
}
|
|
40549
40880
|
function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) => spawnSync8("opencode", args, {
|
|
40550
40881
|
cwd,
|
|
40551
40882
|
encoding: "utf8",
|
|
@@ -40553,6 +40884,7 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
|
|
|
40553
40884
|
maxBuffer: 16 * 1024 * 1024
|
|
40554
40885
|
}), projectDir = process.cwd()) {
|
|
40555
40886
|
const configured = [];
|
|
40887
|
+
const models = [];
|
|
40556
40888
|
const root = config && typeof config === "object" ? config : {};
|
|
40557
40889
|
for (const agent of ["historian", "dreamer"]) {
|
|
40558
40890
|
const section = root[agent];
|
|
@@ -40562,21 +40894,25 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
|
|
|
40562
40894
|
if (!block || typeof block !== "object")
|
|
40563
40895
|
continue;
|
|
40564
40896
|
const record = block;
|
|
40565
|
-
const add = (entry, defaultVariant) => {
|
|
40897
|
+
const add = (entry, defaultVariant, fallback) => {
|
|
40566
40898
|
const value = entry && typeof entry === "object" ? entry : {};
|
|
40567
40899
|
const model = typeof entry === "string" ? entry : value.model;
|
|
40568
40900
|
const variant = value.variant ?? defaultVariant;
|
|
40569
|
-
if (typeof model
|
|
40570
|
-
|
|
40901
|
+
if (typeof model !== "string" || !model.includes("/"))
|
|
40902
|
+
return;
|
|
40903
|
+
if (!models.some((known) => known.agent === agent && known.model === model)) {
|
|
40904
|
+
models.push({ agent, model, fallback });
|
|
40571
40905
|
}
|
|
40906
|
+
if (typeof variant === "string")
|
|
40907
|
+
configured.push({ agent, model, variant });
|
|
40572
40908
|
};
|
|
40573
|
-
add(record.model, record.variant);
|
|
40909
|
+
add(record.model, record.variant, false);
|
|
40574
40910
|
if (Array.isArray(record.fallback_models)) {
|
|
40575
40911
|
for (const entry of record.fallback_models)
|
|
40576
|
-
add(entry, undefined);
|
|
40912
|
+
add(entry, undefined, true);
|
|
40577
40913
|
}
|
|
40578
40914
|
}
|
|
40579
|
-
if (
|
|
40915
|
+
if (models.length === 0)
|
|
40580
40916
|
return;
|
|
40581
40917
|
const tempRoot = mkdtempSync(join32(tmpdir3(), "magic-context-opencode-catalog-"));
|
|
40582
40918
|
try {
|
|
@@ -40585,9 +40921,14 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
|
|
|
40585
40921
|
const result = run(command, tempRoot);
|
|
40586
40922
|
const catalog = hostGeneration === "v2" ? parseOpenCodeV2ModelCatalog(result.stdout ?? "") : parseOpenCodeModelCatalog(result.stdout ?? "");
|
|
40587
40923
|
if (result.error || result.status !== 0 || catalog.length === 0) {
|
|
40588
|
-
warn(`Could not verify configured hidden-agent variants: this OpenCode host did not provide a readable model catalog. ${hostGeneration === "v2" ? "Start the background service with opencode service start, then check" : "Check"} ${guidance}.`);
|
|
40924
|
+
warn(`Could not verify configured hidden-agent models and variants: this OpenCode host did not provide a readable model catalog. ${hostGeneration === "v2" ? "Start the background service with opencode service start, then check" : "Check"} ${guidance}.`);
|
|
40589
40925
|
return;
|
|
40590
40926
|
}
|
|
40927
|
+
for (const entry of findUnknownConfiguredModels(models, catalog)) {
|
|
40928
|
+
const [providerID] = entry.model.split("/", 1);
|
|
40929
|
+
const role = `${entry.agent}${entry.fallback ? " fallback" : ""} model ${entry.model}`;
|
|
40930
|
+
warn(entry.unknown === "provider" ? `${role} names provider '${providerID}', which this OpenCode host does not have. The ${entry.agent} cannot run on it; configure that provider in OpenCode or choose a model listed by ${guidance}.` : `${role} is not offered by provider '${providerID}' on this OpenCode host. The ${entry.agent} cannot run on it; choose a model listed by ${guidance}.`);
|
|
40931
|
+
}
|
|
40591
40932
|
for (const entry of findUndeclaredConfiguredVariants(configured, catalog)) {
|
|
40592
40933
|
warn(`${entry.agent} model ${entry.model} requests variant '${entry.variant}', which this host does not offer. Remove the variant or choose one listed by ${guidance}.`);
|
|
40593
40934
|
}
|
|
@@ -40763,7 +41104,7 @@ function getUserNpmrcPath() {
|
|
|
40763
41104
|
function collectNpmReleaseAgeWarnings() {
|
|
40764
41105
|
const ageWarnings = [];
|
|
40765
41106
|
const npmrcPath = getUserNpmrcPath();
|
|
40766
|
-
if (!
|
|
41107
|
+
if (!existsSync38(npmrcPath))
|
|
40767
41108
|
return ageWarnings;
|
|
40768
41109
|
try {
|
|
40769
41110
|
const npmrc = readFileSync26(npmrcPath, "utf-8");
|
|
@@ -40900,7 +41241,7 @@ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
|
|
|
40900
41241
|
return { issues: 0 };
|
|
40901
41242
|
}
|
|
40902
41243
|
async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
40903
|
-
if (!
|
|
41244
|
+
if (!existsSync38(magicContextConfigPath)) {
|
|
40904
41245
|
return checkLocalEmbeddingRuntimeForDoctor();
|
|
40905
41246
|
}
|
|
40906
41247
|
let rawText;
|
|
@@ -41108,7 +41449,7 @@ async function runDoctor2(options = {}) {
|
|
|
41108
41449
|
const activeInstallation = installationReports[0];
|
|
41109
41450
|
if (!activeInstallation) {
|
|
41110
41451
|
fail("OpenCode is not installed or not in PATH");
|
|
41111
|
-
log2.info("Doctor checked ~/.opencode/bin/opencode
|
|
41452
|
+
log2.info("Doctor checked ~/.opencode/bin/opencode, each entry in $PATH, and the OpenCode CLI bundled in OpenChamber.app.");
|
|
41112
41453
|
log2.info("If `which opencode` succeeds outside doctor, your wrapper or shim may not be readable by Node — please share that wrapper in the issue.");
|
|
41113
41454
|
outro2("Doctor failed — install OpenCode first");
|
|
41114
41455
|
return 1;
|
|
@@ -41124,7 +41465,19 @@ async function runDoctor2(options = {}) {
|
|
|
41124
41465
|
pass(installationReports.length > 1 ? `OpenCode ${activeInstallation.version} installed (active install marked above)` : `OpenCode ${activeInstallation.version} installed`);
|
|
41125
41466
|
}
|
|
41126
41467
|
const hostGeneration = openCodeHostGenerationFromVersion(activeInstallation.version);
|
|
41127
|
-
const
|
|
41468
|
+
const storeHostSelection = selectOpenCodeStoreHost(installationReports, openCodeHostGenerationFromVersion);
|
|
41469
|
+
const storeHost = storeHostSelection?.host ?? activeInstallation;
|
|
41470
|
+
const storeGeneration = openCodeHostGenerationFromVersion(storeHost.version);
|
|
41471
|
+
const openCodeDbResolution = resolveOpenCodeDbPath(storeGeneration);
|
|
41472
|
+
if (storeHostSelection?.shadowed) {
|
|
41473
|
+
const activeStore = resolveOpenCodeDbPath(hostGeneration).path;
|
|
41474
|
+
const shared = activeStore === openCodeDbResolution.path;
|
|
41475
|
+
const versionLabel = (version) => version.replace(/^opencode\s+v?/i, "");
|
|
41476
|
+
const activeVersion = versionLabel(activeInstallation.version);
|
|
41477
|
+
const storeVersion = versionLabel(storeHost.version);
|
|
41478
|
+
warn(`OpenCode ${activeVersion} (${activeInstallation.path}) is first on PATH, and OpenCode ${storeVersion} is also installed (${storeHost.path})${shared ? `; both use ${openCodeDbResolution.path}` : ""}.`);
|
|
41479
|
+
log2.warn(` Store and conversion checks below use OpenCode ${storeVersion}. Plugin configuration checks use OpenCode ${activeVersion}; to check OpenCode ${storeVersion}'s configuration instead, put its binary first on PATH and run doctor again.`);
|
|
41480
|
+
}
|
|
41128
41481
|
const openCodeDbCheck = describeOpenCodeDatabaseDoctorCheck(openCodeDbResolution);
|
|
41129
41482
|
if (openCodeDbCheck.ok)
|
|
41130
41483
|
pass(openCodeDbCheck.message);
|
|
@@ -41148,14 +41501,16 @@ async function runDoctor2(options = {}) {
|
|
|
41148
41501
|
fixed += report.repaired;
|
|
41149
41502
|
} else if (options.fix) {
|
|
41150
41503
|
warn(`${summary}; repaired=${report.repaired}, but some rows remain unconvertible`);
|
|
41504
|
+
} else if (report.migrationCompleted) {
|
|
41505
|
+
log2.info(`${summary}; OpenCode 2 already converted this store`);
|
|
41151
41506
|
} else {
|
|
41152
41507
|
warn(`${summary}; run \`magic-context doctor --fix\` before upgrading OpenCode`);
|
|
41153
41508
|
}
|
|
41154
|
-
|
|
41155
|
-
|
|
41156
|
-
|
|
41157
|
-
|
|
41158
|
-
|
|
41509
|
+
const notice = formatOpenCodeV2MissingMarkerNotice(report);
|
|
41510
|
+
if (notice) {
|
|
41511
|
+
for (const [index, line] of notice.entries()) {
|
|
41512
|
+
log2.info(index === 0 ? line : ` ${line}`);
|
|
41513
|
+
}
|
|
41159
41514
|
}
|
|
41160
41515
|
} catch (error) {
|
|
41161
41516
|
warn(`OpenCode compaction marker conversion check unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -41171,9 +41526,14 @@ async function runDoctor2(options = {}) {
|
|
|
41171
41526
|
readonly: true,
|
|
41172
41527
|
fileMustExist: true
|
|
41173
41528
|
});
|
|
41174
|
-
const dangling = listDanglingCompartmentBoundaries(contextDb, sessionDb, /\d/.test(
|
|
41529
|
+
const dangling = listDanglingCompartmentBoundaries(contextDb, sessionDb, /\d/.test(storeHost.version) ? storeGeneration : undefined, (line) => log2.info(line));
|
|
41175
41530
|
if (dangling.length === 0) {
|
|
41176
41531
|
pass("Compartment boundary ids resolve in the OpenCode session store");
|
|
41532
|
+
} else if (storeGeneration === "v2" && /\d/.test(storeHost.version)) {
|
|
41533
|
+
log2.info(`${dangling.length} compartment(s) point at OpenCode message ids that are not in the OpenCode 2 store. Magic Context places these from the neighbouring compartments; any it cannot place are listed as excluded from range recovery below.`);
|
|
41534
|
+
for (const boundary of dangling) {
|
|
41535
|
+
log2.info(` ${formatDanglingCompartmentBoundary(boundary)}`);
|
|
41536
|
+
}
|
|
41177
41537
|
} else {
|
|
41178
41538
|
warn(`${dangling.length} compartment(s) have dangling OpenCode boundary ids`);
|
|
41179
41539
|
for (const boundary of dangling) {
|
|
@@ -41182,11 +41542,11 @@ async function runDoctor2(options = {}) {
|
|
|
41182
41542
|
}
|
|
41183
41543
|
if (!supportsCoordinateGenerationReporting(contextDb)) {
|
|
41184
41544
|
log2.info("Store projection check: this context database predates the coordinate columns");
|
|
41185
|
-
} else if (!/\d/.test(
|
|
41545
|
+
} else if (!/\d/.test(storeHost.version)) {
|
|
41186
41546
|
log2.info("Store projection check: OpenCode reported no version, so the running projection is unknown");
|
|
41187
41547
|
} else {
|
|
41188
|
-
const pendingRebases = countPendingCoordinateRebases(contextDb,
|
|
41189
|
-
const pendingLine = formatPendingCoordinateRebases(pendingRebases,
|
|
41548
|
+
const pendingRebases = countPendingCoordinateRebases(contextDb, storeGeneration);
|
|
41549
|
+
const pendingLine = formatPendingCoordinateRebases(pendingRebases, storeGeneration);
|
|
41190
41550
|
if (pendingRebases.changed + pendingRebases.unrecorded === 0) {
|
|
41191
41551
|
pass(pendingLine);
|
|
41192
41552
|
} else {
|
|
@@ -41231,7 +41591,7 @@ async function runDoctor2(options = {}) {
|
|
|
41231
41591
|
pass(`OpenCode config: ${paths.opencodeConfig}`);
|
|
41232
41592
|
}
|
|
41233
41593
|
let autoUpdateEnabled = true;
|
|
41234
|
-
if (
|
|
41594
|
+
if (existsSync38(paths.magicContextConfig)) {
|
|
41235
41595
|
pass(`Magic Context config: ${paths.magicContextConfig}`);
|
|
41236
41596
|
try {
|
|
41237
41597
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
@@ -41267,7 +41627,7 @@ async function runDoctor2(options = {}) {
|
|
|
41267
41627
|
warn(`No magic-context.jsonc found — using defaults`);
|
|
41268
41628
|
log2.info(" Run 'setup' to create one with model recommendations");
|
|
41269
41629
|
}
|
|
41270
|
-
if (
|
|
41630
|
+
if (existsSync38(paths.magicContextConfig)) {
|
|
41271
41631
|
try {
|
|
41272
41632
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
41273
41633
|
if (!raw)
|
|
@@ -41466,7 +41826,7 @@ async function runDoctor2(options = {}) {
|
|
|
41466
41826
|
pass("Added TUI sidebar plugin to tui.json");
|
|
41467
41827
|
warn("Restart OpenCode to see the sidebar");
|
|
41468
41828
|
fixed++;
|
|
41469
|
-
} else if (
|
|
41829
|
+
} else if (existsSync38(paths.tuiConfig)) {
|
|
41470
41830
|
try {
|
|
41471
41831
|
const tuiRaw = readFileSync26(paths.tuiConfig, "utf-8");
|
|
41472
41832
|
const tuiConfig = import_comment_json11.parse(tuiRaw);
|
|
@@ -41506,7 +41866,7 @@ async function runDoctor2(options = {}) {
|
|
|
41506
41866
|
fail("Could not create or verify the TUI sidebar config");
|
|
41507
41867
|
}
|
|
41508
41868
|
}
|
|
41509
|
-
if (
|
|
41869
|
+
if (existsSync38(paths.magicContextConfig)) {
|
|
41510
41870
|
try {
|
|
41511
41871
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
41512
41872
|
if (!raw)
|
|
@@ -41530,7 +41890,7 @@ async function runDoctor2(options = {}) {
|
|
|
41530
41890
|
const storage = getMagicContextStorageResolution();
|
|
41531
41891
|
const dbPath = join32(storage.path, "context.db");
|
|
41532
41892
|
log2.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
|
|
41533
|
-
if (!
|
|
41893
|
+
if (!existsSync38(dbPath)) {
|
|
41534
41894
|
log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
|
|
41535
41895
|
} else {
|
|
41536
41896
|
log2.info(`Shared context DB exists at ${dbPath}`);
|
|
@@ -41577,25 +41937,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41577
41937
|
fail(`SQLite integrity_check failed: ${err instanceof Error ? err.message : String(err)}
|
|
41578
41938
|
${formatDatabaseRepairGuidance(dbPath)}`);
|
|
41579
41939
|
}
|
|
41580
|
-
|
|
41581
|
-
const counts = {};
|
|
41582
|
-
for (const table of [
|
|
41583
|
-
"tags",
|
|
41584
|
-
"compartments",
|
|
41585
|
-
"memories",
|
|
41586
|
-
"notes",
|
|
41587
|
-
"dream_runs"
|
|
41588
|
-
]) {
|
|
41589
|
-
try {
|
|
41590
|
-
const row = db.prepare(`SELECT COUNT(*) as c FROM ${table}`).get();
|
|
41591
|
-
counts[table] = row?.c ?? 0;
|
|
41592
|
-
} catch {
|
|
41593
|
-
counts[table] = 0;
|
|
41594
|
-
}
|
|
41595
|
-
}
|
|
41596
|
-
const summary = Object.entries(counts).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
41597
|
-
log2.info(`Shared DB row counts: ${summary}`);
|
|
41598
|
-
} catch {}
|
|
41940
|
+
log2.info(`Shared DB row counts: ${formatSharedDbRowCounts(db)}`);
|
|
41599
41941
|
for (const stall of listShadowBackfillStalls(db)) {
|
|
41600
41942
|
warn(formatShadowBackfillStall(stall));
|
|
41601
41943
|
}
|
|
@@ -41664,6 +42006,10 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41664
42006
|
fixed++;
|
|
41665
42007
|
if (v2Cache.issue)
|
|
41666
42008
|
issues++;
|
|
42009
|
+
const sharedDbVersion = readContextDbSchemaVersion(dbPath);
|
|
42010
|
+
if (sharedDbVersion !== null) {
|
|
42011
|
+
reportCachedPluginFences(compareCachedPluginFences(listCachedOpenCodePluginFences(), sharedDbVersion), { pass, fail, info: (message) => log2.info(message) });
|
|
42012
|
+
}
|
|
41667
42013
|
{
|
|
41668
42014
|
const ageWarnings = collectNpmReleaseAgeWarnings();
|
|
41669
42015
|
if (ageWarnings.length > 0) {
|
|
@@ -41676,7 +42022,11 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41676
42022
|
issues++;
|
|
41677
42023
|
}
|
|
41678
42024
|
}
|
|
41679
|
-
const
|
|
42025
|
+
const logHarnesses = [
|
|
42026
|
+
...hostGeneration === "v1" ? ["opencode"] : [],
|
|
42027
|
+
...hostGeneration === "v2" || storeGeneration === "v2" ? ["opencode2"] : []
|
|
42028
|
+
];
|
|
42029
|
+
const logFiles = logHarnesses.flatMap((harness) => inspectMagicContextLogs(harness)).filter((file, index, all) => all.findIndex((other) => other.path === file.path) === index);
|
|
41680
42030
|
const existingLogFiles = logFiles.filter((file) => file.exists);
|
|
41681
42031
|
if (existingLogFiles.length === 0) {
|
|
41682
42032
|
log2.info(`No plugin log file yet; checked: ${logFiles.map((file) => file.path).join(", ")}`);
|
|
@@ -41724,7 +42074,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
41724
42074
|
}
|
|
41725
42075
|
return 0;
|
|
41726
42076
|
}
|
|
41727
|
-
var import_comment_json11, CLI_PACKAGE_NAME = "@cortexkit/magic-context";
|
|
42077
|
+
var import_comment_json11, CLI_PACKAGE_NAME = "@cortexkit/magic-context", SHARED_DB_ROW_COUNT_TABLES;
|
|
41728
42078
|
var init_doctor_opencode = __esm(async () => {
|
|
41729
42079
|
init_config();
|
|
41730
42080
|
init_agent_disable();
|
|
@@ -41768,13 +42118,15 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
41768
42118
|
init_storage_versions(),
|
|
41769
42119
|
init_v22_backfill_commands(),
|
|
41770
42120
|
init_doctor_authority(),
|
|
42121
|
+
init_doctor_cached_plugin_fence(),
|
|
41771
42122
|
init_doctor_harness_relabel()
|
|
41772
42123
|
]);
|
|
41773
42124
|
import_comment_json11 = __toESM(require_src3(), 1);
|
|
42125
|
+
SHARED_DB_ROW_COUNT_TABLES = ["tags", "compartments", "memories", "notes", "dream_runs"];
|
|
41774
42126
|
});
|
|
41775
42127
|
|
|
41776
42128
|
// src/lib/diagnostics-pi.ts
|
|
41777
|
-
import { existsSync as
|
|
42129
|
+
import { existsSync as existsSync39, readdirSync as readdirSync7, readFileSync as readFileSync27, statSync as statSync16 } from "node:fs";
|
|
41778
42130
|
import { createRequire as createRequire7 } from "node:module";
|
|
41779
42131
|
import { join as join33 } from "node:path";
|
|
41780
42132
|
function getSelfVersion3() {
|
|
@@ -41791,7 +42143,7 @@ function getSelfVersion3() {
|
|
|
41791
42143
|
}
|
|
41792
42144
|
function fileSize2(path) {
|
|
41793
42145
|
try {
|
|
41794
|
-
return
|
|
42146
|
+
return existsSync39(path) ? statSync16(path).size : 0;
|
|
41795
42147
|
} catch {
|
|
41796
42148
|
return 0;
|
|
41797
42149
|
}
|
|
@@ -41803,7 +42155,7 @@ function sanitizeValue2(value) {
|
|
|
41803
42155
|
return sanitizeConfigValue(value);
|
|
41804
42156
|
}
|
|
41805
42157
|
function readJsonc(path) {
|
|
41806
|
-
if (!
|
|
42158
|
+
if (!existsSync39(path))
|
|
41807
42159
|
return { value: {} };
|
|
41808
42160
|
try {
|
|
41809
42161
|
return {
|
|
@@ -41823,7 +42175,7 @@ function readConfigDiagnostic(path) {
|
|
|
41823
42175
|
const parsed = readJsonc(path);
|
|
41824
42176
|
return {
|
|
41825
42177
|
path,
|
|
41826
|
-
exists:
|
|
42178
|
+
exists: existsSync39(path),
|
|
41827
42179
|
...parsed.parseError ? { parseError: parsed.parseError } : {},
|
|
41828
42180
|
flags: sanitizeValue2(parsed.value)
|
|
41829
42181
|
};
|
|
@@ -41841,7 +42193,7 @@ function reverseSlugToDirectory(slug) {
|
|
|
41841
42193
|
}
|
|
41842
42194
|
function collectPiRecentSessions() {
|
|
41843
42195
|
const sessionsRoot = getPiSessionsRoot();
|
|
41844
|
-
if (!
|
|
42196
|
+
if (!existsSync39(sessionsRoot))
|
|
41845
42197
|
return [];
|
|
41846
42198
|
try {
|
|
41847
42199
|
const slugs = readdirSync7(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
@@ -41910,7 +42262,7 @@ function parseHistorianDumpMeta2(path) {
|
|
|
41910
42262
|
}
|
|
41911
42263
|
}
|
|
41912
42264
|
function listDumpsInDir2(dir, limit) {
|
|
41913
|
-
if (!
|
|
42265
|
+
if (!existsSync39(dir))
|
|
41914
42266
|
return { count: 0, recent: [] };
|
|
41915
42267
|
try {
|
|
41916
42268
|
const entries = readdirSync7(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
@@ -42004,7 +42356,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
42004
42356
|
piVersion: pi ? getPiVersion(pi.path) : null,
|
|
42005
42357
|
settings: {
|
|
42006
42358
|
path: settingsPath,
|
|
42007
|
-
exists:
|
|
42359
|
+
exists: existsSync39(settingsPath),
|
|
42008
42360
|
...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
|
|
42009
42361
|
hasMagicContextPackage: hasPiMagicContextPackage(packages),
|
|
42010
42362
|
packages: sanitizeValue2(packages)
|
|
@@ -42021,7 +42373,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
42021
42373
|
storageDir: {
|
|
42022
42374
|
path: storageDirPath,
|
|
42023
42375
|
source: storageResolution.source,
|
|
42024
|
-
exists:
|
|
42376
|
+
exists: existsSync39(storageDirPath),
|
|
42025
42377
|
contextDbSizeBytes: fileSize2(dbPath)
|
|
42026
42378
|
},
|
|
42027
42379
|
conflicts: {
|
|
@@ -42127,7 +42479,7 @@ var init_diagnostics_pi = __esm(() => {
|
|
|
42127
42479
|
|
|
42128
42480
|
// src/lib/logs-pi.ts
|
|
42129
42481
|
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
42130
|
-
import { dirname as
|
|
42482
|
+
import { dirname as dirname19, join as join34 } from "node:path";
|
|
42131
42483
|
function sanitizeLogContent2(content) {
|
|
42132
42484
|
return sanitizeString2(content);
|
|
42133
42485
|
}
|
|
@@ -42198,7 +42550,7 @@ async function bundleIssueReport2(report, description, title, options = {}) {
|
|
|
42198
42550
|
const cwd = options.cwd ?? process.cwd();
|
|
42199
42551
|
const timestamp = formatTimestamp2(options.now ?? new Date);
|
|
42200
42552
|
const path = options.outputPath ?? join34(cwd, `magic-context-pi-issue-${timestamp}.md`);
|
|
42201
|
-
mkdirSync10(
|
|
42553
|
+
mkdirSync10(dirname19(path), { recursive: true });
|
|
42202
42554
|
writeFileSync9(path, `${bodyMarkdown}
|
|
42203
42555
|
`);
|
|
42204
42556
|
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` : join34(cwd, `magic-context-pi-issue-${timestamp}-full.md`) : undefined;
|
|
@@ -42215,10 +42567,10 @@ var init_logs_pi = __esm(() => {
|
|
|
42215
42567
|
|
|
42216
42568
|
// src/commands/doctor-pi.ts
|
|
42217
42569
|
import { execFileSync as execFileSync6, spawnSync as spawnSync9 } from "node:child_process";
|
|
42218
|
-
import { existsSync as
|
|
42570
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync11, readdirSync as readdirSync8, readFileSync as readFileSync28, rmSync as rmSync6, statSync as statSync17 } from "node:fs";
|
|
42219
42571
|
import { createRequire as createRequire8 } from "node:module";
|
|
42220
42572
|
import { homedir as homedir17 } from "node:os";
|
|
42221
|
-
import { dirname as
|
|
42573
|
+
import { dirname as dirname20, isAbsolute as isAbsolute8, join as join35 } from "node:path";
|
|
42222
42574
|
function depsFrom(options) {
|
|
42223
42575
|
return {
|
|
42224
42576
|
...DEFAULT_DEPS5,
|
|
@@ -42361,13 +42713,13 @@ function piPluginDirCandidates(packages, cwd) {
|
|
|
42361
42713
|
}
|
|
42362
42714
|
dirs.push(join35(agentDir, "npm", "node_modules", PACKAGE_NAME2));
|
|
42363
42715
|
dirs.push(join35(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
|
|
42364
|
-
return dirs.filter((dir) =>
|
|
42716
|
+
return dirs.filter((dir) => existsSync40(join35(dir, "package.json")));
|
|
42365
42717
|
}
|
|
42366
42718
|
function projectConfigPath(cwd) {
|
|
42367
42719
|
return resolveCortexKitProjectConfigPath(cwd);
|
|
42368
42720
|
}
|
|
42369
42721
|
function readConfigForEmbedding(path, isProjectConfig) {
|
|
42370
|
-
if (!
|
|
42722
|
+
if (!existsSync40(path))
|
|
42371
42723
|
return null;
|
|
42372
42724
|
try {
|
|
42373
42725
|
const raw = loadRawConfigFile({
|
|
@@ -42468,7 +42820,7 @@ function cacheRoots(cwd) {
|
|
|
42468
42820
|
function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
42469
42821
|
const found = new Map;
|
|
42470
42822
|
const visit = (path, depth) => {
|
|
42471
|
-
if (depth < 0 || !
|
|
42823
|
+
if (depth < 0 || !existsSync40(path))
|
|
42472
42824
|
return;
|
|
42473
42825
|
let stat;
|
|
42474
42826
|
try {
|
|
@@ -42479,7 +42831,7 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
|
42479
42831
|
if (!stat.isDirectory())
|
|
42480
42832
|
return;
|
|
42481
42833
|
const packageJson = join35(path, "package.json");
|
|
42482
|
-
if (
|
|
42834
|
+
if (existsSync40(packageJson)) {
|
|
42483
42835
|
try {
|
|
42484
42836
|
const pkg = JSON.parse(readFileSync28(packageJson, "utf-8"));
|
|
42485
42837
|
const name = typeof pkg.name === "string" ? pkg.name : "";
|
|
@@ -42546,7 +42898,7 @@ async function runHealthChecks2(options) {
|
|
|
42546
42898
|
}
|
|
42547
42899
|
const settingsPath = getPiUserExtensionsPath();
|
|
42548
42900
|
let packages = [];
|
|
42549
|
-
if (!
|
|
42901
|
+
if (!existsSync40(settingsPath)) {
|
|
42550
42902
|
add2(results, "fail", `Pi settings not found at ${settingsPath}`);
|
|
42551
42903
|
repairPlan.addPackageEntry = true;
|
|
42552
42904
|
} else {
|
|
@@ -42570,7 +42922,7 @@ async function runHealthChecks2(options) {
|
|
|
42570
42922
|
["user", userConfigPath, true],
|
|
42571
42923
|
["project", projectPath, false]
|
|
42572
42924
|
]) {
|
|
42573
|
-
if (!
|
|
42925
|
+
if (!existsSync40(path)) {
|
|
42574
42926
|
if (required) {
|
|
42575
42927
|
add2(results, "warn", `No ${label} magic-context.jsonc found at ${path}`);
|
|
42576
42928
|
if (userConfigMigrationRefused) {
|
|
@@ -42612,7 +42964,7 @@ async function runHealthChecks2(options) {
|
|
|
42612
42964
|
const storageDir = storage.path;
|
|
42613
42965
|
const dbPath = join35(storageDir, "context.db");
|
|
42614
42966
|
add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
|
|
42615
|
-
const existedBeforeOpen =
|
|
42967
|
+
const existedBeforeOpen = existsSync40(dbPath);
|
|
42616
42968
|
if (existedBeforeOpen)
|
|
42617
42969
|
add2(results, "pass", `Shared context DB exists at ${dbPath}`);
|
|
42618
42970
|
else
|
|
@@ -42830,7 +43182,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
42830
43182
|
return { results, repairPlan, ...summarize(results) };
|
|
42831
43183
|
}
|
|
42832
43184
|
function writeDefaultMagicContextConfig(path) {
|
|
42833
|
-
mkdirSync11(
|
|
43185
|
+
mkdirSync11(dirname20(path), { recursive: true });
|
|
42834
43186
|
const config = {
|
|
42835
43187
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
42836
43188
|
...MagicContextConfigSchema.parse({})
|
|
@@ -42852,7 +43204,7 @@ function repair2(plan, prompts) {
|
|
|
42852
43204
|
}
|
|
42853
43205
|
if (plan.writeUserConfig) {
|
|
42854
43206
|
const configPath = getPiUserConfigPath();
|
|
42855
|
-
if (!
|
|
43207
|
+
if (!existsSync40(configPath)) {
|
|
42856
43208
|
try {
|
|
42857
43209
|
writeDefaultMagicContextConfig(configPath);
|
|
42858
43210
|
prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
|
|
@@ -43104,7 +43456,7 @@ var init_doctor_pi = __esm(async () => {
|
|
|
43104
43456
|
});
|
|
43105
43457
|
|
|
43106
43458
|
// src/commands/doctor.ts
|
|
43107
|
-
import { existsSync as
|
|
43459
|
+
import { existsSync as existsSync41, rmSync as rmSync7 } from "node:fs";
|
|
43108
43460
|
import { join as join36 } from "node:path";
|
|
43109
43461
|
async function runDoctor4(options) {
|
|
43110
43462
|
if (options.clear)
|
|
@@ -43251,7 +43603,7 @@ async function runClear() {
|
|
|
43251
43603
|
failed += 1;
|
|
43252
43604
|
continue;
|
|
43253
43605
|
}
|
|
43254
|
-
} else if (
|
|
43606
|
+
} else if (existsSync41(item.path)) {
|
|
43255
43607
|
rmSync7(item.path, { recursive: true, force: true });
|
|
43256
43608
|
}
|
|
43257
43609
|
s.stop(`Cleared ${item.path}`);
|
|
@@ -43288,9 +43640,121 @@ var init_doctor = __esm(async () => {
|
|
|
43288
43640
|
});
|
|
43289
43641
|
|
|
43290
43642
|
// src/index.ts
|
|
43291
|
-
init_prompts();
|
|
43292
43643
|
import { createRequire as createRequire9 } from "node:module";
|
|
43293
43644
|
|
|
43645
|
+
// src/lib/cli-help.ts
|
|
43646
|
+
var HELP_FLAGS = new Set(["--help", "-h"]);
|
|
43647
|
+
function hasHelpFlag(args) {
|
|
43648
|
+
return args.some((arg) => HELP_FLAGS.has(arg));
|
|
43649
|
+
}
|
|
43650
|
+
var DOCTOR_SUBCOMMANDS_WITH_OWN_HELP = new Set([
|
|
43651
|
+
"migrate",
|
|
43652
|
+
"migrate-session",
|
|
43653
|
+
"repair-db"
|
|
43654
|
+
]);
|
|
43655
|
+
var HARNESS_LINES = [
|
|
43656
|
+
" Harness selection:",
|
|
43657
|
+
" --harness opencode Target OpenCode only",
|
|
43658
|
+
" --harness pi Target Pi only",
|
|
43659
|
+
" --harness omp Target Oh My Pi (OMP) only",
|
|
43660
|
+
" (default: auto-detect, prompt if multiple installed)"
|
|
43661
|
+
];
|
|
43662
|
+
var SETUP_HELP = [
|
|
43663
|
+
"",
|
|
43664
|
+
" Usage: magic-context setup [--harness opencode|pi|omp] [--dry-run]",
|
|
43665
|
+
"",
|
|
43666
|
+
" Interactive setup wizard: registers the Magic Context plugin with the",
|
|
43667
|
+
" selected harness and writes its Magic Context config.",
|
|
43668
|
+
"",
|
|
43669
|
+
" Options:",
|
|
43670
|
+
" --dry-run Preview the wizard without writing any files",
|
|
43671
|
+
...HARNESS_LINES,
|
|
43672
|
+
""
|
|
43673
|
+
].join(`
|
|
43674
|
+
`);
|
|
43675
|
+
var DOCTOR_HELP = [
|
|
43676
|
+
"",
|
|
43677
|
+
" Usage: magic-context doctor [options]",
|
|
43678
|
+
" magic-context doctor <subcommand> [options]",
|
|
43679
|
+
"",
|
|
43680
|
+
" Check the installed harnesses and fix configuration issues.",
|
|
43681
|
+
"",
|
|
43682
|
+
" Options:",
|
|
43683
|
+
" --fix Repair safe, Magic Context-owned store rows and clear an outdated OpenCode 2 plugin cache",
|
|
43684
|
+
" --force Force-clear the plugin cache",
|
|
43685
|
+
" --clear Interactive cache cleanup picker",
|
|
43686
|
+
" --issue Collect diagnostics and open a GitHub issue",
|
|
43687
|
+
" --report <path> Write the issue diagnostics to <path> without prompting",
|
|
43688
|
+
" --check-v22-backfill Show v22 memory backfill status",
|
|
43689
|
+
" --retry-v22-backfill Retry failed v22 memory backfill rows",
|
|
43690
|
+
" --rekey-v22-dir-identity <path> Re-key legacy dir identity rows",
|
|
43691
|
+
...HARNESS_LINES,
|
|
43692
|
+
"",
|
|
43693
|
+
" Subcommands (each accepts --help):",
|
|
43694
|
+
" drain-authority <project> Drain module memory/note authority back to TypeScript",
|
|
43695
|
+
" migrate Migrate an OpenCode session to Pi or OMP JSONL",
|
|
43696
|
+
" migrate-session Re-home an OpenCode session to another directory",
|
|
43697
|
+
" merge-identity Merge project rows between identities",
|
|
43698
|
+
" repair-db Back up and salvage a corrupted shared database",
|
|
43699
|
+
" list-hidden-sessions List Magic Context OpenCode 2 roots",
|
|
43700
|
+
""
|
|
43701
|
+
].join(`
|
|
43702
|
+
`);
|
|
43703
|
+
var DRAIN_AUTHORITY_HELP = [
|
|
43704
|
+
"",
|
|
43705
|
+
" Usage: magic-context doctor drain-authority <project>",
|
|
43706
|
+
"",
|
|
43707
|
+
" Drain the module's memory and note authority for <project> back to TypeScript.",
|
|
43708
|
+
""
|
|
43709
|
+
].join(`
|
|
43710
|
+
`);
|
|
43711
|
+
var MERGE_IDENTITY_HELP = [
|
|
43712
|
+
"",
|
|
43713
|
+
" Usage: magic-context doctor merge-identity --from <identity> --to <identity> [--dry-run] [--yes] [--db <path>]",
|
|
43714
|
+
"",
|
|
43715
|
+
" Merge every project-scoped row from one project identity into another.",
|
|
43716
|
+
"",
|
|
43717
|
+
" Options:",
|
|
43718
|
+
" --from <identity> Identity whose rows are moved",
|
|
43719
|
+
" --to <identity> Identity that receives them",
|
|
43720
|
+
" --dry-run Report what would change without writing",
|
|
43721
|
+
" --yes Confirm the write (required unless --dry-run)",
|
|
43722
|
+
" --db <path> Use this context.db instead of the shared one",
|
|
43723
|
+
""
|
|
43724
|
+
].join(`
|
|
43725
|
+
`);
|
|
43726
|
+
var LIST_HIDDEN_SESSIONS_HELP = [
|
|
43727
|
+
"",
|
|
43728
|
+
" Usage: magic-context doctor list-hidden-sessions",
|
|
43729
|
+
"",
|
|
43730
|
+
" List the hidden OpenCode 2 root sessions Magic Context reuses for its",
|
|
43731
|
+
" historian and dreamer runs. Read-only.",
|
|
43732
|
+
""
|
|
43733
|
+
].join(`
|
|
43734
|
+
`);
|
|
43735
|
+
function subcommandHelp(argv) {
|
|
43736
|
+
const [command, ...rest] = argv;
|
|
43737
|
+
if (!hasHelpFlag(rest))
|
|
43738
|
+
return null;
|
|
43739
|
+
if (command === "setup")
|
|
43740
|
+
return SETUP_HELP;
|
|
43741
|
+
if (command !== "doctor")
|
|
43742
|
+
return null;
|
|
43743
|
+
const subcommand = rest[0];
|
|
43744
|
+
if (subcommand === "drain-authority")
|
|
43745
|
+
return DRAIN_AUTHORITY_HELP;
|
|
43746
|
+
if (subcommand === "merge-identity")
|
|
43747
|
+
return MERGE_IDENTITY_HELP;
|
|
43748
|
+
if (subcommand === "list-hidden-sessions")
|
|
43749
|
+
return LIST_HIDDEN_SESSIONS_HELP;
|
|
43750
|
+
if (subcommand !== undefined && DOCTOR_SUBCOMMANDS_WITH_OWN_HELP.has(subcommand))
|
|
43751
|
+
return null;
|
|
43752
|
+
return DOCTOR_HELP;
|
|
43753
|
+
}
|
|
43754
|
+
|
|
43755
|
+
// src/index.ts
|
|
43756
|
+
init_prompts();
|
|
43757
|
+
|
|
43294
43758
|
// src/lib/sqlite-preflight.ts
|
|
43295
43759
|
async function probeSqliteBackend() {
|
|
43296
43760
|
await init_sqlite().then(() => ({}));
|
|
@@ -43300,7 +43764,7 @@ function formatSqlitePreflightFailure(error) {
|
|
|
43300
43764
|
return [
|
|
43301
43765
|
"Magic Context doctor cannot use SQLite in this runtime.",
|
|
43302
43766
|
`SQLite probe: ${detail}`,
|
|
43303
|
-
"Remediation: install Node.js >= 24 or use a Bun build with node:sqlite.",
|
|
43767
|
+
"Remediation: install Node.js 22.16+ (22.x) or >= 24, or use a Bun build with node:sqlite.",
|
|
43304
43768
|
"For Docker, use node:24-slim or a two-runtime image."
|
|
43305
43769
|
].join(`
|
|
43306
43770
|
`);
|
|
@@ -43367,6 +43831,7 @@ function printUsage() {
|
|
|
43367
43831
|
console.log(" (default: auto-detect, prompt if multiple installed)");
|
|
43368
43832
|
console.log("");
|
|
43369
43833
|
console.log(" Usage:");
|
|
43834
|
+
console.log(" npx @cortexkit/magic-context@latest <command> --help # help for one command");
|
|
43370
43835
|
console.log(" npx @cortexkit/magic-context@latest setup");
|
|
43371
43836
|
console.log(" # add --dry-run to preview the wizard without writing any files");
|
|
43372
43837
|
console.log(" npx @cortexkit/magic-context@latest doctor");
|
|
@@ -43386,6 +43851,11 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
43386
43851
|
}
|
|
43387
43852
|
const command = argv[0];
|
|
43388
43853
|
const rest = argv.slice(1);
|
|
43854
|
+
const help = subcommandHelp(argv);
|
|
43855
|
+
if (help !== null) {
|
|
43856
|
+
console.log(help);
|
|
43857
|
+
return 0;
|
|
43858
|
+
}
|
|
43389
43859
|
try {
|
|
43390
43860
|
if (command === "setup") {
|
|
43391
43861
|
await Promise.resolve().then(() => init_setup());
|