@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.
Files changed (46) hide show
  1. package/README.md +387 -376
  2. package/config.jsonc +800 -800
  3. package/features/ann-config.js +102 -110
  4. package/features/clear-cache.js +81 -84
  5. package/features/find-similar-code.js +265 -286
  6. package/features/hybrid-search.js +487 -536
  7. package/features/index-codebase.js +3139 -3270
  8. package/features/lifecycle.js +1041 -1063
  9. package/features/package-version.js +277 -291
  10. package/features/register.js +351 -370
  11. package/features/resources.js +115 -130
  12. package/features/set-workspace.js +214 -240
  13. package/index.js +742 -762
  14. package/lib/cache-ops.js +22 -22
  15. package/lib/cache-utils.js +465 -519
  16. package/lib/cache.js +1699 -1767
  17. package/lib/call-graph.js +396 -396
  18. package/lib/cli.js +232 -226
  19. package/lib/config.js +1483 -1495
  20. package/lib/constants.js +511 -492
  21. package/lib/embed-query-process.js +206 -212
  22. package/lib/embedding-process.js +434 -451
  23. package/lib/embedding-worker.js +862 -934
  24. package/lib/ignore-patterns.js +276 -316
  25. package/lib/json-worker.js +14 -14
  26. package/lib/json-writer.js +302 -310
  27. package/lib/logging.js +116 -127
  28. package/lib/memory-logger.js +13 -13
  29. package/lib/onnx-backend.js +188 -193
  30. package/lib/path-utils.js +18 -23
  31. package/lib/project-detector.js +82 -84
  32. package/lib/server-lifecycle.js +133 -145
  33. package/lib/settings-editor.js +738 -739
  34. package/lib/slice-normalize.js +25 -31
  35. package/lib/tokenizer.js +168 -203
  36. package/lib/utils.js +364 -409
  37. package/lib/vector-store-binary.js +811 -591
  38. package/lib/vector-store-sqlite.js +377 -414
  39. package/lib/workspace-env.js +32 -34
  40. package/mcp_config.json +9 -9
  41. package/package.json +86 -86
  42. package/scripts/clear-cache.js +20 -20
  43. package/scripts/download-model.js +43 -43
  44. package/scripts/mcp-launcher.js +49 -49
  45. package/scripts/postinstall.js +12 -12
  46. package/search-configs.js +36 -36
package/lib/cli.js CHANGED
@@ -1,109 +1,115 @@
1
- export const DEFAULT_LOG_TAIL_LINES = 200;
2
- const FLAG_ARGS_WITH_VALUES = new Set(['--tail', '--workspace', '--start', '--register', '--clear']);
3
- const COMMAND_ALIASES = Object.freeze({
4
- status: '--status',
5
- stat: '--status',
6
- log: '--logs',
7
- logs: '--logs',
8
- start: '--start',
9
- stop: '--stop',
10
- cache: '--cache',
11
- 'clear-cache': '--clear-cache',
12
- clearcache: '--clear-cache',
1
+ export const DEFAULT_LOG_TAIL_LINES = 200;
2
+ const FLAG_ARGS_WITH_VALUES = new Set([
3
+ '--tail',
4
+ '--workspace',
5
+ '--start',
6
+ '--register',
7
+ '--clear',
8
+ ]);
9
+ const COMMAND_ALIASES = Object.freeze({
10
+ status: '--status',
11
+ stat: '--status',
12
+ log: '--logs',
13
+ logs: '--logs',
14
+ start: '--start',
15
+ stop: '--stop',
16
+ cache: '--cache',
17
+ 'clear-cache': '--clear-cache',
18
+ clearcache: '--clear-cache',
13
19
  clear: '--clear',
14
20
  clean: '--clear',
15
21
  mem: '--mem',
16
- memory: '--mem',
17
- version: '--version',
18
- help: '--help',
19
- register: '--register',
20
- });
21
- const FLAG_ALIASES = Object.freeze({
22
- '--log': '--logs',
23
- });
24
-
25
- export function printHelp(defaultTailLines = DEFAULT_LOG_TAIL_LINES) {
26
- console.info(`Heuristic MCP Server
27
-
28
- Usage:
29
- heuristic-mcp [options]
30
- heuristic-mcp <command> [args]
31
-
32
- Options:
33
- --cache Show cache status and cleanup recommendations (dry-run)
34
- --cache --clean Remove stale cache directories (performs cleanup)
35
- --status Show server status and cache summary
36
- --clear <cache_id> Remove a specific cache by ID
37
- --clear-cache Remove cache for current workspace (and stale global caches)
38
- --logs Tail server logs (defaults to last 200 lines, follows)
39
- --mem Show last memory snapshot from logs (requires verbose logging)
40
- --tail <lines> Lines to show with --logs (default: ${defaultTailLines})
41
- --no-follow Do not follow log output with --logs
42
- --start [ide] Register + enable in IDE config (antigravity|codex|cursor|vscode|windsurf|warp|"Claude Desktop")
43
- --stop Stop running server instances
44
- --workspace <path> Workspace path (used by IDE launch / log viewer)
45
- --version, -v Show version
46
- --help, -h Show this help
47
-
48
- `);
49
- }
50
-
51
- export function normalizeCliArgs(rawArgs = []) {
52
- const normalized = [];
53
- let expectsValue = false;
54
-
55
- for (const token of rawArgs) {
56
- if (expectsValue) {
57
- normalized.push(token);
58
- expectsValue = false;
59
- continue;
60
- }
61
-
62
- if (token.startsWith('--')) {
63
- const eqIdx = token.indexOf('=');
64
- if (eqIdx !== -1) {
65
- const flagPart = token.slice(0, eqIdx);
66
- const valuePart = token.slice(eqIdx + 1);
67
- const mappedFlag = FLAG_ALIASES[flagPart] || flagPart;
68
- normalized.push(`${mappedFlag}=${valuePart}`);
69
- continue;
70
- }
71
-
72
- const mappedFlag = FLAG_ALIASES[token] || token;
73
- normalized.push(mappedFlag);
74
- if (FLAG_ARGS_WITH_VALUES.has(mappedFlag)) {
75
- expectsValue = true;
76
- }
77
- continue;
78
- }
79
-
80
- if (token.startsWith('-')) {
81
- normalized.push(token);
82
- continue;
83
- }
84
-
85
- const mappedCommand = COMMAND_ALIASES[token.toLowerCase()];
86
- if (mappedCommand) {
87
- normalized.push(mappedCommand);
88
- if (FLAG_ARGS_WITH_VALUES.has(mappedCommand)) {
89
- expectsValue = true;
90
- }
91
- continue;
92
- }
93
-
94
- normalized.push(token);
95
- }
96
-
97
- return normalized;
98
- }
99
-
100
- export function shouldDefaultToHelp(
101
- args,
102
- runtime = { stdinIsTTY: process.stdin.isTTY, stdoutIsTTY: process.stdout.isTTY }
103
- ) {
104
- return args.length === 0 && Boolean(runtime.stdinIsTTY && runtime.stdoutIsTTY);
105
- }
106
-
22
+ memory: '--mem',
23
+ version: '--version',
24
+ help: '--help',
25
+ register: '--register',
26
+ });
27
+ const FLAG_ALIASES = Object.freeze({
28
+ '--log': '--logs',
29
+ });
30
+
31
+ export function printHelp(defaultTailLines = DEFAULT_LOG_TAIL_LINES) {
32
+ console.info(`Heuristic MCP Server
33
+
34
+ Usage:
35
+ heuristic-mcp [options]
36
+ heuristic-mcp <command> [args]
37
+
38
+ Options:
39
+ --cache Show cache status and cleanup recommendations (dry-run)
40
+ --cache --clean Remove stale cache directories (performs cleanup)
41
+ --status Show server status and cache summary
42
+ --clear <cache_id> Remove a specific cache by ID
43
+ --clear-cache Remove cache for current workspace (and stale global caches)
44
+ --logs Tail server logs (defaults to last 200 lines, follows)
45
+ --mem Show last memory snapshot from logs (requires verbose logging)
46
+ --tail <lines> Lines to show with --logs (default: ${defaultTailLines})
47
+ --no-follow Do not follow log output with --logs
48
+ --start [ide] Register + enable in IDE config (antigravity|codex|cursor|vscode|windsurf|warp|"Claude Desktop")
49
+ --stop Stop running server instances
50
+ --workspace <path> Workspace path (used by IDE launch / log viewer)
51
+ --version, -v Show version
52
+ --help, -h Show this help
53
+
54
+ `);
55
+ }
56
+
57
+ export function normalizeCliArgs(rawArgs = []) {
58
+ const normalized = [];
59
+ let expectsValue = false;
60
+
61
+ for (const token of rawArgs) {
62
+ if (expectsValue) {
63
+ normalized.push(token);
64
+ expectsValue = false;
65
+ continue;
66
+ }
67
+
68
+ if (token.startsWith('--')) {
69
+ const eqIdx = token.indexOf('=');
70
+ if (eqIdx !== -1) {
71
+ const flagPart = token.slice(0, eqIdx);
72
+ const valuePart = token.slice(eqIdx + 1);
73
+ const mappedFlag = FLAG_ALIASES[flagPart] || flagPart;
74
+ normalized.push(`${mappedFlag}=${valuePart}`);
75
+ continue;
76
+ }
77
+
78
+ const mappedFlag = FLAG_ALIASES[token] || token;
79
+ normalized.push(mappedFlag);
80
+ if (FLAG_ARGS_WITH_VALUES.has(mappedFlag)) {
81
+ expectsValue = true;
82
+ }
83
+ continue;
84
+ }
85
+
86
+ if (token.startsWith('-')) {
87
+ normalized.push(token);
88
+ continue;
89
+ }
90
+
91
+ const mappedCommand = COMMAND_ALIASES[token.toLowerCase()];
92
+ if (mappedCommand) {
93
+ normalized.push(mappedCommand);
94
+ if (FLAG_ARGS_WITH_VALUES.has(mappedCommand)) {
95
+ expectsValue = true;
96
+ }
97
+ continue;
98
+ }
99
+
100
+ normalized.push(token);
101
+ }
102
+
103
+ return normalized;
104
+ }
105
+
106
+ export function shouldDefaultToHelp(
107
+ args,
108
+ runtime = { stdinIsTTY: process.stdin.isTTY, stdoutIsTTY: process.stdout.isTTY }
109
+ ) {
110
+ return args.length === 0 && Boolean(runtime.stdinIsTTY && runtime.stdoutIsTTY);
111
+ }
112
+
107
113
  export function parseWorkspaceDir(args) {
108
114
  const isUnexpandedWorkspaceValue = (value) =>
109
115
  value.includes('${') || /\{\{.+\}\}/.test(value) || /%[A-Za-z_][A-Za-z0-9_]*%/.test(value);
@@ -134,126 +140,126 @@ export function parseWorkspaceDir(args) {
134
140
 
135
141
  return null;
136
142
  }
137
-
138
- export function collectUnknownFlags(rawArgs, knownFlags, flagsWithValue) {
139
- const unknownFlags = [];
140
- for (let i = 0; i < rawArgs.length; i += 1) {
141
- const arg = rawArgs[i];
142
- if (flagsWithValue.has(arg)) {
143
- if (arg.includes('=')) continue;
144
- const next = rawArgs[i + 1];
145
- if (next && !next.startsWith('-')) {
146
- i += 1;
147
- }
148
- continue;
149
- }
150
- if (arg.startsWith('-') && !knownFlags.has(arg) && !arg.startsWith('--workspace=')) {
151
- unknownFlags.push(arg);
152
- }
153
- }
154
- return unknownFlags;
155
- }
156
-
157
- export function parseArgs(
158
- argv = process.argv,
159
- runtime = { stdinIsTTY: process.stdin.isTTY, stdoutIsTTY: process.stdout.isTTY }
160
- ) {
161
- const args = normalizeCliArgs(argv.slice(2));
162
- const rawArgs = [...args];
163
-
164
- const wantsVersion = args.includes('--version') || args.includes('-v');
165
- const wantsHelp = args.includes('--help') || args.includes('-h') || shouldDefaultToHelp(args, runtime);
166
- const wantsCache = args.includes('--cache');
167
- const wantsClean = args.includes('--clean');
168
- const wantsStatus = args.includes('--status');
169
- const wantsClearCache = args.includes('--clear-cache');
170
- const wantsLogs = args.includes('--logs');
171
- const wantsMem = args.includes('--mem');
172
- const wantsRegister = args.includes('--register');
173
- const wantsStart = args.includes('--start') || wantsRegister;
174
- const wantsStop = args.includes('--stop');
175
- const wantsFix = args.includes('--fix');
176
- const wantsNoFollow = args.includes('--no-follow');
177
-
178
- const isServerMode = !(
179
- wantsCache ||
180
- wantsStatus ||
181
- wantsClearCache ||
182
- wantsLogs ||
183
- wantsMem ||
184
- wantsStart ||
185
- wantsStop ||
186
- wantsHelp ||
187
- wantsVersion
188
- );
189
-
190
- const workspaceDir = parseWorkspaceDir(args);
191
-
192
- let tailLines = DEFAULT_LOG_TAIL_LINES;
193
- if (wantsLogs) {
194
- const tailIndex = args.indexOf('--tail');
195
- if (tailIndex !== -1 && args[tailIndex + 1]) {
196
- const parsed = parseInt(args[tailIndex + 1], 10);
197
- if (!isNaN(parsed) && parsed > 0) {
198
- tailLines = parsed;
199
- }
200
- }
201
- }
202
-
203
- let startFilter = null;
204
- if (wantsStart) {
205
- const getFilter = (flag) => {
206
- const filterIndex = args.indexOf(flag);
207
- if (filterIndex === -1) return null;
208
- const value = args[filterIndex + 1];
209
- return value && !value.startsWith('-') ? value : null;
210
- };
211
- startFilter = getFilter('--start') ?? getFilter('--register');
212
- }
213
-
214
- const knownFlags = new Set([
215
- '--cache',
216
- '--clean',
217
- '--status',
218
- '--clear',
219
- '--clear-cache',
220
- '--logs',
221
- '--mem',
222
- '--tail',
223
- '--no-follow',
224
- '--start',
225
- '--register',
226
- '--stop',
227
- '--workspace',
228
- '--fix',
229
- '--version',
230
- '-v',
231
- '--help',
232
- '-h',
233
- ]);
234
- const flagsWithValue = FLAG_ARGS_WITH_VALUES;
235
- const unknownFlags = collectUnknownFlags(rawArgs, knownFlags, flagsWithValue);
236
-
237
- return {
238
- args,
239
- rawArgs,
240
- isServerMode,
241
- workspaceDir,
242
- wantsVersion,
243
- wantsHelp,
244
- wantsCache,
245
- wantsClean,
246
- wantsStatus,
247
- wantsClearCache,
248
- wantsLogs,
249
- wantsMem,
250
- wantsStart,
251
- wantsStop,
252
- wantsFix,
253
- wantsNoFollow,
254
- tailLines,
255
- startFilter,
256
- unknownFlags,
257
- };
258
- }
259
-
143
+
144
+ export function collectUnknownFlags(rawArgs, knownFlags, flagsWithValue) {
145
+ const unknownFlags = [];
146
+ for (let i = 0; i < rawArgs.length; i += 1) {
147
+ const arg = rawArgs[i];
148
+ if (flagsWithValue.has(arg)) {
149
+ if (arg.includes('=')) continue;
150
+ const next = rawArgs[i + 1];
151
+ if (next && !next.startsWith('-')) {
152
+ i += 1;
153
+ }
154
+ continue;
155
+ }
156
+ if (arg.startsWith('-') && !knownFlags.has(arg) && !arg.startsWith('--workspace=')) {
157
+ unknownFlags.push(arg);
158
+ }
159
+ }
160
+ return unknownFlags;
161
+ }
162
+
163
+ export function parseArgs(
164
+ argv = process.argv,
165
+ runtime = { stdinIsTTY: process.stdin.isTTY, stdoutIsTTY: process.stdout.isTTY }
166
+ ) {
167
+ const args = normalizeCliArgs(argv.slice(2));
168
+ const rawArgs = [...args];
169
+
170
+ const wantsVersion = args.includes('--version') || args.includes('-v');
171
+ const wantsHelp =
172
+ args.includes('--help') || args.includes('-h') || shouldDefaultToHelp(args, runtime);
173
+ const wantsCache = args.includes('--cache');
174
+ const wantsClean = args.includes('--clean');
175
+ const wantsStatus = args.includes('--status');
176
+ const wantsClearCache = args.includes('--clear-cache');
177
+ const wantsLogs = args.includes('--logs');
178
+ const wantsMem = args.includes('--mem');
179
+ const wantsRegister = args.includes('--register');
180
+ const wantsStart = args.includes('--start') || wantsRegister;
181
+ const wantsStop = args.includes('--stop');
182
+ const wantsFix = args.includes('--fix');
183
+ const wantsNoFollow = args.includes('--no-follow');
184
+
185
+ const isServerMode = !(
186
+ wantsCache ||
187
+ wantsStatus ||
188
+ wantsClearCache ||
189
+ wantsLogs ||
190
+ wantsMem ||
191
+ wantsStart ||
192
+ wantsStop ||
193
+ wantsHelp ||
194
+ wantsVersion
195
+ );
196
+
197
+ const workspaceDir = parseWorkspaceDir(args);
198
+
199
+ let tailLines = DEFAULT_LOG_TAIL_LINES;
200
+ if (wantsLogs) {
201
+ const tailIndex = args.indexOf('--tail');
202
+ if (tailIndex !== -1 && args[tailIndex + 1]) {
203
+ const parsed = parseInt(args[tailIndex + 1], 10);
204
+ if (!isNaN(parsed) && parsed > 0) {
205
+ tailLines = parsed;
206
+ }
207
+ }
208
+ }
209
+
210
+ let startFilter = null;
211
+ if (wantsStart) {
212
+ const getFilter = (flag) => {
213
+ const filterIndex = args.indexOf(flag);
214
+ if (filterIndex === -1) return null;
215
+ const value = args[filterIndex + 1];
216
+ return value && !value.startsWith('-') ? value : null;
217
+ };
218
+ startFilter = getFilter('--start') ?? getFilter('--register');
219
+ }
220
+
221
+ const knownFlags = new Set([
222
+ '--cache',
223
+ '--clean',
224
+ '--status',
225
+ '--clear',
226
+ '--clear-cache',
227
+ '--logs',
228
+ '--mem',
229
+ '--tail',
230
+ '--no-follow',
231
+ '--start',
232
+ '--register',
233
+ '--stop',
234
+ '--workspace',
235
+ '--fix',
236
+ '--version',
237
+ '-v',
238
+ '--help',
239
+ '-h',
240
+ ]);
241
+ const flagsWithValue = FLAG_ARGS_WITH_VALUES;
242
+ const unknownFlags = collectUnknownFlags(rawArgs, knownFlags, flagsWithValue);
243
+
244
+ return {
245
+ args,
246
+ rawArgs,
247
+ isServerMode,
248
+ workspaceDir,
249
+ wantsVersion,
250
+ wantsHelp,
251
+ wantsCache,
252
+ wantsClean,
253
+ wantsStatus,
254
+ wantsClearCache,
255
+ wantsLogs,
256
+ wantsMem,
257
+ wantsStart,
258
+ wantsStop,
259
+ wantsFix,
260
+ wantsNoFollow,
261
+ tailLines,
262
+ startFilter,
263
+ unknownFlags,
264
+ };
265
+ }