@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,310 +1,302 @@
1
- import fs from 'fs';
2
-
3
- function isTypedArray(x) {
4
- return x && ArrayBuffer.isView(x) && !(x instanceof DataView);
5
- }
6
-
7
- function onceDrainOrError(stream) {
8
- return new Promise((resolve, reject) => {
9
- const onDrain = () => cleanup(resolve);
10
- const onError = (err) => cleanup(() => reject(err));
11
-
12
- const cleanup = (fn) => {
13
- stream.off('drain', onDrain);
14
- stream.off('error', onError);
15
- fn();
16
- };
17
-
18
- stream.once('drain', onDrain);
19
- stream.once('error', onError);
20
- });
21
- }
22
-
23
-
24
- export class StreamingJsonWriter {
25
-
26
- constructor(
27
- filePath,
28
- {
29
- highWaterMark = 256 * 1024,
30
- floatDigits = 6,
31
- flushChars = 256 * 1024,
32
- indent = '',
33
- assumeFinite,
34
- checkFinite,
35
- noMutation = false,
36
- joinThreshold = 8192,
37
- joinChunkSize = 2048,
38
- } = {}
39
- ) {
40
- this.filePath = filePath;
41
- this.highWaterMark =
42
- Number.isInteger(highWaterMark) && highWaterMark > 8 * 1024 ? highWaterMark : 256 * 1024;
43
- this.flushChars =
44
- Number.isInteger(flushChars) && flushChars > 8 * 1024 ? flushChars : 256 * 1024;
45
- this.indent = typeof indent === 'string' ? indent : '';
46
- this.pretty = this.indent.length > 0;
47
- this.assumeFinite = typeof checkFinite === 'boolean' ? !checkFinite : !!assumeFinite;
48
- this.noMutation = !!noMutation;
49
- this.joinThreshold =
50
- Number.isInteger(joinThreshold) && joinThreshold > 0 ? joinThreshold : 8192;
51
- this.joinChunkSize =
52
- Number.isInteger(joinChunkSize) && joinChunkSize > 0 ? joinChunkSize : 2048;
53
-
54
- this._prefixFirst = this.pretty ? this.indent : '';
55
- this._prefixNext = this.pretty ? ',\n' + this.indent : ',';
56
-
57
- this.stream = null;
58
- this.first = true;
59
- this._streamError = null;
60
-
61
-
62
- this._useJoinFastPath = floatDigits === null;
63
-
64
- if (!this._useJoinFastPath) {
65
- const digitsOk = Number.isInteger(floatDigits) && floatDigits >= 0 && floatDigits <= 12;
66
- const d = digitsOk ? floatDigits : 6;
67
- const scale = 10 ** d;
68
- if (this.assumeFinite) {
69
- this._formatFn = (x) => String(Math.round(x * scale) / scale);
70
- } else {
71
- this._formatFn = (x) => {
72
- if (!Number.isFinite(x)) return '0';
73
- return String(Math.round(x * scale) / scale);
74
- };
75
- }
76
- } else {
77
- if (this.assumeFinite) {
78
- this._formatFn = (x) => String(x);
79
- } else {
80
- this._formatFn = (x) => {
81
- if (!Number.isFinite(x)) return '0';
82
- return String(x);
83
- };
84
- }
85
- }
86
- }
87
-
88
- async writeStart() {
89
- if (this.stream) return;
90
-
91
- this.stream = fs.createWriteStream(this.filePath, {
92
- flags: 'w',
93
- encoding: 'utf8',
94
- highWaterMark: this.highWaterMark,
95
- });
96
-
97
- this.stream.on('error', (err) => {
98
- this._streamError = err;
99
- });
100
-
101
- await new Promise((resolve, reject) => {
102
- if (this.stream.fd !== null) return resolve();
103
- this.stream.once('open', resolve);
104
- this.stream.once('error', reject);
105
- });
106
-
107
- const p = this._writeRaw(this.pretty ? '[\n' : '[');
108
- if (p) await p;
109
- this.first = true;
110
- }
111
-
112
-
113
- abort(err) {
114
- if (!this.stream) return;
115
- try {
116
- this._streamError = err || this._streamError || new Error('StreamingJsonWriter aborted');
117
- this.stream.destroy(this._streamError);
118
- } catch {
119
-
120
- } finally {
121
- this.stream = null;
122
- }
123
- }
124
-
125
- async drain() {
126
- if (!this.stream || !this.stream.writableNeedDrain) return;
127
- await onceDrainOrError(this.stream);
128
- }
129
-
130
- writeItem(item) {
131
- if (!this.stream) throw new Error('StreamingJsonWriter not started. Call writeStart() first.');
132
- if (this._streamError) throw this._streamError;
133
-
134
- const prefix = this.first ? this._prefixFirst : this._prefixNext;
135
- this.first = false;
136
-
137
- const vec = item?.vector;
138
-
139
- if (isTypedArray(vec)) {
140
- const base = this.noMutation
141
- ? this._stringifyWithoutMutation(item, vec)
142
- : this._stringifyWithoutVector(item, vec);
143
- const hasBase = typeof base === 'string' && base.length > 0 && base !== '{}';
144
- const header = hasBase ? `${prefix}${base.slice(0, -1)},"vector":` : `${prefix}{"vector":`;
145
-
146
- return this._chain(this._writeRaw(header), () =>
147
- this._chain(this._writeTypedArray(vec), () => this._writeRaw('}'))
148
- );
149
- }
150
-
151
- return this._writeRaw(prefix + JSON.stringify(item));
152
- }
153
-
154
- async writeEnd() {
155
- if (!this.stream) return;
156
- if (this._streamError) throw this._streamError;
157
-
158
- const p = this._writeRaw(this.pretty ? '\n]\n' : ']\n');
159
- if (p) await p;
160
-
161
- await new Promise((resolve, reject) => {
162
- this.stream.once('error', reject);
163
- this.stream.end(resolve);
164
- });
165
-
166
- this.stream = null;
167
- this._streamError = null;
168
- }
169
-
170
- _chain(promise, next) {
171
- if (promise) return promise.then(() => next());
172
- return next();
173
- }
174
-
175
- _stringifyWithoutVector(item, vec) {
176
- let base;
177
- let restored = false;
178
-
179
- try {
180
- const prev = item.vector;
181
- item.vector = undefined;
182
- base = JSON.stringify(item);
183
- item.vector = prev;
184
- restored = true;
185
- } catch {
186
- base = JSON.stringify(item, (key, val) =>
187
- key === 'vector' && val === vec ? undefined : val
188
- );
189
- } finally {
190
- if (!restored) {
191
- try {
192
- item.vector = vec;
193
- } catch {
194
-
195
- }
196
- }
197
- }
198
-
199
- return base;
200
- }
201
-
202
- _stringifyWithoutMutation(item, vec) {
203
- try {
204
- const rest = { ...item };
205
- delete rest.vector;
206
- return JSON.stringify(rest);
207
- } catch {
208
- return JSON.stringify(item, (key, val) =>
209
- key === 'vector' && val === vec ? undefined : val
210
- );
211
- }
212
- }
213
-
214
-
215
- _writeRaw(str) {
216
- if (this._streamError) throw this._streamError;
217
-
218
- const ok = this.stream.write(str);
219
- if (ok) return null;
220
-
221
- return onceDrainOrError(this.stream).then(() => {
222
- if (this._streamError) throw this._streamError;
223
- });
224
- }
225
-
226
- _writeTypedArray(vec) {
227
- return this._chain(this._writeRaw('['), () => this._writeTypedArrayBody(vec));
228
- }
229
-
230
- _writeTypedArrayBody(vec) {
231
- if (this._useJoinFastPath) {
232
- if (!this.assumeFinite && !this._allFinite(vec)) {
233
- return this._writeFormatted(vec);
234
- }
235
-
236
- if (vec.length <= this.joinThreshold) {
237
- return this._chain(this._writeRaw(vec.join(',')), () => this._writeRaw(']'));
238
- }
239
-
240
- return this._writeJoinChunks(vec);
241
- }
242
-
243
- return this._writeFormatted(vec);
244
- }
245
-
246
- _allFinite(vec) {
247
- for (let i = 0; i < vec.length; i++) {
248
- if (!Number.isFinite(vec[i])) return false;
249
- }
250
- return true;
251
- }
252
-
253
- _writeJoinChunks(vec) {
254
- const len = vec.length;
255
- if (len === 0) return this._writeRaw(']');
256
-
257
- let i = 0;
258
- const chunkSize = this.joinChunkSize;
259
-
260
- const writeNext = () => {
261
- while (i < len) {
262
- const end = Math.min(len, i + chunkSize);
263
- let chunk = vec.subarray(i, end).join(',');
264
- if (i !== 0) chunk = ',' + chunk;
265
- i = end;
266
-
267
- const pending = this._writeRaw(chunk);
268
- if (pending) return pending.then(writeNext);
269
- }
270
-
271
- return this._writeRaw(']');
272
- };
273
-
274
- return writeNext();
275
- }
276
-
277
- _writeFormatted(vec) {
278
- const len = vec.length;
279
- if (len === 0) return this._writeRaw(']');
280
-
281
- let i = 0;
282
- let buf = '';
283
- const FLUSH_AT = this.flushChars;
284
- const format = this._formatFn;
285
-
286
- const writeNext = () => {
287
- while (i < len) {
288
- if (i) buf += ',';
289
- buf += format(vec[i]);
290
- i += 1;
291
-
292
- if (buf.length >= FLUSH_AT) {
293
- const pending = this._writeRaw(buf);
294
- buf = '';
295
- if (pending) return pending.then(writeNext);
296
- }
297
- }
298
-
299
- if (buf) {
300
- const pending = this._writeRaw(buf);
301
- buf = '';
302
- if (pending) return pending.then(() => this._writeRaw(']'));
303
- }
304
-
305
- return this._writeRaw(']');
306
- };
307
-
308
- return writeNext();
309
- }
310
- }
1
+ import fs from 'fs';
2
+
3
+ function isTypedArray(x) {
4
+ return x && ArrayBuffer.isView(x) && !(x instanceof DataView);
5
+ }
6
+
7
+ function onceDrainOrError(stream) {
8
+ return new Promise((resolve, reject) => {
9
+ const onDrain = () => cleanup(resolve);
10
+ const onError = (err) => cleanup(() => reject(err));
11
+
12
+ const cleanup = (fn) => {
13
+ stream.off('drain', onDrain);
14
+ stream.off('error', onError);
15
+ fn();
16
+ };
17
+
18
+ stream.once('drain', onDrain);
19
+ stream.once('error', onError);
20
+ });
21
+ }
22
+
23
+ export class StreamingJsonWriter {
24
+ constructor(
25
+ filePath,
26
+ {
27
+ highWaterMark = 256 * 1024,
28
+ floatDigits = 6,
29
+ flushChars = 256 * 1024,
30
+ indent = '',
31
+ assumeFinite,
32
+ checkFinite,
33
+ noMutation = false,
34
+ joinThreshold = 8192,
35
+ joinChunkSize = 2048,
36
+ } = {}
37
+ ) {
38
+ this.filePath = filePath;
39
+ this.highWaterMark =
40
+ Number.isInteger(highWaterMark) && highWaterMark > 8 * 1024 ? highWaterMark : 256 * 1024;
41
+ this.flushChars =
42
+ Number.isInteger(flushChars) && flushChars > 8 * 1024 ? flushChars : 256 * 1024;
43
+ this.indent = typeof indent === 'string' ? indent : '';
44
+ this.pretty = this.indent.length > 0;
45
+ this.assumeFinite = typeof checkFinite === 'boolean' ? !checkFinite : !!assumeFinite;
46
+ this.noMutation = !!noMutation;
47
+ this.joinThreshold =
48
+ Number.isInteger(joinThreshold) && joinThreshold > 0 ? joinThreshold : 8192;
49
+ this.joinChunkSize =
50
+ Number.isInteger(joinChunkSize) && joinChunkSize > 0 ? joinChunkSize : 2048;
51
+
52
+ this._prefixFirst = this.pretty ? this.indent : '';
53
+ this._prefixNext = this.pretty ? ',\n' + this.indent : ',';
54
+
55
+ this.stream = null;
56
+ this.first = true;
57
+ this._streamError = null;
58
+
59
+ this._useJoinFastPath = floatDigits === null;
60
+
61
+ if (!this._useJoinFastPath) {
62
+ const digitsOk = Number.isInteger(floatDigits) && floatDigits >= 0 && floatDigits <= 12;
63
+ const d = digitsOk ? floatDigits : 6;
64
+ const scale = 10 ** d;
65
+ if (this.assumeFinite) {
66
+ this._formatFn = (x) => String(Math.round(x * scale) / scale);
67
+ } else {
68
+ this._formatFn = (x) => {
69
+ if (!Number.isFinite(x)) return '0';
70
+ return String(Math.round(x * scale) / scale);
71
+ };
72
+ }
73
+ } else {
74
+ if (this.assumeFinite) {
75
+ this._formatFn = (x) => String(x);
76
+ } else {
77
+ this._formatFn = (x) => {
78
+ if (!Number.isFinite(x)) return '0';
79
+ return String(x);
80
+ };
81
+ }
82
+ }
83
+ }
84
+
85
+ async writeStart() {
86
+ if (this.stream) return;
87
+
88
+ this.stream = fs.createWriteStream(this.filePath, {
89
+ flags: 'w',
90
+ encoding: 'utf8',
91
+ highWaterMark: this.highWaterMark,
92
+ });
93
+
94
+ this.stream.on('error', (err) => {
95
+ this._streamError = err;
96
+ });
97
+
98
+ await new Promise((resolve, reject) => {
99
+ if (this.stream.fd !== null) return resolve();
100
+ this.stream.once('open', resolve);
101
+ this.stream.once('error', reject);
102
+ });
103
+
104
+ const p = this._writeRaw(this.pretty ? '[\n' : '[');
105
+ if (p) await p;
106
+ this.first = true;
107
+ }
108
+
109
+ abort(err) {
110
+ if (!this.stream) return;
111
+ try {
112
+ this._streamError = err || this._streamError || new Error('StreamingJsonWriter aborted');
113
+ this.stream.destroy(this._streamError);
114
+ } catch {
115
+ } finally {
116
+ this.stream = null;
117
+ }
118
+ }
119
+
120
+ async drain() {
121
+ if (!this.stream || !this.stream.writableNeedDrain) return;
122
+ await onceDrainOrError(this.stream);
123
+ }
124
+
125
+ writeItem(item) {
126
+ if (!this.stream) throw new Error('StreamingJsonWriter not started. Call writeStart() first.');
127
+ if (this._streamError) throw this._streamError;
128
+
129
+ const prefix = this.first ? this._prefixFirst : this._prefixNext;
130
+ this.first = false;
131
+
132
+ const vec = item?.vector;
133
+
134
+ if (isTypedArray(vec)) {
135
+ const base = this.noMutation
136
+ ? this._stringifyWithoutMutation(item, vec)
137
+ : this._stringifyWithoutVector(item, vec);
138
+ const hasBase = typeof base === 'string' && base.length > 0 && base !== '{}';
139
+ const header = hasBase ? `${prefix}${base.slice(0, -1)},"vector":` : `${prefix}{"vector":`;
140
+
141
+ return this._chain(this._writeRaw(header), () =>
142
+ this._chain(this._writeTypedArray(vec), () => this._writeRaw('}'))
143
+ );
144
+ }
145
+
146
+ return this._writeRaw(prefix + JSON.stringify(item));
147
+ }
148
+
149
+ async writeEnd() {
150
+ if (!this.stream) return;
151
+ if (this._streamError) throw this._streamError;
152
+
153
+ const p = this._writeRaw(this.pretty ? '\n]\n' : ']\n');
154
+ if (p) await p;
155
+
156
+ await new Promise((resolve, reject) => {
157
+ this.stream.once('error', reject);
158
+ this.stream.end(resolve);
159
+ });
160
+
161
+ this.stream = null;
162
+ this._streamError = null;
163
+ }
164
+
165
+ _chain(promise, next) {
166
+ if (promise) return promise.then(() => next());
167
+ return next();
168
+ }
169
+
170
+ _stringifyWithoutVector(item, vec) {
171
+ let base;
172
+ let restored = false;
173
+
174
+ try {
175
+ const prev = item.vector;
176
+ item.vector = undefined;
177
+ base = JSON.stringify(item);
178
+ item.vector = prev;
179
+ restored = true;
180
+ } catch {
181
+ base = JSON.stringify(item, (key, val) =>
182
+ key === 'vector' && val === vec ? undefined : val
183
+ );
184
+ } finally {
185
+ if (!restored) {
186
+ try {
187
+ item.vector = vec;
188
+ } catch {}
189
+ }
190
+ }
191
+
192
+ return base;
193
+ }
194
+
195
+ _stringifyWithoutMutation(item, vec) {
196
+ try {
197
+ const rest = { ...item };
198
+ delete rest.vector;
199
+ return JSON.stringify(rest);
200
+ } catch {
201
+ return JSON.stringify(item, (key, val) =>
202
+ key === 'vector' && val === vec ? undefined : val
203
+ );
204
+ }
205
+ }
206
+
207
+ _writeRaw(str) {
208
+ if (this._streamError) throw this._streamError;
209
+
210
+ const ok = this.stream.write(str);
211
+ if (ok) return null;
212
+
213
+ return onceDrainOrError(this.stream).then(() => {
214
+ if (this._streamError) throw this._streamError;
215
+ });
216
+ }
217
+
218
+ _writeTypedArray(vec) {
219
+ return this._chain(this._writeRaw('['), () => this._writeTypedArrayBody(vec));
220
+ }
221
+
222
+ _writeTypedArrayBody(vec) {
223
+ if (this._useJoinFastPath) {
224
+ if (!this.assumeFinite && !this._allFinite(vec)) {
225
+ return this._writeFormatted(vec);
226
+ }
227
+
228
+ if (vec.length <= this.joinThreshold) {
229
+ return this._chain(this._writeRaw(vec.join(',')), () => this._writeRaw(']'));
230
+ }
231
+
232
+ return this._writeJoinChunks(vec);
233
+ }
234
+
235
+ return this._writeFormatted(vec);
236
+ }
237
+
238
+ _allFinite(vec) {
239
+ for (let i = 0; i < vec.length; i++) {
240
+ if (!Number.isFinite(vec[i])) return false;
241
+ }
242
+ return true;
243
+ }
244
+
245
+ _writeJoinChunks(vec) {
246
+ const len = vec.length;
247
+ if (len === 0) return this._writeRaw(']');
248
+
249
+ let i = 0;
250
+ const chunkSize = this.joinChunkSize;
251
+
252
+ const writeNext = () => {
253
+ while (i < len) {
254
+ const end = Math.min(len, i + chunkSize);
255
+ let chunk = vec.subarray(i, end).join(',');
256
+ if (i !== 0) chunk = ',' + chunk;
257
+ i = end;
258
+
259
+ const pending = this._writeRaw(chunk);
260
+ if (pending) return pending.then(writeNext);
261
+ }
262
+
263
+ return this._writeRaw(']');
264
+ };
265
+
266
+ return writeNext();
267
+ }
268
+
269
+ _writeFormatted(vec) {
270
+ const len = vec.length;
271
+ if (len === 0) return this._writeRaw(']');
272
+
273
+ let i = 0;
274
+ let buf = '';
275
+ const FLUSH_AT = this.flushChars;
276
+ const format = this._formatFn;
277
+
278
+ const writeNext = () => {
279
+ while (i < len) {
280
+ if (i) buf += ',';
281
+ buf += format(vec[i]);
282
+ i += 1;
283
+
284
+ if (buf.length >= FLUSH_AT) {
285
+ const pending = this._writeRaw(buf);
286
+ buf = '';
287
+ if (pending) return pending.then(writeNext);
288
+ }
289
+ }
290
+
291
+ if (buf) {
292
+ const pending = this._writeRaw(buf);
293
+ buf = '';
294
+ if (pending) return pending.then(() => this._writeRaw(']'));
295
+ }
296
+
297
+ return this._writeRaw(']');
298
+ };
299
+
300
+ return writeNext();
301
+ }
302
+ }