@danielblomma/cortex-mcp 2.0.9 → 2.0.12
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/package.json +1 -1
- package/scaffold/mcp/package.json +2 -1
- package/scaffold/mcp/src/embed.ts +5 -10
- package/scaffold/mcp/src/loadGraph.ts +1 -7
- package/scaffold/mcp/src/paths.ts +39 -3
- package/scaffold/mcp/tests/paths.test.mjs +38 -0
- package/scaffold/scripts/embed.sh +1 -1
- package/scaffold/scripts/load-ryu.sh +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielblomma/cortex-mcp",
|
|
3
3
|
"mcpName": "io.github.DanielBlomma/cortex",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.12",
|
|
5
5
|
"description": "Local, repo-scoped context platform for coding assistants. Semantic search, graph relationships, and architectural rule context.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Daniel Blomma",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"graph:load": "npm run build --silent && node dist/loadGraph.js",
|
|
10
10
|
"dev": "node --loader ts-node/esm src/server.ts",
|
|
11
11
|
"start": "node dist/server.js",
|
|
12
|
-
"test": "npm run build --silent && node --test tests/*.test.mjs"
|
|
12
|
+
"test": "npm run build --silent && node --test tests/*.test.mjs",
|
|
13
|
+
"test:ci": "npm run build --silent && node --test --test-reporter=spec tests/*.test.mjs"
|
|
13
14
|
},
|
|
14
15
|
"dependencies": {
|
|
15
16
|
"@huggingface/transformers": "^4.1.0",
|
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
4
|
import { env, pipeline } from "@huggingface/transformers";
|
|
6
5
|
import { readJsonl, asString, asNumber, asBoolean } from "./jsonl.js";
|
|
6
|
+
import { CACHE_DIR, PATHS } from "./paths.js";
|
|
7
7
|
import type { JsonObject, JsonValue } from "./types.js";
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const CACHE_DIR = path.join(CONTEXT_DIR, "cache");
|
|
14
|
-
const EMBEDDINGS_DIR = path.join(CONTEXT_DIR, "embeddings");
|
|
15
|
-
const EMBEDDINGS_PATH = path.join(EMBEDDINGS_DIR, "entities.jsonl");
|
|
16
|
-
const EMBEDDINGS_MANIFEST_PATH = path.join(EMBEDDINGS_DIR, "manifest.json");
|
|
17
|
-
const MODEL_CACHE_DIR = path.join(EMBEDDINGS_DIR, "models");
|
|
9
|
+
const EMBEDDINGS_PATH = PATHS.embeddingsEntities;
|
|
10
|
+
const EMBEDDINGS_MANIFEST_PATH = PATHS.embeddingsManifest;
|
|
11
|
+
const MODEL_CACHE_DIR = PATHS.embeddingsModelCache;
|
|
12
|
+
const EMBEDDINGS_DIR = path.dirname(EMBEDDINGS_PATH);
|
|
18
13
|
|
|
19
14
|
const DEFAULT_MODEL_ID = "Xenova/all-MiniLM-L6-v2";
|
|
20
15
|
const DEFAULT_MAX_TEXT_CHARS = 7000;
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
3
|
import ryugraph, { type Connection, type PreparedStatement, type QueryResult, type RyuValue } from "ryugraph";
|
|
5
4
|
import { readJsonl, asString, asNumber, asBoolean } from "./jsonl.js";
|
|
5
|
+
import { CACHE_DIR, CONTEXT_DIR, DB_PATH } from "./paths.js";
|
|
6
6
|
import type { JsonObject } from "./types.js";
|
|
7
7
|
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
const REPO_ROOT = path.resolve(__dirname, "../..");
|
|
11
|
-
const CONTEXT_DIR = path.join(REPO_ROOT, ".context");
|
|
12
|
-
const CACHE_DIR = path.join(CONTEXT_DIR, "cache");
|
|
13
|
-
const DB_PATH = path.join(CONTEXT_DIR, "db", "graph.ryu");
|
|
14
8
|
const ONTOLOGY_PATH = path.join(CONTEXT_DIR, "ontology.cypher");
|
|
15
9
|
const BATCH_SIZE = 50;
|
|
16
10
|
|
|
@@ -21,9 +21,45 @@ function normalizeForWsl(rawPath: string): string {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const PROJECT_ROOT_OVERRIDE = process.env.CORTEX_PROJECT_ROOT?.trim();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
|
|
25
|
+
function hasContextConfig(candidate: string): boolean {
|
|
26
|
+
return fs.existsSync(path.join(candidate, ".context", "config.yaml"));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function resolveFrom(startDir: string): string | null {
|
|
30
|
+
let current = path.resolve(startDir);
|
|
31
|
+
while (true) {
|
|
32
|
+
if (hasContextConfig(current)) {
|
|
33
|
+
return current;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const parent = path.dirname(current);
|
|
37
|
+
if (parent === current) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
current = parent;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function resolveRepoRoot(): string {
|
|
45
|
+
const candidates = [
|
|
46
|
+
PROJECT_ROOT_OVERRIDE ? path.resolve(normalizeForWsl(PROJECT_ROOT_OVERRIDE)) : null,
|
|
47
|
+
process.cwd(),
|
|
48
|
+
__dirname,
|
|
49
|
+
process.env.INIT_CWD?.trim() ? path.resolve(normalizeForWsl(process.env.INIT_CWD.trim())) : null
|
|
50
|
+
].filter((value): value is string => Boolean(value));
|
|
51
|
+
|
|
52
|
+
for (const candidate of candidates) {
|
|
53
|
+
const resolved = resolveFrom(candidate);
|
|
54
|
+
if (resolved) {
|
|
55
|
+
return resolved;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return path.resolve(__dirname, "../../..");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const REPO_ROOT = resolveRepoRoot();
|
|
27
63
|
export const CONTEXT_DIR = path.join(REPO_ROOT, ".context");
|
|
28
64
|
export const CACHE_DIR = path.join(CONTEXT_DIR, "cache");
|
|
29
65
|
export const DB_PATH = path.join(CONTEXT_DIR, "db", "graph.ryu");
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, mkdirSync, realpathSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
|
|
9
|
+
test("paths resolve the project root from cwd without duplicating .context", () => {
|
|
10
|
+
const projectRoot = mkdtempSync(path.join(tmpdir(), "cortex-paths-"));
|
|
11
|
+
const contextDir = path.join(projectRoot, ".context");
|
|
12
|
+
const mcpDir = path.join(contextDir, "mcp");
|
|
13
|
+
const pathsModuleUrl = pathToFileURL(path.resolve("dist/paths.js")).href;
|
|
14
|
+
|
|
15
|
+
mkdirSync(mcpDir, { recursive: true });
|
|
16
|
+
writeFileSync(path.join(contextDir, "config.yaml"), "source_paths:\n - src\n");
|
|
17
|
+
|
|
18
|
+
const result = spawnSync(
|
|
19
|
+
process.execPath,
|
|
20
|
+
[
|
|
21
|
+
"--input-type=module",
|
|
22
|
+
"-e",
|
|
23
|
+
`import { REPO_ROOT, CONTEXT_DIR, CACHE_DIR } from ${JSON.stringify(pathsModuleUrl)}; console.log(JSON.stringify({ REPO_ROOT, CONTEXT_DIR, CACHE_DIR }));`
|
|
24
|
+
],
|
|
25
|
+
{
|
|
26
|
+
cwd: mcpDir,
|
|
27
|
+
encoding: "utf8"
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
assert.equal(result.status, 0, result.stderr);
|
|
32
|
+
|
|
33
|
+
const parsed = JSON.parse(result.stdout.trim());
|
|
34
|
+
const resolvedProjectRoot = realpathSync(projectRoot);
|
|
35
|
+
assert.equal(parsed.REPO_ROOT, resolvedProjectRoot);
|
|
36
|
+
assert.equal(parsed.CONTEXT_DIR, path.join(resolvedProjectRoot, ".context"));
|
|
37
|
+
assert.equal(parsed.CACHE_DIR, path.join(resolvedProjectRoot, ".context", "cache"));
|
|
38
|
+
});
|
|
@@ -12,4 +12,4 @@ fi
|
|
|
12
12
|
mkdir -p "$MCP_DIR/.npm-cache"
|
|
13
13
|
|
|
14
14
|
echo "[embed] generating embeddings via .context/mcp/embed"
|
|
15
|
-
NPM_CONFIG_CACHE="$MCP_DIR/.npm-cache" npm --prefix "$MCP_DIR" run embed --silent -- "$@"
|
|
15
|
+
CORTEX_PROJECT_ROOT="$REPO_ROOT" NPM_CONFIG_CACHE="$MCP_DIR/.npm-cache" npm --prefix "$MCP_DIR" run embed --silent -- "$@"
|
|
@@ -15,4 +15,4 @@ if [[ ! -d "$MCP_DIR/node_modules" ]]; then
|
|
|
15
15
|
exit 1
|
|
16
16
|
fi
|
|
17
17
|
|
|
18
|
-
NPM_CONFIG_CACHE="$MCP_DIR/.npm-cache" npm --prefix "$MCP_DIR" run graph:load -- "$@"
|
|
18
|
+
CORTEX_PROJECT_ROOT="$REPO_ROOT" NPM_CONFIG_CACHE="$MCP_DIR/.npm-cache" npm --prefix "$MCP_DIR" run graph:load -- "$@"
|