@pkgseer/cli 0.3.1 → 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 +1614 -139
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-55x4vqp2.js → chunk-c1e7ntb6.js} +1 -1
- package/package.json +1 -1
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-
|
|
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
|
|
@@ -262,13 +265,16 @@ var CombinedSearchDocument = gql`
|
|
|
262
265
|
}
|
|
263
266
|
`;
|
|
264
267
|
var SearchProgressDocument = gql`
|
|
265
|
-
query SearchProgress($searchRef: String
|
|
266
|
-
searchProgress(searchRef: $searchRef) {
|
|
268
|
+
query SearchProgress($searchRef: String!, $includeResults: Boolean) {
|
|
269
|
+
searchProgress(searchRef: $searchRef, includeResults: $includeResults) {
|
|
267
270
|
searchRef
|
|
268
271
|
status
|
|
269
272
|
packagesTotal
|
|
270
273
|
packagesReady
|
|
271
274
|
elapsedMs
|
|
275
|
+
query
|
|
276
|
+
mode
|
|
277
|
+
expiresAt
|
|
272
278
|
}
|
|
273
279
|
}
|
|
274
280
|
`;
|
|
@@ -287,6 +293,7 @@ var SearchResultsDocument = gql`
|
|
|
287
293
|
registry
|
|
288
294
|
score
|
|
289
295
|
snippet
|
|
296
|
+
matchLine
|
|
290
297
|
filePath
|
|
291
298
|
startLine
|
|
292
299
|
endLine
|
|
@@ -343,6 +350,14 @@ var CliDocsGetDocument = gql`
|
|
|
343
350
|
}
|
|
344
351
|
}
|
|
345
352
|
`;
|
|
353
|
+
var TriggerIndexingDocument = gql`
|
|
354
|
+
mutation TriggerIndexing($input: TriggerIndexingInput!) {
|
|
355
|
+
triggerIndexing(input: $input) {
|
|
356
|
+
accepted
|
|
357
|
+
skipped
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
`;
|
|
346
361
|
var CreateProjectDocument = gql`
|
|
347
362
|
mutation CreateProject($input: CreateProjectInput!) {
|
|
348
363
|
createProject(input: $input) {
|
|
@@ -372,6 +387,7 @@ var PackageSummaryDocument = gql`
|
|
|
372
387
|
repositoryUrl
|
|
373
388
|
license
|
|
374
389
|
downloadsLastMonth
|
|
390
|
+
downloadsTotal
|
|
375
391
|
downloadsRefreshedAt
|
|
376
392
|
}
|
|
377
393
|
security {
|
|
@@ -514,6 +530,7 @@ var ComparePackagesDocument = gql`
|
|
|
514
530
|
latestVersion
|
|
515
531
|
license
|
|
516
532
|
downloadsLastMonth
|
|
533
|
+
downloadsTotal
|
|
517
534
|
vulnerabilityCount
|
|
518
535
|
quality {
|
|
519
536
|
score
|
|
@@ -637,6 +654,237 @@ var SearchPackageDocsDocument = gql`
|
|
|
637
654
|
}
|
|
638
655
|
}
|
|
639
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
|
+
`;
|
|
640
888
|
var SearchProjectDocsDocument = gql`
|
|
641
889
|
query SearchProjectDocs($project: String!, $keywords: [String!], $matchMode: MatchMode, $includeSnippets: Boolean, $limit: Int) {
|
|
642
890
|
searchProjectDocs(
|
|
@@ -679,6 +927,7 @@ var SearchProgressDocumentString = print(SearchProgressDocument);
|
|
|
679
927
|
var SearchResultsDocumentString = print(SearchResultsDocument);
|
|
680
928
|
var FetchCodeContextDocumentString = print(FetchCodeContextDocument);
|
|
681
929
|
var CliDocsGetDocumentString = print(CliDocsGetDocument);
|
|
930
|
+
var TriggerIndexingDocumentString = print(TriggerIndexingDocument);
|
|
682
931
|
var CreateProjectDocumentString = print(CreateProjectDocument);
|
|
683
932
|
var PackageSummaryDocumentString = print(PackageSummaryDocument);
|
|
684
933
|
var PackageVulnerabilitiesDocumentString = print(PackageVulnerabilitiesDocument);
|
|
@@ -689,6 +938,13 @@ var ListPackageDocsDocumentString = print(ListPackageDocsDocument);
|
|
|
689
938
|
var FetchPackageDocDocumentString = print(FetchPackageDocDocument);
|
|
690
939
|
var GetDocPageDocumentString = print(GetDocPageDocument);
|
|
691
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);
|
|
692
948
|
var SearchProjectDocsDocumentString = print(SearchProjectDocsDocument);
|
|
693
949
|
function getSdk(client, withWrapper = defaultWrapper) {
|
|
694
950
|
return {
|
|
@@ -731,6 +987,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
731
987
|
CliDocsGet(variables, requestHeaders) {
|
|
732
988
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(CliDocsGetDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CliDocsGet", "query", variables);
|
|
733
989
|
},
|
|
990
|
+
TriggerIndexing(variables, requestHeaders) {
|
|
991
|
+
return withWrapper((wrappedRequestHeaders) => client.rawRequest(TriggerIndexingDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "TriggerIndexing", "mutation", variables);
|
|
992
|
+
},
|
|
734
993
|
CreateProject(variables, requestHeaders) {
|
|
735
994
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(CreateProjectDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
|
|
736
995
|
},
|
|
@@ -761,6 +1020,27 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
761
1020
|
SearchPackageDocs(variables, requestHeaders) {
|
|
762
1021
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchPackageDocsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchPackageDocs", "query", variables);
|
|
763
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
|
+
},
|
|
764
1044
|
SearchProjectDocs(variables, requestHeaders) {
|
|
765
1045
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchProjectDocsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchProjectDocs", "query", variables);
|
|
766
1046
|
}
|
|
@@ -1093,7 +1373,15 @@ var TOOL_NAMES = [
|
|
|
1093
1373
|
"search",
|
|
1094
1374
|
"search_status",
|
|
1095
1375
|
"fetch_code_context",
|
|
1096
|
-
"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"
|
|
1097
1385
|
];
|
|
1098
1386
|
var ToolNameSchema = z.enum(TOOL_NAMES);
|
|
1099
1387
|
var SharedConfigFields = {
|
|
@@ -1495,8 +1783,11 @@ class PkgseerServiceImpl {
|
|
|
1495
1783
|
});
|
|
1496
1784
|
return { data: result.data, errors: result.errors };
|
|
1497
1785
|
}
|
|
1498
|
-
async getSearchProgress(searchRef) {
|
|
1499
|
-
const result = await this.client.SearchProgress({
|
|
1786
|
+
async getSearchProgress(searchRef, options) {
|
|
1787
|
+
const result = await this.client.SearchProgress({
|
|
1788
|
+
searchRef,
|
|
1789
|
+
includeResults: options?.includeResults
|
|
1790
|
+
});
|
|
1500
1791
|
return { data: result.data, errors: result.errors };
|
|
1501
1792
|
}
|
|
1502
1793
|
async getSearchResults(searchRef) {
|
|
@@ -1513,6 +1804,100 @@ class PkgseerServiceImpl {
|
|
|
1513
1804
|
});
|
|
1514
1805
|
return { data: result.data, errors: result.errors };
|
|
1515
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
|
+
}
|
|
1516
1901
|
}
|
|
1517
1902
|
// src/services/project-service.ts
|
|
1518
1903
|
var PROJECT_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
@@ -1810,58 +2195,6 @@ function registerAuthStatusCommand(program) {
|
|
|
1810
2195
|
});
|
|
1811
2196
|
}
|
|
1812
2197
|
|
|
1813
|
-
// src/commands/config-show.ts
|
|
1814
|
-
async function configShowAction(deps) {
|
|
1815
|
-
const { configService } = deps;
|
|
1816
|
-
const { config, globalPath, projectPath } = await configService.loadMergedConfig();
|
|
1817
|
-
if (!globalPath && !projectPath) {
|
|
1818
|
-
console.log(`No configuration found.
|
|
1819
|
-
`);
|
|
1820
|
-
console.log(" Global config: ~/.pkgseer/config.yml");
|
|
1821
|
-
console.log(` Project config: pkgseer.yml
|
|
1822
|
-
`);
|
|
1823
|
-
console.log("Create a config file to customize pkgseer behavior.");
|
|
1824
|
-
return;
|
|
1825
|
-
}
|
|
1826
|
-
console.log(`Configuration sources:
|
|
1827
|
-
`);
|
|
1828
|
-
if (globalPath) {
|
|
1829
|
-
console.log(` Global: ${globalPath}`);
|
|
1830
|
-
}
|
|
1831
|
-
if (projectPath) {
|
|
1832
|
-
console.log(` Project: ${projectPath}`);
|
|
1833
|
-
}
|
|
1834
|
-
console.log(`
|
|
1835
|
-
Merged configuration:
|
|
1836
|
-
`);
|
|
1837
|
-
if (config.enabled_tools !== undefined) {
|
|
1838
|
-
if (config.enabled_tools.length > 0) {
|
|
1839
|
-
console.log(" enabled_tools:");
|
|
1840
|
-
for (const tool of config.enabled_tools) {
|
|
1841
|
-
console.log(` - ${tool}`);
|
|
1842
|
-
}
|
|
1843
|
-
} else {
|
|
1844
|
-
console.log(" enabled_tools: [] (no tools enabled)");
|
|
1845
|
-
}
|
|
1846
|
-
} else {
|
|
1847
|
-
console.log(" enabled_tools: (all tools enabled by default)");
|
|
1848
|
-
}
|
|
1849
|
-
if (config.project) {
|
|
1850
|
-
console.log(` project: ${config.project}`);
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
var SHOW_DESCRIPTION = `Display current configuration.
|
|
1854
|
-
|
|
1855
|
-
Shows the merged configuration from global (~/.pkgseer/config.yml) and
|
|
1856
|
-
project (pkgseer.yml) config files. Project config takes precedence
|
|
1857
|
-
over global config for overlapping settings.`;
|
|
1858
|
-
function registerConfigShowCommand(program) {
|
|
1859
|
-
program.command("show").summary("Display current configuration").description(SHOW_DESCRIPTION).action(async () => {
|
|
1860
|
-
const deps = await createContainer();
|
|
1861
|
-
await configShowAction(deps);
|
|
1862
|
-
});
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
2198
|
// src/commands/shared.ts
|
|
1866
2199
|
function parsePackageSpec(spec) {
|
|
1867
2200
|
let registry = "npm";
|
|
@@ -1869,7 +2202,16 @@ function parsePackageSpec(spec) {
|
|
|
1869
2202
|
if (spec.includes(":")) {
|
|
1870
2203
|
const colonIndex = spec.indexOf(":");
|
|
1871
2204
|
const potentialRegistry = spec.slice(0, colonIndex).toLowerCase();
|
|
1872
|
-
if ([
|
|
2205
|
+
if ([
|
|
2206
|
+
"npm",
|
|
2207
|
+
"pypi",
|
|
2208
|
+
"hex",
|
|
2209
|
+
"crates",
|
|
2210
|
+
"nuget",
|
|
2211
|
+
"maven",
|
|
2212
|
+
"zig",
|
|
2213
|
+
"vcpkg"
|
|
2214
|
+
].includes(potentialRegistry)) {
|
|
1873
2215
|
registry = potentialRegistry;
|
|
1874
2216
|
rest = spec.slice(colonIndex + 1);
|
|
1875
2217
|
}
|
|
@@ -1889,7 +2231,11 @@ function toGraphQLRegistry(registry) {
|
|
|
1889
2231
|
npm: "NPM",
|
|
1890
2232
|
pypi: "PYPI",
|
|
1891
2233
|
hex: "HEX",
|
|
1892
|
-
crates: "CRATES"
|
|
2234
|
+
crates: "CRATES",
|
|
2235
|
+
nuget: "NUGET",
|
|
2236
|
+
maven: "MAVEN",
|
|
2237
|
+
zig: "ZIG",
|
|
2238
|
+
vcpkg: "VCPKG"
|
|
1893
2239
|
};
|
|
1894
2240
|
return map[registry.toLowerCase()] || "NPM";
|
|
1895
2241
|
}
|
|
@@ -1935,6 +2281,11 @@ function formatNumber(num) {
|
|
|
1935
2281
|
return "N/A";
|
|
1936
2282
|
return num.toLocaleString();
|
|
1937
2283
|
}
|
|
2284
|
+
function truncate(text, maxLength) {
|
|
2285
|
+
if (text.length <= maxLength)
|
|
2286
|
+
return text;
|
|
2287
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
2288
|
+
}
|
|
1938
2289
|
function keyValueTable(pairs) {
|
|
1939
2290
|
const maxKeyLen = Math.max(...pairs.map(([k]) => k.length));
|
|
1940
2291
|
return pairs.map(([key, value]) => ` ${key.padEnd(maxKeyLen)} ${value ?? "N/A"}`).join(`
|
|
@@ -2019,18 +2370,624 @@ async function withCliErrorHandling(json, fn) {
|
|
|
2019
2370
|
outputError(`${message}. Hint: wait and retry.`, json);
|
|
2020
2371
|
return;
|
|
2021
2372
|
}
|
|
2022
|
-
const colonMatch = message.match(/^([^:]+):/);
|
|
2023
|
-
const shortMessage = colonMatch?.[1] ?? message;
|
|
2024
|
-
outputError(shortMessage, json);
|
|
2373
|
+
const colonMatch = message.match(/^([^:]+):/);
|
|
2374
|
+
const shortMessage = colonMatch?.[1] ?? message;
|
|
2375
|
+
outputError(shortMessage, json);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
function formatScore(score) {
|
|
2379
|
+
if (score == null)
|
|
2380
|
+
return "N/A";
|
|
2381
|
+
const percentage = score > 1 ? Math.round(score) : Math.round(score * 100);
|
|
2382
|
+
const filled = Math.round(percentage / 5);
|
|
2383
|
+
const bar = "█".repeat(Math.min(filled, 20)) + "░".repeat(Math.max(20 - filled, 0));
|
|
2384
|
+
return `${bar} ${percentage}%`;
|
|
2385
|
+
}
|
|
2386
|
+
|
|
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);
|
|
2394
|
+
return {
|
|
2395
|
+
registry: toGraphQLRegistry(parsed2.registry),
|
|
2396
|
+
packageName: parsed2.name,
|
|
2397
|
+
symbolName: symbolName || undefined
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
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) };
|
|
2409
|
+
}
|
|
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}`);
|
|
2025
2979
|
}
|
|
2026
2980
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
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
|
+
});
|
|
2034
2991
|
}
|
|
2035
2992
|
|
|
2036
2993
|
// src/commands/docs/get.ts
|
|
@@ -2401,7 +3358,7 @@ async function docsListAction(packageArg, options, deps) {
|
|
|
2401
3358
|
console.log(formatDocsList(result.data.listPackageDocs));
|
|
2402
3359
|
}
|
|
2403
3360
|
}
|
|
2404
|
-
var
|
|
3361
|
+
var LIST_DESCRIPTION2 = `List available documentation pages for a package.
|
|
2405
3362
|
|
|
2406
3363
|
Shows all documentation pages with titles, globally unique page IDs,
|
|
2407
3364
|
word counts, and descriptions. Use the page ID with 'docs get'
|
|
@@ -2414,7 +3371,7 @@ Examples:
|
|
|
2414
3371
|
pkgseer docs list pypi:requests
|
|
2415
3372
|
pkgseer docs list hex:phoenix@1.7.0 --json`;
|
|
2416
3373
|
function registerDocsListCommand(program) {
|
|
2417
|
-
program.command("list <package>").summary("List documentation pages").description(
|
|
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) => {
|
|
2418
3375
|
await withCliErrorHandling(options.json ?? false, async () => {
|
|
2419
3376
|
const deps = await createContainer();
|
|
2420
3377
|
await docsListAction(packageName, options, deps);
|
|
@@ -2689,7 +3646,7 @@ function abbrevLang(lang) {
|
|
|
2689
3646
|
const lower = lang.toLowerCase();
|
|
2690
3647
|
return LANG_ABBREV[lower] ?? lower;
|
|
2691
3648
|
}
|
|
2692
|
-
function
|
|
3649
|
+
function truncate2(text, maxLen) {
|
|
2693
3650
|
if (text.length <= maxLen)
|
|
2694
3651
|
return text;
|
|
2695
3652
|
return `${text.slice(0, maxLen - 3)}...`;
|
|
@@ -2743,9 +3700,9 @@ function formatEntryCompact(entry, useColors) {
|
|
|
2743
3700
|
if (entry.snippet) {
|
|
2744
3701
|
const bestLine = findBestSnippetLine(entry.snippet);
|
|
2745
3702
|
if (bestLine) {
|
|
2746
|
-
snippet = ` ${
|
|
3703
|
+
snippet = ` ${truncate2(bestLine, 80)}`;
|
|
2747
3704
|
if (useColors) {
|
|
2748
|
-
snippet = ` ${colors.dim}${
|
|
3705
|
+
snippet = ` ${colors.dim}${truncate2(bestLine, 80)}${colors.reset}`;
|
|
2749
3706
|
}
|
|
2750
3707
|
}
|
|
2751
3708
|
}
|
|
@@ -3071,7 +4028,7 @@ function outputResults(results, options, useColors) {
|
|
|
3071
4028
|
console.log(formatSearchResultsCompact(results, useColors));
|
|
3072
4029
|
}
|
|
3073
4030
|
}
|
|
3074
|
-
var
|
|
4031
|
+
var SEARCH_DESCRIPTION2 = `Search code and documentation across packages.
|
|
3075
4032
|
|
|
3076
4033
|
Searches both code (functions, classes) and documentation pages
|
|
3077
4034
|
using the combined search endpoint. Returns results with snippets
|
|
@@ -3107,7 +4064,7 @@ function addSearchOptions(cmd) {
|
|
|
3107
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");
|
|
3108
4065
|
}
|
|
3109
4066
|
function registerSearchCommand(program) {
|
|
3110
|
-
const cmd = program.command("search [query...]").summary("Search code and documentation across packages").description(
|
|
4067
|
+
const cmd = program.command("search [query...]").summary("Search code and documentation across packages").description(SEARCH_DESCRIPTION2);
|
|
3111
4068
|
addSearchOptions(cmd).action(async (query, options) => {
|
|
3112
4069
|
await withCliErrorHandling(options.json ?? false, async () => {
|
|
3113
4070
|
const deps = await createContainer();
|
|
@@ -3156,6 +4113,70 @@ function registerDocsSearchCommand(program) {
|
|
|
3156
4113
|
});
|
|
3157
4114
|
});
|
|
3158
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
|
+
|
|
3159
4180
|
// src/commands/shared-colors.ts
|
|
3160
4181
|
var colors2 = {
|
|
3161
4182
|
reset: "\x1B[0m",
|
|
@@ -4927,7 +5948,7 @@ function registerLogoutCommand(program) {
|
|
|
4927
5948
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4928
5949
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4929
5950
|
|
|
4930
|
-
// src/tools/
|
|
5951
|
+
// src/tools/call-path.ts
|
|
4931
5952
|
import { z as z3 } from "zod";
|
|
4932
5953
|
|
|
4933
5954
|
// src/tools/shared.ts
|
|
@@ -4952,15 +5973,68 @@ function toGraphQLRegistry2(registry) {
|
|
|
4952
5973
|
npm: "NPM",
|
|
4953
5974
|
pypi: "PYPI",
|
|
4954
5975
|
hex: "HEX",
|
|
4955
|
-
crates: "CRATES"
|
|
5976
|
+
crates: "CRATES",
|
|
5977
|
+
nuget: "NUGET",
|
|
5978
|
+
maven: "MAVEN",
|
|
5979
|
+
zig: "ZIG",
|
|
5980
|
+
vcpkg: "VCPKG"
|
|
4956
5981
|
};
|
|
4957
5982
|
return map[registry.toLowerCase()] || "NPM";
|
|
4958
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
|
+
}
|
|
4959
6017
|
var schemas = {
|
|
4960
|
-
registry: z2.enum(["npm", "pypi", "hex", "crates"]).describe("Package registry (npm, pypi, hex, or
|
|
6018
|
+
registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).describe("Package registry (npm, pypi, hex, crates, nuget, maven, zig, or vcpkg)"),
|
|
4961
6019
|
packageName: z2.string().max(255).describe("Name of the package"),
|
|
4962
|
-
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
|
+
})
|
|
4963
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
|
+
}
|
|
4964
6038
|
function buildHintedMessage(operation, message) {
|
|
4965
6039
|
const lower = message.toLowerCase();
|
|
4966
6040
|
const isTimeout = lower.includes("-32001") || lower.includes("timeout") || lower.includes("timed out");
|
|
@@ -4998,20 +6072,60 @@ function notFoundError(packageName, registry) {
|
|
|
4998
6072
|
return errorResult(`Package not found: ${packageName} in ${registry}`);
|
|
4999
6073
|
}
|
|
5000
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
|
+
}
|
|
5001
6114
|
// src/tools/compare-packages.ts
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
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()
|
|
5006
6120
|
});
|
|
5007
|
-
var
|
|
5008
|
-
packages:
|
|
6121
|
+
var argsSchema2 = {
|
|
6122
|
+
packages: z4.array(packageInputSchema).min(2).max(10).describe("List of packages to compare (2-10 packages)")
|
|
5009
6123
|
};
|
|
5010
6124
|
function createComparePackagesTool(pkgseerService) {
|
|
5011
6125
|
return {
|
|
5012
6126
|
name: "compare_packages",
|
|
5013
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"}]',
|
|
5014
|
-
schema:
|
|
6128
|
+
schema: argsSchema2,
|
|
5015
6129
|
handler: async ({ packages }, _extra) => {
|
|
5016
6130
|
return withErrorHandling("compare packages", async () => {
|
|
5017
6131
|
const input2 = packages.map((pkg) => ({
|
|
@@ -5032,19 +6146,19 @@ function createComparePackagesTool(pkgseerService) {
|
|
|
5032
6146
|
};
|
|
5033
6147
|
}
|
|
5034
6148
|
// src/tools/fetch-code-context.ts
|
|
5035
|
-
import { z as
|
|
5036
|
-
var
|
|
5037
|
-
repo_url:
|
|
5038
|
-
git_ref:
|
|
5039
|
-
file_path:
|
|
5040
|
-
start_line:
|
|
5041
|
-
end_line:
|
|
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.")
|
|
5042
6156
|
};
|
|
5043
6157
|
function createFetchCodeContextTool(pkgseerService) {
|
|
5044
6158
|
return {
|
|
5045
6159
|
name: "fetch_code_context",
|
|
5046
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.",
|
|
5047
|
-
schema:
|
|
6161
|
+
schema: argsSchema3,
|
|
5048
6162
|
handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
|
|
5049
6163
|
return withErrorHandling("fetch code context", async () => {
|
|
5050
6164
|
const result = await pkgseerService.fetchCodeContext(repo_url, git_ref, file_path, {
|
|
@@ -5063,15 +6177,15 @@ function createFetchCodeContextTool(pkgseerService) {
|
|
|
5063
6177
|
};
|
|
5064
6178
|
}
|
|
5065
6179
|
// src/tools/fetch-package-doc.ts
|
|
5066
|
-
import { z as
|
|
5067
|
-
var
|
|
5068
|
-
page_id:
|
|
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)")
|
|
5069
6183
|
};
|
|
5070
6184
|
function createFetchPackageDocTool(pkgseerService) {
|
|
5071
6185
|
return {
|
|
5072
6186
|
name: "fetch_package_doc",
|
|
5073
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.",
|
|
5074
|
-
schema:
|
|
6188
|
+
schema: argsSchema4,
|
|
5075
6189
|
handler: async ({ page_id }, _extra) => {
|
|
5076
6190
|
return withErrorHandling("fetch documentation page", async () => {
|
|
5077
6191
|
const result = await pkgseerService.getDocPage(page_id);
|
|
@@ -5086,8 +6200,60 @@ function createFetchPackageDocTool(pkgseerService) {
|
|
|
5086
6200
|
}
|
|
5087
6201
|
};
|
|
5088
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
|
+
}
|
|
5089
6255
|
// src/tools/list-package-docs.ts
|
|
5090
|
-
var
|
|
6256
|
+
var argsSchema6 = {
|
|
5091
6257
|
registry: schemas.registry,
|
|
5092
6258
|
package_name: schemas.packageName.describe("Name of the package to list documentation for"),
|
|
5093
6259
|
version: schemas.version
|
|
@@ -5096,7 +6262,7 @@ function createListPackageDocsTool(pkgseerService) {
|
|
|
5096
6262
|
return {
|
|
5097
6263
|
name: "list_package_docs",
|
|
5098
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.",
|
|
5099
|
-
schema:
|
|
6265
|
+
schema: argsSchema6,
|
|
5100
6266
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
5101
6267
|
return withErrorHandling("list package documentation", async () => {
|
|
5102
6268
|
const result = await pkgseerService.listPackageDocs(toGraphQLRegistry2(registry), package_name, version2);
|
|
@@ -5111,14 +6277,69 @@ function createListPackageDocsTool(pkgseerService) {
|
|
|
5111
6277
|
}
|
|
5112
6278
|
};
|
|
5113
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
|
+
}
|
|
5114
6335
|
// src/tools/package-dependencies.ts
|
|
5115
|
-
import { z as
|
|
5116
|
-
var
|
|
6336
|
+
import { z as z9 } from "zod";
|
|
6337
|
+
var argsSchema8 = {
|
|
5117
6338
|
registry: schemas.registry,
|
|
5118
6339
|
package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
|
|
5119
6340
|
version: schemas.version,
|
|
5120
|
-
include_transitive:
|
|
5121
|
-
max_depth:
|
|
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)")
|
|
5122
6343
|
};
|
|
5123
6344
|
function decodeDag(rawDag) {
|
|
5124
6345
|
if (!rawDag || typeof rawDag !== "object")
|
|
@@ -5196,7 +6417,7 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
5196
6417
|
return {
|
|
5197
6418
|
name: "package_dependencies",
|
|
5198
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.",
|
|
5199
|
-
schema:
|
|
6420
|
+
schema: argsSchema8,
|
|
5200
6421
|
handler: async ({ registry, package_name, version: version2, include_transitive, max_depth }, _extra) => {
|
|
5201
6422
|
return withErrorHandling("fetch package dependencies", async () => {
|
|
5202
6423
|
const result = await pkgseerService.getPackageDependencies(toGraphQLRegistry2(registry), package_name, version2, include_transitive, max_depth);
|
|
@@ -5233,8 +6454,46 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
5233
6454
|
}
|
|
5234
6455
|
};
|
|
5235
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
|
+
}
|
|
5236
6495
|
// src/tools/package-quality.ts
|
|
5237
|
-
var
|
|
6496
|
+
var argsSchema10 = {
|
|
5238
6497
|
registry: schemas.registry,
|
|
5239
6498
|
package_name: schemas.packageName.describe("Name of the package to analyze"),
|
|
5240
6499
|
version: schemas.version
|
|
@@ -5243,7 +6502,7 @@ function createPackageQualityTool(pkgseerService) {
|
|
|
5243
6502
|
return {
|
|
5244
6503
|
name: "package_quality",
|
|
5245
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.",
|
|
5246
|
-
schema:
|
|
6505
|
+
schema: argsSchema10,
|
|
5247
6506
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
5248
6507
|
return withErrorHandling("fetch package quality", async () => {
|
|
5249
6508
|
const result = await pkgseerService.getPackageQuality(toGraphQLRegistry2(registry), package_name, version2);
|
|
@@ -5259,7 +6518,7 @@ function createPackageQualityTool(pkgseerService) {
|
|
|
5259
6518
|
};
|
|
5260
6519
|
}
|
|
5261
6520
|
// src/tools/package-summary.ts
|
|
5262
|
-
var
|
|
6521
|
+
var argsSchema11 = {
|
|
5263
6522
|
registry: schemas.registry,
|
|
5264
6523
|
package_name: schemas.packageName.describe("Name of the package to retrieve summary for")
|
|
5265
6524
|
};
|
|
@@ -5267,7 +6526,7 @@ function createPackageSummaryTool(pkgseerService) {
|
|
|
5267
6526
|
return {
|
|
5268
6527
|
name: "package_summary",
|
|
5269
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).",
|
|
5270
|
-
schema:
|
|
6529
|
+
schema: argsSchema11,
|
|
5271
6530
|
handler: async ({ registry, package_name }, _extra) => {
|
|
5272
6531
|
return withErrorHandling("fetch package summary", async () => {
|
|
5273
6532
|
const result = await pkgseerService.getPackageSummary(toGraphQLRegistry2(registry), package_name);
|
|
@@ -5283,7 +6542,7 @@ function createPackageSummaryTool(pkgseerService) {
|
|
|
5283
6542
|
};
|
|
5284
6543
|
}
|
|
5285
6544
|
// src/tools/package-vulnerabilities.ts
|
|
5286
|
-
var
|
|
6545
|
+
var argsSchema12 = {
|
|
5287
6546
|
registry: schemas.registry,
|
|
5288
6547
|
package_name: schemas.packageName.describe("Name of the package to inspect for vulnerabilities"),
|
|
5289
6548
|
version: schemas.version
|
|
@@ -5292,7 +6551,7 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
|
5292
6551
|
return {
|
|
5293
6552
|
name: "package_vulnerabilities",
|
|
5294
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.",
|
|
5295
|
-
schema:
|
|
6554
|
+
schema: argsSchema12,
|
|
5296
6555
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
5297
6556
|
return withErrorHandling("fetch package vulnerabilities", async () => {
|
|
5298
6557
|
const result = await pkgseerService.getPackageVulnerabilities(toGraphQLRegistry2(registry), package_name, version2);
|
|
@@ -5308,19 +6567,19 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
|
5308
6567
|
};
|
|
5309
6568
|
}
|
|
5310
6569
|
// src/tools/search.ts
|
|
5311
|
-
import { z as
|
|
5312
|
-
var packageInputSchema2 =
|
|
6570
|
+
import { z as z11 } from "zod";
|
|
6571
|
+
var packageInputSchema2 = z11.object({
|
|
5313
6572
|
registry: schemas.registry,
|
|
5314
|
-
name:
|
|
5315
|
-
version:
|
|
6573
|
+
name: z11.string().min(1).describe("Package name"),
|
|
6574
|
+
version: z11.string().optional().describe("Specific version (defaults to latest)")
|
|
5316
6575
|
});
|
|
5317
6576
|
var DEFAULT_AGENT_WAIT_TIMEOUT_MS = 1e4;
|
|
5318
|
-
var
|
|
5319
|
-
packages:
|
|
5320
|
-
query:
|
|
5321
|
-
mode:
|
|
5322
|
-
limit:
|
|
5323
|
-
waitTimeoutMs:
|
|
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)")
|
|
5324
6583
|
};
|
|
5325
6584
|
function toSearchMode2(mode) {
|
|
5326
6585
|
if (!mode)
|
|
@@ -5359,7 +6618,7 @@ function createSearchTool(pkgseerService) {
|
|
|
5359
6618
|
return {
|
|
5360
6619
|
name: "search",
|
|
5361
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.",
|
|
5362
|
-
schema:
|
|
6621
|
+
schema: argsSchema13,
|
|
5363
6622
|
handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
|
|
5364
6623
|
return withErrorHandling("search packages", async () => {
|
|
5365
6624
|
const normalizedQuery = query.trim();
|
|
@@ -5411,21 +6670,21 @@ function createSearchTool(pkgseerService) {
|
|
|
5411
6670
|
};
|
|
5412
6671
|
}
|
|
5413
6672
|
// src/tools/search-project-docs.ts
|
|
5414
|
-
import { z as
|
|
5415
|
-
var
|
|
5416
|
-
project_directory:
|
|
5417
|
-
project:
|
|
5418
|
-
terms:
|
|
5419
|
-
match_mode:
|
|
5420
|
-
include_snippets:
|
|
5421
|
-
limit:
|
|
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")
|
|
5422
6681
|
};
|
|
5423
6682
|
function createSearchProjectDocsTool(deps) {
|
|
5424
6683
|
const { pkgseerService, configService, defaultProjectDir } = deps;
|
|
5425
6684
|
return {
|
|
5426
6685
|
name: "search_project_docs",
|
|
5427
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.",
|
|
5428
|
-
schema:
|
|
6687
|
+
schema: argsSchema14,
|
|
5429
6688
|
handler: async ({
|
|
5430
6689
|
project_directory,
|
|
5431
6690
|
project,
|
|
@@ -5471,15 +6730,15 @@ function createSearchProjectDocsTool(deps) {
|
|
|
5471
6730
|
};
|
|
5472
6731
|
}
|
|
5473
6732
|
// src/tools/search-status.ts
|
|
5474
|
-
import { z as
|
|
5475
|
-
var
|
|
5476
|
-
searchRef:
|
|
6733
|
+
import { z as z13 } from "zod";
|
|
6734
|
+
var argsSchema15 = {
|
|
6735
|
+
searchRef: z13.string().min(1).describe("Search reference from a previous incomplete search")
|
|
5477
6736
|
};
|
|
5478
6737
|
function createSearchStatusTool(pkgseerService) {
|
|
5479
6738
|
return {
|
|
5480
6739
|
name: "search_status",
|
|
5481
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.",
|
|
5482
|
-
schema:
|
|
6741
|
+
schema: argsSchema15,
|
|
5483
6742
|
handler: async ({ searchRef }, _extra) => {
|
|
5484
6743
|
return withErrorHandling("check search status", async () => {
|
|
5485
6744
|
const progressResult = await pkgseerService.getSearchProgress(searchRef);
|
|
@@ -5519,6 +6778,185 @@ function createSearchStatusTool(pkgseerService) {
|
|
|
5519
6778
|
}
|
|
5520
6779
|
};
|
|
5521
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
|
+
}
|
|
5522
6960
|
// src/commands/mcp.ts
|
|
5523
6961
|
var TOOL_FACTORIES = {
|
|
5524
6962
|
package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
|
|
@@ -5535,7 +6973,15 @@ var TOOL_FACTORIES = {
|
|
|
5535
6973
|
pkgseerService,
|
|
5536
6974
|
configService,
|
|
5537
6975
|
defaultProjectDir
|
|
5538
|
-
})
|
|
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)
|
|
5539
6985
|
};
|
|
5540
6986
|
var PUBLIC_READ_TOOLS = [
|
|
5541
6987
|
"package_summary",
|
|
@@ -5547,7 +6993,15 @@ var PUBLIC_READ_TOOLS = [
|
|
|
5547
6993
|
"fetch_package_doc",
|
|
5548
6994
|
"search",
|
|
5549
6995
|
"search_status",
|
|
5550
|
-
"fetch_code_context"
|
|
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"
|
|
5551
7005
|
];
|
|
5552
7006
|
var PROJECT_READ_TOOLS = ["search_project_docs"];
|
|
5553
7007
|
var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
|
|
@@ -6547,6 +8001,18 @@ Documentation commands:
|
|
|
6547
8001
|
pkgseer docs get <pkg> <page> Fetch a doc page
|
|
6548
8002
|
pkgseer docs search <query> Search docs only
|
|
6549
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
|
+
|
|
6550
8016
|
Learn more at https://pkgseer.dev`);
|
|
6551
8017
|
registerInitCommand(program);
|
|
6552
8018
|
registerMcpCommand(program);
|
|
@@ -6568,6 +8034,15 @@ var docs = program.command("docs").description("Package documentation commands")
|
|
|
6568
8034
|
registerDocsListCommand(docs);
|
|
6569
8035
|
registerDocsGetCommand(docs);
|
|
6570
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);
|
|
6571
8046
|
var project = program.command("project").description("Project management commands");
|
|
6572
8047
|
registerProjectInitCommand(project);
|
|
6573
8048
|
registerProjectDetectCommand(project);
|