@lzehrung/codegraph 2.3.7 → 2.3.9

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 (75) hide show
  1. package/codegraph-skill/codegraph/SKILL.md +3 -0
  2. package/dist/agent/query-index/content.d.ts.map +1 -1
  3. package/dist/agent/query-index/content.js +8 -4
  4. package/dist/agent/query-index/content.js.map +1 -1
  5. package/dist/agent/renamePreview.js +4 -3
  6. package/dist/agent/renamePreview.js.map +1 -1
  7. package/dist/agent/session.d.ts.map +1 -1
  8. package/dist/agent/session.js +12 -0
  9. package/dist/agent/session.js.map +1 -1
  10. package/dist/bin/cli.js +459 -119
  11. package/dist/bin/queryIndexWorker.js +32 -13
  12. package/dist/documentLinks/check.d.ts.map +1 -1
  13. package/dist/documentLinks/check.js +5 -3
  14. package/dist/documentLinks/check.js.map +1 -1
  15. package/dist/duplicates/units.d.ts.map +1 -1
  16. package/dist/duplicates/units.js +23 -8
  17. package/dist/duplicates/units.js.map +1 -1
  18. package/dist/graph-builder.d.ts.map +1 -1
  19. package/dist/graph-builder.js +2 -2
  20. package/dist/graph-builder.js.map +1 -1
  21. package/dist/graph-edge-collector.d.ts.map +1 -1
  22. package/dist/graph-edge-collector.js +19 -14
  23. package/dist/graph-edge-collector.js.map +1 -1
  24. package/dist/graphs/unresolved.d.ts.map +1 -1
  25. package/dist/graphs/unresolved.js +12 -4
  26. package/dist/graphs/unresolved.js.map +1 -1
  27. package/dist/impact/callCompatibility.js +2 -2
  28. package/dist/impact/callCompatibility.js.map +1 -1
  29. package/dist/impact/map.js +5 -5
  30. package/dist/impact/map.js.map +1 -1
  31. package/dist/indexer/build-cache/module-cache.js +2 -2
  32. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  33. package/dist/indexer/build-index.d.ts.map +1 -1
  34. package/dist/indexer/build-index.js +20 -6
  35. package/dist/indexer/build-index.js.map +1 -1
  36. package/dist/indexer/build-workers.d.ts +4 -0
  37. package/dist/indexer/build-workers.d.ts.map +1 -1
  38. package/dist/indexer/build-workers.js +9 -5
  39. package/dist/indexer/build-workers.js.map +1 -1
  40. package/dist/indexer/navigation-references.d.ts.map +1 -1
  41. package/dist/indexer/navigation-references.js +2 -2
  42. package/dist/indexer/navigation-references.js.map +1 -1
  43. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  44. package/dist/indexer/navigation-resolve.js +77 -66
  45. package/dist/indexer/navigation-resolve.js.map +1 -1
  46. package/dist/indexer/navigation.d.ts.map +1 -1
  47. package/dist/indexer/navigation.js +6 -4
  48. package/dist/indexer/navigation.js.map +1 -1
  49. package/dist/indexer/parse-context.d.ts +1 -1
  50. package/dist/indexer/parse-context.d.ts.map +1 -1
  51. package/dist/indexer/parse-context.js +6 -2
  52. package/dist/indexer/parse-context.js.map +1 -1
  53. package/dist/indexer/reference-context.d.ts.map +1 -1
  54. package/dist/indexer/reference-context.js +2 -2
  55. package/dist/indexer/reference-context.js.map +1 -1
  56. package/dist/languages/filePrep.d.ts +11 -6
  57. package/dist/languages/filePrep.d.ts.map +1 -1
  58. package/dist/languages/filePrep.js +1 -1
  59. package/dist/languages/filePrep.js.map +1 -1
  60. package/dist/languages.d.ts +16 -0
  61. package/dist/languages.d.ts.map +1 -1
  62. package/dist/languages.js +41 -8
  63. package/dist/languages.js.map +1 -1
  64. package/dist/review/risk.js +2 -2
  65. package/dist/review/risk.js.map +1 -1
  66. package/dist/sql/sourceGraph.d.ts.map +1 -1
  67. package/dist/sql/sourceGraph.js +2 -2
  68. package/dist/sql/sourceGraph.js.map +1 -1
  69. package/dist/util/lazySymbols.js +2 -2
  70. package/dist/util/lazySymbols.js.map +1 -1
  71. package/dist/util/specifiers.d.ts +12 -0
  72. package/dist/util/specifiers.d.ts.map +1 -1
  73. package/dist/util/specifiers.js +271 -0
  74. package/dist/util/specifiers.js.map +1 -1
  75. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -4584,7 +4584,9 @@ __export(languages_exports, {
4584
4584
  languageExtensionPatterns: () => languageExtensionPatterns,
4585
4585
  normalizeLanguageExtensions: () => normalizeLanguageExtensions,
4586
4586
  supportById: () => supportById,
4587
- supportForFile: () => supportForFile
4587
+ supportForFile: () => supportForFile,
4588
+ supportForFileWithSource: () => supportForFileWithSource,
4589
+ supportForFileWithoutHeaderSample: () => supportForFileWithoutHeaderSample
4588
4590
  });
4589
4591
  import fs5 from "node:fs";
4590
4592
  import path4 from "node:path";
@@ -4628,6 +4630,8 @@ function languageExtensionPatterns(extensions) {
4628
4630
  return Object.keys(normalizeLanguageExtensions(extensions) ?? {}).map(caseInsensitiveExtensionPattern);
4629
4631
  }
4630
4632
  function mappedSupportForFile(filename, extensionMap) {
4633
+ if (!extensionMap)
4634
+ return void 0;
4631
4635
  const mappings = Object.entries(normalizeLanguageExtensions(extensionMap) ?? {}).sort((left, right) => right[0].length - left[0].length || left[0].localeCompare(right[0]));
4632
4636
  const lowerFilename = filename.toLowerCase();
4633
4637
  for (const [extension, languageId] of mappings) {
@@ -4637,19 +4641,36 @@ function mappedSupportForFile(filename, extensionMap) {
4637
4641
  }
4638
4642
  return void 0;
4639
4643
  }
4640
- function supportForFile(filename, extensionMap) {
4641
- const mapped = extensionMap ? mappedSupportForFile(filename, extensionMap) : void 0;
4644
+ function supportForFileWithoutHeaderSample(filename, extensionMap) {
4645
+ const mapped = mappedSupportForFile(filename, extensionMap);
4642
4646
  if (mapped)
4643
4647
  return mapped;
4644
4648
  const ext = path4.extname(filename).toLowerCase();
4645
- if (ext === ".h") {
4646
- const sample = readFileSample(filename);
4647
- if (sample && isLikelyCppHeader(sample))
4648
- return CPP_SUPPORT;
4649
- return C_SUPPORT;
4650
- }
4651
4649
  return LANGUAGE_SUPPORTS.find((s) => s.matchExts.includes(ext));
4652
4650
  }
4651
+ function supportForFile(filename, extensionMap) {
4652
+ if (path4.extname(filename).toLowerCase() !== ".h") {
4653
+ return supportForFileWithoutHeaderSample(filename, extensionMap);
4654
+ }
4655
+ const mapped = mappedSupportForFile(filename, extensionMap);
4656
+ if (mapped)
4657
+ return mapped;
4658
+ const sample = readFileSample(filename);
4659
+ if (sample && isLikelyCppHeader(sample))
4660
+ return CPP_SUPPORT;
4661
+ return C_SUPPORT;
4662
+ }
4663
+ function supportForFileWithSource(filename, source, extensionMap) {
4664
+ if (path4.extname(filename).toLowerCase() !== ".h") {
4665
+ return supportForFileWithoutHeaderSample(filename, extensionMap);
4666
+ }
4667
+ const mapped = mappedSupportForFile(filename, extensionMap);
4668
+ if (mapped)
4669
+ return mapped;
4670
+ if (isLikelyCppHeader(source.slice(0, HEADER_SAMPLE_SIZE)))
4671
+ return CPP_SUPPORT;
4672
+ return C_SUPPORT;
4673
+ }
4653
4674
  function supportById(id) {
4654
4675
  return LANGUAGE_SUPPORTS.find((s) => s.id === id);
4655
4676
  }
@@ -19547,7 +19568,7 @@ async function prepareSourceInput(file2, opts) {
19547
19568
  const rawSource2 = opts?.source ?? await fsp14.readFile(file2, "utf8");
19548
19569
  return prepareSFCSourceInput(rawSource2, framework);
19549
19570
  }
19550
- const sup = supportForFile(file2, opts?.languageExtensions);
19571
+ const sup = opts?.support ?? supportForFile(file2, opts?.languageExtensions);
19551
19572
  if (!sup)
19552
19573
  throw new UnsupportedParserInputError(file2);
19553
19574
  const rawSource = opts?.source ?? await fsp14.readFile(file2, "utf8");
@@ -21827,6 +21848,243 @@ function extractJsTsDynamicSpecifiers(source, fromFile, projectRoot) {
21827
21848
  }
21828
21849
  return out;
21829
21850
  }
21851
+ function maskPythonString(source, mask, start) {
21852
+ const quote = source[start];
21853
+ const triple = source[start + 1] === quote && source[start + 2] === quote;
21854
+ const delimiterLength = triple ? 3 : 1;
21855
+ for (let offset = 0; offset < delimiterLength; offset += 1) {
21856
+ mask[start + offset] = 1;
21857
+ }
21858
+ let index = start + delimiterLength;
21859
+ while (index < source.length) {
21860
+ const ch = source[index];
21861
+ if (!triple && (ch === "\n" || ch === "\r"))
21862
+ return index;
21863
+ mask[index] = 1;
21864
+ if (ch === "\\") {
21865
+ const nextIndex = index + 1;
21866
+ if (nextIndex < source.length)
21867
+ mask[nextIndex] = 1;
21868
+ index += 2;
21869
+ continue;
21870
+ }
21871
+ if (ch === quote) {
21872
+ if (!triple)
21873
+ return index + 1;
21874
+ if (source[index + 1] === quote && source[index + 2] === quote) {
21875
+ mask[index + 1] = 1;
21876
+ mask[index + 2] = 1;
21877
+ return index + delimiterLength;
21878
+ }
21879
+ }
21880
+ index += 1;
21881
+ }
21882
+ return source.length;
21883
+ }
21884
+ function buildPythonNonCodeMask(source) {
21885
+ if (!source.includes("#") && !source.includes("'") && !source.includes('"'))
21886
+ return void 0;
21887
+ const mask = new Uint8Array(source.length);
21888
+ for (let index = 0; index < source.length; index += 1) {
21889
+ const ch = source[index];
21890
+ if (ch === "#") {
21891
+ while (index < source.length && source[index] !== "\n" && source[index] !== "\r") {
21892
+ mask[index] = 1;
21893
+ index += 1;
21894
+ }
21895
+ index -= 1;
21896
+ continue;
21897
+ }
21898
+ if (ch === "'" || ch === '"') {
21899
+ index = maskPythonString(source, mask, index) - 1;
21900
+ }
21901
+ }
21902
+ return mask;
21903
+ }
21904
+ function decodePythonStringContent(content, prefix) {
21905
+ if (prefix.includes("r"))
21906
+ return content;
21907
+ let decoded = "";
21908
+ for (let index = 0; index < content.length; index += 1) {
21909
+ const ch = content[index];
21910
+ if (ch !== "\\") {
21911
+ decoded += ch;
21912
+ continue;
21913
+ }
21914
+ index += 1;
21915
+ const escape2 = content[index];
21916
+ if (escape2 === void 0)
21917
+ return null;
21918
+ const simpleEscape = PYTHON_SIMPLE_STRING_ESCAPES[escape2];
21919
+ if (simpleEscape !== void 0) {
21920
+ decoded += simpleEscape;
21921
+ continue;
21922
+ }
21923
+ if (escape2 === "\n")
21924
+ continue;
21925
+ if (escape2 === "\r") {
21926
+ if (content[index + 1] === "\n")
21927
+ index += 1;
21928
+ continue;
21929
+ }
21930
+ let hexLength = 0;
21931
+ if (escape2 === "x")
21932
+ hexLength = 2;
21933
+ else if (escape2 === "u")
21934
+ hexLength = 4;
21935
+ else if (escape2 === "U")
21936
+ hexLength = 8;
21937
+ if (hexLength) {
21938
+ const digits = content.slice(index + 1, index + 1 + hexLength);
21939
+ if (digits.length !== hexLength || !/^[0-9a-fA-F]+$/.test(digits))
21940
+ return null;
21941
+ const codePoint = Number.parseInt(digits, 16);
21942
+ if (codePoint > 1114111)
21943
+ return null;
21944
+ decoded += String.fromCodePoint(codePoint);
21945
+ index += hexLength;
21946
+ continue;
21947
+ }
21948
+ if (escape2 >= "0" && escape2 <= "7") {
21949
+ let end = index + 1;
21950
+ while (end < content.length && end - index < 3) {
21951
+ const digit = content[end];
21952
+ if (digit < "0" || digit > "7")
21953
+ break;
21954
+ end += 1;
21955
+ }
21956
+ decoded += String.fromCodePoint(Number.parseInt(content.slice(index, end), 8));
21957
+ index = end - 1;
21958
+ continue;
21959
+ }
21960
+ decoded += `\\${escape2}`;
21961
+ }
21962
+ return decoded;
21963
+ }
21964
+ function parsePythonStaticStringLiteral(source, start) {
21965
+ let quoteIndex = start;
21966
+ let prefixLength = 0;
21967
+ while (prefixLength < 2) {
21968
+ const prefixCharacter = source[quoteIndex];
21969
+ if (!prefixCharacter || !"rRuUfF".includes(prefixCharacter))
21970
+ break;
21971
+ quoteIndex += 1;
21972
+ prefixLength += 1;
21973
+ }
21974
+ const prefix = source.slice(start, quoteIndex).toLowerCase();
21975
+ if (!["", "r", "u", "f", "fr", "rf"].includes(prefix))
21976
+ return null;
21977
+ const quote = source[quoteIndex];
21978
+ if (quote !== "'" && quote !== '"')
21979
+ return null;
21980
+ const triple = source[quoteIndex + 1] === quote && source[quoteIndex + 2] === quote;
21981
+ const delimiterLength = triple ? 3 : 1;
21982
+ const contentStart = quoteIndex + delimiterLength;
21983
+ for (let index = contentStart; index < source.length; index += 1) {
21984
+ const ch = source[index];
21985
+ if (!triple && (ch === "\n" || ch === "\r"))
21986
+ return null;
21987
+ if (ch === "\\") {
21988
+ index += 1;
21989
+ continue;
21990
+ }
21991
+ if (ch !== quote)
21992
+ continue;
21993
+ if (triple && (source[index + 1] !== quote || source[index + 2] !== quote))
21994
+ continue;
21995
+ const value = decodePythonStringContent(source.slice(contentStart, index), prefix);
21996
+ if (value === null)
21997
+ return null;
21998
+ return { value, end: index + delimiterLength };
21999
+ }
22000
+ return null;
22001
+ }
22002
+ function skipPythonExpressionTrivia(source, start) {
22003
+ let index = start;
22004
+ while (index < source.length) {
22005
+ while (index < source.length && /\s/.test(source[index]))
22006
+ index += 1;
22007
+ if (source[index] !== "#")
22008
+ break;
22009
+ while (index < source.length && source[index] !== "\n" && source[index] !== "\r")
22010
+ index += 1;
22011
+ }
22012
+ return index;
22013
+ }
22014
+ function parsePythonStaticStringExpression(source, start) {
22015
+ let index = skipPythonExpressionTrivia(source, start);
22016
+ let value = "";
22017
+ let literalCount = 0;
22018
+ while (true) {
22019
+ const literal2 = parsePythonStaticStringLiteral(source, index);
22020
+ if (!literal2)
22021
+ break;
22022
+ value += literal2.value;
22023
+ literalCount += 1;
22024
+ index = skipPythonExpressionTrivia(source, literal2.end);
22025
+ }
22026
+ if (!literalCount || source[index] !== "," && source[index] !== ")")
22027
+ return null;
22028
+ return value;
22029
+ }
22030
+ function collectPythonDynamicImportAliases(source) {
22031
+ const importlibAliases = /* @__PURE__ */ new Set(["importlib"]);
22032
+ const importModuleAliases = /* @__PURE__ */ new Set();
22033
+ const cleaned = stripPythonCommentsAndStrings(source);
22034
+ for (const match of cleaned.matchAll(/^\s*import\s+([^\r\n;]+)/gmu)) {
22035
+ for (const rawClause of (match[1] ?? "").split(",")) {
22036
+ const clause = rawClause.trim();
22037
+ const parsed = PYTHON_IMPORTLIB_ALIAS_PATTERN.exec(clause);
22038
+ if (parsed)
22039
+ importlibAliases.add(parsed[1] ?? "importlib");
22040
+ }
22041
+ }
22042
+ for (const match of cleaned.matchAll(PYTHON_FROM_IMPORTLIB_PATTERN)) {
22043
+ const importList = match[1] ?? match[2] ?? "";
22044
+ for (const rawClause of importList.split(",")) {
22045
+ const clause = rawClause.trim();
22046
+ const parsed = PYTHON_IMPORT_MODULE_ALIAS_PATTERN.exec(clause);
22047
+ if (parsed)
22048
+ importModuleAliases.add(parsed[1] ?? "import_module");
22049
+ }
22050
+ }
22051
+ return { importlibAliases, importModuleAliases };
22052
+ }
22053
+ function extractPythonDynamicSpecifiers(source) {
22054
+ const out = [];
22055
+ try {
22056
+ const mask = buildPythonNonCodeMask(source);
22057
+ const { importlibAliases, importModuleAliases } = collectPythonDynamicImportAliases(source);
22058
+ const seen = /* @__PURE__ */ new Set();
22059
+ for (const match of source.matchAll(PYTHON_DYNAMIC_CALL_PREFIX_PATTERN)) {
22060
+ if (!matchStartsInCode(mask, match))
22061
+ continue;
22062
+ const receiver = match[1] ?? "";
22063
+ const member = match[2];
22064
+ const isBuiltinImport = !member && receiver === "__import__";
22065
+ const isImportlibCall = member === "import_module" && importlibAliases.has(receiver);
22066
+ const isImportedFunctionCall = !member && importModuleAliases.has(receiver);
22067
+ if (!isBuiltinImport && !isImportlibCall && !isImportedFunctionCall)
22068
+ continue;
22069
+ const argumentStart = (match.index ?? 0) + (match[0]?.length ?? 0);
22070
+ const spec = parsePythonStaticStringExpression(source, argumentStart);
22071
+ if (!spec || !PYTHON_DYNAMIC_MODULE_PATTERN.test(spec) || seen.has(spec))
22072
+ continue;
22073
+ if (isBuiltinImport && spec.startsWith("."))
22074
+ continue;
22075
+ seen.add(spec);
22076
+ out.push({ spec, resolved: "heuristic", confidence: 0.7 });
22077
+ }
22078
+ } catch {
22079
+ }
22080
+ return out;
22081
+ }
22082
+ function extractDynamicImportSpecifiers(languageId, source, fromFile, projectRoot) {
22083
+ const extractor = DYNAMIC_IMPORT_SPECIFIER_EXTRACTORS[languageId];
22084
+ if (!extractor)
22085
+ return [];
22086
+ return extractor(source, fromFile, projectRoot);
22087
+ }
21830
22088
  function extractPythonSpecifiers(source) {
21831
22089
  const out = [];
21832
22090
  try {
@@ -21841,7 +22099,7 @@ function extractPythonSpecifiers(source) {
21841
22099
  }
21842
22100
  return out;
21843
22101
  }
21844
- var PYTHON_DOTTED_NAME_SOURCE;
22102
+ var PYTHON_DOTTED_NAME_SOURCE, PYTHON_IMPORTLIB_ALIAS_PATTERN, PYTHON_IMPORT_MODULE_ALIAS_PATTERN, PYTHON_DYNAMIC_CALL_PREFIX_PATTERN, PYTHON_DYNAMIC_MODULE_PATTERN, PYTHON_FROM_IMPORTLIB_PATTERN, PYTHON_SIMPLE_STRING_ESCAPES, DYNAMIC_IMPORT_SPECIFIER_EXTRACTORS;
21845
22103
  var init_specifiers = __esm({
21846
22104
  "dist/util/specifiers.js"() {
21847
22105
  "use strict";
@@ -21849,6 +22107,28 @@ var init_specifiers = __esm({
21849
22107
  init_identifiers();
21850
22108
  init_paths();
21851
22109
  PYTHON_DOTTED_NAME_SOURCE = String.raw`${PYTHON_IDENTIFIER_SOURCE}(?:\.${PYTHON_IDENTIFIER_SOURCE})*`;
22110
+ PYTHON_IMPORTLIB_ALIAS_PATTERN = new RegExp(String.raw`^importlib(?:\s+as\s+(${PYTHON_IDENTIFIER_SOURCE}))?$`, "u");
22111
+ PYTHON_IMPORT_MODULE_ALIAS_PATTERN = new RegExp(String.raw`^import_module(?:\s+as\s+(${PYTHON_IDENTIFIER_SOURCE}))?$`, "u");
22112
+ PYTHON_DYNAMIC_CALL_PREFIX_PATTERN = new RegExp(String.raw`(?<![._\p{XID_Continue}])(${PYTHON_IDENTIFIER_SOURCE})(?:\s*\.\s*(${PYTHON_IDENTIFIER_SOURCE}))?\s*\(\s*(?:name\s*=\s*)?`, "gmu");
22113
+ PYTHON_DYNAMIC_MODULE_PATTERN = new RegExp(String.raw`^\.*${PYTHON_DOTTED_NAME_SOURCE}$`, "u");
22114
+ PYTHON_FROM_IMPORTLIB_PATTERN = /^\s*from\s+importlib\s+import\s+(?:\(([\s\S]*?)\)|([^\r\n;]+))/gmu;
22115
+ PYTHON_SIMPLE_STRING_ESCAPES = {
22116
+ "\\": "\\",
22117
+ "'": "'",
22118
+ '"': '"',
22119
+ a: "\x07",
22120
+ b: "\b",
22121
+ f: "\f",
22122
+ n: "\n",
22123
+ r: "\r",
22124
+ t: " ",
22125
+ v: "\v"
22126
+ };
22127
+ DYNAMIC_IMPORT_SPECIFIER_EXTRACTORS = {
22128
+ js: extractJsTsDynamicSpecifiers,
22129
+ ts: extractJsTsDynamicSpecifiers,
22130
+ python: extractPythonDynamicSpecifiers
22131
+ };
21852
22132
  }
21853
22133
  });
21854
22134
 
@@ -25267,7 +25547,7 @@ var init_extractFacts = __esm({
25267
25547
  import crypto2 from "node:crypto";
25268
25548
  import fsp16 from "node:fs/promises";
25269
25549
  function isSqlFile(filePath, languageExtensions) {
25270
- return supportForFile(filePath, languageExtensions)?.id === "sql";
25550
+ return supportForFileWithoutHeaderSample(filePath, languageExtensions)?.id === "sql";
25271
25551
  }
25272
25552
  function sqlCorpusSignature(sqlFiles2, fileSignatures) {
25273
25553
  if (!sqlFiles2.length || !fileSignatures)
@@ -25466,6 +25746,17 @@ var init_sourceGraph = __esm({
25466
25746
  });
25467
25747
 
25468
25748
  // dist/graph-edge-collector.js
25749
+ function appendMissingSpecifiers(target, incoming) {
25750
+ if (!incoming.length)
25751
+ return;
25752
+ const existing = new Set(target.map((entry) => entry.spec));
25753
+ for (const entry of incoming) {
25754
+ if (existing.has(entry.spec))
25755
+ continue;
25756
+ existing.add(entry.spec);
25757
+ target.push(entry);
25758
+ }
25759
+ }
25469
25760
  function deduplicateEdges(edges, rawIsIdentity = false) {
25470
25761
  const deduplicated = /* @__PURE__ */ new Map();
25471
25762
  for (const edge of edges) {
@@ -25505,7 +25796,7 @@ async function collectEdgesForFile(file2, projectRoot, workspaceConfig, opts) {
25505
25796
  const sigEntry = opts.fileSignature;
25506
25797
  const sig = sigEntry?.sig;
25507
25798
  const gitSig = sigEntry?.gitSig;
25508
- const sqlFile = supportForFile(normalizedFile, opts.languageExtensions)?.id === "sql";
25799
+ const sqlFile = supportForFileWithoutHeaderSample(normalizedFile, opts.languageExtensions)?.id === "sql";
25509
25800
  const emitCacheEntry = (edges2) => {
25510
25801
  if (!sig || !opts.onFileEdges)
25511
25802
  return;
@@ -25572,17 +25863,8 @@ async function collectEdgesForFile(file2, projectRoot, workspaceConfig, opts) {
25572
25863
  ...opts.native ? { native: opts.native } : {},
25573
25864
  ...opts.logLevel ? { logLevel: opts.logLevel } : {}
25574
25865
  });
25575
- if ((sup.id === "ts" || sup.id === "js") && opts.dynamicImportHeuristics) {
25576
- const dynamicSpecs = extractJsTsDynamicSpecifiers(src, normalizedFile, projectRoot);
25577
- if (dynamicSpecs.length) {
25578
- const existing = new Set(specs.map((entry) => entry.spec));
25579
- for (const entry of dynamicSpecs) {
25580
- if (existing.has(entry.spec))
25581
- continue;
25582
- existing.add(entry.spec);
25583
- specs.push(entry);
25584
- }
25585
- }
25866
+ if (opts.dynamicImportHeuristics) {
25867
+ appendMissingSpecifiers(specs, extractDynamicImportSpecifiers(sup.id, src, normalizedFile, projectRoot));
25586
25868
  }
25587
25869
  const specSources = specs.map((entry) => ({ entry, support: sup }));
25588
25870
  for (const block of embeddedBlocks) {
@@ -25594,6 +25876,9 @@ async function collectEdgesForFile(file2, projectRoot, workspaceConfig, opts) {
25594
25876
  ...opts.native ? { native: opts.native } : {},
25595
25877
  ...opts.logLevel ? { logLevel: opts.logLevel } : {}
25596
25878
  });
25879
+ if (opts.dynamicImportHeuristics) {
25880
+ appendMissingSpecifiers(blockSpecs, extractDynamicImportSpecifiers(block.sup.id, block.source, normalizedFile, projectRoot));
25881
+ }
25597
25882
  for (const entry of blockSpecs) {
25598
25883
  specSources.push({ entry, support: block.sup });
25599
25884
  }
@@ -25672,7 +25957,7 @@ function canReuseSqlEdgeCache(file2, sqlCorpusSig, fileSignatures, cachedFileEdg
25672
25957
  async function collectGraph(projectRoot, files, opts) {
25673
25958
  const normalizedFiles = files.map(normalizePath);
25674
25959
  const normalizedAllFiles = (opts?.allFiles ?? files).map(normalizePath);
25675
- const isSqlFile4 = (file2) => supportForFile(file2, opts?.languageExtensions)?.id === "sql";
25960
+ const isSqlFile4 = (file2) => supportForFileWithoutHeaderSample(file2, opts?.languageExtensions)?.id === "sql";
25676
25961
  const hasExplicitReplace = !!opts?.replaceFiles;
25677
25962
  const requestedReplaceSet = hasExplicitReplace ? new Set(Array.from(opts.replaceFiles ?? [], (file2) => normalizePath(file2))) : new Set(normalizedFiles);
25678
25963
  const sqlFiles2 = Array.from(new Set(normalizedAllFiles.filter(isSqlFile4))).sort((left, right) => left.localeCompare(right));
@@ -26336,8 +26621,12 @@ function parsePreparedFileContext(context) {
26336
26621
  }
26337
26622
  throw new Error(`Failed to reconstruct syntax tree for ${context.file}`);
26338
26623
  }
26339
- async function prepareFileForIndexing(file2, native, languageExtensions, source) {
26340
- const prep = await prepareSourceInput(file2, { languageExtensions, ...source !== void 0 ? { source } : {} });
26624
+ async function prepareFileForIndexing(file2, native, languageExtensions, source, support) {
26625
+ const prep = await prepareSourceInput(file2, {
26626
+ languageExtensions,
26627
+ ...source !== void 0 ? { source } : {},
26628
+ ...support ? { support } : {}
26629
+ });
26341
26630
  if (isGraphOnlyLanguage(prep.sup.id)) {
26342
26631
  return {
26343
26632
  file: file2,
@@ -32499,7 +32788,7 @@ async function cacheSignatureForFile(file2, sigInfo, opts) {
32499
32788
  async function buildBloomFilterForFile(file2, opts) {
32500
32789
  try {
32501
32790
  const source = await fsp18.readFile(file2, "utf8");
32502
- const support = supportForFile(file2, opts?.languageExtensions);
32791
+ const support = supportForFileWithoutHeaderSample(file2, opts?.languageExtensions);
32503
32792
  if (!support)
32504
32793
  return null;
32505
32794
  return buildBloomFilterFromSource(source, support);
@@ -33267,8 +33556,13 @@ function winnowShingles(shingles, windowSize, maxFingerprints) {
33267
33556
  }
33268
33557
  return fingerprints;
33269
33558
  }
33270
- function languageForFile(filePath) {
33271
- const support = supportForFile(filePath);
33559
+ function isDuplicateCandidateFile(filePath) {
33560
+ if (supportForFileWithoutHeaderSample(filePath))
33561
+ return true;
33562
+ return !!textLanguageByExtension[path39.extname(filePath).toLowerCase()];
33563
+ }
33564
+ function languageForFile(filePath, source) {
33565
+ const support = supportForFileWithSource(filePath, source);
33272
33566
  if (support) {
33273
33567
  return { id: support.id, textOnly: false };
33274
33568
  }
@@ -33443,7 +33737,7 @@ async function getDuplicateAstContext(index, file2, source, cache) {
33443
33737
  return context;
33444
33738
  }
33445
33739
  try {
33446
- const prepared = await prepareSourceInput(file2, { source });
33740
+ const prepared = await prepareSourceInput(file2, { source, support: supportForFileWithSource(file2, source) });
33447
33741
  const attempt = attemptParsePreparedFileContext({
33448
33742
  file: file2,
33449
33743
  source: prepared.source,
@@ -33610,11 +33904,11 @@ async function collectDuplicateUnits(index, options) {
33610
33904
  return { units, belowThresholdUnits, belowThresholdUnitsByFile };
33611
33905
  }
33612
33906
  async function buildDuplicateUnitsForFile(index, file2, projectRoot, minTokens, maxTokens, shingleSize, windowSize, astContextCache) {
33613
- const moduleIndex = index.byFile.get(fileIdentityKey(file2));
33614
- const language = languageForFile(file2);
33615
- if (!language)
33907
+ const fileKey = fileIdentityKey(file2);
33908
+ const moduleIndex = index.byFile.get(fileKey);
33909
+ if (!isDuplicateCandidateFile(file2))
33616
33910
  return [];
33617
- let source = index.parsed?.get(fileIdentityKey(file2))?.source;
33911
+ let source = index.parsed?.get(fileKey)?.source;
33618
33912
  if (source === void 0) {
33619
33913
  try {
33620
33914
  source = await fsp19.readFile(file2, "utf8");
@@ -33622,6 +33916,9 @@ async function buildDuplicateUnitsForFile(index, file2, projectRoot, minTokens,
33622
33916
  return [];
33623
33917
  }
33624
33918
  }
33919
+ const language = languageForFile(file2, source);
33920
+ if (!language)
33921
+ return [];
33625
33922
  const astContext = language.textOnly ? void 0 : await getDuplicateAstContext(index, file2, source, astContextCache);
33626
33923
  const { chunks, symbolChunks } = makeDuplicateChunksWithSymbols(file2, language.id, language.textOnly, source, minTokens, maxTokens);
33627
33924
  const symbolUnits = (moduleIndex?.locals ?? []).map((symbol2) => {
@@ -51174,7 +51471,7 @@ function moduleNameLookup(index, file2) {
51174
51471
  if (!lookups) {
51175
51472
  lookups = /* @__PURE__ */ new Map();
51176
51473
  for (const moduleEntry of index.byFile.values()) {
51177
- const normalizeIdentifier = supportForFile(moduleEntry.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51474
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(moduleEntry.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51178
51475
  const localExports = /* @__PURE__ */ new Map();
51179
51476
  const namespaceReexports = /* @__PURE__ */ new Map();
51180
51477
  const reexports = /* @__PURE__ */ new Map();
@@ -51219,7 +51516,7 @@ function sameSymbolDef(index, left, right) {
51219
51516
  if (fileIdentityKey(left.file) !== fileIdentityKey(right.file) || left.kind !== right.kind) {
51220
51517
  return false;
51221
51518
  }
51222
- const normalizeIdentifier = supportForFile(left.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51519
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(left.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51223
51520
  if (normalizeIdentifier(left.localName) !== normalizeIdentifier(right.localName)) {
51224
51521
  return false;
51225
51522
  }
@@ -51249,64 +51546,68 @@ function packageNameCacheFor(index) {
51249
51546
  }
51250
51547
  return caches;
51251
51548
  }
51549
+ function packageDeclarationSource(index, filePath, fileKey) {
51550
+ const retained = index.parsed?.get(fileKey)?.source;
51551
+ if (retained !== void 0)
51552
+ return retained;
51553
+ try {
51554
+ return fs20.readFileSync(filePath, "utf8");
51555
+ } catch {
51556
+ return null;
51557
+ }
51558
+ }
51252
51559
  function readGoPackageName(index, filePath) {
51253
51560
  const cache = packageNameCacheFor(index).go;
51254
51561
  const key = fileIdentityKey(filePath);
51255
51562
  const cached2 = cache.get(key);
51256
51563
  if (cached2 !== void 0)
51257
51564
  return cached2;
51258
- try {
51259
- const source = fs20.readFileSync(filePath, "utf8");
51260
- const match = GO_PACKAGE_PATTERN.exec(source);
51261
- const packageName = match?.[1] ?? null;
51262
- cache.set(key, packageName);
51263
- return packageName;
51264
- } catch {
51565
+ const source = packageDeclarationSource(index, filePath, key);
51566
+ if (source === null) {
51265
51567
  cache.set(key, null);
51266
51568
  return null;
51267
51569
  }
51570
+ const packageName = GO_PACKAGE_PATTERN.exec(source)?.[1] ?? null;
51571
+ cache.set(key, packageName);
51572
+ return packageName;
51268
51573
  }
51269
51574
  function resolveGoPackageExport(index, file2, exportedName) {
51270
- try {
51271
- const support = supportForFile(file2, index.languageExtensions);
51272
- if (!support || support.id !== "go")
51273
- return null;
51274
- const directory = packageDirectoryLookup(index, "go").get(fileIdentityKey(path42.dirname(file2)));
51275
- if (!directory)
51276
- return null;
51277
- const sourcePackage = readGoPackageName(index, file2);
51278
- const candidates = sourcePackage ? directory.byName.get(sourcePackage) ?? [] : directory.all;
51279
- const matches = [];
51280
- for (const moduleEntry of candidates) {
51281
- const names = moduleNameLookup(index, moduleEntry.file);
51282
- if (!names)
51283
- continue;
51284
- for (const target of names.localExports.get(names.normalizeIdentifier(exportedName)) ?? []) {
51285
- if (!matches.some((candidate) => sameSymbolDef(index, candidate, target))) {
51286
- matches.push(target);
51287
- }
51575
+ if (supportForFileWithoutHeaderSample(file2, index.languageExtensions)?.id !== "go")
51576
+ return null;
51577
+ const directory = packageDirectoryLookup(index, "go").get(fileIdentityKey(path42.dirname(file2)));
51578
+ if (!directory)
51579
+ return null;
51580
+ const sourcePackage = readGoPackageName(index, file2);
51581
+ const candidates = sourcePackage ? directory.byName.get(sourcePackage) ?? [] : directory.all;
51582
+ const matches = [];
51583
+ for (const moduleEntry of candidates) {
51584
+ const names = moduleNameLookup(index, moduleEntry.file);
51585
+ if (!names)
51586
+ continue;
51587
+ for (const target of names.localExports.get(names.normalizeIdentifier(exportedName)) ?? []) {
51588
+ if (!matches.some((candidate) => sameSymbolDef(index, candidate, target))) {
51589
+ matches.push(target);
51288
51590
  }
51289
51591
  }
51290
- return matches.length === 1 ? matches[0] ?? null : null;
51291
- } catch {
51292
51592
  }
51293
- return null;
51593
+ return matches.length === 1 ? matches[0] ?? null : null;
51294
51594
  }
51295
51595
  function readPackageNameForLanguage(index, filePath, languageId) {
51296
51596
  const cache = packageNameCacheFor(index).jvm;
51297
- const key = `${languageId}::${fileIdentityKey(filePath)}`;
51597
+ const fileKey = fileIdentityKey(filePath);
51598
+ const key = `${languageId}::${fileKey}`;
51298
51599
  const cached2 = cache.get(key);
51299
51600
  if (cached2 !== void 0)
51300
51601
  return cached2;
51301
- try {
51302
- const source = fs20.readFileSync(filePath, "utf8");
51303
- const packageName = languageId === "kotlin" ? KOTLIN_PACKAGE_NAME_PATTERN.exec(source)?.[1] ?? null : JAVA_PACKAGE_NAME_PATTERN.exec(source)?.[1] ?? null;
51304
- cache.set(key, packageName);
51305
- return packageName;
51306
- } catch {
51602
+ const source = packageDeclarationSource(index, filePath, fileKey);
51603
+ if (source === null) {
51307
51604
  cache.set(key, null);
51308
51605
  return null;
51309
51606
  }
51607
+ const pattern = languageId === "kotlin" ? KOTLIN_PACKAGE_NAME_PATTERN : JAVA_PACKAGE_NAME_PATTERN;
51608
+ const packageName = pattern.exec(source)?.[1] ?? null;
51609
+ cache.set(key, packageName);
51610
+ return packageName;
51310
51611
  }
51311
51612
  function packageDirectoryLookup(index, languageId) {
51312
51613
  let byLanguage = packageDirectoryLookups.get(index);
@@ -51326,6 +51627,9 @@ function packageDirectoryLookup(index, languageId) {
51326
51627
  directories.set(directoryKey, directory);
51327
51628
  }
51328
51629
  directory.all.push(moduleEntry);
51630
+ const moduleLanguageId = supportForFileWithoutHeaderSample(moduleEntry.file, index.languageExtensions)?.id;
51631
+ if (!moduleLanguageId || !PACKAGE_DECLARING_LANGUAGE_IDS[languageId].has(moduleLanguageId))
51632
+ continue;
51329
51633
  const packageName = languageId === "go" ? readGoPackageName(index, moduleEntry.file) : readPackageNameForLanguage(index, moduleEntry.file, languageId);
51330
51634
  if (!packageName)
51331
51635
  continue;
@@ -51552,30 +51856,23 @@ function resolveImported(index, imp, exportedName) {
51552
51856
  return hit.def;
51553
51857
  if (hit?.kind === "namespace")
51554
51858
  return { namespace: hit.file };
51555
- try {
51556
- const support = supportForFile(targetFile);
51557
- if (support?.id === "java" || support?.id === "kotlin") {
51558
- const siblingHit = resolveSiblingPackageExport(index, targetFile, exportedName, support.id);
51559
- if (siblingHit?.kind === "resolved")
51560
- return siblingHit.def;
51561
- if (siblingHit?.kind === "namespace") {
51562
- return { namespace: siblingHit.file };
51563
- }
51859
+ const support = supportForFileWithoutHeaderSample(targetFile, index.languageExtensions);
51860
+ if (support?.id === "java" || support?.id === "kotlin") {
51861
+ const siblingHit = resolveSiblingPackageExport(index, targetFile, exportedName, support.id);
51862
+ if (siblingHit?.kind === "resolved")
51863
+ return siblingHit.def;
51864
+ if (siblingHit?.kind === "namespace") {
51865
+ return { namespace: siblingHit.file };
51564
51866
  }
51565
- } catch {
51566
51867
  }
51567
- try {
51568
- const support = supportForFile(targetFile);
51569
- if (support?.id === "python") {
51570
- const submodule = resolvePythonSubmodule(targetFile, exportedName);
51571
- if (submodule)
51572
- return { namespace: submodule };
51573
- }
51574
- } catch {
51868
+ if (support?.id === "python") {
51869
+ const submodule = resolvePythonSubmodule(targetFile, exportedName);
51870
+ if (submodule)
51871
+ return { namespace: submodule };
51575
51872
  }
51576
51873
  return null;
51577
51874
  }
51578
- var GO_PACKAGE_PATTERN, JAVA_PACKAGE_NAME_PATTERN, KOTLIN_PACKAGE_NAME_PATTERN, moduleNameLookups, packageDirectoryLookups, packageNameCaches;
51875
+ var GO_PACKAGE_PATTERN, JAVA_PACKAGE_NAME_PATTERN, KOTLIN_PACKAGE_NAME_PATTERN, PACKAGE_DECLARING_LANGUAGE_IDS, moduleNameLookups, packageDirectoryLookups, packageNameCaches;
51579
51876
  var init_navigation_resolve = __esm({
51580
51877
  "dist/indexer/navigation-resolve.js"() {
51581
51878
  "use strict";
@@ -51586,6 +51883,11 @@ var init_navigation_resolve = __esm({
51586
51883
  GO_PACKAGE_PATTERN = new RegExp(String.raw`^\s*package\s+(${GO_IDENTIFIER_SOURCE})`, "mu");
51587
51884
  JAVA_PACKAGE_NAME_PATTERN = new RegExp(String.raw`^\s*package\s+(${JAVA_IDENTIFIER_SOURCE}(?:\.${JAVA_IDENTIFIER_SOURCE})*)\s*;`, "mu");
51588
51885
  KOTLIN_PACKAGE_NAME_PATTERN = new RegExp(String.raw`^\s*package\s+(${KOTLIN_IDENTIFIER_SOURCE}(?:\.${KOTLIN_IDENTIFIER_SOURCE})*)`, "mu");
51886
+ PACKAGE_DECLARING_LANGUAGE_IDS = {
51887
+ go: /* @__PURE__ */ new Set(["go"]),
51888
+ java: /* @__PURE__ */ new Set(["java", "kotlin"]),
51889
+ kotlin: /* @__PURE__ */ new Set(["java", "kotlin"])
51890
+ };
51589
51891
  moduleNameLookups = /* @__PURE__ */ new WeakMap();
51590
51892
  packageDirectoryLookups = /* @__PURE__ */ new WeakMap();
51591
51893
  packageNameCaches = /* @__PURE__ */ new WeakMap();
@@ -54643,7 +54945,7 @@ function isNativeWorkerEligibleFile(filePath, support) {
54643
54945
  function countNativeWorkerEligibleFiles(files, languageExtensions) {
54644
54946
  let count = 0;
54645
54947
  for (const file2 of files) {
54646
- if (isNativeWorkerEligibleFile(file2, supportForFile(file2, languageExtensions)))
54948
+ if (isNativeWorkerEligibleFile(file2, supportForFileWithoutHeaderSample(file2, languageExtensions)))
54647
54949
  count++;
54648
54950
  }
54649
54951
  return count;
@@ -54778,10 +55080,10 @@ async function prepareFileContextForBuild(file2, support, opts, workerSetup, rep
54778
55080
  workerSetup.report.errors.push({ file: file2, message: stringifyUnknown(error51) });
54779
55081
  }
54780
55082
  }
54781
- prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source);
55083
+ prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source, support);
54782
55084
  }
54783
55085
  } else {
54784
- prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source);
55086
+ prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source, support);
54785
55087
  }
54786
55088
  recordPreparedNativeExecutionOutcome(report, prepared);
54787
55089
  return prepared;
@@ -55308,6 +55610,17 @@ function emitIndexLifecycleProgress(opts, phase, mode, total, elapsedMs2) {
55308
55610
  ...elapsedMs2 !== void 0 ? { elapsedMs: elapsedMs2 } : {}
55309
55611
  });
55310
55612
  }
55613
+ function emitIndexCheckStart(opts, activity = "Checking project index") {
55614
+ opts?.onProgress?.({
55615
+ type: "progress",
55616
+ phase: "start",
55617
+ mode: "check",
55618
+ message: activity,
55619
+ activity,
55620
+ current: 0,
55621
+ total: 0
55622
+ });
55623
+ }
55311
55624
  function emitIndexCheckActivity(opts, activity, current = 0, total = 0) {
55312
55625
  opts?.onProgress?.({
55313
55626
  type: "progress",
@@ -55414,7 +55727,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55414
55727
  const sqlFiles2 = normalizedFiles.filter((file2) => {
55415
55728
  if (!languageExtensions)
55416
55729
  return path47.extname(file2).toLowerCase() === ".sql";
55417
- return supportForFile(file2, languageExtensions)?.id === "sql";
55730
+ return supportForFileWithoutHeaderSample(file2, languageExtensions)?.id === "sql";
55418
55731
  }).sort((left, right) => left.localeCompare(right));
55419
55732
  const fileSignatures = await prepareFileSignatures({
55420
55733
  projectRoot,
@@ -55432,7 +55745,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55432
55745
  return sqlFactCachePromise;
55433
55746
  };
55434
55747
  const shouldProvideSqlFactCache = (file2, sigInfo, cachedEdgesEntry) => {
55435
- if (supportForFile(file2, opts?.languageExtensions)?.id !== "sql")
55748
+ if (supportForFileWithoutHeaderSample(file2, opts?.languageExtensions)?.id !== "sql")
55436
55749
  return false;
55437
55750
  if (!cachedEdgesEntry || !sqlCorpusSig || cachedEdgesEntry.sqlCorpusSig !== sqlCorpusSig)
55438
55751
  return true;
@@ -55728,9 +56041,12 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
55728
56041
  try {
55729
56042
  const useDiskCache = (opts?.cache ?? "off") === "disk";
55730
56043
  const wantsMaxSymlinkCorrectness = !!opts?.cacheStrict || !!opts?.cacheVerify;
55731
- const symlinkHintManifest = helperOpts?.ignoreExistingManifest || wantsMaxSymlinkCorrectness || !useDiskCache ? null : await loadManifest(projectRoot, opts);
56044
+ const symlinkHintManifest = !helperOpts?.ignoreExistingManifest && !wantsMaxSymlinkCorrectness && useDiskCache ? await loadManifest(projectRoot, opts) : null;
55732
56045
  const rootMtime = symlinkHintManifest ? (await fsp26.stat(projectRoot)).mtimeMs : void 0;
55733
56046
  const symlinkHintIsFresh = symlinkHintManifest?.symlinkDirectoriesRootMtimeMs !== void 0 && rootMtime === symlinkHintManifest.symlinkDirectoriesRootMtimeMs;
56047
+ if (!helperOpts?.reportDiscoveryProgress && !symlinkHintIsFresh) {
56048
+ emitIndexCheckStart(opts, "Discovering source files");
56049
+ }
55734
56050
  const knownSymlinkDirectories = symlinkHintIsFresh ? symlinkHintManifest?.symlinkDirectories : void 0;
55735
56051
  let discoveredSymlinkDirectories = knownSymlinkDirectories;
55736
56052
  const onSymlinkDirectoriesDiscovered = (directories) => {
@@ -58012,6 +58328,17 @@ async function resolveAgentDiscoverySettings(options) {
58012
58328
  ...cacheLocation ? { cacheLocation } : {}
58013
58329
  };
58014
58330
  }
58331
+ function emitAgentFilePlanProgress(options) {
58332
+ options.buildOptions?.onProgress?.({
58333
+ type: "progress",
58334
+ phase: "start",
58335
+ mode: "check",
58336
+ message: "Discovering source files",
58337
+ activity: "Discovering source files",
58338
+ current: 0,
58339
+ total: 0
58340
+ });
58341
+ }
58015
58342
  async function resolveAgentSessionFilePlan(options) {
58016
58343
  const { discoveryOptions, graphOptions, languageExtensions, cacheLocation } = await resolveAgentDiscoverySettings(options);
58017
58344
  const incrementalOptions = {
@@ -58035,6 +58362,7 @@ async function resolveAgentSessionFilePlan(options) {
58035
58362
  const { DEFAULT_PROJECT_PATTERNS: DEFAULT_PROJECT_PATTERNS2 } = await Promise.resolve().then(() => (init_projectFiles(), projectFiles_exports));
58036
58363
  const customPatterns = languageExtensionPatterns(languageExtensions);
58037
58364
  const patterns = customPatterns.length ? [...DEFAULT_PROJECT_PATTERNS2, ...customPatterns] : void 0;
58365
+ emitAgentFilePlanProgress(options);
58038
58366
  const files = await listProjectFiles(options.root, patterns, discoveryOptions);
58039
58367
  return {
58040
58368
  files,
@@ -64168,7 +64496,7 @@ async function checkMarkdownLinksInFiles(projectRoot, files) {
64168
64496
  return absoluteFile;
64169
64497
  }
64170
64498
  }));
64171
- const markdownFiles = Array.from(new Set(markdownFileCandidates)).filter((file2) => isFilePathWithinRoot(realRoot, file2)).filter((file2) => supportForFile(file2)?.id === "markdown");
64499
+ const markdownFiles = Array.from(new Set(markdownFileCandidates)).filter((file2) => isFilePathWithinRoot(realRoot, file2)).filter((file2) => supportForFileWithoutHeaderSample(file2)?.id === "markdown");
64172
64500
  const targetStatusByPath = /* @__PURE__ */ new Map();
64173
64501
  const anchorsByPath = /* @__PURE__ */ new Map();
64174
64502
  const failures = [];
@@ -64207,7 +64535,7 @@ async function checkMarkdownLinksInFiles(projectRoot, files) {
64207
64535
  failures.push(toFailure(realRoot, displayFile, occurrence, "outside_root", resolvedTarget));
64208
64536
  continue;
64209
64537
  }
64210
- if (!target.fragment || targetStatus.isDirectory || supportForFile(resolvedTarget)?.id !== "markdown")
64538
+ if (!target.fragment || targetStatus.isDirectory || supportForFileWithoutHeaderSample(resolvedTarget)?.id !== "markdown")
64211
64539
  continue;
64212
64540
  const anchors = await cachedMarkdownAnchors(targetStatus.realPath, anchorsByPath);
64213
64541
  if (!anchors.has(target.fragment)) {
@@ -65276,7 +65604,7 @@ var init_navigation_php = __esm({
65276
65604
  function sameDef(left, right, languageExtensions) {
65277
65605
  const leftIndex = left.range.start.index ?? 0;
65278
65606
  const rightIndex = right.range.start.index ?? 0;
65279
- const normalizeIdentifier = supportForFile(left.file, languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65607
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(left.file, languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65280
65608
  return fileIdentityKey(left.file) === fileIdentityKey(right.file) && normalizeIdentifier(left.localName) === normalizeIdentifier(right.localName) && leftIndex === rightIndex;
65281
65609
  }
65282
65610
  function rangeContains(range, pos) {
@@ -65559,7 +65887,7 @@ function hasExpandedNamedImport(moduleIndex, targetFile, symbolName) {
65559
65887
  return moduleIndex.imports.some((candidate) => candidate.kind === "named" && candidate.local === symbolName && candidate.imported === symbolName && typeof candidate.resolved === "string" && fileIdentityKey(candidate.resolved) === targetKey);
65560
65888
  }
65561
65889
  function referenceCandidateCacheKey(index, def, exportedNames) {
65562
- const normalizeIdentifier = supportForFile(def.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65890
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(def.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65563
65891
  const sortedNames = exportedNames.map(normalizeIdentifier).sort();
65564
65892
  return `${fileIdentityKey(def.file)}::${def.range.start.index ?? 0}::canonical::${sortedNames.join("\0")}`;
65565
65893
  }
@@ -66337,7 +66665,7 @@ async function findReferences(index, req, opts) {
66337
66665
  const filter = index.bloomFilters?.get(fileIdentityKey(candidateFile));
66338
66666
  if (!filter)
66339
66667
  return true;
66340
- const normalizeIdentifier = supportForFile(candidateFile, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
66668
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(candidateFile, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
66341
66669
  const aliases = getCandidateReferenceNames(module2, definitionFile, exportedNameSet);
66342
66670
  if (!aliases.length) {
66343
66671
  return [...exportedNames, ...phpQualifiedNames].some((candidateName) => filter.mightContain(normalizeIdentifier(candidateName)));
@@ -66367,7 +66695,7 @@ async function findReferences(index, req, opts) {
66367
66695
  }
66368
66696
  return scopeIndex;
66369
66697
  };
66370
- if (supportForFile(fileId, index.languageExtensions)?.supportsExportFromReferences) {
66698
+ if (supportForFileWithoutHeaderSample(fileId, index.languageExtensions)?.supportsExportFromReferences) {
66371
66699
  for (const entry of module2.exports) {
66372
66700
  if (hasReachedMaxReferences())
66373
66701
  break;
@@ -66495,7 +66823,7 @@ async function findReferences(index, req, opts) {
66495
66823
  if (hasReachedMaxReferences())
66496
66824
  break;
66497
66825
  const filter = index.bloomFilters?.get(fileIdentityKey(fileId));
66498
- const canonicalName = supportForFile(fileId, index.languageExtensions)?.normalizeIdentifier(def.localName) ?? def.localName;
66826
+ const canonicalName = supportForFileWithoutHeaderSample(fileId, index.languageExtensions)?.normalizeIdentifier(def.localName) ?? def.localName;
66499
66827
  if (filter && !filter.mightContain(canonicalName))
66500
66828
  continue;
66501
66829
  const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
@@ -67997,7 +68325,7 @@ function hasDiagnostics(diagnostics) {
67997
68325
  return !!(diagnostics.missingFiles.length || diagnostics.symbolMappingParseFailures.length || diagnostics.memberResolutionCoverage?.limitedLanguages.length);
67998
68326
  }
67999
68327
  function isRiskRelevantSymbolMappingFile(file2) {
68000
- return supportForFile(file2)?.supportsCrossModuleSymbols ?? false;
68328
+ return supportForFileWithoutHeaderSample(file2)?.supportsCrossModuleSymbols ?? false;
68001
68329
  }
68002
68330
  var init_risk = __esm({
68003
68331
  "dist/review/risk.js"() {
@@ -69893,7 +70221,7 @@ async function collectVerifiedCallsiteReferences(index, changedSymbol, maxRefs,
69893
70221
  if (!shouldIncludeReference(file2)) {
69894
70222
  continue;
69895
70223
  }
69896
- const support = supportForFile(file2);
70224
+ const support = supportForFileWithoutHeaderSample(file2, index.languageExtensions);
69897
70225
  if (!support || !supportsCallCompatibilityLanguage(support.id)) {
69898
70226
  continue;
69899
70227
  }
@@ -70306,7 +70634,7 @@ var init_hunks = __esm({
70306
70634
  // dist/impact/map.js
70307
70635
  async function locateChangedSymbolsWithLines(index, file2, hunks) {
70308
70636
  const changedLines = collectChangedLines(hunks);
70309
- if (isGraphOnlyFile(file2)) {
70637
+ if (isGraphOnlyFile(file2, index.languageExtensions)) {
70310
70638
  return { changedSymbols: [], changedLines, parseFailed: false };
70311
70639
  }
70312
70640
  let parsedEntry;
@@ -70446,7 +70774,7 @@ function sameRangeStartPosition(left, right) {
70446
70774
  return left.start.line === right.start.line && left.start.column === right.start.column && left.start.index === right.start.index;
70447
70775
  }
70448
70776
  async function mapChangedLinesToSymbols(index, file2, hunks, changedLinesOverride) {
70449
- if (isGraphOnlyFile(file2)) {
70777
+ if (isGraphOnlyFile(file2, index.languageExtensions)) {
70450
70778
  return /* @__PURE__ */ new Map();
70451
70779
  }
70452
70780
  let parsedEntry;
@@ -70487,8 +70815,8 @@ async function mapChangedLinesToSymbols(index, file2, hunks, changedLinesOverrid
70487
70815
  }
70488
70816
  return linesByHandle;
70489
70817
  }
70490
- function isGraphOnlyFile(file2) {
70491
- const support = supportForFile(file2);
70818
+ function isGraphOnlyFile(file2, languageExtensions) {
70819
+ const support = supportForFileWithoutHeaderSample(file2, languageExtensions);
70492
70820
  return support ? isGraphOnlyLanguage(support.id) : false;
70493
70821
  }
70494
70822
  function hasOverlapSorted(sorted, lo, hi) {
@@ -73028,17 +73356,25 @@ function isNodeBuiltinSpecifier(specifier) {
73028
73356
  return NODE_BUILTIN_MODULES2.has(specifier);
73029
73357
  }
73030
73358
  function isGraphOnlyImporter(file2) {
73031
- const support = supportForFile(file2);
73359
+ const support = supportForFileWithoutHeaderSample(file2);
73032
73360
  return support ? isGraphOnlyLanguage(support.id) : false;
73033
73361
  }
73034
73362
  function getUnresolvedImports(graph, opts = {}) {
73035
73363
  const unresolved = /* @__PURE__ */ new Map();
73036
73364
  const classificationCache = /* @__PURE__ */ new Map();
73365
+ const graphOnlyImporterCache = /* @__PURE__ */ new Map();
73037
73366
  for (const edge of graph.edges) {
73038
73367
  if (edge.to.type !== "external")
73039
73368
  continue;
73040
- if (!opts.includeGraphOnly && isGraphOnlyImporter(edge.from))
73041
- continue;
73369
+ if (!opts.includeGraphOnly) {
73370
+ let graphOnly = graphOnlyImporterCache.get(edge.from);
73371
+ if (graphOnly === void 0) {
73372
+ graphOnly = isGraphOnlyImporter(edge.from);
73373
+ graphOnlyImporterCache.set(edge.from, graphOnly);
73374
+ }
73375
+ if (graphOnly)
73376
+ continue;
73377
+ }
73042
73378
  if (isNodeBuiltinSpecifier(edge.to.name) || isNodeBuiltinSpecifier(edge.raw))
73043
73379
  continue;
73044
73380
  const classificationKey = `${edge.from}\0${edge.to.name}\0${edge.raw}\0${opts.projectRoot ?? ""}`;
@@ -74109,7 +74445,9 @@ function detectQueryIndexSurface(relativePath3) {
74109
74445
  return "code";
74110
74446
  }
74111
74447
  function buildQueryTextChunks(file2, text) {
74112
- const support = supportForFile(file2);
74448
+ return chunkQueryText(file2, text, supportForFileWithSource(file2, text));
74449
+ }
74450
+ function chunkQueryText(file2, text, support) {
74113
74451
  const languageId = support ? CHUNK_LANGUAGE_ALIASES[support.id] ?? support.id : void 0;
74114
74452
  const language = languageId ? LANG_CONFIGS[languageId] : void 0;
74115
74453
  if (language) {
@@ -74147,13 +74485,13 @@ function buildQueryTextChunks(file2, text) {
74147
74485
  async function prepareQueryIndexFile(input) {
74148
74486
  try {
74149
74487
  const stat = await fs32.stat(input.absolutePath);
74150
- const support = supportForFile(input.absolutePath);
74151
74488
  if (stat.size > MAX_QUERY_INDEX_TEXT_BYTES) {
74489
+ const support2 = supportForFile(input.absolutePath);
74152
74490
  return {
74153
74491
  path: input.path,
74154
74492
  sourceIdentity: input.sourceIdentity,
74155
74493
  surface: detectQueryIndexSurface(input.path),
74156
- ...support ? { language: support.id } : {},
74494
+ ...support2 ? { language: support2.id } : {},
74157
74495
  byteLength: stat.size,
74158
74496
  lineCount: 0,
74159
74497
  normalizedText: compressQueryText(""),
@@ -74162,6 +74500,7 @@ async function prepareQueryIndexFile(input) {
74162
74500
  };
74163
74501
  }
74164
74502
  const text = await fs32.readFile(input.absolutePath, "utf8");
74503
+ const support = supportForFileWithSource(input.absolutePath, text);
74165
74504
  return {
74166
74505
  path: input.path,
74167
74506
  sourceIdentity: input.sourceIdentity,
@@ -74170,7 +74509,7 @@ async function prepareQueryIndexFile(input) {
74170
74509
  byteLength: stat.size,
74171
74510
  lineCount: text ? text.split(/\r?\n/).length : 0,
74172
74511
  normalizedText: compressQueryText(normalizeQuerySearchText(text)),
74173
- chunks: buildQueryTextChunks(input.absolutePath, text).map((chunk) => ({
74512
+ chunks: chunkQueryText(input.absolutePath, text, support).map((chunk) => ({
74174
74513
  ...chunk,
74175
74514
  text: compressQueryText(chunk.text)
74176
74515
  })),
@@ -82459,15 +82798,16 @@ function validateNewName(snapshot, def, newName) {
82459
82798
  const file2 = normalizeAgentFilePath(snapshot.root, def.file);
82460
82799
  const conflicts = [];
82461
82800
  const invalidPathCharacters = newName.includes("/") || newName.includes("\\") || newName.includes("\0");
82462
- const support = supportForFile(def.file, snapshot.index.languageExtensions);
82801
+ const support = supportForFileWithoutHeaderSample(def.file, snapshot.index.languageExtensions);
82463
82802
  const allowsDollar = support?.id === "js" || support?.id === "ts" || support?.id === "tsx";
82464
82803
  const identifierPattern = allowsDollar ? /^[$_\p{ID_Start}](?:[$_\p{ID_Continue}]|\u200c|\u200d)*$/u : /^[_\p{ID_Start}][_\p{ID_Continue}]*$/u;
82465
82804
  if (!newName || invalidPathCharacters || !identifierPattern.test(newName)) {
82805
+ const displaySupport = supportForFile(def.file, snapshot.index.languageExtensions);
82466
82806
  conflicts.push({
82467
82807
  file: file2,
82468
82808
  location: { file: file2, range: def.range },
82469
82809
  reason: "invalid_identifier",
82470
- message: `"${newName}" is not a valid ${support?.id ?? "conservative"} identifier.`
82810
+ message: `"${newName}" is not a valid ${displaySupport?.id ?? "conservative"} identifier.`
82471
82811
  });
82472
82812
  }
82473
82813
  if (newName !== def.localName && newName.toLocaleLowerCase() === def.localName.toLocaleLowerCase()) {