token-goat 2.6.34 → 2.6.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/SECURITY.md +11 -10
  2. package/dist/{token-goat-chunk-IYYQOPY4.mjs → token-goat-chunk-D5IZEGN2.mjs} +18 -4
  3. package/dist/{token-goat-chunk-WA2ER6TZ.mjs → token-goat-chunk-DQIT5JIF.mjs} +1 -1
  4. package/dist/{token-goat-chunk-L7QLEVO7.mjs → token-goat-chunk-DRAIYVUI.mjs} +16 -14
  5. package/dist/{token-goat-chunk-GXBPEQR2.mjs → token-goat-chunk-HW4VUKJ5.mjs} +14 -8
  6. package/dist/{token-goat-chunk-CN7GUPX6.mjs → token-goat-chunk-I2KCEGIP.mjs} +378 -54
  7. package/dist/{token-goat-chunk-7FWBSPCT.mjs → token-goat-chunk-K7W3P2TJ.mjs} +139 -6
  8. package/dist/{token-goat-chunk-OA3GFKP2.mjs → token-goat-chunk-SIHYQCTM.mjs} +2 -2
  9. package/dist/{token-goat-chunk-I6EQH27G.mjs → token-goat-chunk-UIZVX3HN.mjs} +2 -2
  10. package/dist/{token-goat-chunk-FRMEOIRU.mjs → token-goat-chunk-Y2NH6DGZ.mjs} +208 -13
  11. package/dist/{token-goat-chunk-CKRATWCJ.mjs → token-goat-chunk-YF67EWRH.mjs} +5 -5
  12. package/dist/{token-goat-hook-chunk-CNLMPHXT.mjs → token-goat-hook-chunk-2O7P4Z6Q.mjs} +139 -6
  13. package/dist/{token-goat-hook-chunk-I5VM5PO5.mjs → token-goat-hook-chunk-3AAH72SO.mjs} +14 -8
  14. package/dist/{token-goat-hook-chunk-BU5OFDGQ.mjs → token-goat-hook-chunk-4POU6OHK.mjs} +208 -13
  15. package/dist/{token-goat-hook-chunk-6C5RN3CM.mjs → token-goat-hook-chunk-CRBMPT74.mjs} +2 -2
  16. package/dist/{token-goat-hook-chunk-QTZ6YUMQ.mjs → token-goat-hook-chunk-D6UJEFHX.mjs} +2 -2
  17. package/dist/{token-goat-hook-chunk-ATEGFQAU.mjs → token-goat-hook-chunk-J4HKWUWZ.mjs} +5 -5
  18. package/dist/{token-goat-hook-chunk-2ISZ4AZR.mjs → token-goat-hook-chunk-NIPXIAPA.mjs} +1 -1
  19. package/dist/{token-goat-hook-chunk-KGLMNOGD.mjs → token-goat-hook-chunk-NXVT4F3S.mjs} +18 -4
  20. package/dist/{token-goat-hook-chunk-OQML5EMA.mjs → token-goat-hook-chunk-VU6VGZBM.mjs} +16 -14
  21. package/dist/{token-goat-hook-chunk-6QTWMSRO.mjs → token-goat-hook-chunk-XM4W3WCO.mjs} +378 -54
  22. package/dist/token-goat-hook.mjs +5 -5
  23. package/dist/token-goat.core.mjs +5 -5
  24. package/package.json +4 -3
@@ -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,
@@ -87,7 +88,7 @@ import {
87
88
  withFileLock,
88
89
  writeIfDifferent,
89
90
  writeJsonSettings
90
- } from "./token-goat-chunk-7FWBSPCT.mjs";
91
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
91
92
  import {
92
93
  registerReset
93
94
  } from "./token-goat-chunk-AO2QD2AG.mjs";
@@ -159,7 +160,12 @@ function decodeZipEntry(entries, entryPath) {
159
160
  async function parseOoxmlPart(xmlText2) {
160
161
  const fxp = await loadXmlParser();
161
162
  if (!fxp) throw new Error("fast-xml-parser is not installed; run `npm install fast-xml-parser` to enable this command");
162
- const parser = new fxp.XMLParser({ ignoreAttributes: false, preserveOrder: false, trimValues: false });
163
+ const parser = new fxp.XMLParser({
164
+ ignoreAttributes: false,
165
+ preserveOrder: false,
166
+ trimValues: false,
167
+ parseTagValue: false
168
+ });
163
169
  return parser.parse(xmlText2);
164
170
  }
165
171
  function pushTextValue(runs, val) {
@@ -2288,28 +2294,254 @@ function formatCsvProfile(profiles) {
2288
2294
  }).join("\n\n");
2289
2295
  }
2290
2296
 
2291
- // src/xlsx_extract.ts
2292
- var loadExcelJs = createLazyModuleLoader(async () => {
2293
- const mod = await import("exceljs");
2294
- return mod.default ?? mod;
2295
- }, "xlsx reading disabled (exceljs package unavailable)");
2296
- async function requireExcelJs() {
2297
- const mod = await loadExcelJs();
2298
- if (!mod) throw new Error("exceljs is not installed; run `npm install exceljs` to enable this command");
2299
- return mod;
2297
+ // src/xlsx_reader.ts
2298
+ var EMPTY_CELL = Object.freeze({ value: null, text: "" });
2299
+ function asArray(val) {
2300
+ if (val === void 0 || val === null) return [];
2301
+ if (Array.isArray(val)) return val.filter((v) => v !== null && typeof v === "object");
2302
+ if (typeof val === "object") return [val];
2303
+ return [];
2304
+ }
2305
+ function textOf(node) {
2306
+ if (node === void 0 || node === null) return "";
2307
+ if (typeof node === "string") return node;
2308
+ if (typeof node === "number" || typeof node === "boolean") return String(node);
2309
+ if (Array.isArray(node)) return node.map(textOf).join("");
2310
+ const t = node["#text"];
2311
+ return t === void 0 ? "" : String(t);
2312
+ }
2313
+ function attr(node, name) {
2314
+ if (node === void 0) return void 0;
2315
+ const v = node[`@_${name}`];
2316
+ return v === void 0 || v === null ? void 0 : String(v);
2317
+ }
2318
+ function isTruthyAttr(v) {
2319
+ return v === "1" || v === "true";
2320
+ }
2321
+ function refToColumn(ref2) {
2322
+ let n = 0;
2323
+ for (const ch of ref2) {
2324
+ const code = ch.toUpperCase().charCodeAt(0);
2325
+ if (code < 65 || code > 90) break;
2326
+ n = n * 26 + (code - 64);
2327
+ }
2328
+ return n;
2300
2329
  }
2301
- async function loadWorkbook(filePath) {
2302
- const ExcelJS = await requireExcelJs();
2303
- const wb = new ExcelJS.Workbook();
2304
- try {
2305
- await wb.xlsx.readFile(filePath);
2306
- } catch (err) {
2307
- const msg = extractErrorMessage(err);
2308
- if (msg.startsWith("File not found:")) throw err;
2309
- throw new Error(`not a valid .xlsx file: ${filePath}`, { cause: err });
2330
+ function refToRow(ref2) {
2331
+ const m = /(\d+)\s*$/.exec(ref2);
2332
+ return m ? parseInt(m[1], 10) : 0;
2333
+ }
2334
+ var BUILTIN_DATE_FORMAT_IDS = /* @__PURE__ */ new Set([14, 15, 16, 17, 18, 19, 20, 21, 22, 45, 46, 47]);
2335
+ function formatCodeIsDate(formatCode) {
2336
+ const stripped = formatCode.replace(/"[^"]*"/g, "").replace(/\[[^\]]*\]/g, "").replace(/\\./g, "");
2337
+ return /[ymdhs]/i.test(stripped);
2338
+ }
2339
+ function serialToDate(serial, date1904) {
2340
+ if (date1904) return new Date(Date.UTC(1904, 0, 1) + Math.round(serial * 864e5));
2341
+ const adjusted = serial >= 61 ? serial - 1 : serial;
2342
+ return new Date(Date.UTC(1899, 11, 31) + Math.round(adjusted * 864e5));
2343
+ }
2344
+ function numberToText(n) {
2345
+ return String(n);
2346
+ }
2347
+ function parseStyles(xml, parsed) {
2348
+ if (xml === null || parsed === null || typeof parsed !== "object") return { dateStyles: [] };
2349
+ const sheet = parsed["styleSheet"];
2350
+ if (sheet === void 0 || sheet === null || typeof sheet !== "object") return { dateStyles: [] };
2351
+ const root = sheet;
2352
+ const customDateFormats = /* @__PURE__ */ new Set();
2353
+ for (const fmt of asArray(root["numFmts"]?.["numFmt"])) {
2354
+ const id = Number(attr(fmt, "numFmtId"));
2355
+ const code = attr(fmt, "formatCode");
2356
+ if (Number.isFinite(id) && code !== void 0 && formatCodeIsDate(code)) customDateFormats.add(id);
2357
+ }
2358
+ const dateStyles = [];
2359
+ for (const xf of asArray(root["cellXfs"]?.["xf"])) {
2360
+ const id = Number(attr(xf, "numFmtId") ?? "0");
2361
+ dateStyles.push(Number.isFinite(id) && (BUILTIN_DATE_FORMAT_IDS.has(id) || customDateFormats.has(id)));
2362
+ }
2363
+ return { dateStyles };
2364
+ }
2365
+ function parseSharedStrings(parsed) {
2366
+ if (parsed === null || typeof parsed !== "object") return [];
2367
+ const sst = parsed["sst"];
2368
+ if (sst === void 0 || sst === null || typeof sst !== "object") return [];
2369
+ return asArray(sst["si"]).map((si) => {
2370
+ if (si["t"] !== void 0) return textOf(si["t"]);
2371
+ const runs = asArray(si["r"]);
2372
+ if (runs.length > 0) return runs.map((r) => textOf(r["t"])).join("");
2373
+ return "";
2374
+ });
2375
+ }
2376
+ function parseWorkbookRels(parsed) {
2377
+ const out = /* @__PURE__ */ new Map();
2378
+ if (parsed === null || typeof parsed !== "object") return out;
2379
+ const rels = parsed["Relationships"];
2380
+ if (rels === void 0 || rels === null || typeof rels !== "object") return out;
2381
+ for (const rel of asArray(rels["Relationship"])) {
2382
+ const id = attr(rel, "Id");
2383
+ const target = attr(rel, "Target");
2384
+ if (id === void 0 || target === void 0) continue;
2385
+ const normalized = target.startsWith("/") ? target.slice(1) : `xl/${target.replace(/^\.\//, "")}`;
2386
+ out.set(id, normalized);
2387
+ }
2388
+ return out;
2389
+ }
2390
+ function buildCell(c, shared, styles, date1904) {
2391
+ const type = attr(c, "t") ?? "n";
2392
+ const styleIdx = Number(attr(c, "s") ?? "-1");
2393
+ const isDateStyle = Number.isInteger(styleIdx) && styleIdx >= 0 && styles.dateStyles[styleIdx] === true;
2394
+ const hasV = c["v"] !== void 0;
2395
+ const hasIs = c["is"] !== void 0;
2396
+ const fNode = c["f"];
2397
+ const formula = fNode === void 0 ? "" : textOf(fNode);
2398
+ if (!hasV && !hasIs && formula === "") return null;
2399
+ let raw;
2400
+ let text;
2401
+ if (type === "s") {
2402
+ const idx = Number(textOf(c["v"]));
2403
+ const s = Number.isInteger(idx) ? shared[idx] ?? "" : "";
2404
+ raw = s;
2405
+ text = s;
2406
+ } else if (type === "inlineStr") {
2407
+ const isNode = c["is"];
2408
+ const s = isNode !== void 0 && isNode !== null && typeof isNode === "object" ? (() => {
2409
+ const node = isNode;
2410
+ if (node["t"] !== void 0) return textOf(node["t"]);
2411
+ return asArray(node["r"]).map((r) => textOf(r["t"])).join("");
2412
+ })() : textOf(isNode);
2413
+ raw = s;
2414
+ text = s;
2415
+ } else if (type === "str") {
2416
+ const s = textOf(c["v"]);
2417
+ raw = s;
2418
+ text = s;
2419
+ } else if (type === "b") {
2420
+ const b = textOf(c["v"]).trim() === "1";
2421
+ raw = b;
2422
+ text = b ? "TRUE" : "FALSE";
2423
+ } else if (type === "e") {
2424
+ const e = textOf(c["v"]);
2425
+ raw = { error: e };
2426
+ text = e;
2427
+ } else {
2428
+ const n = Number(textOf(c["v"]));
2429
+ if (!Number.isFinite(n)) {
2430
+ raw = null;
2431
+ text = "";
2432
+ } else if (isDateStyle) {
2433
+ const d = serialToDate(n, date1904);
2434
+ raw = d;
2435
+ text = d.toISOString();
2436
+ } else {
2437
+ raw = n;
2438
+ text = numberToText(n);
2439
+ }
2440
+ }
2441
+ if (formula !== "") return { value: { formula, result: raw }, text, formula };
2442
+ return { value: raw, text };
2443
+ }
2444
+ function parseSheet(parsed, shared, styles, date1904) {
2445
+ const cells = /* @__PURE__ */ new Map();
2446
+ let rowCount = 0;
2447
+ let columnCount = 0;
2448
+ let populatedRows = 0;
2449
+ if (parsed === null || typeof parsed !== "object") return { cells, rowCount, columnCount, populatedRows };
2450
+ const ws = parsed["worksheet"];
2451
+ if (ws === void 0 || ws === null || typeof ws !== "object") return { cells, rowCount, columnCount, populatedRows };
2452
+ const sheetData = ws["sheetData"];
2453
+ if (sheetData === void 0 || sheetData === null || typeof sheetData !== "object") {
2454
+ return { cells, rowCount, columnCount, populatedRows };
2455
+ }
2456
+ let fallbackRow = 0;
2457
+ for (const row of asArray(sheetData["row"])) {
2458
+ const declaredRow = Number(attr(row, "r"));
2459
+ const rowIdx = Number.isInteger(declaredRow) && declaredRow > 0 ? declaredRow : fallbackRow + 1;
2460
+ fallbackRow = rowIdx;
2461
+ let fallbackCol = 0;
2462
+ const rowCells = /* @__PURE__ */ new Map();
2463
+ for (const c of asArray(row["c"])) {
2464
+ const ref2 = attr(c, "r");
2465
+ const declaredCol = ref2 === void 0 ? 0 : refToColumn(ref2);
2466
+ const colIdx = declaredCol > 0 ? declaredCol : fallbackCol + 1;
2467
+ fallbackCol = colIdx;
2468
+ const cell = buildCell(c, shared, styles, date1904);
2469
+ if (cell === null) continue;
2470
+ rowCells.set(colIdx, cell);
2471
+ if (colIdx > columnCount) columnCount = colIdx;
2472
+ }
2473
+ if (rowCells.size === 0) continue;
2474
+ cells.set(rowIdx, rowCells);
2475
+ populatedRows++;
2476
+ if (rowIdx > rowCount) rowCount = rowIdx;
2477
+ }
2478
+ return { cells, rowCount, columnCount, populatedRows };
2479
+ }
2480
+ function makeWorksheet(name, data) {
2481
+ function getRow(r) {
2482
+ const rowCells = data.cells.get(r);
2483
+ return {
2484
+ get values() {
2485
+ const out = [];
2486
+ if (rowCells !== void 0) for (const [col, cell] of rowCells) out[col] = cell.value;
2487
+ return out;
2488
+ },
2489
+ eachCell(opts, cb) {
2490
+ if (opts.includeEmpty) {
2491
+ const maxCol = data.columnCount;
2492
+ for (let c = 1; c <= maxCol; c++) cb(rowCells?.get(c) ?? EMPTY_CELL, c);
2493
+ return;
2494
+ }
2495
+ if (rowCells === void 0) return;
2496
+ for (const col of [...rowCells.keys()].sort((a, b) => a - b)) cb(rowCells.get(col), col);
2497
+ }
2498
+ };
2310
2499
  }
2311
- return wb;
2500
+ return {
2501
+ name,
2502
+ rowCount: data.rowCount,
2503
+ columnCount: data.columnCount,
2504
+ actualRowCount: data.populatedRows,
2505
+ getRow,
2506
+ getCell(addr) {
2507
+ return data.cells.get(refToRow(addr))?.get(refToColumn(addr)) ?? EMPTY_CELL;
2508
+ }
2509
+ };
2510
+ }
2511
+ async function readXlsxWorkbook(filePath) {
2512
+ const entries = await readOoxmlZip(filePath, ".xlsx");
2513
+ const workbookXml = decodeZipEntry(entries, "xl/workbook.xml");
2514
+ if (workbookXml === null) throw new Error(`not a valid .xlsx file: ${filePath}`);
2515
+ const workbookRoot = await parseOoxmlPart(workbookXml);
2516
+ const wbNode = workbookRoot?.["workbook"];
2517
+ if (wbNode === void 0 || wbNode === null || typeof wbNode !== "object") {
2518
+ throw new Error(`not a valid .xlsx file: ${filePath}`);
2519
+ }
2520
+ const wb = wbNode;
2521
+ const date1904 = isTruthyAttr(attr(wb["workbookPr"], "date1904"));
2522
+ const relsXml = decodeZipEntry(entries, "xl/_rels/workbook.xml.rels");
2523
+ const rels = parseWorkbookRels(relsXml === null ? null : await parseOoxmlPart(relsXml));
2524
+ const sharedXml = decodeZipEntry(entries, "xl/sharedStrings.xml");
2525
+ const shared = sharedXml === null ? [] : parseSharedStrings(await parseOoxmlPart(sharedXml));
2526
+ const stylesXml = decodeZipEntry(entries, "xl/styles.xml");
2527
+ const styles = parseStyles(stylesXml, stylesXml === null ? null : await parseOoxmlPart(stylesXml));
2528
+ const worksheets = [];
2529
+ for (const sheet of asArray(wb["sheets"]?.["sheet"])) {
2530
+ const name = attr(sheet, "name") ?? "";
2531
+ const rid = attr(sheet, "r:id") ?? attr(sheet, "relationshipId");
2532
+ const partPath = rid === void 0 ? void 0 : rels.get(rid);
2533
+ const sheetXml = partPath === void 0 ? null : decodeZipEntry(entries, partPath);
2534
+ const data = sheetXml === null ? { cells: /* @__PURE__ */ new Map(), rowCount: 0, columnCount: 0, populatedRows: 0 } : parseSheet(await parseOoxmlPart(sheetXml), shared, styles, date1904);
2535
+ worksheets.push(makeWorksheet(name, data));
2536
+ }
2537
+ return {
2538
+ worksheets,
2539
+ getWorksheet: (name) => worksheets.find((ws) => ws.name === name)
2540
+ };
2312
2541
  }
2542
+
2543
+ // src/xlsx_extract.ts
2544
+ var loadWorkbook = readXlsxWorkbook;
2313
2545
  function requireSheet(wb, sheetName) {
2314
2546
  const ws = wb.getWorksheet(sheetName);
2315
2547
  if (ws === void 0) {
@@ -3067,7 +3299,7 @@ function logHintEmission(category, sessionId, correlator, compensateSelfResolve
3067
3299
  } catch {
3068
3300
  }
3069
3301
  }
3070
- var TOKEN_GOAT_INVOCATION_RE = /(?:^|[\s;&|])token-goat(?=[\s]|$)/;
3302
+ var TOKEN_GOAT_INVOCATION_RE = /(?:^|[\s;&|])(?:token-goat|tg)(?=[\s]|$)/;
3071
3303
  function commandMentionsCorrelator(command, correlator) {
3072
3304
  let idx = command.indexOf(correlator);
3073
3305
  while (idx !== -1) {
@@ -7158,6 +7390,12 @@ async function embedTexts(texts, modelName = DEFAULT_MODEL) {
7158
7390
  `Dimension mismatch: model returned ${vec.length}-dim vector, expected ${expectedDim}`
7159
7391
  );
7160
7392
  }
7393
+ const badIndex = vec.findIndex((component) => !Number.isFinite(component));
7394
+ if (badIndex !== -1) {
7395
+ throw new Error(
7396
+ `Non-finite embedding component at index ${badIndex}: model returned ${String(vec[badIndex])}`
7397
+ );
7398
+ }
7161
7399
  vecs.push(vec);
7162
7400
  }
7163
7401
  } finally {
@@ -7168,6 +7406,11 @@ function packVec(vec) {
7168
7406
  const view = new Float32Array(vec.length);
7169
7407
  for (const [i, val] of vec.entries()) {
7170
7408
  view[i] = val;
7409
+ if (!Number.isFinite(view[i])) {
7410
+ throw new Error(
7411
+ `Non-finite embedding component at index ${i}: ${String(val)} is not representable as a 32-bit float`
7412
+ );
7413
+ }
7171
7414
  }
7172
7415
  return Buffer.from(view.buffer);
7173
7416
  }
@@ -7368,7 +7611,7 @@ function fetchScopedHits(db, queryVec, k, maxDistance, rootDir) {
7368
7611
  if (!row) {
7369
7612
  continue;
7370
7613
  }
7371
- if (row.distance <= maxDistance) {
7614
+ if (typeof row.distance === "number" && Number.isFinite(row.distance) && row.distance <= maxDistance) {
7372
7615
  const chunk = scopeParams !== void 0 ? chunkStmt.get(row.rowid, ...scopeParams) : chunkStmt.get(row.rowid);
7373
7616
  if (chunk) {
7374
7617
  hits.push({
@@ -8638,9 +8881,9 @@ var MONITORING_COMMAND_PATTERNS = [
8638
8881
  recallHint: "--tail 50"
8639
8882
  },
8640
8883
  // token-goat section/outline/symbol repeat calls — output is stable until the file changes
8641
- { pattern: /^token-goat\s+section\s+["'][^"']+["']/, recallHint: "" },
8642
- { pattern: /^token-goat\s+outline\s+\S+/, recallHint: "" },
8643
- { pattern: /^token-goat\s+symbol\s+\S+/, recallHint: "" }
8884
+ { pattern: /^(?:token-goat|tg)\s+section\s+["'][^"']+["']/, recallHint: "" },
8885
+ { pattern: /^(?:token-goat|tg)\s+outline\s+\S+/, recallHint: "" },
8886
+ { pattern: /^(?:token-goat|tg)\s+symbol\s+\S+/, recallHint: "" }
8644
8887
  ];
8645
8888
  function isPsMultilineSystemQuery(cmd) {
8646
8889
  if (!/^(?:powershell(?:\.exe)?|pwsh(?:\.exe)?)\s+/i.test(cmd)) return false;
@@ -12166,7 +12409,7 @@ function extractLua(content, filePath) {
12166
12409
  symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200)));
12167
12410
  }
12168
12411
  if (!lineClosesItself(stripped)) {
12169
- funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false });
12412
+ funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12170
12413
  }
12171
12414
  continue;
12172
12415
  }
@@ -12180,7 +12423,7 @@ function extractLua(content, filePath) {
12180
12423
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200)));
12181
12424
  }
12182
12425
  if (!lineClosesItself(stripped)) {
12183
- funcStack.push({ name: fname, endKeywordNeeded: true, isBlock: false });
12426
+ funcStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12184
12427
  }
12185
12428
  continue;
12186
12429
  }
@@ -12195,7 +12438,7 @@ function extractLua(content, filePath) {
12195
12438
  symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200)));
12196
12439
  }
12197
12440
  if (!lineClosesItself(stripped)) {
12198
- funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false });
12441
+ funcStack.push({ name: baseName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12199
12442
  }
12200
12443
  continue;
12201
12444
  }
@@ -12216,7 +12459,13 @@ function extractLua(content, filePath) {
12216
12459
  if (/^(?:\bend\b[\s),;}]*)+$/.test(stripped)) {
12217
12460
  const popCount = (stripped.match(/\bend\b/g) ?? []).length;
12218
12461
  for (let k = 0; k < popCount && funcStack.length > 0; k++) {
12219
- funcStack.pop();
12462
+ const popped = funcStack.pop();
12463
+ if (popped !== void 0 && popped.symbolIndex !== void 0) {
12464
+ const open = symbols[popped.symbolIndex];
12465
+ if (open !== void 0 && lineNum > open.lineStart) {
12466
+ symbols[popped.symbolIndex] = { ...open, lineEnd: lineNum, body: lines2.slice(open.lineStart - 1, lineNum).join("\n") };
12467
+ }
12468
+ }
12220
12469
  }
12221
12470
  }
12222
12471
  }
@@ -12258,14 +12507,14 @@ function extractElixir(content, filePath) {
12258
12507
  if (modM) {
12259
12508
  const modName = modM[1] ?? "";
12260
12509
  symbols.push(makeLineSymbol(filePath, modName, "class", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
12261
- moduleStack.push({ name: modName, endKeywordNeeded: true, isBlock: false });
12510
+ moduleStack.push({ name: modName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12262
12511
  continue;
12263
12512
  }
12264
12513
  const protoM = PROTOCOL_RE.exec(stripped);
12265
12514
  if (protoM) {
12266
12515
  const protoName = protoM[1] ?? "";
12267
12516
  symbols.push(makeLineSymbol(filePath, protoName, "protocol", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
12268
- moduleStack.push({ name: protoName, endKeywordNeeded: true, isBlock: false });
12517
+ moduleStack.push({ name: protoName, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12269
12518
  continue;
12270
12519
  }
12271
12520
  const fm = FUNC_RE4.exec(stripped);
@@ -12278,7 +12527,7 @@ function extractElixir(content, filePath) {
12278
12527
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
12279
12528
  }
12280
12529
  if (opensDoBlock) {
12281
- moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false });
12530
+ moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12282
12531
  }
12283
12532
  continue;
12284
12533
  }
@@ -12292,7 +12541,7 @@ function extractElixir(content, filePath) {
12292
12541
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
12293
12542
  }
12294
12543
  if (opensDoBlock) {
12295
- moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false });
12544
+ moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
12296
12545
  }
12297
12546
  continue;
12298
12547
  }
@@ -12309,7 +12558,13 @@ function extractElixir(content, filePath) {
12309
12558
  }
12310
12559
  if (stripped === "end" || /^end\s/.test(stripped) || /^end$/.test(stripped)) {
12311
12560
  if (moduleStack.length > 0) {
12312
- moduleStack.pop();
12561
+ const popped = moduleStack.pop();
12562
+ if (popped !== void 0 && popped.symbolIndex !== void 0) {
12563
+ const open = symbols[popped.symbolIndex];
12564
+ if (open !== void 0 && lineNum > open.lineStart) {
12565
+ symbols[popped.symbolIndex] = { ...open, lineEnd: lineNum, body: lines2.slice(open.lineStart - 1, lineNum).join("\n") };
12566
+ }
12567
+ }
12313
12568
  }
12314
12569
  }
12315
12570
  }
@@ -13036,25 +13291,53 @@ function stripBashComment(line) {
13036
13291
  }
13037
13292
  return line;
13038
13293
  }
13039
- function findHeredocOpeners(line) {
13294
+ function maskArithmeticSpans(line, carryDepth) {
13295
+ const chars = line.split("");
13296
+ let depth = carryDepth;
13297
+ for (let i = 0; i < chars.length; i++) {
13298
+ if (depth > 0) {
13299
+ if (chars[i] === "(") depth++;
13300
+ else if (chars[i] === ")") depth--;
13301
+ chars[i] = " ";
13302
+ continue;
13303
+ }
13304
+ const isDollar = chars[i] === "$" && chars[i + 1] === "(" && chars[i + 2] === "(";
13305
+ const isBare = chars[i] === "(" && chars[i + 1] === "(";
13306
+ if (!isDollar && !isBare) continue;
13307
+ if (isInsideStringLiteral(line, i)) continue;
13308
+ const open = isDollar ? i + 1 : i;
13309
+ for (let j = open; j < chars.length; j++) {
13310
+ if (chars[j] === "(") depth++;
13311
+ else if (chars[j] === ")") depth--;
13312
+ chars[j] = " ";
13313
+ i = j;
13314
+ if (depth === 0) break;
13315
+ }
13316
+ }
13317
+ return { masked: chars.join(""), depth };
13318
+ }
13319
+ function findHeredocOpeners(line, carryDepth) {
13040
13320
  const terminators = [];
13321
+ const { masked, depth } = maskArithmeticSpans(line, carryDepth);
13041
13322
  HEREDOC_RE.lastIndex = 0;
13042
13323
  let m;
13043
- while ((m = HEREDOC_RE.exec(line)) !== null) {
13324
+ while ((m = HEREDOC_RE.exec(masked)) !== null) {
13044
13325
  if (isInsideStringLiteral(line, m.index)) continue;
13045
13326
  const terminator = m[2] ?? "";
13046
13327
  if (terminator) terminators.push(terminator);
13047
13328
  }
13048
- return terminators;
13329
+ return { terminators, depth };
13049
13330
  }
13050
13331
  function extractBash(content, filePath) {
13051
13332
  const symbols = [];
13052
13333
  const lines2 = content.split(/\r?\n/);
13053
13334
  const heredocs = [];
13335
+ let arithmeticDepth = 0;
13054
13336
  let braceDepth = 0;
13055
13337
  let inFunction = false;
13056
13338
  let functionBraceDepth = 0;
13057
13339
  let awaitingFunctionBrace = false;
13340
+ let openFunctionIndex = null;
13058
13341
  for (let i = 0; i < lines2.length; i++) {
13059
13342
  const rawLine = lines2[i] ?? "";
13060
13343
  const lineNum = i + 1;
@@ -13064,7 +13347,9 @@ function extractBash(content, filePath) {
13064
13347
  }
13065
13348
  const noComment = stripBashComment(rawLine);
13066
13349
  const stripped = noComment.trim();
13067
- heredocs.push(...findHeredocOpeners(noComment));
13350
+ const opened = findHeredocOpeners(noComment, arithmeticDepth);
13351
+ arithmeticDepth = opened.depth;
13352
+ heredocs.push(...opened.terminators);
13068
13353
  if (!stripped) continue;
13069
13354
  if (!inFunction && !awaitingFunctionBrace && braceDepth === 0) {
13070
13355
  const kwMatch = FUNC_KEYWORD_RE.exec(stripped);
@@ -13072,7 +13357,9 @@ function extractBash(content, filePath) {
13072
13357
  const funcMatch = kwMatch ?? posixMatch;
13073
13358
  if (funcMatch) {
13074
13359
  const fname = funcMatch[1] ?? "";
13360
+ let pushedIndex = null;
13075
13361
  if (fname && symbols.length < MAX_SYMBOLS4) {
13362
+ pushedIndex = symbols.length;
13076
13363
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines2, "hash"));
13077
13364
  }
13078
13365
  if (fname) {
@@ -13084,9 +13371,11 @@ function extractBash(content, filePath) {
13084
13371
  } else if (openCount > closeCount) {
13085
13372
  inFunction = true;
13086
13373
  functionBraceDepth = braceDepth;
13374
+ openFunctionIndex = pushedIndex;
13087
13375
  }
13088
13376
  } else {
13089
13377
  awaitingFunctionBrace = true;
13378
+ openFunctionIndex = pushedIndex;
13090
13379
  }
13091
13380
  }
13092
13381
  } else {
@@ -13107,6 +13396,13 @@ function extractBash(content, filePath) {
13107
13396
  braceDepth += (braceLine.match(/\{/g) ?? []).length - (braceLine.match(/\}/g) ?? []).length;
13108
13397
  if (inFunction && braceDepth <= functionBraceDepth) {
13109
13398
  inFunction = false;
13399
+ if (openFunctionIndex !== null) {
13400
+ const open = symbols[openFunctionIndex];
13401
+ if (open !== void 0 && lineNum > open.lineStart) {
13402
+ symbols[openFunctionIndex] = { ...open, lineEnd: lineNum, body: lines2.slice(open.lineStart - 1, lineNum).join("\n") };
13403
+ }
13404
+ openFunctionIndex = null;
13405
+ }
13110
13406
  }
13111
13407
  }
13112
13408
  return symbols;
@@ -13691,7 +13987,7 @@ var TRIGGER_RE2 = new RegExp(
13691
13987
  var RETURN_TYPE = "(?:[A-Za-z_][A-Za-z0-9_.<>?,\\[\\] ]*[ \\t]+)";
13692
13988
  var STATEMENT_KEYWORD_GUARD = "(?!(?:return|throw|new|yield|else|do|try|finally|break|continue)\\b)";
13693
13989
  var METHOD_RE3 = new RegExp(
13694
- `^[ \\t]*(?:@${IDENT3}(?:\\([^\\n)]*\\))?[ \\t]+)*(?:(?:${MODIFIER}[ \\t]+)+(${RETURN_TYPE})?|(?:${MODIFIER}[ \\t]+)*${STATEMENT_KEYWORD_GUARD}(${RETURN_TYPE}))(${IDENT3})[ \\t]*\\([^;{}]*\\)[ \\t\\r\\n]*(?:\\{|;)`,
13990
+ `^[ \\t]*(?:@${IDENT3}(?:\\([^\\n)]*\\))?[ \\t]+)*(?=[^\\n]*\\()(?:(?:${MODIFIER}[ \\t]+)+(${RETURN_TYPE})?|(?:${MODIFIER}[ \\t]+)*${STATEMENT_KEYWORD_GUARD}(${RETURN_TYPE}))(${IDENT3})[ \\t]*\\([^;{}]*\\)[ \\t\\r\\n]*(?:\\{|;)`,
13695
13991
  "gm"
13696
13992
  );
13697
13993
  var CONTROL_NAMES = /* @__PURE__ */ new Set([
@@ -16267,8 +16563,8 @@ var NO_TREE_SITTER_EXTRACTORS = {
16267
16563
  toml: extractTomlSymbols,
16268
16564
  css: extractCssSymbols,
16269
16565
  dockerfile: extractDockerfileSymbols,
16270
- csharp: (content, filePath) => extractCsharp(content, filePath).symbols,
16271
- php: (content, filePath) => extractPhp(content, filePath).symbols,
16566
+ csharp: (content, filePath) => assignBraceBlockSpans(extractCsharp(content, filePath).symbols, content, "//"),
16567
+ php: (content, filePath) => assignBraceBlockSpans(extractPhp(content, filePath).symbols, content, "//"),
16272
16568
  html: (content, filePath) => {
16273
16569
  const r = extractHtml(content, filePath);
16274
16570
  return [...r.symbols, ...sectionsToHeadingSymbols(r.sections, filePath)];
@@ -16277,13 +16573,13 @@ var NO_TREE_SITTER_EXTRACTORS = {
16277
16573
  const r = extractLiquid(content, filePath);
16278
16574
  return [...r.symbols, ...sectionsToHeadingSymbols(r.sections, filePath)];
16279
16575
  },
16280
- kotlin: (content, filePath) => extractKotlin(content, filePath).symbols,
16281
- swift: (content, filePath) => extractSwift(content, filePath).symbols,
16282
- scala: (content, filePath) => extractScala(content, filePath).symbols,
16576
+ kotlin: (content, filePath) => assignBraceBlockSpans(extractKotlin(content, filePath).symbols, content, "//"),
16577
+ swift: (content, filePath) => assignBraceBlockSpans(extractSwift(content, filePath).symbols, content, "//"),
16578
+ scala: (content, filePath) => assignBraceBlockSpans(extractScala(content, filePath).symbols, content, "//"),
16283
16579
  lua: (content, filePath) => extractLua(content, filePath).symbols,
16284
16580
  elixir: (content, filePath) => extractElixir(content, filePath).symbols,
16285
- dart: (content, filePath) => extractDart(content, filePath).symbols,
16286
- zig: (content, filePath) => extractZig(content, filePath).symbols,
16581
+ dart: (content, filePath) => assignBraceBlockSpans(extractDart(content, filePath).symbols, content, "//"),
16582
+ zig: (content, filePath) => assignBraceBlockSpans(extractZig(content, filePath).symbols, content, "//"),
16287
16583
  r: (content, filePath) => extractR(content, filePath).symbols,
16288
16584
  graphql: (content, filePath) => extractGraphql(content, filePath).symbols,
16289
16585
  sql: extractSql,
@@ -16291,7 +16587,7 @@ var NO_TREE_SITTER_EXTRACTORS = {
16291
16587
  makefile: extractMakefile,
16292
16588
  proto: (content, filePath) => extractProto(content, filePath).symbols,
16293
16589
  terraform: extractTerraform,
16294
- powershell: (content, filePath) => extractPowershell(content, filePath).symbols,
16590
+ powershell: (content, filePath) => assignBraceBlockSpans(extractPowershell(content, filePath).symbols, content, "#"),
16295
16591
  apex: (content, filePath) => extractApex(content, filePath).symbols,
16296
16592
  salesforce_metadata: (content, filePath) => extractSalesforceMetadata(content, filePath).symbols,
16297
16593
  env_file: extractEnv,
@@ -16430,7 +16726,23 @@ function indexedPathSpellingIsStale(storedPath, absPath) {
16430
16726
  } catch {
16431
16727
  return false;
16432
16728
  }
16433
- return real !== stored && foldPath(real) === foldPath(stored);
16729
+ if (real === stored) return false;
16730
+ if (foldPath(real) !== foldPath(stored)) return false;
16731
+ const storedSegments = stored.split("/");
16732
+ const realSegments = real.split("/");
16733
+ if (storedSegments.length !== realSegments.length) return real !== stored;
16734
+ const storedBase = storedSegments[storedSegments.length - 1];
16735
+ const realBase = realSegments[realSegments.length - 1];
16736
+ if (storedBase !== realBase) return true;
16737
+ for (let i = storedSegments.length - 2; i >= 0; i--) {
16738
+ if (storedSegments[i] !== realSegments[i]) {
16739
+ if (storedSegments.slice(0, i + 1).join("/") === candidate.split("/").slice(0, i + 1).join("/")) {
16740
+ continue;
16741
+ }
16742
+ return true;
16743
+ }
16744
+ }
16745
+ return false;
16434
16746
  }
16435
16747
  function isEmbedFresh(storedEmbedSha, sha, embeddingsEnabled, depsAvailable) {
16436
16748
  if (storedEmbedSha === void 0) return false;
@@ -16922,14 +17234,21 @@ var INDEX_FAILED = /* @__PURE__ */ Symbol("indexFailed");
16922
17234
  var inFlightEmbeddings = /* @__PURE__ */ new Map();
16923
17235
  var activeEmbedSlots = 0;
16924
17236
  var embedSlotWaiters = [];
16925
- function releaseEmbedSlot() {
16926
- activeEmbedSlots -= 1;
16927
- const next = embedSlotWaiters.shift();
16928
- if (next) next();
17237
+ var embedSlotEpoch = 0;
17238
+ function makeReleaseEmbedSlot() {
17239
+ const epoch = embedSlotEpoch;
17240
+ return () => {
17241
+ if (epoch !== embedSlotEpoch) return;
17242
+ activeEmbedSlots -= 1;
17243
+ const next = embedSlotWaiters.shift();
17244
+ if (next) next();
17245
+ };
16929
17246
  }
16930
17247
  registerReset(() => {
17248
+ embedSlotEpoch += 1;
16931
17249
  activeEmbedSlots = 0;
16932
17250
  embedSlotWaiters.length = 0;
17251
+ inFlightEmbeddings.clear();
16933
17252
  });
16934
17253
  function embedFileSerialized(absPath, dbPath, sha) {
16935
17254
  const key = foldPath(absPath);
@@ -16943,7 +17262,8 @@ function embedFileSerialized(absPath, dbPath, sha) {
16943
17262
  const limit = loadConfig().worker.max_pool_workers ?? 4;
16944
17263
  const dispatchEmbed = () => {
16945
17264
  const result = indexFileEmbeddings(absPath, dbPath, sha, onEmbedError);
16946
- result.then(releaseEmbedSlot, releaseEmbedSlot);
17265
+ const release = makeReleaseEmbedSlot();
17266
+ result.then(release, release);
16947
17267
  return result;
16948
17268
  };
16949
17269
  const runEmbed = () => {
@@ -17360,8 +17680,12 @@ var KNOWN_ROOTS_SWEEP_INTERVAL_MS = 24 * 60 * 60 * 1e3;
17360
17680
  async function runWorkerLoop(dir, pollIntervalMs, shouldStop = () => false) {
17361
17681
  let lastSnapshotCleanupMs = 0;
17362
17682
  let lastKnownRootsSweepMs = 0;
17683
+ let ownedPidFile = false;
17363
17684
  while (!shouldStop()) {
17364
17685
  if (!fs28.existsSync(dir)) break;
17686
+ const pidOwner = readPidFile(dir);
17687
+ if (pidOwner === process.pid) ownedPidFile = true;
17688
+ else if (ownedPidFile && pidOwner !== null) break;
17365
17689
  try {
17366
17690
  drainOnce(dir);
17367
17691
  } catch {