token-goat 2.9.28 → 2.9.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -40
- package/SECURITY.md +28 -10
- package/THIRD_PARTY_NOTICES.md +40 -3
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/ort-wasm-simd-threaded.mjs +59 -0
- package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
- package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
- package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
- package/dist/{token-goat-chunk-66LODAUT.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
- package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
- package/dist/token-goat-chunk-54K3EUV3.mjs +35 -0
- package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
- package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
- package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
- package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
- package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
- package/dist/{token-goat-chunk-NILVK7XM.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -6
- package/dist/{token-goat-chunk-LEG3JNJ6.mjs → token-goat-chunk-664RTTUV.mjs} +31 -15
- package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
- package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
- package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
- package/dist/{token-goat-chunk-F7QZRIWM.mjs → token-goat-chunk-7F2UBPD3.mjs} +42 -35
- package/dist/{token-goat-chunk-CC2PYJM7.mjs → token-goat-chunk-7IN2MKDS.mjs} +718 -595
- package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
- package/dist/{token-goat-chunk-6SGLIPQB.mjs → token-goat-chunk-A3CK6N5Z.mjs} +621 -72
- package/dist/{token-goat-chunk-HXNAC4ZF.mjs → token-goat-chunk-AFLYLHDH.mjs} +48 -33
- package/dist/token-goat-chunk-AM5V6GSX.mjs +367 -0
- package/dist/{token-goat-chunk-I7CB3X4K.mjs → token-goat-chunk-APGZXSPS.mjs} +44 -148
- package/dist/{token-goat-chunk-BJBRGPBX.mjs → token-goat-chunk-ARDNEC2U.mjs} +11 -7
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
- package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
- package/dist/{token-goat-chunk-QM76S6YS.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -5
- package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
- package/dist/{token-goat-chunk-GGLEE35R.mjs → token-goat-chunk-C63JQV5K.mjs} +49 -10
- package/dist/{token-goat-chunk-RJH64KQH.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
- package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
- package/dist/token-goat-chunk-CYCEYAEO.mjs +265 -0
- package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
- package/dist/token-goat-chunk-DZX2YDPT.mjs +15 -0
- package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
- package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
- package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
- package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
- package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
- package/dist/{token-goat-chunk-6Z5ULNE5.mjs → token-goat-chunk-FBNQNSJK.mjs} +2490 -4957
- package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
- package/dist/{token-goat-chunk-XI2VFAV6.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
- package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
- package/dist/{token-goat-chunk-VE27HPIF.mjs → token-goat-chunk-GFBSN7BD.mjs} +30 -398
- package/dist/{token-goat-chunk-L45ZQRT7.mjs → token-goat-chunk-GOLEOXZP.mjs} +780 -786
- package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
- package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
- package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
- package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
- package/dist/{token-goat-chunk-CBMY2FGI.mjs → token-goat-chunk-HOJLCGDP.mjs} +17113 -15554
- package/dist/{token-goat-chunk-HUDC5GS5.mjs → token-goat-chunk-HYBFA5X3.mjs} +120 -19
- package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
- package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
- package/dist/{token-goat-chunk-UBUKHVYW.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
- package/dist/{token-goat-chunk-4JMWPWCS.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
- package/dist/{token-goat-chunk-Q4S3UQGO.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
- package/dist/{token-goat-chunk-7R2XYKC5.mjs → token-goat-chunk-JDU3EXSU.mjs} +14 -10
- package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
- package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-JN4XMLSD.mjs} +7 -4
- package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
- package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
- package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
- package/dist/{token-goat-chunk-4RN64ZND.mjs → token-goat-chunk-KWPNJBDH.mjs} +28 -3
- package/dist/token-goat-chunk-LOBGHXPB.mjs +242 -0
- package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
- package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
- package/dist/{token-goat-chunk-YWSP6IU7.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
- package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
- package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
- package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
- package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
- package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
- package/dist/{token-goat-chunk-VWZKZPSR.mjs → token-goat-chunk-PU7V3FD6.mjs} +8752 -11098
- package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
- package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
- package/dist/{token-goat-chunk-IHKZ3QNA.mjs → token-goat-chunk-QCLDAQTS.mjs} +33 -19
- package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
- package/dist/{token-goat-chunk-4STDIGYC.mjs → token-goat-chunk-RC35RBUL.mjs} +7 -5
- package/dist/{token-goat-chunk-D5ICEPSB.mjs → token-goat-chunk-RHXKCZX3.mjs} +887 -507
- package/dist/{token-goat-chunk-RSS3TLXU.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
- package/dist/{token-goat-chunk-MAMQPC43.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
- package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
- package/dist/{token-goat-chunk-EL7M26WP.mjs → token-goat-chunk-SQSSNQPE.mjs} +2100 -1442
- package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-T4FK7VOV.mjs} +3 -3
- package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
- package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
- package/dist/{token-goat-chunk-XKY4VKJ4.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
- package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
- package/dist/token-goat-chunk-VES7EL7O.mjs +205 -0
- package/dist/{token-goat-chunk-M56BWPBN.mjs → token-goat-chunk-VL3YIFHZ.mjs} +550 -49
- package/dist/{token-goat-chunk-IZXKVT4A.mjs → token-goat-chunk-VPBBTSJR.mjs} +362 -128
- package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
- package/dist/{token-goat-chunk-FSTWAOW6.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -5
- package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
- package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
- package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
- package/dist/{token-goat-chunk-6CCQDAYY.mjs → token-goat-chunk-Y776AENC.mjs} +138 -33
- package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
- package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
- package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-Z44YO3QZ.mjs} +12 -6
- package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
- package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-ZCDTCVIS.mjs} +49 -30
- package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
- package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
- package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
- package/dist/{token-goat-chunk-SJEKA7Y2.mjs → token-goat-chunk-ZQSJMO2R.mjs} +381 -201
- package/dist/token-goat-hook-client.cjs +539 -0
- package/dist/token-goat-hook-client.mjs +26 -0
- package/dist/token-goat-hook.mjs +48 -28
- package/dist/token-goat.core.mjs +10 -45
- package/docs/C4_RUNTIME_ARCHITECTURE.md +3 -3
- package/docs/cli.md +82 -47
- package/docs/install.md +58 -23
- package/docs/security.md +7 -7
- package/package.json +17 -7
- package/scripts/verify-native-dist.mjs +386 -0
- package/dist/token-goat-chunk-4JJBFT7V.mjs +0 -20
- package/dist/token-goat-chunk-5NNYIUGV.mjs +0 -143
- package/dist/token-goat-chunk-6DQNNFJ6.mjs +0 -294
- package/dist/token-goat-chunk-7MAFDRVR.mjs +0 -47
- package/dist/token-goat-chunk-BCN2YQC6.mjs +0 -32
- package/dist/token-goat-chunk-D7GHQKQD.mjs +0 -30
- package/dist/token-goat-chunk-GMOUBOX4.mjs +0 -386
- package/dist/token-goat-chunk-IFORDBGC.mjs +0 -192
- package/dist/token-goat-chunk-JXK2HQXS.mjs +0 -318
- package/dist/token-goat-chunk-L7SDVGBT.mjs +0 -430
- package/dist/token-goat-chunk-MMLMALWK.mjs +0 -1381
- package/dist/token-goat-chunk-MVSWBNMD.mjs +0 -1985
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
|
-
import {
|
|
4
|
-
registerReset
|
|
5
|
-
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
6
3
|
import {
|
|
7
4
|
Database
|
|
8
|
-
} from "./token-goat-chunk-
|
|
5
|
+
} from "./token-goat-chunk-XB5KKOCG.mjs";
|
|
6
|
+
import {
|
|
7
|
+
registerReset
|
|
8
|
+
} from "./token-goat-chunk-YZAAZU2S.mjs";
|
|
9
9
|
import {
|
|
10
|
-
SYMBOL_BODY_CHAR_CAP,
|
|
11
10
|
countContentLines,
|
|
12
|
-
dataDir,
|
|
13
11
|
ensureDirSync,
|
|
14
|
-
escapeRegExp
|
|
12
|
+
escapeRegExp
|
|
13
|
+
} from "./token-goat-chunk-GOLEOXZP.mjs";
|
|
14
|
+
import {
|
|
15
15
|
foldCase,
|
|
16
16
|
foldPath,
|
|
17
17
|
sleepSync
|
|
18
|
-
} from "./token-goat-chunk-
|
|
18
|
+
} from "./token-goat-chunk-AM5V6GSX.mjs";
|
|
19
19
|
import {
|
|
20
20
|
safeJoin
|
|
21
|
-
} from "./token-goat-chunk-
|
|
21
|
+
} from "./token-goat-chunk-FNFBKLRD.mjs";
|
|
22
|
+
import {
|
|
23
|
+
SYMBOL_BODY_CHAR_CAP,
|
|
24
|
+
dataDir
|
|
25
|
+
} from "./token-goat-chunk-VES7EL7O.mjs";
|
|
22
26
|
import {
|
|
23
27
|
init_define_import_meta_env
|
|
24
28
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -389,6 +393,13 @@ function scalaCharLiteralLength(line, index) {
|
|
|
389
393
|
return line[index + 1] !== void 0 && line[index + 1] !== "'" && line[index + 2] === "'" ? 3 : 0;
|
|
390
394
|
}
|
|
391
395
|
function stripStringLiterals(line, opts = {}) {
|
|
396
|
+
const stringFrame = (idx, delim) => {
|
|
397
|
+
const quote = line[idx];
|
|
398
|
+
const prev = line[idx - 1] ?? "";
|
|
399
|
+
const bareBraceHole = quote === '"' && (idx > 0 && prev === "$" || idx > 1 && prev === "@" && line[idx - 2] === "$" || idx > 1 && prev === "$" && line[idx - 2] === "@");
|
|
400
|
+
const plain = opts.interpolatorPrefix === true && !/[A-Za-z0-9_]/.test(prev) || opts.singleQuoteHoles === true && prev === "r" && !/[A-Za-z0-9_$]/.test(line[idx - 2] ?? "");
|
|
401
|
+
return { kind: "string", quote: delim, bareBraceHole, plain };
|
|
402
|
+
};
|
|
392
403
|
const openDelim = (idx) => {
|
|
393
404
|
const q = line[idx];
|
|
394
405
|
if (opts.tripleQuotes && line[idx + 1] === q && line[idx + 2] === q) return q + q + q;
|
|
@@ -413,9 +424,8 @@ function stripStringLiterals(line, opts = {}) {
|
|
|
413
424
|
continue;
|
|
414
425
|
}
|
|
415
426
|
if (ch === '"' || ch === "'") {
|
|
416
|
-
const bareBraceHole = ch === '"' && i > 0 && line[i - 1] === "$";
|
|
417
427
|
const delim = openDelim(i);
|
|
418
|
-
stack.push(
|
|
428
|
+
stack.push(stringFrame(i, delim));
|
|
419
429
|
out += delim;
|
|
420
430
|
i += delim.length;
|
|
421
431
|
continue;
|
|
@@ -425,15 +435,35 @@ function stripStringLiterals(line, opts = {}) {
|
|
|
425
435
|
continue;
|
|
426
436
|
}
|
|
427
437
|
if (top.kind === "hole") {
|
|
438
|
+
if (top.paren === true && (ch === "(" || ch === ")")) {
|
|
439
|
+
if (ch === "(") {
|
|
440
|
+
top.depth++;
|
|
441
|
+
out += ch;
|
|
442
|
+
} else {
|
|
443
|
+
if (top.depth > 0) {
|
|
444
|
+
top.depth--;
|
|
445
|
+
out += ch;
|
|
446
|
+
} else {
|
|
447
|
+
stack.pop();
|
|
448
|
+
out += " ";
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
i++;
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
if (top.paren === true && (ch === "{" || ch === "}")) {
|
|
455
|
+
out += ch;
|
|
456
|
+
i++;
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
428
459
|
if (opts.symbolLiterals === true && ch === "'" && scalaCharLiteralLength(line, i) === 0) {
|
|
429
460
|
out += ch;
|
|
430
461
|
i++;
|
|
431
462
|
continue;
|
|
432
463
|
}
|
|
433
464
|
if (ch === '"' || ch === "'") {
|
|
434
|
-
const bareBraceHole = ch === '"' && i > 0 && line[i - 1] === "$";
|
|
435
465
|
const delim = openDelim(i);
|
|
436
|
-
stack.push(
|
|
466
|
+
stack.push(stringFrame(i, delim));
|
|
437
467
|
out += delim;
|
|
438
468
|
i += delim.length;
|
|
439
469
|
continue;
|
|
@@ -458,6 +488,12 @@ function stripStringLiterals(line, opts = {}) {
|
|
|
458
488
|
i++;
|
|
459
489
|
continue;
|
|
460
490
|
}
|
|
491
|
+
if (opts.swiftInterpolation === true && top.quote === '"' && ch === "\\" && line[i + 1] === "(") {
|
|
492
|
+
stack.push({ kind: "hole", depth: 0, paren: true });
|
|
493
|
+
out += " ";
|
|
494
|
+
i += 2;
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
461
497
|
if (ch === "\\" && i + 1 < line.length && line[i + 1] !== "\n") {
|
|
462
498
|
out += " ";
|
|
463
499
|
i += 2;
|
|
@@ -469,7 +505,7 @@ function stripStringLiterals(line, opts = {}) {
|
|
|
469
505
|
i += top.quote.length;
|
|
470
506
|
continue;
|
|
471
507
|
}
|
|
472
|
-
if (top.quote === '"') {
|
|
508
|
+
if (!top.plain && (top.quote === '"' || opts.singleQuoteHoles === true && top.quote[0] === "'")) {
|
|
473
509
|
if (top.bareBraceHole && ch === "{") {
|
|
474
510
|
if (line[i + 1] === "{") {
|
|
475
511
|
out += " ";
|
|
@@ -1180,12 +1216,21 @@ function findMatchingBraceEndLine(content, openBraceIndex, totalLines, lineIndex
|
|
|
1180
1216
|
const rRaw = opts?.rRawStrings === true;
|
|
1181
1217
|
const tripleDelims = tripleQuoteDelimiters(opts);
|
|
1182
1218
|
const lineString = opts?.lineStringPrefix;
|
|
1219
|
+
const interpolation = opts?.interpolation;
|
|
1220
|
+
let interpolated = false;
|
|
1183
1221
|
let depth = 0;
|
|
1184
1222
|
let quote = null;
|
|
1185
1223
|
let verbatim = false;
|
|
1186
1224
|
for (let i = openBraceIndex; i < content.length; i++) {
|
|
1187
1225
|
const ch = content[i];
|
|
1188
1226
|
if (quote !== null) {
|
|
1227
|
+
if (interpolated && interpolation !== void 0) {
|
|
1228
|
+
const past = skipInterpolationAt(content, i, content.length, interpolation);
|
|
1229
|
+
if (past !== null) {
|
|
1230
|
+
i = past - 1;
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1189
1234
|
if (verbatim) {
|
|
1190
1235
|
if (ch === quote) {
|
|
1191
1236
|
if (content[i + 1] === quote) {
|
|
@@ -1248,6 +1293,7 @@ function findMatchingBraceEndLine(content, openBraceIndex, totalLines, lineIndex
|
|
|
1248
1293
|
if (ch === '"' || ch === "'" || backtick && ch === "`") {
|
|
1249
1294
|
quote = ch;
|
|
1250
1295
|
verbatim = escapes === "csharp" && ch === '"' && opensCsharpVerbatimString(content, i);
|
|
1296
|
+
interpolated = interpolation !== void 0 && opensInterpolatedString(content, i, interpolation);
|
|
1251
1297
|
continue;
|
|
1252
1298
|
}
|
|
1253
1299
|
if (ch === "{") depth++;
|
|
@@ -1281,6 +1327,7 @@ function assignBraceBlockSpans(symbols, content, opts = {}) {
|
|
|
1281
1327
|
rawStringQuotes: opts.rawStringQuotes ?? false,
|
|
1282
1328
|
tripleSingleQuote: opts.tripleSingleQuote ?? false,
|
|
1283
1329
|
tripleQuoteRunClose: opts.tripleQuoteRunClose ?? "last",
|
|
1330
|
+
...opts.interpolation === void 0 ? {} : { interpolation: opts.interpolation },
|
|
1284
1331
|
...blockComment === void 0 ? {} : { blockComment, nestedBlockComments },
|
|
1285
1332
|
...lineStringPrefix === void 0 ? {} : { lineStringPrefix },
|
|
1286
1333
|
...opts.lineCommentExceptions === void 0 ? {} : { lineCommentExceptions: opts.lineCommentExceptions }
|
|
@@ -1288,6 +1335,18 @@ function assignBraceBlockSpans(symbols, content, opts = {}) {
|
|
|
1288
1335
|
return symbols.map((sym) => {
|
|
1289
1336
|
if (sym.lineEnd !== sym.lineStart) return sym;
|
|
1290
1337
|
const nextStart = starts.find((s) => s > sym.lineStart);
|
|
1338
|
+
if (opts.expressionBodies === true) {
|
|
1339
|
+
const arrowLast = Math.min(nextStart !== void 0 ? nextStart - 1 : totalLines, sym.lineStart + BRACE_SEARCH_MAX_LINES);
|
|
1340
|
+
const arrowEnd = findArrowBodyEndLine(scanContent, lineIndex, sym.lineStart, arrowLast);
|
|
1341
|
+
if (arrowEnd !== null) {
|
|
1342
|
+
return arrowEnd <= sym.lineStart ? withWholeLineBody(sym, lines) : { ...sym, lineEnd: arrowEnd, body: lines.slice(sym.lineStart - 1, arrowEnd).join("\n") };
|
|
1343
|
+
}
|
|
1344
|
+
} else if (opts.expressionBodies === "kotlin") {
|
|
1345
|
+
const eqEnd = findKotlinEqualsBodyEndLine(scanContent, lineIndex, sym.lineStart, nextStart !== void 0 ? nextStart - 1 : totalLines);
|
|
1346
|
+
if (eqEnd !== null) {
|
|
1347
|
+
return eqEnd <= sym.lineStart ? withWholeLineBody(sym, lines) : { ...sym, lineEnd: eqEnd, body: lines.slice(sym.lineStart - 1, eqEnd).join("\n") };
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1291
1350
|
const lastSearchLine = Math.min(nextStart !== void 0 ? nextStart - 1 : totalLines, sym.lineStart + BRACE_SEARCH_MAX_LINES);
|
|
1292
1351
|
const openIndex = findBlockOpenBrace(scanContent, lineIndex, sym.lineStart, lastSearchLine, lineCommentPrefix, scanOpts);
|
|
1293
1352
|
if (openIndex === null) return sym;
|
|
@@ -1299,11 +1358,304 @@ function assignBraceBlockSpans(symbols, content, opts = {}) {
|
|
|
1299
1358
|
lineCommentPrefix,
|
|
1300
1359
|
scanOpts
|
|
1301
1360
|
);
|
|
1302
|
-
if (endLine
|
|
1361
|
+
if (endLine === sym.lineStart) return withWholeLineBody(sym, lines);
|
|
1362
|
+
if (endLine < sym.lineStart) return sym;
|
|
1303
1363
|
return { ...sym, lineEnd: endLine, body: lines.slice(sym.lineStart - 1, endLine).join("\n") };
|
|
1304
1364
|
});
|
|
1305
1365
|
}
|
|
1366
|
+
function withWholeLineBody(sym, lines) {
|
|
1367
|
+
const line = lines[sym.lineStart - 1];
|
|
1368
|
+
if (line === void 0 || sym.body.includes("{") || !line.includes("{")) return sym;
|
|
1369
|
+
return { ...sym, body: line.trimEnd() };
|
|
1370
|
+
}
|
|
1306
1371
|
var BRACE_SEARCH_MAX_LINES = 10;
|
|
1372
|
+
function skipCsharpInterpolationHole(content, i, to) {
|
|
1373
|
+
let depth = 0;
|
|
1374
|
+
for (let k = i; k < to; k++) {
|
|
1375
|
+
const lit = skipCsharpLiteral(content, k, to);
|
|
1376
|
+
if (lit !== null) {
|
|
1377
|
+
k = lit - 1;
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
const ch = content[k];
|
|
1381
|
+
if (ch === "{") depth++;
|
|
1382
|
+
else if (ch === "}" && --depth === 0) return k + 1;
|
|
1383
|
+
}
|
|
1384
|
+
return to;
|
|
1385
|
+
}
|
|
1386
|
+
function skipCsharpLiteral(content, i, to) {
|
|
1387
|
+
const first = content[i];
|
|
1388
|
+
if (first === "'") {
|
|
1389
|
+
if (content[i + 1] === "\\") {
|
|
1390
|
+
const close = content.indexOf("'", i + 3);
|
|
1391
|
+
return close === -1 || close >= to ? null : close + 1;
|
|
1392
|
+
}
|
|
1393
|
+
return content[i + 2] === "'" ? i + 3 : null;
|
|
1394
|
+
}
|
|
1395
|
+
let j = i;
|
|
1396
|
+
while ((content[j] === "$" || content[j] === "@") && j - i < 3) j++;
|
|
1397
|
+
if (content[j] !== '"') return null;
|
|
1398
|
+
const prefix = content.slice(i, j);
|
|
1399
|
+
if (j > i && /[A-Za-z0-9_]/.test(content[i - 1] ?? "")) return null;
|
|
1400
|
+
const interpolated = prefix.includes("$");
|
|
1401
|
+
const verbatim = prefix.includes("@");
|
|
1402
|
+
const run = quoteRunLength(content, j);
|
|
1403
|
+
if (run >= 3) {
|
|
1404
|
+
const end = skipRawStringQuotes(content, j + run, run);
|
|
1405
|
+
return end === -1 ? to : end;
|
|
1406
|
+
}
|
|
1407
|
+
for (let k = j + 1; k < to; k++) {
|
|
1408
|
+
const ch = content[k];
|
|
1409
|
+
if (ch === void 0) break;
|
|
1410
|
+
if (verbatim) {
|
|
1411
|
+
if (ch === '"') {
|
|
1412
|
+
if (content[k + 1] === '"') {
|
|
1413
|
+
k++;
|
|
1414
|
+
continue;
|
|
1415
|
+
}
|
|
1416
|
+
return k + 1;
|
|
1417
|
+
}
|
|
1418
|
+
} else if (ch === "\\") {
|
|
1419
|
+
k++;
|
|
1420
|
+
continue;
|
|
1421
|
+
} else if (ch === '"') return k + 1;
|
|
1422
|
+
if (interpolated) {
|
|
1423
|
+
if (ch === "{") {
|
|
1424
|
+
if (content[k + 1] === "{") {
|
|
1425
|
+
k++;
|
|
1426
|
+
continue;
|
|
1427
|
+
}
|
|
1428
|
+
k = skipCsharpInterpolationHole(content, k, to) - 1;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
return to;
|
|
1433
|
+
}
|
|
1434
|
+
function findArrowBodyEndLine(content, lineIndex, startLine, lastSearchLine) {
|
|
1435
|
+
const from = lineIndex[startLine - 1];
|
|
1436
|
+
if (from === void 0) return null;
|
|
1437
|
+
const to = lineIndex[lastSearchLine] ?? content.length;
|
|
1438
|
+
let depth = 0;
|
|
1439
|
+
let seenArrow = false;
|
|
1440
|
+
for (let i = from; i < to; i++) {
|
|
1441
|
+
const ch = content[i];
|
|
1442
|
+
if (ch === void 0) break;
|
|
1443
|
+
if (ch === "/" && content[i + 1] === "/") {
|
|
1444
|
+
while (i + 1 < to && content[i + 1] !== "\n") i++;
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
if (ch === "/" && content[i + 1] === "*") {
|
|
1448
|
+
const end = content.indexOf("*/", i + 2);
|
|
1449
|
+
if (end === -1) return null;
|
|
1450
|
+
i = end + 1;
|
|
1451
|
+
continue;
|
|
1452
|
+
}
|
|
1453
|
+
const lit = skipCsharpLiteral(content, i, to);
|
|
1454
|
+
if (lit !== null) {
|
|
1455
|
+
i = lit - 1;
|
|
1456
|
+
continue;
|
|
1457
|
+
}
|
|
1458
|
+
if (ch === "(" || ch === "[") depth++;
|
|
1459
|
+
else if (ch === ")" || ch === "]") {
|
|
1460
|
+
if (depth > 0) depth--;
|
|
1461
|
+
} else if (ch === "=" && content[i + 1] === ">" && depth === 0) {
|
|
1462
|
+
seenArrow = true;
|
|
1463
|
+
i++;
|
|
1464
|
+
} else if (ch === "{") {
|
|
1465
|
+
if (!seenArrow && depth === 0) return null;
|
|
1466
|
+
depth++;
|
|
1467
|
+
} else if (ch === "}") {
|
|
1468
|
+
if (depth === 0) return null;
|
|
1469
|
+
depth--;
|
|
1470
|
+
} else if (ch === ";" && depth === 0) {
|
|
1471
|
+
if (!seenArrow) return null;
|
|
1472
|
+
let line = startLine;
|
|
1473
|
+
for (let k = from; k < i; k++) if (content[k] === "\n") line++;
|
|
1474
|
+
return line;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
return null;
|
|
1478
|
+
}
|
|
1479
|
+
function skipKotlinTemplateHole(content, i, to) {
|
|
1480
|
+
let depth = 0;
|
|
1481
|
+
for (let k = i; k < to; k++) {
|
|
1482
|
+
const lit = skipKotlinLiteral(content, k, to);
|
|
1483
|
+
if (lit !== null) {
|
|
1484
|
+
k = lit - 1;
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
const ch = content[k];
|
|
1488
|
+
if (ch === "{") depth++;
|
|
1489
|
+
else if (ch === "}" && --depth === 0) return k + 1;
|
|
1490
|
+
}
|
|
1491
|
+
return to;
|
|
1492
|
+
}
|
|
1493
|
+
function skipKotlinLiteral(content, i, to) {
|
|
1494
|
+
const first = content[i];
|
|
1495
|
+
if (first === "'") {
|
|
1496
|
+
for (let k = i + 1; k < to && content[k] !== "\n"; k++) {
|
|
1497
|
+
if (content[k] === "\\") {
|
|
1498
|
+
k++;
|
|
1499
|
+
continue;
|
|
1500
|
+
}
|
|
1501
|
+
if (content[k] === "'") return k + 1;
|
|
1502
|
+
}
|
|
1503
|
+
return null;
|
|
1504
|
+
}
|
|
1505
|
+
if (first !== '"') return null;
|
|
1506
|
+
const triple = content.startsWith('"""', i);
|
|
1507
|
+
for (let k = i + (triple ? 3 : 1); k < to; k++) {
|
|
1508
|
+
const ch = content[k];
|
|
1509
|
+
if (triple) {
|
|
1510
|
+
if (ch === '"' && content.startsWith('"""', k)) {
|
|
1511
|
+
k += 3;
|
|
1512
|
+
while (content[k] === '"') k++;
|
|
1513
|
+
return k;
|
|
1514
|
+
}
|
|
1515
|
+
} else if (ch === "\\") {
|
|
1516
|
+
k++;
|
|
1517
|
+
continue;
|
|
1518
|
+
} else if (ch === '"') return k + 1;
|
|
1519
|
+
else if (ch === "\n") return k;
|
|
1520
|
+
if (ch === "$" && content[k + 1] === "{") k = skipKotlinTemplateHole(content, k + 1, to) - 1;
|
|
1521
|
+
}
|
|
1522
|
+
return to;
|
|
1523
|
+
}
|
|
1524
|
+
function opensInterpolatedString(content, i, lang) {
|
|
1525
|
+
const q = content[i];
|
|
1526
|
+
const prev = content[i - 1] ?? "";
|
|
1527
|
+
if (lang === "csharp") return q === '"' && (prev === "$" || prev === "@" && content[i - 2] === "$");
|
|
1528
|
+
if (lang === "scala") return q === '"' && /[A-Za-z0-9_]/.test(prev);
|
|
1529
|
+
if (lang === "dart") return !(prev === "r" && !/[A-Za-z0-9_$]/.test(content[i - 2] ?? ""));
|
|
1530
|
+
return q === '"';
|
|
1531
|
+
}
|
|
1532
|
+
function skipInterpolationAt(content, i, to, lang) {
|
|
1533
|
+
const ch = content[i];
|
|
1534
|
+
if (lang === "swift") return ch === "\\" && content[i + 1] === "(" ? skipInterpolationHole(content, i + 1, to, lang) : null;
|
|
1535
|
+
if (lang === "csharp") {
|
|
1536
|
+
if (ch !== "{") return null;
|
|
1537
|
+
return content[i + 1] === "{" ? i + 2 : skipInterpolationHole(content, i, to, lang);
|
|
1538
|
+
}
|
|
1539
|
+
return ch === "$" && content[i + 1] === "{" ? skipInterpolationHole(content, i + 1, to, lang) : null;
|
|
1540
|
+
}
|
|
1541
|
+
function skipInterpolationHole(content, i, to, lang) {
|
|
1542
|
+
const open = content[i];
|
|
1543
|
+
const close = open === "(" ? ")" : "}";
|
|
1544
|
+
let depth = 0;
|
|
1545
|
+
for (let k = i; k < to; k++) {
|
|
1546
|
+
const lit = skipNestedLiteral(content, k, to, lang);
|
|
1547
|
+
if (lit !== null) {
|
|
1548
|
+
k = lit - 1;
|
|
1549
|
+
continue;
|
|
1550
|
+
}
|
|
1551
|
+
const ch = content[k];
|
|
1552
|
+
if (ch === open) depth++;
|
|
1553
|
+
else if (ch === close && --depth === 0) return k + 1;
|
|
1554
|
+
}
|
|
1555
|
+
return to;
|
|
1556
|
+
}
|
|
1557
|
+
function skipNestedLiteral(content, i, to, lang) {
|
|
1558
|
+
const ch = content[i];
|
|
1559
|
+
if (lang === "csharp") return skipCsharpLiteral(content, i, to);
|
|
1560
|
+
if (lang === "kotlin") return skipKotlinLiteral(content, i, to);
|
|
1561
|
+
if (ch === "'" && lang === "scala") {
|
|
1562
|
+
const len = scalaCharLiteralLength(content, i);
|
|
1563
|
+
return len > 0 ? i + len : null;
|
|
1564
|
+
}
|
|
1565
|
+
if (ch !== '"' && !(ch === "'" && lang === "dart")) return null;
|
|
1566
|
+
return skipInterpolatedString(content, i, to, lang, opensInterpolatedString(content, i, lang));
|
|
1567
|
+
}
|
|
1568
|
+
function skipInterpolatedString(content, i, to, lang, interpolated) {
|
|
1569
|
+
const q = content[i];
|
|
1570
|
+
if (content.startsWith(q + q + q, i)) {
|
|
1571
|
+
const end = content.indexOf(q + q + q, i + 3);
|
|
1572
|
+
return end === -1 || end >= to ? to : end + 3;
|
|
1573
|
+
}
|
|
1574
|
+
for (let k = i + 1; k < to; k++) {
|
|
1575
|
+
const ch = content[k];
|
|
1576
|
+
if (ch === "\n") return k;
|
|
1577
|
+
if (interpolated) {
|
|
1578
|
+
const past = skipInterpolationAt(content, k, to, lang);
|
|
1579
|
+
if (past !== null) {
|
|
1580
|
+
k = past - 1;
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (ch === "\\") {
|
|
1585
|
+
k++;
|
|
1586
|
+
continue;
|
|
1587
|
+
}
|
|
1588
|
+
if (ch === q) return k + 1;
|
|
1589
|
+
}
|
|
1590
|
+
return to;
|
|
1591
|
+
}
|
|
1592
|
+
function kotlinBodyContinues(content, lastSig, ifParenClosedAt, nextLineFrom) {
|
|
1593
|
+
const c = content[lastSig];
|
|
1594
|
+
const prev = content[lastSig - 1];
|
|
1595
|
+
if (lastSig === ifParenClosedAt) return true;
|
|
1596
|
+
if (c !== void 0 && "=*/%&|,.:".includes(c)) return true;
|
|
1597
|
+
if ((c === "+" || c === "-") && prev !== c) return true;
|
|
1598
|
+
if (c === ">" && prev === "-") return true;
|
|
1599
|
+
if (/(?:^|[^A-Za-z0-9_])else$/.test(content.slice(Math.max(0, lastSig - 4), lastSig + 1))) return true;
|
|
1600
|
+
const rest = content.slice(nextLineFrom);
|
|
1601
|
+
const next = /^(?:[ \t\r]*(?:\/\/[^\n]*)?\n)*[ \t]*(\.|\?\.|\?:|&&|\|\||else\b|as\b|catch\b|finally\b)/.exec(rest);
|
|
1602
|
+
return next !== null;
|
|
1603
|
+
}
|
|
1604
|
+
function findKotlinEqualsBodyEndLine(content, lineIndex, startLine, lastLine) {
|
|
1605
|
+
const from = lineIndex[startLine - 1];
|
|
1606
|
+
if (from === void 0) return null;
|
|
1607
|
+
const to = lineIndex[lastLine] ?? content.length;
|
|
1608
|
+
let depth = 0;
|
|
1609
|
+
let seenEq = false;
|
|
1610
|
+
let line = startLine;
|
|
1611
|
+
let lastSig = -1;
|
|
1612
|
+
let ifParenClosedAt = -1;
|
|
1613
|
+
const ifParens = [];
|
|
1614
|
+
for (let i = from; i < to; i++) {
|
|
1615
|
+
const ch = content[i];
|
|
1616
|
+
if (ch === void 0) break;
|
|
1617
|
+
if (ch === "\n") {
|
|
1618
|
+
if (depth === 0) {
|
|
1619
|
+
if (!seenEq) return null;
|
|
1620
|
+
if (!kotlinBodyContinues(content, lastSig, ifParenClosedAt, i + 1)) return line;
|
|
1621
|
+
}
|
|
1622
|
+
line++;
|
|
1623
|
+
continue;
|
|
1624
|
+
}
|
|
1625
|
+
if (ch === " " || ch === " " || ch === "\r") continue;
|
|
1626
|
+
if (ch === "/" && content[i + 1] === "/") {
|
|
1627
|
+
while (i + 1 < to && content[i + 1] !== "\n") i++;
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1630
|
+
if (ch === "/" && content[i + 1] === "*") {
|
|
1631
|
+
const end = content.indexOf("*/", i + 2);
|
|
1632
|
+
if (end === -1) return null;
|
|
1633
|
+
for (let k = i; k < end; k++) if (content[k] === "\n") line++;
|
|
1634
|
+
i = end + 1;
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
const lit = skipKotlinLiteral(content, i, to);
|
|
1638
|
+
if (lit !== null) {
|
|
1639
|
+
for (let k = i; k < lit; k++) if (content[k] === "\n") line++;
|
|
1640
|
+
lastSig = lit - 1;
|
|
1641
|
+
i = lit - 1;
|
|
1642
|
+
continue;
|
|
1643
|
+
}
|
|
1644
|
+
lastSig = i;
|
|
1645
|
+
if (ch === "(" || ch === "[" || ch === "{") {
|
|
1646
|
+
if (ch === "{" && !seenEq && depth === 0) return null;
|
|
1647
|
+
ifParens.push(ch === "(" && /\bif\s*$/.test(content.slice(Math.max(from, i - 8), i)));
|
|
1648
|
+
depth++;
|
|
1649
|
+
} else if (ch === ")" || ch === "]" || ch === "}") {
|
|
1650
|
+
if (depth === 0) return null;
|
|
1651
|
+
depth--;
|
|
1652
|
+
if (ifParens.pop() === true) ifParenClosedAt = i;
|
|
1653
|
+
} else if (ch === "=" && !seenEq && depth === 0 && !"=!<>".includes(content[i - 1] ?? " ") && content[i + 1] !== "=") {
|
|
1654
|
+
seenEq = true;
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
return seenEq && depth === 0 ? line : null;
|
|
1658
|
+
}
|
|
1307
1659
|
function maskMultilineStrings(content, lang) {
|
|
1308
1660
|
let state = null;
|
|
1309
1661
|
const parts = [];
|
|
@@ -1333,6 +1685,8 @@ function findBlockOpenBrace(content, lineIndex, startLine, lastSearchLine, lineC
|
|
|
1333
1685
|
const from = lineIndex[startLine - 1];
|
|
1334
1686
|
if (from === void 0) return null;
|
|
1335
1687
|
const to = lineIndex[lastSearchLine] ?? content.length;
|
|
1688
|
+
const interpolation = opts?.interpolation;
|
|
1689
|
+
let interpolated = false;
|
|
1336
1690
|
let quote = null;
|
|
1337
1691
|
let parenDepth = 0;
|
|
1338
1692
|
let linesSeen = 0;
|
|
@@ -1342,6 +1696,13 @@ function findBlockOpenBrace(content, lineIndex, startLine, lastSearchLine, lineC
|
|
|
1342
1696
|
const ch = content[i];
|
|
1343
1697
|
if (ch === void 0) break;
|
|
1344
1698
|
if (quote !== null) {
|
|
1699
|
+
if (interpolated && interpolation !== void 0) {
|
|
1700
|
+
const past = skipInterpolationAt(content, i, to, interpolation);
|
|
1701
|
+
if (past !== null) {
|
|
1702
|
+
i = past - 1;
|
|
1703
|
+
continue;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1345
1706
|
if (verbatim) {
|
|
1346
1707
|
if (ch === quote) {
|
|
1347
1708
|
if (content[i + 1] === quote) {
|
|
@@ -1408,6 +1769,7 @@ function findBlockOpenBrace(content, lineIndex, startLine, lastSearchLine, lineC
|
|
|
1408
1769
|
if (ch === '"' || ch === "'") {
|
|
1409
1770
|
quote = ch;
|
|
1410
1771
|
verbatim = stringEscapes === "csharp" && ch === '"' && opensCsharpVerbatimString(content, i);
|
|
1772
|
+
interpolated = interpolation !== void 0 && opensInterpolatedString(content, i, interpolation);
|
|
1411
1773
|
continue;
|
|
1412
1774
|
}
|
|
1413
1775
|
if (ch === "(" || ch === "[") parenDepth++;
|
|
@@ -1972,7 +2334,7 @@ CREATE INDEX IF NOT EXISTS idx_symbols_file ON symbols(file_path);
|
|
|
1972
2334
|
CREATE INDEX IF NOT EXISTS idx_symbols_name_kind ON symbols(name, kind);
|
|
1973
2335
|
CREATE INDEX IF NOT EXISTS idx_symbols_file_folded ON symbols(TG_LOWER(file_path));
|
|
1974
2336
|
CREATE INDEX IF NOT EXISTS idx_symbols_file_name_folded ON symbols(TG_LOWER(file_path), name);
|
|
1975
|
-
-- Partial index backing checkSymbolBodySize (
|
|
2337
|
+
-- Partial index backing checkSymbolBodySize (symbol_body_probe.ts), which every SessionStart hook runs.
|
|
1976
2338
|
-- Its predicate cannot be served by any index above, so the check had to read the whole symbols
|
|
1977
2339
|
-- table -- 226 MB / 231324 rows here, 229 ms per session start, and the early-exit LIMIT 1 never
|
|
1978
2340
|
-- fires on a healthy index because there is nothing to find. Indexing the *violating* rows only
|
|
@@ -1980,7 +2342,7 @@ CREATE INDEX IF NOT EXISTS idx_symbols_file_name_folded ON symbols(TG_LOWER(file
|
|
|
1980
2342
|
-- ms, 4 KB on disk, and no measurable insert cost (-0.2%, within noise, over 40000 real rows),
|
|
1981
2343
|
-- because SQLite evaluates the predicate and skips the b-tree write for every row under the cap.
|
|
1982
2344
|
-- SQLite uses a partial index only where the query's WHERE implies the index's, so the probe in
|
|
1983
|
-
--
|
|
2345
|
+
-- symbol_body_probe.ts spells its comparison the same way and against the same constant. That makes the
|
|
1984
2346
|
-- threshold part of the stored schema -- see SYMBOL_BODY_CHAR_CAP in constants.ts for what
|
|
1985
2347
|
-- changing it requires. A query with a lower threshold correctly gets a full scan instead, so no
|
|
1986
2348
|
-- other reader can be served stale rows by this index.
|
|
@@ -2076,7 +2438,11 @@ CREATE INDEX IF NOT EXISTS idx_cache_recall_type ON cache_recall(cache_type);
|
|
|
2076
2438
|
-- picked and averaging fabrications into a measured rate is how 174 of bash_redirect's 698 rows
|
|
2077
2439
|
-- came to hold its efficacy down to 0.86% when the observed figure was 1.15%. calls_remaining is
|
|
2078
2440
|
-- the countdown of subsequent tool-use events still eligible to resolve this row before it is
|
|
2079
|
-
-- considered timed out. displayed
|
|
2441
|
+
-- considered timed out. A displayed, observable row with resolved=0 is pending: nothing has
|
|
2442
|
+
-- scored it yet. Nothing sweeps these on a clock, so a session that ends mid-window leaves its
|
|
2443
|
+
-- rows pending for good, and efficacy and suppression count only resolved rows -- counting a
|
|
2444
|
+
-- pending one as not acted on is what muted bash_redirect at 1 in 11 when its scored rows stood
|
|
2445
|
+
-- at 1 in 6. displayed=0 marks a detection that never reached the agent -- auto-
|
|
2080
2446
|
-- suppressed, or declined by a hint's own net-benefit gate -- recorded so the ledger can answer
|
|
2081
2447
|
-- how often a hint fired at all, which it previously could not: a suppressed detection left no
|
|
2082
2448
|
-- trace, so a fully-muted category was indistinguishable from one that had stopped triggering.
|
|
@@ -2313,7 +2679,7 @@ function runMigrations(conn, fromVersion, toVersion) {
|
|
|
2313
2679
|
}
|
|
2314
2680
|
}
|
|
2315
2681
|
var WAL_SWITCH_DEADLINE_MS = 15e3;
|
|
2316
|
-
function enableWalWithRetry(conn, budgetMs = WAL_SWITCH_DEADLINE_MS) {
|
|
2682
|
+
function enableWalWithRetry(conn, budgetMs = WAL_SWITCH_DEADLINE_MS, stopOn) {
|
|
2317
2683
|
const deadline = Date.now() + budgetMs;
|
|
2318
2684
|
let lastError;
|
|
2319
2685
|
for (; ; ) {
|
|
@@ -2323,55 +2689,147 @@ function enableWalWithRetry(conn, budgetMs = WAL_SWITCH_DEADLINE_MS) {
|
|
|
2323
2689
|
lastError = new Error(`got: ${String(mode)}`);
|
|
2324
2690
|
} catch (e) {
|
|
2325
2691
|
lastError = e;
|
|
2692
|
+
if (isDamagedDatabaseError(e) || stopOn?.(e) === true) throw walSwitchError(e);
|
|
2326
2693
|
}
|
|
2327
2694
|
try {
|
|
2328
2695
|
if (String(conn.pragma("journal_mode", { simple: true })).toLowerCase() === "wal") return;
|
|
2329
2696
|
} catch {
|
|
2330
2697
|
}
|
|
2331
|
-
if (Date.now() >= deadline)
|
|
2332
|
-
throw new Error(`db: failed to enable WAL mode (${lastError instanceof Error ? lastError.message : String(lastError)})`);
|
|
2333
|
-
}
|
|
2698
|
+
if (Date.now() >= deadline) throw walSwitchError(lastError);
|
|
2334
2699
|
sleepSync(25);
|
|
2335
2700
|
}
|
|
2336
2701
|
}
|
|
2337
|
-
function
|
|
2702
|
+
function isDamagedDatabaseError(e) {
|
|
2703
|
+
const code = e?.code;
|
|
2704
|
+
return typeof code === "string" && /^SQLITE_(?:NOTADB|CORRUPT)/.test(code);
|
|
2705
|
+
}
|
|
2706
|
+
function walSwitchError(lastError) {
|
|
2707
|
+
return new Error(`db: failed to enable WAL mode (${lastError instanceof Error ? lastError.message : String(lastError)})`, { cause: lastError });
|
|
2708
|
+
}
|
|
2709
|
+
function initConnection(conn, walStopOn) {
|
|
2338
2710
|
conn.pragma("busy_timeout = 15000");
|
|
2339
|
-
enableWalWithRetry(conn);
|
|
2711
|
+
enableWalWithRetry(conn, WAL_SWITCH_DEADLINE_MS, walStopOn);
|
|
2340
2712
|
conn.pragma("synchronous = NORMAL");
|
|
2341
2713
|
conn.pragma("cache_size = -32000");
|
|
2342
2714
|
conn.pragma("temp_store = MEMORY");
|
|
2343
2715
|
conn.pragma("mmap_size = 134217728");
|
|
2344
|
-
conn
|
|
2345
|
-
"TG_LOWER",
|
|
2346
|
-
{ deterministic: true },
|
|
2347
|
-
(value) => value === null ? null : foldCase(String(value))
|
|
2348
|
-
);
|
|
2716
|
+
registerTgLower(conn);
|
|
2349
2717
|
const storedVersion = Number(conn.pragma("user_version", { simple: true }));
|
|
2350
|
-
if (storedVersion > SCHEMA_VERSION)
|
|
2351
|
-
throw new Error(
|
|
2352
|
-
`db: index schema version ${storedVersion} is newer than this token-goat build supports (expected ${SCHEMA_VERSION}). Update token-goat, or delete the stale index database and let it rebuild.`
|
|
2353
|
-
);
|
|
2354
|
-
}
|
|
2718
|
+
if (storedVersion > SCHEMA_VERSION) throw newerSchemaError(storedVersion);
|
|
2355
2719
|
conn.exec(SCHEMA_SQL);
|
|
2356
2720
|
try {
|
|
2357
2721
|
conn.exec(FTS_SQL);
|
|
2358
2722
|
} catch {
|
|
2359
2723
|
}
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
`CREATE VIRTUAL TABLE IF NOT EXISTS chunk_vectors USING vec0(
|
|
2724
|
+
if (loadSqliteVec(conn)) {
|
|
2725
|
+
try {
|
|
2726
|
+
conn.exec(
|
|
2727
|
+
`CREATE VIRTUAL TABLE IF NOT EXISTS chunk_vectors USING vec0(
|
|
2365
2728
|
embedding float[384]
|
|
2366
2729
|
);`
|
|
2367
|
-
|
|
2368
|
-
|
|
2730
|
+
);
|
|
2731
|
+
} catch {
|
|
2732
|
+
}
|
|
2369
2733
|
}
|
|
2370
2734
|
if (storedVersion < SCHEMA_VERSION) {
|
|
2371
2735
|
runMigrations(conn, storedVersion, SCHEMA_VERSION);
|
|
2372
2736
|
conn.pragma(`user_version = ${SCHEMA_VERSION}`);
|
|
2373
2737
|
}
|
|
2374
2738
|
}
|
|
2739
|
+
function newerSchemaError(storedVersion) {
|
|
2740
|
+
return new Error(
|
|
2741
|
+
`db: index schema version ${storedVersion} is newer than this token-goat build supports (expected ${SCHEMA_VERSION}). Update token-goat, or delete the stale index database and let it rebuild.`
|
|
2742
|
+
);
|
|
2743
|
+
}
|
|
2744
|
+
function registerTgLower(conn) {
|
|
2745
|
+
conn.function(
|
|
2746
|
+
"TG_LOWER",
|
|
2747
|
+
{ deterministic: true },
|
|
2748
|
+
(value) => value === null ? null : foldCase(String(value))
|
|
2749
|
+
);
|
|
2750
|
+
}
|
|
2751
|
+
function loadSqliteVec(conn) {
|
|
2752
|
+
try {
|
|
2753
|
+
const sqliteVec = _require("sqlite-vec");
|
|
2754
|
+
sqliteVec.load(conn);
|
|
2755
|
+
return true;
|
|
2756
|
+
} catch {
|
|
2757
|
+
return false;
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
var _readOnlyFallback;
|
|
2761
|
+
var _readOnlyConnections = /* @__PURE__ */ new Map();
|
|
2762
|
+
function allowReadOnlyIndex(onFirstUse) {
|
|
2763
|
+
_readOnlyFallback = { onFirstUse, used: false };
|
|
2764
|
+
}
|
|
2765
|
+
function isReadOnlyDb(dbPath) {
|
|
2766
|
+
if (_readOnlyFallback === void 0) return false;
|
|
2767
|
+
try {
|
|
2768
|
+
getDb(dbPath);
|
|
2769
|
+
} catch {
|
|
2770
|
+
return false;
|
|
2771
|
+
}
|
|
2772
|
+
return _readOnlyConnections.has(connectionKey(dbPath).key);
|
|
2773
|
+
}
|
|
2774
|
+
var WRITE_ACCESS_SQLITE_CODE_RE = /^SQLITE_(?:CANTOPEN|READONLY|PERM|IOERR_ACCESS|IOERR_SHMOPEN)/;
|
|
2775
|
+
var WRITE_ACCESS_FS_CODES = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EROFS"]);
|
|
2776
|
+
function isWriteAccessError(e) {
|
|
2777
|
+
for (let cur = e, depth = 0; cur instanceof Error && depth < 4; cur = cur.cause, depth++) {
|
|
2778
|
+
const code = cur.code;
|
|
2779
|
+
if (typeof code === "string" && (WRITE_ACCESS_SQLITE_CODE_RE.test(code) || WRITE_ACCESS_FS_CODES.has(code))) return true;
|
|
2780
|
+
}
|
|
2781
|
+
return false;
|
|
2782
|
+
}
|
|
2783
|
+
function writeRefusal(resolved) {
|
|
2784
|
+
let fd;
|
|
2785
|
+
try {
|
|
2786
|
+
fd = fs2.openSync(resolved, "r+");
|
|
2787
|
+
} catch (e) {
|
|
2788
|
+
return isWriteAccessError(e) ? e : void 0;
|
|
2789
|
+
}
|
|
2790
|
+
fs2.closeSync(fd);
|
|
2791
|
+
return void 0;
|
|
2792
|
+
}
|
|
2793
|
+
function openReadOnlyAt(resolved, immutable) {
|
|
2794
|
+
const conn = new Database(resolved, { readonly: true, fileMustExist: true, immutable });
|
|
2795
|
+
try {
|
|
2796
|
+
conn.pragma("busy_timeout = 15000");
|
|
2797
|
+
return { conn, storedVersion: Number(conn.pragma("user_version", { simple: true })) };
|
|
2798
|
+
} catch (e) {
|
|
2799
|
+
try {
|
|
2800
|
+
conn.close();
|
|
2801
|
+
} catch {
|
|
2802
|
+
}
|
|
2803
|
+
throw e;
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
function openIndexReadOnly(resolved) {
|
|
2807
|
+
let opened;
|
|
2808
|
+
try {
|
|
2809
|
+
opened = openReadOnlyAt(resolved, false);
|
|
2810
|
+
} catch (e) {
|
|
2811
|
+
if (!isWriteAccessError(e)) throw e;
|
|
2812
|
+
opened = openReadOnlyAt(resolved, true);
|
|
2813
|
+
}
|
|
2814
|
+
const { conn, storedVersion } = opened;
|
|
2815
|
+
try {
|
|
2816
|
+
if (storedVersion > SCHEMA_VERSION) throw newerSchemaError(storedVersion);
|
|
2817
|
+
if (storedVersion < SCHEMA_VERSION) {
|
|
2818
|
+
throw new Error(
|
|
2819
|
+
`db: index schema version ${storedVersion} predates this token-goat build (expected ${SCHEMA_VERSION}) and cannot be upgraded without write access. Run token-goat once where its data directory is writable.`
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
registerTgLower(conn);
|
|
2823
|
+
loadSqliteVec(conn);
|
|
2824
|
+
} catch (e) {
|
|
2825
|
+
try {
|
|
2826
|
+
conn.close();
|
|
2827
|
+
} catch {
|
|
2828
|
+
}
|
|
2829
|
+
throw e;
|
|
2830
|
+
}
|
|
2831
|
+
return conn;
|
|
2832
|
+
}
|
|
2375
2833
|
function resolveDbPath(dbPath) {
|
|
2376
2834
|
if (path2.isAbsolute(dbPath)) return dbPath;
|
|
2377
2835
|
if (dbPath.includes("/") || dbPath.includes("\\")) return path2.resolve(dbPath);
|
|
@@ -2385,35 +2843,75 @@ function getDb(dbPath) {
|
|
|
2385
2843
|
const { resolved, key } = connectionKey(dbPath);
|
|
2386
2844
|
const existing = _connections.get(key);
|
|
2387
2845
|
if (existing !== void 0) return existing;
|
|
2846
|
+
const fallback = _readOnlyFallback;
|
|
2847
|
+
if (fallback !== void 0) {
|
|
2848
|
+
const readOnly = _readOnlyConnections.get(key);
|
|
2849
|
+
if (readOnly !== void 0) return readOnly;
|
|
2850
|
+
const refused = writeRefusal(resolved);
|
|
2851
|
+
if (refused !== void 0) return openReadOnlyFallback(resolved, key, fallback, refused);
|
|
2852
|
+
}
|
|
2388
2853
|
const dir = path2.dirname(resolved);
|
|
2389
2854
|
try {
|
|
2390
2855
|
ensureDirSync(dir);
|
|
2391
2856
|
} catch (e) {
|
|
2392
2857
|
if (e.code !== "EEXIST" || !fs2.existsSync(dir)) throw e;
|
|
2393
2858
|
}
|
|
2394
|
-
|
|
2859
|
+
let conn;
|
|
2395
2860
|
try {
|
|
2396
|
-
|
|
2861
|
+
conn = new Database(resolved);
|
|
2862
|
+
initConnection(conn, fallback !== void 0 ? isWriteAccessError : void 0);
|
|
2397
2863
|
} catch (e) {
|
|
2398
2864
|
try {
|
|
2399
|
-
conn
|
|
2865
|
+
conn?.close();
|
|
2400
2866
|
} catch {
|
|
2401
2867
|
}
|
|
2868
|
+
if (fallback !== void 0 && isWriteAccessError(e)) return openReadOnlyFallback(resolved, key, fallback, e);
|
|
2402
2869
|
throw e;
|
|
2403
2870
|
}
|
|
2404
2871
|
_connections.set(key, conn);
|
|
2405
2872
|
return conn;
|
|
2406
2873
|
}
|
|
2407
|
-
function
|
|
2408
|
-
|
|
2874
|
+
function openReadOnlyFallback(resolved, key, fallback, writeError) {
|
|
2875
|
+
let conn;
|
|
2876
|
+
try {
|
|
2877
|
+
conn = openIndexReadOnly(resolved);
|
|
2878
|
+
} catch (e) {
|
|
2879
|
+
throw isWriteAccessError(e) || !fs2.existsSync(resolved) ? writeError : e;
|
|
2880
|
+
}
|
|
2881
|
+
_readOnlyConnections.set(key, conn);
|
|
2882
|
+
if (!fallback.used) {
|
|
2883
|
+
fallback.used = true;
|
|
2884
|
+
fallback.onFirstUse();
|
|
2885
|
+
}
|
|
2886
|
+
return conn;
|
|
2887
|
+
}
|
|
2888
|
+
function closeDb(dbPath) {
|
|
2889
|
+
const { key } = connectionKey(dbPath);
|
|
2890
|
+
for (const cache of [_connections, _readOnlyConnections]) {
|
|
2891
|
+
const conn = cache.get(key);
|
|
2892
|
+
if (conn === void 0) continue;
|
|
2409
2893
|
try {
|
|
2410
2894
|
conn.close();
|
|
2411
2895
|
} catch {
|
|
2412
2896
|
}
|
|
2897
|
+
cache.delete(key);
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
function closeAllDbs() {
|
|
2901
|
+
for (const cache of [_connections, _readOnlyConnections]) {
|
|
2902
|
+
for (const conn of cache.values()) {
|
|
2903
|
+
try {
|
|
2904
|
+
conn.close();
|
|
2905
|
+
} catch {
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
cache.clear();
|
|
2413
2909
|
}
|
|
2414
|
-
_connections.clear();
|
|
2415
2910
|
}
|
|
2416
|
-
registerReset(closeAllDbs);
|
|
2911
|
+
registerReset(closeAllDbs, { perRequest: true });
|
|
2912
|
+
registerReset(() => {
|
|
2913
|
+
_readOnlyFallback = void 0;
|
|
2914
|
+
}, { perRequest: true });
|
|
2417
2915
|
|
|
2418
2916
|
export {
|
|
2419
2917
|
precedingDocComment,
|
|
@@ -2470,5 +2968,8 @@ export {
|
|
|
2470
2968
|
unsupportedLanguageName,
|
|
2471
2969
|
isDotenvPath,
|
|
2472
2970
|
redactIfDotenv,
|
|
2473
|
-
|
|
2971
|
+
allowReadOnlyIndex,
|
|
2972
|
+
isReadOnlyDb,
|
|
2973
|
+
getDb,
|
|
2974
|
+
closeDb
|
|
2474
2975
|
};
|