@wrongstack/tools 0.317.0 → 0.317.2
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/dist/_spawn-stream.d.ts +1 -1
- package/dist/audit.d.ts +37 -2
- package/dist/audit.js +4 -4
- package/dist/bash.js +1 -1
- package/dist/batch-tool-use.js +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/tools.d.ts +16 -1
- package/dist/builtin.js +43 -43
- package/dist/{chunk-SDLVH5RZ.js → chunk-3QQSBUXR.js} +6 -5
- package/dist/{chunk-K3WNSHUF.js → chunk-45JPRMC2.js} +62 -36
- package/dist/{chunk-EJWSCQ6D.js → chunk-4AEZIFOW.js} +6 -5
- package/dist/{chunk-PQKK5JH7.js → chunk-4E42D7UF.js} +2 -2
- package/dist/{chunk-JRJJX3L5.js → chunk-5WNDJHT6.js} +3 -2
- package/dist/{chunk-7EY5DCRO.js → chunk-5ZYEGP2P.js} +4 -4
- package/dist/{chunk-HPEO4EA7.js → chunk-6RR5VX6U.js} +35 -17
- package/dist/{chunk-QDQY7NQ2.js → chunk-A2PX7M7A.js} +5 -5
- package/dist/{chunk-JQRIR762.js → chunk-AK2K4KHR.js} +27 -19
- package/dist/{chunk-P7FYFZ6M.js → chunk-BANPF4LY.js} +11 -7
- package/dist/{chunk-RGISBZBD.js → chunk-CPSAF2AU.js} +3 -2
- package/dist/{chunk-BSLVR56S.js → chunk-CPVLVQYT.js} +6 -5
- package/dist/{chunk-VJNHFZ7J.js → chunk-CVALEVGA.js} +6 -5
- package/dist/{chunk-PY2IOS7C.js → chunk-CWALNI6K.js} +5 -5
- package/dist/{chunk-LIJQMYYX.js → chunk-ELFFQ4RU.js} +7 -3
- package/dist/{chunk-JNNVRHMV.js → chunk-FJEQZHZN.js} +8 -8
- package/dist/{chunk-S5CCLZL3.js → chunk-FRN7TIAA.js} +2 -2
- package/dist/{chunk-PCHQ6YRR.js → chunk-FYDKHXN7.js} +2 -2
- package/dist/{chunk-NKJW5GFO.js → chunk-H6AWAZ2Y.js} +3 -3
- package/dist/{chunk-IVWV2UM6.js → chunk-HTYEO67J.js} +6 -5
- package/dist/{chunk-UNSKG6DC.js → chunk-ICAXDRP6.js} +10 -15
- package/dist/{chunk-IYK7XGDZ.js → chunk-JJQB6R7Y.js} +7 -7
- package/dist/{chunk-LWKUTMD5.js → chunk-MRZOVQ5D.js} +6 -5
- package/dist/{chunk-YGG6X57C.js → chunk-NKX4SJ5R.js} +12 -9
- package/dist/{chunk-U4D5S3VQ.js → chunk-NWZ6XGBJ.js} +2 -1
- package/dist/{chunk-UKU2ZX4C.js → chunk-P7ZQ2FAJ.js} +27 -17
- package/dist/{chunk-4I4LWFOO.js → chunk-PQTONQ4P.js} +16 -11
- package/dist/{chunk-XGHMUZ77.js → chunk-RMB76PDS.js} +3 -3
- package/dist/{chunk-5OAOKALG.js → chunk-RUOMW2I6.js} +4 -3
- package/dist/{chunk-553IQUMO.js → chunk-S2JRYDYG.js} +7 -6
- package/dist/{chunk-OUBDL3WH.js → chunk-SOG7XIRF.js} +11 -8
- package/dist/{chunk-U6DZWHBA.js → chunk-TDLZIDCY.js} +9 -7
- package/dist/{chunk-TRDX25UH.js → chunk-TFEGJDH5.js} +293 -86
- package/dist/{chunk-AHHDWNXC.js → chunk-TKA4VEX2.js} +2 -2
- package/dist/{chunk-5H4GSJAI.js → chunk-UE3UBMCP.js} +7 -6
- package/dist/{chunk-IXMNTNW5.js → chunk-UKGMDCXT.js} +4 -3
- package/dist/{chunk-VGBUDLW4.js → chunk-UOXX4SQZ.js} +7 -6
- package/dist/{chunk-T2F4S7U4.js → chunk-WI3VDXHD.js} +18 -8
- package/dist/{chunk-O4MBV4AX.js → chunk-WJYXMB2R.js} +6 -5
- package/dist/{chunk-U4VAATKP.js → chunk-WXJY3BKV.js} +16 -6
- package/dist/{chunk-DR7JOQTC.js → chunk-X5K3U6GI.js} +3 -3
- package/dist/{chunk-DSEANA2W.js → chunk-XVGB6KYU.js} +37 -36
- package/dist/{chunk-TEBQ4VPZ.js → chunk-YOHO4DVT.js} +6 -5
- package/dist/{chunk-RXISBFR5.js → chunk-ZE6KLBUO.js} +5 -4
- package/dist/{chunk-22B7GE5T.js → chunk-ZHH3BEWU.js} +13 -12
- package/dist/codebase-index/bm25.d.ts +14 -1
- package/dist/codebase-index/index.js +8 -8
- package/dist/codebase-index/json-parser.d.ts +4 -0
- package/dist/codebase-index/parser-worker-script.js +2 -2
- package/dist/codebase-index/project-server.js +48 -9
- package/dist/codebase-index/worker.js +4 -4
- package/dist/codebase-index/writer-bulk-insert.d.ts +0 -1
- package/dist/codebase-index/writer-schema.d.ts +1 -1
- package/dist/codebase-index/writer.d.ts +38 -0
- package/dist/diff.js +1 -1
- package/dist/e2e.d.ts +40 -1
- package/dist/e2e.js +1 -1
- package/dist/edit.js +7 -7
- package/dist/exec.js +1 -1
- package/dist/fetch.js +1 -1
- package/dist/format.d.ts +42 -2
- package/dist/format.js +4 -4
- package/dist/git.d.ts +70 -1
- package/dist/git.js +1 -1
- package/dist/glob.js +3 -3
- package/dist/{go-parser-JXYKJHRC.js → go-parser-IKHW67WE.js} +2 -2
- package/dist/grep.js +3 -3
- package/dist/index.js +45 -45
- package/dist/install.d.ts +51 -2
- package/dist/install.js +4 -4
- package/dist/{json-parser-IBHZ4BZC.js → json-parser-2EOVP5MR.js} +81 -15
- package/dist/kanban.d.ts +19 -1
- package/dist/kanban.js +2 -2
- package/dist/languages/index.js +2 -2
- package/dist/{legacy-bridge-7M6QLUQN.js → legacy-bridge-SFNXIRAP.js} +4 -4
- package/dist/lint.js +4 -4
- package/dist/logs.js +1 -1
- package/dist/outdated.d.ts +25 -1
- package/dist/outdated.js +1 -1
- package/dist/pack.js +44 -44
- package/dist/{parser-dispatch-QH4XPGG6.js → parser-dispatch-X62UWXJS.js} +3 -3
- package/dist/patch.js +7 -7
- package/dist/plan.js +4 -4
- package/dist/{py-parser-IS4HKYMF.js → py-parser-TDXSQZBC.js} +2 -2
- package/dist/read.js +7 -7
- package/dist/replace.js +7 -7
- package/dist/{rs-parser-XHUUO2KZ.js → rs-parser-GIWPUA3T.js} +2 -2
- package/dist/scaffold.js +1 -1
- package/dist/search.js +1 -1
- package/dist/session-kanban.js +1 -1
- package/dist/task.js +4 -4
- package/dist/test.js +4 -4
- package/dist/todo.js +3 -3
- package/dist/tool-diff.js +1 -1
- package/dist/tool-tier.js +45 -45
- package/dist/tool-use.js +1 -1
- package/dist/{ts-parser-RCTYKSVI.js → ts-parser-7W26YB26.js} +2 -2
- package/dist/typecheck.js +4 -4
- package/dist/write.js +7 -7
- package/dist/{yaml-parser-4SAXV3PL.js → yaml-parser-RGBXEZE4.js} +2 -2
- package/package.json +5 -5
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseFilesContent
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JJQB6R7Y.js";
|
|
4
4
|
import {
|
|
5
5
|
INDEXABLE_EXTENSIONS,
|
|
6
6
|
LANG_FAMILY_ENTRIES,
|
|
7
7
|
detectLang,
|
|
8
8
|
languageFamily
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YOHO4DVT.js";
|
|
10
10
|
import {
|
|
11
11
|
loadGitignoreMatcher
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ELFFQ4RU.js";
|
|
13
13
|
|
|
14
14
|
// src/codebase-index/circuit-breaker.ts
|
|
15
15
|
var CircuitOpenError = class extends Error {
|
|
@@ -99,13 +99,59 @@ var K1 = 1.5;
|
|
|
99
99
|
var B = 0.75;
|
|
100
100
|
var TOKENISE_RE = new RegExp("[^\\p{L}\\p{N}$']", "gu");
|
|
101
101
|
function tokenise(text) {
|
|
102
|
-
|
|
102
|
+
if (!text) return [];
|
|
103
|
+
const cleaned = text.replace(TOKENISE_RE, " ").toLowerCase().trim();
|
|
104
|
+
if (!cleaned) return [];
|
|
105
|
+
return cleaned.split(/\s+/);
|
|
103
106
|
}
|
|
107
|
+
var SPLIT_CANDIDATE_RE = /[A-Z_\d-]/;
|
|
104
108
|
function splitName(name) {
|
|
109
|
+
if (!name || !SPLIT_CANDIDATE_RE.test(name)) return name;
|
|
105
110
|
return name.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([\p{L}])(\d)/gu, "$1 $2").replace(/(\d)([\p{L}])/gu, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
106
111
|
}
|
|
112
|
+
var FTS_SIGNATURE_MAX_CHARS = 300;
|
|
113
|
+
function ftsSignature(signature) {
|
|
114
|
+
if (!signature) return "";
|
|
115
|
+
const bodyStart = declarationBodyStart(signature);
|
|
116
|
+
const header = bodyStart === -1 ? signature : signature.slice(0, bodyStart);
|
|
117
|
+
return header.slice(0, FTS_SIGNATURE_MAX_CHARS);
|
|
118
|
+
}
|
|
119
|
+
function declarationBodyStart(s) {
|
|
120
|
+
let parenDepth = 0;
|
|
121
|
+
let paramsClosed = false;
|
|
122
|
+
let i = 0;
|
|
123
|
+
while (i < s.length) {
|
|
124
|
+
const ch = s[i];
|
|
125
|
+
if (!paramsClosed) {
|
|
126
|
+
if (ch === "(") parenDepth++;
|
|
127
|
+
else if (ch === ")") {
|
|
128
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
129
|
+
if (parenDepth === 0) paramsClosed = true;
|
|
130
|
+
}
|
|
131
|
+
i++;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (ch === "{") {
|
|
135
|
+
let j = i - 1;
|
|
136
|
+
while (j >= 0 && /\s/.test(s[j] ?? "")) j--;
|
|
137
|
+
if (s[j] === ":") {
|
|
138
|
+
let braceDepth = 1;
|
|
139
|
+
i++;
|
|
140
|
+
while (i < s.length && braceDepth > 0) {
|
|
141
|
+
if (s[i] === "{") braceDepth++;
|
|
142
|
+
else if (s[i] === "}") braceDepth--;
|
|
143
|
+
i++;
|
|
144
|
+
}
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
return i;
|
|
148
|
+
}
|
|
149
|
+
i++;
|
|
150
|
+
}
|
|
151
|
+
return -1;
|
|
152
|
+
}
|
|
107
153
|
function buildIndexableText(name, signature, docComment) {
|
|
108
|
-
return [splitName(name), name, signature, docComment].filter(Boolean).join(" ");
|
|
154
|
+
return [splitName(name), name, ftsSignature(signature), docComment].filter(Boolean).join(" ");
|
|
109
155
|
}
|
|
110
156
|
function buildBm25Index(docs) {
|
|
111
157
|
const documents = docs.map((d) => {
|
|
@@ -189,7 +235,7 @@ var SCHEMA_VERSION = 5;
|
|
|
189
235
|
// src/codebase-index/writer-helpers.ts
|
|
190
236
|
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
191
237
|
function escapeLike(value) {
|
|
192
|
-
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
238
|
+
return /[\\%_]/.test(value) ? value.replace(/[\\%_]/g, (char) => `\\${char}`) : value;
|
|
193
239
|
}
|
|
194
240
|
function ladderChunkSizes(total, max) {
|
|
195
241
|
if (total <= 0) return [];
|
|
@@ -214,8 +260,22 @@ function padToInBucket(values) {
|
|
|
214
260
|
while (padded.length < target) padded.push(padded[0]);
|
|
215
261
|
return padded;
|
|
216
262
|
}
|
|
263
|
+
var PLACEHOLDER_BUCKETS = {
|
|
264
|
+
1: "?",
|
|
265
|
+
2: "?,?",
|
|
266
|
+
4: "?,?,?,?",
|
|
267
|
+
8: "?,?,?,?,?,?,?,?",
|
|
268
|
+
16: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
|
|
269
|
+
32: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
|
|
270
|
+
64: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
|
|
271
|
+
128: Array.from({ length: 128 }, () => "?").join(","),
|
|
272
|
+
256: Array.from({ length: 256 }, () => "?").join(","),
|
|
273
|
+
512: Array.from({ length: 512 }, () => "?").join(","),
|
|
274
|
+
1024: Array.from({ length: 1024 }, () => "?").join(",")
|
|
275
|
+
};
|
|
217
276
|
function placeholders(count) {
|
|
218
|
-
|
|
277
|
+
if (count <= 0) return "";
|
|
278
|
+
return PLACEHOLDER_BUCKETS[count] ?? Array.from({ length: count }, () => "?").join(",");
|
|
219
279
|
}
|
|
220
280
|
function inListChunks(total, max) {
|
|
221
281
|
if (total <= 0) return [];
|
|
@@ -224,7 +284,8 @@ function inListChunks(total, max) {
|
|
|
224
284
|
return ladderChunkSizes(total, powMax);
|
|
225
285
|
}
|
|
226
286
|
function posixIndexPath(file) {
|
|
227
|
-
|
|
287
|
+
const p = file.includes("\\") ? file.replace(/\\/g, "/") : file;
|
|
288
|
+
return p.startsWith("./") ? p.slice(2) : p;
|
|
228
289
|
}
|
|
229
290
|
function indexedFileMatchSql(column = "file") {
|
|
230
291
|
return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
|
|
@@ -373,11 +434,13 @@ function isLockError(err) {
|
|
|
373
434
|
if (typeof code === "number" && (code === 5 || code === 6)) return true;
|
|
374
435
|
return /SQLITE_(BUSY|LOCKED)/.test(err.message);
|
|
375
436
|
}
|
|
437
|
+
var SLEEP_BUFFER;
|
|
376
438
|
function sleepSync(ms) {
|
|
377
439
|
try {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
440
|
+
if (!SLEEP_BUFFER) {
|
|
441
|
+
SLEEP_BUFFER = new Int32Array(new SharedArrayBuffer(4));
|
|
442
|
+
}
|
|
443
|
+
Atomics.wait(SLEEP_BUFFER, 0, 0, ms);
|
|
381
444
|
} catch {
|
|
382
445
|
}
|
|
383
446
|
}
|
|
@@ -453,11 +516,8 @@ function decodeVector(buf) {
|
|
|
453
516
|
if (buf.byteLength % 4 !== 0) {
|
|
454
517
|
throw new Error(`decodeVector: invalid vector byteLength ${buf.byteLength} (must be a multiple of 4)`);
|
|
455
518
|
}
|
|
456
|
-
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
457
519
|
const copy = new Float32Array(buf.byteLength / 4);
|
|
458
|
-
|
|
459
|
-
copy[i] = view.getFloat32(i * 4, true);
|
|
460
|
-
}
|
|
520
|
+
new Uint8Array(copy.buffer).set(buf);
|
|
461
521
|
return copy;
|
|
462
522
|
}
|
|
463
523
|
function reciprocalRankFusion(bm25Ranks, vectorRanks, k = RRF_K) {
|
|
@@ -480,9 +540,11 @@ import * as fs from "node:fs";
|
|
|
480
540
|
import * as path from "node:path";
|
|
481
541
|
var DB_FILE = "index.db";
|
|
482
542
|
function getAllIndexableWithStatement(stmt) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
543
|
+
const rows = stmt("SELECT id, name, signature, doc_comment FROM symbols").all();
|
|
544
|
+
return rows.map((row) => ({
|
|
545
|
+
id: row.id,
|
|
546
|
+
text: buildIndexableText(row.name, row.signature, row.doc_comment)
|
|
547
|
+
}));
|
|
486
548
|
}
|
|
487
549
|
function getMaxSymbolIdWithStatement(stmt) {
|
|
488
550
|
const rows = stmt("SELECT MAX(id) AS m FROM symbols").all();
|
|
@@ -557,6 +619,16 @@ function getIndexDbSizeBytes(indexDir) {
|
|
|
557
619
|
}
|
|
558
620
|
|
|
559
621
|
// src/codebase-index/writer-bulk-insert.ts
|
|
622
|
+
var ROW_PLACEHOLDERS_CACHE = /* @__PURE__ */ new Map();
|
|
623
|
+
function getRowPlaceholders(rowTemplate, count) {
|
|
624
|
+
const key = `${rowTemplate}\0${count}`;
|
|
625
|
+
let result = ROW_PLACEHOLDERS_CACHE.get(key);
|
|
626
|
+
if (result === void 0) {
|
|
627
|
+
result = Array.from({ length: count }, () => rowTemplate).join(", ");
|
|
628
|
+
ROW_PLACEHOLDERS_CACHE.set(key, result);
|
|
629
|
+
}
|
|
630
|
+
return result;
|
|
631
|
+
}
|
|
560
632
|
function bulkInsertSymbolsWithStatement(stmt, maxSqlVars, rows) {
|
|
561
633
|
if (rows.length === 0) return;
|
|
562
634
|
const ladder = ladderChunkSizes(rows.length, Math.max(1, Math.floor(maxSqlVars / 12)));
|
|
@@ -564,9 +636,12 @@ function bulkInsertSymbolsWithStatement(stmt, maxSqlVars, rows) {
|
|
|
564
636
|
for (const take of ladder) {
|
|
565
637
|
const chunk = rows.slice(cursor, cursor + take);
|
|
566
638
|
cursor += take;
|
|
567
|
-
const placeholders2 =
|
|
639
|
+
const placeholders2 = getRowPlaceholders(
|
|
640
|
+
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
641
|
+
chunk.length
|
|
642
|
+
);
|
|
568
643
|
const insert = stmt(
|
|
569
|
-
`INSERT INTO symbols(id, lang, kind, name, file, line, col, signature, doc_comment, scope
|
|
644
|
+
`INSERT INTO symbols(id, lang, kind, name, file, line, col, signature, doc_comment, scope)
|
|
570
645
|
VALUES ${placeholders2}`
|
|
571
646
|
);
|
|
572
647
|
const binds = [];
|
|
@@ -581,8 +656,7 @@ function bulkInsertSymbolsWithStatement(stmt, maxSqlVars, rows) {
|
|
|
581
656
|
r.col,
|
|
582
657
|
r.signature,
|
|
583
658
|
r.docComment,
|
|
584
|
-
r.scope
|
|
585
|
-
r.text
|
|
659
|
+
r.scope
|
|
586
660
|
);
|
|
587
661
|
}
|
|
588
662
|
insert.run(...binds);
|
|
@@ -595,7 +669,7 @@ function bulkInsertFtsWithStatement(stmt, maxSqlVars, ftsAvailable, rows) {
|
|
|
595
669
|
for (const take of ladder) {
|
|
596
670
|
const chunk = rows.slice(cursor, cursor + take);
|
|
597
671
|
cursor += take;
|
|
598
|
-
const placeholders2 =
|
|
672
|
+
const placeholders2 = getRowPlaceholders("(?, ?)", chunk.length);
|
|
599
673
|
const insert = stmt(`INSERT INTO symbols_fts(rowid, text) VALUES ${placeholders2}`);
|
|
600
674
|
const binds = [];
|
|
601
675
|
for (const r of chunk) binds.push(r.id, r.text);
|
|
@@ -609,7 +683,7 @@ function bulkInsertVectorsWithStatement(stmt, maxSqlVars, rows) {
|
|
|
609
683
|
for (const take of ladder) {
|
|
610
684
|
const chunk = rows.slice(cursor, cursor + take);
|
|
611
685
|
cursor += take;
|
|
612
|
-
const placeholders2 =
|
|
686
|
+
const placeholders2 = getRowPlaceholders("(?, ?)", chunk.length);
|
|
613
687
|
const insert = stmt(`INSERT INTO symbol_vectors(symbol_id, vector) VALUES ${placeholders2}`);
|
|
614
688
|
const binds = [];
|
|
615
689
|
for (const r of chunk) binds.push(r.id, r.vector);
|
|
@@ -623,7 +697,10 @@ function bulkInsertRefsWithStatement(stmt, maxSqlVars, refs) {
|
|
|
623
697
|
for (const take of ladder) {
|
|
624
698
|
const chunk = refs.slice(cursor, cursor + take);
|
|
625
699
|
cursor += take;
|
|
626
|
-
const placeholders2 =
|
|
700
|
+
const placeholders2 = getRowPlaceholders(
|
|
701
|
+
"(?, ?, ?, ?, ?, ?, ?, ?)",
|
|
702
|
+
chunk.length
|
|
703
|
+
);
|
|
627
704
|
const insert = stmt(
|
|
628
705
|
`INSERT INTO refs(from_id, to_name, to_id, call_type, line, lang, module, to_file)
|
|
629
706
|
VALUES ${placeholders2}`
|
|
@@ -649,7 +726,7 @@ function bulkInsertRefsWithStatement(stmt, maxSqlVars, refs) {
|
|
|
649
726
|
import * as fs2 from "node:fs/promises";
|
|
650
727
|
import * as path2 from "node:path";
|
|
651
728
|
function toPortablePath(file) {
|
|
652
|
-
return file.replace(/\\/g, "/");
|
|
729
|
+
return file.includes("\\") ? file.replace(/\\/g, "/") : file;
|
|
653
730
|
}
|
|
654
731
|
async function readTextIfPresent(file) {
|
|
655
732
|
try {
|
|
@@ -953,9 +1030,16 @@ function createPackageLabeller(stored) {
|
|
|
953
1030
|
function buildPackageGraphNodes(fileCounts, files, packageOf) {
|
|
954
1031
|
const pkgNodes = /* @__PURE__ */ new Map();
|
|
955
1032
|
const fileToPkg = /* @__PURE__ */ new Map();
|
|
1033
|
+
const getOrSetPkg = (file) => {
|
|
1034
|
+
let pkg = fileToPkg.get(file);
|
|
1035
|
+
if (pkg === void 0) {
|
|
1036
|
+
pkg = packageOf(file);
|
|
1037
|
+
fileToPkg.set(file, pkg);
|
|
1038
|
+
}
|
|
1039
|
+
return pkg;
|
|
1040
|
+
};
|
|
956
1041
|
for (const { file, n } of fileCounts) {
|
|
957
|
-
const pkg =
|
|
958
|
-
fileToPkg.set(file, pkg);
|
|
1042
|
+
const pkg = getOrSetPkg(file);
|
|
959
1043
|
const node = pkgNodes.get(pkg);
|
|
960
1044
|
if (node) {
|
|
961
1045
|
node.symbolCount = (node.symbolCount ?? 0) + n;
|
|
@@ -971,8 +1055,7 @@ function buildPackageGraphNodes(fileCounts, files, packageOf) {
|
|
|
971
1055
|
}
|
|
972
1056
|
}
|
|
973
1057
|
for (const { file } of files) {
|
|
974
|
-
const pkg =
|
|
975
|
-
fileToPkg.set(file, pkg);
|
|
1058
|
+
const pkg = getOrSetPkg(file);
|
|
976
1059
|
const node = pkgNodes.get(pkg);
|
|
977
1060
|
if (node) {
|
|
978
1061
|
node.fileCount = (node.fileCount ?? 0) + 1;
|
|
@@ -1004,9 +1087,11 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
|
|
|
1004
1087
|
const ensureFileNode = (file) => {
|
|
1005
1088
|
if (fileNodes.has(file)) return;
|
|
1006
1089
|
const stats = fileStats.get(file);
|
|
1090
|
+
const lastSlash = Math.max(file.lastIndexOf("/"), file.lastIndexOf("\\"));
|
|
1091
|
+
const label = lastSlash === -1 ? file : file.slice(lastSlash + 1);
|
|
1007
1092
|
fileNodes.set(file, {
|
|
1008
1093
|
id: `file:${file}`,
|
|
1009
|
-
label
|
|
1094
|
+
label,
|
|
1010
1095
|
kind: "file",
|
|
1011
1096
|
package: packageOf(file),
|
|
1012
1097
|
file,
|
|
@@ -1021,17 +1106,25 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
|
|
|
1021
1106
|
return { fileNodes, symToFile, fileStats, ensureFileNode };
|
|
1022
1107
|
}
|
|
1023
1108
|
function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
|
|
1024
|
-
const
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
)
|
|
1028
|
-
|
|
1029
|
-
const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
const
|
|
1109
|
+
const rawSet = typeof localFiles === "string" ? [localFiles] : localFiles;
|
|
1110
|
+
const local = /* @__PURE__ */ new Set();
|
|
1111
|
+
for (const f of rawSet) {
|
|
1112
|
+
local.add(f.includes("\\") ? f.replace(/\\/g, "/") : f);
|
|
1113
|
+
}
|
|
1114
|
+
const isLocal = (file) => local.has(file.includes("\\") ? file.replace(/\\/g, "/") : file);
|
|
1115
|
+
const matched = [];
|
|
1116
|
+
for (const id of relatedIds) {
|
|
1117
|
+
const s = symById.get(id);
|
|
1118
|
+
if (s) {
|
|
1119
|
+
matched.push({ ...s, isExt: !isLocal(s.file) });
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
matched.sort((a, b) => {
|
|
1123
|
+
const aExternal = a.isExt ? 1 : 0;
|
|
1124
|
+
const bExternal = b.isExt ? 1 : 0;
|
|
1033
1125
|
return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
|
|
1034
|
-
})
|
|
1126
|
+
});
|
|
1127
|
+
return matched.map((s) => ({
|
|
1035
1128
|
id: `sym:${s.id}`,
|
|
1036
1129
|
label: s.name,
|
|
1037
1130
|
kind: "symbol",
|
|
@@ -1043,7 +1136,7 @@ function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
|
|
|
1043
1136
|
line: s.line,
|
|
1044
1137
|
signature: s.signature,
|
|
1045
1138
|
scope: s.scope,
|
|
1046
|
-
external:
|
|
1139
|
+
external: s.isExt
|
|
1047
1140
|
}));
|
|
1048
1141
|
}
|
|
1049
1142
|
function addWeightedEdge(edgeMap, source, target, callType, weight) {
|
|
@@ -1089,7 +1182,7 @@ function mapWriterRefRow(row) {
|
|
|
1089
1182
|
line: row.line,
|
|
1090
1183
|
// `lang`/`module`/`to_file` are absent from the narrower column lists some
|
|
1091
1184
|
// queries select; `undefined` keeps those rows valid Refs.
|
|
1092
|
-
lang: row.lang
|
|
1185
|
+
lang: row.lang ?? void 0,
|
|
1093
1186
|
module: row.module ?? void 0,
|
|
1094
1187
|
toFile: row.to_file ?? void 0
|
|
1095
1188
|
};
|
|
@@ -1099,9 +1192,10 @@ function mapWriterRefRow(row) {
|
|
|
1099
1192
|
var MAX_SQL_VARS = 900;
|
|
1100
1193
|
function chunkedIdQuery(stmt, ids, buildSql, extraArgs = []) {
|
|
1101
1194
|
const results = [];
|
|
1195
|
+
let cursor = 0;
|
|
1102
1196
|
for (const take of inListChunks(ids.length, MAX_SQL_VARS)) {
|
|
1103
|
-
const chunk = padToInBucket(ids.slice(
|
|
1104
|
-
|
|
1197
|
+
const chunk = padToInBucket(ids.slice(cursor, cursor + take));
|
|
1198
|
+
cursor += take;
|
|
1105
1199
|
const sql = buildSql(placeholders(chunk.length));
|
|
1106
1200
|
results.push(...stmt(sql).all(...chunk, ...extraArgs));
|
|
1107
1201
|
}
|
|
@@ -1109,9 +1203,10 @@ function chunkedIdQuery(stmt, ids, buildSql, extraArgs = []) {
|
|
|
1109
1203
|
}
|
|
1110
1204
|
function chunkedIdScalar(stmt, ids, buildSql, extraArgs = []) {
|
|
1111
1205
|
let total = 0;
|
|
1206
|
+
let cursor = 0;
|
|
1112
1207
|
for (const take of inListChunks(ids.length, MAX_SQL_VARS)) {
|
|
1113
|
-
const chunk = padToInBucket(ids.slice(
|
|
1114
|
-
|
|
1208
|
+
const chunk = padToInBucket(ids.slice(cursor, cursor + take));
|
|
1209
|
+
cursor += take;
|
|
1115
1210
|
const sql = buildSql(placeholders(chunk.length));
|
|
1116
1211
|
const rows = stmt(sql).all(...chunk, ...extraArgs);
|
|
1117
1212
|
total += rows[0]?.n ?? 0;
|
|
@@ -1663,8 +1758,7 @@ function commitBatchWithStatement(stmtFn, maxSqlVars, ftsAvailable, vectorsAvail
|
|
|
1663
1758
|
col: s.col,
|
|
1664
1759
|
signature: s.signature,
|
|
1665
1760
|
docComment: s.docComment,
|
|
1666
|
-
scope: s.scope
|
|
1667
|
-
text: s.text
|
|
1761
|
+
scope: s.scope
|
|
1668
1762
|
});
|
|
1669
1763
|
if (ftsAvailable) {
|
|
1670
1764
|
ftsRows.push({
|
|
@@ -1676,7 +1770,7 @@ function commitBatchWithStatement(stmtFn, maxSqlVars, ftsAvailable, vectorsAvail
|
|
|
1676
1770
|
vectorRows.push({
|
|
1677
1771
|
id,
|
|
1678
1772
|
vector: encodeVector(
|
|
1679
|
-
embedText(
|
|
1773
|
+
embedText(buildIndexableText(s.name, s.signature, s.docComment))
|
|
1680
1774
|
)
|
|
1681
1775
|
});
|
|
1682
1776
|
}
|
|
@@ -1770,8 +1864,7 @@ var CORE_TABLES_SQL = `
|
|
|
1770
1864
|
col INTEGER NOT NULL,
|
|
1771
1865
|
signature TEXT NOT NULL DEFAULT '',
|
|
1772
1866
|
doc_comment TEXT NOT NULL DEFAULT '',
|
|
1773
|
-
scope TEXT NOT NULL DEFAULT ''
|
|
1774
|
-
text TEXT NOT NULL DEFAULT ''
|
|
1867
|
+
scope TEXT NOT NULL DEFAULT ''
|
|
1775
1868
|
);
|
|
1776
1869
|
`;
|
|
1777
1870
|
var FILE_INDEX_SQL = [
|
|
@@ -1846,7 +1939,11 @@ function getNamespaceDeclarationsWithStatement(stmtFn) {
|
|
|
1846
1939
|
}
|
|
1847
1940
|
function getFilePackagesWithStatement(stmtFn) {
|
|
1848
1941
|
const rows = stmtFn("SELECT file, package FROM files WHERE package != ''").all();
|
|
1849
|
-
|
|
1942
|
+
const map = /* @__PURE__ */ new Map();
|
|
1943
|
+
for (const row of rows) {
|
|
1944
|
+
map.set(row.file, row.package);
|
|
1945
|
+
}
|
|
1946
|
+
return map;
|
|
1850
1947
|
}
|
|
1851
1948
|
function getUnresolvedImportsWithStatement(stmtFn, maxSqlVars, onlyFiles) {
|
|
1852
1949
|
const base = `SELECT DISTINCT s.file AS fromFile, r.lang AS lang, r.module AS module
|
|
@@ -2061,8 +2158,15 @@ function buildWriterSearchWhere(query, filter) {
|
|
|
2061
2158
|
}
|
|
2062
2159
|
if (query.trim()) {
|
|
2063
2160
|
const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
2064
|
-
conditions.push(
|
|
2065
|
-
|
|
2161
|
+
conditions.push(
|
|
2162
|
+
`(${tokens.map(
|
|
2163
|
+
() => "(name LIKE ? ESCAPE '\\' OR signature LIKE ? ESCAPE '\\' OR doc_comment LIKE ? ESCAPE '\\')"
|
|
2164
|
+
).join(" OR ")})`
|
|
2165
|
+
);
|
|
2166
|
+
for (const token of tokens) {
|
|
2167
|
+
const like = `%${escapeLike(token)}%`;
|
|
2168
|
+
values.push(like, like, like);
|
|
2169
|
+
}
|
|
2066
2170
|
}
|
|
2067
2171
|
return { where: conditions.length ? `WHERE ${conditions.join(" AND ")}` : "", values };
|
|
2068
2172
|
}
|
|
@@ -2139,8 +2243,11 @@ function searchRankedWithStatement(stmtFn, searchFn, ftsAvailable, vectorsAvaila
|
|
|
2139
2243
|
const conditions = ["symbols_fts MATCH ?"];
|
|
2140
2244
|
const values = [match];
|
|
2141
2245
|
for (const shortTok of shortTokens) {
|
|
2142
|
-
|
|
2143
|
-
|
|
2246
|
+
const like = `%${escapeLike(shortTok)}%`;
|
|
2247
|
+
conditions.push(
|
|
2248
|
+
"(s.name LIKE ? ESCAPE '\\' OR s.signature LIKE ? ESCAPE '\\' OR s.doc_comment LIKE ? ESCAPE '\\')"
|
|
2249
|
+
);
|
|
2250
|
+
values.push(like, like, like);
|
|
2144
2251
|
}
|
|
2145
2252
|
if (effectiveKind) {
|
|
2146
2253
|
conditions.push("s.kind = ?");
|
|
@@ -2439,11 +2546,11 @@ var IndexStore = class _IndexStore {
|
|
|
2439
2546
|
}
|
|
2440
2547
|
];
|
|
2441
2548
|
for (const { table, columns } of expected) {
|
|
2442
|
-
const
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
)
|
|
2446
|
-
|
|
2549
|
+
const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
|
|
2550
|
+
const present = /* @__PURE__ */ new Set();
|
|
2551
|
+
for (const row of rows) {
|
|
2552
|
+
if (typeof row.name === "string") present.add(row.name);
|
|
2553
|
+
}
|
|
2447
2554
|
if (present.size === 0) continue;
|
|
2448
2555
|
for (const [name, type] of columns) {
|
|
2449
2556
|
if (present.has(name)) continue;
|
|
@@ -2451,6 +2558,31 @@ var IndexStore = class _IndexStore {
|
|
|
2451
2558
|
}
|
|
2452
2559
|
}
|
|
2453
2560
|
}
|
|
2561
|
+
/**
|
|
2562
|
+
* P4: `symbols.text` duplicated name + signature + doc_comment (~19 MB on
|
|
2563
|
+
* the live index) and is derived on demand now. In-place DROP COLUMN — no
|
|
2564
|
+
* SCHEMA_VERSION bump, so no wipe-and-reparse. Best-effort: a busy or
|
|
2565
|
+
* SQLite-without-DROP-COLUMN open leaves the column in place, where new
|
|
2566
|
+
* inserts simply default it to '' and the next open retries.
|
|
2567
|
+
*/
|
|
2568
|
+
dropDeprecatedSymbolsColumns() {
|
|
2569
|
+
if (this.getMetadata(_IndexStore.SYMBOLS_TEXT_DROPPED_KEY) !== void 0) return;
|
|
2570
|
+
const present = new Set(
|
|
2571
|
+
this.db.prepare("PRAGMA table_info(symbols)").all().flatMap(
|
|
2572
|
+
(row) => typeof row.name === "string" ? [row.name] : []
|
|
2573
|
+
)
|
|
2574
|
+
);
|
|
2575
|
+
if (present.size === 0) return;
|
|
2576
|
+
if (!present.has("text")) {
|
|
2577
|
+
this.setMetadata(_IndexStore.SYMBOLS_TEXT_DROPPED_KEY, "1");
|
|
2578
|
+
return;
|
|
2579
|
+
}
|
|
2580
|
+
try {
|
|
2581
|
+
this.db.exec("ALTER TABLE symbols DROP COLUMN text");
|
|
2582
|
+
this.setMetadata(_IndexStore.SYMBOLS_TEXT_DROPPED_KEY, "1");
|
|
2583
|
+
} catch {
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2454
2586
|
initSchema() {
|
|
2455
2587
|
this.db.exec(METADATA_TABLE_SQL);
|
|
2456
2588
|
const storedRows = this.stmt("SELECT value FROM metadata WHERE key = ?").all("version");
|
|
@@ -2476,6 +2608,7 @@ var IndexStore = class _IndexStore {
|
|
|
2476
2608
|
this.db.exec(CORE_TABLES_SQL);
|
|
2477
2609
|
this.db.exec(REFS_TABLE_SQL);
|
|
2478
2610
|
this.repairMissingColumns();
|
|
2611
|
+
this.dropDeprecatedSymbolsColumns();
|
|
2479
2612
|
for (const sql of FILE_INDEX_SQL) this.db.exec(sql);
|
|
2480
2613
|
for (const sql of SYMBOL_INDEX_SQL) this.db.exec(sql);
|
|
2481
2614
|
for (const sql of REFS_INDEX_SQL) this.db.exec(sql);
|
|
@@ -2535,6 +2668,10 @@ var IndexStore = class _IndexStore {
|
|
|
2535
2668
|
}
|
|
2536
2669
|
static NEXT_SYMBOL_ID_KEY = "next_symbol_id";
|
|
2537
2670
|
static MAX_SQL_VARS = 900;
|
|
2671
|
+
/** P2: persisted FTS-mutation churn counter — see {@link optimizeFtsIfNeeded}. */
|
|
2672
|
+
static FTS_CHURN_KEY = "fts_churn_since_maintain";
|
|
2673
|
+
/** P4: one-shot marker that the deprecated symbols.text column is gone. */
|
|
2674
|
+
static SYMBOLS_TEXT_DROPPED_KEY = "symbols_text_dropped";
|
|
2538
2675
|
ensureNextSymbolIdSeeded() {
|
|
2539
2676
|
const existing = this.stmt("SELECT value FROM metadata WHERE key = ?").get(
|
|
2540
2677
|
_IndexStore.NEXT_SYMBOL_ID_KEY
|
|
@@ -2605,8 +2742,7 @@ var IndexStore = class _IndexStore {
|
|
|
2605
2742
|
col: s.col,
|
|
2606
2743
|
signature: s.signature,
|
|
2607
2744
|
docComment: s.docComment,
|
|
2608
|
-
scope: s.scope
|
|
2609
|
-
text: s.text
|
|
2745
|
+
scope: s.scope
|
|
2610
2746
|
});
|
|
2611
2747
|
if (this.ftsAvailable) {
|
|
2612
2748
|
ftsRows.push({ id, text: buildIndexableText(s.name, s.signature, s.docComment) });
|
|
@@ -2615,7 +2751,7 @@ var IndexStore = class _IndexStore {
|
|
|
2615
2751
|
vectorRows.push({
|
|
2616
2752
|
id,
|
|
2617
2753
|
vector: encodeVector(
|
|
2618
|
-
embedText(
|
|
2754
|
+
embedText(buildIndexableText(s.name, s.signature, s.docComment))
|
|
2619
2755
|
)
|
|
2620
2756
|
});
|
|
2621
2757
|
}
|
|
@@ -2635,6 +2771,7 @@ var IndexStore = class _IndexStore {
|
|
|
2635
2771
|
vectorRows
|
|
2636
2772
|
);
|
|
2637
2773
|
}
|
|
2774
|
+
this.recordFtsChurn(symbols.length);
|
|
2638
2775
|
this.commitWriteTransaction(ownsTransaction);
|
|
2639
2776
|
return result;
|
|
2640
2777
|
} catch (err) {
|
|
@@ -2659,7 +2796,10 @@ var IndexStore = class _IndexStore {
|
|
|
2659
2796
|
"DELETE FROM symbol_vectors WHERE symbol_id IN (SELECT id FROM symbols WHERE file = ?)"
|
|
2660
2797
|
).run(file);
|
|
2661
2798
|
}
|
|
2662
|
-
|
|
2799
|
+
const deletedChanges = Number(
|
|
2800
|
+
this.stmt("DELETE FROM symbols WHERE file = ?").run(file).changes
|
|
2801
|
+
);
|
|
2802
|
+
this.recordFtsChurn(deletedChanges);
|
|
2663
2803
|
this.resolveRefsForNamesUnsafe(affectedNames);
|
|
2664
2804
|
this.commitWriteTransaction(ownsTransaction);
|
|
2665
2805
|
} catch (error) {
|
|
@@ -2687,7 +2827,10 @@ var IndexStore = class _IndexStore {
|
|
|
2687
2827
|
this.stmt("DELETE FROM refs WHERE from_id IN (SELECT id FROM symbols WHERE file = ?)").run(
|
|
2688
2828
|
file
|
|
2689
2829
|
);
|
|
2690
|
-
|
|
2830
|
+
const deletedChanges = Number(
|
|
2831
|
+
this.stmt("DELETE FROM symbols WHERE file = ?").run(file).changes
|
|
2832
|
+
);
|
|
2833
|
+
this.recordFtsChurn(deletedChanges);
|
|
2691
2834
|
this.stmt("DELETE FROM files WHERE file = ?").run(file);
|
|
2692
2835
|
this.resolveRefsForNamesUnsafe(affectedNames);
|
|
2693
2836
|
this.commitWriteTransaction(ownsTransaction);
|
|
@@ -2856,6 +2999,19 @@ var IndexStore = class _IndexStore {
|
|
|
2856
2999
|
return this.runWithRetry(() => {
|
|
2857
3000
|
const ownsTransaction = this.beginWriteTransaction();
|
|
2858
3001
|
try {
|
|
3002
|
+
const owned = options.deleteForFiles?.length ?? 0;
|
|
3003
|
+
let churnRows = entries.reduce((sum, e) => sum + e.symbols.length, 0);
|
|
3004
|
+
if (owned > 0) {
|
|
3005
|
+
let cursor = 0;
|
|
3006
|
+
for (const take of inListChunks(owned, Math.floor(_IndexStore.MAX_SQL_VARS / 4))) {
|
|
3007
|
+
const bucket = options.deleteForFiles.slice(cursor, cursor + take);
|
|
3008
|
+
cursor += take;
|
|
3009
|
+
const row = this.stmt(
|
|
3010
|
+
`SELECT COUNT(*) AS n FROM symbols WHERE file IN (${placeholders(bucket.length)})`
|
|
3011
|
+
).get(...bucket);
|
|
3012
|
+
churnRows += Number(row?.n ?? 0);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
2859
3015
|
const result = commitBatchWithStatement(
|
|
2860
3016
|
(sql) => this.stmt(sql),
|
|
2861
3017
|
_IndexStore.MAX_SQL_VARS,
|
|
@@ -2867,6 +3023,7 @@ var IndexStore = class _IndexStore {
|
|
|
2867
3023
|
entries,
|
|
2868
3024
|
options
|
|
2869
3025
|
);
|
|
3026
|
+
this.recordFtsChurn(churnRows);
|
|
2870
3027
|
this.commitWriteTransaction(ownsTransaction);
|
|
2871
3028
|
return result;
|
|
2872
3029
|
} catch (err) {
|
|
@@ -2907,7 +3064,10 @@ var IndexStore = class _IndexStore {
|
|
|
2907
3064
|
this.stmt("DELETE FROM refs WHERE from_id IN (SELECT id FROM symbols WHERE file = ?)").run(
|
|
2908
3065
|
meta.file
|
|
2909
3066
|
);
|
|
2910
|
-
|
|
3067
|
+
const deletedChanges = Number(
|
|
3068
|
+
this.stmt("DELETE FROM symbols WHERE file = ?").run(meta.file).changes
|
|
3069
|
+
);
|
|
3070
|
+
this.recordFtsChurn(deletedChanges);
|
|
2911
3071
|
this.stmt(
|
|
2912
3072
|
`INSERT INTO files(file, lang, mtime_ms, content_hash, symbol_count, last_indexed)
|
|
2913
3073
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
@@ -2939,6 +3099,54 @@ var IndexStore = class _IndexStore {
|
|
|
2939
3099
|
} catch {
|
|
2940
3100
|
}
|
|
2941
3101
|
}
|
|
3102
|
+
/**
|
|
3103
|
+
* P2: churn-gated FTS5 segment maintenance.
|
|
3104
|
+
*
|
|
3105
|
+
* FTS5 postings only compact when FTS5 itself merges them: every delete
|
|
3106
|
+
* leaves tombstone postings in the segments, and neither VACUUM nor
|
|
3107
|
+
* `PRAGMA optimize` reclaims them. Measured on the live index (2026-08-30):
|
|
3108
|
+
* one delete+reinsert cycle grew symbols_fts_data 174.9→212.8 MB, while the
|
|
3109
|
+
* FTS5 'optimize'/'rebuild' merge resets it (rebuild: 212.9→28.2 MB in
|
|
3110
|
+
* 1.26 s for 131k rows). 'optimize' is the recurring command — an
|
|
3111
|
+
* incremental merge that discards deleted docs — and only runs once churn
|
|
3112
|
+
* crosses the gate, so a clean index never pays for it.
|
|
3113
|
+
*
|
|
3114
|
+
* Follows the {@link checkpointWal} contract: best-effort, returns whether
|
|
3115
|
+
* it ran, safe to call from the daemon's single-threaded idle path.
|
|
3116
|
+
*/
|
|
3117
|
+
optimizeFtsIfNeeded(options = {}) {
|
|
3118
|
+
if (!this.ftsAvailable) return false;
|
|
3119
|
+
try {
|
|
3120
|
+
const minChurnRatio = options.minChurnRatio ?? 0.1;
|
|
3121
|
+
const minChurnRows = options.minChurnRows ?? 5e3;
|
|
3122
|
+
const churn = Number(this.getMetadata(_IndexStore.FTS_CHURN_KEY) ?? "0") || 0;
|
|
3123
|
+
const liveRows = Number(
|
|
3124
|
+
this.stmt("SELECT COUNT(*) AS n FROM symbols").get()?.n ?? 0
|
|
3125
|
+
);
|
|
3126
|
+
if (churn < Math.max(minChurnRows, liveRows * minChurnRatio)) return false;
|
|
3127
|
+
this.runWithRetry(() => {
|
|
3128
|
+
this.stmt(`INSERT INTO symbols_fts(symbols_fts) VALUES('optimize')`).run();
|
|
3129
|
+
});
|
|
3130
|
+
this.setMetadata(_IndexStore.FTS_CHURN_KEY, "0");
|
|
3131
|
+
return true;
|
|
3132
|
+
} catch {
|
|
3133
|
+
return false;
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
/**
|
|
3137
|
+
* Best-effort churn bookkeeping for {@link optimizeFtsIfNeeded}. Counts the
|
|
3138
|
+
* FTS rows a mutation inserts or deletes so the maintenance gate can fire
|
|
3139
|
+
* after real churn, not on a timer. Persisted in metadata so the counter
|
|
3140
|
+
* survives store open/close cycles in the daemon pool.
|
|
3141
|
+
*/
|
|
3142
|
+
recordFtsChurn(rows) {
|
|
3143
|
+
if (rows <= 0 || !this.ftsAvailable) return;
|
|
3144
|
+
try {
|
|
3145
|
+
const current = Number(this.getMetadata(_IndexStore.FTS_CHURN_KEY) ?? "0") || 0;
|
|
3146
|
+
this.setMetadata(_IndexStore.FTS_CHURN_KEY, String(current + rows));
|
|
3147
|
+
} catch {
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
2942
3150
|
/**
|
|
2943
3151
|
* P4.14: best-effort WAL checkpoint for idle-time maintenance.
|
|
2944
3152
|
*
|
|
@@ -3066,15 +3274,11 @@ function rotl64(x, n) {
|
|
|
3066
3274
|
const v = x & MASK64;
|
|
3067
3275
|
return (v << BigInt(n) | v >> BigInt(64 - n)) & MASK64;
|
|
3068
3276
|
}
|
|
3069
|
-
function readU64LE(
|
|
3070
|
-
|
|
3071
|
-
for (let i = 7; i >= 0; i--) {
|
|
3072
|
-
v = v << 8n | BigInt(buf[off + i] ?? 0);
|
|
3073
|
-
}
|
|
3074
|
-
return v & MASK64;
|
|
3277
|
+
function readU64LE(view, off) {
|
|
3278
|
+
return view.getBigUint64(off, true);
|
|
3075
3279
|
}
|
|
3076
|
-
function readU32LE(
|
|
3077
|
-
return
|
|
3280
|
+
function readU32LE(view, off) {
|
|
3281
|
+
return BigInt(view.getUint32(off, true));
|
|
3078
3282
|
}
|
|
3079
3283
|
function xxh64Round(acc, lane) {
|
|
3080
3284
|
return mul64(rotl64(acc + mul64(lane, PRIME64_2) & MASK64, 31), PRIME64_1);
|
|
@@ -3084,6 +3288,7 @@ function xxh64MergeRound(acc, val) {
|
|
|
3084
3288
|
}
|
|
3085
3289
|
function xxhash64Hex(buf, explicitLen) {
|
|
3086
3290
|
const length = explicitLen ?? buf.length;
|
|
3291
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
3087
3292
|
let h;
|
|
3088
3293
|
let off = 0;
|
|
3089
3294
|
if (length >= 32) {
|
|
@@ -3093,10 +3298,10 @@ function xxhash64Hex(buf, explicitLen) {
|
|
|
3093
3298
|
let v4 = 0n - PRIME64_1 & MASK64;
|
|
3094
3299
|
const end32 = length - 32;
|
|
3095
3300
|
while (off <= end32) {
|
|
3096
|
-
v1 = xxh64Round(v1, readU64LE(
|
|
3097
|
-
v2 = xxh64Round(v2, readU64LE(
|
|
3098
|
-
v3 = xxh64Round(v3, readU64LE(
|
|
3099
|
-
v4 = xxh64Round(v4, readU64LE(
|
|
3301
|
+
v1 = xxh64Round(v1, readU64LE(view, off));
|
|
3302
|
+
v2 = xxh64Round(v2, readU64LE(view, off + 8));
|
|
3303
|
+
v3 = xxh64Round(v3, readU64LE(view, off + 16));
|
|
3304
|
+
v4 = xxh64Round(v4, readU64LE(view, off + 24));
|
|
3100
3305
|
off += 32;
|
|
3101
3306
|
}
|
|
3102
3307
|
h = rotl64(v1, 1) + rotl64(v2, 7) + rotl64(v3, 12) + rotl64(v4, 18) & MASK64;
|
|
@@ -3109,12 +3314,12 @@ function xxhash64Hex(buf, explicitLen) {
|
|
|
3109
3314
|
}
|
|
3110
3315
|
h = h + BigInt(length) & MASK64;
|
|
3111
3316
|
while (off + 8 <= length) {
|
|
3112
|
-
const k1 = xxh64Round(0n, readU64LE(
|
|
3317
|
+
const k1 = xxh64Round(0n, readU64LE(view, off));
|
|
3113
3318
|
h = mul64(rotl64(h ^ k1, 27), PRIME64_1) + PRIME64_4 & MASK64;
|
|
3114
3319
|
off += 8;
|
|
3115
3320
|
}
|
|
3116
3321
|
if (off + 4 <= length) {
|
|
3117
|
-
h = mul64(rotl64(h ^ mul64(readU32LE(
|
|
3322
|
+
h = mul64(rotl64(h ^ mul64(readU32LE(view, off), PRIME64_1), 23), PRIME64_2) + PRIME64_3 & MASK64;
|
|
3118
3323
|
off += 4;
|
|
3119
3324
|
}
|
|
3120
3325
|
while (off < length) {
|
|
@@ -3188,8 +3393,10 @@ var ModuleResolver = class {
|
|
|
3188
3393
|
for (const { name, file } of namespaces) {
|
|
3189
3394
|
const lang = detectLang(file);
|
|
3190
3395
|
if (!lang) continue;
|
|
3191
|
-
const
|
|
3192
|
-
if (
|
|
3396
|
+
const norm = normalizeNamespace(name);
|
|
3397
|
+
if (!norm) continue;
|
|
3398
|
+
const key = `${languageFamily(lang)}:${norm}`;
|
|
3399
|
+
if (!this.byNamespace.has(key)) {
|
|
3193
3400
|
this.byNamespace.set(key, file);
|
|
3194
3401
|
}
|
|
3195
3402
|
}
|
|
@@ -3617,7 +3824,7 @@ var ParserWorkerPool = class {
|
|
|
3617
3824
|
*/
|
|
3618
3825
|
async reparseInline(batch, orphaned, workerId) {
|
|
3619
3826
|
try {
|
|
3620
|
-
const { parseFileContent } = await import("./parser-dispatch-
|
|
3827
|
+
const { parseFileContent } = await import("./parser-dispatch-X62UWXJS.js");
|
|
3621
3828
|
for (const item of orphaned) {
|
|
3622
3829
|
if (batch.settled) return;
|
|
3623
3830
|
try {
|
|
@@ -4406,4 +4613,4 @@ export {
|
|
|
4406
4613
|
incomingCallsService,
|
|
4407
4614
|
outgoingCallsService
|
|
4408
4615
|
};
|
|
4409
|
-
//# sourceMappingURL=chunk-
|
|
4616
|
+
//# sourceMappingURL=chunk-TFEGJDH5.js.map
|