@pkgseer/cli 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  version
4
- } from "./shared/chunk-9yar14cw.js";
4
+ } from "./shared/chunk-c1e7ntb6.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -24,6 +24,7 @@ var CliPackageInfoDocument = gql`
24
24
  homepage
25
25
  repositoryUrl
26
26
  downloadsLastMonth
27
+ downloadsTotal
27
28
  }
28
29
  security {
29
30
  vulnerabilityCount
@@ -106,6 +107,7 @@ var CliComparePackagesDocument = gql`
106
107
  version
107
108
  license
108
109
  downloadsLastMonth
110
+ downloadsTotal
109
111
  vulnerabilityCount
110
112
  quality {
111
113
  score
@@ -234,6 +236,7 @@ var CombinedSearchDocument = gql`
234
236
  registry
235
237
  score
236
238
  snippet
239
+ matchLine
237
240
  filePath
238
241
  startLine
239
242
  endLine
@@ -261,6 +264,56 @@ var CombinedSearchDocument = gql`
261
264
  }
262
265
  }
263
266
  `;
267
+ var SearchProgressDocument = gql`
268
+ query SearchProgress($searchRef: String!, $includeResults: Boolean) {
269
+ searchProgress(searchRef: $searchRef, includeResults: $includeResults) {
270
+ searchRef
271
+ status
272
+ packagesTotal
273
+ packagesReady
274
+ elapsedMs
275
+ query
276
+ mode
277
+ expiresAt
278
+ }
279
+ }
280
+ `;
281
+ var SearchResultsDocument = gql`
282
+ query SearchResults($searchRef: String!) {
283
+ searchResults(searchRef: $searchRef) {
284
+ query
285
+ mode
286
+ totalResults
287
+ entries {
288
+ id
289
+ type
290
+ title
291
+ subtitle
292
+ packageName
293
+ registry
294
+ score
295
+ snippet
296
+ matchLine
297
+ filePath
298
+ startLine
299
+ endLine
300
+ language
301
+ chunkType
302
+ repoUrl
303
+ gitRef
304
+ pageId
305
+ sourceUrl
306
+ }
307
+ indexingStatus {
308
+ registry
309
+ packageName
310
+ version
311
+ codeStatus
312
+ docsStatus
313
+ }
314
+ }
315
+ }
316
+ `;
264
317
  var FetchCodeContextDocument = gql`
265
318
  query FetchCodeContext($repoUrl: String!, $gitRef: String!, $filePath: String!, $startLine: Int, $endLine: Int) {
266
319
  fetchCodeContext(
@@ -297,6 +350,14 @@ var CliDocsGetDocument = gql`
297
350
  }
298
351
  }
299
352
  `;
353
+ var TriggerIndexingDocument = gql`
354
+ mutation TriggerIndexing($input: TriggerIndexingInput!) {
355
+ triggerIndexing(input: $input) {
356
+ accepted
357
+ skipped
358
+ }
359
+ }
360
+ `;
300
361
  var CreateProjectDocument = gql`
301
362
  mutation CreateProject($input: CreateProjectInput!) {
302
363
  createProject(input: $input) {
@@ -326,6 +387,7 @@ var PackageSummaryDocument = gql`
326
387
  repositoryUrl
327
388
  license
328
389
  downloadsLastMonth
390
+ downloadsTotal
329
391
  downloadsRefreshedAt
330
392
  }
331
393
  security {
@@ -468,6 +530,7 @@ var ComparePackagesDocument = gql`
468
530
  latestVersion
469
531
  license
470
532
  downloadsLastMonth
533
+ downloadsTotal
471
534
  vulnerabilityCount
472
535
  quality {
473
536
  score
@@ -591,6 +654,237 @@ var SearchPackageDocsDocument = gql`
591
654
  }
592
655
  }
593
656
  `;
657
+ var FindSymbolDocument = gql`
658
+ query FindSymbol($registry: Registry!, $packageName: String!, $name: String, $namespace: String, $kind: SymbolKind, $publicOnly: Boolean, $version: String, $includeCode: Boolean, $contextLines: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
659
+ findSymbol(
660
+ registry: $registry
661
+ packageName: $packageName
662
+ name: $name
663
+ namespace: $namespace
664
+ kind: $kind
665
+ publicOnly: $publicOnly
666
+ version: $version
667
+ includeCode: $includeCode
668
+ contextLines: $contextLines
669
+ mode: $mode
670
+ waitTimeoutMs: $waitTimeoutMs
671
+ ) {
672
+ symbols {
673
+ symbolId
674
+ name
675
+ qualifiedPath
676
+ kind
677
+ arity
678
+ isPublic
679
+ filePath
680
+ startLine
681
+ endLine
682
+ code
683
+ callerCount
684
+ }
685
+ totalMatches
686
+ hasMore
687
+ indexedVersion
688
+ }
689
+ }
690
+ `;
691
+ var SearchSymbolsDocument = gql`
692
+ query SearchSymbols($registry: Registry!, $packageName: String!, $query: String!, $kind: SymbolKind, $version: String, $limit: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
693
+ searchSymbols(
694
+ registry: $registry
695
+ packageName: $packageName
696
+ query: $query
697
+ kind: $kind
698
+ version: $version
699
+ limit: $limit
700
+ mode: $mode
701
+ waitTimeoutMs: $waitTimeoutMs
702
+ ) {
703
+ results {
704
+ name
705
+ chunkType
706
+ filePath
707
+ startLine
708
+ endLine
709
+ preview
710
+ contentPreview
711
+ language
712
+ }
713
+ totalMatches
714
+ hasMore
715
+ indexedVersion
716
+ }
717
+ }
718
+ `;
719
+ var ListSymbolsDocument = gql`
720
+ query ListSymbols($registry: Registry!, $packageName: String!, $scope: ListScope!, $filePath: String, $namespace: String, $publicOnly: Boolean, $includePopularity: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
721
+ listSymbols(
722
+ registry: $registry
723
+ packageName: $packageName
724
+ scope: $scope
725
+ filePath: $filePath
726
+ namespace: $namespace
727
+ publicOnly: $publicOnly
728
+ includePopularity: $includePopularity
729
+ limit: $limit
730
+ version: $version
731
+ mode: $mode
732
+ waitTimeoutMs: $waitTimeoutMs
733
+ ) {
734
+ symbols {
735
+ symbolId
736
+ name
737
+ qualifiedPath
738
+ kind
739
+ arity
740
+ isPublic
741
+ filePath
742
+ startLine
743
+ endLine
744
+ callerCount
745
+ }
746
+ namespaces
747
+ total
748
+ hasMore
749
+ file {
750
+ path
751
+ language
752
+ }
753
+ error
754
+ }
755
+ }
756
+ `;
757
+ var SymbolDependenciesDocument = gql`
758
+ query SymbolDependencies($symbol: SymbolReferenceInput!, $maxDepth: Int, $maxResults: Int, $includeExternal: Boolean, $includeBuiltins: Boolean, $mode: NavigationMode, $waitTimeoutMs: Int) {
759
+ symbolDependencies(
760
+ symbol: $symbol
761
+ maxDepth: $maxDepth
762
+ maxResults: $maxResults
763
+ includeExternal: $includeExternal
764
+ includeBuiltins: $includeBuiltins
765
+ mode: $mode
766
+ waitTimeoutMs: $waitTimeoutMs
767
+ ) {
768
+ root {
769
+ symbolId
770
+ name
771
+ qualifiedPath
772
+ }
773
+ dependencies {
774
+ symbolId
775
+ name
776
+ qualifiedPath
777
+ kind
778
+ filePath
779
+ callLine
780
+ isExternal
781
+ depth
782
+ package {
783
+ registry
784
+ name
785
+ }
786
+ }
787
+ externalPackages
788
+ builtinCalls
789
+ missingPackages
790
+ total
791
+ hasMore
792
+ }
793
+ }
794
+ `;
795
+ var SymbolDependentsDocument = gql`
796
+ query SymbolDependents($symbol: SymbolReferenceInput!, $samePackageOnly: Boolean, $maxResults: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
797
+ symbolDependents(
798
+ symbol: $symbol
799
+ samePackageOnly: $samePackageOnly
800
+ maxResults: $maxResults
801
+ mode: $mode
802
+ waitTimeoutMs: $waitTimeoutMs
803
+ ) {
804
+ target {
805
+ symbolId
806
+ name
807
+ qualifiedPath
808
+ }
809
+ dependents {
810
+ symbolId
811
+ name
812
+ qualifiedPath
813
+ kind
814
+ isPublic
815
+ filePath
816
+ callLine
817
+ }
818
+ total
819
+ hasMore
820
+ }
821
+ }
822
+ `;
823
+ var PackageImportsDocument = gql`
824
+ query PackageImports($registry: Registry!, $packageName: String!, $filePath: String, $resolvedOnly: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
825
+ packageImports(
826
+ registry: $registry
827
+ packageName: $packageName
828
+ filePath: $filePath
829
+ resolvedOnly: $resolvedOnly
830
+ limit: $limit
831
+ version: $version
832
+ mode: $mode
833
+ waitTimeoutMs: $waitTimeoutMs
834
+ ) {
835
+ imports {
836
+ sourcePath
837
+ imported
838
+ alias
839
+ kind
840
+ filePath
841
+ line
842
+ isGlob
843
+ typeOnly
844
+ package
845
+ resolvedPackage {
846
+ registry
847
+ name
848
+ }
849
+ }
850
+ uniqueDependencies
851
+ unresolvedCount
852
+ }
853
+ }
854
+ `;
855
+ var CallPathDocument = gql`
856
+ query CallPath($from: SymbolReferenceInput!, $to: SymbolReferenceInput!, $maxDepth: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
857
+ callPath(
858
+ from: $from
859
+ to: $to
860
+ maxDepth: $maxDepth
861
+ mode: $mode
862
+ waitTimeoutMs: $waitTimeoutMs
863
+ ) {
864
+ pathFound
865
+ fromSymbol {
866
+ symbolId
867
+ name
868
+ qualifiedPath
869
+ }
870
+ toSymbol {
871
+ symbolId
872
+ name
873
+ qualifiedPath
874
+ }
875
+ paths {
876
+ length
877
+ hops {
878
+ symbolId
879
+ name
880
+ qualifiedPath
881
+ filePath
882
+ callLine
883
+ }
884
+ }
885
+ }
886
+ }
887
+ `;
594
888
  var SearchProjectDocsDocument = gql`
595
889
  query SearchProjectDocs($project: String!, $keywords: [String!], $matchMode: MatchMode, $includeSnippets: Boolean, $limit: Int) {
596
890
  searchProjectDocs(
@@ -629,8 +923,11 @@ var CliDocsSearchDocumentString = print(CliDocsSearchDocument);
629
923
  var CliProjectDocsSearchDocumentString = print(CliProjectDocsSearchDocument);
630
924
  var CliDocsListDocumentString = print(CliDocsListDocument);
631
925
  var CombinedSearchDocumentString = print(CombinedSearchDocument);
926
+ var SearchProgressDocumentString = print(SearchProgressDocument);
927
+ var SearchResultsDocumentString = print(SearchResultsDocument);
632
928
  var FetchCodeContextDocumentString = print(FetchCodeContextDocument);
633
929
  var CliDocsGetDocumentString = print(CliDocsGetDocument);
930
+ var TriggerIndexingDocumentString = print(TriggerIndexingDocument);
634
931
  var CreateProjectDocumentString = print(CreateProjectDocument);
635
932
  var PackageSummaryDocumentString = print(PackageSummaryDocument);
636
933
  var PackageVulnerabilitiesDocumentString = print(PackageVulnerabilitiesDocument);
@@ -641,6 +938,13 @@ var ListPackageDocsDocumentString = print(ListPackageDocsDocument);
641
938
  var FetchPackageDocDocumentString = print(FetchPackageDocDocument);
642
939
  var GetDocPageDocumentString = print(GetDocPageDocument);
643
940
  var SearchPackageDocsDocumentString = print(SearchPackageDocsDocument);
941
+ var FindSymbolDocumentString = print(FindSymbolDocument);
942
+ var SearchSymbolsDocumentString = print(SearchSymbolsDocument);
943
+ var ListSymbolsDocumentString = print(ListSymbolsDocument);
944
+ var SymbolDependenciesDocumentString = print(SymbolDependenciesDocument);
945
+ var SymbolDependentsDocumentString = print(SymbolDependentsDocument);
946
+ var PackageImportsDocumentString = print(PackageImportsDocument);
947
+ var CallPathDocumentString = print(CallPathDocument);
644
948
  var SearchProjectDocsDocumentString = print(SearchProjectDocsDocument);
645
949
  function getSdk(client, withWrapper = defaultWrapper) {
646
950
  return {
@@ -671,12 +975,21 @@ function getSdk(client, withWrapper = defaultWrapper) {
671
975
  CombinedSearch(variables, requestHeaders) {
672
976
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(CombinedSearchDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CombinedSearch", "query", variables);
673
977
  },
978
+ SearchProgress(variables, requestHeaders) {
979
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchProgressDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchProgress", "query", variables);
980
+ },
981
+ SearchResults(variables, requestHeaders) {
982
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchResultsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchResults", "query", variables);
983
+ },
674
984
  FetchCodeContext(variables, requestHeaders) {
675
985
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(FetchCodeContextDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "FetchCodeContext", "query", variables);
676
986
  },
677
987
  CliDocsGet(variables, requestHeaders) {
678
988
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(CliDocsGetDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CliDocsGet", "query", variables);
679
989
  },
990
+ TriggerIndexing(variables, requestHeaders) {
991
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(TriggerIndexingDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "TriggerIndexing", "mutation", variables);
992
+ },
680
993
  CreateProject(variables, requestHeaders) {
681
994
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(CreateProjectDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
682
995
  },
@@ -707,6 +1020,27 @@ function getSdk(client, withWrapper = defaultWrapper) {
707
1020
  SearchPackageDocs(variables, requestHeaders) {
708
1021
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchPackageDocsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchPackageDocs", "query", variables);
709
1022
  },
1023
+ FindSymbol(variables, requestHeaders) {
1024
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(FindSymbolDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "FindSymbol", "query", variables);
1025
+ },
1026
+ SearchSymbols(variables, requestHeaders) {
1027
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchSymbolsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchSymbols", "query", variables);
1028
+ },
1029
+ ListSymbols(variables, requestHeaders) {
1030
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(ListSymbolsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "ListSymbols", "query", variables);
1031
+ },
1032
+ SymbolDependencies(variables, requestHeaders) {
1033
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(SymbolDependenciesDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SymbolDependencies", "query", variables);
1034
+ },
1035
+ SymbolDependents(variables, requestHeaders) {
1036
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(SymbolDependentsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SymbolDependents", "query", variables);
1037
+ },
1038
+ PackageImports(variables, requestHeaders) {
1039
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(PackageImportsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "PackageImports", "query", variables);
1040
+ },
1041
+ CallPath(variables, requestHeaders) {
1042
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(CallPathDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CallPath", "query", variables);
1043
+ },
710
1044
  SearchProjectDocs(variables, requestHeaders) {
711
1045
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchProjectDocsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchProjectDocs", "query", variables);
712
1046
  }
@@ -1037,8 +1371,17 @@ var TOOL_NAMES = [
1037
1371
  "list_package_docs",
1038
1372
  "fetch_package_doc",
1039
1373
  "search",
1374
+ "search_status",
1040
1375
  "fetch_code_context",
1041
- "search_project_docs"
1376
+ "search_project_docs",
1377
+ "find_symbol",
1378
+ "search_symbols",
1379
+ "list_symbols",
1380
+ "symbol_callers",
1381
+ "symbol_callees",
1382
+ "package_imports",
1383
+ "call_path",
1384
+ "trigger_indexing"
1042
1385
  ];
1043
1386
  var ToolNameSchema = z.enum(TOOL_NAMES);
1044
1387
  var SharedConfigFields = {
@@ -1440,6 +1783,17 @@ class PkgseerServiceImpl {
1440
1783
  });
1441
1784
  return { data: result.data, errors: result.errors };
1442
1785
  }
1786
+ async getSearchProgress(searchRef, options) {
1787
+ const result = await this.client.SearchProgress({
1788
+ searchRef,
1789
+ includeResults: options?.includeResults
1790
+ });
1791
+ return { data: result.data, errors: result.errors };
1792
+ }
1793
+ async getSearchResults(searchRef) {
1794
+ const result = await this.client.SearchResults({ searchRef });
1795
+ return { data: result.data, errors: result.errors };
1796
+ }
1443
1797
  async fetchCodeContext(repoUrl, gitRef, filePath, options) {
1444
1798
  const result = await this.client.FetchCodeContext({
1445
1799
  repoUrl,
@@ -1450,6 +1804,100 @@ class PkgseerServiceImpl {
1450
1804
  });
1451
1805
  return { data: result.data, errors: result.errors };
1452
1806
  }
1807
+ async findSymbol(registry, packageName, options) {
1808
+ const result = await this.client.FindSymbol({
1809
+ registry,
1810
+ packageName,
1811
+ name: options?.name,
1812
+ namespace: options?.namespace,
1813
+ kind: options?.kind,
1814
+ publicOnly: options?.publicOnly,
1815
+ version: options?.version,
1816
+ includeCode: options?.includeCode,
1817
+ contextLines: options?.contextLines,
1818
+ mode: options?.mode,
1819
+ waitTimeoutMs: options?.waitTimeoutMs
1820
+ });
1821
+ return { data: result.data, errors: result.errors };
1822
+ }
1823
+ async searchSymbols(registry, packageName, query, options) {
1824
+ const result = await this.client.SearchSymbols({
1825
+ registry,
1826
+ packageName,
1827
+ query,
1828
+ kind: options?.kind,
1829
+ version: options?.version,
1830
+ limit: options?.limit,
1831
+ mode: options?.mode,
1832
+ waitTimeoutMs: options?.waitTimeoutMs
1833
+ });
1834
+ return { data: result.data, errors: result.errors };
1835
+ }
1836
+ async listSymbols(registry, packageName, scope, options) {
1837
+ const result = await this.client.ListSymbols({
1838
+ registry,
1839
+ packageName,
1840
+ scope,
1841
+ filePath: options?.filePath,
1842
+ namespace: options?.namespace,
1843
+ publicOnly: options?.publicOnly,
1844
+ includePopularity: options?.includePopularity,
1845
+ limit: options?.limit,
1846
+ version: options?.version,
1847
+ mode: options?.mode,
1848
+ waitTimeoutMs: options?.waitTimeoutMs
1849
+ });
1850
+ return { data: result.data, errors: result.errors };
1851
+ }
1852
+ async symbolDependencies(symbol, options) {
1853
+ const result = await this.client.SymbolDependencies({
1854
+ symbol,
1855
+ maxDepth: options?.maxDepth,
1856
+ maxResults: options?.maxResults,
1857
+ includeExternal: options?.includeExternal,
1858
+ includeBuiltins: options?.includeBuiltins,
1859
+ mode: options?.mode,
1860
+ waitTimeoutMs: options?.waitTimeoutMs
1861
+ });
1862
+ return { data: result.data, errors: result.errors };
1863
+ }
1864
+ async symbolDependents(symbol, options) {
1865
+ const result = await this.client.SymbolDependents({
1866
+ symbol,
1867
+ samePackageOnly: options?.samePackageOnly,
1868
+ maxResults: options?.maxResults,
1869
+ mode: options?.mode,
1870
+ waitTimeoutMs: options?.waitTimeoutMs
1871
+ });
1872
+ return { data: result.data, errors: result.errors };
1873
+ }
1874
+ async packageImports(registry, packageName, options) {
1875
+ const result = await this.client.PackageImports({
1876
+ registry,
1877
+ packageName,
1878
+ filePath: options?.filePath,
1879
+ resolvedOnly: options?.resolvedOnly,
1880
+ limit: options?.limit,
1881
+ version: options?.version,
1882
+ mode: options?.mode,
1883
+ waitTimeoutMs: options?.waitTimeoutMs
1884
+ });
1885
+ return { data: result.data, errors: result.errors };
1886
+ }
1887
+ async callPath(from, to, options) {
1888
+ const result = await this.client.CallPath({
1889
+ from,
1890
+ to,
1891
+ maxDepth: options?.maxDepth,
1892
+ mode: options?.mode,
1893
+ waitTimeoutMs: options?.waitTimeoutMs
1894
+ });
1895
+ return { data: result.data, errors: result.errors };
1896
+ }
1897
+ async triggerIndexing(input) {
1898
+ const result = await this.client.TriggerIndexing({ input });
1899
+ return { data: result.data, errors: result.errors };
1900
+ }
1453
1901
  }
1454
1902
  // src/services/project-service.ts
1455
1903
  var PROJECT_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
@@ -1747,58 +2195,6 @@ function registerAuthStatusCommand(program) {
1747
2195
  });
1748
2196
  }
1749
2197
 
1750
- // src/commands/config-show.ts
1751
- async function configShowAction(deps) {
1752
- const { configService } = deps;
1753
- const { config, globalPath, projectPath } = await configService.loadMergedConfig();
1754
- if (!globalPath && !projectPath) {
1755
- console.log(`No configuration found.
1756
- `);
1757
- console.log(" Global config: ~/.pkgseer/config.yml");
1758
- console.log(` Project config: pkgseer.yml
1759
- `);
1760
- console.log("Create a config file to customize pkgseer behavior.");
1761
- return;
1762
- }
1763
- console.log(`Configuration sources:
1764
- `);
1765
- if (globalPath) {
1766
- console.log(` Global: ${globalPath}`);
1767
- }
1768
- if (projectPath) {
1769
- console.log(` Project: ${projectPath}`);
1770
- }
1771
- console.log(`
1772
- Merged configuration:
1773
- `);
1774
- if (config.enabled_tools !== undefined) {
1775
- if (config.enabled_tools.length > 0) {
1776
- console.log(" enabled_tools:");
1777
- for (const tool of config.enabled_tools) {
1778
- console.log(` - ${tool}`);
1779
- }
1780
- } else {
1781
- console.log(" enabled_tools: [] (no tools enabled)");
1782
- }
1783
- } else {
1784
- console.log(" enabled_tools: (all tools enabled by default)");
1785
- }
1786
- if (config.project) {
1787
- console.log(` project: ${config.project}`);
1788
- }
1789
- }
1790
- var SHOW_DESCRIPTION = `Display current configuration.
1791
-
1792
- Shows the merged configuration from global (~/.pkgseer/config.yml) and
1793
- project (pkgseer.yml) config files. Project config takes precedence
1794
- over global config for overlapping settings.`;
1795
- function registerConfigShowCommand(program) {
1796
- program.command("show").summary("Display current configuration").description(SHOW_DESCRIPTION).action(async () => {
1797
- const deps = await createContainer();
1798
- await configShowAction(deps);
1799
- });
1800
- }
1801
-
1802
2198
  // src/commands/shared.ts
1803
2199
  function parsePackageSpec(spec) {
1804
2200
  let registry = "npm";
@@ -1806,7 +2202,16 @@ function parsePackageSpec(spec) {
1806
2202
  if (spec.includes(":")) {
1807
2203
  const colonIndex = spec.indexOf(":");
1808
2204
  const potentialRegistry = spec.slice(0, colonIndex).toLowerCase();
1809
- if (["npm", "pypi", "hex", "crates"].includes(potentialRegistry)) {
2205
+ if ([
2206
+ "npm",
2207
+ "pypi",
2208
+ "hex",
2209
+ "crates",
2210
+ "nuget",
2211
+ "maven",
2212
+ "zig",
2213
+ "vcpkg"
2214
+ ].includes(potentialRegistry)) {
1810
2215
  registry = potentialRegistry;
1811
2216
  rest = spec.slice(colonIndex + 1);
1812
2217
  }
@@ -1826,7 +2231,11 @@ function toGraphQLRegistry(registry) {
1826
2231
  npm: "NPM",
1827
2232
  pypi: "PYPI",
1828
2233
  hex: "HEX",
1829
- crates: "CRATES"
2234
+ crates: "CRATES",
2235
+ nuget: "NUGET",
2236
+ maven: "MAVEN",
2237
+ zig: "ZIG",
2238
+ vcpkg: "VCPKG"
1830
2239
  };
1831
2240
  return map[registry.toLowerCase()] || "NPM";
1832
2241
  }
@@ -1872,6 +2281,11 @@ function formatNumber(num) {
1872
2281
  return "N/A";
1873
2282
  return num.toLocaleString();
1874
2283
  }
2284
+ function truncate(text, maxLength) {
2285
+ if (text.length <= maxLength)
2286
+ return text;
2287
+ return `${text.slice(0, maxLength - 3)}...`;
2288
+ }
1875
2289
  function keyValueTable(pairs) {
1876
2290
  const maxKeyLen = Math.max(...pairs.map(([k]) => k.length));
1877
2291
  return pairs.map(([key, value]) => ` ${key.padEnd(maxKeyLen)} ${value ?? "N/A"}`).join(`
@@ -1970,24 +2384,630 @@ function formatScore(score) {
1970
2384
  return `${bar} ${percentage}%`;
1971
2385
  }
1972
2386
 
1973
- // src/commands/docs/get.ts
1974
- function parsePackageRef(ref) {
1975
- if (!ref.includes("/")) {
2387
+ // src/commands/code/shared.ts
2388
+ function parseSymbolRef(spec) {
2389
+ const hashIndex = spec.indexOf("#");
2390
+ if (hashIndex >= 0) {
2391
+ const packagePart = spec.slice(0, hashIndex);
2392
+ const symbolName = spec.slice(hashIndex + 1);
2393
+ const parsed2 = parsePackageSpec(packagePart);
1976
2394
  return {
1977
- pageId: ref,
1978
- originalRef: ref,
1979
- isGlobalId: true
2395
+ registry: toGraphQLRegistry(parsed2.registry),
2396
+ packageName: parsed2.name,
2397
+ symbolName: symbolName || undefined
1980
2398
  };
1981
2399
  }
1982
- const parts = ref.split("/");
1983
- if (parts.length < 2) {
1984
- throw new Error(`Invalid format: "${ref}". Expected at least 2 parts separated by "/"`);
2400
+ const parsed = parsePackageSpec(spec);
2401
+ return {
2402
+ registry: toGraphQLRegistry(parsed.registry),
2403
+ packageName: parsed.name
2404
+ };
2405
+ }
2406
+ function buildSymbolReference(spec, id) {
2407
+ if (id) {
2408
+ return { symbolId: Number.parseInt(id, 10) };
1985
2409
  }
1986
- if (parts.length >= 4) {
1987
- const registry = parts[0];
1988
- const packageName2 = parts[1];
1989
- const version2 = parts[2];
1990
- const pageId2 = parts.slice(3).join("/");
2410
+ if (!spec) {
2411
+ throw new Error("Symbol reference required. Use registry:package#symbolName or --id <number>");
2412
+ }
2413
+ return parseSymbolRef(spec);
2414
+ }
2415
+ function parseIntOption(value, name) {
2416
+ if (value === undefined)
2417
+ return;
2418
+ const n = Number.parseInt(value, 10);
2419
+ if (Number.isNaN(n) || n < 0) {
2420
+ throw new Error(`${name} must be a non-negative integer`);
2421
+ }
2422
+ return n;
2423
+ }
2424
+ function parseWaitTimeout(wait) {
2425
+ if (wait === undefined)
2426
+ return;
2427
+ const ms = Number.parseInt(wait, 10);
2428
+ if (Number.isNaN(ms) || ms < 0 || ms > 30000) {
2429
+ throw new Error("--wait must be a number between 0 and 30000");
2430
+ }
2431
+ return ms;
2432
+ }
2433
+ function parseNavigationMode(mode) {
2434
+ if (!mode)
2435
+ return;
2436
+ const upper = mode.toUpperCase();
2437
+ if (upper === "SUMMARY" || upper === "DETAILED")
2438
+ return upper;
2439
+ throw new Error("--mode must be 'summary' or 'detailed'");
2440
+ }
2441
+ function formatSymbol(symbol) {
2442
+ const parts = [];
2443
+ const kindLabel = symbol.kind ? `[${symbol.kind}]` : "";
2444
+ const visibility = symbol.isPublic === false ? "(private) " : "";
2445
+ const arity = symbol.arity != null ? `/${symbol.arity}` : "";
2446
+ parts.push(`${kindLabel} ${visibility}${symbol.name}${arity}`.trim());
2447
+ if (symbol.qualifiedPath && symbol.qualifiedPath !== symbol.name) {
2448
+ parts.push(` Path: ${symbol.qualifiedPath}`);
2449
+ }
2450
+ if (symbol.filePath) {
2451
+ const loc = symbol.startLine ? `${symbol.filePath}:${symbol.startLine}` : symbol.filePath;
2452
+ parts.push(` File: ${loc}`);
2453
+ }
2454
+ const meta = [`id:${symbol.symbolId}`];
2455
+ if (symbol.callerCount != null) {
2456
+ meta.push(`callers:${symbol.callerCount}`);
2457
+ }
2458
+ parts.push(` ${meta.join(" ")}`);
2459
+ if (symbol.code) {
2460
+ parts.push("");
2461
+ parts.push(symbol.code.split(`
2462
+ `).map((line) => ` ${line}`).join(`
2463
+ `));
2464
+ }
2465
+ return parts.join(`
2466
+ `);
2467
+ }
2468
+ function formatDependencyEntry(entry) {
2469
+ const parts = [];
2470
+ const kindLabel = entry.kind ? `[${entry.kind}]` : "";
2471
+ const depthLabel = entry.depth ? ` (depth:${entry.depth})` : "";
2472
+ const extLabel = entry.isExternal ? " [external]" : "";
2473
+ parts.push(`${kindLabel} ${entry.name}${depthLabel}${extLabel}`.trim());
2474
+ if (entry.qualifiedPath && entry.qualifiedPath !== entry.name) {
2475
+ parts.push(` Path: ${entry.qualifiedPath}`);
2476
+ }
2477
+ if (entry.filePath) {
2478
+ const loc = entry.callLine ? `${entry.filePath}:${entry.callLine}` : entry.filePath;
2479
+ parts.push(` File: ${loc}`);
2480
+ }
2481
+ if (entry.package) {
2482
+ parts.push(` Package: ${entry.package.registry}:${entry.package.name}`);
2483
+ }
2484
+ if (entry.symbolId) {
2485
+ parts.push(` id:${entry.symbolId}`);
2486
+ }
2487
+ return parts.join(`
2488
+ `);
2489
+ }
2490
+
2491
+ // src/commands/code/callees.ts
2492
+ function formatCalleesResult(data) {
2493
+ const lines = [];
2494
+ lines.push(`Callees of ${data.root.qualifiedPath ?? data.root.name} (id:${data.root.symbolId})`);
2495
+ lines.push(`${data.total} callee(s)${data.hasMore ? " (more available)" : ""}`);
2496
+ if (data.externalPackages && data.externalPackages.length > 0) {
2497
+ lines.push(`External packages: ${data.externalPackages.join(", ")}`);
2498
+ }
2499
+ if (data.builtinCalls && data.builtinCalls.length > 0) {
2500
+ const builtins = data.builtinCalls.filter(Boolean);
2501
+ if (builtins.length > 0) {
2502
+ lines.push(`Builtin calls: ${builtins.join(", ")}`);
2503
+ }
2504
+ }
2505
+ lines.push("");
2506
+ for (const dep of data.dependencies) {
2507
+ lines.push(formatDependencyEntry(dep));
2508
+ lines.push("");
2509
+ }
2510
+ return lines.join(`
2511
+ `).trimEnd();
2512
+ }
2513
+ async function codeCalleesAction(symbolArg, options, deps) {
2514
+ const { pkgseerService } = deps;
2515
+ const symbolRef = buildSymbolReference(symbolArg, options.id);
2516
+ const result = await pkgseerService.symbolDependencies(symbolRef, {
2517
+ maxDepth: parseIntOption(options.maxDepth, "--max-depth"),
2518
+ maxResults: parseIntOption(options.limit, "--limit"),
2519
+ includeExternal: options.includeExternal,
2520
+ includeBuiltins: options.includeBuiltins,
2521
+ mode: parseNavigationMode(options.mode),
2522
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2523
+ });
2524
+ handleErrors(result.errors, options.json ?? false);
2525
+ if (!result.data.symbolDependencies) {
2526
+ outputError("Symbol not found. Verify the symbol reference or use --id.", options.json ?? false);
2527
+ return;
2528
+ }
2529
+ if (options.json) {
2530
+ output(result.data.symbolDependencies, true);
2531
+ } else {
2532
+ console.log(formatCalleesResult(result.data.symbolDependencies));
2533
+ }
2534
+ }
2535
+ var CALLEES_DESCRIPTION = `Find what a symbol calls.
2536
+
2537
+ Shows functions and methods that the specified symbol depends on.
2538
+ Use registry:package#symbolName format or --id for direct lookup.
2539
+
2540
+ Examples:
2541
+ pkgseer code callees npm:express#Router
2542
+ pkgseer code callees --id 12345
2543
+ pkgseer code callees npm:lodash#merge --max-depth 2 --include-external`;
2544
+ function registerCodeCalleesCommand(program) {
2545
+ program.command("callees [symbol]").summary("Find what a symbol calls").description(CALLEES_DESCRIPTION).option("--id <id>", "Direct symbol ID").option("--max-depth <n>", "Max traversal depth").option("--limit <n>", "Max results").option("--include-external", "Include external package calls").option("--include-builtins", "Include builtin function calls").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (symbolArg, options) => {
2546
+ await withCliErrorHandling(options.json ?? false, async () => {
2547
+ const deps = await createContainer();
2548
+ await codeCalleesAction(symbolArg, options, deps);
2549
+ });
2550
+ });
2551
+ }
2552
+ // src/commands/code/callers.ts
2553
+ function formatCallersResult(data) {
2554
+ const lines = [];
2555
+ lines.push(`Callers of ${data.target.qualifiedPath ?? data.target.name} (id:${data.target.symbolId})`);
2556
+ lines.push(`${data.total} caller(s)${data.hasMore ? " (more available)" : ""}`);
2557
+ lines.push("");
2558
+ for (const dep of data.dependents) {
2559
+ lines.push(formatDependencyEntry(dep));
2560
+ lines.push("");
2561
+ }
2562
+ return lines.join(`
2563
+ `).trimEnd();
2564
+ }
2565
+ async function codeCallersAction(symbolArg, options, deps) {
2566
+ const { pkgseerService } = deps;
2567
+ const symbolRef = buildSymbolReference(symbolArg, options.id);
2568
+ const result = await pkgseerService.symbolDependents(symbolRef, {
2569
+ samePackageOnly: options.samePackageOnly,
2570
+ maxResults: parseIntOption(options.limit, "--limit"),
2571
+ mode: parseNavigationMode(options.mode),
2572
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2573
+ });
2574
+ handleErrors(result.errors, options.json ?? false);
2575
+ if (!result.data.symbolDependents) {
2576
+ outputError("Symbol not found. Verify the symbol reference or use --id.", options.json ?? false);
2577
+ return;
2578
+ }
2579
+ if (options.json) {
2580
+ output(result.data.symbolDependents, true);
2581
+ } else {
2582
+ console.log(formatCallersResult(result.data.symbolDependents));
2583
+ }
2584
+ }
2585
+ var CALLERS_DESCRIPTION = `Find what calls a symbol.
2586
+
2587
+ Shows functions and methods that call the specified symbol.
2588
+ Use registry:package#symbolName format or --id for direct lookup.
2589
+
2590
+ Examples:
2591
+ pkgseer code callers npm:express#Router
2592
+ pkgseer code callers --id 12345
2593
+ pkgseer code callers npm:lodash#debounce --same-package-only`;
2594
+ function registerCodeCallersCommand(program) {
2595
+ program.command("callers [symbol]").summary("Find what calls a symbol").description(CALLERS_DESCRIPTION).option("--id <id>", "Direct symbol ID").option("--same-package-only", "Only show callers from the same package").option("--limit <n>", "Max results").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (symbolArg, options) => {
2596
+ await withCliErrorHandling(options.json ?? false, async () => {
2597
+ const deps = await createContainer();
2598
+ await codeCallersAction(symbolArg, options, deps);
2599
+ });
2600
+ });
2601
+ }
2602
+ // src/commands/code/find.ts
2603
+ function formatFindResult(data) {
2604
+ const lines = [];
2605
+ lines.push(`Found ${data.totalMatches} symbol(s)${data.hasMore ? " (more available)" : ""}`);
2606
+ if (data.indexedVersion) {
2607
+ lines.push(`Indexed version: ${data.indexedVersion}`);
2608
+ }
2609
+ lines.push("");
2610
+ for (const symbol of data.symbols) {
2611
+ lines.push(formatSymbol(symbol));
2612
+ lines.push("");
2613
+ }
2614
+ return lines.join(`
2615
+ `).trimEnd();
2616
+ }
2617
+ async function codeFindAction(packageArg, nameArg, options, deps) {
2618
+ const { pkgseerService } = deps;
2619
+ const parsed = parsePackageSpec(packageArg);
2620
+ const registry = toGraphQLRegistry(parsed.registry);
2621
+ const result = await pkgseerService.findSymbol(registry, parsed.name, {
2622
+ name: nameArg,
2623
+ namespace: options.namespace,
2624
+ kind: options.kind?.toUpperCase(),
2625
+ publicOnly: options.publicOnly,
2626
+ version: parsed.version,
2627
+ includeCode: options.includeCode,
2628
+ contextLines: parseIntOption(options.contextLines, "--context-lines"),
2629
+ mode: parseNavigationMode(options.mode),
2630
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2631
+ });
2632
+ handleErrors(result.errors, options.json ?? false);
2633
+ if (!result.data.findSymbol) {
2634
+ outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
2635
+ return;
2636
+ }
2637
+ if (options.json) {
2638
+ output(result.data.findSymbol, true);
2639
+ } else {
2640
+ console.log(formatFindResult(result.data.findSymbol));
2641
+ }
2642
+ }
2643
+ var FIND_DESCRIPTION = `Find symbols (functions, classes, modules) by name.
2644
+
2645
+ Searches for symbols in a package by exact or partial name match.
2646
+ Returns symbol metadata, location, and optionally source code.
2647
+
2648
+ Examples:
2649
+ pkgseer code find npm:express Router
2650
+ pkgseer code find pypi:requests get --kind function
2651
+ pkgseer code find npm:lodash --namespace array --public-only
2652
+ pkgseer code find npm:express Router --include-code`;
2653
+ function registerCodeFindCommand(program) {
2654
+ program.command("find <package> [name]").summary("Find symbols by name").description(FIND_DESCRIPTION).option("--namespace <ns>", "Filter by namespace").option("--kind <kind>", "Filter by symbol kind (function, class, module, etc.)").option("--public-only", "Only show public symbols").option("--include-code", "Include source code in results").option("--context-lines <n>", "Lines of context around code").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, nameArg, options) => {
2655
+ await withCliErrorHandling(options.json ?? false, async () => {
2656
+ const deps = await createContainer();
2657
+ await codeFindAction(packageArg, nameArg, options, deps);
2658
+ });
2659
+ });
2660
+ }
2661
+ // src/commands/code/imports.ts
2662
+ function formatImport(entry) {
2663
+ const parts = [];
2664
+ const kindLabel = entry.kind ? `[${entry.kind}]` : "";
2665
+ const typeLabel = entry.typeOnly ? " (type)" : "";
2666
+ const aliasLabel = entry.alias ? ` as ${entry.alias}` : "";
2667
+ const imported = entry.imported ?? "*";
2668
+ parts.push(`${kindLabel} ${imported}${aliasLabel}${typeLabel}`.trim());
2669
+ if (entry.sourcePath) {
2670
+ parts.push(` from: ${entry.sourcePath}`);
2671
+ }
2672
+ if (entry.filePath) {
2673
+ const loc = entry.line ? `${entry.filePath}:${entry.line}` : entry.filePath;
2674
+ parts.push(` File: ${loc}`);
2675
+ }
2676
+ if (entry.resolvedPackage) {
2677
+ parts.push(` Resolves to: ${entry.resolvedPackage.registry}:${entry.resolvedPackage.name}`);
2678
+ } else if (entry.package) {
2679
+ parts.push(` Package: ${entry.package}`);
2680
+ }
2681
+ return parts.join(`
2682
+ `);
2683
+ }
2684
+ function formatImportsResult(data) {
2685
+ const lines = [];
2686
+ lines.push(`${data.imports.length} import(s)`);
2687
+ if (data.uniqueDependencies && data.uniqueDependencies.length > 0) {
2688
+ lines.push(`Unique dependencies: ${data.uniqueDependencies.join(", ")}`);
2689
+ }
2690
+ if (data.unresolvedCount != null && data.unresolvedCount > 0) {
2691
+ lines.push(`Unresolved: ${data.unresolvedCount}`);
2692
+ }
2693
+ lines.push("");
2694
+ for (const entry of data.imports) {
2695
+ lines.push(formatImport(entry));
2696
+ lines.push("");
2697
+ }
2698
+ return lines.join(`
2699
+ `).trimEnd();
2700
+ }
2701
+ async function codeImportsAction(packageArg, options, deps) {
2702
+ const { pkgseerService } = deps;
2703
+ const parsed = parsePackageSpec(packageArg);
2704
+ const registry = toGraphQLRegistry(parsed.registry);
2705
+ const result = await pkgseerService.packageImports(registry, parsed.name, {
2706
+ filePath: options.file,
2707
+ resolvedOnly: options.resolvedOnly,
2708
+ limit: parseIntOption(options.limit, "--limit"),
2709
+ version: parsed.version,
2710
+ mode: parseNavigationMode(options.mode),
2711
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2712
+ });
2713
+ handleErrors(result.errors, options.json ?? false);
2714
+ if (!result.data.packageImports) {
2715
+ outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
2716
+ return;
2717
+ }
2718
+ if (options.json) {
2719
+ output(result.data.packageImports, true);
2720
+ } else {
2721
+ console.log(formatImportsResult(result.data.packageImports));
2722
+ }
2723
+ }
2724
+ var IMPORTS_DESCRIPTION = `List import statements in a package.
2725
+
2726
+ Shows what a package imports, including source paths, resolved packages,
2727
+ and import types. Useful for understanding package dependencies at code level.
2728
+
2729
+ Examples:
2730
+ pkgseer code imports npm:express
2731
+ pkgseer code imports npm:lodash --file src/index.js
2732
+ pkgseer code imports pypi:requests --resolved-only`;
2733
+ function registerCodeImportsCommand(program) {
2734
+ program.command("imports <package>").summary("List package import statements").description(IMPORTS_DESCRIPTION).option("--file <path>", "Filter by source file path").option("--resolved-only", "Only show resolved imports").option("--limit <n>", "Max results").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, options) => {
2735
+ await withCliErrorHandling(options.json ?? false, async () => {
2736
+ const deps = await createContainer();
2737
+ await codeImportsAction(packageArg, options, deps);
2738
+ });
2739
+ });
2740
+ }
2741
+ // src/commands/code/list.ts
2742
+ function formatListResult(data) {
2743
+ const lines = [];
2744
+ lines.push(`${data.total} symbol(s)${data.hasMore ? " (more available)" : ""}`);
2745
+ if (data.namespaces && data.namespaces.length > 0) {
2746
+ lines.push(`Namespaces: ${data.namespaces.join(", ")}`);
2747
+ }
2748
+ if (data.file) {
2749
+ lines.push(`File: ${data.file.path}${data.file.language ? ` (${data.file.language})` : ""}`);
2750
+ }
2751
+ if (data.error) {
2752
+ lines.push(`Warning: ${data.error}`);
2753
+ }
2754
+ lines.push("");
2755
+ for (const symbol of data.symbols) {
2756
+ lines.push(formatSymbol(symbol));
2757
+ lines.push("");
2758
+ }
2759
+ return lines.join(`
2760
+ `).trimEnd();
2761
+ }
2762
+ async function codeListAction(packageArg, options, deps) {
2763
+ const { pkgseerService } = deps;
2764
+ const parsed = parsePackageSpec(packageArg);
2765
+ const registry = toGraphQLRegistry(parsed.registry);
2766
+ const scope = options.scope?.toUpperCase() ?? "EXPORTS";
2767
+ if (scope !== "EXPORTS" && scope !== "FILE") {
2768
+ outputError("--scope must be 'exports' or 'file'", options.json ?? false);
2769
+ return;
2770
+ }
2771
+ if (scope === "FILE" && !options.file) {
2772
+ outputError("--file is required when --scope is 'file'", options.json ?? false);
2773
+ return;
2774
+ }
2775
+ const result = await pkgseerService.listSymbols(registry, parsed.name, scope, {
2776
+ filePath: options.file,
2777
+ namespace: options.namespace,
2778
+ publicOnly: options.publicOnly,
2779
+ includePopularity: options.includePopularity,
2780
+ limit: parseIntOption(options.limit, "--limit"),
2781
+ version: parsed.version,
2782
+ mode: parseNavigationMode(options.mode),
2783
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2784
+ });
2785
+ handleErrors(result.errors, options.json ?? false);
2786
+ if (!result.data.listSymbols) {
2787
+ outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
2788
+ return;
2789
+ }
2790
+ if (options.json) {
2791
+ output(result.data.listSymbols, true);
2792
+ } else {
2793
+ console.log(formatListResult(result.data.listSymbols));
2794
+ }
2795
+ }
2796
+ var LIST_DESCRIPTION = `Browse symbols in a package.
2797
+
2798
+ Lists public exports (default) or file contents. Returns symbol names,
2799
+ types, locations, and optionally popularity data.
2800
+
2801
+ Examples:
2802
+ pkgseer code list npm:express
2803
+ pkgseer code list npm:lodash --namespace array
2804
+ pkgseer code list npm:express --scope file --file src/router.js
2805
+ pkgseer code list pypi:requests --include-popularity`;
2806
+ function registerCodeListCommand(program) {
2807
+ program.command("list <package>").summary("Browse symbols in a package").description(LIST_DESCRIPTION).option("--scope <scope>", "Scope: exports (default) or file").option("--file <path>", "File path (required when scope=file)").option("--namespace <ns>", "Filter by namespace").option("--public-only", "Only show public symbols").option("--include-popularity", "Include popularity data").option("--limit <n>", "Max results").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, options) => {
2808
+ await withCliErrorHandling(options.json ?? false, async () => {
2809
+ const deps = await createContainer();
2810
+ await codeListAction(packageArg, options, deps);
2811
+ });
2812
+ });
2813
+ }
2814
+ // src/commands/code/path.ts
2815
+ function formatPathResult(data) {
2816
+ const lines = [];
2817
+ const fromName = data.fromSymbol.qualifiedPath ?? data.fromSymbol.name;
2818
+ const toName = data.toSymbol.qualifiedPath ?? data.toSymbol.name;
2819
+ lines.push(`Call path: ${fromName} -> ${toName}`);
2820
+ if (!data.pathFound) {
2821
+ lines.push("No path found between these symbols.");
2822
+ return lines.join(`
2823
+ `);
2824
+ }
2825
+ lines.push(`${data.paths.length} path(s) found`);
2826
+ lines.push("");
2827
+ for (const [i, callPath] of data.paths.entries()) {
2828
+ lines.push(`Path ${i + 1} (${callPath.length} hop${callPath.length !== 1 ? "s" : ""}):`);
2829
+ for (const [j, hop] of callPath.hops.entries()) {
2830
+ const name = hop.qualifiedPath ?? hop.name ?? "unknown";
2831
+ const loc = hop.filePath ? hop.callLine ? ` ${hop.filePath}:${hop.callLine}` : ` ${hop.filePath}` : "";
2832
+ const idPart = hop.symbolId ? ` (id:${hop.symbolId})` : "";
2833
+ const arrow = j < callPath.hops.length - 1 ? " ->" : "";
2834
+ lines.push(` ${j + 1}. ${name}${idPart}${loc}${arrow}`);
2835
+ }
2836
+ lines.push("");
2837
+ }
2838
+ return lines.join(`
2839
+ `).trimEnd();
2840
+ }
2841
+ async function codePathAction(fromArg, toArg, options, deps) {
2842
+ const { pkgseerService } = deps;
2843
+ const fromRef = buildSymbolReference(fromArg, options.fromId);
2844
+ const toRef = buildSymbolReference(toArg, options.toId);
2845
+ const result = await pkgseerService.callPath(fromRef, toRef, {
2846
+ maxDepth: parseIntOption(options.maxDepth, "--max-depth"),
2847
+ mode: parseNavigationMode(options.mode),
2848
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2849
+ });
2850
+ handleErrors(result.errors, options.json ?? false);
2851
+ if (!result.data.callPath) {
2852
+ outputError("Could not find call path. Verify the symbol references.", options.json ?? false);
2853
+ return;
2854
+ }
2855
+ if (options.json) {
2856
+ output(result.data.callPath, true);
2857
+ } else {
2858
+ console.log(formatPathResult(result.data.callPath));
2859
+ }
2860
+ }
2861
+ var PATH_DESCRIPTION = `Find call path between two symbols.
2862
+
2863
+ Discovers the shortest call path from one symbol to another.
2864
+ Use registry:package#symbolName format or --from-id/--to-id for direct lookup.
2865
+
2866
+ Examples:
2867
+ pkgseer code path npm:express#app npm:express#Router
2868
+ pkgseer code path --from-id 123 --to-id 456
2869
+ pkgseer code path npm:lodash#merge npm:lodash#cloneDeep --max-depth 5`;
2870
+ function registerCodePathCommand(program) {
2871
+ program.command("path [from] [to]").summary("Find call path between symbols").description(PATH_DESCRIPTION).option("--from-id <id>", "Source symbol ID").option("--to-id <id>", "Target symbol ID").option("--max-depth <n>", "Max path depth").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (fromArg, toArg, options) => {
2872
+ await withCliErrorHandling(options.json ?? false, async () => {
2873
+ const deps = await createContainer();
2874
+ await codePathAction(fromArg, toArg, options, deps);
2875
+ });
2876
+ });
2877
+ }
2878
+ // src/commands/code/search.ts
2879
+ function formatSearchResult(data) {
2880
+ const lines = [];
2881
+ lines.push(`${data.totalMatches} match(es)${data.hasMore ? " (more available)" : ""}`);
2882
+ if (data.indexedVersion) {
2883
+ lines.push(`Indexed version: ${data.indexedVersion}`);
2884
+ }
2885
+ lines.push("");
2886
+ for (const entry of data.results) {
2887
+ const kindLabel = entry.chunkType ? `[${entry.chunkType}]` : "";
2888
+ const name = entry.name ?? "unnamed";
2889
+ lines.push(`${kindLabel} ${name}`.trim());
2890
+ if (entry.filePath) {
2891
+ const loc = entry.startLine ? `${entry.filePath}:${entry.startLine}` : entry.filePath;
2892
+ lines.push(` File: ${loc}`);
2893
+ }
2894
+ if (entry.preview) {
2895
+ lines.push(` ${truncate(entry.preview, 200)}`);
2896
+ }
2897
+ lines.push("");
2898
+ }
2899
+ return lines.join(`
2900
+ `).trimEnd();
2901
+ }
2902
+ async function codeSearchAction(packageArg, query, options, deps) {
2903
+ const { pkgseerService } = deps;
2904
+ const parsed = parsePackageSpec(packageArg);
2905
+ const registry = toGraphQLRegistry(parsed.registry);
2906
+ const result = await pkgseerService.searchSymbols(registry, parsed.name, query, {
2907
+ kind: options.kind?.toUpperCase(),
2908
+ version: parsed.version,
2909
+ limit: parseIntOption(options.limit, "--limit"),
2910
+ mode: parseNavigationMode(options.mode),
2911
+ waitTimeoutMs: parseWaitTimeout(options.wait)
2912
+ });
2913
+ handleErrors(result.errors, options.json ?? false);
2914
+ if (!result.data.searchSymbols) {
2915
+ outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
2916
+ return;
2917
+ }
2918
+ if (options.json) {
2919
+ output(result.data.searchSymbols, true);
2920
+ } else {
2921
+ console.log(formatSearchResult(result.data.searchSymbols));
2922
+ }
2923
+ }
2924
+ var SEARCH_DESCRIPTION = `Full-text search within package code.
2925
+
2926
+ Searches across functions, classes, modules, and doc sections.
2927
+ Returns matching code chunks with names, types, and previews.
2928
+
2929
+ Examples:
2930
+ pkgseer code search npm:express "middleware"
2931
+ pkgseer code search pypi:requests "timeout" --kind function
2932
+ pkgseer code search npm:lodash "deep clone" --limit 10`;
2933
+ function registerCodeSearchCommand(program) {
2934
+ program.command("search <package> <query>").summary("Full-text search in package code").description(SEARCH_DESCRIPTION).option("--kind <kind>", "Filter by chunk type (function, class, module, etc.)").option("--limit <n>", "Max results (default: 25, max: 50)").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, query, options) => {
2935
+ await withCliErrorHandling(options.json ?? false, async () => {
2936
+ const deps = await createContainer();
2937
+ await codeSearchAction(packageArg, query, options, deps);
2938
+ });
2939
+ });
2940
+ }
2941
+ // src/commands/config-show.ts
2942
+ async function configShowAction(deps) {
2943
+ const { configService } = deps;
2944
+ const { config, globalPath, projectPath } = await configService.loadMergedConfig();
2945
+ if (!globalPath && !projectPath) {
2946
+ console.log(`No configuration found.
2947
+ `);
2948
+ console.log(" Global config: ~/.pkgseer/config.yml");
2949
+ console.log(` Project config: pkgseer.yml
2950
+ `);
2951
+ console.log("Create a config file to customize pkgseer behavior.");
2952
+ return;
2953
+ }
2954
+ console.log(`Configuration sources:
2955
+ `);
2956
+ if (globalPath) {
2957
+ console.log(` Global: ${globalPath}`);
2958
+ }
2959
+ if (projectPath) {
2960
+ console.log(` Project: ${projectPath}`);
2961
+ }
2962
+ console.log(`
2963
+ Merged configuration:
2964
+ `);
2965
+ if (config.enabled_tools !== undefined) {
2966
+ if (config.enabled_tools.length > 0) {
2967
+ console.log(" enabled_tools:");
2968
+ for (const tool of config.enabled_tools) {
2969
+ console.log(` - ${tool}`);
2970
+ }
2971
+ } else {
2972
+ console.log(" enabled_tools: [] (no tools enabled)");
2973
+ }
2974
+ } else {
2975
+ console.log(" enabled_tools: (all tools enabled by default)");
2976
+ }
2977
+ if (config.project) {
2978
+ console.log(` project: ${config.project}`);
2979
+ }
2980
+ }
2981
+ var SHOW_DESCRIPTION = `Display current configuration.
2982
+
2983
+ Shows the merged configuration from global (~/.pkgseer/config.yml) and
2984
+ project (pkgseer.yml) config files. Project config takes precedence
2985
+ over global config for overlapping settings.`;
2986
+ function registerConfigShowCommand(program) {
2987
+ program.command("show").summary("Display current configuration").description(SHOW_DESCRIPTION).action(async () => {
2988
+ const deps = await createContainer();
2989
+ await configShowAction(deps);
2990
+ });
2991
+ }
2992
+
2993
+ // src/commands/docs/get.ts
2994
+ function parsePackageRef(ref) {
2995
+ if (!ref.includes("/")) {
2996
+ return {
2997
+ pageId: ref,
2998
+ originalRef: ref,
2999
+ isGlobalId: true
3000
+ };
3001
+ }
3002
+ const parts = ref.split("/");
3003
+ if (parts.length < 2) {
3004
+ throw new Error(`Invalid format: "${ref}". Expected at least 2 parts separated by "/"`);
3005
+ }
3006
+ if (parts.length >= 4) {
3007
+ const registry = parts[0];
3008
+ const packageName2 = parts[1];
3009
+ const version2 = parts[2];
3010
+ const pageId2 = parts.slice(3).join("/");
1991
3011
  if (!registry || !packageName2 || !version2 || !pageId2) {
1992
3012
  throw new Error(`Invalid full form: "${ref}". All components (registry/package/version/document) are required.`);
1993
3013
  }
@@ -2338,7 +3358,7 @@ async function docsListAction(packageArg, options, deps) {
2338
3358
  console.log(formatDocsList(result.data.listPackageDocs));
2339
3359
  }
2340
3360
  }
2341
- var LIST_DESCRIPTION = `List available documentation pages for a package.
3361
+ var LIST_DESCRIPTION2 = `List available documentation pages for a package.
2342
3362
 
2343
3363
  Shows all documentation pages with titles, globally unique page IDs,
2344
3364
  word counts, and descriptions. Use the page ID with 'docs get'
@@ -2351,15 +3371,66 @@ Examples:
2351
3371
  pkgseer docs list pypi:requests
2352
3372
  pkgseer docs list hex:phoenix@1.7.0 --json`;
2353
3373
  function registerDocsListCommand(program) {
2354
- program.command("list <package>").summary("List documentation pages").description(LIST_DESCRIPTION).option("-r, --registry <registry>", "Package registry", "npm").option("-V, --pkg-version <version>", "Package version").option("--json", "Output as JSON").action(async (packageName, options) => {
3374
+ program.command("list <package>").summary("List documentation pages").description(LIST_DESCRIPTION2).option("-r, --registry <registry>", "Package registry", "npm").option("-V, --pkg-version <version>", "Package version").option("--json", "Output as JSON").action(async (packageName, options) => {
2355
3375
  await withCliErrorHandling(options.json ?? false, async () => {
2356
3376
  const deps = await createContainer();
2357
3377
  await docsListAction(packageName, options, deps);
2358
3378
  });
2359
3379
  });
2360
3380
  }
3381
+ // src/lib/polling.ts
3382
+ var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3383
+ async function pollUntilDone(config) {
3384
+ const {
3385
+ fetch: fetch2,
3386
+ isDone,
3387
+ onUpdate,
3388
+ intervalMs,
3389
+ maxWaitMs,
3390
+ sleep = defaultSleep,
3391
+ now = Date.now
3392
+ } = config;
3393
+ const startTime = now();
3394
+ let lastData;
3395
+ while (true) {
3396
+ try {
3397
+ const data = await fetch2();
3398
+ lastData = data;
3399
+ if (onUpdate) {
3400
+ onUpdate(data);
3401
+ }
3402
+ if (isDone(data)) {
3403
+ return { success: true, data };
3404
+ }
3405
+ const elapsed = now() - startTime;
3406
+ if (elapsed >= maxWaitMs) {
3407
+ return {
3408
+ success: false,
3409
+ error: `Client polling timeout after ${elapsed}ms`,
3410
+ lastData
3411
+ };
3412
+ }
3413
+ await sleep(intervalMs);
3414
+ } catch (error) {
3415
+ const message = error instanceof Error ? error.message : String(error);
3416
+ return {
3417
+ success: false,
3418
+ error: `Poll failed: ${message}`,
3419
+ lastData
3420
+ };
3421
+ }
3422
+ }
3423
+ }
3424
+
2361
3425
  // src/commands/search.ts
2362
3426
  var DEFAULT_WAIT_TIMEOUT_MS = 30000;
3427
+ var DEFAULT_POLL_INTERVAL_MS = 2000;
3428
+ var DEFAULT_MAX_POLL_TIME_MS = 120000;
3429
+ var TERMINAL_STATUSES = [
3430
+ "COMPLETED",
3431
+ "TIMEOUT",
3432
+ "FAILED"
3433
+ ];
2363
3434
  var colors = {
2364
3435
  reset: "\x1B[0m",
2365
3436
  bold: "\x1B[1m",
@@ -2575,7 +3646,7 @@ function abbrevLang(lang) {
2575
3646
  const lower = lang.toLowerCase();
2576
3647
  return LANG_ABBREV[lower] ?? lower;
2577
3648
  }
2578
- function truncate(text, maxLen) {
3649
+ function truncate2(text, maxLen) {
2579
3650
  if (text.length <= maxLen)
2580
3651
  return text;
2581
3652
  return `${text.slice(0, maxLen - 3)}...`;
@@ -2629,9 +3700,9 @@ function formatEntryCompact(entry, useColors) {
2629
3700
  if (entry.snippet) {
2630
3701
  const bestLine = findBestSnippetLine(entry.snippet);
2631
3702
  if (bestLine) {
2632
- snippet = ` ${truncate(bestLine, 80)}`;
3703
+ snippet = ` ${truncate2(bestLine, 80)}`;
2633
3704
  if (useColors) {
2634
- snippet = ` ${colors.dim}${truncate(bestLine, 80)}${colors.reset}`;
3705
+ snippet = ` ${colors.dim}${truncate2(bestLine, 80)}${colors.reset}`;
2635
3706
  }
2636
3707
  }
2637
3708
  }
@@ -2737,24 +3808,138 @@ function formatSearchProgress(progress, searchRef, useColors) {
2737
3808
  lines.push(`Search ref: ${searchRef}`);
2738
3809
  }
2739
3810
  }
2740
- return lines.join(`
2741
- `);
2742
- }
2743
- function getWaitTimeoutMs(options) {
2744
- if (options.noWait) {
2745
- return 0;
3811
+ return lines.join(`
3812
+ `);
3813
+ }
3814
+ function getWaitTimeoutMs(options) {
3815
+ if (options.noWait) {
3816
+ return 0;
3817
+ }
3818
+ if (options.wait) {
3819
+ const parsed = Number.parseInt(options.wait, 10);
3820
+ if (!Number.isNaN(parsed) && parsed >= 0) {
3821
+ return parsed;
3822
+ }
3823
+ console.warn(`Warning: Invalid --wait value "${options.wait}". Using default (${DEFAULT_WAIT_TIMEOUT_MS}ms).`);
3824
+ }
3825
+ return DEFAULT_WAIT_TIMEOUT_MS;
3826
+ }
3827
+ function shouldPoll(options) {
3828
+ if (options.noPoll) {
3829
+ return false;
3830
+ }
3831
+ return process.stdout.isTTY ?? false;
3832
+ }
3833
+ async function pollSearchProgress(searchRef, pkgseerService, useColors) {
3834
+ const result = await pollUntilDone({
3835
+ fetch: async () => {
3836
+ const res = await pkgseerService.getSearchProgress(searchRef);
3837
+ return res.data.searchProgress ?? null;
3838
+ },
3839
+ isDone: (progress) => {
3840
+ if (!progress)
3841
+ return true;
3842
+ return TERMINAL_STATUSES.includes(progress.status);
3843
+ },
3844
+ onUpdate: (progress) => {
3845
+ if (progress) {
3846
+ const statusText = progress.status?.toLowerCase() ?? "unknown";
3847
+ const ready = progress.packagesReady ?? 0;
3848
+ const total = progress.packagesTotal ?? 0;
3849
+ const elapsed = ((progress.elapsedMs ?? 0) / 1000).toFixed(1);
3850
+ console.log(` ${statusText} (${ready}/${total} ready) - ${elapsed}s`);
3851
+ }
3852
+ },
3853
+ intervalMs: DEFAULT_POLL_INTERVAL_MS,
3854
+ maxWaitMs: DEFAULT_MAX_POLL_TIME_MS
3855
+ });
3856
+ if (!result.success) {
3857
+ return { success: false, error: result.error };
3858
+ }
3859
+ if (!result.data) {
3860
+ return { success: false, error: "Search session not found" };
3861
+ }
3862
+ return { success: true, status: result.data.status };
3863
+ }
3864
+ async function handleResume(searchRef, pkgseerService, options, useColors) {
3865
+ const progressResult = await pkgseerService.getSearchProgress(searchRef);
3866
+ if (progressResult.errors?.length) {
3867
+ handleErrors(progressResult.errors, options.json ?? false);
3868
+ return true;
3869
+ }
3870
+ const progress = progressResult.data.searchProgress;
3871
+ if (!progress) {
3872
+ outputError("Search session not found. It may have expired (sessions last 1 hour).", options.json ?? false);
3873
+ return true;
3874
+ }
3875
+ if (progress.status === "COMPLETED") {
3876
+ const resultsResponse = await pkgseerService.getSearchResults(searchRef);
3877
+ if (resultsResponse.errors?.length) {
3878
+ handleErrors(resultsResponse.errors, options.json ?? false);
3879
+ return true;
3880
+ }
3881
+ const searchResults = resultsResponse.data.searchResults;
3882
+ if (!searchResults) {
3883
+ outputError("Search completed but no results returned.", options.json ?? false);
3884
+ return true;
3885
+ }
3886
+ outputResults(searchResults, options, useColors);
3887
+ return true;
3888
+ }
3889
+ if (progress.status === "FAILED") {
3890
+ outputError(`Search failed. Ref: ${searchRef}`, options.json ?? false);
3891
+ return true;
3892
+ }
3893
+ if (progress.status === "TIMEOUT") {
3894
+ outputError(`Search timed out. Try again or use --wait with a higher value.
3895
+ Ref: ${searchRef}`, options.json ?? false);
3896
+ return true;
2746
3897
  }
2747
- if (options.wait) {
2748
- const parsed = Number.parseInt(options.wait, 10);
2749
- if (!Number.isNaN(parsed) && parsed >= 0) {
2750
- return parsed;
3898
+ if (options.json) {
3899
+ output({
3900
+ completed: false,
3901
+ searchRef,
3902
+ progress: {
3903
+ status: progress.status,
3904
+ packagesTotal: progress.packagesTotal,
3905
+ packagesReady: progress.packagesReady,
3906
+ elapsedMs: progress.elapsedMs
3907
+ },
3908
+ message: "Search is still in progress."
3909
+ }, true);
3910
+ return true;
3911
+ }
3912
+ console.log("Checking search status...");
3913
+ console.log(`Status: ${progress.status?.toLowerCase() ?? "unknown"}`);
3914
+ if (shouldPoll(options)) {
3915
+ console.log("Polling for completion...");
3916
+ const pollResult = await pollSearchProgress(searchRef, pkgseerService, useColors);
3917
+ if (!pollResult.success) {
3918
+ outputError(pollResult.error, false);
3919
+ console.log(`Resume with: pkgseer search --resume ${searchRef}`);
3920
+ return true;
2751
3921
  }
2752
- console.warn(`Warning: Invalid --wait value "${options.wait}". Using default (${DEFAULT_WAIT_TIMEOUT_MS}ms).`);
3922
+ if (pollResult.status === "COMPLETED") {
3923
+ const resultsResponse = await pkgseerService.getSearchResults(searchRef);
3924
+ if (resultsResponse.data.searchResults) {
3925
+ outputResults(resultsResponse.data.searchResults, options, useColors);
3926
+ }
3927
+ } else {
3928
+ console.log(`Search ended with status: ${pollResult.status.toLowerCase()}`);
3929
+ }
3930
+ } else {
3931
+ console.log(`
3932
+ Resume with: pkgseer search --resume ${searchRef}`);
2753
3933
  }
2754
- return DEFAULT_WAIT_TIMEOUT_MS;
3934
+ return true;
2755
3935
  }
2756
3936
  async function searchAction(queryArg, options, deps, defaultMode = "ALL") {
2757
3937
  const { pkgseerService } = deps;
3938
+ const useColors = shouldUseColors(options.noColor);
3939
+ if (options.resume?.trim()) {
3940
+ await handleResume(options.resume.trim(), pkgseerService, options, useColors);
3941
+ return;
3942
+ }
2758
3943
  const query = Array.isArray(queryArg) ? queryArg.join(" ") : queryArg ?? "";
2759
3944
  if (!query.trim()) {
2760
3945
  outputError("Search query required. Provide query as argument.", options.json ?? false);
@@ -2771,7 +3956,6 @@ async function searchAction(queryArg, options, deps, defaultMode = "ALL") {
2771
3956
  const packages = parsePackageList(options.packages);
2772
3957
  const limit = options.limit ? Number.parseInt(options.limit, 10) : 25;
2773
3958
  const mode = options.mode ? toSearchMode(options.mode) : defaultMode;
2774
- const useColors = shouldUseColors(options.noColor);
2775
3959
  const waitTimeoutMs = getWaitTimeoutMs(options);
2776
3960
  const result = await pkgseerService.combinedSearch(packages, query, {
2777
3961
  mode,
@@ -2785,16 +3969,40 @@ async function searchAction(queryArg, options, deps, defaultMode = "ALL") {
2785
3969
  return;
2786
3970
  }
2787
3971
  if (!asyncResult.completed) {
3972
+ const searchRef = asyncResult.searchRef;
2788
3973
  if (options.json) {
2789
3974
  output({
2790
3975
  completed: false,
2791
- searchRef: asyncResult.searchRef,
3976
+ searchRef,
2792
3977
  progress: asyncResult.progress,
2793
3978
  message: "Search is still indexing. Retry for complete results."
2794
3979
  }, true);
2795
- } else {
2796
- console.log(formatSearchProgress(asyncResult.progress, asyncResult.searchRef, useColors));
3980
+ return;
3981
+ }
3982
+ if (shouldPoll(options) && searchRef) {
3983
+ console.log("Search in progress, polling for completion...");
3984
+ const pollResult = await pollSearchProgress(searchRef, pkgseerService, useColors);
3985
+ if (pollResult.success && pollResult.status === "COMPLETED") {
3986
+ const resultsResponse = await pkgseerService.getSearchResults(searchRef);
3987
+ if (resultsResponse.data.searchResults) {
3988
+ console.log("");
3989
+ outputResults(resultsResponse.data.searchResults, options, useColors);
3990
+ return;
3991
+ }
3992
+ }
3993
+ if (!pollResult.success) {
3994
+ console.log(`
3995
+ ${pollResult.error}`);
3996
+ } else if (pollResult.status !== "COMPLETED") {
3997
+ console.log(`
3998
+ Search ended with status: ${pollResult.status.toLowerCase()}`);
3999
+ }
4000
+ if (searchRef) {
4001
+ console.log(`Resume with: pkgseer search --resume ${searchRef}`);
4002
+ }
4003
+ return;
2797
4004
  }
4005
+ console.log(formatSearchProgress(asyncResult.progress, searchRef, useColors));
2798
4006
  return;
2799
4007
  }
2800
4008
  const searchResults = asyncResult.result;
@@ -2820,7 +4028,7 @@ function outputResults(results, options, useColors) {
2820
4028
  console.log(formatSearchResultsCompact(results, useColors));
2821
4029
  }
2822
4030
  }
2823
- var SEARCH_DESCRIPTION = `Search code and documentation across packages.
4031
+ var SEARCH_DESCRIPTION2 = `Search code and documentation across packages.
2824
4032
 
2825
4033
  Searches both code (functions, classes) and documentation pages
2826
4034
  using the combined search endpoint. Returns results with snippets
@@ -2853,10 +4061,10 @@ Examples:
2853
4061
  # JSON output
2854
4062
  pkgseer search "error" -P express --json`;
2855
4063
  function addSearchOptions(cmd) {
2856
- return cmd.option("-P, --packages <packages>", "Packages to search (comma-separated). Format: name or registry/name[@version]. Examples: express | express,lodash | pypi/django@4.2").option("-m, --mode <mode>", "Search mode: all (default), code, docs").option("-l, --limit <n>", "Max results (default: 25)").option("-v, --verbose", "Expanded output with more details").option("--refs-only", "Output only references (for piping)").option("--count", "Output result counts by package").option("--format <format>", "Output format: human|summary|json", "human").option("--no-color", "Disable colored output").option("--json", "Output as JSON").option("--wait <ms>", "Max milliseconds to wait for indexing (default: 30000)").option("--no-wait", "Return immediately without waiting for indexing");
4064
+ return cmd.option("-P, --packages <packages>", "Packages to search (comma-separated). Format: name or registry/name[@version]. Examples: express | express,lodash | pypi/django@4.2").option("-m, --mode <mode>", "Search mode: all (default), code, docs").option("-l, --limit <n>", "Max results (default: 25)").option("-v, --verbose", "Expanded output with more details").option("--refs-only", "Output only references (for piping)").option("--count", "Output result counts by package").option("--format <format>", "Output format: human|summary|json", "human").option("--no-color", "Disable colored output").option("--json", "Output as JSON").option("--wait <ms>", "Max milliseconds to wait for indexing (default: 30000)").option("--no-wait", "Return immediately without waiting for indexing").option("--resume <ref>", "Resume a previous search by reference").option("--no-poll", "Disable auto-polling for incomplete searches");
2857
4065
  }
2858
4066
  function registerSearchCommand(program) {
2859
- const cmd = program.command("search [query...]").summary("Search code and documentation across packages").description(SEARCH_DESCRIPTION);
4067
+ const cmd = program.command("search [query...]").summary("Search code and documentation across packages").description(SEARCH_DESCRIPTION2);
2860
4068
  addSearchOptions(cmd).action(async (query, options) => {
2861
4069
  await withCliErrorHandling(options.json ?? false, async () => {
2862
4070
  const deps = await createContainer();
@@ -2905,6 +4113,70 @@ function registerDocsSearchCommand(program) {
2905
4113
  });
2906
4114
  });
2907
4115
  }
4116
+ // src/commands/index-cmd.ts
4117
+ async function indexAction(packages, options, deps) {
4118
+ const { pkgseerService } = deps;
4119
+ const input2 = {};
4120
+ if (packages.length > 0) {
4121
+ input2.packages = packages.map((spec) => {
4122
+ const parsed = parsePackageSpec(spec);
4123
+ return {
4124
+ registry: toGraphQLRegistry(parsed.registry),
4125
+ name: parsed.name,
4126
+ version: parsed.version
4127
+ };
4128
+ });
4129
+ }
4130
+ if (options.repo && options.repo.length > 0) {
4131
+ input2.repositories = options.repo.map((url) => ({
4132
+ url,
4133
+ ref: options.ref,
4134
+ discoverPackages: options.discoverPackages
4135
+ }));
4136
+ }
4137
+ if (!input2.packages?.length && !input2.repositories?.length) {
4138
+ console.error("Error: Provide at least one package or --repo URL.");
4139
+ process.exit(1);
4140
+ }
4141
+ const result = await pkgseerService.triggerIndexing(input2);
4142
+ handleErrors(result.errors, options.json ?? false);
4143
+ const data = result.data.triggerIndexing;
4144
+ if (options.json) {
4145
+ output(data, true);
4146
+ } else {
4147
+ if (data) {
4148
+ console.log(`Accepted: ${data.accepted}`);
4149
+ console.log(`Skipped: ${data.skipped}`);
4150
+ } else {
4151
+ console.log("Indexing request submitted.");
4152
+ }
4153
+ }
4154
+ }
4155
+ var INDEX_DESCRIPTION = `Trigger pre-indexing for packages or repositories.
4156
+
4157
+ Requests that PkgSeer index the specified packages or repositories.
4158
+ Useful for warming up indexes before code navigation queries.
4159
+
4160
+ Package specs support registry:name@version format.
4161
+ Repository URLs should be GitHub repository URLs.
4162
+
4163
+ Examples:
4164
+ pkgseer index npm:express npm:lodash
4165
+ pkgseer index pypi:requests@2.31.0
4166
+ pkgseer index --repo https://github.com/expressjs/express
4167
+ pkgseer index --repo https://github.com/org/repo --ref v1.0.0 --discover-packages`;
4168
+ function registerIndexCommand(program) {
4169
+ program.command("index [packages...]").summary("Trigger pre-indexing for packages or repositories").description(INDEX_DESCRIPTION).option("--repo <url>", "Repository URL to index (repeatable)", collectValues, []).option("--ref <ref>", "Git ref for repository indexing").option("--discover-packages", "Discover and index packages in repository").option("--json", "Output as JSON").action(async (packages, options) => {
4170
+ await withCliErrorHandling(options.json ?? false, async () => {
4171
+ const deps = await createContainer();
4172
+ await indexAction(packages, options, deps);
4173
+ });
4174
+ });
4175
+ }
4176
+ function collectValues(value, previous) {
4177
+ return [...previous, value];
4178
+ }
4179
+
2908
4180
  // src/commands/shared-colors.ts
2909
4181
  var colors2 = {
2910
4182
  reset: "\x1B[0m",
@@ -4676,7 +5948,7 @@ function registerLogoutCommand(program) {
4676
5948
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4677
5949
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4678
5950
 
4679
- // src/tools/compare-packages.ts
5951
+ // src/tools/call-path.ts
4680
5952
  import { z as z3 } from "zod";
4681
5953
 
4682
5954
  // src/tools/shared.ts
@@ -4701,15 +5973,68 @@ function toGraphQLRegistry2(registry) {
4701
5973
  npm: "NPM",
4702
5974
  pypi: "PYPI",
4703
5975
  hex: "HEX",
4704
- crates: "CRATES"
5976
+ crates: "CRATES",
5977
+ nuget: "NUGET",
5978
+ maven: "MAVEN",
5979
+ zig: "ZIG",
5980
+ vcpkg: "VCPKG"
4705
5981
  };
4706
5982
  return map[registry.toLowerCase()] || "NPM";
4707
5983
  }
5984
+ function toNavigationMode(mode) {
5985
+ if (!mode)
5986
+ return;
5987
+ const upper = mode.toUpperCase();
5988
+ if (upper === "SUMMARY" || upper === "DETAILED")
5989
+ return upper;
5990
+ return;
5991
+ }
5992
+ var VALID_SYMBOL_KINDS = new Set([
5993
+ "FUNCTION",
5994
+ "METHOD",
5995
+ "CLASS",
5996
+ "MODULE",
5997
+ "INTERFACE",
5998
+ "TYPE",
5999
+ "DOC_SECTION"
6000
+ ]);
6001
+ function toSymbolKind(kind) {
6002
+ if (!kind)
6003
+ return;
6004
+ const upper = kind.toUpperCase();
6005
+ if (VALID_SYMBOL_KINDS.has(upper))
6006
+ return upper;
6007
+ return;
6008
+ }
6009
+ function toListScope(scope) {
6010
+ if (!scope)
6011
+ return;
6012
+ const upper = scope.toUpperCase();
6013
+ if (upper === "EXPORTS" || upper === "FILE")
6014
+ return upper;
6015
+ return;
6016
+ }
4708
6017
  var schemas = {
4709
- registry: z2.enum(["npm", "pypi", "hex", "crates"]).describe("Package registry (npm, pypi, hex, or crates)"),
6018
+ registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).describe("Package registry (npm, pypi, hex, crates, nuget, maven, zig, or vcpkg)"),
4710
6019
  packageName: z2.string().max(255).describe("Name of the package"),
4711
- version: z2.string().max(100).optional().describe("Specific version (defaults to latest)")
6020
+ version: z2.string().max(100).optional().describe("Specific version (defaults to latest)"),
6021
+ navigationMode: z2.enum(["summary", "detailed"]).optional().describe("Response detail level. summary (default) returns core fields; detailed adds all optional fields."),
6022
+ waitTimeoutMs: z2.number().int().min(0).max(30000).optional().describe("Max milliseconds to wait for package indexing (0-30000). 0 = error immediately if not indexed."),
6023
+ symbolReference: z2.object({
6024
+ symbol_id: z2.number().int().optional().describe("Direct symbol ID (preferred when available)"),
6025
+ registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (required for name-based lookup)"),
6026
+ package_name: z2.string().max(255).optional().describe("Package name (required for name-based lookup)"),
6027
+ symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath.")
6028
+ })
4712
6029
  };
6030
+ function toSymbolReferenceInput(ref) {
6031
+ return {
6032
+ symbolId: ref.symbol_id,
6033
+ registry: ref.registry ? toGraphQLRegistry2(ref.registry) : undefined,
6034
+ packageName: ref.package_name,
6035
+ symbolName: ref.symbol_name
6036
+ };
6037
+ }
4713
6038
  function buildHintedMessage(operation, message) {
4714
6039
  const lower = message.toLowerCase();
4715
6040
  const isTimeout = lower.includes("-32001") || lower.includes("timeout") || lower.includes("timed out");
@@ -4747,20 +6072,60 @@ function notFoundError(packageName, registry) {
4747
6072
  return errorResult(`Package not found: ${packageName} in ${registry}`);
4748
6073
  }
4749
6074
 
6075
+ // src/tools/call-path.ts
6076
+ var argsSchema = {
6077
+ from: schemas.symbolReference.describe("Source symbol. Provide either symbol_id or registry + package_name + symbol_name."),
6078
+ to: schemas.symbolReference.describe("Destination symbol. Provide either symbol_id or registry + package_name + symbol_name."),
6079
+ max_depth: z3.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
6080
+ mode: schemas.navigationMode,
6081
+ wait_timeout_ms: schemas.waitTimeoutMs
6082
+ };
6083
+ function createCallPathTool(pkgseerService) {
6084
+ return {
6085
+ name: "call_path",
6086
+ description: "Find the shortest call path between two symbols in the same package. " + "Uses BFS to find how function A eventually calls function B through intermediate calls. " + "Returns: whether a path was found, source and destination symbols, " + "and ordered call paths (shortest first) with hop details.",
6087
+ schema: argsSchema,
6088
+ handler: async (args, _extra) => {
6089
+ return withErrorHandling("find call path", async () => {
6090
+ const fromInput = toSymbolReferenceInput(args.from);
6091
+ const toInput = toSymbolReferenceInput(args.to);
6092
+ if (!fromInput.symbolId && (!fromInput.symbolName || !fromInput.registry || !fromInput.packageName)) {
6093
+ return errorResult("Invalid 'from' symbol: provide either symbol_id or symbol_name with registry and package_name.");
6094
+ }
6095
+ if (!toInput.symbolId && (!toInput.symbolName || !toInput.registry || !toInput.packageName)) {
6096
+ return errorResult("Invalid 'to' symbol: provide either symbol_id or symbol_name with registry and package_name.");
6097
+ }
6098
+ const result = await pkgseerService.callPath(fromInput, toInput, {
6099
+ maxDepth: args.max_depth,
6100
+ mode: toNavigationMode(args.mode),
6101
+ waitTimeoutMs: args.wait_timeout_ms
6102
+ });
6103
+ const graphqlError = handleGraphQLErrors(result.errors);
6104
+ if (graphqlError)
6105
+ return graphqlError;
6106
+ if (!result.data.callPath) {
6107
+ return errorResult("Could not find call path. Verify the symbols exist and the package is indexed.");
6108
+ }
6109
+ return textResult(JSON.stringify(result.data.callPath, null, 2));
6110
+ });
6111
+ }
6112
+ };
6113
+ }
4750
6114
  // src/tools/compare-packages.ts
4751
- var packageInputSchema = z3.object({
4752
- registry: z3.enum(["npm", "pypi", "hex", "crates"]),
4753
- name: z3.string().max(255),
4754
- version: z3.string().max(100).optional()
6115
+ import { z as z4 } from "zod";
6116
+ var packageInputSchema = z4.object({
6117
+ registry: z4.enum(["npm", "pypi", "hex", "crates"]),
6118
+ name: z4.string().max(255),
6119
+ version: z4.string().max(100).optional()
4755
6120
  });
4756
- var argsSchema = {
4757
- packages: z3.array(packageInputSchema).min(2).max(10).describe("List of packages to compare (2-10 packages)")
6121
+ var argsSchema2 = {
6122
+ packages: z4.array(packageInputSchema).min(2).max(10).describe("List of packages to compare (2-10 packages)")
4758
6123
  };
4759
6124
  function createComparePackagesTool(pkgseerService) {
4760
6125
  return {
4761
6126
  name: "compare_packages",
4762
6127
  description: "Compare 2-10 packages side-by-side. Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex, crates). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
4763
- schema: argsSchema,
6128
+ schema: argsSchema2,
4764
6129
  handler: async ({ packages }, _extra) => {
4765
6130
  return withErrorHandling("compare packages", async () => {
4766
6131
  const input2 = packages.map((pkg) => ({
@@ -4781,19 +6146,19 @@ function createComparePackagesTool(pkgseerService) {
4781
6146
  };
4782
6147
  }
4783
6148
  // src/tools/fetch-code-context.ts
4784
- import { z as z4 } from "zod";
4785
- var argsSchema2 = {
4786
- repo_url: z4.string().min(1).describe("Repository URL (GitHub). Example: https://github.com/expressjs/express"),
4787
- git_ref: z4.string().min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
4788
- file_path: z4.string().min(1).describe("Path to file in repository. Example: src/router/index.js"),
4789
- start_line: z4.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
4790
- end_line: z4.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
6149
+ import { z as z5 } from "zod";
6150
+ var argsSchema3 = {
6151
+ repo_url: z5.string().min(1).describe("Repository URL (GitHub). Example: https://github.com/expressjs/express"),
6152
+ git_ref: z5.string().min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
6153
+ file_path: z5.string().min(1).describe("Path to file in repository. Example: src/router/index.js"),
6154
+ start_line: z5.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
6155
+ end_line: z5.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
4791
6156
  };
4792
6157
  function createFetchCodeContextTool(pkgseerService) {
4793
6158
  return {
4794
6159
  name: "fetch_code_context",
4795
6160
  description: "Fetch code content from a repository. Use this to expand code search results and see " + "more context around a match. Returns full file by default, or a specific line range. " + "Requires repo_url, git_ref (tag/commit/branch), and file_path from search results.",
4796
- schema: argsSchema2,
6161
+ schema: argsSchema3,
4797
6162
  handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
4798
6163
  return withErrorHandling("fetch code context", async () => {
4799
6164
  const result = await pkgseerService.fetchCodeContext(repo_url, git_ref, file_path, {
@@ -4812,15 +6177,15 @@ function createFetchCodeContextTool(pkgseerService) {
4812
6177
  };
4813
6178
  }
4814
6179
  // src/tools/fetch-package-doc.ts
4815
- import { z as z5 } from "zod";
4816
- var argsSchema3 = {
4817
- page_id: z5.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
6180
+ import { z as z6 } from "zod";
6181
+ var argsSchema4 = {
6182
+ page_id: z6.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
4818
6183
  };
4819
6184
  function createFetchPackageDocTool(pkgseerService) {
4820
6185
  return {
4821
6186
  name: "fetch_package_doc",
4822
6187
  description: "Get full content of a documentation page. Requires page_id from list_package_docs. " + "Returns: title, full content (markdown/HTML), format type, navigation breadcrumbs, " + "source URL, and last updated timestamp. Use this when you need complete documentation, " + "not just search snippets.",
4823
- schema: argsSchema3,
6188
+ schema: argsSchema4,
4824
6189
  handler: async ({ page_id }, _extra) => {
4825
6190
  return withErrorHandling("fetch documentation page", async () => {
4826
6191
  const result = await pkgseerService.getDocPage(page_id);
@@ -4835,8 +6200,60 @@ function createFetchPackageDocTool(pkgseerService) {
4835
6200
  }
4836
6201
  };
4837
6202
  }
6203
+ // src/tools/find-symbol.ts
6204
+ import { z as z7 } from "zod";
6205
+ var argsSchema5 = {
6206
+ registry: schemas.registry,
6207
+ package_name: schemas.packageName.describe("Name of the package to search for symbols"),
6208
+ name: z7.string().max(500).optional().describe("Symbol name to search for (exact match or prefix). Omit to return all public exports."),
6209
+ namespace: z7.string().max(500).optional().describe("Filter by namespace/module path prefix"),
6210
+ kind: z7.enum([
6211
+ "function",
6212
+ "method",
6213
+ "class",
6214
+ "module",
6215
+ "interface",
6216
+ "type",
6217
+ "doc_section"
6218
+ ]).optional().describe("Filter by symbol kind"),
6219
+ public_only: z7.boolean().optional().describe("Only return public/exported symbols"),
6220
+ version: schemas.version,
6221
+ include_code: z7.boolean().optional().describe("Include source code in results"),
6222
+ context_lines: z7.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
6223
+ mode: schemas.navigationMode,
6224
+ wait_timeout_ms: schemas.waitTimeoutMs
6225
+ };
6226
+ function createFindSymbolTool(pkgseerService) {
6227
+ return {
6228
+ name: "find_symbol",
6229
+ description: "Find functions, methods, or classes by name in a package. " + "Use for targeted lookups when you know the symbol name. " + "Returns: symbol ID, name, qualified path, kind, file location, and optionally source code. " + "Omit name to get all public exports. Use namespace to filter by module path.",
6230
+ schema: argsSchema5,
6231
+ handler: async (args, _extra) => {
6232
+ return withErrorHandling("find symbol", async () => {
6233
+ const result = await pkgseerService.findSymbol(toGraphQLRegistry2(args.registry), args.package_name, {
6234
+ name: args.name,
6235
+ namespace: args.namespace,
6236
+ kind: toSymbolKind(args.kind),
6237
+ publicOnly: args.public_only,
6238
+ version: args.version,
6239
+ includeCode: args.include_code,
6240
+ contextLines: args.context_lines,
6241
+ mode: toNavigationMode(args.mode),
6242
+ waitTimeoutMs: args.wait_timeout_ms
6243
+ });
6244
+ const graphqlError = handleGraphQLErrors(result.errors);
6245
+ if (graphqlError)
6246
+ return graphqlError;
6247
+ if (!result.data.findSymbol) {
6248
+ return notFoundError(args.package_name, args.registry);
6249
+ }
6250
+ return textResult(JSON.stringify(result.data.findSymbol, null, 2));
6251
+ });
6252
+ }
6253
+ };
6254
+ }
4838
6255
  // src/tools/list-package-docs.ts
4839
- var argsSchema4 = {
6256
+ var argsSchema6 = {
4840
6257
  registry: schemas.registry,
4841
6258
  package_name: schemas.packageName.describe("Name of the package to list documentation for"),
4842
6259
  version: schemas.version
@@ -4845,7 +6262,7 @@ function createListPackageDocsTool(pkgseerService) {
4845
6262
  return {
4846
6263
  name: "list_package_docs",
4847
6264
  description: "Discover available documentation pages for a package. Start here before fetching or searching docs. " + "Returns: page titles, unique IDs (needed for fetch_package_doc), word counts, and update timestamps. " + "Workflow: list_package_docs → fetch_package_doc for full content, or search_package_docs to find specific topics.",
4848
- schema: argsSchema4,
6265
+ schema: argsSchema6,
4849
6266
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
4850
6267
  return withErrorHandling("list package documentation", async () => {
4851
6268
  const result = await pkgseerService.listPackageDocs(toGraphQLRegistry2(registry), package_name, version2);
@@ -4860,14 +6277,69 @@ function createListPackageDocsTool(pkgseerService) {
4860
6277
  }
4861
6278
  };
4862
6279
  }
6280
+ // src/tools/list-symbols.ts
6281
+ import { z as z8 } from "zod";
6282
+ var argsSchema7 = {
6283
+ registry: schemas.registry,
6284
+ package_name: schemas.packageName.describe("Name of the package to browse symbols for"),
6285
+ scope: z8.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
6286
+ file_path: z8.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
6287
+ namespace: z8.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
6288
+ public_only: z8.boolean().optional().describe("Only return public symbols"),
6289
+ include_popularity: z8.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
6290
+ limit: z8.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
6291
+ version: schemas.version,
6292
+ mode: schemas.navigationMode,
6293
+ wait_timeout_ms: schemas.waitTimeoutMs
6294
+ };
6295
+ function createListSymbolsTool(pkgseerService) {
6296
+ return {
6297
+ name: "list_symbols",
6298
+ description: "Browse symbols in a package by scope. " + "Use scope='exports' for public API exploration with namespace grouping and optional popularity data. " + "Use scope='file' with file_path to see all symbols in a specific file. " + "Returns: symbols with IDs, names, qualified paths, kinds, and file locations.",
6299
+ schema: argsSchema7,
6300
+ handler: async (args, _extra) => {
6301
+ return withErrorHandling("list symbols", async () => {
6302
+ const scope = toListScope(args.scope);
6303
+ if (!scope) {
6304
+ return {
6305
+ content: [
6306
+ {
6307
+ type: "text",
6308
+ text: "Invalid scope. Use 'exports' or 'file'."
6309
+ }
6310
+ ],
6311
+ isError: true
6312
+ };
6313
+ }
6314
+ const result = await pkgseerService.listSymbols(toGraphQLRegistry2(args.registry), args.package_name, scope, {
6315
+ filePath: args.file_path,
6316
+ namespace: args.namespace,
6317
+ publicOnly: args.public_only,
6318
+ includePopularity: args.include_popularity,
6319
+ limit: args.limit,
6320
+ version: args.version,
6321
+ mode: toNavigationMode(args.mode),
6322
+ waitTimeoutMs: args.wait_timeout_ms
6323
+ });
6324
+ const graphqlError = handleGraphQLErrors(result.errors);
6325
+ if (graphqlError)
6326
+ return graphqlError;
6327
+ if (!result.data.listSymbols) {
6328
+ return notFoundError(args.package_name, args.registry);
6329
+ }
6330
+ return textResult(JSON.stringify(result.data.listSymbols, null, 2));
6331
+ });
6332
+ }
6333
+ };
6334
+ }
4863
6335
  // src/tools/package-dependencies.ts
4864
- import { z as z6 } from "zod";
4865
- var argsSchema5 = {
6336
+ import { z as z9 } from "zod";
6337
+ var argsSchema8 = {
4866
6338
  registry: schemas.registry,
4867
6339
  package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
4868
6340
  version: schemas.version,
4869
- include_transitive: z6.boolean().optional().describe("Whether to include transitive dependency DAG"),
4870
- max_depth: z6.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
6341
+ include_transitive: z9.boolean().optional().describe("Whether to include transitive dependency DAG"),
6342
+ max_depth: z9.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
4871
6343
  };
4872
6344
  function decodeDag(rawDag) {
4873
6345
  if (!rawDag || typeof rawDag !== "object")
@@ -4945,7 +6417,7 @@ function createPackageDependenciesTool(pkgseerService) {
4945
6417
  return {
4946
6418
  name: "package_dependencies",
4947
6419
  description: "Analyze package dependencies. By default returns direct dependencies only. " + "Set include_transitive=true to get the full dependency tree (use max_depth to limit large trees). " + "Returns: dependency names, version constraints, and for transitive deps, a graph with depth levels. " + "Use this to understand complexity before adding a package, or to find nested dependencies.",
4948
- schema: argsSchema5,
6420
+ schema: argsSchema8,
4949
6421
  handler: async ({ registry, package_name, version: version2, include_transitive, max_depth }, _extra) => {
4950
6422
  return withErrorHandling("fetch package dependencies", async () => {
4951
6423
  const result = await pkgseerService.getPackageDependencies(toGraphQLRegistry2(registry), package_name, version2, include_transitive, max_depth);
@@ -4982,8 +6454,46 @@ function createPackageDependenciesTool(pkgseerService) {
4982
6454
  }
4983
6455
  };
4984
6456
  }
6457
+ // src/tools/package-imports.ts
6458
+ import { z as z10 } from "zod";
6459
+ var argsSchema9 = {
6460
+ registry: schemas.registry,
6461
+ package_name: schemas.packageName.describe("Name of the package to get imports for"),
6462
+ file_path: z10.string().max(1000).optional().describe("Filter to a specific file path"),
6463
+ resolved_only: z10.boolean().optional().describe("Only return imports resolved to a known package"),
6464
+ limit: z10.number().int().min(1).max(500).optional().describe("Max imports to return"),
6465
+ version: schemas.version,
6466
+ mode: schemas.navigationMode,
6467
+ wait_timeout_ms: schemas.waitTimeoutMs
6468
+ };
6469
+ function createPackageImportsTool(pkgseerService) {
6470
+ return {
6471
+ name: "package_imports",
6472
+ description: "Get import statements in a package. " + "Returns parsed import/require/use statements with optional resolution to known packages. " + "Use resolved_only=true to see only imports that map to packages in the PkgSeer registry. " + "Includes: source path, imported names, and de-duplicated dependency list.",
6473
+ schema: argsSchema9,
6474
+ handler: async (args, _extra) => {
6475
+ return withErrorHandling("fetch package imports", async () => {
6476
+ const result = await pkgseerService.packageImports(toGraphQLRegistry2(args.registry), args.package_name, {
6477
+ filePath: args.file_path,
6478
+ resolvedOnly: args.resolved_only,
6479
+ limit: args.limit,
6480
+ version: args.version,
6481
+ mode: toNavigationMode(args.mode),
6482
+ waitTimeoutMs: args.wait_timeout_ms
6483
+ });
6484
+ const graphqlError = handleGraphQLErrors(result.errors);
6485
+ if (graphqlError)
6486
+ return graphqlError;
6487
+ if (!result.data.packageImports) {
6488
+ return notFoundError(args.package_name, args.registry);
6489
+ }
6490
+ return textResult(JSON.stringify(result.data.packageImports, null, 2));
6491
+ });
6492
+ }
6493
+ };
6494
+ }
4985
6495
  // src/tools/package-quality.ts
4986
- var argsSchema6 = {
6496
+ var argsSchema10 = {
4987
6497
  registry: schemas.registry,
4988
6498
  package_name: schemas.packageName.describe("Name of the package to analyze"),
4989
6499
  version: schemas.version
@@ -4992,7 +6502,7 @@ function createPackageQualityTool(pkgseerService) {
4992
6502
  return {
4993
6503
  name: "package_quality",
4994
6504
  description: "Evaluate package maintenance health and code quality. Use this to assess if a package is well-maintained " + "before adding it as a dependency. Returns: overall score (0-100), category scores (documentation, " + "testing, community, maintenance), and individual rule results with pass/fail status. " + "Useful for comparing quality between alternative packages.",
4995
- schema: argsSchema6,
6505
+ schema: argsSchema10,
4996
6506
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
4997
6507
  return withErrorHandling("fetch package quality", async () => {
4998
6508
  const result = await pkgseerService.getPackageQuality(toGraphQLRegistry2(registry), package_name, version2);
@@ -5008,7 +6518,7 @@ function createPackageQualityTool(pkgseerService) {
5008
6518
  };
5009
6519
  }
5010
6520
  // src/tools/package-summary.ts
5011
- var argsSchema7 = {
6521
+ var argsSchema11 = {
5012
6522
  registry: schemas.registry,
5013
6523
  package_name: schemas.packageName.describe("Name of the package to retrieve summary for")
5014
6524
  };
@@ -5016,7 +6526,7 @@ function createPackageSummaryTool(pkgseerService) {
5016
6526
  return {
5017
6527
  name: "package_summary",
5018
6528
  description: "Get a comprehensive overview of a package. Use this as your first tool when researching a package. " + "Returns: description, latest version, license, repository URL, download stats, " + "active security advisories count, and quickstart/installation instructions. " + "For deeper analysis, follow up with package_quality (maintenance health) or " + "package_vulnerabilities (security details).",
5019
- schema: argsSchema7,
6529
+ schema: argsSchema11,
5020
6530
  handler: async ({ registry, package_name }, _extra) => {
5021
6531
  return withErrorHandling("fetch package summary", async () => {
5022
6532
  const result = await pkgseerService.getPackageSummary(toGraphQLRegistry2(registry), package_name);
@@ -5032,7 +6542,7 @@ function createPackageSummaryTool(pkgseerService) {
5032
6542
  };
5033
6543
  }
5034
6544
  // src/tools/package-vulnerabilities.ts
5035
- var argsSchema8 = {
6545
+ var argsSchema12 = {
5036
6546
  registry: schemas.registry,
5037
6547
  package_name: schemas.packageName.describe("Name of the package to inspect for vulnerabilities"),
5038
6548
  version: schemas.version
@@ -5041,7 +6551,7 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
5041
6551
  return {
5042
6552
  name: "package_vulnerabilities",
5043
6553
  description: "Check security vulnerabilities for a package. Use this before adding dependencies or when auditing existing ones. " + "Returns: list of CVEs/advisories with severity levels, affected version ranges, fixed versions, " + "and upgrade recommendations. If version is specified, shows only vulnerabilities affecting that version.",
5044
- schema: argsSchema8,
6554
+ schema: argsSchema12,
5045
6555
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
5046
6556
  return withErrorHandling("fetch package vulnerabilities", async () => {
5047
6557
  const result = await pkgseerService.getPackageVulnerabilities(toGraphQLRegistry2(registry), package_name, version2);
@@ -5057,19 +6567,19 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
5057
6567
  };
5058
6568
  }
5059
6569
  // src/tools/search.ts
5060
- import { z as z7 } from "zod";
5061
- var packageInputSchema2 = z7.object({
6570
+ import { z as z11 } from "zod";
6571
+ var packageInputSchema2 = z11.object({
5062
6572
  registry: schemas.registry,
5063
- name: z7.string().min(1).describe("Package name"),
5064
- version: z7.string().optional().describe("Specific version (defaults to latest)")
6573
+ name: z11.string().min(1).describe("Package name"),
6574
+ version: z11.string().optional().describe("Specific version (defaults to latest)")
5065
6575
  });
5066
6576
  var DEFAULT_AGENT_WAIT_TIMEOUT_MS = 1e4;
5067
- var argsSchema9 = {
5068
- packages: z7.array(packageInputSchema2).min(1).max(20).describe("Packages to search (1-20). Each package needs registry and name."),
5069
- query: z7.string().min(1).describe("Search query - natural language or keywords"),
5070
- mode: z7.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
5071
- limit: z7.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
5072
- waitTimeoutMs: z7.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
6577
+ var argsSchema13 = {
6578
+ packages: z11.array(packageInputSchema2).min(1).max(20).describe("Packages to search (1-20). Each package needs registry and name."),
6579
+ query: z11.string().min(1).describe("Search query - natural language or keywords"),
6580
+ mode: z11.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
6581
+ limit: z11.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
6582
+ waitTimeoutMs: z11.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
5073
6583
  };
5074
6584
  function toSearchMode2(mode) {
5075
6585
  if (!mode)
@@ -5108,7 +6618,7 @@ function createSearchTool(pkgseerService) {
5108
6618
  return {
5109
6619
  name: "search",
5110
6620
  description: "Search code and documentation across packages. Returns functions, classes, and documentation pages " + "matching your query. Use mode='code' for code only, mode='docs' for documentation only, or " + "mode='all' (default) for both. Provide 1-20 packages to search. Results include relevance scores " + "and snippets showing matches. If packages need indexing, the search will wait up to waitTimeoutMs " + "(default 10s). If not complete, returns progress info with searchRef for follow-up.",
5111
- schema: argsSchema9,
6621
+ schema: argsSchema13,
5112
6622
  handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
5113
6623
  return withErrorHandling("search packages", async () => {
5114
6624
  const normalizedQuery = query.trim();
@@ -5160,21 +6670,21 @@ function createSearchTool(pkgseerService) {
5160
6670
  };
5161
6671
  }
5162
6672
  // src/tools/search-project-docs.ts
5163
- import { z as z8 } from "zod";
5164
- var argsSchema10 = {
5165
- project_directory: z8.string().optional().describe("Directory to search for pkgseer.yml configuration. " + "Use this to specify which project's context to use when the MCP server " + "is installed at user level. Defaults to MCP server's working directory."),
5166
- project: z8.string().optional().describe("Project name to search. Overrides value from pkgseer.yml if provided."),
5167
- terms: z8.array(z8.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
5168
- match_mode: z8.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
5169
- include_snippets: z8.boolean().optional().describe("Include content excerpts around matches"),
5170
- limit: z8.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
6673
+ import { z as z12 } from "zod";
6674
+ var argsSchema14 = {
6675
+ project_directory: z12.string().optional().describe("Directory to search for pkgseer.yml configuration. " + "Use this to specify which project's context to use when the MCP server " + "is installed at user level. Defaults to MCP server's working directory."),
6676
+ project: z12.string().optional().describe("Project name to search. Overrides value from pkgseer.yml if provided."),
6677
+ terms: z12.array(z12.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
6678
+ match_mode: z12.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
6679
+ include_snippets: z12.boolean().optional().describe("Include content excerpts around matches"),
6680
+ limit: z12.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
5171
6681
  };
5172
6682
  function createSearchProjectDocsTool(deps) {
5173
6683
  const { pkgseerService, configService, defaultProjectDir } = deps;
5174
6684
  return {
5175
6685
  name: "search_project_docs",
5176
6686
  description: "Searches documentation across all dependencies in a PkgSeer project using search terms and match modes (any/all). Returns ranked results from multiple packages. Use project_directory to specify which project's context to use, or project to search a specific project directly.",
5177
- schema: argsSchema10,
6687
+ schema: argsSchema14,
5178
6688
  handler: async ({
5179
6689
  project_directory,
5180
6690
  project,
@@ -5219,6 +6729,234 @@ function createSearchProjectDocsTool(deps) {
5219
6729
  }
5220
6730
  };
5221
6731
  }
6732
+ // src/tools/search-status.ts
6733
+ import { z as z13 } from "zod";
6734
+ var argsSchema15 = {
6735
+ searchRef: z13.string().min(1).describe("Search reference from a previous incomplete search")
6736
+ };
6737
+ function createSearchStatusTool(pkgseerService) {
6738
+ return {
6739
+ name: "search_status",
6740
+ description: "Check the status of an async search and get results if complete. " + "Use this after a search returns incomplete (completed=false) to poll for completion. " + "Returns status (PENDING, INDEXING, SEARCHING, COMPLETED, TIMEOUT, FAILED), " + "progress info (packagesReady/packagesTotal), and results when status is COMPLETED.",
6741
+ schema: argsSchema15,
6742
+ handler: async ({ searchRef }, _extra) => {
6743
+ return withErrorHandling("check search status", async () => {
6744
+ const progressResult = await pkgseerService.getSearchProgress(searchRef);
6745
+ const graphqlError = handleGraphQLErrors(progressResult.errors);
6746
+ if (graphqlError)
6747
+ return graphqlError;
6748
+ const progress = progressResult.data.searchProgress;
6749
+ if (!progress) {
6750
+ return errorResult("Search session not found. It may have expired (sessions last 1 hour).");
6751
+ }
6752
+ if (progress.status === "COMPLETED") {
6753
+ const resultsResponse = await pkgseerService.getSearchResults(searchRef);
6754
+ const resultsError = handleGraphQLErrors(resultsResponse.errors);
6755
+ if (resultsError)
6756
+ return resultsError;
6757
+ const searchResults = resultsResponse.data.searchResults;
6758
+ if (!searchResults) {
6759
+ return errorResult("Search completed but results are no longer available. " + "The session may have expired (sessions last 1 hour).");
6760
+ }
6761
+ return textResult(JSON.stringify({
6762
+ status: progress.status,
6763
+ searchRef: progress.searchRef,
6764
+ result: searchResults
6765
+ }, null, 2));
6766
+ }
6767
+ return textResult(JSON.stringify({
6768
+ status: progress.status,
6769
+ searchRef: progress.searchRef,
6770
+ progress: {
6771
+ packagesTotal: progress.packagesTotal,
6772
+ packagesReady: progress.packagesReady,
6773
+ elapsedMs: progress.elapsedMs
6774
+ },
6775
+ message: progress.status === "FAILED" ? "Search failed." : progress.status === "TIMEOUT" ? "Search timed out before completion." : "Search is still in progress. Poll again to check status."
6776
+ }, null, 2));
6777
+ });
6778
+ }
6779
+ };
6780
+ }
6781
+ // src/tools/search-symbols.ts
6782
+ import { z as z14 } from "zod";
6783
+ var argsSchema16 = {
6784
+ registry: schemas.registry,
6785
+ package_name: schemas.packageName.describe("Name of the package to search within"),
6786
+ query: z14.string().max(500).describe("Search query for full-text code search (max 500 chars)"),
6787
+ kind: z14.enum([
6788
+ "function",
6789
+ "method",
6790
+ "class",
6791
+ "module",
6792
+ "interface",
6793
+ "type",
6794
+ "doc_section"
6795
+ ]).optional().describe("Filter results by code chunk type"),
6796
+ version: schemas.version,
6797
+ limit: z14.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
6798
+ mode: schemas.navigationMode,
6799
+ wait_timeout_ms: schemas.waitTimeoutMs
6800
+ };
6801
+ function createSearchSymbolsTool(pkgseerService) {
6802
+ return {
6803
+ name: "search_symbols",
6804
+ description: "Full-text search within package code. " + "Searches across functions, classes, modules, and doc sections. " + "Returns: matching code chunks with name, type, file path, line numbers, " + "and content previews. Use for finding implementations by keyword.",
6805
+ schema: argsSchema16,
6806
+ handler: async (args, _extra) => {
6807
+ return withErrorHandling("search symbols", async () => {
6808
+ const result = await pkgseerService.searchSymbols(toGraphQLRegistry2(args.registry), args.package_name, args.query, {
6809
+ kind: toSymbolKind(args.kind),
6810
+ version: args.version,
6811
+ limit: args.limit,
6812
+ mode: toNavigationMode(args.mode),
6813
+ waitTimeoutMs: args.wait_timeout_ms
6814
+ });
6815
+ const graphqlError = handleGraphQLErrors(result.errors);
6816
+ if (graphqlError)
6817
+ return graphqlError;
6818
+ if (!result.data.searchSymbols) {
6819
+ return notFoundError(args.package_name, args.registry);
6820
+ }
6821
+ return textResult(JSON.stringify(result.data.searchSymbols, null, 2));
6822
+ });
6823
+ }
6824
+ };
6825
+ }
6826
+ // src/tools/symbol-callees.ts
6827
+ import { z as z15 } from "zod";
6828
+ var argsSchema17 = {
6829
+ symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide either symbol_id or registry + package_name + symbol_name."),
6830
+ max_depth: z15.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
6831
+ limit: z15.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
6832
+ include_external: z15.boolean().optional().describe("Include calls to symbols in other packages"),
6833
+ include_builtins: z15.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
6834
+ mode: schemas.navigationMode,
6835
+ wait_timeout_ms: schemas.waitTimeoutMs
6836
+ };
6837
+ function createSymbolCalleesTool(pkgseerService) {
6838
+ return {
6839
+ name: "symbol_callees",
6840
+ description: "Find what a symbol calls (its dependencies). " + "Returns direct callees at max_depth=1, or transitive call chains at higher depths. " + "Includes: callee names, qualified paths, file locations, call lines, " + "and external package references. Use to understand a function's dependency footprint.",
6841
+ schema: argsSchema17,
6842
+ handler: async (args, _extra) => {
6843
+ return withErrorHandling("find symbol callees", async () => {
6844
+ const symbolInput = toSymbolReferenceInput(args.symbol);
6845
+ if (!symbolInput.symbolId && (!symbolInput.symbolName || !symbolInput.registry || !symbolInput.packageName)) {
6846
+ return errorResult("Provide either symbol_id or symbol_name with registry and package_name to identify the symbol.");
6847
+ }
6848
+ const result = await pkgseerService.symbolDependencies(symbolInput, {
6849
+ maxDepth: args.max_depth,
6850
+ maxResults: args.limit,
6851
+ includeExternal: args.include_external,
6852
+ includeBuiltins: args.include_builtins,
6853
+ mode: toNavigationMode(args.mode),
6854
+ waitTimeoutMs: args.wait_timeout_ms
6855
+ });
6856
+ const graphqlError = handleGraphQLErrors(result.errors);
6857
+ if (graphqlError)
6858
+ return graphqlError;
6859
+ if (!result.data.symbolDependencies) {
6860
+ return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
6861
+ }
6862
+ return textResult(JSON.stringify(result.data.symbolDependencies, null, 2));
6863
+ });
6864
+ }
6865
+ };
6866
+ }
6867
+ // src/tools/symbol-callers.ts
6868
+ import { z as z16 } from "zod";
6869
+ var argsSchema18 = {
6870
+ symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide either symbol_id or registry + package_name + symbol_name."),
6871
+ same_package_only: z16.boolean().optional().describe("Only return callers from the same package"),
6872
+ limit: z16.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
6873
+ mode: schemas.navigationMode,
6874
+ wait_timeout_ms: schemas.waitTimeoutMs
6875
+ };
6876
+ function createSymbolCallersTool(pkgseerService) {
6877
+ return {
6878
+ name: "symbol_callers",
6879
+ description: "Find what calls a symbol (its dependents/callers). " + "Returns: the target symbol and a list of symbols that call it, " + "with their file locations and call line numbers. " + "Use same_package_only to limit to callers within the same package.",
6880
+ schema: argsSchema18,
6881
+ handler: async (args, _extra) => {
6882
+ return withErrorHandling("find symbol callers", async () => {
6883
+ const symbolInput = toSymbolReferenceInput(args.symbol);
6884
+ if (!symbolInput.symbolId && (!symbolInput.symbolName || !symbolInput.registry || !symbolInput.packageName)) {
6885
+ return errorResult("Provide either symbol_id or symbol_name with registry and package_name to identify the symbol.");
6886
+ }
6887
+ const result = await pkgseerService.symbolDependents(symbolInput, {
6888
+ samePackageOnly: args.same_package_only,
6889
+ maxResults: args.limit,
6890
+ mode: toNavigationMode(args.mode),
6891
+ waitTimeoutMs: args.wait_timeout_ms
6892
+ });
6893
+ const graphqlError = handleGraphQLErrors(result.errors);
6894
+ if (graphqlError)
6895
+ return graphqlError;
6896
+ if (!result.data.symbolDependents) {
6897
+ return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
6898
+ }
6899
+ return textResult(JSON.stringify(result.data.symbolDependents, null, 2));
6900
+ });
6901
+ }
6902
+ };
6903
+ }
6904
+ // src/tools/trigger-indexing.ts
6905
+ import { z as z17 } from "zod";
6906
+ var packageInputSchema3 = z17.object({
6907
+ registry: schemas.registry,
6908
+ name: z17.string().max(255).describe("Package name"),
6909
+ version: z17.string().max(100).optional().describe("Specific version to index")
6910
+ });
6911
+ var repositoryInputSchema = z17.object({
6912
+ url: z17.string().max(2000).describe("GitHub repository URL"),
6913
+ ref: z17.string().max(200).optional().describe("Git ref to index (tag, branch, commit). Defaults to HEAD"),
6914
+ discover_packages: z17.boolean().optional().describe("If true, discover packages published from this repo and trigger their metadata fetch")
6915
+ });
6916
+ var argsSchema19 = {
6917
+ packages: z17.array(packageInputSchema3).max(100).optional().describe("Package versions to index (max 100)"),
6918
+ repositories: z17.array(repositoryInputSchema).max(50).optional().describe("Repository URLs to index (max 50)")
6919
+ };
6920
+ function createTriggerIndexingTool(pkgseerService) {
6921
+ return {
6922
+ name: "trigger_indexing",
6923
+ description: "Pre-warm PkgSeer indexes by triggering indexing for packages and/or repositories. " + "Fire-and-forget: triggers jobs and returns immediately with accepted/skipped counts. " + "Use before search requests to ensure packages are indexed. " + "Rate limited to 10 requests per minute.",
6924
+ schema: argsSchema19,
6925
+ handler: async (args, _extra) => {
6926
+ return withErrorHandling("trigger indexing", async () => {
6927
+ const packages = args.packages?.map((p) => ({
6928
+ registry: toGraphQLRegistry2(p.registry),
6929
+ name: p.name,
6930
+ version: p.version
6931
+ }));
6932
+ const repositories = args.repositories?.map((r) => ({
6933
+ url: r.url,
6934
+ ref: r.ref,
6935
+ discoverPackages: r.discover_packages
6936
+ }));
6937
+ const result = await pkgseerService.triggerIndexing({
6938
+ packages,
6939
+ repositories
6940
+ });
6941
+ const graphqlError = handleGraphQLErrors(result.errors);
6942
+ if (graphqlError)
6943
+ return graphqlError;
6944
+ if (!result.data.triggerIndexing) {
6945
+ return {
6946
+ content: [
6947
+ {
6948
+ type: "text",
6949
+ text: "Indexing request failed. Check authentication and input."
6950
+ }
6951
+ ],
6952
+ isError: true
6953
+ };
6954
+ }
6955
+ return textResult(JSON.stringify(result.data.triggerIndexing, null, 2));
6956
+ });
6957
+ }
6958
+ };
6959
+ }
5222
6960
  // src/commands/mcp.ts
5223
6961
  var TOOL_FACTORIES = {
5224
6962
  package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
@@ -5229,12 +6967,21 @@ var TOOL_FACTORIES = {
5229
6967
  list_package_docs: ({ pkgseerService }) => createListPackageDocsTool(pkgseerService),
5230
6968
  fetch_package_doc: ({ pkgseerService }) => createFetchPackageDocTool(pkgseerService),
5231
6969
  search: ({ pkgseerService }) => createSearchTool(pkgseerService),
6970
+ search_status: ({ pkgseerService }) => createSearchStatusTool(pkgseerService),
5232
6971
  fetch_code_context: ({ pkgseerService }) => createFetchCodeContextTool(pkgseerService),
5233
6972
  search_project_docs: ({ pkgseerService, configService, defaultProjectDir }) => createSearchProjectDocsTool({
5234
6973
  pkgseerService,
5235
6974
  configService,
5236
6975
  defaultProjectDir
5237
- })
6976
+ }),
6977
+ find_symbol: ({ pkgseerService }) => createFindSymbolTool(pkgseerService),
6978
+ search_symbols: ({ pkgseerService }) => createSearchSymbolsTool(pkgseerService),
6979
+ list_symbols: ({ pkgseerService }) => createListSymbolsTool(pkgseerService),
6980
+ symbol_callers: ({ pkgseerService }) => createSymbolCallersTool(pkgseerService),
6981
+ symbol_callees: ({ pkgseerService }) => createSymbolCalleesTool(pkgseerService),
6982
+ package_imports: ({ pkgseerService }) => createPackageImportsTool(pkgseerService),
6983
+ call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
6984
+ trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService)
5238
6985
  };
5239
6986
  var PUBLIC_READ_TOOLS = [
5240
6987
  "package_summary",
@@ -5245,7 +6992,16 @@ var PUBLIC_READ_TOOLS = [
5245
6992
  "list_package_docs",
5246
6993
  "fetch_package_doc",
5247
6994
  "search",
5248
- "fetch_code_context"
6995
+ "search_status",
6996
+ "fetch_code_context",
6997
+ "find_symbol",
6998
+ "search_symbols",
6999
+ "list_symbols",
7000
+ "symbol_callers",
7001
+ "symbol_callees",
7002
+ "package_imports",
7003
+ "call_path",
7004
+ "trigger_indexing"
5249
7005
  ];
5250
7006
  var PROJECT_READ_TOOLS = ["search_project_docs"];
5251
7007
  var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
@@ -6245,6 +8001,18 @@ Documentation commands:
6245
8001
  pkgseer docs get <pkg> <page> Fetch a doc page
6246
8002
  pkgseer docs search <query> Search docs only
6247
8003
 
8004
+ Code navigation commands:
8005
+ pkgseer code find <pkg> [name] Find symbols by name
8006
+ pkgseer code search <pkg> <q> Search in package code
8007
+ pkgseer code list <package> Browse package symbols
8008
+ pkgseer code callers <symbol> Find what calls a symbol
8009
+ pkgseer code callees <symbol> Find what a symbol calls
8010
+ pkgseer code imports <package> List package imports
8011
+ pkgseer code path <from> <to> Find call path between symbols
8012
+
8013
+ Indexing:
8014
+ pkgseer index <packages...> Trigger pre-indexing
8015
+
6248
8016
  Learn more at https://pkgseer.dev`);
6249
8017
  registerInitCommand(program);
6250
8018
  registerMcpCommand(program);
@@ -6266,6 +8034,15 @@ var docs = program.command("docs").description("Package documentation commands")
6266
8034
  registerDocsListCommand(docs);
6267
8035
  registerDocsGetCommand(docs);
6268
8036
  registerDocsSearchCommand(docs);
8037
+ var code = program.command("code").description("Code navigation commands");
8038
+ registerCodeFindCommand(code);
8039
+ registerCodeSearchCommand(code);
8040
+ registerCodeListCommand(code);
8041
+ registerCodeCallersCommand(code);
8042
+ registerCodeCalleesCommand(code);
8043
+ registerCodeImportsCommand(code);
8044
+ registerCodePathCommand(code);
8045
+ registerIndexCommand(program);
6269
8046
  var project = program.command("project").description("Project management commands");
6270
8047
  registerProjectInitCommand(project);
6271
8048
  registerProjectDetectCommand(project);