token-goat 2.6.34 → 2.6.36
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 +4 -2
- package/SECURITY.md +14 -11
- package/dist/{token-goat-chunk-L7QLEVO7.mjs → token-goat-chunk-65BKISIS.mjs} +16 -14
- package/dist/{token-goat-chunk-I6EQH27G.mjs → token-goat-chunk-CNDOJ3ZP.mjs} +2 -2
- package/dist/{token-goat-chunk-FRMEOIRU.mjs → token-goat-chunk-FRTBMRP7.mjs} +208 -13
- package/dist/{token-goat-chunk-IYYQOPY4.mjs → token-goat-chunk-IYTVE6KN.mjs} +29 -10
- package/dist/{token-goat-chunk-GXBPEQR2.mjs → token-goat-chunk-KYFJC37X.mjs} +21 -14
- package/dist/{token-goat-chunk-CKRATWCJ.mjs → token-goat-chunk-LN6OUHTV.mjs} +5 -5
- package/dist/{token-goat-chunk-WA2ER6TZ.mjs → token-goat-chunk-MGOUYAA2.mjs} +1 -1
- package/dist/{token-goat-chunk-CN7GUPX6.mjs → token-goat-chunk-UFOVM7ZN.mjs} +461 -97
- package/dist/{token-goat-chunk-7FWBSPCT.mjs → token-goat-chunk-V465YKOR.mjs} +198 -21
- package/dist/{token-goat-chunk-OA3GFKP2.mjs → token-goat-chunk-VYMGEVZS.mjs} +16 -4
- package/dist/{token-goat-hook-chunk-2ISZ4AZR.mjs → token-goat-hook-chunk-3ZDBWJDF.mjs} +1 -1
- package/dist/{token-goat-hook-chunk-6C5RN3CM.mjs → token-goat-hook-chunk-5UH54CW6.mjs} +16 -4
- package/dist/{token-goat-hook-chunk-OQML5EMA.mjs → token-goat-hook-chunk-6ODM3MP7.mjs} +16 -14
- package/dist/{token-goat-hook-chunk-6QTWMSRO.mjs → token-goat-hook-chunk-A77A26A7.mjs} +461 -97
- package/dist/{token-goat-hook-chunk-BU5OFDGQ.mjs → token-goat-hook-chunk-BDR6C6IE.mjs} +208 -13
- package/dist/{token-goat-hook-chunk-I5VM5PO5.mjs → token-goat-hook-chunk-C6GIABOX.mjs} +21 -14
- package/dist/{token-goat-hook-chunk-QTZ6YUMQ.mjs → token-goat-hook-chunk-E257IGSN.mjs} +2 -2
- package/dist/{token-goat-hook-chunk-KGLMNOGD.mjs → token-goat-hook-chunk-MW5HPEGD.mjs} +29 -10
- package/dist/{token-goat-hook-chunk-ATEGFQAU.mjs → token-goat-hook-chunk-QSCYNJ2B.mjs} +5 -5
- package/dist/{token-goat-hook-chunk-CNLMPHXT.mjs → token-goat-hook-chunk-Y2WHX2P3.mjs} +198 -21
- package/dist/token-goat-hook.mjs +5 -5
- package/dist/token-goat.core.mjs +5 -5
- package/package.json +13 -11
- package/scripts/install-git-hooks.mjs +55 -0
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
PER_FILE_COUNTERFACTUAL_CEILING,
|
|
6
6
|
SOURCE_HINT,
|
|
7
7
|
SYMBOL_BODY_CHAR_CAP,
|
|
8
|
+
assignBraceBlockSpans,
|
|
8
9
|
assignFlatEndLines,
|
|
9
10
|
atomicWriteBytes,
|
|
10
11
|
atomicWriteText,
|
|
@@ -55,6 +56,7 @@ import {
|
|
|
55
56
|
parse,
|
|
56
57
|
precedingDocComment,
|
|
57
58
|
propagateEndLinesToSymbols,
|
|
59
|
+
pushAll,
|
|
58
60
|
recordStat,
|
|
59
61
|
redactIfDotenv,
|
|
60
62
|
redactSecrets,
|
|
@@ -87,7 +89,7 @@ import {
|
|
|
87
89
|
withFileLock,
|
|
88
90
|
writeIfDifferent,
|
|
89
91
|
writeJsonSettings
|
|
90
|
-
} from "./token-goat-hook-chunk-
|
|
92
|
+
} from "./token-goat-hook-chunk-Y2WHX2P3.mjs";
|
|
91
93
|
import {
|
|
92
94
|
registerReset
|
|
93
95
|
} from "./token-goat-hook-chunk-BUOCULAM.mjs";
|
|
@@ -2474,6 +2476,7 @@ registerReset(() => {
|
|
|
2474
2476
|
});
|
|
2475
2477
|
|
|
2476
2478
|
// src/session_store.ts
|
|
2479
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
2477
2480
|
import * as fs9 from "node:fs";
|
|
2478
2481
|
import * as path8 from "node:path";
|
|
2479
2482
|
|
|
@@ -2700,9 +2703,22 @@ function sweepCacheRoots(extraRoots = []) {
|
|
|
2700
2703
|
var MAX_FILES = 500;
|
|
2701
2704
|
var SESSIONS_SUBDIR = "sessions";
|
|
2702
2705
|
var AGENT_SALT_MARKER = sanitizeIdForFilename(":agent:");
|
|
2706
|
+
var AGENT_SALT_SEPARATOR = ":agent:";
|
|
2707
|
+
var AGENT_DIGEST_CHARS = 12;
|
|
2708
|
+
var SALTED_SESSION_MAX = 64 - AGENT_SALT_MARKER.length - AGENT_DIGEST_CHARS;
|
|
2709
|
+
function saltedStemPrefix(sessionId) {
|
|
2710
|
+
return `${sanitizeIdForFilename(sessionId, SALTED_SESSION_MAX)}${AGENT_SALT_MARKER}`;
|
|
2711
|
+
}
|
|
2712
|
+
function sessionFileStem(sessionId) {
|
|
2713
|
+
const sep = sessionId.indexOf(AGENT_SALT_SEPARATOR);
|
|
2714
|
+
if (sep < 0) return sanitizeIdForFilename(sessionId, 64);
|
|
2715
|
+
const agentId = sessionId.slice(sep + AGENT_SALT_SEPARATOR.length);
|
|
2716
|
+
const digest = createHash2("sha256").update(agentId).digest("hex").slice(0, AGENT_DIGEST_CHARS);
|
|
2717
|
+
return `${saltedStemPrefix(sessionId.slice(0, sep))}${digest}`;
|
|
2718
|
+
}
|
|
2703
2719
|
function sessionPath(sessionId) {
|
|
2704
2720
|
if (!sessionId) return null;
|
|
2705
|
-
const safe =
|
|
2721
|
+
const safe = sessionFileStem(sessionId);
|
|
2706
2722
|
if (!safe) return null;
|
|
2707
2723
|
const dir = path8.join(tokenGoatHome(), SESSIONS_SUBDIR);
|
|
2708
2724
|
const candidate = path8.join(dir, `${safe}.json`);
|
|
@@ -2954,9 +2970,8 @@ function readSessionStateFile(sessionId) {
|
|
|
2954
2970
|
}
|
|
2955
2971
|
function listSiblingSessionStates(sessionId) {
|
|
2956
2972
|
if (!sessionId) return [];
|
|
2957
|
-
const
|
|
2958
|
-
if (
|
|
2959
|
-
const prefix = `${safeSessionId}${AGENT_SALT_MARKER}`;
|
|
2973
|
+
const prefix = saltedStemPrefix(sessionId);
|
|
2974
|
+
if (prefix === AGENT_SALT_MARKER) return [];
|
|
2960
2975
|
const dir = path8.join(tokenGoatHome(), SESSIONS_SUBDIR);
|
|
2961
2976
|
const out = [];
|
|
2962
2977
|
try {
|
|
@@ -3235,7 +3250,7 @@ function logHintEmission(category, sessionId, correlator, compensateSelfResolve
|
|
|
3235
3250
|
} catch {
|
|
3236
3251
|
}
|
|
3237
3252
|
}
|
|
3238
|
-
var TOKEN_GOAT_INVOCATION_RE = /(?:^|[\s;&|])token-goat(?=[\s]|$)/;
|
|
3253
|
+
var TOKEN_GOAT_INVOCATION_RE = /(?:^|[\s;&|])(?:token-goat|tg)(?=[\s]|$)/;
|
|
3239
3254
|
function commandMentionsCorrelator(command, correlator) {
|
|
3240
3255
|
let idx = command.indexOf(correlator);
|
|
3241
3256
|
while (idx !== -1) {
|
|
@@ -3442,7 +3457,7 @@ function scanForInjectionPatterns(text) {
|
|
|
3442
3457
|
var UNTRUSTED_WEB_TAG = "untrusted-web-content";
|
|
3443
3458
|
function neutralizeFenceMarkers(text, tag) {
|
|
3444
3459
|
const escapedTag = tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3445
|
-
const marker = new RegExp(`<\\s*/?\\s*${escapedTag}(
|
|
3460
|
+
const marker = new RegExp(`<\\s*/?\\s*${escapedTag}(?=[\\s/>])[^>]*>`, "gi");
|
|
3446
3461
|
return text.replace(marker, (m) => m.replace(/</g, "<").replace(/>/g, ">"));
|
|
3447
3462
|
}
|
|
3448
3463
|
function fenceUntrustedContent(text, matchedPatternNames, tag = UNTRUSTED_WEB_TAG) {
|
|
@@ -4040,7 +4055,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
|
|
|
4040
4055
|
}
|
|
4041
4056
|
|
|
4042
4057
|
// src/image_shrink.ts
|
|
4043
|
-
import { createHash as
|
|
4058
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
4044
4059
|
import * as fs12 from "node:fs";
|
|
4045
4060
|
import * as path10 from "node:path";
|
|
4046
4061
|
|
|
@@ -4258,7 +4273,7 @@ function imageShrinkCacheDir() {
|
|
|
4258
4273
|
return path10.join(tokenGoatHome(), "image_shrink_cache");
|
|
4259
4274
|
}
|
|
4260
4275
|
function shrinkCacheKey(originalPath, size, mtimeMs, quality) {
|
|
4261
|
-
return
|
|
4276
|
+
return createHash3("sha256").update(`${originalPath}:${size}:${mtimeMs}:${quality}`).digest("hex").slice(0, 16);
|
|
4262
4277
|
}
|
|
4263
4278
|
function findCachedShrink(originalPath, size, mtimeMs, quality) {
|
|
4264
4279
|
const key = shrinkCacheKey(originalPath, size, mtimeMs, quality);
|
|
@@ -4307,18 +4322,18 @@ function pruneShrinkCache() {
|
|
|
4307
4322
|
}
|
|
4308
4323
|
async function finalizeShrinkResult(result, filePath) {
|
|
4309
4324
|
const basename12 = path10.basename(filePath);
|
|
4325
|
+
const shrinkSaved = result.originalBytes - result.shrunkBytes;
|
|
4326
|
+
recordStat("image_shrink", shrinkSaved, Math.round(shrinkSaved / 4), void 0, basename12);
|
|
4310
4327
|
if (loadConfig().image_shrink.ocr_enabled) {
|
|
4311
4328
|
const ocr = await ocrImage(result.data);
|
|
4312
4329
|
if (ocr !== null && isTextHeavy(ocr, loadConfig().image_shrink.ocr_min_confidence)) {
|
|
4313
4330
|
const textBytes = Buffer.byteLength(ocr.text, "utf8");
|
|
4314
|
-
const
|
|
4315
|
-
recordStat("image_ocr",
|
|
4331
|
+
const saved = Math.max(0, result.shrunkBytes - textBytes);
|
|
4332
|
+
recordStat("image_ocr", saved, Math.round(saved / 4), void 0, basename12);
|
|
4316
4333
|
return contextOutput(formatOcrSummary(ocr, basename12, result.originalBytes));
|
|
4317
4334
|
}
|
|
4318
4335
|
}
|
|
4319
|
-
const saved = result.originalBytes - result.shrunkBytes;
|
|
4320
4336
|
const { summary, dataUrl } = formatShrinkSummary(result, basename12);
|
|
4321
|
-
recordStat("image_shrink", saved, Math.round(saved / 4), void 0, basename12);
|
|
4322
4337
|
return contextOutput(`${summary}
|
|
4323
4338
|
${dataUrl}`);
|
|
4324
4339
|
}
|
|
@@ -4562,6 +4577,12 @@ async function embedTexts(texts, modelName = DEFAULT_MODEL) {
|
|
|
4562
4577
|
`Dimension mismatch: model returned ${vec.length}-dim vector, expected ${expectedDim}`
|
|
4563
4578
|
);
|
|
4564
4579
|
}
|
|
4580
|
+
const badIndex = vec.findIndex((component) => !Number.isFinite(component));
|
|
4581
|
+
if (badIndex !== -1) {
|
|
4582
|
+
throw new Error(
|
|
4583
|
+
`Non-finite embedding component at index ${badIndex}: model returned ${String(vec[badIndex])}`
|
|
4584
|
+
);
|
|
4585
|
+
}
|
|
4565
4586
|
vecs.push(vec);
|
|
4566
4587
|
}
|
|
4567
4588
|
} finally {
|
|
@@ -4572,6 +4593,11 @@ function packVec(vec) {
|
|
|
4572
4593
|
const view = new Float32Array(vec.length);
|
|
4573
4594
|
for (const [i, val] of vec.entries()) {
|
|
4574
4595
|
view[i] = val;
|
|
4596
|
+
if (!Number.isFinite(view[i])) {
|
|
4597
|
+
throw new Error(
|
|
4598
|
+
`Non-finite embedding component at index ${i}: ${String(val)} is not representable as a 32-bit float`
|
|
4599
|
+
);
|
|
4600
|
+
}
|
|
4575
4601
|
}
|
|
4576
4602
|
return Buffer.from(view.buffer);
|
|
4577
4603
|
}
|
|
@@ -4584,7 +4610,8 @@ function splitRangeIntoChunks(filePath, lines2, rangeStart, rangeEnd, chunkSize,
|
|
|
4584
4610
|
const line = lines2[lineNo - 1] ?? "";
|
|
4585
4611
|
const lineWithNewline = line + "\n";
|
|
4586
4612
|
if (currentChunk.length + lineWithNewline.length > chunkSize && currentChunk.length > 0) {
|
|
4587
|
-
const
|
|
4613
|
+
const trimmedLength = currentChunk.trim().length;
|
|
4614
|
+
const currentChunkTooSmall = trimmedLength < MIN_CHUNK_CHARS;
|
|
4588
4615
|
if (!currentChunkTooSmall) {
|
|
4589
4616
|
chunks.push({
|
|
4590
4617
|
filePath,
|
|
@@ -4594,12 +4621,21 @@ function splitRangeIntoChunks(filePath, lines2, rangeStart, rangeEnd, chunkSize,
|
|
|
4594
4621
|
kind
|
|
4595
4622
|
});
|
|
4596
4623
|
}
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4624
|
+
let overlapChars = 0;
|
|
4625
|
+
let computedOverlapStart = currentLine;
|
|
4626
|
+
while (computedOverlapStart > rangeStart) {
|
|
4627
|
+
const candidateChars = (lines2[computedOverlapStart - 2] ?? "").length + 1;
|
|
4628
|
+
if (overlapChars + candidateChars > overlap) break;
|
|
4629
|
+
overlapChars += candidateChars;
|
|
4630
|
+
computedOverlapStart--;
|
|
4631
|
+
}
|
|
4632
|
+
const droppedChunkHadContent = currentChunkTooSmall && trimmedLength > 0;
|
|
4633
|
+
const overlapStart = droppedChunkHadContent ? Math.min(computedOverlapStart, startLine) : computedOverlapStart;
|
|
4634
|
+
if (overlapStart !== startLine) {
|
|
4635
|
+
const overlapText = lines2.slice(overlapStart - 1, currentLine - 1).join("\n");
|
|
4636
|
+
currentChunk = overlapText + "\n";
|
|
4637
|
+
startLine = overlapStart;
|
|
4638
|
+
}
|
|
4603
4639
|
}
|
|
4604
4640
|
currentChunk += lineWithNewline;
|
|
4605
4641
|
currentLine++;
|
|
@@ -4748,7 +4784,7 @@ async function upsertChunks(db, chunks) {
|
|
|
4748
4784
|
insertChunkVector(vectorInsertStmt, chunkResult.lastInsertRowid, embedding);
|
|
4749
4785
|
}
|
|
4750
4786
|
});
|
|
4751
|
-
tx();
|
|
4787
|
+
tx.immediate();
|
|
4752
4788
|
return "embedded";
|
|
4753
4789
|
}
|
|
4754
4790
|
var BACKFILL_MULTIPLIER = 3;
|
|
@@ -4772,7 +4808,7 @@ function fetchScopedHits(db, queryVec, k, maxDistance, rootDir) {
|
|
|
4772
4808
|
if (!row) {
|
|
4773
4809
|
continue;
|
|
4774
4810
|
}
|
|
4775
|
-
if (row.distance <= maxDistance) {
|
|
4811
|
+
if (typeof row.distance === "number" && Number.isFinite(row.distance) && row.distance <= maxDistance) {
|
|
4776
4812
|
const chunk = scopeParams !== void 0 ? chunkStmt.get(row.rowid, ...scopeParams) : chunkStmt.get(row.rowid);
|
|
4777
4813
|
if (chunk) {
|
|
4778
4814
|
hits.push({
|
|
@@ -6042,9 +6078,9 @@ var MONITORING_COMMAND_PATTERNS = [
|
|
|
6042
6078
|
recallHint: "--tail 50"
|
|
6043
6079
|
},
|
|
6044
6080
|
// token-goat section/outline/symbol repeat calls — output is stable until the file changes
|
|
6045
|
-
{ pattern: /^token-goat\s+section\s+["'][^"']+["']/, recallHint: "" },
|
|
6046
|
-
{ pattern: /^token-goat\s+outline\s+\S+/, recallHint: "" },
|
|
6047
|
-
{ pattern: /^token-goat\s+symbol\s+\S+/, recallHint: "" }
|
|
6081
|
+
{ pattern: /^(?:token-goat|tg)\s+section\s+["'][^"']+["']/, recallHint: "" },
|
|
6082
|
+
{ pattern: /^(?:token-goat|tg)\s+outline\s+\S+/, recallHint: "" },
|
|
6083
|
+
{ pattern: /^(?:token-goat|tg)\s+symbol\s+\S+/, recallHint: "" }
|
|
6048
6084
|
];
|
|
6049
6085
|
function isPsMultilineSystemQuery(cmd) {
|
|
6050
6086
|
if (!/^(?:powershell(?:\.exe)?|pwsh(?:\.exe)?)\s+/i.test(cmd)) return false;
|
|
@@ -9340,7 +9376,12 @@ function decodeZipEntry(entries, entryPath) {
|
|
|
9340
9376
|
async function parseOoxmlPart(xmlText2) {
|
|
9341
9377
|
const fxp = await loadXmlParser();
|
|
9342
9378
|
if (!fxp) throw new Error("fast-xml-parser is not installed; run `npm install fast-xml-parser` to enable this command");
|
|
9343
|
-
const parser = new fxp.XMLParser({
|
|
9379
|
+
const parser = new fxp.XMLParser({
|
|
9380
|
+
ignoreAttributes: false,
|
|
9381
|
+
preserveOrder: false,
|
|
9382
|
+
trimValues: false,
|
|
9383
|
+
parseTagValue: false
|
|
9384
|
+
});
|
|
9344
9385
|
return parser.parse(xmlText2);
|
|
9345
9386
|
}
|
|
9346
9387
|
function pushTextValue(runs, val) {
|
|
@@ -9386,7 +9427,7 @@ function collectElements(node, tag) {
|
|
|
9386
9427
|
const obj = n;
|
|
9387
9428
|
for (const [key, val] of Object.entries(obj)) {
|
|
9388
9429
|
if (key === tag) {
|
|
9389
|
-
if (Array.isArray(val)) out
|
|
9430
|
+
if (Array.isArray(val)) pushAll(out, val);
|
|
9390
9431
|
else out.push(val);
|
|
9391
9432
|
} else if (val !== null && typeof val === "object") {
|
|
9392
9433
|
walk(val);
|
|
@@ -9765,28 +9806,257 @@ function formatCsvProfile(profiles) {
|
|
|
9765
9806
|
}).join("\n\n");
|
|
9766
9807
|
}
|
|
9767
9808
|
|
|
9768
|
-
// src/
|
|
9769
|
-
var
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
9809
|
+
// src/xlsx_reader.ts
|
|
9810
|
+
var EMPTY_CELL = Object.freeze({ value: null, text: "" });
|
|
9811
|
+
function asArray(val) {
|
|
9812
|
+
if (val === void 0 || val === null) return [];
|
|
9813
|
+
if (Array.isArray(val)) return val.filter((v) => v !== null && typeof v === "object");
|
|
9814
|
+
if (typeof val === "object") return [val];
|
|
9815
|
+
return [];
|
|
9816
|
+
}
|
|
9817
|
+
function textOf(node) {
|
|
9818
|
+
if (node === void 0 || node === null) return "";
|
|
9819
|
+
if (typeof node === "string") return node;
|
|
9820
|
+
if (typeof node === "number" || typeof node === "boolean") return String(node);
|
|
9821
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
9822
|
+
const t = node["#text"];
|
|
9823
|
+
return t === void 0 ? "" : String(t);
|
|
9824
|
+
}
|
|
9825
|
+
function attr(node, name) {
|
|
9826
|
+
if (node === void 0) return void 0;
|
|
9827
|
+
const v = node[`@_${name}`];
|
|
9828
|
+
return v === void 0 || v === null ? void 0 : String(v);
|
|
9829
|
+
}
|
|
9830
|
+
function isTruthyAttr(v) {
|
|
9831
|
+
return v === "1" || v === "true";
|
|
9832
|
+
}
|
|
9833
|
+
function refToColumn(ref2) {
|
|
9834
|
+
let n = 0;
|
|
9835
|
+
for (const ch of ref2) {
|
|
9836
|
+
const code = ch.toUpperCase().charCodeAt(0);
|
|
9837
|
+
if (code < 65 || code > 90) break;
|
|
9838
|
+
n = n * 26 + (code - 64);
|
|
9839
|
+
}
|
|
9840
|
+
return n;
|
|
9777
9841
|
}
|
|
9778
|
-
|
|
9779
|
-
const
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9842
|
+
function refToRow(ref2) {
|
|
9843
|
+
const m = /(\d+)\s*$/.exec(ref2);
|
|
9844
|
+
return m ? parseInt(m[1], 10) : 0;
|
|
9845
|
+
}
|
|
9846
|
+
var BUILTIN_DATE_FORMAT_IDS = /* @__PURE__ */ new Set([14, 15, 16, 17, 18, 19, 20, 21, 22, 45, 46, 47]);
|
|
9847
|
+
function formatCodeIsDate(formatCode) {
|
|
9848
|
+
const stripped = formatCode.replace(/"[^"]*"/g, "").replace(/\[[^\]]*\]/g, "").replace(/\\./g, "");
|
|
9849
|
+
return /[ymdhs]/i.test(stripped);
|
|
9850
|
+
}
|
|
9851
|
+
function serialToDate(serial, date1904) {
|
|
9852
|
+
if (date1904) return new Date(Date.UTC(1904, 0, 1) + Math.round(serial * 864e5));
|
|
9853
|
+
const adjusted = serial >= 61 ? serial - 1 : serial;
|
|
9854
|
+
return new Date(Date.UTC(1899, 11, 31) + Math.round(adjusted * 864e5));
|
|
9855
|
+
}
|
|
9856
|
+
function numberToText(n) {
|
|
9857
|
+
return String(n);
|
|
9858
|
+
}
|
|
9859
|
+
function parseStyles(xml, parsed) {
|
|
9860
|
+
if (xml === null || parsed === null || typeof parsed !== "object") return { dateStyles: [] };
|
|
9861
|
+
const sheet = parsed["styleSheet"];
|
|
9862
|
+
if (sheet === void 0 || sheet === null || typeof sheet !== "object") return { dateStyles: [] };
|
|
9863
|
+
const root = sheet;
|
|
9864
|
+
const customDateFormats = /* @__PURE__ */ new Set();
|
|
9865
|
+
for (const fmt of asArray(root["numFmts"]?.["numFmt"])) {
|
|
9866
|
+
const id = Number(attr(fmt, "numFmtId"));
|
|
9867
|
+
const code = attr(fmt, "formatCode");
|
|
9868
|
+
if (Number.isFinite(id) && code !== void 0 && formatCodeIsDate(code)) customDateFormats.add(id);
|
|
9869
|
+
}
|
|
9870
|
+
const dateStyles = [];
|
|
9871
|
+
for (const xf of asArray(root["cellXfs"]?.["xf"])) {
|
|
9872
|
+
const id = Number(attr(xf, "numFmtId") ?? "0");
|
|
9873
|
+
dateStyles.push(Number.isFinite(id) && (BUILTIN_DATE_FORMAT_IDS.has(id) || customDateFormats.has(id)));
|
|
9874
|
+
}
|
|
9875
|
+
return { dateStyles };
|
|
9876
|
+
}
|
|
9877
|
+
function parseSharedStrings(parsed) {
|
|
9878
|
+
if (parsed === null || typeof parsed !== "object") return [];
|
|
9879
|
+
const sst = parsed["sst"];
|
|
9880
|
+
if (sst === void 0 || sst === null || typeof sst !== "object") return [];
|
|
9881
|
+
return asArray(sst["si"]).map((si) => {
|
|
9882
|
+
if (si["t"] !== void 0) return textOf(si["t"]);
|
|
9883
|
+
const runs = asArray(si["r"]);
|
|
9884
|
+
if (runs.length > 0) return runs.map((r) => textOf(r["t"])).join("");
|
|
9885
|
+
return "";
|
|
9886
|
+
});
|
|
9887
|
+
}
|
|
9888
|
+
function parseWorkbookRels(parsed) {
|
|
9889
|
+
const out = /* @__PURE__ */ new Map();
|
|
9890
|
+
if (parsed === null || typeof parsed !== "object") return out;
|
|
9891
|
+
const rels = parsed["Relationships"];
|
|
9892
|
+
if (rels === void 0 || rels === null || typeof rels !== "object") return out;
|
|
9893
|
+
for (const rel of asArray(rels["Relationship"])) {
|
|
9894
|
+
const id = attr(rel, "Id");
|
|
9895
|
+
const target = attr(rel, "Target");
|
|
9896
|
+
if (id === void 0 || target === void 0) continue;
|
|
9897
|
+
const normalized = target.startsWith("/") ? target.slice(1) : `xl/${target.replace(/^\.\//, "")}`;
|
|
9898
|
+
out.set(id, normalized);
|
|
9899
|
+
}
|
|
9900
|
+
return out;
|
|
9901
|
+
}
|
|
9902
|
+
function buildCell(c, shared, styles, date1904) {
|
|
9903
|
+
const type = attr(c, "t") ?? "n";
|
|
9904
|
+
const styleIdx = Number(attr(c, "s") ?? "-1");
|
|
9905
|
+
const isDateStyle = Number.isInteger(styleIdx) && styleIdx >= 0 && styles.dateStyles[styleIdx] === true;
|
|
9906
|
+
const hasV = c["v"] !== void 0;
|
|
9907
|
+
const hasIs = c["is"] !== void 0;
|
|
9908
|
+
const fNode = c["f"];
|
|
9909
|
+
const formula = fNode === void 0 ? "" : textOf(fNode);
|
|
9910
|
+
if (!hasV && !hasIs && formula === "") return null;
|
|
9911
|
+
let raw;
|
|
9912
|
+
let text;
|
|
9913
|
+
if (type === "s") {
|
|
9914
|
+
const idx = Number(textOf(c["v"]));
|
|
9915
|
+
const s = Number.isInteger(idx) ? shared[idx] ?? "" : "";
|
|
9916
|
+
raw = s;
|
|
9917
|
+
text = s;
|
|
9918
|
+
} else if (type === "inlineStr") {
|
|
9919
|
+
const isNode = c["is"];
|
|
9920
|
+
const s = isNode !== void 0 && isNode !== null && typeof isNode === "object" ? (() => {
|
|
9921
|
+
const node = isNode;
|
|
9922
|
+
if (node["t"] !== void 0) return textOf(node["t"]);
|
|
9923
|
+
return asArray(node["r"]).map((r) => textOf(r["t"])).join("");
|
|
9924
|
+
})() : textOf(isNode);
|
|
9925
|
+
raw = s;
|
|
9926
|
+
text = s;
|
|
9927
|
+
} else if (type === "str") {
|
|
9928
|
+
const s = textOf(c["v"]);
|
|
9929
|
+
raw = s;
|
|
9930
|
+
text = s;
|
|
9931
|
+
} else if (type === "b") {
|
|
9932
|
+
const b = textOf(c["v"]).trim() === "1";
|
|
9933
|
+
raw = b;
|
|
9934
|
+
text = b ? "TRUE" : "FALSE";
|
|
9935
|
+
} else if (type === "e") {
|
|
9936
|
+
const e = textOf(c["v"]);
|
|
9937
|
+
raw = { error: e };
|
|
9938
|
+
text = e;
|
|
9939
|
+
} else {
|
|
9940
|
+
const n = Number(textOf(c["v"]));
|
|
9941
|
+
if (!Number.isFinite(n)) {
|
|
9942
|
+
raw = null;
|
|
9943
|
+
text = "";
|
|
9944
|
+
} else if (isDateStyle) {
|
|
9945
|
+
const d = serialToDate(n, date1904);
|
|
9946
|
+
raw = d;
|
|
9947
|
+
text = d.toISOString();
|
|
9948
|
+
} else {
|
|
9949
|
+
raw = n;
|
|
9950
|
+
text = numberToText(n);
|
|
9951
|
+
}
|
|
9952
|
+
}
|
|
9953
|
+
if (formula !== "") return { value: { formula, result: raw }, text, formula };
|
|
9954
|
+
return { value: raw, text };
|
|
9955
|
+
}
|
|
9956
|
+
function parseSheet(parsed, shared, styles, date1904) {
|
|
9957
|
+
const cells = /* @__PURE__ */ new Map();
|
|
9958
|
+
let rowCount = 0;
|
|
9959
|
+
let columnCount = 0;
|
|
9960
|
+
let populatedRows = 0;
|
|
9961
|
+
if (parsed === null || typeof parsed !== "object") return { cells, rowCount, columnCount, populatedRows };
|
|
9962
|
+
const ws = parsed["worksheet"];
|
|
9963
|
+
if (ws === void 0 || ws === null || typeof ws !== "object") return { cells, rowCount, columnCount, populatedRows };
|
|
9964
|
+
const sheetData = ws["sheetData"];
|
|
9965
|
+
if (sheetData === void 0 || sheetData === null || typeof sheetData !== "object") {
|
|
9966
|
+
return { cells, rowCount, columnCount, populatedRows };
|
|
9967
|
+
}
|
|
9968
|
+
let fallbackRow = 0;
|
|
9969
|
+
for (const row of asArray(sheetData["row"])) {
|
|
9970
|
+
const declaredRow = Number(attr(row, "r"));
|
|
9971
|
+
const rowIdx = Number.isInteger(declaredRow) && declaredRow > 0 ? declaredRow : fallbackRow + 1;
|
|
9972
|
+
fallbackRow = rowIdx;
|
|
9973
|
+
let fallbackCol = 0;
|
|
9974
|
+
const rowCells = /* @__PURE__ */ new Map();
|
|
9975
|
+
for (const c of asArray(row["c"])) {
|
|
9976
|
+
const ref2 = attr(c, "r");
|
|
9977
|
+
const declaredCol = ref2 === void 0 ? 0 : refToColumn(ref2);
|
|
9978
|
+
const colIdx = declaredCol > 0 ? declaredCol : fallbackCol + 1;
|
|
9979
|
+
fallbackCol = colIdx;
|
|
9980
|
+
const cell = buildCell(c, shared, styles, date1904);
|
|
9981
|
+
if (cell === null) continue;
|
|
9982
|
+
rowCells.set(colIdx, cell);
|
|
9983
|
+
if (colIdx > columnCount) columnCount = colIdx;
|
|
9984
|
+
}
|
|
9985
|
+
if (rowCells.size === 0) continue;
|
|
9986
|
+
cells.set(rowIdx, rowCells);
|
|
9987
|
+
populatedRows++;
|
|
9988
|
+
if (rowIdx > rowCount) rowCount = rowIdx;
|
|
9989
|
+
}
|
|
9990
|
+
return { cells, rowCount, columnCount, populatedRows };
|
|
9991
|
+
}
|
|
9992
|
+
function makeWorksheet(name, data) {
|
|
9993
|
+
function getRow(r) {
|
|
9994
|
+
const rowCells = data.cells.get(r);
|
|
9995
|
+
return {
|
|
9996
|
+
get values() {
|
|
9997
|
+
const out = [];
|
|
9998
|
+
if (rowCells !== void 0) for (const [col, cell] of rowCells) out[col] = cell.value;
|
|
9999
|
+
return out;
|
|
10000
|
+
},
|
|
10001
|
+
eachCell(opts, cb) {
|
|
10002
|
+
if (opts.includeEmpty) {
|
|
10003
|
+
let maxCol = 0;
|
|
10004
|
+
if (rowCells !== void 0) {
|
|
10005
|
+
for (const c of rowCells.keys()) if (c > maxCol) maxCol = c;
|
|
10006
|
+
}
|
|
10007
|
+
for (let c = 1; c <= maxCol; c++) cb(rowCells?.get(c) ?? EMPTY_CELL, c);
|
|
10008
|
+
return;
|
|
10009
|
+
}
|
|
10010
|
+
if (rowCells === void 0) return;
|
|
10011
|
+
for (const col of [...rowCells.keys()].sort((a, b) => a - b)) cb(rowCells.get(col), col);
|
|
10012
|
+
}
|
|
10013
|
+
};
|
|
10014
|
+
}
|
|
10015
|
+
return {
|
|
10016
|
+
name,
|
|
10017
|
+
rowCount: data.rowCount,
|
|
10018
|
+
columnCount: data.columnCount,
|
|
10019
|
+
actualRowCount: data.populatedRows,
|
|
10020
|
+
getRow,
|
|
10021
|
+
getCell(addr) {
|
|
10022
|
+
return data.cells.get(refToRow(addr))?.get(refToColumn(addr)) ?? EMPTY_CELL;
|
|
10023
|
+
}
|
|
10024
|
+
};
|
|
10025
|
+
}
|
|
10026
|
+
async function readXlsxWorkbook(filePath) {
|
|
10027
|
+
const entries = await readOoxmlZip(filePath, ".xlsx");
|
|
10028
|
+
const workbookXml = decodeZipEntry(entries, "xl/workbook.xml");
|
|
10029
|
+
if (workbookXml === null) throw new Error(`not a valid .xlsx file: ${filePath}`);
|
|
10030
|
+
const workbookRoot = await parseOoxmlPart(workbookXml);
|
|
10031
|
+
const wbNode = workbookRoot?.["workbook"];
|
|
10032
|
+
if (wbNode === void 0 || wbNode === null || typeof wbNode !== "object") {
|
|
10033
|
+
throw new Error(`not a valid .xlsx file: ${filePath}`);
|
|
10034
|
+
}
|
|
10035
|
+
const wb = wbNode;
|
|
10036
|
+
const date1904 = isTruthyAttr(attr(wb["workbookPr"], "date1904"));
|
|
10037
|
+
const relsXml = decodeZipEntry(entries, "xl/_rels/workbook.xml.rels");
|
|
10038
|
+
const rels = parseWorkbookRels(relsXml === null ? null : await parseOoxmlPart(relsXml));
|
|
10039
|
+
const sharedXml = decodeZipEntry(entries, "xl/sharedStrings.xml");
|
|
10040
|
+
const shared = sharedXml === null ? [] : parseSharedStrings(await parseOoxmlPart(sharedXml));
|
|
10041
|
+
const stylesXml = decodeZipEntry(entries, "xl/styles.xml");
|
|
10042
|
+
const styles = parseStyles(stylesXml, stylesXml === null ? null : await parseOoxmlPart(stylesXml));
|
|
10043
|
+
const worksheets = [];
|
|
10044
|
+
for (const sheet of asArray(wb["sheets"]?.["sheet"])) {
|
|
10045
|
+
const name = attr(sheet, "name") ?? "";
|
|
10046
|
+
const rid = attr(sheet, "r:id") ?? attr(sheet, "relationshipId");
|
|
10047
|
+
const partPath = rid === void 0 ? void 0 : rels.get(rid);
|
|
10048
|
+
const sheetXml = partPath === void 0 ? null : decodeZipEntry(entries, partPath);
|
|
10049
|
+
const data = sheetXml === null ? { cells: /* @__PURE__ */ new Map(), rowCount: 0, columnCount: 0, populatedRows: 0 } : parseSheet(await parseOoxmlPart(sheetXml), shared, styles, date1904);
|
|
10050
|
+
worksheets.push(makeWorksheet(name, data));
|
|
9787
10051
|
}
|
|
9788
|
-
return
|
|
10052
|
+
return {
|
|
10053
|
+
worksheets,
|
|
10054
|
+
getWorksheet: (name) => worksheets.find((ws) => ws.name === name)
|
|
10055
|
+
};
|
|
9789
10056
|
}
|
|
10057
|
+
|
|
10058
|
+
// src/xlsx_extract.ts
|
|
10059
|
+
var loadWorkbook = readXlsxWorkbook;
|
|
9790
10060
|
function requireSheet(wb, sheetName) {
|
|
9791
10061
|
const ws = wb.getWorksheet(sheetName);
|
|
9792
10062
|
if (ws === void 0) {
|
|
@@ -11361,7 +11631,7 @@ function extractLua(content, filePath) {
|
|
|
11361
11631
|
symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200)));
|
|
11362
11632
|
}
|
|
11363
11633
|
if (!lineClosesItself(stripped)) {
|
|
11364
|
-
funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false });
|
|
11634
|
+
funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11365
11635
|
}
|
|
11366
11636
|
continue;
|
|
11367
11637
|
}
|
|
@@ -11375,7 +11645,7 @@ function extractLua(content, filePath) {
|
|
|
11375
11645
|
symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200)));
|
|
11376
11646
|
}
|
|
11377
11647
|
if (!lineClosesItself(stripped)) {
|
|
11378
|
-
funcStack.push({ name: fname, endKeywordNeeded: true, isBlock: false });
|
|
11648
|
+
funcStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11379
11649
|
}
|
|
11380
11650
|
continue;
|
|
11381
11651
|
}
|
|
@@ -11390,7 +11660,7 @@ function extractLua(content, filePath) {
|
|
|
11390
11660
|
symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200)));
|
|
11391
11661
|
}
|
|
11392
11662
|
if (!lineClosesItself(stripped)) {
|
|
11393
|
-
funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false });
|
|
11663
|
+
funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11394
11664
|
}
|
|
11395
11665
|
continue;
|
|
11396
11666
|
}
|
|
@@ -11411,7 +11681,13 @@ function extractLua(content, filePath) {
|
|
|
11411
11681
|
if (/^(?:\bend\b[\s),;}]*)+$/.test(stripped)) {
|
|
11412
11682
|
const popCount = (stripped.match(/\bend\b/g) ?? []).length;
|
|
11413
11683
|
for (let k = 0; k < popCount && funcStack.length > 0; k++) {
|
|
11414
|
-
funcStack.pop();
|
|
11684
|
+
const popped = funcStack.pop();
|
|
11685
|
+
if (popped !== void 0 && popped.symbolIndex !== void 0) {
|
|
11686
|
+
const open = symbols[popped.symbolIndex];
|
|
11687
|
+
if (open !== void 0 && lineNum > open.lineStart) {
|
|
11688
|
+
symbols[popped.symbolIndex] = { ...open, lineEnd: lineNum, body: lines2.slice(open.lineStart - 1, lineNum).join("\n") };
|
|
11689
|
+
}
|
|
11690
|
+
}
|
|
11415
11691
|
}
|
|
11416
11692
|
}
|
|
11417
11693
|
}
|
|
@@ -11453,14 +11729,14 @@ function extractElixir(content, filePath) {
|
|
|
11453
11729
|
if (modM) {
|
|
11454
11730
|
const modName = modM[1] ?? "";
|
|
11455
11731
|
symbols.push(makeLineSymbol(filePath, modName, "class", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
|
|
11456
|
-
moduleStack.push({ name: modName, endKeywordNeeded: true, isBlock: false });
|
|
11732
|
+
moduleStack.push({ name: modName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11457
11733
|
continue;
|
|
11458
11734
|
}
|
|
11459
11735
|
const protoM = PROTOCOL_RE.exec(stripped);
|
|
11460
11736
|
if (protoM) {
|
|
11461
11737
|
const protoName = protoM[1] ?? "";
|
|
11462
11738
|
symbols.push(makeLineSymbol(filePath, protoName, "protocol", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
|
|
11463
|
-
moduleStack.push({ name: protoName, endKeywordNeeded: true, isBlock: false });
|
|
11739
|
+
moduleStack.push({ name: protoName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11464
11740
|
continue;
|
|
11465
11741
|
}
|
|
11466
11742
|
const fm = FUNC_RE4.exec(stripped);
|
|
@@ -11473,7 +11749,7 @@ function extractElixir(content, filePath) {
|
|
|
11473
11749
|
symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
|
|
11474
11750
|
}
|
|
11475
11751
|
if (opensDoBlock) {
|
|
11476
|
-
moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false });
|
|
11752
|
+
moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11477
11753
|
}
|
|
11478
11754
|
continue;
|
|
11479
11755
|
}
|
|
@@ -11487,7 +11763,7 @@ function extractElixir(content, filePath) {
|
|
|
11487
11763
|
symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
|
|
11488
11764
|
}
|
|
11489
11765
|
if (opensDoBlock) {
|
|
11490
|
-
moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false });
|
|
11766
|
+
moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
|
|
11491
11767
|
}
|
|
11492
11768
|
continue;
|
|
11493
11769
|
}
|
|
@@ -11504,7 +11780,13 @@ function extractElixir(content, filePath) {
|
|
|
11504
11780
|
}
|
|
11505
11781
|
if (stripped === "end" || /^end\s/.test(stripped) || /^end$/.test(stripped)) {
|
|
11506
11782
|
if (moduleStack.length > 0) {
|
|
11507
|
-
moduleStack.pop();
|
|
11783
|
+
const popped = moduleStack.pop();
|
|
11784
|
+
if (popped !== void 0 && popped.symbolIndex !== void 0) {
|
|
11785
|
+
const open = symbols[popped.symbolIndex];
|
|
11786
|
+
if (open !== void 0 && lineNum > open.lineStart) {
|
|
11787
|
+
symbols[popped.symbolIndex] = { ...open, lineEnd: lineNum, body: lines2.slice(open.lineStart - 1, lineNum).join("\n") };
|
|
11788
|
+
}
|
|
11789
|
+
}
|
|
11508
11790
|
}
|
|
11509
11791
|
}
|
|
11510
11792
|
}
|
|
@@ -11802,7 +12084,7 @@ function bracedBodyEndLine(content, lineIndex, parenIndex, totalLines, fallback)
|
|
|
11802
12084
|
j++;
|
|
11803
12085
|
}
|
|
11804
12086
|
if (content[j] !== "{") return fallback;
|
|
11805
|
-
return findMatchingBraceEndLine(content, j, totalLines, lineIndex, "#");
|
|
12087
|
+
return findMatchingBraceEndLine(content, j, totalLines, lineIndex, "#", { backtickQuote: true });
|
|
11806
12088
|
}
|
|
11807
12089
|
function callEndLine(content, lineIndex, parenIndex, fallback) {
|
|
11808
12090
|
const close = matchingParenIndex(content, parenIndex);
|
|
@@ -12231,25 +12513,53 @@ function stripBashComment(line) {
|
|
|
12231
12513
|
}
|
|
12232
12514
|
return line;
|
|
12233
12515
|
}
|
|
12234
|
-
function
|
|
12516
|
+
function maskArithmeticSpans(line, carryDepth) {
|
|
12517
|
+
const chars = line.split("");
|
|
12518
|
+
let depth = carryDepth;
|
|
12519
|
+
for (let i = 0; i < chars.length; i++) {
|
|
12520
|
+
if (depth > 0) {
|
|
12521
|
+
if (chars[i] === "(") depth++;
|
|
12522
|
+
else if (chars[i] === ")") depth--;
|
|
12523
|
+
chars[i] = " ";
|
|
12524
|
+
continue;
|
|
12525
|
+
}
|
|
12526
|
+
const isDollar = chars[i] === "$" && chars[i + 1] === "(" && chars[i + 2] === "(";
|
|
12527
|
+
const isBare = chars[i] === "(" && chars[i + 1] === "(";
|
|
12528
|
+
if (!isDollar && !isBare) continue;
|
|
12529
|
+
if (isInsideStringLiteral(line, i)) continue;
|
|
12530
|
+
const open = isDollar ? i + 1 : i;
|
|
12531
|
+
for (let j = open; j < chars.length; j++) {
|
|
12532
|
+
if (chars[j] === "(") depth++;
|
|
12533
|
+
else if (chars[j] === ")") depth--;
|
|
12534
|
+
chars[j] = " ";
|
|
12535
|
+
i = j;
|
|
12536
|
+
if (depth === 0) break;
|
|
12537
|
+
}
|
|
12538
|
+
}
|
|
12539
|
+
return { masked: chars.join(""), depth };
|
|
12540
|
+
}
|
|
12541
|
+
function findHeredocOpeners(line, carryDepth) {
|
|
12235
12542
|
const terminators = [];
|
|
12543
|
+
const { masked, depth } = maskArithmeticSpans(line, carryDepth);
|
|
12236
12544
|
HEREDOC_RE.lastIndex = 0;
|
|
12237
12545
|
let m;
|
|
12238
|
-
while ((m = HEREDOC_RE.exec(
|
|
12546
|
+
while ((m = HEREDOC_RE.exec(masked)) !== null) {
|
|
12239
12547
|
if (isInsideStringLiteral(line, m.index)) continue;
|
|
12240
12548
|
const terminator = m[2] ?? "";
|
|
12241
12549
|
if (terminator) terminators.push(terminator);
|
|
12242
12550
|
}
|
|
12243
|
-
return terminators;
|
|
12551
|
+
return { terminators, depth };
|
|
12244
12552
|
}
|
|
12245
12553
|
function extractBash(content, filePath) {
|
|
12246
12554
|
const symbols = [];
|
|
12247
12555
|
const lines2 = content.split(/\r?\n/);
|
|
12248
12556
|
const heredocs = [];
|
|
12557
|
+
let arithmeticDepth = 0;
|
|
12249
12558
|
let braceDepth = 0;
|
|
12250
12559
|
let inFunction = false;
|
|
12251
12560
|
let functionBraceDepth = 0;
|
|
12252
12561
|
let awaitingFunctionBrace = false;
|
|
12562
|
+
let openFunctionIndex = null;
|
|
12253
12563
|
for (let i = 0; i < lines2.length; i++) {
|
|
12254
12564
|
const rawLine = lines2[i] ?? "";
|
|
12255
12565
|
const lineNum = i + 1;
|
|
@@ -12259,7 +12569,9 @@ function extractBash(content, filePath) {
|
|
|
12259
12569
|
}
|
|
12260
12570
|
const noComment = stripBashComment(rawLine);
|
|
12261
12571
|
const stripped = noComment.trim();
|
|
12262
|
-
|
|
12572
|
+
const opened = findHeredocOpeners(noComment, arithmeticDepth);
|
|
12573
|
+
arithmeticDepth = opened.depth;
|
|
12574
|
+
heredocs.push(...opened.terminators);
|
|
12263
12575
|
if (!stripped) continue;
|
|
12264
12576
|
if (!inFunction && !awaitingFunctionBrace && braceDepth === 0) {
|
|
12265
12577
|
const kwMatch = FUNC_KEYWORD_RE.exec(stripped);
|
|
@@ -12267,7 +12579,9 @@ function extractBash(content, filePath) {
|
|
|
12267
12579
|
const funcMatch = kwMatch ?? posixMatch;
|
|
12268
12580
|
if (funcMatch) {
|
|
12269
12581
|
const fname = funcMatch[1] ?? "";
|
|
12582
|
+
let pushedIndex = null;
|
|
12270
12583
|
if (fname && symbols.length < MAX_SYMBOLS4) {
|
|
12584
|
+
pushedIndex = symbols.length;
|
|
12271
12585
|
symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
|
|
12272
12586
|
}
|
|
12273
12587
|
if (fname) {
|
|
@@ -12279,9 +12593,11 @@ function extractBash(content, filePath) {
|
|
|
12279
12593
|
} else if (openCount > closeCount) {
|
|
12280
12594
|
inFunction = true;
|
|
12281
12595
|
functionBraceDepth = braceDepth;
|
|
12596
|
+
openFunctionIndex = pushedIndex;
|
|
12282
12597
|
}
|
|
12283
12598
|
} else {
|
|
12284
12599
|
awaitingFunctionBrace = true;
|
|
12600
|
+
openFunctionIndex = pushedIndex;
|
|
12285
12601
|
}
|
|
12286
12602
|
}
|
|
12287
12603
|
} else {
|
|
@@ -12302,6 +12618,13 @@ function extractBash(content, filePath) {
|
|
|
12302
12618
|
braceDepth += (braceLine.match(/\{/g) ?? []).length - (braceLine.match(/\}/g) ?? []).length;
|
|
12303
12619
|
if (inFunction && braceDepth <= functionBraceDepth) {
|
|
12304
12620
|
inFunction = false;
|
|
12621
|
+
if (openFunctionIndex !== null) {
|
|
12622
|
+
const open = symbols[openFunctionIndex];
|
|
12623
|
+
if (open !== void 0 && lineNum > open.lineStart) {
|
|
12624
|
+
symbols[openFunctionIndex] = { ...open, lineEnd: lineNum, body: lines2.slice(open.lineStart - 1, lineNum).join("\n") };
|
|
12625
|
+
}
|
|
12626
|
+
openFunctionIndex = null;
|
|
12627
|
+
}
|
|
12305
12628
|
}
|
|
12306
12629
|
}
|
|
12307
12630
|
return symbols;
|
|
@@ -12886,7 +13209,7 @@ var TRIGGER_RE2 = new RegExp(
|
|
|
12886
13209
|
var RETURN_TYPE = "(?:[A-Za-z_][A-Za-z0-9_.<>?,\\[\\] ]*[ \\t]+)";
|
|
12887
13210
|
var STATEMENT_KEYWORD_GUARD = "(?!(?:return|throw|new|yield|else|do|try|finally|break|continue)\\b)";
|
|
12888
13211
|
var METHOD_RE3 = new RegExp(
|
|
12889
|
-
`^[ \\t]*(?:@${IDENT3}(?:\\([^\\n)]*\\))?[ \\t]+)*(?:(?:${MODIFIER}[ \\t]+)+(${RETURN_TYPE})?|(?:${MODIFIER}[ \\t]+)*${STATEMENT_KEYWORD_GUARD}(${RETURN_TYPE}))(${IDENT3})[ \\t]*\\([^;{}]*\\)[ \\t\\r\\n]*(?:\\{|;)`,
|
|
13212
|
+
`^[ \\t]*(?:@${IDENT3}(?:\\([^\\n)]*\\))?[ \\t]+)*(?=[^\\n]*\\()(?:(?:${MODIFIER}[ \\t]+)+(${RETURN_TYPE})?|(?:${MODIFIER}[ \\t]+)*${STATEMENT_KEYWORD_GUARD}(${RETURN_TYPE}))(${IDENT3})[ \\t]*\\([^;{}]*\\)[ \\t\\r\\n]*(?:\\{|;)`,
|
|
12890
13213
|
"gm"
|
|
12891
13214
|
);
|
|
12892
13215
|
var CONTROL_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -13646,21 +13969,22 @@ function maskSpans(content, spans) {
|
|
|
13646
13969
|
}
|
|
13647
13970
|
return chars.join("");
|
|
13648
13971
|
}
|
|
13649
|
-
function
|
|
13650
|
-
|
|
13972
|
+
function componentSymbols(filePath, name, kind, totalLines) {
|
|
13973
|
+
if (totalLines < 1) return [];
|
|
13974
|
+
return [{ filePath, name, kind, lineStart: 1, lineEnd: totalLines, body: "", docstring: "", parent: "" }];
|
|
13651
13975
|
}
|
|
13652
13976
|
function extractVue(content, filePath) {
|
|
13653
13977
|
const totalLines = countContentLines(content);
|
|
13654
13978
|
const lineIndex = buildLineIndex(content);
|
|
13655
13979
|
const name = componentName(filePath);
|
|
13656
|
-
const symbols =
|
|
13980
|
+
const symbols = componentSymbols(filePath, name, "vue_component", totalLines);
|
|
13657
13981
|
const refs = [];
|
|
13658
13982
|
for (const block of extractTagBlocks(content, lineIndex, "script")) {
|
|
13659
|
-
symbols
|
|
13983
|
+
pushAll(symbols, extractTopLevelDeclarations(block.content, filePath, block.contentStartLine));
|
|
13660
13984
|
}
|
|
13661
13985
|
for (const block of extractTagBlocks(content, lineIndex, "template")) {
|
|
13662
13986
|
const markup = stripXmlComments(block.content);
|
|
13663
|
-
refs
|
|
13987
|
+
pushAll(refs, extractComponentRefs(markup, filePath, block.contentStartLine, true));
|
|
13664
13988
|
}
|
|
13665
13989
|
return finalize(symbols, refs);
|
|
13666
13990
|
}
|
|
@@ -13668,11 +13992,11 @@ function extractSvelte(content, filePath) {
|
|
|
13668
13992
|
const totalLines = countContentLines(content);
|
|
13669
13993
|
const lineIndex = buildLineIndex(content);
|
|
13670
13994
|
const name = componentName(filePath);
|
|
13671
|
-
const symbols =
|
|
13995
|
+
const symbols = componentSymbols(filePath, name, "svelte_component", totalLines);
|
|
13672
13996
|
const refs = [];
|
|
13673
13997
|
const scriptBlocks = extractTagBlocks(content, lineIndex, "script");
|
|
13674
13998
|
for (const block of scriptBlocks) {
|
|
13675
|
-
symbols
|
|
13999
|
+
pushAll(symbols, extractTopLevelDeclarations(block.content, filePath, block.contentStartLine));
|
|
13676
14000
|
}
|
|
13677
14001
|
const styleBlocks = extractTagBlocks(content, lineIndex, "style");
|
|
13678
14002
|
const spans = [...scriptBlocks, ...styleBlocks].map((b) => [
|
|
@@ -13680,7 +14004,7 @@ function extractSvelte(content, filePath) {
|
|
|
13680
14004
|
b.matchEnd
|
|
13681
14005
|
]);
|
|
13682
14006
|
const markup = stripXmlComments(maskSpans(content, spans));
|
|
13683
|
-
refs
|
|
14007
|
+
pushAll(refs, extractComponentRefs(markup, filePath, 1, true));
|
|
13684
14008
|
return finalize(symbols, refs);
|
|
13685
14009
|
}
|
|
13686
14010
|
function detectAstroFrontmatter(content) {
|
|
@@ -13701,7 +14025,7 @@ function extractAstro(content, filePath) {
|
|
|
13701
14025
|
const totalLines = countContentLines(content);
|
|
13702
14026
|
const lineIndex = buildLineIndex(content);
|
|
13703
14027
|
const name = componentName(filePath);
|
|
13704
|
-
const symbols =
|
|
14028
|
+
const symbols = componentSymbols(filePath, name, "astro_component", totalLines);
|
|
13705
14029
|
const refs = [];
|
|
13706
14030
|
const lines2 = content.split("\n");
|
|
13707
14031
|
const fm = detectAstroFrontmatter(content);
|
|
@@ -13709,7 +14033,7 @@ function extractAstro(content, filePath) {
|
|
|
13709
14033
|
if (fm) {
|
|
13710
14034
|
const frontmatterContent = lines2.slice(fm.openLine + 1, fm.closeLine).join("\n");
|
|
13711
14035
|
const contentStartLine = fm.openLine + 2;
|
|
13712
|
-
symbols
|
|
14036
|
+
pushAll(symbols, extractTopLevelDeclarations(frontmatterContent, filePath, contentStartLine));
|
|
13713
14037
|
const fenceStartOffset = lineIndex[fm.openLine] ?? 0;
|
|
13714
14038
|
const fenceEndOffset = lineIndex[fm.closeLine + 1] ?? content.length;
|
|
13715
14039
|
spans.push([fenceStartOffset, fenceEndOffset]);
|
|
@@ -13717,7 +14041,7 @@ function extractAstro(content, filePath) {
|
|
|
13717
14041
|
const styleBlocks = extractTagBlocks(content, lineIndex, "style");
|
|
13718
14042
|
for (const block of styleBlocks) spans.push([block.matchStart, block.matchEnd]);
|
|
13719
14043
|
const markup = stripXmlComments(maskSpans(content, spans));
|
|
13720
|
-
refs
|
|
14044
|
+
pushAll(refs, extractComponentRefs(markup, filePath, 1, false));
|
|
13721
14045
|
return finalize(symbols, refs);
|
|
13722
14046
|
}
|
|
13723
14047
|
|
|
@@ -15462,8 +15786,8 @@ var NO_TREE_SITTER_EXTRACTORS = {
|
|
|
15462
15786
|
toml: extractTomlSymbols,
|
|
15463
15787
|
css: extractCssSymbols,
|
|
15464
15788
|
dockerfile: extractDockerfileSymbols,
|
|
15465
|
-
csharp: (content, filePath) => extractCsharp(content, filePath).symbols,
|
|
15466
|
-
php: (content, filePath) => extractPhp(content, filePath).symbols,
|
|
15789
|
+
csharp: (content, filePath) => assignBraceBlockSpans(extractCsharp(content, filePath).symbols, content, "//"),
|
|
15790
|
+
php: (content, filePath) => assignBraceBlockSpans(extractPhp(content, filePath).symbols, content, "//"),
|
|
15467
15791
|
html: (content, filePath) => {
|
|
15468
15792
|
const r = extractHtml(content, filePath);
|
|
15469
15793
|
return [...r.symbols, ...sectionsToHeadingSymbols(r.sections, filePath)];
|
|
@@ -15472,13 +15796,13 @@ var NO_TREE_SITTER_EXTRACTORS = {
|
|
|
15472
15796
|
const r = extractLiquid(content, filePath);
|
|
15473
15797
|
return [...r.symbols, ...sectionsToHeadingSymbols(r.sections, filePath)];
|
|
15474
15798
|
},
|
|
15475
|
-
kotlin: (content, filePath) => extractKotlin(content, filePath).symbols,
|
|
15476
|
-
swift: (content, filePath) => extractSwift(content, filePath).symbols,
|
|
15477
|
-
scala: (content, filePath) => extractScala(content, filePath).symbols,
|
|
15799
|
+
kotlin: (content, filePath) => assignBraceBlockSpans(extractKotlin(content, filePath).symbols, content, "//"),
|
|
15800
|
+
swift: (content, filePath) => assignBraceBlockSpans(extractSwift(content, filePath).symbols, content, "//"),
|
|
15801
|
+
scala: (content, filePath) => assignBraceBlockSpans(extractScala(content, filePath).symbols, content, "//"),
|
|
15478
15802
|
lua: (content, filePath) => extractLua(content, filePath).symbols,
|
|
15479
15803
|
elixir: (content, filePath) => extractElixir(content, filePath).symbols,
|
|
15480
|
-
dart: (content, filePath) => extractDart(content, filePath).symbols,
|
|
15481
|
-
zig: (content, filePath) => extractZig(content, filePath).symbols,
|
|
15804
|
+
dart: (content, filePath) => assignBraceBlockSpans(extractDart(content, filePath).symbols, content, "//"),
|
|
15805
|
+
zig: (content, filePath) => assignBraceBlockSpans(extractZig(content, filePath).symbols, content, "//"),
|
|
15482
15806
|
r: (content, filePath) => extractR(content, filePath).symbols,
|
|
15483
15807
|
graphql: (content, filePath) => extractGraphql(content, filePath).symbols,
|
|
15484
15808
|
sql: extractSql,
|
|
@@ -15486,7 +15810,7 @@ var NO_TREE_SITTER_EXTRACTORS = {
|
|
|
15486
15810
|
makefile: extractMakefile,
|
|
15487
15811
|
proto: (content, filePath) => extractProto(content, filePath).symbols,
|
|
15488
15812
|
terraform: extractTerraform,
|
|
15489
|
-
powershell: (content, filePath) => extractPowershell(content, filePath).symbols,
|
|
15813
|
+
powershell: (content, filePath) => assignBraceBlockSpans(extractPowershell(content, filePath).symbols, content, "#"),
|
|
15490
15814
|
apex: (content, filePath) => extractApex(content, filePath).symbols,
|
|
15491
15815
|
salesforce_metadata: (content, filePath) => extractSalesforceMetadata(content, filePath).symbols,
|
|
15492
15816
|
env_file: extractEnv,
|
|
@@ -15567,7 +15891,7 @@ function writeParseResult(filePath, content, result, dbPath) {
|
|
|
15567
15891
|
insRef.run(r.filePath, r.name, r.line, r.col, r.context);
|
|
15568
15892
|
}
|
|
15569
15893
|
});
|
|
15570
|
-
writeAll();
|
|
15894
|
+
writeAll.immediate();
|
|
15571
15895
|
}
|
|
15572
15896
|
function indexFileSync(filePath, dbPath = globalDbPath(), preReadBytes) {
|
|
15573
15897
|
const ixCfg = loadConfig().indexing;
|
|
@@ -15625,7 +15949,23 @@ function indexedPathSpellingIsStale(storedPath, absPath) {
|
|
|
15625
15949
|
} catch {
|
|
15626
15950
|
return false;
|
|
15627
15951
|
}
|
|
15628
|
-
|
|
15952
|
+
if (real === stored) return false;
|
|
15953
|
+
if (foldPath(real) !== foldPath(stored)) return false;
|
|
15954
|
+
const storedSegments = stored.split("/");
|
|
15955
|
+
const realSegments = real.split("/");
|
|
15956
|
+
if (storedSegments.length !== realSegments.length) return real !== stored;
|
|
15957
|
+
const storedBase = storedSegments[storedSegments.length - 1];
|
|
15958
|
+
const realBase = realSegments[realSegments.length - 1];
|
|
15959
|
+
if (storedBase !== realBase) return true;
|
|
15960
|
+
for (let i = storedSegments.length - 2; i >= 0; i--) {
|
|
15961
|
+
if (storedSegments[i] !== realSegments[i]) {
|
|
15962
|
+
if (storedSegments.slice(0, i + 1).join("/") === candidate.split("/").slice(0, i + 1).join("/")) {
|
|
15963
|
+
continue;
|
|
15964
|
+
}
|
|
15965
|
+
return true;
|
|
15966
|
+
}
|
|
15967
|
+
}
|
|
15968
|
+
return false;
|
|
15629
15969
|
}
|
|
15630
15970
|
function isEmbedFresh(storedEmbedSha, sha, embeddingsEnabled, depsAvailable) {
|
|
15631
15971
|
if (storedEmbedSha === void 0) return false;
|
|
@@ -15731,11 +16071,13 @@ function removeFileFromIndex(db, filePath) {
|
|
|
15731
16071
|
deleteFileRows(db, filePath);
|
|
15732
16072
|
deleteFileEmbeddings(db, filePath);
|
|
15733
16073
|
});
|
|
15734
|
-
tx();
|
|
16074
|
+
tx.immediate();
|
|
15735
16075
|
}
|
|
15736
16076
|
function isTooShallowToPrune(rootPrefix) {
|
|
15737
|
-
const
|
|
16077
|
+
const normalized = normalizePath(rootPrefix);
|
|
16078
|
+
const segments = normalized.split("/").filter((s) => s.length > 0 && !/^[a-z]:$/i.test(s));
|
|
15738
16079
|
if (segments.length === 2 && segments[0]?.toLowerCase() === "mnt" && /^[a-z]$/i.test(segments[1] ?? "")) return true;
|
|
16080
|
+
if (normalized.startsWith("//") && segments.length <= 2) return true;
|
|
15739
16081
|
return segments.length === 0;
|
|
15740
16082
|
}
|
|
15741
16083
|
function foldedBounds(rootPrefix) {
|
|
@@ -15760,7 +16102,8 @@ function findDeletablePaths(rootPrefix, dbPath) {
|
|
|
15760
16102
|
for (const p of foldedPathsUnderRoot(rootPrefix, dbPath)) {
|
|
15761
16103
|
let stillExists;
|
|
15762
16104
|
try {
|
|
15763
|
-
|
|
16105
|
+
const st = fs22.statSync(p, { throwIfNoEntry: false });
|
|
16106
|
+
stillExists = st !== void 0 && st.isFile();
|
|
15764
16107
|
} catch {
|
|
15765
16108
|
continue;
|
|
15766
16109
|
}
|
|
@@ -15783,14 +16126,23 @@ function removeFilesBestEffort(db, paths) {
|
|
|
15783
16126
|
return removed;
|
|
15784
16127
|
}
|
|
15785
16128
|
function removeDeletedFilesBestEffort(db, paths) {
|
|
15786
|
-
const
|
|
16129
|
+
const removed = [];
|
|
16130
|
+
for (const p of paths) {
|
|
16131
|
+
let gone;
|
|
15787
16132
|
try {
|
|
15788
|
-
|
|
16133
|
+
const st = fs22.statSync(p, { throwIfNoEntry: false });
|
|
16134
|
+
gone = st === void 0 || !st.isFile();
|
|
15789
16135
|
} catch {
|
|
15790
|
-
|
|
16136
|
+
continue;
|
|
15791
16137
|
}
|
|
15792
|
-
|
|
15793
|
-
|
|
16138
|
+
if (!gone) continue;
|
|
16139
|
+
try {
|
|
16140
|
+
removeFileFromIndex(db, p);
|
|
16141
|
+
removed.push(p);
|
|
16142
|
+
} catch {
|
|
16143
|
+
}
|
|
16144
|
+
}
|
|
16145
|
+
return removed;
|
|
15794
16146
|
}
|
|
15795
16147
|
function pruneDeletedFiles(rootPrefix, dbPath = globalDbPath()) {
|
|
15796
16148
|
if (isTooShallowToPrune(rootPrefix)) return 0;
|
|
@@ -15868,7 +16220,7 @@ function sweepKnownRoots(dbPath = globalDbPath(), opts) {
|
|
|
15868
16220
|
if (isTooShallowToPrune(root)) continue;
|
|
15869
16221
|
let reachable;
|
|
15870
16222
|
try {
|
|
15871
|
-
reachable = fs22.
|
|
16223
|
+
reachable = fs22.statSync(root, { throwIfNoEntry: false })?.isDirectory() === true;
|
|
15872
16224
|
} catch {
|
|
15873
16225
|
reachable = false;
|
|
15874
16226
|
}
|
|
@@ -15997,7 +16349,7 @@ function bumpRetryCount(dbPath, absPath) {
|
|
|
15997
16349
|
db.prepare("INSERT INTO files (path, retry_count) VALUES (?, 1)").run(normalized);
|
|
15998
16350
|
return 1;
|
|
15999
16351
|
});
|
|
16000
|
-
return tx();
|
|
16352
|
+
return tx.immediate();
|
|
16001
16353
|
}
|
|
16002
16354
|
function clearRetryCount(dbPath, absPath) {
|
|
16003
16355
|
try {
|
|
@@ -16117,14 +16469,21 @@ var INDEX_FAILED = /* @__PURE__ */ Symbol("indexFailed");
|
|
|
16117
16469
|
var inFlightEmbeddings = /* @__PURE__ */ new Map();
|
|
16118
16470
|
var activeEmbedSlots = 0;
|
|
16119
16471
|
var embedSlotWaiters = [];
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
const
|
|
16123
|
-
|
|
16472
|
+
var embedSlotEpoch = 0;
|
|
16473
|
+
function makeReleaseEmbedSlot() {
|
|
16474
|
+
const epoch = embedSlotEpoch;
|
|
16475
|
+
return () => {
|
|
16476
|
+
if (epoch !== embedSlotEpoch) return;
|
|
16477
|
+
activeEmbedSlots -= 1;
|
|
16478
|
+
const next = embedSlotWaiters.shift();
|
|
16479
|
+
if (next) next();
|
|
16480
|
+
};
|
|
16124
16481
|
}
|
|
16125
16482
|
registerReset(() => {
|
|
16483
|
+
embedSlotEpoch += 1;
|
|
16126
16484
|
activeEmbedSlots = 0;
|
|
16127
16485
|
embedSlotWaiters.length = 0;
|
|
16486
|
+
inFlightEmbeddings.clear();
|
|
16128
16487
|
});
|
|
16129
16488
|
function embedFileSerialized(absPath, dbPath, sha) {
|
|
16130
16489
|
const key = foldPath(absPath);
|
|
@@ -16138,7 +16497,8 @@ function embedFileSerialized(absPath, dbPath, sha) {
|
|
|
16138
16497
|
const limit = loadConfig().worker.max_pool_workers ?? 4;
|
|
16139
16498
|
const dispatchEmbed = () => {
|
|
16140
16499
|
const result = indexFileEmbeddings(absPath, dbPath, sha, onEmbedError);
|
|
16141
|
-
|
|
16500
|
+
const release = makeReleaseEmbedSlot();
|
|
16501
|
+
result.then(release, release);
|
|
16142
16502
|
return result;
|
|
16143
16503
|
};
|
|
16144
16504
|
const runEmbed = () => {
|
|
@@ -16555,8 +16915,12 @@ var KNOWN_ROOTS_SWEEP_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
|
16555
16915
|
async function runWorkerLoop(dir, pollIntervalMs, shouldStop = () => false) {
|
|
16556
16916
|
let lastSnapshotCleanupMs = 0;
|
|
16557
16917
|
let lastKnownRootsSweepMs = 0;
|
|
16918
|
+
let ownedPidFile = false;
|
|
16558
16919
|
while (!shouldStop()) {
|
|
16559
16920
|
if (!fs23.existsSync(dir)) break;
|
|
16921
|
+
const pidOwner = readPidFile(dir);
|
|
16922
|
+
if (pidOwner === process.pid) ownedPidFile = true;
|
|
16923
|
+
else if (ownedPidFile && pidOwner !== null) break;
|
|
16560
16924
|
try {
|
|
16561
16925
|
drainOnce(dir);
|
|
16562
16926
|
} catch {
|