token-goat 2.6.35 → 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.
Files changed (26) hide show
  1. package/README.md +4 -2
  2. package/SECURITY.md +3 -1
  3. package/dist/{token-goat-chunk-DRAIYVUI.mjs → token-goat-chunk-65BKISIS.mjs} +3 -3
  4. package/dist/{token-goat-chunk-UIZVX3HN.mjs → token-goat-chunk-CNDOJ3ZP.mjs} +2 -2
  5. package/dist/{token-goat-chunk-Y2NH6DGZ.mjs → token-goat-chunk-FRTBMRP7.mjs} +5 -5
  6. package/dist/{token-goat-chunk-D5IZEGN2.mjs → token-goat-chunk-IYTVE6KN.mjs} +13 -8
  7. package/dist/{token-goat-chunk-HW4VUKJ5.mjs → token-goat-chunk-KYFJC37X.mjs} +14 -13
  8. package/dist/{token-goat-chunk-YF67EWRH.mjs → token-goat-chunk-LN6OUHTV.mjs} +5 -5
  9. package/dist/{token-goat-hook-chunk-NIPXIAPA.mjs → token-goat-chunk-MGOUYAA2.mjs} +1 -1
  10. package/dist/{token-goat-chunk-I2KCEGIP.mjs → token-goat-chunk-UFOVM7ZN.mjs} +85 -45
  11. package/dist/{token-goat-chunk-K7W3P2TJ.mjs → token-goat-chunk-V465YKOR.mjs} +61 -17
  12. package/dist/{token-goat-chunk-SIHYQCTM.mjs → token-goat-chunk-VYMGEVZS.mjs} +16 -4
  13. package/dist/{token-goat-chunk-DQIT5JIF.mjs → token-goat-hook-chunk-3ZDBWJDF.mjs} +1 -1
  14. package/dist/{token-goat-hook-chunk-CRBMPT74.mjs → token-goat-hook-chunk-5UH54CW6.mjs} +16 -4
  15. package/dist/{token-goat-hook-chunk-VU6VGZBM.mjs → token-goat-hook-chunk-6ODM3MP7.mjs} +3 -3
  16. package/dist/{token-goat-hook-chunk-XM4W3WCO.mjs → token-goat-hook-chunk-A77A26A7.mjs} +85 -45
  17. package/dist/{token-goat-hook-chunk-4POU6OHK.mjs → token-goat-hook-chunk-BDR6C6IE.mjs} +5 -5
  18. package/dist/{token-goat-hook-chunk-3AAH72SO.mjs → token-goat-hook-chunk-C6GIABOX.mjs} +14 -13
  19. package/dist/{token-goat-hook-chunk-D6UJEFHX.mjs → token-goat-hook-chunk-E257IGSN.mjs} +2 -2
  20. package/dist/{token-goat-hook-chunk-NXVT4F3S.mjs → token-goat-hook-chunk-MW5HPEGD.mjs} +13 -8
  21. package/dist/{token-goat-hook-chunk-J4HKWUWZ.mjs → token-goat-hook-chunk-QSCYNJ2B.mjs} +5 -5
  22. package/dist/{token-goat-hook-chunk-2O7P4Z6Q.mjs → token-goat-hook-chunk-Y2WHX2P3.mjs} +61 -17
  23. package/dist/token-goat-hook.mjs +5 -5
  24. package/dist/token-goat.core.mjs +5 -5
  25. package/package.json +10 -9
  26. package/scripts/install-git-hooks.mjs +55 -0
@@ -56,6 +56,7 @@ import {
56
56
  parse,
57
57
  precedingDocComment,
58
58
  propagateEndLinesToSymbols,
59
+ pushAll,
59
60
  recordStat,
60
61
  redactIfDotenv,
61
62
  redactSecrets,
@@ -88,7 +89,7 @@ import {
88
89
  withFileLock,
89
90
  writeIfDifferent,
90
91
  writeJsonSettings
91
- } from "./token-goat-hook-chunk-2O7P4Z6Q.mjs";
92
+ } from "./token-goat-hook-chunk-Y2WHX2P3.mjs";
92
93
  import {
93
94
  registerReset
94
95
  } from "./token-goat-hook-chunk-BUOCULAM.mjs";
@@ -2475,6 +2476,7 @@ registerReset(() => {
2475
2476
  });
2476
2477
 
2477
2478
  // src/session_store.ts
2479
+ import { createHash as createHash2 } from "node:crypto";
2478
2480
  import * as fs9 from "node:fs";
2479
2481
  import * as path8 from "node:path";
2480
2482
 
@@ -2701,9 +2703,22 @@ function sweepCacheRoots(extraRoots = []) {
2701
2703
  var MAX_FILES = 500;
2702
2704
  var SESSIONS_SUBDIR = "sessions";
2703
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
+ }
2704
2719
  function sessionPath(sessionId) {
2705
2720
  if (!sessionId) return null;
2706
- const safe = sanitizeIdForFilename(sessionId, 64);
2721
+ const safe = sessionFileStem(sessionId);
2707
2722
  if (!safe) return null;
2708
2723
  const dir = path8.join(tokenGoatHome(), SESSIONS_SUBDIR);
2709
2724
  const candidate = path8.join(dir, `${safe}.json`);
@@ -2955,9 +2970,8 @@ function readSessionStateFile(sessionId) {
2955
2970
  }
2956
2971
  function listSiblingSessionStates(sessionId) {
2957
2972
  if (!sessionId) return [];
2958
- const safeSessionId = sanitizeIdForFilename(sessionId);
2959
- if (!safeSessionId) return [];
2960
- const prefix = `${safeSessionId}${AGENT_SALT_MARKER}`;
2973
+ const prefix = saltedStemPrefix(sessionId);
2974
+ if (prefix === AGENT_SALT_MARKER) return [];
2961
2975
  const dir = path8.join(tokenGoatHome(), SESSIONS_SUBDIR);
2962
2976
  const out = [];
2963
2977
  try {
@@ -3443,7 +3457,7 @@ function scanForInjectionPatterns(text) {
3443
3457
  var UNTRUSTED_WEB_TAG = "untrusted-web-content";
3444
3458
  function neutralizeFenceMarkers(text, tag) {
3445
3459
  const escapedTag = tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3446
- const marker = new RegExp(`<\\s*/?\\s*${escapedTag}(?:\\s[^>]*)?\\s*/?\\s*>`, "gi");
3460
+ const marker = new RegExp(`<\\s*/?\\s*${escapedTag}(?=[\\s/>])[^>]*>`, "gi");
3447
3461
  return text.replace(marker, (m) => m.replace(/</g, "&lt;").replace(/>/g, "&gt;"));
3448
3462
  }
3449
3463
  function fenceUntrustedContent(text, matchedPatternNames, tag = UNTRUSTED_WEB_TAG) {
@@ -4041,7 +4055,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
4041
4055
  }
4042
4056
 
4043
4057
  // src/image_shrink.ts
4044
- import { createHash as createHash2 } from "node:crypto";
4058
+ import { createHash as createHash3 } from "node:crypto";
4045
4059
  import * as fs12 from "node:fs";
4046
4060
  import * as path10 from "node:path";
4047
4061
 
@@ -4259,7 +4273,7 @@ function imageShrinkCacheDir() {
4259
4273
  return path10.join(tokenGoatHome(), "image_shrink_cache");
4260
4274
  }
4261
4275
  function shrinkCacheKey(originalPath, size, mtimeMs, quality) {
4262
- return createHash2("sha256").update(`${originalPath}:${size}:${mtimeMs}:${quality}`).digest("hex").slice(0, 16);
4276
+ return createHash3("sha256").update(`${originalPath}:${size}:${mtimeMs}:${quality}`).digest("hex").slice(0, 16);
4263
4277
  }
4264
4278
  function findCachedShrink(originalPath, size, mtimeMs, quality) {
4265
4279
  const key = shrinkCacheKey(originalPath, size, mtimeMs, quality);
@@ -4308,18 +4322,18 @@ function pruneShrinkCache() {
4308
4322
  }
4309
4323
  async function finalizeShrinkResult(result, filePath) {
4310
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);
4311
4327
  if (loadConfig().image_shrink.ocr_enabled) {
4312
4328
  const ocr = await ocrImage(result.data);
4313
4329
  if (ocr !== null && isTextHeavy(ocr, loadConfig().image_shrink.ocr_min_confidence)) {
4314
4330
  const textBytes = Buffer.byteLength(ocr.text, "utf8");
4315
- const saved2 = Math.max(0, result.shrunkBytes - textBytes);
4316
- recordStat("image_ocr", saved2, Math.round(saved2 / 4), void 0, basename12);
4331
+ const saved = Math.max(0, result.shrunkBytes - textBytes);
4332
+ recordStat("image_ocr", saved, Math.round(saved / 4), void 0, basename12);
4317
4333
  return contextOutput(formatOcrSummary(ocr, basename12, result.originalBytes));
4318
4334
  }
4319
4335
  }
4320
- const saved = result.originalBytes - result.shrunkBytes;
4321
4336
  const { summary, dataUrl } = formatShrinkSummary(result, basename12);
4322
- recordStat("image_shrink", saved, Math.round(saved / 4), void 0, basename12);
4323
4337
  return contextOutput(`${summary}
4324
4338
  ${dataUrl}`);
4325
4339
  }
@@ -4596,7 +4610,8 @@ function splitRangeIntoChunks(filePath, lines2, rangeStart, rangeEnd, chunkSize,
4596
4610
  const line = lines2[lineNo - 1] ?? "";
4597
4611
  const lineWithNewline = line + "\n";
4598
4612
  if (currentChunk.length + lineWithNewline.length > chunkSize && currentChunk.length > 0) {
4599
- const currentChunkTooSmall = currentChunk.trim().length < MIN_CHUNK_CHARS;
4613
+ const trimmedLength = currentChunk.trim().length;
4614
+ const currentChunkTooSmall = trimmedLength < MIN_CHUNK_CHARS;
4600
4615
  if (!currentChunkTooSmall) {
4601
4616
  chunks.push({
4602
4617
  filePath,
@@ -4606,12 +4621,21 @@ function splitRangeIntoChunks(filePath, lines2, rangeStart, rangeEnd, chunkSize,
4606
4621
  kind
4607
4622
  });
4608
4623
  }
4609
- const overlapLines = Math.ceil(overlap / 40);
4610
- const computedOverlapStart = Math.max(rangeStart, currentLine - overlapLines);
4611
- const overlapStart = currentChunkTooSmall ? Math.min(computedOverlapStart, startLine) : computedOverlapStart;
4612
- const overlapText = lines2.slice(overlapStart - 1, currentLine - 1).join("\n");
4613
- currentChunk = overlapText + "\n";
4614
- startLine = overlapStart;
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
+ }
4615
4639
  }
4616
4640
  currentChunk += lineWithNewline;
4617
4641
  currentLine++;
@@ -4760,7 +4784,7 @@ async function upsertChunks(db, chunks) {
4760
4784
  insertChunkVector(vectorInsertStmt, chunkResult.lastInsertRowid, embedding);
4761
4785
  }
4762
4786
  });
4763
- tx();
4787
+ tx.immediate();
4764
4788
  return "embedded";
4765
4789
  }
4766
4790
  var BACKFILL_MULTIPLIER = 3;
@@ -9403,7 +9427,7 @@ function collectElements(node, tag) {
9403
9427
  const obj = n;
9404
9428
  for (const [key, val] of Object.entries(obj)) {
9405
9429
  if (key === tag) {
9406
- if (Array.isArray(val)) out.push(...val);
9430
+ if (Array.isArray(val)) pushAll(out, val);
9407
9431
  else out.push(val);
9408
9432
  } else if (val !== null && typeof val === "object") {
9409
9433
  walk(val);
@@ -9976,7 +10000,10 @@ function makeWorksheet(name, data) {
9976
10000
  },
9977
10001
  eachCell(opts, cb) {
9978
10002
  if (opts.includeEmpty) {
9979
- const maxCol = data.columnCount;
10003
+ let maxCol = 0;
10004
+ if (rowCells !== void 0) {
10005
+ for (const c of rowCells.keys()) if (c > maxCol) maxCol = c;
10006
+ }
9980
10007
  for (let c = 1; c <= maxCol; c++) cb(rowCells?.get(c) ?? EMPTY_CELL, c);
9981
10008
  return;
9982
10009
  }
@@ -12057,7 +12084,7 @@ function bracedBodyEndLine(content, lineIndex, parenIndex, totalLines, fallback)
12057
12084
  j++;
12058
12085
  }
12059
12086
  if (content[j] !== "{") return fallback;
12060
- return findMatchingBraceEndLine(content, j, totalLines, lineIndex, "#");
12087
+ return findMatchingBraceEndLine(content, j, totalLines, lineIndex, "#", { backtickQuote: true });
12061
12088
  }
12062
12089
  function callEndLine(content, lineIndex, parenIndex, fallback) {
12063
12090
  const close = matchingParenIndex(content, parenIndex);
@@ -13942,21 +13969,22 @@ function maskSpans(content, spans) {
13942
13969
  }
13943
13970
  return chars.join("");
13944
13971
  }
13945
- function componentSymbol(filePath, name, kind, totalLines) {
13946
- return { filePath, name, kind, lineStart: 1, lineEnd: totalLines, body: "", docstring: "", parent: "" };
13972
+ function componentSymbols(filePath, name, kind, totalLines) {
13973
+ if (totalLines < 1) return [];
13974
+ return [{ filePath, name, kind, lineStart: 1, lineEnd: totalLines, body: "", docstring: "", parent: "" }];
13947
13975
  }
13948
13976
  function extractVue(content, filePath) {
13949
13977
  const totalLines = countContentLines(content);
13950
13978
  const lineIndex = buildLineIndex(content);
13951
13979
  const name = componentName(filePath);
13952
- const symbols = [componentSymbol(filePath, name, "vue_component", totalLines)];
13980
+ const symbols = componentSymbols(filePath, name, "vue_component", totalLines);
13953
13981
  const refs = [];
13954
13982
  for (const block of extractTagBlocks(content, lineIndex, "script")) {
13955
- symbols.push(...extractTopLevelDeclarations(block.content, filePath, block.contentStartLine));
13983
+ pushAll(symbols, extractTopLevelDeclarations(block.content, filePath, block.contentStartLine));
13956
13984
  }
13957
13985
  for (const block of extractTagBlocks(content, lineIndex, "template")) {
13958
13986
  const markup = stripXmlComments(block.content);
13959
- refs.push(...extractComponentRefs(markup, filePath, block.contentStartLine, true));
13987
+ pushAll(refs, extractComponentRefs(markup, filePath, block.contentStartLine, true));
13960
13988
  }
13961
13989
  return finalize(symbols, refs);
13962
13990
  }
@@ -13964,11 +13992,11 @@ function extractSvelte(content, filePath) {
13964
13992
  const totalLines = countContentLines(content);
13965
13993
  const lineIndex = buildLineIndex(content);
13966
13994
  const name = componentName(filePath);
13967
- const symbols = [componentSymbol(filePath, name, "svelte_component", totalLines)];
13995
+ const symbols = componentSymbols(filePath, name, "svelte_component", totalLines);
13968
13996
  const refs = [];
13969
13997
  const scriptBlocks = extractTagBlocks(content, lineIndex, "script");
13970
13998
  for (const block of scriptBlocks) {
13971
- symbols.push(...extractTopLevelDeclarations(block.content, filePath, block.contentStartLine));
13999
+ pushAll(symbols, extractTopLevelDeclarations(block.content, filePath, block.contentStartLine));
13972
14000
  }
13973
14001
  const styleBlocks = extractTagBlocks(content, lineIndex, "style");
13974
14002
  const spans = [...scriptBlocks, ...styleBlocks].map((b) => [
@@ -13976,7 +14004,7 @@ function extractSvelte(content, filePath) {
13976
14004
  b.matchEnd
13977
14005
  ]);
13978
14006
  const markup = stripXmlComments(maskSpans(content, spans));
13979
- refs.push(...extractComponentRefs(markup, filePath, 1, true));
14007
+ pushAll(refs, extractComponentRefs(markup, filePath, 1, true));
13980
14008
  return finalize(symbols, refs);
13981
14009
  }
13982
14010
  function detectAstroFrontmatter(content) {
@@ -13997,7 +14025,7 @@ function extractAstro(content, filePath) {
13997
14025
  const totalLines = countContentLines(content);
13998
14026
  const lineIndex = buildLineIndex(content);
13999
14027
  const name = componentName(filePath);
14000
- const symbols = [componentSymbol(filePath, name, "astro_component", totalLines)];
14028
+ const symbols = componentSymbols(filePath, name, "astro_component", totalLines);
14001
14029
  const refs = [];
14002
14030
  const lines2 = content.split("\n");
14003
14031
  const fm = detectAstroFrontmatter(content);
@@ -14005,7 +14033,7 @@ function extractAstro(content, filePath) {
14005
14033
  if (fm) {
14006
14034
  const frontmatterContent = lines2.slice(fm.openLine + 1, fm.closeLine).join("\n");
14007
14035
  const contentStartLine = fm.openLine + 2;
14008
- symbols.push(...extractTopLevelDeclarations(frontmatterContent, filePath, contentStartLine));
14036
+ pushAll(symbols, extractTopLevelDeclarations(frontmatterContent, filePath, contentStartLine));
14009
14037
  const fenceStartOffset = lineIndex[fm.openLine] ?? 0;
14010
14038
  const fenceEndOffset = lineIndex[fm.closeLine + 1] ?? content.length;
14011
14039
  spans.push([fenceStartOffset, fenceEndOffset]);
@@ -14013,7 +14041,7 @@ function extractAstro(content, filePath) {
14013
14041
  const styleBlocks = extractTagBlocks(content, lineIndex, "style");
14014
14042
  for (const block of styleBlocks) spans.push([block.matchStart, block.matchEnd]);
14015
14043
  const markup = stripXmlComments(maskSpans(content, spans));
14016
- refs.push(...extractComponentRefs(markup, filePath, 1, false));
14044
+ pushAll(refs, extractComponentRefs(markup, filePath, 1, false));
14017
14045
  return finalize(symbols, refs);
14018
14046
  }
14019
14047
 
@@ -15863,7 +15891,7 @@ function writeParseResult(filePath, content, result, dbPath) {
15863
15891
  insRef.run(r.filePath, r.name, r.line, r.col, r.context);
15864
15892
  }
15865
15893
  });
15866
- writeAll();
15894
+ writeAll.immediate();
15867
15895
  }
15868
15896
  function indexFileSync(filePath, dbPath = globalDbPath(), preReadBytes) {
15869
15897
  const ixCfg = loadConfig().indexing;
@@ -16043,11 +16071,13 @@ function removeFileFromIndex(db, filePath) {
16043
16071
  deleteFileRows(db, filePath);
16044
16072
  deleteFileEmbeddings(db, filePath);
16045
16073
  });
16046
- tx();
16074
+ tx.immediate();
16047
16075
  }
16048
16076
  function isTooShallowToPrune(rootPrefix) {
16049
- const segments = rootPrefix.split("/").filter((s) => s.length > 0 && !/^[a-z]:$/i.test(s));
16077
+ const normalized = normalizePath(rootPrefix);
16078
+ const segments = normalized.split("/").filter((s) => s.length > 0 && !/^[a-z]:$/i.test(s));
16050
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;
16051
16081
  return segments.length === 0;
16052
16082
  }
16053
16083
  function foldedBounds(rootPrefix) {
@@ -16072,7 +16102,8 @@ function findDeletablePaths(rootPrefix, dbPath) {
16072
16102
  for (const p of foldedPathsUnderRoot(rootPrefix, dbPath)) {
16073
16103
  let stillExists;
16074
16104
  try {
16075
- stillExists = fs22.statSync(p, { throwIfNoEntry: false }) !== void 0;
16105
+ const st = fs22.statSync(p, { throwIfNoEntry: false });
16106
+ stillExists = st !== void 0 && st.isFile();
16076
16107
  } catch {
16077
16108
  continue;
16078
16109
  }
@@ -16095,14 +16126,23 @@ function removeFilesBestEffort(db, paths) {
16095
16126
  return removed;
16096
16127
  }
16097
16128
  function removeDeletedFilesBestEffort(db, paths) {
16098
- const stillGone = paths.filter((p) => {
16129
+ const removed = [];
16130
+ for (const p of paths) {
16131
+ let gone;
16099
16132
  try {
16100
- return fs22.statSync(p, { throwIfNoEntry: false }) === void 0;
16133
+ const st = fs22.statSync(p, { throwIfNoEntry: false });
16134
+ gone = st === void 0 || !st.isFile();
16101
16135
  } catch {
16102
- return false;
16136
+ continue;
16103
16137
  }
16104
- });
16105
- return removeFilesBestEffort(db, stillGone);
16138
+ if (!gone) continue;
16139
+ try {
16140
+ removeFileFromIndex(db, p);
16141
+ removed.push(p);
16142
+ } catch {
16143
+ }
16144
+ }
16145
+ return removed;
16106
16146
  }
16107
16147
  function pruneDeletedFiles(rootPrefix, dbPath = globalDbPath()) {
16108
16148
  if (isTooShallowToPrune(rootPrefix)) return 0;
@@ -16180,7 +16220,7 @@ function sweepKnownRoots(dbPath = globalDbPath(), opts) {
16180
16220
  if (isTooShallowToPrune(root)) continue;
16181
16221
  let reachable;
16182
16222
  try {
16183
- reachable = fs22.existsSync(root);
16223
+ reachable = fs22.statSync(root, { throwIfNoEntry: false })?.isDirectory() === true;
16184
16224
  } catch {
16185
16225
  reachable = false;
16186
16226
  }
@@ -16309,7 +16349,7 @@ function bumpRetryCount(dbPath, absPath) {
16309
16349
  db.prepare("INSERT INTO files (path, retry_count) VALUES (?, 1)").run(normalized);
16310
16350
  return 1;
16311
16351
  });
16312
- return tx();
16352
+ return tx.immediate();
16313
16353
  }
16314
16354
  function clearRetryCount(dbPath, absPath) {
16315
16355
  try {
@@ -10,7 +10,7 @@ import {
10
10
  isRewriteWorthwhile,
11
11
  resolveMinNetSavingsBytes,
12
12
  shlexSplit
13
- } from "./token-goat-hook-chunk-NIPXIAPA.mjs";
13
+ } from "./token-goat-hook-chunk-3ZDBWJDF.mjs";
14
14
  import {
15
15
  BASH_OUTPUT_SUBDIR,
16
16
  HOOK_EVENTS,
@@ -28,7 +28,7 @@ import {
28
28
  storeBashOutput,
29
29
  storeWebOutput,
30
30
  summarizeOutputDelta
31
- } from "./token-goat-hook-chunk-CRBMPT74.mjs";
31
+ } from "./token-goat-hook-chunk-5UH54CW6.mjs";
32
32
  import {
33
33
  BODY_FIRST_TOOL_RESPONSE_KEYS,
34
34
  OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
@@ -118,7 +118,7 @@ import {
118
118
  wasCliReadThisSession,
119
119
  wasFileReadThisSession,
120
120
  wasHintShown
121
- } from "./token-goat-hook-chunk-XM4W3WCO.mjs";
121
+ } from "./token-goat-hook-chunk-A77A26A7.mjs";
122
122
  import {
123
123
  VERSION,
124
124
  detectHarness,
@@ -137,7 +137,7 @@ import {
137
137
  runGit,
138
138
  shortFingerprint,
139
139
  toKB
140
- } from "./token-goat-hook-chunk-2O7P4Z6Q.mjs";
140
+ } from "./token-goat-hook-chunk-Y2WHX2P3.mjs";
141
141
 
142
142
  // src/hooks_grep.ts
143
143
  function grepIntInput(toolInput, key) {
@@ -575,7 +575,7 @@ import crypto from "node:crypto";
575
575
  var TRACKED_SKILL = "token-goat";
576
576
  var MAX_COMMANDS_SHOWN = 8;
577
577
  async function currentCommandNames() {
578
- const { buildProgram } = await import("./token-goat-hook-chunk-3AAH72SO.mjs");
578
+ const { buildProgram } = await import("./token-goat-hook-chunk-C6GIABOX.mjs");
579
579
  return flattenCommandNames(buildCommandManifest(buildProgram()));
580
580
  }
581
581
  async function recordSkillVersionSnapshot(sessionId, skillName) {
@@ -84,7 +84,7 @@ import {
84
84
  runZipRead,
85
85
  symbolNamesInFile,
86
86
  upsertNote
87
- } from "./token-goat-hook-chunk-NXVT4F3S.mjs";
87
+ } from "./token-goat-hook-chunk-MW5HPEGD.mjs";
88
88
  import {
89
89
  BASH_OUTPUT_SUBDIR,
90
90
  GEMINI_TOOL_NAME_MAP,
@@ -105,7 +105,7 @@ import {
105
105
  readStdinJson,
106
106
  searchRecall,
107
107
  storeWebOutput
108
- } from "./token-goat-hook-chunk-CRBMPT74.mjs";
108
+ } from "./token-goat-hook-chunk-5UH54CW6.mjs";
109
109
  import {
110
110
  AGENT_SALT_MARKER,
111
111
  CONTEXT_AUTOCOMPACT_TOKENS,
@@ -243,7 +243,7 @@ import {
243
243
  vscodeDecoderConfigured,
244
244
  walkProject,
245
245
  writeCompact
246
- } from "./token-goat-hook-chunk-XM4W3WCO.mjs";
246
+ } from "./token-goat-hook-chunk-A77A26A7.mjs";
247
247
  import {
248
248
  C,
249
249
  CONFIG_KEY_ENV_OVERRIDES,
@@ -294,6 +294,8 @@ import {
294
294
  normalizePath,
295
295
  pad,
296
296
  parse,
297
+ pushAll,
298
+ readConfigSource,
297
299
  recordStat,
298
300
  redactIfDotenv,
299
301
  redactUrlQuery,
@@ -322,7 +324,7 @@ import {
322
324
  withFileLock,
323
325
  withRetryOnLock,
324
326
  writeJsonSettings
325
- } from "./token-goat-hook-chunk-2O7P4Z6Q.mjs";
327
+ } from "./token-goat-hook-chunk-Y2WHX2P3.mjs";
326
328
  import "./token-goat-hook-chunk-BUOCULAM.mjs";
327
329
  import {
328
330
  __export
@@ -5874,7 +5876,7 @@ function checkConfigValid(configPath2) {
5874
5876
  };
5875
5877
  }
5876
5878
  try {
5877
- const content = fs12.readFileSync(configPath2, "utf-8");
5879
+ const content = readConfigSource(configPath2);
5878
5880
  parse(content);
5879
5881
  return {
5880
5882
  name: "Config",
@@ -9562,7 +9564,7 @@ function collectTodoFiles(patterns) {
9562
9564
  try {
9563
9565
  const stat = fs16.statSync(abs);
9564
9566
  if (stat.isDirectory()) {
9565
- results.push(...walkProject(abs).files);
9567
+ pushAll(results, walkProject(abs).files);
9566
9568
  } else {
9567
9569
  results.push(abs);
9568
9570
  }
@@ -9580,7 +9582,7 @@ function cmdTodo(patterns, opts) {
9580
9582
  const files = collectTodoFiles(patterns);
9581
9583
  const items = [];
9582
9584
  for (const f of files) {
9583
- items.push(...scanFileForTodos(f, kindSet));
9585
+ pushAll(items, scanFileForTodos(f, kindSet));
9584
9586
  }
9585
9587
  if (opts.json === true) {
9586
9588
  process.stdout.write(JSON.stringify({ items }, null, 2) + "\n");
@@ -11333,7 +11335,7 @@ function reclaimIndex(dbPath, opts = {}) {
11333
11335
  db.prepare(`DELETE FROM "${table}"`).run();
11334
11336
  dropped[table] = before;
11335
11337
  }
11336
- })();
11338
+ }).immediate();
11337
11339
  if (tableExists(db, "symbols_fts")) {
11338
11340
  try {
11339
11341
  db.prepare(`INSERT INTO symbols_fts(symbols_fts) VALUES('rebuild')`).run();
@@ -11702,8 +11704,7 @@ function cmdConfig(opts) {
11702
11704
  let raw = {};
11703
11705
  let parseErr = null;
11704
11706
  try {
11705
- const text = fs19.readFileSync(cfgFile, "utf8");
11706
- raw = parse(text);
11707
+ raw = parse(readConfigSource(cfgFile));
11707
11708
  } catch (e) {
11708
11709
  const code = e.code;
11709
11710
  if (code !== "ENOENT") {
@@ -13447,7 +13448,7 @@ async function cmdMcpServe() {
13447
13448
  let StdioServerTransport;
13448
13449
  try {
13449
13450
  ;
13450
- ({ createMcpServer } = await import("./token-goat-hook-chunk-VU6VGZBM.mjs"));
13451
+ ({ createMcpServer } = await import("./token-goat-hook-chunk-6ODM3MP7.mjs"));
13451
13452
  ({ StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js"));
13452
13453
  } catch (err2) {
13453
13454
  process.stderr.write(
@@ -13468,7 +13469,7 @@ async function cmdHook(event, opts) {
13468
13469
  if (typeof opts.harness === "string" && opts.harness.length > 0) {
13469
13470
  process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
13470
13471
  }
13471
- const { relay } = await import("./token-goat-hook-chunk-J4HKWUWZ.mjs");
13472
+ const { relay } = await import("./token-goat-hook-chunk-QSCYNJ2B.mjs");
13472
13473
  await relay(event);
13473
13474
  }
13474
13475
  async function cmdInstall(opts) {
@@ -14325,7 +14326,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
14325
14326
  }
14326
14327
  async function cmdCompress(opts) {
14327
14328
  try {
14328
- const bashRunner = await import("./token-goat-hook-chunk-D6UJEFHX.mjs");
14329
+ const bashRunner = await import("./token-goat-hook-chunk-E257IGSN.mjs");
14329
14330
  if (opts.compress === false) {
14330
14331
  process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
14331
14332
  return;
@@ -10,11 +10,11 @@ import {
10
10
  selectFilter,
11
11
  shlexSplit,
12
12
  wrappedShell
13
- } from "./token-goat-hook-chunk-NIPXIAPA.mjs";
13
+ } from "./token-goat-hook-chunk-3ZDBWJDF.mjs";
14
14
  import {
15
15
  loadConfig,
16
16
  recordStat
17
- } from "./token-goat-hook-chunk-2O7P4Z6Q.mjs";
17
+ } from "./token-goat-hook-chunk-Y2WHX2P3.mjs";
18
18
  import "./token-goat-hook-chunk-BUOCULAM.mjs";
19
19
  import "./token-goat-hook-chunk-RFRLWOQH.mjs";
20
20
 
@@ -50,7 +50,7 @@ import {
50
50
  walkProject,
51
51
  yamlLineClosesQuote,
52
52
  yamlOpenQuoteAfter
53
- } from "./token-goat-hook-chunk-XM4W3WCO.mjs";
53
+ } from "./token-goat-hook-chunk-A77A26A7.mjs";
54
54
  import {
55
55
  PER_FILE_COUNTERFACTUAL_CEILING,
56
56
  _detectOpenQuote,
@@ -83,6 +83,7 @@ import {
83
83
  loadConfig,
84
84
  normalizePath,
85
85
  offsetToLine,
86
+ pushAll,
86
87
  recordStat,
87
88
  redactIfDotenv,
88
89
  redactSecrets,
@@ -100,7 +101,7 @@ import {
100
101
  unsupportedLanguageName,
101
102
  windowsCmdQuoteArg,
102
103
  withExtension
103
- } from "./token-goat-hook-chunk-2O7P4Z6Q.mjs";
104
+ } from "./token-goat-hook-chunk-Y2WHX2P3.mjs";
104
105
  import {
105
106
  registerReset
106
107
  } from "./token-goat-hook-chunk-BUOCULAM.mjs";
@@ -563,9 +564,9 @@ function evalJsonPath(data, ops) {
563
564
  } else if (op.kind === "wildcard") {
564
565
  fanned = true;
565
566
  if (Array.isArray(item)) {
566
- next.push(...item);
567
+ pushAll(next, item);
567
568
  } else if (typeof item === "object" && item !== null) {
568
- next.push(...Object.values(item));
569
+ pushAll(next, Object.values(item));
569
570
  }
570
571
  } else {
571
572
  fanned = true;
@@ -997,7 +998,7 @@ function queryXml(xmlText, pathStr) {
997
998
  const attrName = step.attributeSelect;
998
999
  for (const cand of currentCandidates) {
999
1000
  if (attrName === "*") {
1000
- attrVals.push(...Object.values(cand.attributes));
1001
+ pushAll(attrVals, Object.values(cand.attributes));
1001
1002
  } else if (cand.attributes[attrName] !== void 0) {
1002
1003
  attrVals.push(cand.attributes[attrName]);
1003
1004
  }
@@ -1046,7 +1047,7 @@ function queryXml(xmlText, pathStr) {
1046
1047
  if (step.allIndices || matching.length > 1 || step.attributeFilter !== void 0) {
1047
1048
  hasFanned = true;
1048
1049
  }
1049
- nextCandidates.push(...matching);
1050
+ pushAll(nextCandidates, matching);
1050
1051
  }
1051
1052
  }
1052
1053
  currentCandidates = nextCandidates;
@@ -6552,6 +6553,10 @@ function mergeListingJson(files, blocks, anyOk) {
6552
6553
  const payload = { items, truncated, totalCount, ...errors.length > 0 ? { errors } : {} };
6553
6554
  return { text: JSON.stringify(payload, null, 2), code: anyOk ? 0 : 1 };
6554
6555
  }
6556
+ function symbolCountLabel(shown, truncated, trueCount) {
6557
+ if (!truncated || trueCount === void 0 || trueCount <= shown) return countNoun(shown, "symbol");
6558
+ return `${shown} of ${countNoun(trueCount, "symbol")}`;
6559
+ }
6555
6560
  function runSkeleton(opts) {
6556
6561
  const multiFiles = parseMultiFileSpec(opts.file);
6557
6562
  if (multiFiles !== null) return runPerFileListing(multiFiles, (file) => runSkeleton({ ...opts, file, includeFilePath: true }), opts.json === true);
@@ -6584,7 +6589,7 @@ function runSkeleton(opts) {
6584
6589
  return { text: text2, code: 0 };
6585
6590
  }
6586
6591
  const totalLines = filtered.length > 0 ? Math.max(...filtered.map((s) => s.lineEnd)) : 0;
6587
- const lines = [`# Skeleton: ${opts.file} (${countNoun(filtered.length, "symbol")}, ${countNoun(totalLines, "line")})`];
6592
+ const lines = [`# Skeleton: ${opts.file} (${symbolCountLabel(filtered.length, symbolsTruncated, trueSymbolCount)}, ${countNoun(totalLines, "line")})`];
6588
6593
  if (filtered.length === 0 && preFilterCount > 0) lines.push(filteredToEmptyNotice(preFilterCount, opts.minLines, opts.grep));
6589
6594
  for (const sym of filtered) {
6590
6595
  const lineStr = sym.lineStart.toString().padStart(6);
@@ -6626,7 +6631,7 @@ function runOutline(opts) {
6626
6631
  recordReadStat("outline", fullSourceBytes, text2, opts.file);
6627
6632
  return { text: text2, code: 0 };
6628
6633
  }
6629
- const lines = [`# Outline: ${opts.file} (${countNoun(filtered.length, "symbol")})`];
6634
+ const lines = [`# Outline: ${opts.file} (${symbolCountLabel(filtered.length, symbolsTruncated, trueSymbolCount)})`];
6630
6635
  if (filtered.length === 0 && preFilterCount > 0) lines.push(filteredToEmptyNotice(preFilterCount, opts.minLines, opts.grep));
6631
6636
  for (const sym of filtered) {
6632
6637
  const rangeStr = `${sym.lineStart.toString().padStart(4)}-${sym.lineEnd.toString().padEnd(6)}`;
@@ -4,14 +4,14 @@ import {
4
4
  buildEvent,
5
5
  relay,
6
6
  relayInProcess
7
- } from "./token-goat-hook-chunk-4POU6OHK.mjs";
8
- import "./token-goat-hook-chunk-NIPXIAPA.mjs";
7
+ } from "./token-goat-hook-chunk-BDR6C6IE.mjs";
8
+ import "./token-goat-hook-chunk-3ZDBWJDF.mjs";
9
9
  import {
10
10
  MAX_STDIN_BYTES,
11
11
  readStdinJson
12
- } from "./token-goat-hook-chunk-CRBMPT74.mjs";
13
- import "./token-goat-hook-chunk-XM4W3WCO.mjs";
14
- import "./token-goat-hook-chunk-2O7P4Z6Q.mjs";
12
+ } from "./token-goat-hook-chunk-5UH54CW6.mjs";
13
+ import "./token-goat-hook-chunk-A77A26A7.mjs";
14
+ import "./token-goat-hook-chunk-Y2WHX2P3.mjs";
15
15
  import "./token-goat-hook-chunk-BUOCULAM.mjs";
16
16
  import "./token-goat-hook-chunk-RFRLWOQH.mjs";
17
17
  export {