@softerist/heuristic-mcp 3.2.2 → 3.2.4
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/README.md +387 -376
- package/config.jsonc +800 -800
- package/features/ann-config.js +102 -110
- package/features/clear-cache.js +81 -84
- package/features/find-similar-code.js +265 -286
- package/features/hybrid-search.js +487 -536
- package/features/index-codebase.js +3139 -3270
- package/features/lifecycle.js +1041 -1063
- package/features/package-version.js +277 -291
- package/features/register.js +351 -370
- package/features/resources.js +115 -130
- package/features/set-workspace.js +214 -240
- package/index.js +742 -762
- package/lib/cache-ops.js +22 -22
- package/lib/cache-utils.js +465 -519
- package/lib/cache.js +1699 -1767
- package/lib/call-graph.js +396 -396
- package/lib/cli.js +232 -226
- package/lib/config.js +1483 -1495
- package/lib/constants.js +511 -492
- package/lib/embed-query-process.js +206 -212
- package/lib/embedding-process.js +434 -451
- package/lib/embedding-worker.js +862 -934
- package/lib/ignore-patterns.js +276 -316
- package/lib/json-worker.js +14 -14
- package/lib/json-writer.js +302 -310
- package/lib/logging.js +116 -127
- package/lib/memory-logger.js +13 -13
- package/lib/onnx-backend.js +188 -193
- package/lib/path-utils.js +18 -23
- package/lib/project-detector.js +82 -84
- package/lib/server-lifecycle.js +133 -145
- package/lib/settings-editor.js +738 -739
- package/lib/slice-normalize.js +25 -31
- package/lib/tokenizer.js +168 -203
- package/lib/utils.js +364 -409
- package/lib/vector-store-binary.js +811 -591
- package/lib/vector-store-sqlite.js +377 -414
- package/lib/workspace-env.js +32 -34
- package/mcp_config.json +9 -9
- package/package.json +86 -86
- package/scripts/clear-cache.js +20 -20
- package/scripts/download-model.js +43 -43
- package/scripts/mcp-launcher.js +49 -49
- package/scripts/postinstall.js +12 -12
- package/search-configs.js +36 -36
package/lib/workspace-env.js
CHANGED
|
@@ -5,9 +5,7 @@ import {
|
|
|
5
5
|
WORKSPACE_ENV_VARS,
|
|
6
6
|
} from './constants.js';
|
|
7
7
|
|
|
8
|
-
const EXCLUDED_DYNAMIC_WORKSPACE_ENV_KEYS = new Set([
|
|
9
|
-
'ANTIGRAVITY_EDITOR_APP_ROOT',
|
|
10
|
-
]);
|
|
8
|
+
const EXCLUDED_DYNAMIC_WORKSPACE_ENV_KEYS = new Set(['ANTIGRAVITY_EDITOR_APP_ROOT']);
|
|
11
9
|
|
|
12
10
|
function isTruthy(value) {
|
|
13
11
|
return /^(1|true|yes|on)$/i.test(String(value || '').trim());
|
|
@@ -21,20 +19,20 @@ export function isDynamicWorkspaceEnvEnabled(env = process.env, options = {}) {
|
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
export function scoreWorkspaceEnvKey(key) {
|
|
24
|
-
const upper = String(key || '').toUpperCase();
|
|
25
|
-
let score = 0;
|
|
26
|
-
if (upper.includes('WORKSPACE')) score += 8;
|
|
27
|
-
if (upper.includes('PROJECT')) score += 4;
|
|
28
|
-
if (upper.includes('ROOT')) score += 3;
|
|
29
|
-
if (upper.includes('CWD')) score += 2;
|
|
30
|
-
if (upper.includes('DIR')) score += 1;
|
|
31
|
-
return score;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function hasDynamicWorkspacePrefix(key) {
|
|
35
|
-
return DYNAMIC_WORKSPACE_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
36
|
-
}
|
|
37
|
-
|
|
22
|
+
const upper = String(key || '').toUpperCase();
|
|
23
|
+
let score = 0;
|
|
24
|
+
if (upper.includes('WORKSPACE')) score += 8;
|
|
25
|
+
if (upper.includes('PROJECT')) score += 4;
|
|
26
|
+
if (upper.includes('ROOT')) score += 3;
|
|
27
|
+
if (upper.includes('CWD')) score += 2;
|
|
28
|
+
if (upper.includes('DIR')) score += 1;
|
|
29
|
+
return score;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function hasDynamicWorkspacePrefix(key) {
|
|
33
|
+
return DYNAMIC_WORKSPACE_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
34
|
+
}
|
|
35
|
+
|
|
38
36
|
export function getDynamicWorkspaceEnvKeys(env = process.env, options = {}) {
|
|
39
37
|
if (!isDynamicWorkspaceEnvEnabled(env, options)) {
|
|
40
38
|
return [];
|
|
@@ -43,27 +41,27 @@ export function getDynamicWorkspaceEnvKeys(env = process.env, options = {}) {
|
|
|
43
41
|
return Object.keys(env)
|
|
44
42
|
.filter((key) => !EXCLUDED_DYNAMIC_WORKSPACE_ENV_KEYS.has(String(key || '').toUpperCase()))
|
|
45
43
|
.filter((key) => !WORKSPACE_ENV_VARS.includes(key))
|
|
46
|
-
.filter((key) => {
|
|
47
|
-
const providerSpecific =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
.filter((key) => {
|
|
45
|
+
const providerSpecific =
|
|
46
|
+
hasDynamicWorkspacePrefix(key) && WORKSPACE_ENV_KEY_PATTERN.test(key);
|
|
47
|
+
const genericWorkspace = WORKSPACE_ENV_GENERIC_DISCOVERY_PATTERN.test(key);
|
|
48
|
+
return providerSpecific || genericWorkspace;
|
|
49
|
+
})
|
|
50
|
+
.sort((a, b) => scoreWorkspaceEnvKey(b) - scoreWorkspaceEnvKey(a));
|
|
51
|
+
}
|
|
52
|
+
|
|
54
53
|
export function getWorkspaceEnvKeys(env = process.env, options = {}) {
|
|
55
54
|
return [...WORKSPACE_ENV_VARS, ...getDynamicWorkspaceEnvKeys(env, options)];
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
|
|
59
57
|
export function getWorkspaceEnvDiagnosticKeys(env = process.env, options = {}) {
|
|
60
58
|
const prioritized = getWorkspaceEnvKeys(env, options);
|
|
61
59
|
const prioritizedSet = new Set(prioritized);
|
|
62
|
-
|
|
63
|
-
const extraKeys = Object.keys(env)
|
|
64
|
-
.filter((key) => !prioritizedSet.has(key))
|
|
65
|
-
.filter((key) => WORKSPACE_ENV_KEY_PATTERN.test(key))
|
|
66
|
-
.sort((a, b) => scoreWorkspaceEnvKey(b) - scoreWorkspaceEnvKey(a));
|
|
67
|
-
|
|
68
|
-
return [...prioritized, ...extraKeys];
|
|
69
|
-
}
|
|
60
|
+
|
|
61
|
+
const extraKeys = Object.keys(env)
|
|
62
|
+
.filter((key) => !prioritizedSet.has(key))
|
|
63
|
+
.filter((key) => WORKSPACE_ENV_KEY_PATTERN.test(key))
|
|
64
|
+
.sort((a, b) => scoreWorkspaceEnvKey(b) - scoreWorkspaceEnvKey(a));
|
|
65
|
+
|
|
66
|
+
return [...prioritized, ...extraKeys];
|
|
67
|
+
}
|
package/mcp_config.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mcpServers": {
|
|
3
|
-
"heuristic-mcp": {
|
|
4
|
-
"command": "node",
|
|
5
|
-
"args": ["scripts\\mcp-launcher.js"],
|
|
6
|
-
"disabled": false
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"heuristic-mcp": {
|
|
4
|
+
"command": "node",
|
|
5
|
+
"args": ["scripts\\mcp-launcher.js"],
|
|
6
|
+
"disabled": false
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
}
|
package/package.json
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@softerist/heuristic-mcp",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"description": "An enhanced MCP server providing intelligent semantic code search with find-similar-code, recency ranking, and improved chunking. Fork of smart-coding-mcp.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"heuristic-mcp": "index.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"index.js",
|
|
12
|
-
"config.jsonc",
|
|
13
|
-
"mcp_config.json",
|
|
14
|
-
"search-configs.js",
|
|
15
|
-
"lib/",
|
|
16
|
-
"features/",
|
|
17
|
-
"scripts/",
|
|
18
|
-
"README.md",
|
|
19
|
-
"LICENSE"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"start": "node --expose-gc index.js",
|
|
23
|
-
"dev": "node --expose-gc --watch index.js",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"test:watch": "vitest",
|
|
26
|
-
"clean": "node scripts/clear-cache.js",
|
|
27
|
-
"lint": "eslint .",
|
|
28
|
-
"format": "prettier --write .",
|
|
29
|
-
"postinstall": "node scripts/postinstall.js && node scripts/download-model.js"
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"mcp",
|
|
33
|
-
"semantic-search",
|
|
34
|
-
"code-search",
|
|
35
|
-
"embeddings",
|
|
36
|
-
"ai",
|
|
37
|
-
"model-context-protocol",
|
|
38
|
-
"hybrid-search",
|
|
39
|
-
"code-intelligence",
|
|
40
|
-
"cursor",
|
|
41
|
-
"vscode",
|
|
42
|
-
"claude",
|
|
43
|
-
"codex",
|
|
44
|
-
"openai",
|
|
45
|
-
"gemini",
|
|
46
|
-
"anthropic",
|
|
47
|
-
"antigravity",
|
|
48
|
-
"heuristic"
|
|
49
|
-
],
|
|
50
|
-
"author": {
|
|
51
|
-
"name": "Softerist",
|
|
52
|
-
"url": "https://github.com/softerist"
|
|
53
|
-
},
|
|
54
|
-
"repository": {
|
|
55
|
-
"type": "git",
|
|
56
|
-
"url": "git+https://github.com/softerist/heuristic-mcp.git"
|
|
57
|
-
},
|
|
58
|
-
"homepage": "https://github.com/softerist/heuristic-mcp#readme",
|
|
59
|
-
"license": "MIT",
|
|
60
|
-
"dependencies": {
|
|
61
|
-
"@huggingface/transformers": "^3.8.1",
|
|
62
|
-
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
63
|
-
"better-sqlite3": "^12.6.2",
|
|
64
|
-
"chokidar": "^3.5.3",
|
|
65
|
-
"fdir": "^6.5.0",
|
|
66
|
-
"ignore": "^7.0.5",
|
|
67
|
-
"punycode": "^2.3.1"
|
|
68
|
-
},
|
|
69
|
-
"optionalDependencies": {
|
|
70
|
-
"hnswlib-node": "^3.0.0"
|
|
71
|
-
},
|
|
72
|
-
"engines": {
|
|
73
|
-
"node": ">=18.0.0"
|
|
74
|
-
},
|
|
75
|
-
"overrides": {
|
|
76
|
-
"punycode": "^2.3.1"
|
|
77
|
-
},
|
|
78
|
-
"devDependencies": {
|
|
79
|
-
"@eslint/js": "^9.39.2",
|
|
80
|
-
"@vitest/coverage-v8": "^4.0.18",
|
|
81
|
-
"eslint": "^9.39.2",
|
|
82
|
-
"globals": "^17.1.0",
|
|
83
|
-
"prettier": "^3.8.1",
|
|
84
|
-
"vitest": "^4.0.16"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@softerist/heuristic-mcp",
|
|
3
|
+
"version": "3.2.4",
|
|
4
|
+
"description": "An enhanced MCP server providing intelligent semantic code search with find-similar-code, recency ranking, and improved chunking. Fork of smart-coding-mcp.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"heuristic-mcp": "index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"config.jsonc",
|
|
13
|
+
"mcp_config.json",
|
|
14
|
+
"search-configs.js",
|
|
15
|
+
"lib/",
|
|
16
|
+
"features/",
|
|
17
|
+
"scripts/",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"start": "node --expose-gc index.js",
|
|
23
|
+
"dev": "node --expose-gc --watch index.js",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"clean": "node scripts/clear-cache.js",
|
|
27
|
+
"lint": "eslint .",
|
|
28
|
+
"format": "prettier --write .",
|
|
29
|
+
"postinstall": "node scripts/postinstall.js && node scripts/download-model.js"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"mcp",
|
|
33
|
+
"semantic-search",
|
|
34
|
+
"code-search",
|
|
35
|
+
"embeddings",
|
|
36
|
+
"ai",
|
|
37
|
+
"model-context-protocol",
|
|
38
|
+
"hybrid-search",
|
|
39
|
+
"code-intelligence",
|
|
40
|
+
"cursor",
|
|
41
|
+
"vscode",
|
|
42
|
+
"claude",
|
|
43
|
+
"codex",
|
|
44
|
+
"openai",
|
|
45
|
+
"gemini",
|
|
46
|
+
"anthropic",
|
|
47
|
+
"antigravity",
|
|
48
|
+
"heuristic"
|
|
49
|
+
],
|
|
50
|
+
"author": {
|
|
51
|
+
"name": "Softerist",
|
|
52
|
+
"url": "https://github.com/softerist"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/softerist/heuristic-mcp.git"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://github.com/softerist/heuristic-mcp#readme",
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@huggingface/transformers": "^3.8.1",
|
|
62
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
63
|
+
"better-sqlite3": "^12.6.2",
|
|
64
|
+
"chokidar": "^3.5.3",
|
|
65
|
+
"fdir": "^6.5.0",
|
|
66
|
+
"ignore": "^7.0.5",
|
|
67
|
+
"punycode": "^2.3.1"
|
|
68
|
+
},
|
|
69
|
+
"optionalDependencies": {
|
|
70
|
+
"hnswlib-node": "^3.0.0"
|
|
71
|
+
},
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=18.0.0"
|
|
74
|
+
},
|
|
75
|
+
"overrides": {
|
|
76
|
+
"punycode": "^2.3.1"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@eslint/js": "^9.39.2",
|
|
80
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
81
|
+
"eslint": "^9.39.2",
|
|
82
|
+
"globals": "^17.1.0",
|
|
83
|
+
"prettier": "^3.8.1",
|
|
84
|
+
"vitest": "^4.0.16"
|
|
85
|
+
}
|
|
86
|
+
}
|
package/scripts/clear-cache.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
|
-
import { loadConfig } from '../lib/config.js';
|
|
4
|
-
|
|
5
|
-
async function clearCache() {
|
|
6
|
-
try {
|
|
7
|
-
const config = await loadConfig(process.cwd());
|
|
8
|
-
const cacheDir = config.cacheDirectory;
|
|
9
|
-
|
|
10
|
-
// Remove cache directory
|
|
11
|
-
await fs.rm(cacheDir, { recursive: true, force: true });
|
|
12
|
-
console.info(`Cache cleared successfully: ${cacheDir}`);
|
|
13
|
-
console.info('Next startup will perform a full reindex.');
|
|
14
|
-
} catch (error) {
|
|
15
|
-
console.error(`Error clearing cache: ${error.message}`);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
clearCache();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import { loadConfig } from '../lib/config.js';
|
|
4
|
+
|
|
5
|
+
async function clearCache() {
|
|
6
|
+
try {
|
|
7
|
+
const config = await loadConfig(process.cwd());
|
|
8
|
+
const cacheDir = config.cacheDirectory;
|
|
9
|
+
|
|
10
|
+
// Remove cache directory
|
|
11
|
+
await fs.rm(cacheDir, { recursive: true, force: true });
|
|
12
|
+
console.info(`Cache cleared successfully: ${cacheDir}`);
|
|
13
|
+
console.info('Next startup will perform a full reindex.');
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error(`Error clearing cache: ${error.message}`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
clearCache();
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
|
|
3
|
-
import { getGlobalCacheDir } from '../lib/config.js';
|
|
4
|
-
|
|
5
|
-
async function downloadModel() {
|
|
6
|
-
const globalCacheDir = path.join(getGlobalCacheDir(), 'xenova');
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
const transformers = await import('@huggingface/transformers');
|
|
10
|
-
const { pipeline, env } = transformers;
|
|
11
|
-
|
|
12
|
-
// Force cache directory to global location
|
|
13
|
-
env.cacheDir = globalCacheDir;
|
|
14
|
-
|
|
15
|
-
console.info(`[Model Setup] Pre-caching model to: ${globalCacheDir}`);
|
|
16
|
-
// Check if network is available by pinging HF (simple check)
|
|
17
|
-
// Actually, pipeline() will fail fast if network is down
|
|
18
|
-
console.info(`[Model Setup] Downloading 'jinaai/jina-embeddings-v2-base-code'...`);
|
|
19
|
-
|
|
20
|
-
// This will download the model to the cache directory
|
|
21
|
-
await pipeline('feature-extraction', 'jinaai/jina-embeddings-v2-base-code');
|
|
22
|
-
|
|
23
|
-
console.info(`[Model Setup] ✅ Model cached successfully!`);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
if (error && error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
26
|
-
console.warn(
|
|
27
|
-
'[Model Setup] ⚠️ Transformers not available yet; skipping model pre-download.'
|
|
28
|
-
);
|
|
29
|
-
console.warn(
|
|
30
|
-
'[Model Setup] This is okay! The server will attempt to download it when started.'
|
|
31
|
-
);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
console.warn(`[Model Setup] ⚠️ Constructive warning: Failed to pre-download model.`);
|
|
35
|
-
console.warn(
|
|
36
|
-
'[Model Setup] This is okay! The server will attempt to download it when started.'
|
|
37
|
-
);
|
|
38
|
-
console.warn(`[Model Setup] Error details: ${error.message}`);
|
|
39
|
-
// Don't fail the install, just warn
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
downloadModel();
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { getGlobalCacheDir } from '../lib/config.js';
|
|
4
|
+
|
|
5
|
+
async function downloadModel() {
|
|
6
|
+
const globalCacheDir = path.join(getGlobalCacheDir(), 'xenova');
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const transformers = await import('@huggingface/transformers');
|
|
10
|
+
const { pipeline, env } = transformers;
|
|
11
|
+
|
|
12
|
+
// Force cache directory to global location
|
|
13
|
+
env.cacheDir = globalCacheDir;
|
|
14
|
+
|
|
15
|
+
console.info(`[Model Setup] Pre-caching model to: ${globalCacheDir}`);
|
|
16
|
+
// Check if network is available by pinging HF (simple check)
|
|
17
|
+
// Actually, pipeline() will fail fast if network is down
|
|
18
|
+
console.info(`[Model Setup] Downloading 'jinaai/jina-embeddings-v2-base-code'...`);
|
|
19
|
+
|
|
20
|
+
// This will download the model to the cache directory
|
|
21
|
+
await pipeline('feature-extraction', 'jinaai/jina-embeddings-v2-base-code');
|
|
22
|
+
|
|
23
|
+
console.info(`[Model Setup] ✅ Model cached successfully!`);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error && error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
26
|
+
console.warn(
|
|
27
|
+
'[Model Setup] ⚠️ Transformers not available yet; skipping model pre-download.'
|
|
28
|
+
);
|
|
29
|
+
console.warn(
|
|
30
|
+
'[Model Setup] This is okay! The server will attempt to download it when started.'
|
|
31
|
+
);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.warn(`[Model Setup] ⚠️ Constructive warning: Failed to pre-download model.`);
|
|
35
|
+
console.warn(
|
|
36
|
+
'[Model Setup] This is okay! The server will attempt to download it when started.'
|
|
37
|
+
);
|
|
38
|
+
console.warn(`[Model Setup] Error details: ${error.message}`);
|
|
39
|
+
// Don't fail the install, just warn
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
downloadModel();
|
package/scripts/mcp-launcher.js
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { spawn } from 'node:child_process';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { getWorkspaceEnvKeys } from '../lib/workspace-env.js';
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const repoRoot = path.resolve(__dirname, '..');
|
|
8
|
-
const indexPath = path.join(repoRoot, 'index.js');
|
|
9
|
-
|
|
10
|
-
let workspace;
|
|
11
|
-
const passthrough = [];
|
|
12
|
-
|
|
13
|
-
function readWorkspaceFromEnv() {
|
|
14
|
-
for (const key of getWorkspaceEnvKeys()) {
|
|
15
|
-
const value = process.env[key];
|
|
16
|
-
if (!value || value.includes('${')) continue;
|
|
17
|
-
return value;
|
|
18
|
-
}
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
for (let i = 2; i < process.argv.length; i += 1) {
|
|
23
|
-
const arg = process.argv[i];
|
|
24
|
-
if (arg === '--workspace' && i + 1 < process.argv.length) {
|
|
25
|
-
workspace = process.argv[i + 1];
|
|
26
|
-
i += 1;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
passthrough.push(arg);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (!workspace) {
|
|
33
|
-
workspace = readWorkspaceFromEnv();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!workspace) {
|
|
37
|
-
workspace = process.cwd();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const args = ['--expose-gc', indexPath, '--workspace', workspace, ...passthrough];
|
|
41
|
-
const child = spawn(process.execPath, args, { stdio: 'inherit' });
|
|
42
|
-
|
|
43
|
-
child.on('exit', (code, signal) => {
|
|
44
|
-
if (signal) {
|
|
45
|
-
process.kill(process.pid, signal);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
process.exit(code ?? 1);
|
|
49
|
-
});
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { getWorkspaceEnvKeys } from '../lib/workspace-env.js';
|
|
5
|
+
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
8
|
+
const indexPath = path.join(repoRoot, 'index.js');
|
|
9
|
+
|
|
10
|
+
let workspace;
|
|
11
|
+
const passthrough = [];
|
|
12
|
+
|
|
13
|
+
function readWorkspaceFromEnv() {
|
|
14
|
+
for (const key of getWorkspaceEnvKeys()) {
|
|
15
|
+
const value = process.env[key];
|
|
16
|
+
if (!value || value.includes('${')) continue;
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (let i = 2; i < process.argv.length; i += 1) {
|
|
23
|
+
const arg = process.argv[i];
|
|
24
|
+
if (arg === '--workspace' && i + 1 < process.argv.length) {
|
|
25
|
+
workspace = process.argv[i + 1];
|
|
26
|
+
i += 1;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
passthrough.push(arg);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!workspace) {
|
|
33
|
+
workspace = readWorkspaceFromEnv();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!workspace) {
|
|
37
|
+
workspace = process.cwd();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const args = ['--expose-gc', indexPath, '--workspace', workspace, ...passthrough];
|
|
41
|
+
const child = spawn(process.execPath, args, { stdio: 'inherit' });
|
|
42
|
+
|
|
43
|
+
child.on('exit', (code, signal) => {
|
|
44
|
+
if (signal) {
|
|
45
|
+
process.kill(process.pid, signal);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
process.exit(code ?? 1);
|
|
49
|
+
});
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { register } from '../features/register.js';
|
|
2
|
-
|
|
3
|
-
// Run the registration process - MUST await to ensure file writes complete
|
|
4
|
-
console.info('[PostInstall] Running Heuristic MCP registration...');
|
|
5
|
-
|
|
6
|
-
try {
|
|
7
|
-
await register();
|
|
8
|
-
console.info('[PostInstall] Registration complete.');
|
|
9
|
-
} catch (err) {
|
|
10
|
-
console.error('[PostInstall] Registration failed:', err.message);
|
|
11
|
-
// Don't fail the install if registration fails, just warn
|
|
12
|
-
}
|
|
1
|
+
import { register } from '../features/register.js';
|
|
2
|
+
|
|
3
|
+
// Run the registration process - MUST await to ensure file writes complete
|
|
4
|
+
console.info('[PostInstall] Running Heuristic MCP registration...');
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
await register();
|
|
8
|
+
console.info('[PostInstall] Registration complete.');
|
|
9
|
+
} catch (err) {
|
|
10
|
+
console.error('[PostInstall] Registration failed:', err.message);
|
|
11
|
+
// Don't fail the install if registration fails, just warn
|
|
12
|
+
}
|
package/search-configs.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { loadConfig } from './lib/config.js';
|
|
2
|
-
import { EmbeddingsCache } from './lib/cache.js';
|
|
3
|
-
import { HybridSearch } from './features/hybrid-search.js';
|
|
4
|
-
import { pipeline, env } from '@huggingface/transformers';
|
|
5
|
-
|
|
6
|
-
// Force same thread config as server
|
|
7
|
-
if (env?.backends?.onnx) {
|
|
8
|
-
env.backends.onnx.numThreads = 2;
|
|
9
|
-
if (env.backends.onnx.wasm) {
|
|
10
|
-
env.backends.onnx.wasm.numThreads = 2;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function searchConfigs() {
|
|
15
|
-
const config = await loadConfig(process.cwd());
|
|
16
|
-
const cache = new EmbeddingsCache(config);
|
|
17
|
-
await cache.load();
|
|
18
|
-
|
|
19
|
-
const embedder = async (text) => {
|
|
20
|
-
const pipe = await pipeline('feature-extraction', config.embeddingModel, {
|
|
21
|
-
session_options: { numThreads: 2 },
|
|
22
|
-
dtype: 'fp32',
|
|
23
|
-
});
|
|
24
|
-
return pipe(text, { pooling: 'mean', normalize: true });
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const searcher = new HybridSearch(embedder, cache, config);
|
|
28
|
-
const { results } = await searcher.search('configuration files, config, settings');
|
|
29
|
-
|
|
30
|
-
console.info(JSON.stringify(results, null, 2));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
searchConfigs().catch((err) => {
|
|
34
|
-
console.error(err);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
});
|
|
1
|
+
import { loadConfig } from './lib/config.js';
|
|
2
|
+
import { EmbeddingsCache } from './lib/cache.js';
|
|
3
|
+
import { HybridSearch } from './features/hybrid-search.js';
|
|
4
|
+
import { pipeline, env } from '@huggingface/transformers';
|
|
5
|
+
|
|
6
|
+
// Force same thread config as server
|
|
7
|
+
if (env?.backends?.onnx) {
|
|
8
|
+
env.backends.onnx.numThreads = 2;
|
|
9
|
+
if (env.backends.onnx.wasm) {
|
|
10
|
+
env.backends.onnx.wasm.numThreads = 2;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function searchConfigs() {
|
|
15
|
+
const config = await loadConfig(process.cwd());
|
|
16
|
+
const cache = new EmbeddingsCache(config);
|
|
17
|
+
await cache.load();
|
|
18
|
+
|
|
19
|
+
const embedder = async (text) => {
|
|
20
|
+
const pipe = await pipeline('feature-extraction', config.embeddingModel, {
|
|
21
|
+
session_options: { numThreads: 2 },
|
|
22
|
+
dtype: 'fp32',
|
|
23
|
+
});
|
|
24
|
+
return pipe(text, { pooling: 'mean', normalize: true });
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const searcher = new HybridSearch(embedder, cache, config);
|
|
28
|
+
const { results } = await searcher.search('configuration files, config, settings');
|
|
29
|
+
|
|
30
|
+
console.info(JSON.stringify(results, null, 2));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
searchConfigs().catch((err) => {
|
|
34
|
+
console.error(err);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|