token-goat 2.9.15 → 2.9.16

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 (37) hide show
  1. package/dist/{token-goat-chunk-ASYEPR3S.mjs → token-goat-chunk-2IEIBVVD.mjs} +7 -3
  2. package/dist/{token-goat-chunk-LCZBPOIN.mjs → token-goat-chunk-2PCFAQAS.mjs} +66 -51
  3. package/dist/{token-goat-chunk-PM76YS22.mjs → token-goat-chunk-3H6FQT62.mjs} +1 -1
  4. package/dist/{token-goat-chunk-C5JIO6HK.mjs → token-goat-chunk-4DC6DDIB.mjs} +5 -5
  5. package/dist/{token-goat-chunk-YQ7WI2CO.mjs → token-goat-chunk-5USHO7B6.mjs} +393 -3957
  6. package/dist/{token-goat-chunk-2X2EBBC6.mjs → token-goat-chunk-63QWJ6UM.mjs} +2 -2
  7. package/dist/{token-goat-chunk-NDRP4KJQ.mjs → token-goat-chunk-BFNTLGVA.mjs} +226 -50
  8. package/dist/token-goat-chunk-BGHSSJUA.mjs +102 -0
  9. package/dist/{token-goat-chunk-IVUQLQWN.mjs → token-goat-chunk-DMQ32ZSR.mjs} +5 -3
  10. package/dist/{token-goat-chunk-SFAS46RE.mjs → token-goat-chunk-EJCY6KHO.mjs} +2 -2
  11. package/dist/{token-goat-chunk-Z6UXPYJA.mjs → token-goat-chunk-F2ARFHLJ.mjs} +1 -1
  12. package/dist/{token-goat-chunk-YKG35VHC.mjs → token-goat-chunk-GIMGT34T.mjs} +1 -1
  13. package/dist/{token-goat-chunk-SZWYESBS.mjs → token-goat-chunk-GMXBQS6O.mjs} +155 -54
  14. package/dist/{token-goat-chunk-S4XRY446.mjs → token-goat-chunk-H3DXI6VD.mjs} +4 -3
  15. package/dist/{token-goat-chunk-6DLVZDB6.mjs → token-goat-chunk-LJL6FGDS.mjs} +13 -12
  16. package/dist/{token-goat-chunk-NEI4NC54.mjs → token-goat-chunk-LKSXAMJB.mjs} +7 -2
  17. package/dist/{token-goat-chunk-A4JYKD5H.mjs → token-goat-chunk-M2R4UQ3B.mjs} +2 -2
  18. package/dist/{token-goat-chunk-MZDIJJ3R.mjs → token-goat-chunk-MA5BZ2KI.mjs} +40 -3
  19. package/dist/{token-goat-chunk-GIIHUSZX.mjs → token-goat-chunk-MIL62GMN.mjs} +41 -11
  20. package/dist/{token-goat-chunk-NU7TLMQK.mjs → token-goat-chunk-NAMH252H.mjs} +10 -7
  21. package/dist/{token-goat-chunk-DQ4J5AFF.mjs → token-goat-chunk-NOBZV7PM.mjs} +69 -18
  22. package/dist/{token-goat-chunk-5V7DAC7V.mjs → token-goat-chunk-NQZCSVN2.mjs} +10 -3
  23. package/dist/{token-goat-chunk-7ZYK25AO.mjs → token-goat-chunk-OCI25AXY.mjs} +4 -4
  24. package/dist/{token-goat-chunk-NDPO7GAH.mjs → token-goat-chunk-QMZMHQRR.mjs} +21 -20
  25. package/dist/{token-goat-chunk-K7F2BFIK.mjs → token-goat-chunk-R3X5TCPB.mjs} +1 -1
  26. package/dist/token-goat-chunk-RRNZMM3A.mjs +3364 -0
  27. package/dist/{token-goat-chunk-ATIFTMRC.mjs → token-goat-chunk-ULA4WCED.mjs} +7 -7
  28. package/dist/{token-goat-chunk-OUGNPMDA.mjs → token-goat-chunk-UMXD2M7O.mjs} +30 -14
  29. package/dist/{token-goat-chunk-YZX7EFG4.mjs → token-goat-chunk-UXHDBVUR.mjs} +1 -1
  30. package/dist/{token-goat-chunk-LT7JRU6K.mjs → token-goat-chunk-VVIYEFBI.mjs} +4 -4
  31. package/dist/{token-goat-chunk-BL5LNGBG.mjs → token-goat-chunk-XOHTFRDH.mjs} +2966 -3869
  32. package/dist/{token-goat-chunk-XEPXYDPI.mjs → token-goat-chunk-YPS64ACE.mjs} +11 -2
  33. package/dist/{token-goat-chunk-GMQQA7E4.mjs → token-goat-chunk-Z5VPAXTC.mjs} +2442 -722
  34. package/dist/{token-goat-chunk-3NSDDTGL.mjs → token-goat-chunk-ZEHFYJ7Z.mjs} +5 -5
  35. package/dist/token-goat-hook.mjs +13 -12
  36. package/dist/token-goat.core.mjs +21 -20
  37. package/package.json +1 -1
@@ -6,12 +6,13 @@ import {
6
6
  collectElements,
7
7
  collectParagraphTexts,
8
8
  decodeZipEntry,
9
+ inlineMathRuns,
9
10
  ooxmlPartBudget,
10
11
  ooxmlWorkDeadline,
11
12
  parseOoxmlPart,
12
13
  readOoxmlZip,
13
14
  sortNumberedParts
14
- } from "./token-goat-chunk-MZDIJJ3R.mjs";
15
+ } from "./token-goat-chunk-MA5BZ2KI.mjs";
15
16
  import {
16
17
  compileGuardedRegex
17
18
  } from "./token-goat-chunk-GMOUBOX4.mjs";
@@ -107,16 +108,19 @@ async function notesPathFor(entries, slidePath, budget) {
107
108
  }
108
109
  return null;
109
110
  }
111
+ function inlineSlideMath(xml) {
112
+ return inlineMathRuns(xml, '<a:r><a:t xml:space="preserve">', "</a:t></a:r>").replace(/<a14:m(?:\s[^>]*)?>/g, "").replace(/<\/a14:m>/g, "");
113
+ }
110
114
  async function parseSlide(entries, path, budget) {
111
115
  const xml = decodeZipEntry(entries, path, budget);
112
116
  if (xml === null) throw new Error(`missing part: ${path}`);
113
- return parseOoxmlPart(xml);
117
+ return parseOoxmlPart(inlineSlideMath(xml));
114
118
  }
115
119
  async function notesTextFor(entries, notesPath, budget) {
116
120
  if (notesPath === null) return "";
117
121
  const xml = decodeZipEntry(entries, notesPath, budget);
118
122
  if (xml === null) return "";
119
- const parsed = await parseOoxmlPart(xml);
123
+ const parsed = await parseOoxmlPart(inlineSlideMath(xml));
120
124
  const shapes = collectElements(parsed, "p:sp");
121
125
  const bodyShape = shapes.find((s) => shapePlaceholderType(s) === "body");
122
126
  return bodyShape !== void 0 ? shapeText(bodyShape) : flatSlideText(parsed);
@@ -1,5 +1,11 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ isOcrEngineAvailable,
5
+ isTextHeavy,
6
+ ocrImage,
7
+ ocrIntegrityFailed
8
+ } from "./token-goat-chunk-EJCY6KHO.mjs";
3
9
  import {
4
10
  formatSqliteQueryTable,
5
11
  formatSqliteSchema,
@@ -13,8 +19,10 @@ import {
13
19
  NOTEBOOK_CELL_LINES_SUFFIX,
14
20
  SKIP_DIRS,
15
21
  canShrinkFormat,
22
+ capJsonRows,
16
23
  emptyIndexMessage,
17
24
  enqueueDirtyPathSafe,
25
+ estimateTokens,
18
26
  fenceUntrusted,
19
27
  formatSymbolLocation,
20
28
  getEmbeddingCoverage,
@@ -30,29 +38,35 @@ import {
30
38
  scanAndRecord,
31
39
  searchEvidenceSemantically,
32
40
  shrinkImage,
41
+ trimToBudget,
33
42
  urlPolicyDenialReason,
34
43
  virtualIndexedScopeNote,
35
44
  walkProject
36
- } from "./token-goat-chunk-BL5LNGBG.mjs";
45
+ } from "./token-goat-chunk-XOHTFRDH.mjs";
37
46
  import {
38
- capJsonRows,
39
- estimateTokens,
40
- trimToBudget
41
- } from "./token-goat-chunk-YQ7WI2CO.mjs";
47
+ colorStdout,
48
+ isBlobStale,
49
+ loadBlob,
50
+ recordStat,
51
+ redactSecrets,
52
+ savedTokensFromBytes,
53
+ storeBlob,
54
+ stripAnsi
55
+ } from "./token-goat-chunk-DMQ32ZSR.mjs";
42
56
  import {
43
57
  extractPdfMeta,
44
58
  extractPdfOutline,
45
59
  extractPdfText,
46
60
  locatePdfPages,
47
61
  readPdfFileWithinBounds
48
- } from "./token-goat-chunk-NEI4NC54.mjs";
62
+ } from "./token-goat-chunk-LKSXAMJB.mjs";
49
63
  import {
50
64
  formatCsvProfile,
51
65
  formatCsvTable,
52
66
  parseWhereSpecs,
53
67
  profileCsv,
54
68
  queryCsv
55
- } from "./token-goat-chunk-YKG35VHC.mjs";
69
+ } from "./token-goat-chunk-GIMGT34T.mjs";
56
70
  import {
57
71
  MAX_ZIP_INPUT_BYTES,
58
72
  MAX_ZIP_OUTPUT_BYTES,
@@ -87,7 +101,7 @@ import {
87
101
  extractSolidity,
88
102
  extractThrift,
89
103
  stripLeadingAttributes
90
- } from "./token-goat-chunk-XEPXYDPI.mjs";
104
+ } from "./token-goat-chunk-YPS64ACE.mjs";
91
105
  import {
92
106
  MAX_OVER_FETCH,
93
107
  OVER_FETCH_FACTOR,
@@ -100,7 +114,7 @@ import {
100
114
  mergeNearbyHits,
101
115
  readSection,
102
116
  searchSemantic
103
- } from "./token-goat-chunk-NDRP4KJQ.mjs";
117
+ } from "./token-goat-chunk-BFNTLGVA.mjs";
104
118
  import {
105
119
  DEFAULT_QUERY_LIMIT,
106
120
  countRefs,
@@ -113,23 +127,7 @@ import {
113
127
  queryRefsByContext,
114
128
  querySymbols,
115
129
  searchSymbolsFts
116
- } from "./token-goat-chunk-2X2EBBC6.mjs";
117
- import {
118
- isOcrEngineAvailable,
119
- isTextHeavy,
120
- ocrImage,
121
- ocrIntegrityFailed
122
- } from "./token-goat-chunk-SFAS46RE.mjs";
123
- import {
124
- colorStdout,
125
- isBlobStale,
126
- loadBlob,
127
- recordStat,
128
- redactSecrets,
129
- savedTokensFromBytes,
130
- storeBlob,
131
- stripAnsi
132
- } from "./token-goat-chunk-IVUQLQWN.mjs";
130
+ } from "./token-goat-chunk-63QWJ6UM.mjs";
133
131
  import {
134
132
  FILENAME_LANGUAGE,
135
133
  TREE_SITTER_LANGUAGES,
@@ -148,7 +146,7 @@ import {
148
146
  partialRefsReason,
149
147
  redactIfDotenv,
150
148
  unsupportedLanguageName
151
- } from "./token-goat-chunk-K7F2BFIK.mjs";
149
+ } from "./token-goat-chunk-R3X5TCPB.mjs";
152
150
  import {
153
151
  fileIsAbsent,
154
152
  findProject,
@@ -158,7 +156,7 @@ import {
158
156
  loadConfig,
159
157
  resolveProjectRoot,
160
158
  shortFingerprint
161
- } from "./token-goat-chunk-S4XRY446.mjs";
159
+ } from "./token-goat-chunk-H3DXI6VD.mjs";
162
160
  import {
163
161
  registerReset
164
162
  } from "./token-goat-chunk-EEIDFMEM.mjs";
@@ -190,7 +188,7 @@ import {
190
188
  supportRequestLine,
191
189
  windowsCmdQuoteArg,
192
190
  withExtension
193
- } from "./token-goat-chunk-PM76YS22.mjs";
191
+ } from "./token-goat-chunk-3H6FQT62.mjs";
194
192
  import {
195
193
  UNTRUSTED_FILE_TAG,
196
194
  UNTRUSTED_GITHUB_TAG,
@@ -467,6 +465,7 @@ function queryJson(data, spec) {
467
465
  // src/read_spec.ts
468
466
  init_define_import_meta_env();
469
467
  import * as fs13 from "node:fs";
468
+ import * as path13 from "node:path";
470
469
 
471
470
  // src/read_commands.ts
472
471
  init_define_import_meta_env();
@@ -1593,12 +1592,12 @@ function runScope(opts) {
1593
1592
  emitErr(`Invalid line number: ${lineStr}`);
1594
1593
  return 1;
1595
1594
  }
1596
- const confined = fileConfinementRefusal("This file", file, void 0);
1595
+ const confined = fileConfinementRefusal("This file", file, opts.projectRoot);
1597
1596
  if (confined !== null) {
1598
1597
  emitErr(confined);
1599
1598
  return 1;
1600
1599
  }
1601
- const filePath = resolveIndexPath(file);
1600
+ const filePath = resolveIndexPath(file, opts.projectRoot ?? process.cwd());
1602
1601
  const enclosing = querySymbols({ filePath, enclosingLine: line, limit: ALL_SYMBOLS_IN_FILE_LIMIT }).sort((a, b) => b.lineStart - a.lineStart || a.lineEnd - b.lineEnd || a.name.localeCompare(b.name, "en"));
1603
1602
  if (enclosing.length === 0) {
1604
1603
  if (querySymbols({ filePath, limit: 1 }).length === 0) {
@@ -1643,7 +1642,7 @@ function buildImportGraph(cwd) {
1643
1642
  const files = getTrackedFiles(cwd);
1644
1643
  const filesByFoldedPath = /* @__PURE__ */ new Map();
1645
1644
  for (const f of files) filesByFoldedPath.set(foldPath(f), f);
1646
- const resolve7 = (fromFile, spec) => {
1645
+ const resolve8 = (fromFile, spec) => {
1647
1646
  if (!spec.startsWith(".")) return null;
1648
1647
  const dir = path3.dirname(fromFile);
1649
1648
  const strippedSpec = spec.replace(/\.(m?js|cjs)$/, "");
@@ -1670,7 +1669,7 @@ function buildImportGraph(cwd) {
1670
1669
  }
1671
1670
  const internal = [];
1672
1671
  for (const spec of extractImports(text, importsExtensionFor(file))) {
1673
- const resolved = resolve7(file, spec);
1672
+ const resolved = resolve8(file, spec);
1674
1673
  if (resolved === null) continue;
1675
1674
  internal.push(resolved);
1676
1675
  let importers = importedBy.get(resolved);
@@ -1682,7 +1681,7 @@ function buildImportGraph(cwd) {
1682
1681
  }
1683
1682
  graph.set(file, internal);
1684
1683
  }
1685
- return { files, graph, importedBy, resolve: resolve7 };
1684
+ return { files, graph, importedBy, resolve: resolve8 };
1686
1685
  }
1687
1686
 
1688
1687
  // src/modules.ts
@@ -2106,7 +2105,7 @@ function runArch(opts) {
2106
2105
  }
2107
2106
  const cwd = opts.cwd ?? process.cwd();
2108
2107
  const top = opts.top ?? 10;
2109
- const { files, graph, importedBy, resolve: resolve7 } = buildImportGraph(cwd);
2108
+ const { files, graph, importedBy, resolve: resolve8 } = buildImportGraph(cwd);
2110
2109
  if (files.length === 0 && opts.json !== true) {
2111
2110
  emit2(`no tracked files found under '${toDisplayPath(getDisplayRoot(cwd), cwd)}' (is it a git repo?). Nothing to analyse.`);
2112
2111
  return 0;
@@ -2118,7 +2117,7 @@ function runArch(opts) {
2118
2117
  const entryPointsTotal = allEntryPoints.length;
2119
2118
  const entryPoints = allEntryPoints.slice(0, top);
2120
2119
  const { cycles, truncated: cyclesTruncated } = findCyclesCapped(graph);
2121
- const moduleResult = opts.modules === true ? detectModules({ files, graph, importedBy, resolve: resolve7 }, cwd, top) : null;
2120
+ const moduleResult = opts.modules === true ? detectModules({ files, graph, importedBy, resolve: resolve8 }, cwd, top) : null;
2122
2121
  if (opts.json === true) {
2123
2122
  const modulePayload = moduleResult === null ? {} : { modules: moduleResult.modules, modulesTotal: moduleResult.modulesTotal, modulesTruncated: moduleResult.modules.length < moduleResult.modulesTotal, modularity: moduleResult.modularity, isolatedCount: moduleResult.isolatedCount, crossImports: moduleResult.crossImports, crossImportsTotal: moduleResult.crossImportsTotal, crossImportsTruncated: moduleResult.crossImports.length < moduleResult.crossImportsTotal, noImportEdges: moduleResult.noEdges };
2124
2123
  emit2(displaySafeJson({ hubs, hubsTotal, hubsTruncated: hubs.length < hubsTotal, entryPoints, entryPointsTotal, entryPointsTruncated: entryPoints.length < entryPointsTotal, cycles, ...cyclesTruncated ? { cyclesTruncated: true } : {}, ...modulePayload }));
@@ -2978,7 +2977,7 @@ async function captureOnce(url, ctx) {
2978
2977
  })();
2979
2978
  });
2980
2979
  try {
2981
- await page.goto(url, { waitUntil: "networkidle2", timeout: 3e4 });
2980
+ await page.goto(url, { waitUntil: "networkidle2", timeout: 6e4 });
2982
2981
  } catch (err) {
2983
2982
  if (hop.url !== null) return { redirectTo: hop.url };
2984
2983
  if (navRefusal.reason !== null) throw new Error(navRefusal.reason, { cause: err });
@@ -8263,7 +8262,7 @@ function filteredToEmptyNotice(preFilterCount, minLines, grep) {
8263
8262
  }
8264
8263
  function prepareSymbolListing(file, opts) {
8265
8264
  const resolved = resolveIndexPath(file, opts.projectRoot ?? process.cwd());
8266
- const confined = confinementRefusal("This file", resolved, confinedProjectRoot());
8265
+ const confined = confinementRefusal("This file", resolved, confinedProjectRoot(opts.projectRoot));
8267
8266
  if (confined !== null) return { kind: "confined", text: confined };
8268
8267
  if (opts.forceRefresh === true) {
8269
8268
  indexFileSyncPinned(resolved, globalDbPath());
@@ -8481,6 +8480,8 @@ ${emptyIndexMessage(rootDir2)}`, code: 1 };
8481
8480
  truncated,
8482
8481
  ...hiddenByExcludeTests > 0 ? { hiddenByExcludeTests } : {},
8483
8482
  ...hiddenByGrep > 0 ? { hiddenByGrep } : {},
8483
+ // Mirrors runRead's json branch: emitting the row verbatim would hand a JSON consumer a deleted file's stale body with no signal it is no longer live.
8484
+ ...fileIsGone(match.filePath) ? { deleted: true } : {},
8484
8485
  section
8485
8486
  };
8486
8487
  const jsonText = displaySafeJson(result);
@@ -8496,6 +8497,7 @@ ${emptyIndexMessage(rootDir2)}`, code: 1 };
8496
8497
  body,
8497
8498
  ""
8498
8499
  ];
8500
+ const warning = staleWarning(match.filePath);
8499
8501
  const hiddenNote = excludeTests && hiddenByExcludeTests > 0 ? ` (${excludeTestsHiddenNote(hiddenByExcludeTests)})` : "";
8500
8502
  if (callers.length === 0 && matchesGrep !== void 0 && preGrepCount > 0) {
8501
8503
  lines.push(`Callers (0): ${grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "caller", "callers").trim()}`);
@@ -8515,7 +8517,7 @@ ${emptyIndexMessage(rootDir2)}`, code: 1 };
8515
8517
  lines.push("");
8516
8518
  lines.push(`Section: ${section.heading} (lines ${section.lineStart}-${section.lineEnd})`);
8517
8519
  }
8518
- const text = guardText(trimBlankLines(lines).join("\n"), "symbol");
8520
+ const text = guardText(warning + trimBlankLines(lines).join("\n"), "symbol");
8519
8521
  if (opts.suppressStat !== true) recordReadStat("brief_view", fullSourceBytes, text, opts.spec);
8520
8522
  return { text, code: 0 };
8521
8523
  }
@@ -10723,10 +10725,11 @@ function runSymbol(opts) {
10723
10725
  }
10724
10726
  const matchesGrep = opts.grep !== void 0 ? compileGrepMatcher(opts.grep) : void 0;
10725
10727
  const excludeTests = opts.excludeTests === true;
10726
- const confinedRoot = confinedProjectRoot();
10727
- if (confinedRoot !== null) {
10728
+ const baseConfined = confinedProjectRoot();
10729
+ const confinedRoot = opts.projectRoot !== void 0 && baseConfined !== null && isProjectRootAllowed(opts.projectRoot, baseConfined) ? confinedProjectRoot(opts.projectRoot) ?? baseConfined : baseConfined;
10730
+ if (baseConfined !== null) {
10728
10731
  const requested = opts.projectRoot;
10729
- const projectDenial = requested === void 0 ? null : confinementRefusal("--project", requested, confinedRoot);
10732
+ const projectDenial = requested === void 0 || confinedRoot !== baseConfined ? null : confinementRefusal("--project", requested, baseConfined);
10730
10733
  if (projectDenial !== null) return { text: projectDenial, code: 1 };
10731
10734
  if (opts.file !== void 0) {
10732
10735
  const fileDenial = confinementRefusal("--file", resolveIndexPath(opts.file, requested ?? process.cwd()), confinedRoot);
@@ -11179,9 +11182,11 @@ function runRefs(opts) {
11179
11182
  emitErr4(`--top must be a positive number, got: ${opts.top}`);
11180
11183
  return 1;
11181
11184
  }
11182
- const confinedRoot = confinedProjectRoot();
11183
- if (confinedRoot !== null) {
11184
- const projectDenial = opts.projectRoot === void 0 ? null : confinementRefusal("--project", opts.projectRoot, confinedRoot);
11185
+ const baseConfined = confinedProjectRoot();
11186
+ const confinedRoot = opts.projectRoot !== void 0 && baseConfined !== null && isProjectRootAllowed(opts.projectRoot, baseConfined) ? confinedProjectRoot(opts.projectRoot) ?? baseConfined : baseConfined;
11187
+ if (baseConfined !== null) {
11188
+ const requested = opts.projectRoot;
11189
+ const projectDenial = requested === void 0 || confinedRoot !== baseConfined ? null : confinementRefusal("--project", requested, baseConfined);
11185
11190
  if (projectDenial !== null) {
11186
11191
  emitErr4(projectDenial);
11187
11192
  return 1;
@@ -11835,6 +11840,7 @@ async function runSemantic(query, opts) {
11835
11840
  mergedHits.forEach((h, denseRank) => {
11836
11841
  const enclosing = resolveEnclosingSymbol(h.filePath, h.startLine);
11837
11842
  const key = enclosing !== null ? `${h.filePath}::${enclosing.name}@${enclosing.lineStart}` : `${h.filePath}::L${h.startLine}`;
11843
+ if (fused.has(key)) return;
11838
11844
  fused.set(key, {
11839
11845
  filePath: h.filePath,
11840
11846
  startLine: h.startLine,
@@ -12164,15 +12170,24 @@ function formatAmbiguity(symbol, file, candidates, explicitRoot, commandName = "
12164
12170
  }
12165
12171
  return lines.join("\n");
12166
12172
  }
12167
- function confinedProjectRoot() {
12168
- return loadConfig().indexing.cross_project_symbols ? null : resolveProjectRoot();
12173
+ function confinedProjectRoot(explicitRoot) {
12174
+ if (loadConfig().indexing.cross_project_symbols) return null;
12175
+ return resolveProjectRoot(explicitRoot !== void 0 && explicitRoot.trim().length > 0 ? { project: explicitRoot } : {});
12176
+ }
12177
+ function isProjectRootAllowed(candidateRoot, baseConfinedRoot) {
12178
+ if (isInsideRoot(candidateRoot, baseConfinedRoot)) return true;
12179
+ const allowedRoots = loadConfig().mcp.allowed_roots;
12180
+ if (allowedRoots.length > 0 && allowedRoots.some((allowed) => isInsideRoot(candidateRoot, path13.resolve(allowed)))) {
12181
+ return true;
12182
+ }
12183
+ return false;
12169
12184
  }
12170
12185
  function confinementRefusal(label, resolved, root) {
12171
12186
  if (root === null || isInsideRoot(resolved, root)) return null;
12172
12187
  return `${label} is outside this project root, and indexing.cross_project_symbols = false confines symbol lookups to it: ${toDisplayPath(root, resolved)}`;
12173
12188
  }
12174
12189
  function fileConfinementRefusal(label, file, projectRoot) {
12175
- const root = confinedProjectRoot();
12190
+ const root = confinedProjectRoot(projectRoot);
12176
12191
  if (root === null) return null;
12177
12192
  return confinementRefusal(label, resolveIndexPath(file, projectRoot ?? process.cwd()), root);
12178
12193
  }
@@ -12183,7 +12198,7 @@ function resolveSymbolSpec(spec, forceRefresh, projectRoot) {
12183
12198
  const symbol = anchorMatch !== null ? anchorMatch[1] : rawSymbol;
12184
12199
  const lineAnchor = anchorMatch !== null ? parseInt(anchorMatch[2], 10) : void 0;
12185
12200
  const resolved = resolveIndexPath(file, projectRoot ?? process.cwd());
12186
- const confined = confinementRefusal("This file", resolved, confinedProjectRoot());
12201
+ const confined = confinementRefusal("This file", resolved, confinedProjectRoot(projectRoot));
12187
12202
  if (confined !== null) return { kind: "confined", message: confined };
12188
12203
  if (forceRefresh === true) {
12189
12204
  indexFileSyncPinned(resolved, globalDbPath());
@@ -12290,7 +12305,7 @@ function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
12290
12305
  // src/content_store.ts
12291
12306
  init_define_import_meta_env();
12292
12307
  import { deflateRawSync } from "node:zlib";
12293
- import * as path13 from "node:path";
12308
+ import * as path14 from "node:path";
12294
12309
  var CONTENT_MAX_INPUT_CHARS = 512 * 1024;
12295
12310
  var CONTENT_MAX_ITEMS = 256;
12296
12311
  var CONTENT_MAX_BYTES = 32 * 1024 * 1024;
@@ -12313,7 +12328,7 @@ function contentId(text) {
12313
12328
  return `tg_${shortFingerprint(text)}`;
12314
12329
  }
12315
12330
  function normalizeProjectRoot(projectRoot) {
12316
- const candidate = path13.resolve(projectRoot ?? process.cwd());
12331
+ const candidate = path14.resolve(projectRoot ?? process.cwd());
12317
12332
  return findProject(candidate)?.root ?? candidate;
12318
12333
  }
12319
12334
  function handoffId(name, projectRoot) {
@@ -21,7 +21,7 @@ init_define_import_meta_env();
21
21
  import { createRequire } from "node:module";
22
22
  function resolveVersion() {
23
23
  if (true) {
24
- return "2.9.15";
24
+ return "2.9.16";
25
25
  }
26
26
  const require2 = createRequire(import.meta.url);
27
27
  const pkg = require2("../package.json");
@@ -20,17 +20,17 @@ import {
20
20
  setOcrTimeoutForTesting,
21
21
  setTesseractEntryForTesting,
22
22
  verifyOcrLangCache
23
- } from "./token-goat-chunk-SFAS46RE.mjs";
24
- import "./token-goat-chunk-IVUQLQWN.mjs";
25
- import "./token-goat-chunk-K7F2BFIK.mjs";
23
+ } from "./token-goat-chunk-EJCY6KHO.mjs";
24
+ import "./token-goat-chunk-DMQ32ZSR.mjs";
25
+ import "./token-goat-chunk-R3X5TCPB.mjs";
26
26
  import {
27
27
  DEFAULT_OCR_LANG,
28
28
  isSupportedOcrLang,
29
29
  resolveOcrLangs
30
- } from "./token-goat-chunk-S4XRY446.mjs";
30
+ } from "./token-goat-chunk-H3DXI6VD.mjs";
31
31
  import "./token-goat-chunk-EEIDFMEM.mjs";
32
32
  import "./token-goat-chunk-OSUFN2FV.mjs";
33
- import "./token-goat-chunk-PM76YS22.mjs";
33
+ import "./token-goat-chunk-3H6FQT62.mjs";
34
34
  import "./token-goat-chunk-ERTXEKB6.mjs";
35
35
  import "./token-goat-chunk-GMOUBOX4.mjs";
36
36
  import "./token-goat-chunk-A37V4PBF.mjs";