@softerist/heuristic-mcp 3.2.3 → 3.2.5

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 +3146 -3271
  8. package/features/lifecycle.js +1011 -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 +788 -781
  14. package/lib/cache-ops.js +22 -22
  15. package/lib/cache-utils.js +465 -519
  16. package/lib/cache.js +1749 -1849
  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 -493
  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 +133 -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 +164 -147
  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 +973 -991
  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
@@ -1,265 +1,252 @@
1
- import fs from 'fs/promises';
2
- import { writeFileSync } from 'fs';
3
-
4
- import path from 'path';
5
- import os from 'os';
6
- import {
7
- parseJsonc,
8
- upsertMcpServerEntryInText,
9
- upsertMcpServerEntryInToml,
10
- } from '../lib/settings-editor.js';
11
-
12
- function getUserHomeDir() {
13
- if (process.platform === 'win32' && process.env.USERPROFILE) {
14
- return process.env.USERPROFILE;
15
- }
16
- return os.homedir();
17
- }
18
-
19
-
20
- function detectCurrentIDE() {
21
-
22
- if (process.env.ANTIGRAVITY_AGENT) {
23
- return 'Antigravity';
24
- }
25
- if (process.env.CURSOR_AGENT) {
26
- return 'Cursor';
27
- }
28
- if (
29
- process.env.CODEX_THREAD_ID ||
30
- process.env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE ||
31
- process.env.CODEX_WORKSPACE
32
- ) {
33
- return 'Codex';
34
- }
35
- if (process.env.VSCODE_IPC_HOOK || process.env.TERM_PROGRAM === 'vscode') {
36
- return 'VS Code';
37
- }
38
- if (
39
- process.env.WARP_SESSION_ID ||
40
- process.env.TERM_PROGRAM === 'WarpTerminal' ||
41
- process.env.TERM_PROGRAM === 'Warp'
42
- ) {
43
- return 'Warp';
44
- }
45
- if (process.env.WINDSURF_AGENT || process.env.WINDSURF_WORKSPACE) {
46
- return 'Windsurf';
47
- }
48
-
49
-
50
- return null;
51
- }
52
-
53
-
54
- function getConfigPaths() {
55
- const platform = process.platform;
56
- const home = getUserHomeDir();
57
- const currentIDE = detectCurrentIDE();
58
- const allPaths = [];
59
-
60
-
61
- allPaths.push({
62
- name: 'Antigravity',
63
- path: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'),
64
- format: 'json',
65
- canCreate: true,
66
- });
67
-
68
-
69
- allPaths.push({
70
- name: 'Codex',
71
- path: path.join(home, '.codex', 'config.toml'),
72
- format: 'toml',
73
- canCreate: true,
74
- });
75
-
76
-
77
- if (platform === 'darwin') {
78
- allPaths.push({
79
- name: 'Claude Desktop',
80
- path: path.join(
81
- home,
82
- 'Library',
83
- 'Application Support',
84
- 'Claude',
85
- 'claude_desktop_config.json'
86
- ),
87
- format: 'json',
88
- canCreate: false,
89
- });
90
- } else if (platform === 'win32') {
91
- allPaths.push({
92
- name: 'Claude Desktop',
93
- path: path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json'),
94
- format: 'json',
95
- canCreate: false,
96
- });
97
- }
98
-
99
-
100
- if (platform === 'darwin') {
101
- allPaths.push({
102
- name: 'Cursor',
103
- path: path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'settings.json'),
104
- format: 'json',
105
- canCreate: false,
106
- });
107
- } else if (platform === 'win32') {
108
- allPaths.push({
109
- name: 'Cursor',
110
- path: path.join(process.env.APPDATA || '', 'Cursor', 'User', 'settings.json'),
111
- format: 'json',
112
- canCreate: false,
113
- });
114
- } else {
115
- allPaths.push({
116
- name: 'Cursor',
117
- path: path.join(home, '.config', 'Cursor', 'User', 'settings.json'),
118
- format: 'json',
119
- canCreate: false,
120
- });
121
- }
122
-
123
- // Cursor global MCP config (discovered by VS Code MCP Discovery)
124
- allPaths.push({
125
- name: 'Cursor Global',
126
- path: path.join(home, '.cursor', 'mcp.json'),
127
- format: 'json',
128
- canCreate: false,
129
- preferredContainerKey: 'mcpServers',
130
- });
131
-
132
- // Windsurf global MCP config (discovered by VS Code MCP Discovery)
133
- allPaths.push({
134
- name: 'Windsurf',
135
- path: path.join(home, '.codeium', 'windsurf', 'mcp_config.json'),
136
- format: 'json',
137
- canCreate: false,
138
- preferredContainerKey: 'mcpServers',
139
- });
140
-
141
-
142
- allPaths.push({
143
- name: 'Warp',
144
- path: path.join(home, '.warp', 'mcp_settings.json'),
145
- format: 'json',
146
- canCreate: true,
147
- preferredContainerKey: 'mcpServers',
148
- });
149
- if (platform === 'win32') {
150
- allPaths.push({
151
- name: 'Warp AppData',
152
- path: path.join(process.env.APPDATA || '', 'Warp', 'mcp_settings.json'),
153
- format: 'json',
154
- canCreate: false,
155
- preferredContainerKey: 'mcpServers',
156
- });
157
- }
158
-
159
-
160
- if (platform === 'darwin') {
161
- allPaths.push({
162
- name: 'VS Code',
163
- path: path.join(home, 'Library', 'Application Support', 'Code', 'User', 'mcp.json'),
164
- format: 'json',
165
- canCreate: false,
166
- preferredContainerKey: 'servers',
167
- });
168
- allPaths.push({
169
- name: 'VS Code Insiders',
170
- path: path.join(
171
- home,
172
- 'Library',
173
- 'Application Support',
174
- 'Code - Insiders',
175
- 'User',
176
- 'mcp.json'
177
- ),
178
- format: 'json',
179
- canCreate: false,
180
- preferredContainerKey: 'servers',
181
- });
182
- } else if (platform === 'win32') {
183
- allPaths.push({
184
- name: 'VS Code',
185
- path: path.join(process.env.APPDATA || '', 'Code', 'User', 'mcp.json'),
186
- format: 'json',
187
- canCreate: false,
188
- preferredContainerKey: 'servers',
189
- });
190
- allPaths.push({
191
- name: 'VS Code Insiders',
192
- path: path.join(process.env.APPDATA || '', 'Code - Insiders', 'User', 'mcp.json'),
193
- format: 'json',
194
- canCreate: false,
195
- preferredContainerKey: 'servers',
196
- });
197
- } else {
198
- allPaths.push({
199
- name: 'VS Code',
200
- path: path.join(home, '.config', 'Code', 'User', 'mcp.json'),
201
- format: 'json',
202
- canCreate: false,
203
- preferredContainerKey: 'servers',
204
- });
205
- allPaths.push({
206
- name: 'VS Code Insiders',
207
- path: path.join(home, '.config', 'Code - Insiders', 'User', 'mcp.json'),
208
- format: 'json',
209
- canCreate: false,
210
- preferredContainerKey: 'servers',
211
- });
212
- }
213
-
214
-
215
-
216
- return allPaths.map((entry) => ({
217
- ...entry,
218
- canCreate: entry.canCreate || entry.name === currentIDE,
219
- }));
220
- }
221
-
222
-
223
- function forceLog(message) {
224
- try {
225
- if (process.platform !== 'win32') {
226
- writeFileSync('/dev/tty', message + '\n');
227
- } else {
228
- console.error(message);
229
- }
230
- } catch (_e) {
231
- console.error(message);
232
- }
233
- }
234
-
235
- function normalizeIdeName(name) {
236
- return String(name || '')
237
- .toLowerCase()
238
- .replace(/["']/g, '')
239
- .replace(/[\s_-]+/g, '');
240
- }
241
-
1
+ import fs from 'fs/promises';
2
+ import { writeFileSync } from 'fs';
3
+
4
+ import path from 'path';
5
+ import os from 'os';
6
+ import {
7
+ parseJsonc,
8
+ upsertMcpServerEntryInText,
9
+ upsertMcpServerEntryInToml,
10
+ } from '../lib/settings-editor.js';
11
+
12
+ function getUserHomeDir() {
13
+ if (process.platform === 'win32' && process.env.USERPROFILE) {
14
+ return process.env.USERPROFILE;
15
+ }
16
+ return os.homedir();
17
+ }
18
+
19
+ function detectCurrentIDE() {
20
+ if (process.env.ANTIGRAVITY_AGENT) {
21
+ return 'Antigravity';
22
+ }
23
+ if (process.env.CURSOR_AGENT) {
24
+ return 'Cursor';
25
+ }
26
+ if (
27
+ process.env.CODEX_THREAD_ID ||
28
+ process.env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE ||
29
+ process.env.CODEX_WORKSPACE
30
+ ) {
31
+ return 'Codex';
32
+ }
33
+ if (process.env.VSCODE_IPC_HOOK || process.env.TERM_PROGRAM === 'vscode') {
34
+ return 'VS Code';
35
+ }
36
+ if (
37
+ process.env.WARP_SESSION_ID ||
38
+ process.env.TERM_PROGRAM === 'WarpTerminal' ||
39
+ process.env.TERM_PROGRAM === 'Warp'
40
+ ) {
41
+ return 'Warp';
42
+ }
43
+ if (process.env.WINDSURF_AGENT || process.env.WINDSURF_WORKSPACE) {
44
+ return 'Windsurf';
45
+ }
46
+
47
+ return null;
48
+ }
49
+
50
+ function getConfigPaths() {
51
+ const platform = process.platform;
52
+ const home = getUserHomeDir();
53
+ const currentIDE = detectCurrentIDE();
54
+ const allPaths = [];
55
+
56
+ allPaths.push({
57
+ name: 'Antigravity',
58
+ path: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'),
59
+ format: 'json',
60
+ canCreate: true,
61
+ });
62
+
63
+ allPaths.push({
64
+ name: 'Codex',
65
+ path: path.join(home, '.codex', 'config.toml'),
66
+ format: 'toml',
67
+ canCreate: true,
68
+ });
69
+
70
+ if (platform === 'darwin') {
71
+ allPaths.push({
72
+ name: 'Claude Desktop',
73
+ path: path.join(
74
+ home,
75
+ 'Library',
76
+ 'Application Support',
77
+ 'Claude',
78
+ 'claude_desktop_config.json'
79
+ ),
80
+ format: 'json',
81
+ canCreate: false,
82
+ });
83
+ } else if (platform === 'win32') {
84
+ allPaths.push({
85
+ name: 'Claude Desktop',
86
+ path: path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json'),
87
+ format: 'json',
88
+ canCreate: false,
89
+ });
90
+ }
91
+
92
+ if (platform === 'darwin') {
93
+ allPaths.push({
94
+ name: 'Cursor',
95
+ path: path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'settings.json'),
96
+ format: 'json',
97
+ canCreate: false,
98
+ });
99
+ } else if (platform === 'win32') {
100
+ allPaths.push({
101
+ name: 'Cursor',
102
+ path: path.join(process.env.APPDATA || '', 'Cursor', 'User', 'settings.json'),
103
+ format: 'json',
104
+ canCreate: false,
105
+ });
106
+ } else {
107
+ allPaths.push({
108
+ name: 'Cursor',
109
+ path: path.join(home, '.config', 'Cursor', 'User', 'settings.json'),
110
+ format: 'json',
111
+ canCreate: false,
112
+ });
113
+ }
114
+
115
+ // Cursor global MCP config (discovered by VS Code MCP Discovery)
116
+ allPaths.push({
117
+ name: 'Cursor Global',
118
+ path: path.join(home, '.cursor', 'mcp.json'),
119
+ format: 'json',
120
+ canCreate: false,
121
+ preferredContainerKey: 'mcpServers',
122
+ });
123
+
124
+ // Windsurf global MCP config (discovered by VS Code MCP Discovery)
125
+ allPaths.push({
126
+ name: 'Windsurf',
127
+ path: path.join(home, '.codeium', 'windsurf', 'mcp_config.json'),
128
+ format: 'json',
129
+ canCreate: false,
130
+ preferredContainerKey: 'mcpServers',
131
+ });
132
+
133
+ allPaths.push({
134
+ name: 'Warp',
135
+ path: path.join(home, '.warp', 'mcp_settings.json'),
136
+ format: 'json',
137
+ canCreate: true,
138
+ preferredContainerKey: 'mcpServers',
139
+ });
140
+ if (platform === 'win32') {
141
+ allPaths.push({
142
+ name: 'Warp AppData',
143
+ path: path.join(process.env.APPDATA || '', 'Warp', 'mcp_settings.json'),
144
+ format: 'json',
145
+ canCreate: false,
146
+ preferredContainerKey: 'mcpServers',
147
+ });
148
+ }
149
+
150
+ if (platform === 'darwin') {
151
+ allPaths.push({
152
+ name: 'VS Code',
153
+ path: path.join(home, 'Library', 'Application Support', 'Code', 'User', 'mcp.json'),
154
+ format: 'json',
155
+ canCreate: false,
156
+ preferredContainerKey: 'servers',
157
+ });
158
+ allPaths.push({
159
+ name: 'VS Code Insiders',
160
+ path: path.join(
161
+ home,
162
+ 'Library',
163
+ 'Application Support',
164
+ 'Code - Insiders',
165
+ 'User',
166
+ 'mcp.json'
167
+ ),
168
+ format: 'json',
169
+ canCreate: false,
170
+ preferredContainerKey: 'servers',
171
+ });
172
+ } else if (platform === 'win32') {
173
+ allPaths.push({
174
+ name: 'VS Code',
175
+ path: path.join(process.env.APPDATA || '', 'Code', 'User', 'mcp.json'),
176
+ format: 'json',
177
+ canCreate: false,
178
+ preferredContainerKey: 'servers',
179
+ });
180
+ allPaths.push({
181
+ name: 'VS Code Insiders',
182
+ path: path.join(process.env.APPDATA || '', 'Code - Insiders', 'User', 'mcp.json'),
183
+ format: 'json',
184
+ canCreate: false,
185
+ preferredContainerKey: 'servers',
186
+ });
187
+ } else {
188
+ allPaths.push({
189
+ name: 'VS Code',
190
+ path: path.join(home, '.config', 'Code', 'User', 'mcp.json'),
191
+ format: 'json',
192
+ canCreate: false,
193
+ preferredContainerKey: 'servers',
194
+ });
195
+ allPaths.push({
196
+ name: 'VS Code Insiders',
197
+ path: path.join(home, '.config', 'Code - Insiders', 'User', 'mcp.json'),
198
+ format: 'json',
199
+ canCreate: false,
200
+ preferredContainerKey: 'servers',
201
+ });
202
+ }
203
+
204
+ return allPaths.map((entry) => ({
205
+ ...entry,
206
+ canCreate: entry.canCreate || entry.name === currentIDE,
207
+ }));
208
+ }
209
+
210
+ function forceLog(message) {
211
+ try {
212
+ if (process.platform !== 'win32') {
213
+ writeFileSync('/dev/tty', message + '\n');
214
+ } else {
215
+ console.error(message);
216
+ }
217
+ } catch (_e) {
218
+ console.error(message);
219
+ }
220
+ }
221
+
222
+ function normalizeIdeName(name) {
223
+ return String(name || '')
224
+ .toLowerCase()
225
+ .replace(/["']/g, '')
226
+ .replace(/[\s_-]+/g, '');
227
+ }
228
+
242
229
  function ideMatchesFilter(name, filter) {
243
- if (!filter) return true;
244
- const normalizedName = normalizeIdeName(name);
245
- const normalizedFilter = normalizeIdeName(filter);
246
- if (!normalizedFilter) return true;
247
-
248
- if (normalizedName === normalizedFilter) return true;
249
- if (normalizedFilter === 'claude') return normalizedName === 'claudedesktop';
250
- if (normalizedFilter === 'cursor') {
251
- return normalizedName === 'cursor' || normalizedName === 'cursorglobal';
252
- }
253
- if (normalizedFilter === 'windsurf') {
254
- return normalizedName === 'windsurf';
255
- }
256
- if (normalizedFilter === 'warp') {
257
- return normalizedName === 'warp' || normalizedName === 'warpappdata';
258
- }
259
- if (normalizedFilter === 'vscode') {
260
- return normalizedName === 'vscode' || normalizedName === 'vscodeinsiders';
261
- }
262
-
230
+ if (!filter) return true;
231
+ const normalizedName = normalizeIdeName(name);
232
+ const normalizedFilter = normalizeIdeName(filter);
233
+ if (!normalizedFilter) return true;
234
+
235
+ if (normalizedName === normalizedFilter) return true;
236
+ if (normalizedFilter === 'claude') return normalizedName === 'claudedesktop';
237
+ if (normalizedFilter === 'cursor') {
238
+ return normalizedName === 'cursor' || normalizedName === 'cursorglobal';
239
+ }
240
+ if (normalizedFilter === 'windsurf') {
241
+ return normalizedName === 'windsurf';
242
+ }
243
+ if (normalizedFilter === 'warp') {
244
+ return normalizedName === 'warp' || normalizedName === 'warpappdata';
245
+ }
246
+ if (normalizedFilter === 'vscode') {
247
+ return normalizedName === 'vscode' || normalizedName === 'vscodeinsiders';
248
+ }
249
+
263
250
  return false;
264
251
  }
265
252
 
@@ -295,51 +282,48 @@ export async function register(filter = null) {
295
282
 
296
283
  const configPaths = getConfigPaths();
297
284
  let registeredCount = 0;
298
-
299
- forceLog(`[Auto-Register] Detecting IDE configurations...`);
300
-
301
- for (const { name, path: configPath, canCreate, format, preferredContainerKey } of configPaths) {
302
- if (!ideMatchesFilter(name, filter)) {
303
- continue;
304
- }
305
-
306
- try {
307
-
308
- let fileExists = true;
309
-
310
- try {
311
- await fs.access(configPath);
312
- } catch {
313
- fileExists = false;
314
-
315
-
316
- if (canCreate) {
317
- try {
318
- await fs.mkdir(path.dirname(configPath), { recursive: true });
319
- forceLog(`[Auto-Register] Creating ${name} config at ${configPath}`);
320
- } catch (mkdirErr) {
321
- forceLog(
322
- `[Auto-Register] Skipped ${name}: Cannot create config directory: ${mkdirErr.message}`
323
- );
324
- continue;
325
- }
326
- } else {
327
-
328
- continue;
329
- }
330
- }
331
-
285
+
286
+ forceLog(`[Auto-Register] Detecting IDE configurations...`);
287
+
288
+ for (const { name, path: configPath, canCreate, format, preferredContainerKey } of configPaths) {
289
+ if (!ideMatchesFilter(name, filter)) {
290
+ continue;
291
+ }
292
+
293
+ try {
294
+ let fileExists = true;
295
+
296
+ try {
297
+ await fs.access(configPath);
298
+ } catch {
299
+ fileExists = false;
300
+
301
+ if (canCreate) {
302
+ try {
303
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
304
+ forceLog(`[Auto-Register] Creating ${name} config at ${configPath}`);
305
+ } catch (mkdirErr) {
306
+ forceLog(
307
+ `[Auto-Register] Skipped ${name}: Cannot create config directory: ${mkdirErr.message}`
308
+ );
309
+ continue;
310
+ }
311
+ } else {
312
+ continue;
313
+ }
314
+ }
315
+
332
316
  let content = '';
333
317
  if (fileExists) {
334
318
  content = await fs.readFile(configPath, 'utf-8');
335
- if (format === 'json' && content.trim()) {
336
- const parsed = parseJsonc(content);
337
- if (!parsed) {
338
- forceLog(
339
- `[Auto-Register] Warning: ${name} config is not valid JSON/JSONC; skipping to avoid data loss.`
340
- );
341
- continue;
342
- }
319
+ if (format === 'json' && content.trim()) {
320
+ const parsed = parseJsonc(content);
321
+ if (!parsed) {
322
+ forceLog(
323
+ `[Auto-Register] Warning: ${name} config is not valid JSON/JSONC; skipping to avoid data loss.`
324
+ );
325
+ continue;
326
+ }
343
327
  }
344
328
  }
345
329
 
@@ -347,29 +331,28 @@ export async function register(filter = null) {
347
331
  const updated =
348
332
  format === 'toml'
349
333
  ? upsertMcpServerEntryInToml(content, 'heuristic-mcp', serverConfig)
350
- : upsertMcpServerEntryInText(
351
- content,
352
- 'heuristic-mcp',
353
- serverConfig,
354
- preferredContainerKey || 'mcpServers'
355
- );
356
- if (!updated) {
357
- forceLog(
358
- `[Auto-Register] Warning: Failed to update ${name} config (could not locate root object).`
359
- );
360
- continue;
361
- }
362
-
363
-
364
- writeFileSync(configPath, updated);
365
-
366
- forceLog(`\x1b[32m[Auto-Register] ✅ Successfully registered with ${name}\x1b[0m`);
367
- registeredCount++;
368
- } catch (err) {
369
- forceLog(`[Auto-Register] Failed to register with ${name}: ${err.message}`);
370
- }
371
- }
372
-
334
+ : upsertMcpServerEntryInText(
335
+ content,
336
+ 'heuristic-mcp',
337
+ serverConfig,
338
+ preferredContainerKey || 'mcpServers'
339
+ );
340
+ if (!updated) {
341
+ forceLog(
342
+ `[Auto-Register] Warning: Failed to update ${name} config (could not locate root object).`
343
+ );
344
+ continue;
345
+ }
346
+
347
+ writeFileSync(configPath, updated);
348
+
349
+ forceLog(`\x1b[32m[Auto-Register] ✅ Successfully registered with ${name}\x1b[0m`);
350
+ registeredCount++;
351
+ } catch (err) {
352
+ forceLog(`[Auto-Register] Failed to register with ${name}: ${err.message}`);
353
+ }
354
+ }
355
+
373
356
  if (registeredCount === 0) {
374
357
  const manualServerConfig = {
375
358
  command: 'heuristic-mcp',
@@ -380,47 +363,45 @@ export async function register(filter = null) {
380
363
  `[Auto-Register] Manual Config:\n${JSON.stringify({ mcpServers: { 'heuristic-mcp': manualServerConfig } }, null, 2)}`
381
364
  );
382
365
  } else {
383
-
384
- forceLog('\n\x1b[36m' + '='.repeat(60));
385
- forceLog(' 🚀 Heuristic MCP Installed & Configured! ');
386
- forceLog('='.repeat(60) + '\x1b[0m');
387
-
388
-
389
- const home = getUserHomeDir();
390
- const cacheRoot =
391
- process.platform === 'win32'
392
- ? path.join(
393
- process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'),
394
- 'heuristic-mcp'
395
- )
396
- : process.platform === 'darwin'
397
- ? path.join(home, 'Library', 'Caches', 'heuristic-mcp')
398
- : path.join(process.env.XDG_CACHE_HOME || path.join(home, '.cache'), 'heuristic-mcp');
399
-
400
- forceLog(`
401
- \x1b[33mACTION REQUIRED:\x1b[0m
402
- 1. \x1b[1mRestart your IDE\x1b[0m (or reload the window) to load the new config.
403
- 2. The server will start automatically in the background.
404
-
405
- \x1b[32mSTATUS:\x1b[0m
406
- - \x1b[1mConfig:\x1b[0m Updated ${registeredCount} config file(s).
407
- - \x1b[1mIndexing:\x1b[0m Will begin immediately after restart.
408
- - \x1b[1mUsage:\x1b[0m You can work while it indexes (it catches up!).
409
-
410
- \x1b[90mPATHS:\x1b[0m
411
- - \x1b[1mMCP Config:\x1b[0m ${configPaths.map((p) => p.path).join(', ')}
412
- - \x1b[1mCache:\x1b[0m ${cacheRoot}
413
- - \x1b[1mCheck status:\x1b[0m heuristic-mcp --status
414
- - \x1b[1mView logs:\x1b[0m heuristic-mcp --logs
415
-
416
- \x1b[36mHappy Coding! 🤖\x1b[0m
417
- `);
418
- forceLog(`\n\x1b[90m(Please wait while npm finalizes the installation...)\x1b[0m`);
419
- }
420
-
421
- if (currentIDE === 'Warp' && registeredCount === 0) {
422
- forceLog(
423
- '[Auto-Register] Warp detected but no local Warp MCP config was writable. Use Warp MCP settings/UI if needed.'
424
- );
425
- }
426
- }
366
+ forceLog('\n\x1b[36m' + '='.repeat(60));
367
+ forceLog(' 🚀 Heuristic MCP Installed & Configured! ');
368
+ forceLog('='.repeat(60) + '\x1b[0m');
369
+
370
+ const home = getUserHomeDir();
371
+ const cacheRoot =
372
+ process.platform === 'win32'
373
+ ? path.join(
374
+ process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'),
375
+ 'heuristic-mcp'
376
+ )
377
+ : process.platform === 'darwin'
378
+ ? path.join(home, 'Library', 'Caches', 'heuristic-mcp')
379
+ : path.join(process.env.XDG_CACHE_HOME || path.join(home, '.cache'), 'heuristic-mcp');
380
+
381
+ forceLog(`
382
+ \x1b[33mACTION REQUIRED:\x1b[0m
383
+ 1. \x1b[1mRestart your IDE\x1b[0m (or reload the window) to load the new config.
384
+ 2. The server will start automatically in the background.
385
+
386
+ \x1b[32mSTATUS:\x1b[0m
387
+ - \x1b[1mConfig:\x1b[0m Updated ${registeredCount} config file(s).
388
+ - \x1b[1mIndexing:\x1b[0m Will begin immediately after restart.
389
+ - \x1b[1mUsage:\x1b[0m You can work while it indexes (it catches up!).
390
+
391
+ \x1b[90mPATHS:\x1b[0m
392
+ - \x1b[1mMCP Config:\x1b[0m ${configPaths.map((p) => p.path).join(', ')}
393
+ - \x1b[1mCache:\x1b[0m ${cacheRoot}
394
+ - \x1b[1mCheck status:\x1b[0m heuristic-mcp --status
395
+ - \x1b[1mView logs:\x1b[0m heuristic-mcp --logs
396
+
397
+ \x1b[36mHappy Coding! 🤖\x1b[0m
398
+ `);
399
+ forceLog(`\n\x1b[90m(Please wait while npm finalizes the installation...)\x1b[0m`);
400
+ }
401
+
402
+ if (currentIDE === 'Warp' && registeredCount === 0) {
403
+ forceLog(
404
+ '[Auto-Register] Warp detected but no local Warp MCP config was writable. Use Warp MCP settings/UI if needed.'
405
+ );
406
+ }
407
+ }