memorix 1.8.1 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/dist/cli/index.js +577 -58
- package/dist/index.js +832 -321
- package/dist/maintenance-runner.js +31 -25
- package/dist/media-audio-runner.js +31 -25
- package/dist/media-video-runner.js +31 -25
- package/dist/memcode-runtime/CHANGELOG.md +36 -0
- package/dist/sdk.js +585 -315
- package/dist/vector-backfill-runner.js +31 -25
- package/docs/1.2.0-PROVIDER-QUALITY.md +15 -6
- package/docs/1.3.3-MULTIMODAL-MEDIA-AND-MCP-COMPAT.md +7 -6
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +13 -8
- package/docs/API_REFERENCE.md +14 -11
- package/docs/CONFIGURATION.md +2 -2
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/README.md +13 -7
- package/package.json +2 -1
- package/plugins/antigravity/memorix/plugin.json +2 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +3 -3
- package/src/cli/commands/serve-http.ts +10 -2
- package/src/cli/commands/serve.ts +26 -7
- package/src/codegraph/external-provider.ts +299 -19
- package/src/config/dotenv-loader.ts +9 -4
- package/src/config.ts +16 -16
- package/src/dashboard/maintenance.ts +4 -1
- package/src/llm/provider.ts +17 -4
- package/src/server/mcp-compat.ts +63 -0
- package/src/server/mcp-diagnostics.ts +13 -4
- package/src/server/mcp-discovery.ts +61 -0
- package/src/server/stdio-startup-gate.ts +263 -0
- package/src/server.ts +4 -4
package/dist/cli/index.js
CHANGED
|
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3232
3232
|
|
|
3233
3233
|
// src/cli/version.ts
|
|
3234
3234
|
function getCliVersion() {
|
|
3235
|
-
return true ? "1.8.
|
|
3235
|
+
return true ? "1.8.3" : pkg.version;
|
|
3236
3236
|
}
|
|
3237
3237
|
var init_version = __esm({
|
|
3238
3238
|
"src/cli/version.ts"() {
|
|
@@ -21630,8 +21630,10 @@ function loadEnvFile(filePath) {
|
|
|
21630
21630
|
loadedEnvFiles.push(filePath);
|
|
21631
21631
|
}
|
|
21632
21632
|
function loadDotenv(projectRoot, options = {}) {
|
|
21633
|
-
|
|
21634
|
-
|
|
21633
|
+
const userHomeDir = options.userHomeDir ?? homedir4();
|
|
21634
|
+
const normalizedProjectRoot = projectRoot ?? null;
|
|
21635
|
+
if (dotenvLoaded && dotenvProjectRoot === normalizedProjectRoot && dotenvHomeDir === userHomeDir) return;
|
|
21636
|
+
if (dotenvLoaded && (dotenvProjectRoot !== normalizedProjectRoot || dotenvHomeDir !== userHomeDir)) {
|
|
21635
21637
|
resetDotenv();
|
|
21636
21638
|
}
|
|
21637
21639
|
loadedEnvFiles.length = 0;
|
|
@@ -21640,9 +21642,10 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
21640
21642
|
if (projectRoot) {
|
|
21641
21643
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
21642
21644
|
}
|
|
21643
|
-
loadEnvFile(getGlobalDotenvPath(
|
|
21645
|
+
loadEnvFile(getGlobalDotenvPath(userHomeDir));
|
|
21644
21646
|
dotenvLoaded = true;
|
|
21645
|
-
dotenvProjectRoot =
|
|
21647
|
+
dotenvProjectRoot = normalizedProjectRoot;
|
|
21648
|
+
dotenvHomeDir = userHomeDir;
|
|
21646
21649
|
}
|
|
21647
21650
|
function resetDotenv() {
|
|
21648
21651
|
for (const key of injectedKeys) {
|
|
@@ -21651,6 +21654,7 @@ function resetDotenv() {
|
|
|
21651
21654
|
injectedKeys.clear();
|
|
21652
21655
|
dotenvLoaded = false;
|
|
21653
21656
|
dotenvProjectRoot = null;
|
|
21657
|
+
dotenvHomeDir = null;
|
|
21654
21658
|
loadedEnvFiles.length = 0;
|
|
21655
21659
|
loadedEnvKeys.clear();
|
|
21656
21660
|
}
|
|
@@ -21663,7 +21667,7 @@ function getLoadedEnvKeys() {
|
|
|
21663
21667
|
function getLoadedEnvValue(key) {
|
|
21664
21668
|
return loadedEnvValues.get(key);
|
|
21665
21669
|
}
|
|
21666
|
-
var import_dotenv, dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
21670
|
+
var import_dotenv, dotenvLoaded, dotenvProjectRoot, dotenvHomeDir, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
21667
21671
|
var init_dotenv_loader = __esm({
|
|
21668
21672
|
"src/config/dotenv-loader.ts"() {
|
|
21669
21673
|
"use strict";
|
|
@@ -21672,6 +21676,7 @@ var init_dotenv_loader = __esm({
|
|
|
21672
21676
|
init_config_paths();
|
|
21673
21677
|
dotenvLoaded = false;
|
|
21674
21678
|
dotenvProjectRoot = null;
|
|
21679
|
+
dotenvHomeDir = null;
|
|
21675
21680
|
loadedEnvFiles = [];
|
|
21676
21681
|
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
21677
21682
|
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
@@ -22023,33 +22028,33 @@ __export(config_exports, {
|
|
|
22023
22028
|
resetConfigCache: () => resetConfigCache,
|
|
22024
22029
|
resetDotenv: () => resetDotenv
|
|
22025
22030
|
});
|
|
22026
|
-
function getLLMApiKey() {
|
|
22027
|
-
return getResolvedMemoryLane().llm.apiKey;
|
|
22031
|
+
function getLLMApiKey(options = {}) {
|
|
22032
|
+
return getResolvedMemoryLane(options).llm.apiKey;
|
|
22028
22033
|
}
|
|
22029
|
-
function getLLMProvider() {
|
|
22030
|
-
const provider2 = getResolvedMemoryLane().llm.provider;
|
|
22034
|
+
function getLLMProvider(options = {}) {
|
|
22035
|
+
const provider2 = getResolvedMemoryLane(options).llm.provider;
|
|
22031
22036
|
if (provider2) return provider2;
|
|
22032
22037
|
if (process.env.ANTHROPIC_API_KEY && !process.env.OPENAI_API_KEY) return "anthropic";
|
|
22033
22038
|
if (process.env.OPENROUTER_API_KEY && !process.env.OPENAI_API_KEY) return "openrouter";
|
|
22034
22039
|
return "openai";
|
|
22035
22040
|
}
|
|
22036
|
-
function getLLMModel(providerDefault) {
|
|
22037
|
-
return getResolvedMemoryLane().llm.model || providerDefault;
|
|
22041
|
+
function getLLMModel(providerDefault, options = {}) {
|
|
22042
|
+
return getResolvedMemoryLane(options).llm.model || providerDefault;
|
|
22038
22043
|
}
|
|
22039
|
-
function getLLMBaseUrl(providerDefault) {
|
|
22040
|
-
return getResolvedMemoryLane().llm.baseUrl || providerDefault;
|
|
22044
|
+
function getLLMBaseUrl(providerDefault, options = {}) {
|
|
22045
|
+
return getResolvedMemoryLane(options).llm.baseUrl || providerDefault;
|
|
22041
22046
|
}
|
|
22042
|
-
function getAgentLLMApiKey() {
|
|
22043
|
-
return getResolvedAgentLane().apiKey;
|
|
22047
|
+
function getAgentLLMApiKey(options = {}) {
|
|
22048
|
+
return getResolvedAgentLane(options).apiKey;
|
|
22044
22049
|
}
|
|
22045
|
-
function getAgentLLMProvider() {
|
|
22046
|
-
return getResolvedAgentLane().provider || getLLMProvider();
|
|
22050
|
+
function getAgentLLMProvider(options = {}) {
|
|
22051
|
+
return getResolvedAgentLane(options).provider || getLLMProvider(options);
|
|
22047
22052
|
}
|
|
22048
|
-
function getAgentLLMModel(providerDefault) {
|
|
22049
|
-
return getResolvedAgentLane().model || getLLMModel(providerDefault);
|
|
22053
|
+
function getAgentLLMModel(providerDefault, options = {}) {
|
|
22054
|
+
return getResolvedAgentLane(options).model || getLLMModel(providerDefault, options);
|
|
22050
22055
|
}
|
|
22051
|
-
function getAgentLLMBaseUrl(providerDefault) {
|
|
22052
|
-
return getResolvedAgentLane().baseUrl || getLLMBaseUrl(providerDefault);
|
|
22056
|
+
function getAgentLLMBaseUrl(providerDefault, options = {}) {
|
|
22057
|
+
return getResolvedAgentLane(options).baseUrl || getLLMBaseUrl(providerDefault, options);
|
|
22053
22058
|
}
|
|
22054
22059
|
function getEmbeddingMode() {
|
|
22055
22060
|
const provider2 = getResolvedEmbeddingLane().provider?.toLowerCase()?.trim();
|
|
@@ -24308,18 +24313,19 @@ async function* callLLMWithToolsStream(messages, tools) {
|
|
|
24308
24313
|
}
|
|
24309
24314
|
function initLLM(options = {}) {
|
|
24310
24315
|
const scope = options.scope ?? "memory";
|
|
24311
|
-
const
|
|
24316
|
+
const configOptions = { projectRoot: options.projectRoot, homeDir: options.homeDir };
|
|
24317
|
+
const apiKey = scope === "agent" ? getAgentLLMApiKey(configOptions) : getLLMApiKey(configOptions);
|
|
24312
24318
|
if (!apiKey) {
|
|
24313
24319
|
currentConfig = null;
|
|
24314
24320
|
return null;
|
|
24315
24321
|
}
|
|
24316
|
-
const provider2 = scope === "agent" ? getAgentLLMProvider() : getLLMProvider();
|
|
24322
|
+
const provider2 = scope === "agent" ? getAgentLLMProvider(configOptions) : getLLMProvider(configOptions);
|
|
24317
24323
|
const defaults2 = PROVIDER_DEFAULTS[provider2] ?? PROVIDER_DEFAULTS.openai;
|
|
24318
24324
|
currentConfig = {
|
|
24319
24325
|
provider: provider2,
|
|
24320
24326
|
apiKey,
|
|
24321
|
-
model: scope === "agent" ? getAgentLLMModel(defaults2.model) : getLLMModel(defaults2.model),
|
|
24322
|
-
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults2.baseUrl) : getLLMBaseUrl(defaults2.baseUrl)
|
|
24327
|
+
model: scope === "agent" ? getAgentLLMModel(defaults2.model, configOptions) : getLLMModel(defaults2.model, configOptions),
|
|
24328
|
+
baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults2.baseUrl, configOptions) : getLLMBaseUrl(defaults2.baseUrl, configOptions)
|
|
24323
24329
|
};
|
|
24324
24330
|
return currentConfig;
|
|
24325
24331
|
}
|
|
@@ -197170,6 +197176,27 @@ function unavailableHealth(result) {
|
|
|
197170
197176
|
if (result.outputLimited) return { state: "invalid", reason: "A local CodeGraph response exceeded the safety limit." };
|
|
197171
197177
|
return { state: "unavailable", reason: "A local CodeGraph command did not complete." };
|
|
197172
197178
|
}
|
|
197179
|
+
function notAttemptedDiagnostic(command) {
|
|
197180
|
+
return { command, attempted: false, outcome: "not-attempted" };
|
|
197181
|
+
}
|
|
197182
|
+
function commandDiagnostic(command, result, outcome, reason) {
|
|
197183
|
+
return {
|
|
197184
|
+
command,
|
|
197185
|
+
attempted: true,
|
|
197186
|
+
outcome,
|
|
197187
|
+
...typeof result.exitCode === "number" ? { exitCode: result.exitCode } : {},
|
|
197188
|
+
...reason ? { reason: sanitizeCredentials(reason).slice(0, 240) } : {}
|
|
197189
|
+
};
|
|
197190
|
+
}
|
|
197191
|
+
function failedCommandDiagnostic(command, result) {
|
|
197192
|
+
const outcome = result.timedOut ? "timed-out" : result.outputLimited ? "output-limited" : "failed";
|
|
197193
|
+
return commandDiagnostic(
|
|
197194
|
+
command,
|
|
197195
|
+
result,
|
|
197196
|
+
outcome,
|
|
197197
|
+
result.error || result.stderr || "CodeGraph command did not complete."
|
|
197198
|
+
);
|
|
197199
|
+
}
|
|
197173
197200
|
async function runSafely(runner, input) {
|
|
197174
197201
|
try {
|
|
197175
197202
|
return await runner.run(input);
|
|
@@ -197319,6 +197346,7 @@ function parseOutline(value, projectRoot, exclude) {
|
|
|
197319
197346
|
if (nodes.some((node) => !node)) return void 0;
|
|
197320
197347
|
const byId = /* @__PURE__ */ new Map();
|
|
197321
197348
|
for (const node of nodes) {
|
|
197349
|
+
if (byId.has(node.id)) return void 0;
|
|
197322
197350
|
byId.set(node.id, externalSymbol(node));
|
|
197323
197351
|
}
|
|
197324
197352
|
const entryPoints = value.entryPoints.map((item) => parseNode(item, projectRoot, exclude)).filter((node) => Boolean(node)).map(externalSymbol).filter((node, index, items) => items.findIndex((item) => item.id === node.id) === index).slice(0, 5);
|
|
@@ -197332,7 +197360,7 @@ function parseOutline(value, projectRoot, exclude) {
|
|
|
197332
197360
|
if (!source || !target || !kind || rawEdge.line !== void 0 && (!line || line < 1)) return void 0;
|
|
197333
197361
|
const from = byId.get(source);
|
|
197334
197362
|
const to2 = byId.get(target);
|
|
197335
|
-
if (!from || !to2)
|
|
197363
|
+
if (!from || !to2) return void 0;
|
|
197336
197364
|
relations.push({ from, to: to2, kind, ...line ? { line } : {} });
|
|
197337
197365
|
}
|
|
197338
197366
|
const relatedFiles = value.relatedFiles.map((item) => safeRelativePath(projectRoot, item, exclude));
|
|
@@ -197350,45 +197378,234 @@ function parseOutline(value, projectRoot, exclude) {
|
|
|
197350
197378
|
stats: { nodes: nodeCount, edges: edgeCount, files: fileCount }
|
|
197351
197379
|
};
|
|
197352
197380
|
}
|
|
197381
|
+
function parseTextLocation(value) {
|
|
197382
|
+
const match2 = value.trim().match(/^(.*?)(?::([1-9]\d*))?$/);
|
|
197383
|
+
if (!match2?.[1]) return void 0;
|
|
197384
|
+
return {
|
|
197385
|
+
filePath: match2[1].trim(),
|
|
197386
|
+
...match2[2] ? { line: Number(match2[2]) } : {}
|
|
197387
|
+
};
|
|
197388
|
+
}
|
|
197389
|
+
function parseExploreText(value, projectRoot, exclude) {
|
|
197390
|
+
if (!value.trim() || Buffer.byteLength(value, "utf8") > MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES) return void 0;
|
|
197391
|
+
const entryPoints = [];
|
|
197392
|
+
const nodes = [];
|
|
197393
|
+
const relatedFiles = /* @__PURE__ */ new Set();
|
|
197394
|
+
const byName = /* @__PURE__ */ new Map();
|
|
197395
|
+
let section2 = null;
|
|
197396
|
+
let relationKind = "references";
|
|
197397
|
+
const addNode = (node, entry) => {
|
|
197398
|
+
const key = `${node.filePath}\0${node.name}`;
|
|
197399
|
+
const existing = byName.get(key);
|
|
197400
|
+
if (existing) return;
|
|
197401
|
+
byName.set(key, node);
|
|
197402
|
+
relatedFiles.add(node.filePath);
|
|
197403
|
+
(entry ? entryPoints : nodes).push(node);
|
|
197404
|
+
};
|
|
197405
|
+
for (const rawLine of value.split(/\r?\n/)) {
|
|
197406
|
+
const line = rawLine.trim();
|
|
197407
|
+
const fileHeader = line.match(/^\*\*`([^`]+)`\*\*\s+(?:—|-)\s+(.+)$/);
|
|
197408
|
+
if (fileHeader) {
|
|
197409
|
+
const filePath = safeRelativePath(projectRoot, fileHeader[1], exclude);
|
|
197410
|
+
if (!filePath) return void 0;
|
|
197411
|
+
const symbolText = fileHeader[2].split(/\s+·\s+/, 1)[0] ?? "";
|
|
197412
|
+
const symbols = [...symbolText.matchAll(/([^,]+?)\(([^()]+)\)/g)];
|
|
197413
|
+
if (symbols.length === 0) return void 0;
|
|
197414
|
+
const isFirstFile = entryPoints.length === 0 && nodes.length === 0;
|
|
197415
|
+
for (const symbol2 of symbols.slice(0, MAX_EXTERNAL_NODE_COUNT)) {
|
|
197416
|
+
const name = symbol2[1]?.trim();
|
|
197417
|
+
const kind = symbol2[2]?.trim();
|
|
197418
|
+
if (!name || !kind) return void 0;
|
|
197419
|
+
addNode({
|
|
197420
|
+
id: `explore:${filePath}:${name}`,
|
|
197421
|
+
kind,
|
|
197422
|
+
name,
|
|
197423
|
+
filePath
|
|
197424
|
+
}, isFirstFile);
|
|
197425
|
+
}
|
|
197426
|
+
section2 = null;
|
|
197427
|
+
continue;
|
|
197428
|
+
}
|
|
197429
|
+
if (/^#{2,3}\s+Entry Points?\b/i.test(line)) {
|
|
197430
|
+
section2 = "entry";
|
|
197431
|
+
continue;
|
|
197432
|
+
}
|
|
197433
|
+
if (/^#{2,3}\s+Related Symbols?\b/i.test(line)) {
|
|
197434
|
+
section2 = "related";
|
|
197435
|
+
continue;
|
|
197436
|
+
}
|
|
197437
|
+
if (/^\*\*Relationships\*\*$/i.test(line)) {
|
|
197438
|
+
section2 = "relationships";
|
|
197439
|
+
continue;
|
|
197440
|
+
}
|
|
197441
|
+
if (/^\*\*(?:Source Code|Code)\*\*$/i.test(line) || /^#{2,3}\s+/i.test(line)) {
|
|
197442
|
+
section2 = null;
|
|
197443
|
+
continue;
|
|
197444
|
+
}
|
|
197445
|
+
if (section2 === "entry") {
|
|
197446
|
+
const match2 = line.match(/^-\s+\*\*(.+?)\*\*\s+\(([^)]+)\)\s+-\s+(.+)$/);
|
|
197447
|
+
if (!match2) continue;
|
|
197448
|
+
const location = parseTextLocation(match2[3]);
|
|
197449
|
+
if (!location) return void 0;
|
|
197450
|
+
const filePath = safeRelativePath(projectRoot, location.filePath, exclude);
|
|
197451
|
+
if (!filePath) return void 0;
|
|
197452
|
+
addNode({
|
|
197453
|
+
id: `explore:${filePath}:${match2[1]}`,
|
|
197454
|
+
kind: match2[2],
|
|
197455
|
+
name: match2[1],
|
|
197456
|
+
filePath,
|
|
197457
|
+
...location.line ? { startLine: location.line, endLine: location.line } : {}
|
|
197458
|
+
}, true);
|
|
197459
|
+
continue;
|
|
197460
|
+
}
|
|
197461
|
+
if (section2 === "related") {
|
|
197462
|
+
const match2 = line.match(/^-\s+([^:]+):\s+(.+)$/);
|
|
197463
|
+
if (!match2) continue;
|
|
197464
|
+
const filePath = safeRelativePath(projectRoot, match2[1], exclude);
|
|
197465
|
+
if (!filePath) return void 0;
|
|
197466
|
+
relatedFiles.add(filePath);
|
|
197467
|
+
for (const rawSymbol of match2[2].split(",")) {
|
|
197468
|
+
const symbol2 = rawSymbol.trim().match(/^(.+?)(?::([1-9]\d*))?$/);
|
|
197469
|
+
if (!symbol2?.[1]) return void 0;
|
|
197470
|
+
addNode({
|
|
197471
|
+
id: `explore:${filePath}:${symbol2[1].trim()}`,
|
|
197472
|
+
kind: "unknown",
|
|
197473
|
+
name: symbol2[1].trim(),
|
|
197474
|
+
filePath,
|
|
197475
|
+
...symbol2[2] ? { startLine: Number(symbol2[2]), endLine: Number(symbol2[2]) } : {}
|
|
197476
|
+
}, false);
|
|
197477
|
+
}
|
|
197478
|
+
continue;
|
|
197479
|
+
}
|
|
197480
|
+
if (section2 === "relationships") {
|
|
197481
|
+
const kind = line.match(/^\*\*([^*]+):\*\*$/);
|
|
197482
|
+
if (kind?.[1]) {
|
|
197483
|
+
relationKind = kind[1].trim();
|
|
197484
|
+
continue;
|
|
197485
|
+
}
|
|
197486
|
+
}
|
|
197487
|
+
}
|
|
197488
|
+
const bySymbolName = /* @__PURE__ */ new Map();
|
|
197489
|
+
for (const node of [...entryPoints, ...nodes]) {
|
|
197490
|
+
if (!bySymbolName.has(node.name)) bySymbolName.set(node.name, node);
|
|
197491
|
+
}
|
|
197492
|
+
const relations = [];
|
|
197493
|
+
if (section2 === "relationships") {
|
|
197494
|
+
for (const rawLine of value.split(/\r?\n/)) {
|
|
197495
|
+
const line = rawLine.trim();
|
|
197496
|
+
const match2 = line.match(/^-\s+(.+?)\s+(?:\u2192|->)\s+(.+)$/);
|
|
197497
|
+
if (!match2) continue;
|
|
197498
|
+
const from = bySymbolName.get(match2[1].trim());
|
|
197499
|
+
const to2 = bySymbolName.get(match2[2].trim());
|
|
197500
|
+
if (!from || !to2) continue;
|
|
197501
|
+
relations.push({
|
|
197502
|
+
from: externalSymbol(from),
|
|
197503
|
+
to: externalSymbol(to2),
|
|
197504
|
+
kind: relationKind
|
|
197505
|
+
});
|
|
197506
|
+
}
|
|
197507
|
+
} else {
|
|
197508
|
+
const relationshipStart = value.split(/\r?\n/).findIndex((line) => /^\s*\*\*Relationships\*\*\s*$/i.test(line));
|
|
197509
|
+
if (relationshipStart >= 0) {
|
|
197510
|
+
const relationshipLines = value.split(/\r?\n/).slice(relationshipStart + 1);
|
|
197511
|
+
for (const rawLine of relationshipLines) {
|
|
197512
|
+
const line = rawLine.trim();
|
|
197513
|
+
if (/^\*\*(?:Source Code|Code)\*\*$/i.test(line) || /^#{2,3}\s+/i.test(line)) break;
|
|
197514
|
+
const kind = line.match(/^\*\*([^*]+):\*\*$/);
|
|
197515
|
+
if (kind?.[1]) {
|
|
197516
|
+
relationKind = kind[1].trim();
|
|
197517
|
+
continue;
|
|
197518
|
+
}
|
|
197519
|
+
const match2 = line.match(/^-\s+(.+?)\s+(?:\u2192|->)\s+(.+)$/);
|
|
197520
|
+
if (!match2) continue;
|
|
197521
|
+
const from = bySymbolName.get(match2[1].trim());
|
|
197522
|
+
const to2 = bySymbolName.get(match2[2].trim());
|
|
197523
|
+
if (from && to2) relations.push({ from: externalSymbol(from), to: externalSymbol(to2), kind: relationKind });
|
|
197524
|
+
}
|
|
197525
|
+
}
|
|
197526
|
+
}
|
|
197527
|
+
const allNodes = [...entryPoints, ...nodes];
|
|
197528
|
+
if (allNodes.length === 0) return void 0;
|
|
197529
|
+
return {
|
|
197530
|
+
provider: "external",
|
|
197531
|
+
entryPoints: entryPoints.map(externalSymbol).slice(0, 5),
|
|
197532
|
+
relations: relations.slice(0, 6),
|
|
197533
|
+
relatedFiles: [...relatedFiles].slice(0, 5),
|
|
197534
|
+
stats: {
|
|
197535
|
+
nodes: allNodes.length,
|
|
197536
|
+
edges: relations.length,
|
|
197537
|
+
files: relatedFiles.size
|
|
197538
|
+
}
|
|
197539
|
+
};
|
|
197540
|
+
}
|
|
197541
|
+
function parseExplorePayload(value, projectRoot, exclude) {
|
|
197542
|
+
if (typeof value === "string") return parseExploreText(value, projectRoot, exclude);
|
|
197543
|
+
if (isRecord3(value) && isRecord3(value.result)) value = value.result;
|
|
197544
|
+
if (isRecord3(value) && Array.isArray(value.content)) {
|
|
197545
|
+
const text2 = value.content.filter((item) => isRecord3(item) && item.type === "text" && typeof item.text === "string").map((item) => item.text).join("\n");
|
|
197546
|
+
return parseExploreText(text2, projectRoot, exclude);
|
|
197547
|
+
}
|
|
197548
|
+
return parseOutline(value, projectRoot, exclude);
|
|
197549
|
+
}
|
|
197353
197550
|
function fallbackCaution(health) {
|
|
197354
197551
|
if (health.state === "disabled" || health.state === "not-detected" || health.state === "not-initialized" || health.state === "ready") return void 0;
|
|
197355
197552
|
return "External semantic CodeGraph is " + health.state + "; using Lite structural evidence for this brief.";
|
|
197356
197553
|
}
|
|
197554
|
+
function queryFallbackCaution(diagnostics) {
|
|
197555
|
+
return `External semantic CodeGraph context was unavailable (context: ${diagnostics.context.outcome}; explore: ${diagnostics.explore.outcome}); using Lite structural evidence.`;
|
|
197556
|
+
}
|
|
197357
197557
|
async function getExternalCodeGraphContext(input) {
|
|
197358
197558
|
const inspected = await inspectExternalCodeGraph(input);
|
|
197359
197559
|
if (inspected.health.state !== "ready") {
|
|
197360
197560
|
return { ...inspected, caution: fallbackCaution(inspected.health) };
|
|
197361
197561
|
}
|
|
197362
197562
|
const mode = input.mode ?? "auto";
|
|
197363
|
-
const
|
|
197563
|
+
const runner = input.runner ?? defaultRunner;
|
|
197564
|
+
const contextResult = await runSafely(runner, {
|
|
197364
197565
|
command: input.command,
|
|
197365
197566
|
args: ["context", "--path", input.projectRoot, "--format", "json", "--max-nodes", "8", "--no-code", input.task],
|
|
197366
197567
|
cwd: input.projectRoot,
|
|
197367
197568
|
timeoutMs: boundedTimeout(input.timeoutMs),
|
|
197368
197569
|
maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
|
|
197369
197570
|
});
|
|
197370
|
-
|
|
197371
|
-
|
|
197571
|
+
const diagnostics = {
|
|
197572
|
+
context: contextResult.ok ? commandDiagnostic("context", contextResult, "success") : failedCommandDiagnostic("context", contextResult),
|
|
197573
|
+
explore: notAttemptedDiagnostic("explore")
|
|
197574
|
+
};
|
|
197575
|
+
const contextOutline = contextResult.ok ? parseOutline(parseJson2(contextResult.stdout), input.projectRoot, input.exclude) : void 0;
|
|
197576
|
+
if (contextOutline && (contextOutline.entryPoints.length > 0 || contextOutline.relations.length > 0 || contextOutline.relatedFiles.length > 0)) {
|
|
197372
197577
|
return {
|
|
197373
|
-
|
|
197374
|
-
|
|
197375
|
-
|
|
197578
|
+
...inspected,
|
|
197579
|
+
outline: contextOutline,
|
|
197580
|
+
diagnostics,
|
|
197581
|
+
quality: providerQuality({ mode, health: inspected.health, selected: "external" })
|
|
197376
197582
|
};
|
|
197377
197583
|
}
|
|
197378
|
-
|
|
197379
|
-
|
|
197380
|
-
|
|
197584
|
+
if (contextResult.ok) diagnostics.context = commandDiagnostic("context", contextResult, "invalid-output", "The context payload failed validation or contained no safe outline.");
|
|
197585
|
+
const exploreResult = await runSafely(runner, {
|
|
197586
|
+
command: input.command,
|
|
197587
|
+
args: ["explore", "--path", input.projectRoot, "--max-files", "4", input.task],
|
|
197588
|
+
cwd: input.projectRoot,
|
|
197589
|
+
timeoutMs: boundedTimeout(input.timeoutMs),
|
|
197590
|
+
maxOutputBytes: MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES
|
|
197591
|
+
});
|
|
197592
|
+
diagnostics.explore = exploreResult.ok ? commandDiagnostic("explore", exploreResult, "success") : failedCommandDiagnostic("explore", exploreResult);
|
|
197593
|
+
const exploreOutline = exploreResult.ok ? parseExplorePayload(parseJson2(exploreResult.stdout) ?? exploreResult.stdout, input.projectRoot, input.exclude) : void 0;
|
|
197594
|
+
if (exploreOutline && (exploreOutline.entryPoints.length > 0 || exploreOutline.relations.length > 0 || exploreOutline.relatedFiles.length > 0)) {
|
|
197381
197595
|
return {
|
|
197382
|
-
|
|
197383
|
-
|
|
197384
|
-
|
|
197596
|
+
...inspected,
|
|
197597
|
+
outline: exploreOutline,
|
|
197598
|
+
diagnostics,
|
|
197599
|
+
quality: providerQuality({ mode, health: inspected.health, selected: "external" })
|
|
197385
197600
|
};
|
|
197386
197601
|
}
|
|
197387
|
-
|
|
197602
|
+
if (exploreResult.ok) diagnostics.explore = commandDiagnostic("explore", exploreResult, "invalid-output", "The explore payload failed validation or contained no safe outline.");
|
|
197603
|
+
const health = exploreResult.ok ? { state: "invalid", reason: "The local CodeGraph context and explore payloads failed validation." } : unavailableHealth(exploreResult);
|
|
197388
197604
|
return {
|
|
197389
|
-
|
|
197390
|
-
|
|
197391
|
-
|
|
197605
|
+
health,
|
|
197606
|
+
quality: providerQuality({ mode, health }),
|
|
197607
|
+
diagnostics,
|
|
197608
|
+
caution: queryFallbackCaution(diagnostics)
|
|
197392
197609
|
};
|
|
197393
197610
|
}
|
|
197394
197611
|
var DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS, EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS, MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES, MAX_EXTERNAL_NODE_COUNT, MAX_EXTERNAL_EDGE_COUNT, MAX_EXTERNAL_FILE_COUNT, MAX_EXTERNAL_TEXT_LENGTH, LITE_SUPPORTED_LANGUAGES, defaultRunner;
|
|
@@ -197399,7 +197616,7 @@ var init_external_provider = __esm({
|
|
|
197399
197616
|
init_secret_filter();
|
|
197400
197617
|
init_exclude3();
|
|
197401
197618
|
init_ids();
|
|
197402
|
-
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS =
|
|
197619
|
+
DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 3e3;
|
|
197403
197620
|
MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS = 5e3;
|
|
197404
197621
|
EXTERNAL_CODEGRAPH_LIFECYCLE_TIMEOUT_MS = 3e4;
|
|
197405
197622
|
MAX_EXTERNAL_CODEGRAPH_OUTPUT_BYTES = 256 * 1024;
|
|
@@ -205547,6 +205764,259 @@ var init_tool_profile = __esm({
|
|
|
205547
205764
|
}
|
|
205548
205765
|
});
|
|
205549
205766
|
|
|
205767
|
+
// src/server/mcp-discovery.ts
|
|
205768
|
+
function getMcpServerInfo() {
|
|
205769
|
+
return {
|
|
205770
|
+
name: "memorix",
|
|
205771
|
+
version: true ? "1.8.3" : "1.0.1"
|
|
205772
|
+
};
|
|
205773
|
+
}
|
|
205774
|
+
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
205775
|
+
return {
|
|
205776
|
+
resultType: "complete",
|
|
205777
|
+
supportedVersions: [
|
|
205778
|
+
MCP_MODERN_PROTOCOL_VERSION,
|
|
205779
|
+
MCP_LEGACY_PROTOCOL_VERSION,
|
|
205780
|
+
MCP_OLDEST_LEGACY_PROTOCOL_VERSION
|
|
205781
|
+
],
|
|
205782
|
+
capabilities,
|
|
205783
|
+
_meta: {
|
|
205784
|
+
[MCP_SERVER_INFO_META_KEY]: { ...serverInfo }
|
|
205785
|
+
},
|
|
205786
|
+
// v1 has no response-cache negotiation. A zero private TTL prevents clients
|
|
205787
|
+
// from inventing a shared cache for an implementation that cannot invalidate it.
|
|
205788
|
+
ttlMs: 0,
|
|
205789
|
+
cacheScope: "private"
|
|
205790
|
+
};
|
|
205791
|
+
}
|
|
205792
|
+
function createMcpStartupDiscoverResult(serverInfo) {
|
|
205793
|
+
return createMcpDiscoverResult({ tools: { listChanged: true } }, serverInfo);
|
|
205794
|
+
}
|
|
205795
|
+
var MCP_MODERN_PROTOCOL_VERSION, MCP_LEGACY_PROTOCOL_VERSION, MCP_OLDEST_LEGACY_PROTOCOL_VERSION, MCP_SERVER_DISCOVER_METHOD, MCP_SERVER_INFO_META_KEY;
|
|
205796
|
+
var init_mcp_discovery = __esm({
|
|
205797
|
+
"src/server/mcp-discovery.ts"() {
|
|
205798
|
+
"use strict";
|
|
205799
|
+
init_esm_shims();
|
|
205800
|
+
MCP_MODERN_PROTOCOL_VERSION = "2026-07-28";
|
|
205801
|
+
MCP_LEGACY_PROTOCOL_VERSION = "2025-11-25";
|
|
205802
|
+
MCP_OLDEST_LEGACY_PROTOCOL_VERSION = "2024-11-05";
|
|
205803
|
+
MCP_SERVER_DISCOVER_METHOD = "server/discover";
|
|
205804
|
+
MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
|
|
205805
|
+
}
|
|
205806
|
+
});
|
|
205807
|
+
|
|
205808
|
+
// src/server/stdio-startup-gate.ts
|
|
205809
|
+
import { PassThrough as PassThrough3 } from "stream";
|
|
205810
|
+
var STDIO_STARTUP_GATE_MAX_BUFFER_SIZE, StdioStartupGate;
|
|
205811
|
+
var init_stdio_startup_gate = __esm({
|
|
205812
|
+
"src/server/stdio-startup-gate.ts"() {
|
|
205813
|
+
"use strict";
|
|
205814
|
+
init_esm_shims();
|
|
205815
|
+
init_mcp_discovery();
|
|
205816
|
+
STDIO_STARTUP_GATE_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
205817
|
+
StdioStartupGate = class {
|
|
205818
|
+
input = new PassThrough3();
|
|
205819
|
+
stdin;
|
|
205820
|
+
stdout;
|
|
205821
|
+
serverInfo;
|
|
205822
|
+
maxBufferSize;
|
|
205823
|
+
onError;
|
|
205824
|
+
onEnd;
|
|
205825
|
+
queuedMessages = [];
|
|
205826
|
+
pendingInput = "";
|
|
205827
|
+
queuedBytes = 0;
|
|
205828
|
+
started = false;
|
|
205829
|
+
ready = false;
|
|
205830
|
+
stopped = false;
|
|
205831
|
+
stdinEnded = false;
|
|
205832
|
+
endNotified = false;
|
|
205833
|
+
onData = (chunk) => {
|
|
205834
|
+
if (this.stopped) return;
|
|
205835
|
+
if (this.ready) {
|
|
205836
|
+
if (Buffer.byteLength(chunk, "utf8") > this.maxBufferSize) {
|
|
205837
|
+
this.fail(new Error(`stdio input chunk exceeded ${this.maxBufferSize} bytes`));
|
|
205838
|
+
return;
|
|
205839
|
+
}
|
|
205840
|
+
this.input.write(chunk);
|
|
205841
|
+
return;
|
|
205842
|
+
}
|
|
205843
|
+
const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
205844
|
+
if (this.queuedBytes + Buffer.byteLength(this.pendingInput, "utf8") + Buffer.byteLength(text2, "utf8") > this.maxBufferSize) {
|
|
205845
|
+
this.fail(new Error(`stdio startup input exceeded ${this.maxBufferSize} bytes before a complete JSON-RPC line`));
|
|
205846
|
+
return;
|
|
205847
|
+
}
|
|
205848
|
+
this.pendingInput += text2;
|
|
205849
|
+
let newline = this.pendingInput.indexOf("\n");
|
|
205850
|
+
while (newline >= 0 && !this.stopped) {
|
|
205851
|
+
const line = this.pendingInput.slice(0, newline + 1);
|
|
205852
|
+
this.pendingInput = this.pendingInput.slice(newline + 1);
|
|
205853
|
+
this.handleLine(line);
|
|
205854
|
+
newline = this.pendingInput.indexOf("\n");
|
|
205855
|
+
}
|
|
205856
|
+
if (!this.stopped && Buffer.byteLength(this.pendingInput, "utf8") > this.maxBufferSize) {
|
|
205857
|
+
this.fail(new Error(`stdio startup input exceeded ${this.maxBufferSize} bytes`));
|
|
205858
|
+
}
|
|
205859
|
+
};
|
|
205860
|
+
onStdinError = (error40) => {
|
|
205861
|
+
this.fail(error40);
|
|
205862
|
+
};
|
|
205863
|
+
onStdinEnd = () => {
|
|
205864
|
+
this.stdinEnded = true;
|
|
205865
|
+
if (this.ready) this.finishInput();
|
|
205866
|
+
};
|
|
205867
|
+
constructor(options) {
|
|
205868
|
+
this.stdin = options.stdin;
|
|
205869
|
+
this.stdout = options.stdout;
|
|
205870
|
+
this.serverInfo = { ...options.serverInfo };
|
|
205871
|
+
this.maxBufferSize = options.maxBufferSize ?? STDIO_STARTUP_GATE_MAX_BUFFER_SIZE;
|
|
205872
|
+
this.onError = options.onError;
|
|
205873
|
+
this.onEnd = options.onEnd;
|
|
205874
|
+
}
|
|
205875
|
+
start() {
|
|
205876
|
+
if (this.started || this.stopped) return;
|
|
205877
|
+
this.started = true;
|
|
205878
|
+
this.stdin.on("data", this.onData);
|
|
205879
|
+
this.stdin.on("error", this.onStdinError);
|
|
205880
|
+
this.stdin.on("end", this.onStdinEnd);
|
|
205881
|
+
}
|
|
205882
|
+
/** Release queued messages only after StdioServerTransport has installed its listener. */
|
|
205883
|
+
markReady() {
|
|
205884
|
+
if (this.stopped || this.ready) return;
|
|
205885
|
+
this.ready = true;
|
|
205886
|
+
for (const message of this.queuedMessages) this.input.write(message);
|
|
205887
|
+
this.queuedMessages.length = 0;
|
|
205888
|
+
this.queuedBytes = 0;
|
|
205889
|
+
if (this.pendingInput) {
|
|
205890
|
+
this.input.write(this.pendingInput);
|
|
205891
|
+
this.pendingInput = "";
|
|
205892
|
+
}
|
|
205893
|
+
if (this.stdinEnded) this.finishInput();
|
|
205894
|
+
}
|
|
205895
|
+
stop() {
|
|
205896
|
+
if (this.stopped) return;
|
|
205897
|
+
this.stopped = true;
|
|
205898
|
+
this.stdin.off("data", this.onData);
|
|
205899
|
+
this.stdin.off("error", this.onStdinError);
|
|
205900
|
+
this.stdin.off("end", this.onStdinEnd);
|
|
205901
|
+
this.queuedMessages.length = 0;
|
|
205902
|
+
this.pendingInput = "";
|
|
205903
|
+
this.queuedBytes = 0;
|
|
205904
|
+
if (!this.input.destroyed) this.input.end();
|
|
205905
|
+
}
|
|
205906
|
+
handleLine(line) {
|
|
205907
|
+
const parsed = this.parseLine(line);
|
|
205908
|
+
if (!parsed) return;
|
|
205909
|
+
if ("error" in parsed) {
|
|
205910
|
+
this.writeJsonRpcError(null, parsed.error.code, parsed.error.message);
|
|
205911
|
+
return;
|
|
205912
|
+
}
|
|
205913
|
+
if (!this.ready && this.isDiscoveryRequest(parsed.message)) {
|
|
205914
|
+
const response = {
|
|
205915
|
+
jsonrpc: "2.0",
|
|
205916
|
+
id: parsed.message.id,
|
|
205917
|
+
result: createMcpStartupDiscoverResult(this.serverInfo)
|
|
205918
|
+
};
|
|
205919
|
+
try {
|
|
205920
|
+
this.stdout.write(`${JSON.stringify(response)}
|
|
205921
|
+
`);
|
|
205922
|
+
} catch (error40) {
|
|
205923
|
+
this.fail(error40 instanceof Error ? error40 : new Error(String(error40)));
|
|
205924
|
+
}
|
|
205925
|
+
return;
|
|
205926
|
+
}
|
|
205927
|
+
if (this.ready) {
|
|
205928
|
+
this.input.write(line);
|
|
205929
|
+
return;
|
|
205930
|
+
}
|
|
205931
|
+
const bytes = Buffer.byteLength(line, "utf8");
|
|
205932
|
+
if (this.queuedBytes + bytes > this.maxBufferSize) {
|
|
205933
|
+
this.fail(new Error(`stdio startup queue exceeded ${this.maxBufferSize} bytes`));
|
|
205934
|
+
return;
|
|
205935
|
+
}
|
|
205936
|
+
this.queuedMessages.push(line);
|
|
205937
|
+
this.queuedBytes += bytes;
|
|
205938
|
+
}
|
|
205939
|
+
parseLine(line) {
|
|
205940
|
+
const trimmed = line.endsWith("\n") ? line.slice(0, -1).replace(/\r$/, "") : line;
|
|
205941
|
+
if (!trimmed.trim()) return null;
|
|
205942
|
+
let value;
|
|
205943
|
+
try {
|
|
205944
|
+
value = JSON.parse(trimmed);
|
|
205945
|
+
} catch {
|
|
205946
|
+
return { error: { code: -32700, message: "Parse error" } };
|
|
205947
|
+
}
|
|
205948
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
205949
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205950
|
+
}
|
|
205951
|
+
const message = value;
|
|
205952
|
+
if (message.jsonrpc !== "2.0") {
|
|
205953
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205954
|
+
}
|
|
205955
|
+
const hasId = Object.prototype.hasOwnProperty.call(message, "id");
|
|
205956
|
+
const hasMethod = typeof message.method === "string";
|
|
205957
|
+
const hasResult = Object.prototype.hasOwnProperty.call(message, "result");
|
|
205958
|
+
const hasError = Object.prototype.hasOwnProperty.call(message, "error");
|
|
205959
|
+
if (hasMethod && (hasResult || hasError)) {
|
|
205960
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205961
|
+
}
|
|
205962
|
+
if (!hasMethod && !hasResult && !hasError) {
|
|
205963
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205964
|
+
}
|
|
205965
|
+
if (hasId && !this.isValidRequestId(message.id)) {
|
|
205966
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205967
|
+
}
|
|
205968
|
+
if (!hasMethod && !hasId) {
|
|
205969
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205970
|
+
}
|
|
205971
|
+
return { message };
|
|
205972
|
+
}
|
|
205973
|
+
isDiscoveryRequest(message) {
|
|
205974
|
+
if (message.method !== MCP_SERVER_DISCOVER_METHOD) return false;
|
|
205975
|
+
if (!Object.prototype.hasOwnProperty.call(message, "id")) return false;
|
|
205976
|
+
const params = message.params;
|
|
205977
|
+
return params === void 0 || typeof params === "object" && params !== null && !Array.isArray(params);
|
|
205978
|
+
}
|
|
205979
|
+
isValidRequestId(id) {
|
|
205980
|
+
return id === null || typeof id === "string" || typeof id === "number" && Number.isFinite(id);
|
|
205981
|
+
}
|
|
205982
|
+
writeJsonRpcError(id, code, message) {
|
|
205983
|
+
try {
|
|
205984
|
+
this.stdout.write(`${JSON.stringify({
|
|
205985
|
+
jsonrpc: "2.0",
|
|
205986
|
+
id,
|
|
205987
|
+
error: { code, message }
|
|
205988
|
+
})}
|
|
205989
|
+
`);
|
|
205990
|
+
} catch (error40) {
|
|
205991
|
+
this.fail(error40 instanceof Error ? error40 : new Error(String(error40)));
|
|
205992
|
+
}
|
|
205993
|
+
}
|
|
205994
|
+
finishInput() {
|
|
205995
|
+
if (!this.ready || this.input.destroyed || this.input.writableEnded) return;
|
|
205996
|
+
this.input.end();
|
|
205997
|
+
this.input.once("end", () => this.notifyEnd());
|
|
205998
|
+
}
|
|
205999
|
+
notifyEnd() {
|
|
206000
|
+
if (this.endNotified) return;
|
|
206001
|
+
this.endNotified = true;
|
|
206002
|
+
this.onEnd?.();
|
|
206003
|
+
}
|
|
206004
|
+
fail(error40) {
|
|
206005
|
+
if (this.stopped) return;
|
|
206006
|
+
this.stopped = true;
|
|
206007
|
+
this.stdin.off("data", this.onData);
|
|
206008
|
+
this.stdin.off("error", this.onStdinError);
|
|
206009
|
+
this.stdin.off("end", this.onStdinEnd);
|
|
206010
|
+
this.queuedMessages.length = 0;
|
|
206011
|
+
this.pendingInput = "";
|
|
206012
|
+
this.queuedBytes = 0;
|
|
206013
|
+
if (!this.input.destroyed) this.input.destroy();
|
|
206014
|
+
this.onError?.(error40);
|
|
206015
|
+
}
|
|
206016
|
+
};
|
|
206017
|
+
}
|
|
206018
|
+
});
|
|
206019
|
+
|
|
205550
206020
|
// src/cli/mcp-root-path.ts
|
|
205551
206021
|
import path37 from "path";
|
|
205552
206022
|
function mcpFileUriToPath(uri, platform2 = process.platform) {
|
|
@@ -218992,6 +219462,33 @@ var init_request_context = __esm({
|
|
|
218992
219462
|
}
|
|
218993
219463
|
});
|
|
218994
219464
|
|
|
219465
|
+
// src/server/mcp-compat.ts
|
|
219466
|
+
function buildMcpDiscoverResult(server, serverInfo) {
|
|
219467
|
+
const getCapabilities = server.server.getCapabilities.bind(server.server);
|
|
219468
|
+
return createMcpDiscoverResult(getCapabilities(), serverInfo);
|
|
219469
|
+
}
|
|
219470
|
+
function registerMcpDiscovery(server, serverInfo) {
|
|
219471
|
+
if (registeredServers.has(server)) return;
|
|
219472
|
+
server.server.setRequestHandler(ServerDiscoverRequestSchema, async () => buildMcpDiscoverResult(server, serverInfo));
|
|
219473
|
+
registeredServers.add(server);
|
|
219474
|
+
}
|
|
219475
|
+
var ServerDiscoverRequestSchema, registeredServers;
|
|
219476
|
+
var init_mcp_compat = __esm({
|
|
219477
|
+
"src/server/mcp-compat.ts"() {
|
|
219478
|
+
"use strict";
|
|
219479
|
+
init_esm_shims();
|
|
219480
|
+
init_types8();
|
|
219481
|
+
init_v4();
|
|
219482
|
+
init_mcp_discovery();
|
|
219483
|
+
init_mcp_discovery();
|
|
219484
|
+
ServerDiscoverRequestSchema = RequestSchema.extend({
|
|
219485
|
+
method: external_exports.literal(MCP_SERVER_DISCOVER_METHOD),
|
|
219486
|
+
params: external_exports.looseObject({}).optional()
|
|
219487
|
+
});
|
|
219488
|
+
registeredServers = /* @__PURE__ */ new WeakSet();
|
|
219489
|
+
}
|
|
219490
|
+
});
|
|
219491
|
+
|
|
218995
219492
|
// src/config/behavior.ts
|
|
218996
219493
|
var behavior_exports = {};
|
|
218997
219494
|
__export(behavior_exports, {
|
|
@@ -219278,6 +219775,7 @@ async function executeCleanup(context, payload, token) {
|
|
|
219278
219775
|
return { action: "cleanup", projectId: context.projectId, ...result };
|
|
219279
219776
|
}
|
|
219280
219777
|
async function previewDeduplicate(context) {
|
|
219778
|
+
initLLM({ scope: "memory", projectRoot: context.projectRoot });
|
|
219281
219779
|
if (!isLLMEnabled()) {
|
|
219282
219780
|
return {
|
|
219283
219781
|
action: "deduplicate",
|
|
@@ -261370,10 +261868,9 @@ The path should point to a directory containing a .git folder.`
|
|
|
261370
261868
|
isError: true
|
|
261371
261869
|
};
|
|
261372
261870
|
};
|
|
261373
|
-
const
|
|
261374
|
-
|
|
261375
|
-
|
|
261376
|
-
});
|
|
261871
|
+
const serverInfo = getMcpServerInfo();
|
|
261872
|
+
const server = existingServer ?? new McpServer(serverInfo);
|
|
261873
|
+
registerMcpDiscovery(server, serverInfo);
|
|
261377
261874
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
261378
261875
|
server.registerTool = ((name, ...args) => {
|
|
261379
261876
|
if (!isToolInProfile(name, toolProfile)) {
|
|
@@ -265751,6 +266248,7 @@ var init_server4 = __esm({
|
|
|
265751
266248
|
init_secret_filter();
|
|
265752
266249
|
init_surfaced_registry();
|
|
265753
266250
|
init_request_context();
|
|
266251
|
+
init_mcp_compat();
|
|
265754
266252
|
FORMATION_TIMEOUT_MS = parseFormationTimeoutMs(process.env.MEMORIX_FORMATION_TIMEOUT_MS);
|
|
265755
266253
|
COMPACT_ON_WRITE_TIMEOUT_MS = 12e3;
|
|
265756
266254
|
COMPRESSION_TIMEOUT_MS = 5e3;
|
|
@@ -266106,6 +266604,8 @@ var init_serve = __esm({
|
|
|
266106
266604
|
init_esm_shims();
|
|
266107
266605
|
init_dist2();
|
|
266108
266606
|
init_tool_profile();
|
|
266607
|
+
init_mcp_discovery();
|
|
266608
|
+
init_stdio_startup_gate();
|
|
266109
266609
|
init_mcp_root_path();
|
|
266110
266610
|
serve_default = defineCommand({
|
|
266111
266611
|
meta: {
|
|
@@ -266130,15 +266630,25 @@ var init_serve = __esm({
|
|
|
266130
266630
|
}
|
|
266131
266631
|
},
|
|
266132
266632
|
run: async ({ args }) => {
|
|
266633
|
+
const startupGate = new StdioStartupGate({
|
|
266634
|
+
stdin: process.stdin,
|
|
266635
|
+
stdout: process.stdout,
|
|
266636
|
+
serverInfo: getMcpServerInfo(),
|
|
266637
|
+
onError: (error40) => {
|
|
266638
|
+
console.error(`[memorix] stdio startup gate error: ${error40.message}`);
|
|
266639
|
+
process.exit(1);
|
|
266640
|
+
},
|
|
266641
|
+
onEnd: () => {
|
|
266642
|
+
console.error("[memorix] stdin closed \u2014 exiting");
|
|
266643
|
+
process.exitCode = 0;
|
|
266644
|
+
}
|
|
266645
|
+
});
|
|
266646
|
+
startupGate.start();
|
|
266133
266647
|
const { StdioServerTransport: StdioServerTransport2 } = await Promise.resolve().then(() => (init_stdio2(), stdio_exports));
|
|
266134
266648
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
266135
266649
|
const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
266136
266650
|
const { homedir: homedir36 } = await import("os");
|
|
266137
266651
|
const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
|
|
266138
|
-
process.stdin.on("end", () => {
|
|
266139
|
-
console.error("[memorix] stdin closed \u2014 exiting");
|
|
266140
|
-
process.exit(0);
|
|
266141
|
-
});
|
|
266142
266652
|
let safeCwd;
|
|
266143
266653
|
try {
|
|
266144
266654
|
safeCwd = process.cwd();
|
|
@@ -266173,8 +266683,9 @@ var init_serve = __esm({
|
|
|
266173
266683
|
const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "micro" });
|
|
266174
266684
|
const serverOptions = detected ? { toolProfile, deferProjectRuntimeInit: true } : { allowUntrackedFallback: allowUntracked, deferProjectInitUntilBound: !allowUntracked, deferProjectRuntimeInit: true, toolProfile };
|
|
266175
266685
|
const { server, projectId, deferredInit, switchProject } = await createMemorixServer2(projectRoot, void 0, void 0, serverOptions);
|
|
266176
|
-
const transport = new StdioServerTransport2();
|
|
266686
|
+
const transport = new StdioServerTransport2(startupGate.input, process.stdout);
|
|
266177
266687
|
await server.connect(transport);
|
|
266688
|
+
startupGate.markReady();
|
|
266178
266689
|
console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
|
|
266179
266690
|
console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
|
|
266180
266691
|
const tryRootsSwitch = async () => {
|
|
@@ -266232,13 +266743,17 @@ function getMcpDiagnostics() {
|
|
|
266232
266743
|
protocol: {
|
|
266233
266744
|
current: CURRENT_MCP_PROTOCOL_VERSION,
|
|
266234
266745
|
legacy: LEGACY_MCP_PROTOCOL_VERSION,
|
|
266235
|
-
|
|
266746
|
+
discovery: "supported",
|
|
266747
|
+
versionlessRequests: "legacy-compatible",
|
|
266748
|
+
modernResultMetadata: "discovery-only",
|
|
266749
|
+
statelessRequests: "compatibility-only",
|
|
266236
266750
|
statefulStreamableHttp: "supported"
|
|
266237
266751
|
},
|
|
266238
266752
|
capabilities: {
|
|
266239
266753
|
tasks: "unsupported",
|
|
266240
266754
|
polling: "unsupported",
|
|
266241
|
-
|
|
266755
|
+
subscriptions: "unsupported",
|
|
266756
|
+
listCache: "unsupported",
|
|
266242
266757
|
explicitProjectHandle: "supported"
|
|
266243
266758
|
}
|
|
266244
266759
|
};
|
|
@@ -266249,7 +266764,7 @@ var init_mcp_diagnostics = __esm({
|
|
|
266249
266764
|
"use strict";
|
|
266250
266765
|
init_esm_shims();
|
|
266251
266766
|
CURRENT_MCP_PROTOCOL_VERSION = "2026-07-28";
|
|
266252
|
-
LEGACY_MCP_PROTOCOL_VERSION = "
|
|
266767
|
+
LEGACY_MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
266253
266768
|
MCP_SERVER_NAME = "io.github.AVIDS2/memorix";
|
|
266254
266769
|
}
|
|
266255
266770
|
});
|
|
@@ -268493,9 +269008,13 @@ __export(serve_http_exports, {
|
|
|
268493
269008
|
MCP_SDK_COMPAT_PROTOCOL_VERSION: () => MCP_SDK_COMPAT_PROTOCOL_VERSION,
|
|
268494
269009
|
_testing: () => _testing2,
|
|
268495
269010
|
default: () => serve_http_default,
|
|
269011
|
+
isServerDiscoverRequest: () => isServerDiscoverRequest,
|
|
268496
269012
|
parseSessionTimeoutMs: () => parseSessionTimeoutMs,
|
|
268497
269013
|
resolveServeHttpDefaults: () => resolveServeHttpDefaults
|
|
268498
269014
|
});
|
|
269015
|
+
function isServerDiscoverRequest(body) {
|
|
269016
|
+
return Boolean(body && typeof body === "object" && !Array.isArray(body) && body.method === "server/discover");
|
|
269017
|
+
}
|
|
268499
269018
|
function parseSessionTimeoutMs(raw) {
|
|
268500
269019
|
const value = raw?.trim();
|
|
268501
269020
|
if (!value) return DEFAULT_SESSION_TIMEOUT_MS;
|
|
@@ -268776,7 +269295,7 @@ var init_serve_http = __esm({
|
|
|
268776
269295
|
}
|
|
268777
269296
|
const requestedRoot = typeof req.headers["mcp-project-root"] === "string" ? req.headers["mcp-project-root"] : void 0;
|
|
268778
269297
|
const root = persisted?.projectRoot ?? requestedRoot ?? projectRoot;
|
|
268779
|
-
if (!persisted && !isInitializeRequest2(body)) {
|
|
269298
|
+
if (!persisted && !isInitializeRequest2(body) && !isServerDiscoverRequest(body)) {
|
|
268780
269299
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
268781
269300
|
res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32e3, message: "Stateless MCP requests require Mcp-Project-Handle; initialize first." }, id: null }));
|
|
268782
269301
|
return;
|
|
@@ -268840,7 +269359,7 @@ var init_serve_http = __esm({
|
|
|
268840
269359
|
const sessionId = req.headers["mcp-session-id"];
|
|
268841
269360
|
const body = await parseBody(req);
|
|
268842
269361
|
const requestedProtocol = req.headers["mcp-protocol-version"];
|
|
268843
|
-
const statelessRequested = req.headers["mcp-stateless"] === "true" || requestedProtocol === CURRENT_MCP_PROTOCOL_VERSION;
|
|
269362
|
+
const statelessRequested = req.headers["mcp-stateless"] === "true" || requestedProtocol === CURRENT_MCP_PROTOCOL_VERSION || typeof req.headers["mcp-project-handle"] === "string" || isServerDiscoverRequest(body);
|
|
268844
269363
|
if (!sessionId && statelessRequested) {
|
|
268845
269364
|
await handleStatelessPost(req, res, body);
|
|
268846
269365
|
return;
|