@pkgseer/cli 0.4.11 → 0.5.1
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 +663 -322
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-r3pnzy5b.js → chunk-x6hqsn93.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-x6hqsn93.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -315,13 +315,17 @@ var SearchResultsDocument = gql`
|
|
|
315
315
|
}
|
|
316
316
|
`;
|
|
317
317
|
var FetchCodeContextDocument = gql`
|
|
318
|
-
query FetchCodeContext($repoUrl: String
|
|
318
|
+
query FetchCodeContext($repoUrl: String, $gitRef: String, $registry: Registry, $packageName: String, $version: String, $filePath: String!, $startLine: Int, $endLine: Int, $waitTimeoutMs: Int) {
|
|
319
319
|
fetchCodeContext(
|
|
320
320
|
repoUrl: $repoUrl
|
|
321
321
|
gitRef: $gitRef
|
|
322
|
+
registry: $registry
|
|
323
|
+
packageName: $packageName
|
|
324
|
+
version: $version
|
|
322
325
|
filePath: $filePath
|
|
323
326
|
startLine: $startLine
|
|
324
327
|
endLine: $endLine
|
|
328
|
+
waitTimeoutMs: $waitTimeoutMs
|
|
325
329
|
) {
|
|
326
330
|
content
|
|
327
331
|
filePath
|
|
@@ -331,6 +335,8 @@ var FetchCodeContextDocument = gql`
|
|
|
331
335
|
endLine
|
|
332
336
|
repoUrl
|
|
333
337
|
gitRef
|
|
338
|
+
indexingStatus
|
|
339
|
+
indexingRef
|
|
334
340
|
}
|
|
335
341
|
}
|
|
336
342
|
`;
|
|
@@ -359,6 +365,16 @@ var TriggerIndexingDocument = gql`
|
|
|
359
365
|
}
|
|
360
366
|
}
|
|
361
367
|
`;
|
|
368
|
+
var IndexingProgressDocument = gql`
|
|
369
|
+
query IndexingProgress($ref: String!) {
|
|
370
|
+
indexingProgress(ref: $ref) {
|
|
371
|
+
status
|
|
372
|
+
filesIndexed
|
|
373
|
+
chunksCreated
|
|
374
|
+
elapsedMs
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
`;
|
|
362
378
|
var CreateProjectDocument = gql`
|
|
363
379
|
mutation CreateProject($input: CreateProjectInput!) {
|
|
364
380
|
createProject(input: $input) {
|
|
@@ -656,10 +672,12 @@ var SearchPackageDocsDocument = gql`
|
|
|
656
672
|
}
|
|
657
673
|
`;
|
|
658
674
|
var FindSymbolDocument = gql`
|
|
659
|
-
query FindSymbol($registry: Registry
|
|
675
|
+
query FindSymbol($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $name: String, $namespace: String, $kind: SymbolKind, $publicOnly: Boolean, $version: String, $includeCode: Boolean, $contextLines: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
|
|
660
676
|
findSymbol(
|
|
661
677
|
registry: $registry
|
|
662
678
|
packageName: $packageName
|
|
679
|
+
repoUrl: $repoUrl
|
|
680
|
+
gitRef: $gitRef
|
|
663
681
|
name: $name
|
|
664
682
|
namespace: $namespace
|
|
665
683
|
kind: $kind
|
|
@@ -693,14 +711,18 @@ var FindSymbolDocument = gql`
|
|
|
693
711
|
indexedAt
|
|
694
712
|
hint
|
|
695
713
|
}
|
|
714
|
+
indexingStatus
|
|
715
|
+
indexingRef
|
|
696
716
|
}
|
|
697
717
|
}
|
|
698
718
|
`;
|
|
699
719
|
var SearchSymbolsDocument = gql`
|
|
700
|
-
query SearchSymbols($registry: Registry
|
|
720
|
+
query SearchSymbols($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $query: String, $keywords: [String!], $matchMode: MatchMode, $kind: SymbolKind, $filePath: String, $version: String, $limit: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
|
|
701
721
|
searchSymbols(
|
|
702
722
|
registry: $registry
|
|
703
723
|
packageName: $packageName
|
|
724
|
+
repoUrl: $repoUrl
|
|
725
|
+
gitRef: $gitRef
|
|
704
726
|
query: $query
|
|
705
727
|
keywords: $keywords
|
|
706
728
|
matchMode: $matchMode
|
|
@@ -739,14 +761,18 @@ var SearchSymbolsDocument = gql`
|
|
|
739
761
|
hint
|
|
740
762
|
}
|
|
741
763
|
warning
|
|
764
|
+
indexingStatus
|
|
765
|
+
indexingRef
|
|
742
766
|
}
|
|
743
767
|
}
|
|
744
768
|
`;
|
|
745
769
|
var ListSymbolsDocument = gql`
|
|
746
|
-
query ListSymbols($registry: Registry
|
|
770
|
+
query ListSymbols($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $scope: ListScope!, $filePath: String, $namespace: String, $publicOnly: Boolean, $includePopularity: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
|
|
747
771
|
listSymbols(
|
|
748
772
|
registry: $registry
|
|
749
773
|
packageName: $packageName
|
|
774
|
+
repoUrl: $repoUrl
|
|
775
|
+
gitRef: $gitRef
|
|
750
776
|
scope: $scope
|
|
751
777
|
filePath: $filePath
|
|
752
778
|
namespace: $namespace
|
|
@@ -776,6 +802,8 @@ var ListSymbolsDocument = gql`
|
|
|
776
802
|
path
|
|
777
803
|
language
|
|
778
804
|
}
|
|
805
|
+
indexingStatus
|
|
806
|
+
indexingRef
|
|
779
807
|
}
|
|
780
808
|
}
|
|
781
809
|
`;
|
|
@@ -815,6 +843,8 @@ var SymbolDependenciesDocument = gql`
|
|
|
815
843
|
missingPackages
|
|
816
844
|
total
|
|
817
845
|
hasMore
|
|
846
|
+
indexingStatus
|
|
847
|
+
indexingRef
|
|
818
848
|
}
|
|
819
849
|
}
|
|
820
850
|
`;
|
|
@@ -844,14 +874,18 @@ var SymbolDependentsDocument = gql`
|
|
|
844
874
|
}
|
|
845
875
|
total
|
|
846
876
|
hasMore
|
|
877
|
+
indexingStatus
|
|
878
|
+
indexingRef
|
|
847
879
|
}
|
|
848
880
|
}
|
|
849
881
|
`;
|
|
850
882
|
var PackageImportsDocument = gql`
|
|
851
|
-
query PackageImports($registry: Registry
|
|
883
|
+
query PackageImports($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $filePath: String, $resolvedOnly: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
|
|
852
884
|
packageImports(
|
|
853
885
|
registry: $registry
|
|
854
886
|
packageName: $packageName
|
|
887
|
+
repoUrl: $repoUrl
|
|
888
|
+
gitRef: $gitRef
|
|
855
889
|
filePath: $filePath
|
|
856
890
|
resolvedOnly: $resolvedOnly
|
|
857
891
|
limit: $limit
|
|
@@ -876,6 +910,8 @@ var PackageImportsDocument = gql`
|
|
|
876
910
|
}
|
|
877
911
|
uniqueDependencies
|
|
878
912
|
unresolvedCount
|
|
913
|
+
indexingStatus
|
|
914
|
+
indexingRef
|
|
879
915
|
}
|
|
880
916
|
}
|
|
881
917
|
`;
|
|
@@ -909,6 +945,8 @@ var CallPathDocument = gql`
|
|
|
909
945
|
callLine
|
|
910
946
|
}
|
|
911
947
|
}
|
|
948
|
+
indexingStatus
|
|
949
|
+
indexingRef
|
|
912
950
|
}
|
|
913
951
|
}
|
|
914
952
|
`;
|
|
@@ -941,10 +979,12 @@ var SearchProjectDocsDocument = gql`
|
|
|
941
979
|
}
|
|
942
980
|
`;
|
|
943
981
|
var ListRepoFilesDocument = gql`
|
|
944
|
-
query ListRepoFiles($registry: Registry
|
|
982
|
+
query ListRepoFiles($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $version: String, $pathPrefix: String, $limit: Int, $waitTimeoutMs: Int) {
|
|
945
983
|
listRepoFiles(
|
|
946
984
|
registry: $registry
|
|
947
985
|
packageName: $packageName
|
|
986
|
+
repoUrl: $repoUrl
|
|
987
|
+
gitRef: $gitRef
|
|
948
988
|
version: $version
|
|
949
989
|
pathPrefix: $pathPrefix
|
|
950
990
|
limit: $limit
|
|
@@ -967,14 +1007,18 @@ var ListRepoFilesDocument = gql`
|
|
|
967
1007
|
indexedAt
|
|
968
1008
|
hint
|
|
969
1009
|
}
|
|
1010
|
+
indexingStatus
|
|
1011
|
+
indexingRef
|
|
970
1012
|
}
|
|
971
1013
|
}
|
|
972
1014
|
`;
|
|
973
1015
|
var GrepRepoFileDocument = gql`
|
|
974
|
-
query GrepRepoFile($registry: Registry
|
|
1016
|
+
query GrepRepoFile($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $filePath: String!, $pattern: String!, $contextLines: Int, $maxMatches: Int, $version: String, $waitTimeoutMs: Int) {
|
|
975
1017
|
grepRepoFile(
|
|
976
1018
|
registry: $registry
|
|
977
1019
|
packageName: $packageName
|
|
1020
|
+
repoUrl: $repoUrl
|
|
1021
|
+
gitRef: $gitRef
|
|
978
1022
|
filePath: $filePath
|
|
979
1023
|
pattern: $pattern
|
|
980
1024
|
contextLines: $contextLines
|
|
@@ -1001,14 +1045,18 @@ var GrepRepoFileDocument = gql`
|
|
|
1001
1045
|
indexedAt
|
|
1002
1046
|
hint
|
|
1003
1047
|
}
|
|
1048
|
+
indexingStatus
|
|
1049
|
+
indexingRef
|
|
1004
1050
|
}
|
|
1005
1051
|
}
|
|
1006
1052
|
`;
|
|
1007
1053
|
var VersionDiffDocument = gql`
|
|
1008
|
-
query VersionDiff($registry: Registry
|
|
1054
|
+
query VersionDiff($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $fromVersion: String!, $toVersion: String!, $includePrivate: Boolean, $kind: SymbolKind, $limit: Int, $waitTimeoutMs: Int) {
|
|
1009
1055
|
versionDiff(
|
|
1010
1056
|
registry: $registry
|
|
1011
1057
|
packageName: $packageName
|
|
1058
|
+
repoUrl: $repoUrl
|
|
1059
|
+
gitRef: $gitRef
|
|
1012
1060
|
fromVersion: $fromVersion
|
|
1013
1061
|
toVersion: $toVersion
|
|
1014
1062
|
includePrivate: $includePrivate
|
|
@@ -1056,6 +1104,8 @@ var VersionDiffDocument = gql`
|
|
|
1056
1104
|
}
|
|
1057
1105
|
}
|
|
1058
1106
|
hasMore
|
|
1107
|
+
indexingStatus
|
|
1108
|
+
indexingRef
|
|
1059
1109
|
}
|
|
1060
1110
|
}
|
|
1061
1111
|
`;
|
|
@@ -1074,6 +1124,7 @@ var SearchResultsDocumentString = print(SearchResultsDocument);
|
|
|
1074
1124
|
var FetchCodeContextDocumentString = print(FetchCodeContextDocument);
|
|
1075
1125
|
var CliDocsGetDocumentString = print(CliDocsGetDocument);
|
|
1076
1126
|
var TriggerIndexingDocumentString = print(TriggerIndexingDocument);
|
|
1127
|
+
var IndexingProgressDocumentString = print(IndexingProgressDocument);
|
|
1077
1128
|
var CreateProjectDocumentString = print(CreateProjectDocument);
|
|
1078
1129
|
var PackageSummaryDocumentString = print(PackageSummaryDocument);
|
|
1079
1130
|
var PackageVulnerabilitiesDocumentString = print(PackageVulnerabilitiesDocument);
|
|
@@ -1139,6 +1190,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
1139
1190
|
TriggerIndexing(variables, requestHeaders) {
|
|
1140
1191
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(TriggerIndexingDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "TriggerIndexing", "mutation", variables);
|
|
1141
1192
|
},
|
|
1193
|
+
IndexingProgress(variables, requestHeaders) {
|
|
1194
|
+
return withWrapper((wrappedRequestHeaders) => client.rawRequest(IndexingProgressDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "IndexingProgress", "query", variables);
|
|
1195
|
+
},
|
|
1142
1196
|
CreateProject(variables, requestHeaders) {
|
|
1143
1197
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(CreateProjectDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
|
|
1144
1198
|
},
|
|
@@ -1641,20 +1695,27 @@ var TOOL_NAMES = [
|
|
|
1641
1695
|
"fetch_package_doc",
|
|
1642
1696
|
"search",
|
|
1643
1697
|
"search_status",
|
|
1644
|
-
"
|
|
1698
|
+
"read_file",
|
|
1645
1699
|
"search_project_docs",
|
|
1646
|
-
"
|
|
1647
|
-
"
|
|
1700
|
+
"list_files",
|
|
1701
|
+
"grep_file",
|
|
1648
1702
|
"find_symbol",
|
|
1649
1703
|
"search_symbols",
|
|
1650
1704
|
"list_symbols",
|
|
1651
1705
|
"symbol_callers",
|
|
1652
1706
|
"symbol_callees",
|
|
1653
|
-
"
|
|
1707
|
+
"list_imports",
|
|
1654
1708
|
"call_path",
|
|
1655
1709
|
"trigger_indexing",
|
|
1710
|
+
"indexing_status",
|
|
1656
1711
|
"version_diff"
|
|
1657
1712
|
];
|
|
1713
|
+
var TOOL_NAME_MIGRATION = {
|
|
1714
|
+
fetch_code_context: "read_file",
|
|
1715
|
+
list_package_files: "list_files",
|
|
1716
|
+
grep_package_file: "grep_file",
|
|
1717
|
+
package_imports: "list_imports"
|
|
1718
|
+
};
|
|
1658
1719
|
var ToolNameSchema = z.enum(TOOL_NAMES);
|
|
1659
1720
|
var SharedConfigFields = {
|
|
1660
1721
|
enabled_tools: z.array(ToolNameSchema).optional()
|
|
@@ -1762,6 +1823,24 @@ class ConfigServiceImpl {
|
|
|
1762
1823
|
if (parsed === null || parsed === undefined) {
|
|
1763
1824
|
return schema.parse({});
|
|
1764
1825
|
}
|
|
1826
|
+
if (parsed && typeof parsed === "object" && Array.isArray(parsed.enabled_tools)) {
|
|
1827
|
+
const migrated = [];
|
|
1828
|
+
let hasMigrations = false;
|
|
1829
|
+
for (const name of parsed.enabled_tools) {
|
|
1830
|
+
const replacement = TOOL_NAME_MIGRATION[name];
|
|
1831
|
+
if (replacement) {
|
|
1832
|
+
migrated.push(replacement);
|
|
1833
|
+
hasMigrations = true;
|
|
1834
|
+
} else {
|
|
1835
|
+
migrated.push(name);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
if (hasMigrations) {
|
|
1839
|
+
const oldNames = parsed.enabled_tools.filter((n) => TOOL_NAME_MIGRATION[n]);
|
|
1840
|
+
console.warn(`[pkgseer] Config at ${path}: migrating deprecated tool names: ${oldNames.join(", ")}. Update your config to use the new names.`);
|
|
1841
|
+
parsed.enabled_tools = migrated;
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1765
1844
|
const result = schema.safeParse(parsed);
|
|
1766
1845
|
if (result.success) {
|
|
1767
1846
|
return result.data;
|
|
@@ -2207,9 +2286,13 @@ class PkgseerServiceImpl {
|
|
|
2207
2286
|
const result = await this.client.FetchCodeContext({
|
|
2208
2287
|
repoUrl,
|
|
2209
2288
|
gitRef,
|
|
2289
|
+
registry: options?.registry,
|
|
2290
|
+
packageName: options?.packageName,
|
|
2291
|
+
version: options?.version,
|
|
2210
2292
|
filePath,
|
|
2211
2293
|
startLine: options?.startLine,
|
|
2212
|
-
endLine: options?.endLine
|
|
2294
|
+
endLine: options?.endLine,
|
|
2295
|
+
waitTimeoutMs: options?.waitTimeoutMs
|
|
2213
2296
|
});
|
|
2214
2297
|
return { data: result.data, errors: result.errors };
|
|
2215
2298
|
}
|
|
@@ -2217,6 +2300,8 @@ class PkgseerServiceImpl {
|
|
|
2217
2300
|
const result = await this.client.FindSymbol({
|
|
2218
2301
|
registry,
|
|
2219
2302
|
packageName,
|
|
2303
|
+
repoUrl: options?.repoUrl,
|
|
2304
|
+
gitRef: options?.gitRef,
|
|
2220
2305
|
name: options?.name,
|
|
2221
2306
|
namespace: options?.namespace,
|
|
2222
2307
|
kind: options?.kind,
|
|
@@ -2233,6 +2318,8 @@ class PkgseerServiceImpl {
|
|
|
2233
2318
|
const result = await this.client.SearchSymbols({
|
|
2234
2319
|
registry,
|
|
2235
2320
|
packageName,
|
|
2321
|
+
repoUrl: options?.repoUrl,
|
|
2322
|
+
gitRef: options?.gitRef,
|
|
2236
2323
|
query: options?.query,
|
|
2237
2324
|
keywords: options?.keywords,
|
|
2238
2325
|
matchMode: options?.matchMode,
|
|
@@ -2249,6 +2336,8 @@ class PkgseerServiceImpl {
|
|
|
2249
2336
|
const result = await this.client.ListSymbols({
|
|
2250
2337
|
registry,
|
|
2251
2338
|
packageName,
|
|
2339
|
+
repoUrl: options?.repoUrl,
|
|
2340
|
+
gitRef: options?.gitRef,
|
|
2252
2341
|
scope,
|
|
2253
2342
|
filePath: options?.filePath,
|
|
2254
2343
|
namespace: options?.namespace,
|
|
@@ -2289,6 +2378,8 @@ class PkgseerServiceImpl {
|
|
|
2289
2378
|
const result = await this.client.PackageImports({
|
|
2290
2379
|
registry,
|
|
2291
2380
|
packageName,
|
|
2381
|
+
repoUrl: options?.repoUrl,
|
|
2382
|
+
gitRef: options?.gitRef,
|
|
2292
2383
|
filePath: options?.filePath,
|
|
2293
2384
|
resolvedOnly: options?.resolvedOnly,
|
|
2294
2385
|
limit: options?.limit,
|
|
@@ -2312,6 +2403,8 @@ class PkgseerServiceImpl {
|
|
|
2312
2403
|
const result = await this.client.ListRepoFiles({
|
|
2313
2404
|
registry,
|
|
2314
2405
|
packageName,
|
|
2406
|
+
repoUrl: options?.repoUrl,
|
|
2407
|
+
gitRef: options?.gitRef,
|
|
2315
2408
|
version: options?.version,
|
|
2316
2409
|
pathPrefix: options?.pathPrefix,
|
|
2317
2410
|
limit: options?.limit,
|
|
@@ -2323,6 +2416,8 @@ class PkgseerServiceImpl {
|
|
|
2323
2416
|
const result = await this.client.GrepRepoFile({
|
|
2324
2417
|
registry,
|
|
2325
2418
|
packageName,
|
|
2419
|
+
repoUrl: options?.repoUrl,
|
|
2420
|
+
gitRef: options?.gitRef,
|
|
2326
2421
|
filePath,
|
|
2327
2422
|
pattern,
|
|
2328
2423
|
contextLines: options?.contextLines,
|
|
@@ -2336,6 +2431,8 @@ class PkgseerServiceImpl {
|
|
|
2336
2431
|
const result = await this.client.VersionDiff({
|
|
2337
2432
|
registry,
|
|
2338
2433
|
packageName,
|
|
2434
|
+
repoUrl: options?.repoUrl,
|
|
2435
|
+
gitRef: options?.gitRef,
|
|
2339
2436
|
fromVersion,
|
|
2340
2437
|
toVersion,
|
|
2341
2438
|
includePrivate: options?.includePrivate,
|
|
@@ -2345,6 +2442,10 @@ class PkgseerServiceImpl {
|
|
|
2345
2442
|
});
|
|
2346
2443
|
return { data: result.data, errors: result.errors };
|
|
2347
2444
|
}
|
|
2445
|
+
async getIndexingProgress(ref) {
|
|
2446
|
+
const result = await this.client.IndexingProgress({ ref });
|
|
2447
|
+
return { data: result.data, errors: result.errors };
|
|
2448
|
+
}
|
|
2348
2449
|
async triggerIndexing(input) {
|
|
2349
2450
|
const result = await this.client.TriggerIndexing({ input });
|
|
2350
2451
|
return { data: result.data, errors: result.errors };
|
|
@@ -6744,25 +6845,96 @@ var schemas = {
|
|
|
6744
6845
|
packageName: z2.string().max(255).describe("Name of the package"),
|
|
6745
6846
|
version: z2.string().max(100).optional().describe("Specific version, e.g. '4.18.2' (defaults to latest)"),
|
|
6746
6847
|
navigationMode: z2.enum(["summary", "detailed"]).optional().describe("Response detail level. summary (default) returns core fields; detailed adds all optional fields."),
|
|
6747
|
-
waitTimeoutMs: z2.coerce.number().int().min(0).max(
|
|
6848
|
+
waitTimeoutMs: z2.coerce.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (0-60000, default 10000). Set 0 to error immediately if not indexed."),
|
|
6748
6849
|
symbolReference: z2.object({
|
|
6749
6850
|
symbol_ref: z2.string().optional().describe("Compound symbol reference (registry:package:version:id) from find_symbol or list_symbols results. Self-contained — no additional fields needed."),
|
|
6750
|
-
registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (
|
|
6751
|
-
package_name: z2.string().max(255).optional().describe("Package name (
|
|
6752
|
-
symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath.")
|
|
6753
|
-
|
|
6851
|
+
registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry. For package-scoped lookup (with package_name + symbol_name)."),
|
|
6852
|
+
package_name: z2.string().max(255).optional().describe("Package name. For package-scoped lookup (with registry + symbol_name)."),
|
|
6853
|
+
symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath."),
|
|
6854
|
+
version: z2.string().max(100).optional().describe("Package version. For package-scoped lookup."),
|
|
6855
|
+
repo_url: z2.string().optional().describe("Repository URL (GitHub). For repo-scoped lookup (with git_ref + symbol_name)."),
|
|
6856
|
+
git_ref: z2.string().optional().describe("Git ref (tag, branch, commit, or HEAD). Required with repo_url.")
|
|
6857
|
+
}),
|
|
6858
|
+
codeTarget: z2.object({
|
|
6859
|
+
registry: z2.enum([
|
|
6860
|
+
"npm",
|
|
6861
|
+
"pypi",
|
|
6862
|
+
"hex",
|
|
6863
|
+
"crates",
|
|
6864
|
+
"nuget",
|
|
6865
|
+
"maven",
|
|
6866
|
+
"zig",
|
|
6867
|
+
"vcpkg"
|
|
6868
|
+
]).optional().describe("Package registry (npm, pypi, hex, etc.). Required for package scope."),
|
|
6869
|
+
package_name: z2.string().max(255).optional().describe("Package name. Required for package scope."),
|
|
6870
|
+
version: z2.string().max(100).optional().describe("Package version, e.g. '4.18.2' (defaults to latest). For package scope only."),
|
|
6871
|
+
repo_url: z2.string().optional().describe("Repository URL (GitHub). Required for repo scope. Example: https://github.com/expressjs/express"),
|
|
6872
|
+
git_ref: z2.string().optional().describe("Git ref — tag, branch, or commit. Required for repo scope. Use HEAD for latest.")
|
|
6873
|
+
}).describe("Target: provide registry + package_name (package scope) OR repo_url + git_ref (repo scope).")
|
|
6754
6874
|
};
|
|
6755
6875
|
function toSymbolReferenceInput(ref) {
|
|
6756
6876
|
return {
|
|
6757
6877
|
symbolRef: ref.symbol_ref,
|
|
6758
6878
|
registry: ref.registry ? toGraphQLRegistry(ref.registry) : undefined,
|
|
6759
6879
|
packageName: ref.package_name,
|
|
6760
|
-
symbolName: ref.symbol_name
|
|
6880
|
+
symbolName: ref.symbol_name,
|
|
6881
|
+
version: ref.version,
|
|
6882
|
+
repoUrl: ref.repo_url,
|
|
6883
|
+
gitRef: ref.git_ref
|
|
6884
|
+
};
|
|
6885
|
+
}
|
|
6886
|
+
function isToolError(value) {
|
|
6887
|
+
return "content" in value;
|
|
6888
|
+
}
|
|
6889
|
+
function resolveCodeTarget(target) {
|
|
6890
|
+
const hasPackage = target.registry || target.package_name;
|
|
6891
|
+
const hasRepo = target.repo_url || target.git_ref;
|
|
6892
|
+
if (hasPackage && hasRepo) {
|
|
6893
|
+
return errorResult("Invalid target: provide either registry + package_name (package scope) or repo_url + git_ref (repo scope), not both.");
|
|
6894
|
+
}
|
|
6895
|
+
if (!hasPackage && !hasRepo) {
|
|
6896
|
+
return errorResult("Missing target: provide registry + package_name (package scope) or repo_url + git_ref (repo scope).");
|
|
6897
|
+
}
|
|
6898
|
+
if (hasPackage) {
|
|
6899
|
+
if (!target.registry || !target.package_name) {
|
|
6900
|
+
return errorResult("Incomplete package target: both registry and package_name are required for package scope.");
|
|
6901
|
+
}
|
|
6902
|
+
return {
|
|
6903
|
+
mode: "package",
|
|
6904
|
+
registry: target.registry,
|
|
6905
|
+
packageName: target.package_name,
|
|
6906
|
+
version: target.version
|
|
6907
|
+
};
|
|
6908
|
+
}
|
|
6909
|
+
if (!target.repo_url) {
|
|
6910
|
+
return errorResult("Incomplete repo target: repo_url is required with git_ref.");
|
|
6911
|
+
}
|
|
6912
|
+
if (!target.git_ref) {
|
|
6913
|
+
return errorResult("Incomplete repo target: git_ref is required with repo_url (use HEAD for latest).");
|
|
6914
|
+
}
|
|
6915
|
+
return { mode: "repo", repoUrl: target.repo_url, gitRef: target.git_ref };
|
|
6916
|
+
}
|
|
6917
|
+
function buildCodeTargetVars(resolved) {
|
|
6918
|
+
if (resolved.mode === "package") {
|
|
6919
|
+
return {
|
|
6920
|
+
registry: toGraphQLRegistry(resolved.registry),
|
|
6921
|
+
packageName: resolved.packageName,
|
|
6922
|
+
version: resolved.version,
|
|
6923
|
+
repoUrl: undefined,
|
|
6924
|
+
gitRef: undefined
|
|
6925
|
+
};
|
|
6926
|
+
}
|
|
6927
|
+
return {
|
|
6928
|
+
registry: undefined,
|
|
6929
|
+
packageName: undefined,
|
|
6930
|
+
version: undefined,
|
|
6931
|
+
repoUrl: resolved.repoUrl,
|
|
6932
|
+
gitRef: resolved.gitRef
|
|
6761
6933
|
};
|
|
6762
6934
|
}
|
|
6763
6935
|
var DEFAULT_WAIT_TIMEOUT_MS2 = 1e4;
|
|
6764
6936
|
var MCP_HINTS = {
|
|
6765
|
-
being_indexed: "Hint:
|
|
6937
|
+
being_indexed: "Hint: target is being indexed. Retry with a longer wait_timeout_ms (e.g., 30000) or use indexing_status to poll progress.",
|
|
6766
6938
|
timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
|
|
6767
6939
|
};
|
|
6768
6940
|
function buildHintedMessage(operation, message) {
|
|
@@ -6791,14 +6963,50 @@ function buildHintedMessage(operation, message) {
|
|
|
6791
6963
|
return `Failed to ${operation}: ${message}`;
|
|
6792
6964
|
}
|
|
6793
6965
|
var MCP_GRAPHQL_HINTS = {
|
|
6794
|
-
not_found: "Hint: verify the package name
|
|
6795
|
-
being_indexed: "Hint:
|
|
6966
|
+
not_found: "Hint: verify the package name, registry, or repository URL are correct.",
|
|
6967
|
+
being_indexed: "Hint: target is being indexed. Retry with a longer wait_timeout_ms (e.g., 30000) or use indexing_status to poll progress.",
|
|
6796
6968
|
timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
|
|
6797
6969
|
};
|
|
6970
|
+
function getExtensionCode(errors) {
|
|
6971
|
+
for (const error2 of errors) {
|
|
6972
|
+
const ext = error2.extensions;
|
|
6973
|
+
if (ext?.code && typeof ext.code === "string") {
|
|
6974
|
+
return ext.code;
|
|
6975
|
+
}
|
|
6976
|
+
}
|
|
6977
|
+
return;
|
|
6978
|
+
}
|
|
6979
|
+
function getExtensionIndexingRef(errors) {
|
|
6980
|
+
for (const error2 of errors) {
|
|
6981
|
+
const ext = error2.extensions;
|
|
6982
|
+
const ref = ext?.indexing_ref ?? ext?.indexingRef;
|
|
6983
|
+
if (ref && typeof ref === "string") {
|
|
6984
|
+
return ref;
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6987
|
+
return;
|
|
6988
|
+
}
|
|
6989
|
+
var EXTENSION_CODE_HINTS = {
|
|
6990
|
+
PACKAGE_INDEXING: "Hint: target is being indexed. Use indexing_status to poll progress, or retry with a longer wait_timeout_ms.",
|
|
6991
|
+
NOT_FOUND: "Hint: verify the package name, registry, or repository URL are correct."
|
|
6992
|
+
};
|
|
6798
6993
|
function handleGraphQLErrors(errors) {
|
|
6799
6994
|
if (errors && errors.length > 0) {
|
|
6800
6995
|
const combined = errors.map((e) => e.message).filter(Boolean).join(", ");
|
|
6801
|
-
const
|
|
6996
|
+
const extensionCode = getExtensionCode(errors);
|
|
6997
|
+
const indexingRef = getExtensionIndexingRef(errors);
|
|
6998
|
+
if (extensionCode === "PACKAGE_INDEXING" && indexingRef) {
|
|
6999
|
+
return errorResult(JSON.stringify({
|
|
7000
|
+
error: combined,
|
|
7001
|
+
indexingStatus: "INDEXING",
|
|
7002
|
+
indexingRef,
|
|
7003
|
+
message: "Target is being indexed. Use indexing_status tool with this indexingRef to poll progress, " + "or retry the original query after indexing completes."
|
|
7004
|
+
}));
|
|
7005
|
+
}
|
|
7006
|
+
if (extensionCode === "PACKAGE_INDEXING") {
|
|
7007
|
+
return errorResult(`Error: ${combined}. ` + "Hint: target is being indexed (background refresh). Retry the query in a few seconds.");
|
|
7008
|
+
}
|
|
7009
|
+
const hint = extensionCode ? EXTENSION_CODE_HINTS[extensionCode] : MCP_GRAPHQL_HINTS[classifyError(combined)];
|
|
6802
7010
|
const suffix = hint ? `. ${hint}` : "";
|
|
6803
7011
|
return errorResult(`Error: ${combined}${suffix}`);
|
|
6804
7012
|
}
|
|
@@ -6818,8 +7026,8 @@ function notFoundError(packageName, registry) {
|
|
|
6818
7026
|
|
|
6819
7027
|
// src/tools/call-path.ts
|
|
6820
7028
|
var argsSchema = {
|
|
6821
|
-
from: schemas.symbolReference.describe("Source symbol. Provide
|
|
6822
|
-
to: schemas.symbolReference.describe("Destination symbol. Provide
|
|
7029
|
+
from: schemas.symbolReference.describe("Source symbol. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
|
|
7030
|
+
to: schemas.symbolReference.describe("Destination symbol. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
|
|
6823
7031
|
max_depth: z3.coerce.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
|
|
6824
7032
|
mode: schemas.navigationMode,
|
|
6825
7033
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
@@ -6827,18 +7035,18 @@ var argsSchema = {
|
|
|
6827
7035
|
function createCallPathTool(pkgseerService) {
|
|
6828
7036
|
return {
|
|
6829
7037
|
name: "call_path",
|
|
6830
|
-
description: "Trace how execution flows from one function to another in a dependency — " + "debug how a public API reaches an internal function or error handler. " + "Uses BFS through intermediate calls. " + "Returns ordered call paths (shortest first) with hop details. " + "For direct callers/callees only, use symbol_callers or symbol_callees instead.",
|
|
7038
|
+
description: "Trace how execution flows from one function to another in a dependency — " + "debug how a public API reaches an internal function or error handler. " + "Uses BFS through intermediate calls. " + "Returns ordered call paths (shortest first) with hop details. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "For direct callers/callees only, use symbol_callers or symbol_callees instead.",
|
|
6831
7039
|
schema: argsSchema,
|
|
6832
7040
|
annotations: { readOnlyHint: true },
|
|
6833
7041
|
handler: async (args, _extra) => {
|
|
6834
7042
|
return withErrorHandling("find call path", async () => {
|
|
6835
7043
|
const fromInput = toSymbolReferenceInput(args.from);
|
|
6836
7044
|
const toInput = toSymbolReferenceInput(args.to);
|
|
6837
|
-
if (!fromInput.symbolRef && (
|
|
6838
|
-
return errorResult("Invalid 'from' symbol: provide
|
|
7045
|
+
if (!fromInput.symbolRef && !(fromInput.symbolName && fromInput.registry && fromInput.packageName) && !(fromInput.symbolName && fromInput.repoUrl && fromInput.gitRef)) {
|
|
7046
|
+
return errorResult("Invalid 'from' symbol: provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
6839
7047
|
}
|
|
6840
|
-
if (!toInput.symbolRef && (
|
|
6841
|
-
return errorResult("Invalid 'to' symbol: provide
|
|
7048
|
+
if (!toInput.symbolRef && !(toInput.symbolName && toInput.registry && toInput.packageName) && !(toInput.symbolName && toInput.repoUrl && toInput.gitRef)) {
|
|
7049
|
+
return errorResult("Invalid 'to' symbol: provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
6842
7050
|
}
|
|
6843
7051
|
const result = await pkgseerService.callPath(fromInput, toInput, {
|
|
6844
7052
|
maxDepth: args.max_depth,
|
|
@@ -6888,54 +7096,16 @@ function createComparePackagesTool(pkgseerService) {
|
|
|
6888
7096
|
}
|
|
6889
7097
|
};
|
|
6890
7098
|
}
|
|
6891
|
-
// src/tools/fetch-
|
|
7099
|
+
// src/tools/fetch-package-doc.ts
|
|
6892
7100
|
import { z as z5 } from "zod";
|
|
6893
7101
|
var argsSchema3 = {
|
|
6894
|
-
|
|
6895
|
-
error: "repo_url is required. Get it from package_summary (returns repository URL). " + "Or use find_symbol(include_code=true) to read source without needing repo_url."
|
|
6896
|
-
}).min(1).describe("Repository URL (GitHub). Example: https://github.com/expressjs/express"),
|
|
6897
|
-
git_ref: z5.string({
|
|
6898
|
-
error: "git_ref is required. Use the package version as a tag (e.g., 'v4.18.2'). " + "Get the latest version from package_summary."
|
|
6899
|
-
}).min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
|
|
6900
|
-
file_path: z5.string({
|
|
6901
|
-
error: "file_path is required. Get file paths from find_symbol (returns file locations) " + "or list_package_files (browse package file structure)."
|
|
6902
|
-
}).min(1).describe("Path to file in repository. Example: src/router/index.js"),
|
|
6903
|
-
start_line: z5.coerce.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
|
|
6904
|
-
end_line: z5.coerce.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
|
|
6905
|
-
};
|
|
6906
|
-
function createFetchCodeContextTool(pkgseerService) {
|
|
6907
|
-
return {
|
|
6908
|
-
name: "fetch_code_context",
|
|
6909
|
-
description: "Read source code from a dependency's repository by file path and line range — " + "use when you have a file path from a stack trace or symbol lookup. " + "Returns full file or a specific line range. " + "Prefer find_symbol(include_code=true) for function/class lookup. " + "Requires repo_url (from package_summary), git_ref (version tag, e.g. 'v4.18.2'), " + "and file_path (from find_symbol or list_package_files). " + "Operates on the full repository — not filtered to package subdirectory in monorepos.",
|
|
6910
|
-
schema: argsSchema3,
|
|
6911
|
-
annotations: { readOnlyHint: true },
|
|
6912
|
-
handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
|
|
6913
|
-
return withErrorHandling("fetch code context", async () => {
|
|
6914
|
-
const result = await pkgseerService.fetchCodeContext(repo_url, git_ref, file_path, {
|
|
6915
|
-
startLine: start_line,
|
|
6916
|
-
endLine: end_line
|
|
6917
|
-
});
|
|
6918
|
-
const graphqlError = handleGraphQLErrors(result.errors);
|
|
6919
|
-
if (graphqlError)
|
|
6920
|
-
return graphqlError;
|
|
6921
|
-
if (!result.data?.fetchCodeContext) {
|
|
6922
|
-
return errorResult(`Code not found: ${file_path} at ${git_ref} in ${repo_url}. ` + "Check that the repository, file path, and git ref are correct.");
|
|
6923
|
-
}
|
|
6924
|
-
return textResult(JSON.stringify(result.data?.fetchCodeContext, null, 2));
|
|
6925
|
-
});
|
|
6926
|
-
}
|
|
6927
|
-
};
|
|
6928
|
-
}
|
|
6929
|
-
// src/tools/fetch-package-doc.ts
|
|
6930
|
-
import { z as z6 } from "zod";
|
|
6931
|
-
var argsSchema4 = {
|
|
6932
|
-
page_id: z6.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
|
|
7102
|
+
page_id: z5.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
|
|
6933
7103
|
};
|
|
6934
7104
|
function createFetchPackageDocTool(pkgseerService) {
|
|
6935
7105
|
return {
|
|
6936
7106
|
name: "fetch_package_doc",
|
|
6937
7107
|
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. " + "Requires documentation to have been crawled — if page_id is from a stale listing, re-check with list_package_docs.",
|
|
6938
|
-
schema:
|
|
7108
|
+
schema: argsSchema3,
|
|
6939
7109
|
annotations: { readOnlyHint: true },
|
|
6940
7110
|
handler: async ({ page_id }, _extra) => {
|
|
6941
7111
|
return withErrorHandling("fetch documentation page", async () => {
|
|
@@ -6952,13 +7122,12 @@ function createFetchPackageDocTool(pkgseerService) {
|
|
|
6952
7122
|
};
|
|
6953
7123
|
}
|
|
6954
7124
|
// src/tools/find-symbol.ts
|
|
6955
|
-
import { z as
|
|
6956
|
-
var
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
kind: z7.enum([
|
|
7125
|
+
import { z as z6 } from "zod";
|
|
7126
|
+
var argsSchema4 = {
|
|
7127
|
+
target: schemas.codeTarget,
|
|
7128
|
+
name: z6.string().max(500).optional().describe("Symbol name to search for (exact match or prefix). Omit to return all public exports."),
|
|
7129
|
+
namespace: z6.string().max(500).optional().describe("Filter by namespace/module path prefix"),
|
|
7130
|
+
kind: z6.enum([
|
|
6962
7131
|
"function",
|
|
6963
7132
|
"method",
|
|
6964
7133
|
"class",
|
|
@@ -6967,31 +7136,36 @@ var argsSchema5 = {
|
|
|
6967
7136
|
"type",
|
|
6968
7137
|
"doc_section"
|
|
6969
7138
|
]).optional().describe("Filter by symbol kind"),
|
|
6970
|
-
public_only:
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
context_lines: z7.coerce.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
|
|
7139
|
+
public_only: z6.boolean().optional().describe("Only return public/exported symbols"),
|
|
7140
|
+
include_code: z6.boolean().optional().describe("Include source code in results"),
|
|
7141
|
+
context_lines: z6.coerce.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
|
|
6974
7142
|
mode: schemas.navigationMode,
|
|
6975
7143
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6976
7144
|
};
|
|
6977
7145
|
function createFindSymbolTool(pkgseerService) {
|
|
6978
7146
|
return {
|
|
6979
7147
|
name: "find_symbol",
|
|
6980
|
-
description: "Read source code of any function, class, or method
|
|
6981
|
-
schema:
|
|
7148
|
+
description: "Read source code of any function, class, or method — use instead of guessing " + "implementations from training data. Accepts package scope (registry + package_name) " + "or repo scope (repo_url + git_ref) via the target parameter. " + "Set include_code=true for full source inline. " + "Returns: symbolRef, name, qualified path, kind, file location, and optionally source code. " + "Omit name to get all public exports. Use namespace to filter by module path. " + "Pass symbolRef from results to symbol_callers, symbol_callees, or call_path.",
|
|
7149
|
+
schema: argsSchema4,
|
|
6982
7150
|
annotations: { readOnlyHint: true },
|
|
6983
7151
|
handler: async (args, _extra) => {
|
|
6984
7152
|
return withErrorHandling("find symbol", async () => {
|
|
6985
|
-
const
|
|
7153
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7154
|
+
if (isToolError(resolved))
|
|
7155
|
+
return resolved;
|
|
7156
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7157
|
+
const result = await pkgseerService.findSymbol(tv.registry, tv.packageName, {
|
|
6986
7158
|
name: args.name,
|
|
6987
7159
|
namespace: args.namespace,
|
|
6988
7160
|
kind: toSymbolKind(args.kind),
|
|
6989
7161
|
publicOnly: args.public_only,
|
|
6990
|
-
version:
|
|
7162
|
+
version: tv.version,
|
|
6991
7163
|
includeCode: args.include_code,
|
|
6992
7164
|
contextLines: args.context_lines,
|
|
6993
7165
|
mode: toNavigationMode(args.mode),
|
|
6994
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7166
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7167
|
+
repoUrl: tv.repoUrl,
|
|
7168
|
+
gitRef: tv.gitRef
|
|
6995
7169
|
});
|
|
6996
7170
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
6997
7171
|
if (graphqlError)
|
|
@@ -7005,31 +7179,35 @@ function createFindSymbolTool(pkgseerService) {
|
|
|
7005
7179
|
}
|
|
7006
7180
|
};
|
|
7007
7181
|
}
|
|
7008
|
-
// src/tools/grep-
|
|
7009
|
-
import { z as
|
|
7010
|
-
var
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
max_matches: z8.coerce.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
|
|
7017
|
-
version: schemas.version,
|
|
7182
|
+
// src/tools/grep-file.ts
|
|
7183
|
+
import { z as z7 } from "zod";
|
|
7184
|
+
var argsSchema5 = {
|
|
7185
|
+
target: schemas.codeTarget,
|
|
7186
|
+
file_path: z7.string().describe("Path to the file (relative to package root)"),
|
|
7187
|
+
pattern: z7.string().max(200).describe("Case-insensitive substring to search for (max 200 chars)"),
|
|
7188
|
+
context_lines: z7.coerce.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
|
|
7189
|
+
max_matches: z7.coerce.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
|
|
7018
7190
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7019
7191
|
};
|
|
7020
|
-
function
|
|
7192
|
+
function createGrepFileTool(pkgseerService) {
|
|
7021
7193
|
return {
|
|
7022
|
-
name: "
|
|
7023
|
-
description: "Search for a pattern within a dependency's source file — " + "find error messages, config keys, or specific patterns without cloning the repo. " + "Case-insensitive substring matching with context lines. " + "Use when you know the file path and are looking for specific text. " + "Use
|
|
7024
|
-
schema:
|
|
7194
|
+
name: "grep_file",
|
|
7195
|
+
description: "Search for a pattern within a dependency's source file — " + "find error messages, config keys, or specific patterns without cloning the repo. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Case-insensitive substring matching with context lines. " + "Use when you know the file path and are looking for specific text. " + "Use list_files to discover file paths. " + "In monorepos with package scope, operates only within this package's subdirectory. " + "Requires code indexing.",
|
|
7196
|
+
schema: argsSchema5,
|
|
7025
7197
|
annotations: { readOnlyHint: true },
|
|
7026
7198
|
handler: async (args, _extra) => {
|
|
7027
|
-
return withErrorHandling("grep
|
|
7028
|
-
const
|
|
7199
|
+
return withErrorHandling("grep file", async () => {
|
|
7200
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7201
|
+
if (isToolError(resolved))
|
|
7202
|
+
return resolved;
|
|
7203
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7204
|
+
const result = await pkgseerService.grepRepoFile(tv.registry, tv.packageName, args.file_path, args.pattern, {
|
|
7029
7205
|
contextLines: args.context_lines,
|
|
7030
7206
|
maxMatches: args.max_matches,
|
|
7031
|
-
version:
|
|
7032
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7207
|
+
version: tv.version,
|
|
7208
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7209
|
+
repoUrl: tv.repoUrl,
|
|
7210
|
+
gitRef: tv.gitRef
|
|
7033
7211
|
});
|
|
7034
7212
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7035
7213
|
if (graphqlError)
|
|
@@ -7043,55 +7221,81 @@ function createGrepPackageFileTool(pkgseerService) {
|
|
|
7043
7221
|
}
|
|
7044
7222
|
};
|
|
7045
7223
|
}
|
|
7046
|
-
// src/tools/
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
version: schemas.version
|
|
7224
|
+
// src/tools/indexing-status.ts
|
|
7225
|
+
import { z as z8 } from "zod";
|
|
7226
|
+
var argsSchema6 = {
|
|
7227
|
+
ref: z8.string().min(1).describe("Indexing reference from a previous tool result (returned when indexing times out).")
|
|
7051
7228
|
};
|
|
7052
|
-
function
|
|
7229
|
+
function createIndexingStatusTool(pkgseerService) {
|
|
7053
7230
|
return {
|
|
7054
|
-
name: "
|
|
7055
|
-
description: "
|
|
7056
|
-
schema:
|
|
7231
|
+
name: "indexing_status",
|
|
7232
|
+
description: "Check indexing progress for a code navigation target. " + "Use after any code navigation tool returns an indexingRef (when indexing exceeded wait_timeout_ms). " + "Returns status (PENDING, INDEXING, INDEXED, FAILED, NOT_FOUND) with progress details. " + "When status is INDEXED, retry the original query to get results.",
|
|
7233
|
+
schema: argsSchema6,
|
|
7057
7234
|
annotations: { readOnlyHint: true },
|
|
7058
|
-
handler: async ({
|
|
7059
|
-
return withErrorHandling("
|
|
7060
|
-
const result = await pkgseerService.
|
|
7235
|
+
handler: async ({ ref }, _extra) => {
|
|
7236
|
+
return withErrorHandling("check indexing status", async () => {
|
|
7237
|
+
const result = await pkgseerService.getIndexingProgress(ref);
|
|
7061
7238
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7062
7239
|
if (graphqlError)
|
|
7063
7240
|
return graphqlError;
|
|
7064
|
-
|
|
7065
|
-
|
|
7241
|
+
const progress = result.data?.indexingProgress;
|
|
7242
|
+
if (!progress) {
|
|
7243
|
+
return errorResult("Indexing session not found. The reference may be invalid or the session may have expired.");
|
|
7066
7244
|
}
|
|
7067
|
-
|
|
7245
|
+
const response = {
|
|
7246
|
+
status: progress.status,
|
|
7247
|
+
ref
|
|
7248
|
+
};
|
|
7249
|
+
if (progress.filesIndexed != null) {
|
|
7250
|
+
response.filesIndexed = progress.filesIndexed;
|
|
7251
|
+
}
|
|
7252
|
+
if (progress.chunksCreated != null) {
|
|
7253
|
+
response.chunksCreated = progress.chunksCreated;
|
|
7254
|
+
}
|
|
7255
|
+
if (progress.elapsedMs != null) {
|
|
7256
|
+
response.elapsedMs = progress.elapsedMs;
|
|
7257
|
+
}
|
|
7258
|
+
if (progress.status === "INDEXED") {
|
|
7259
|
+
response.message = "Indexing is complete. Retry your original query to get results.";
|
|
7260
|
+
} else if (progress.status === "INDEXING" || progress.status === "PENDING") {
|
|
7261
|
+
response.message = "Indexing is in progress. Poll again to check status.";
|
|
7262
|
+
} else if (progress.status === "FAILED") {
|
|
7263
|
+
response.message = "Indexing failed.";
|
|
7264
|
+
} else if (progress.status === "NOT_FOUND") {
|
|
7265
|
+
response.message = "Indexing reference not found. The ref may be invalid or the session may have expired.";
|
|
7266
|
+
}
|
|
7267
|
+
return textResult(JSON.stringify(response, null, 2));
|
|
7068
7268
|
});
|
|
7069
7269
|
}
|
|
7070
7270
|
};
|
|
7071
7271
|
}
|
|
7072
|
-
// src/tools/list-
|
|
7272
|
+
// src/tools/list-files.ts
|
|
7073
7273
|
import { z as z9 } from "zod";
|
|
7074
|
-
var
|
|
7075
|
-
|
|
7076
|
-
package_name: schemas.packageName.describe("Name of the package to list files for"),
|
|
7077
|
-
version: schemas.version,
|
|
7274
|
+
var argsSchema7 = {
|
|
7275
|
+
target: schemas.codeTarget,
|
|
7078
7276
|
path_prefix: z9.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
|
|
7079
7277
|
limit: z9.coerce.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
|
|
7080
7278
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7081
7279
|
};
|
|
7082
|
-
function
|
|
7280
|
+
function createListFilesTool(pkgseerService) {
|
|
7083
7281
|
return {
|
|
7084
|
-
name: "
|
|
7085
|
-
description: "Explore a dependency's file structure — " + "see what source files, configs, and docs exist. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals. " + "In monorepos, returns only files within this package's subdirectory. " + "Requires code indexing.",
|
|
7086
|
-
schema:
|
|
7282
|
+
name: "list_files",
|
|
7283
|
+
description: "Explore a dependency's file structure — " + "see what source files, configs, and docs exist. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals. " + "In monorepos with package scope, returns only files within this package's subdirectory. " + "Requires code indexing.",
|
|
7284
|
+
schema: argsSchema7,
|
|
7087
7285
|
annotations: { readOnlyHint: true },
|
|
7088
7286
|
handler: async (args, _extra) => {
|
|
7089
|
-
return withErrorHandling("list
|
|
7090
|
-
const
|
|
7091
|
-
|
|
7287
|
+
return withErrorHandling("list files", async () => {
|
|
7288
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7289
|
+
if (isToolError(resolved))
|
|
7290
|
+
return resolved;
|
|
7291
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7292
|
+
const result = await pkgseerService.listRepoFiles(tv.registry, tv.packageName, {
|
|
7293
|
+
version: tv.version,
|
|
7092
7294
|
pathPrefix: args.path_prefix,
|
|
7093
7295
|
limit: args.limit,
|
|
7094
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7296
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7297
|
+
repoUrl: tv.repoUrl,
|
|
7298
|
+
gitRef: tv.gitRef
|
|
7095
7299
|
});
|
|
7096
7300
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7097
7301
|
if (graphqlError)
|
|
@@ -7105,26 +7309,90 @@ function createListPackageFilesTool(pkgseerService) {
|
|
|
7105
7309
|
}
|
|
7106
7310
|
};
|
|
7107
7311
|
}
|
|
7108
|
-
// src/tools/list-
|
|
7312
|
+
// src/tools/list-imports.ts
|
|
7109
7313
|
import { z as z10 } from "zod";
|
|
7314
|
+
var argsSchema8 = {
|
|
7315
|
+
target: schemas.codeTarget,
|
|
7316
|
+
file_path: z10.string().max(1000).optional().describe("Filter to a specific file path"),
|
|
7317
|
+
resolved_only: z10.boolean().optional().describe("Only return imports resolved to a known package"),
|
|
7318
|
+
limit: z10.coerce.number().int().min(1).max(500).optional().describe("Max imports to return"),
|
|
7319
|
+
mode: schemas.navigationMode,
|
|
7320
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7321
|
+
};
|
|
7322
|
+
function createListImportsTool(pkgseerService) {
|
|
7323
|
+
return {
|
|
7324
|
+
name: "list_imports",
|
|
7325
|
+
description: "See what a dependency imports — understand its internal dependencies and external package usage. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "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.",
|
|
7326
|
+
schema: argsSchema8,
|
|
7327
|
+
annotations: { readOnlyHint: true },
|
|
7328
|
+
handler: async (args, _extra) => {
|
|
7329
|
+
return withErrorHandling("list imports", async () => {
|
|
7330
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7331
|
+
if (isToolError(resolved))
|
|
7332
|
+
return resolved;
|
|
7333
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7334
|
+
const result = await pkgseerService.packageImports(tv.registry, tv.packageName, {
|
|
7335
|
+
filePath: args.file_path,
|
|
7336
|
+
resolvedOnly: args.resolved_only,
|
|
7337
|
+
limit: args.limit,
|
|
7338
|
+
version: tv.version,
|
|
7339
|
+
mode: toNavigationMode(args.mode),
|
|
7340
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7341
|
+
repoUrl: tv.repoUrl,
|
|
7342
|
+
gitRef: tv.gitRef
|
|
7343
|
+
});
|
|
7344
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7345
|
+
if (graphqlError)
|
|
7346
|
+
return graphqlError;
|
|
7347
|
+
return textResult(JSON.stringify(result.data.packageImports, null, 2));
|
|
7348
|
+
});
|
|
7349
|
+
}
|
|
7350
|
+
};
|
|
7351
|
+
}
|
|
7352
|
+
// src/tools/list-package-docs.ts
|
|
7110
7353
|
var argsSchema9 = {
|
|
7111
7354
|
registry: schemas.registry,
|
|
7112
|
-
package_name: schemas.packageName.describe("Name of the package to
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7355
|
+
package_name: schemas.packageName.describe("Name of the package to list documentation for"),
|
|
7356
|
+
version: schemas.version
|
|
7357
|
+
};
|
|
7358
|
+
function createListPackageDocsTool(pkgseerService) {
|
|
7359
|
+
return {
|
|
7360
|
+
name: "list_package_docs",
|
|
7361
|
+
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(mode='docs') to find specific topics. " + "Requires documentation to have been crawled — if results are empty, use trigger_indexing first, then retry.",
|
|
7362
|
+
schema: argsSchema9,
|
|
7363
|
+
annotations: { readOnlyHint: true },
|
|
7364
|
+
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
7365
|
+
return withErrorHandling("list package documentation", async () => {
|
|
7366
|
+
const result = await pkgseerService.listPackageDocs(toGraphQLRegistry(registry), package_name, version2);
|
|
7367
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7368
|
+
if (graphqlError)
|
|
7369
|
+
return graphqlError;
|
|
7370
|
+
if (!result.data?.listPackageDocs) {
|
|
7371
|
+
return notFoundError(package_name, registry);
|
|
7372
|
+
}
|
|
7373
|
+
return textResult(JSON.stringify(result.data?.listPackageDocs, null, 2));
|
|
7374
|
+
});
|
|
7375
|
+
}
|
|
7376
|
+
};
|
|
7377
|
+
}
|
|
7378
|
+
// src/tools/list-symbols.ts
|
|
7379
|
+
import { z as z11 } from "zod";
|
|
7380
|
+
var argsSchema10 = {
|
|
7381
|
+
target: schemas.codeTarget,
|
|
7382
|
+
scope: z11.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
|
|
7383
|
+
file_path: z11.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
|
|
7384
|
+
namespace: z11.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
|
|
7385
|
+
public_only: z11.boolean().optional().describe("Only return public symbols"),
|
|
7386
|
+
include_popularity: z11.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
|
|
7387
|
+
limit: z11.coerce.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
|
|
7120
7388
|
mode: schemas.navigationMode,
|
|
7121
7389
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7122
7390
|
};
|
|
7123
7391
|
function createListSymbolsTool(pkgseerService) {
|
|
7124
7392
|
return {
|
|
7125
7393
|
name: "list_symbols",
|
|
7126
|
-
description: "Browse a dependency's public API or file-level symbols. " + "Use scope='exports' for the public API with optional popularity ranking. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbol refs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to read source for any result.",
|
|
7127
|
-
schema:
|
|
7394
|
+
description: "Browse a dependency's public API or file-level symbols. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Use scope='exports' for the public API with optional popularity ranking. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbol refs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to read source for any result.",
|
|
7395
|
+
schema: argsSchema10,
|
|
7128
7396
|
annotations: { readOnlyHint: true },
|
|
7129
7397
|
handler: async (args, _extra) => {
|
|
7130
7398
|
return withErrorHandling("list symbols", async () => {
|
|
@@ -7140,15 +7408,21 @@ function createListSymbolsTool(pkgseerService) {
|
|
|
7140
7408
|
isError: true
|
|
7141
7409
|
};
|
|
7142
7410
|
}
|
|
7143
|
-
const
|
|
7411
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7412
|
+
if (isToolError(resolved))
|
|
7413
|
+
return resolved;
|
|
7414
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7415
|
+
const result = await pkgseerService.listSymbols(tv.registry, tv.packageName, scope, {
|
|
7144
7416
|
filePath: args.file_path,
|
|
7145
7417
|
namespace: args.namespace,
|
|
7146
7418
|
publicOnly: args.public_only,
|
|
7147
7419
|
includePopularity: args.include_popularity,
|
|
7148
7420
|
limit: args.limit,
|
|
7149
|
-
version:
|
|
7421
|
+
version: tv.version,
|
|
7150
7422
|
mode: toNavigationMode(args.mode),
|
|
7151
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7423
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7424
|
+
repoUrl: tv.repoUrl,
|
|
7425
|
+
gitRef: tv.gitRef
|
|
7152
7426
|
});
|
|
7153
7427
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7154
7428
|
if (graphqlError)
|
|
@@ -7159,13 +7433,13 @@ function createListSymbolsTool(pkgseerService) {
|
|
|
7159
7433
|
};
|
|
7160
7434
|
}
|
|
7161
7435
|
// src/tools/package-dependencies.ts
|
|
7162
|
-
import { z as
|
|
7163
|
-
var
|
|
7436
|
+
import { z as z12 } from "zod";
|
|
7437
|
+
var argsSchema11 = {
|
|
7164
7438
|
registry: schemas.registry,
|
|
7165
7439
|
package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
|
|
7166
7440
|
version: schemas.version,
|
|
7167
|
-
include_transitive:
|
|
7168
|
-
max_depth:
|
|
7441
|
+
include_transitive: z12.boolean().optional().describe("Whether to include transitive dependency DAG"),
|
|
7442
|
+
max_depth: z12.coerce.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
|
|
7169
7443
|
};
|
|
7170
7444
|
function decodeDag(rawDag) {
|
|
7171
7445
|
if (!rawDag || typeof rawDag !== "object")
|
|
@@ -7243,7 +7517,7 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
7243
7517
|
return {
|
|
7244
7518
|
name: "package_dependencies",
|
|
7245
7519
|
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.",
|
|
7246
|
-
schema:
|
|
7520
|
+
schema: argsSchema11,
|
|
7247
7521
|
annotations: { readOnlyHint: true },
|
|
7248
7522
|
handler: async ({ registry, package_name, version: version2, include_transitive, max_depth }, _extra) => {
|
|
7249
7523
|
return withErrorHandling("fetch package dependencies", async () => {
|
|
@@ -7281,42 +7555,6 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
7281
7555
|
}
|
|
7282
7556
|
};
|
|
7283
7557
|
}
|
|
7284
|
-
// src/tools/package-imports.ts
|
|
7285
|
-
import { z as z12 } from "zod";
|
|
7286
|
-
var argsSchema11 = {
|
|
7287
|
-
registry: schemas.registry,
|
|
7288
|
-
package_name: schemas.packageName.describe("Name of the package to get imports for"),
|
|
7289
|
-
file_path: z12.string().max(1000).optional().describe("Filter to a specific file path"),
|
|
7290
|
-
resolved_only: z12.boolean().optional().describe("Only return imports resolved to a known package"),
|
|
7291
|
-
limit: z12.coerce.number().int().min(1).max(500).optional().describe("Max imports to return"),
|
|
7292
|
-
version: schemas.version,
|
|
7293
|
-
mode: schemas.navigationMode,
|
|
7294
|
-
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7295
|
-
};
|
|
7296
|
-
function createPackageImportsTool(pkgseerService) {
|
|
7297
|
-
return {
|
|
7298
|
-
name: "package_imports",
|
|
7299
|
-
description: "See what a dependency imports — understand its internal dependencies and external package usage. " + "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.",
|
|
7300
|
-
schema: argsSchema11,
|
|
7301
|
-
annotations: { readOnlyHint: true },
|
|
7302
|
-
handler: async (args, _extra) => {
|
|
7303
|
-
return withErrorHandling("fetch package imports", async () => {
|
|
7304
|
-
const result = await pkgseerService.packageImports(toGraphQLRegistry(args.registry), args.package_name, {
|
|
7305
|
-
filePath: args.file_path,
|
|
7306
|
-
resolvedOnly: args.resolved_only,
|
|
7307
|
-
limit: args.limit,
|
|
7308
|
-
version: args.version,
|
|
7309
|
-
mode: toNavigationMode(args.mode),
|
|
7310
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7311
|
-
});
|
|
7312
|
-
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7313
|
-
if (graphqlError)
|
|
7314
|
-
return graphqlError;
|
|
7315
|
-
return textResult(JSON.stringify(result.data.packageImports, null, 2));
|
|
7316
|
-
});
|
|
7317
|
-
}
|
|
7318
|
-
};
|
|
7319
|
-
}
|
|
7320
7558
|
// src/tools/package-quality.ts
|
|
7321
7559
|
var argsSchema12 = {
|
|
7322
7560
|
registry: schemas.registry,
|
|
@@ -7394,23 +7632,67 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
|
7394
7632
|
}
|
|
7395
7633
|
};
|
|
7396
7634
|
}
|
|
7397
|
-
// src/tools/
|
|
7635
|
+
// src/tools/read-file.ts
|
|
7398
7636
|
import { z as z13 } from "zod";
|
|
7399
|
-
var packageInputSchema2 = z13.object({
|
|
7400
|
-
registry: schemas.registry,
|
|
7401
|
-
name: z13.string().min(1).describe("Package name"),
|
|
7402
|
-
version: z13.string().optional().describe("Specific version (defaults to latest)")
|
|
7403
|
-
});
|
|
7404
7637
|
var argsSchema15 = {
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7638
|
+
target: schemas.codeTarget,
|
|
7639
|
+
file_path: z13.string({
|
|
7640
|
+
error: "file_path is required. Get file paths from find_symbol (returns file locations) " + "or list_files (browse file structure)."
|
|
7641
|
+
}).min(1).describe("Path to file in repository. Example: src/router/index.js"),
|
|
7642
|
+
start_line: z13.coerce.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
|
|
7643
|
+
end_line: z13.coerce.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file."),
|
|
7644
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7645
|
+
};
|
|
7646
|
+
function createReadFileTool(pkgseerService) {
|
|
7647
|
+
return {
|
|
7648
|
+
name: "read_file",
|
|
7649
|
+
description: "Read source code from a dependency's repository by file path and line range — " + "use when you have a file path from a stack trace or symbol lookup. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns full file or a specific line range. " + "Prefer find_symbol(include_code=true) for function/class lookup. " + "Use list_files to discover file paths. " + "With repo scope, operates on the full repository. " + "With package scope, scoped to the package subdirectory in monorepos.",
|
|
7650
|
+
schema: argsSchema15,
|
|
7651
|
+
annotations: { readOnlyHint: true },
|
|
7652
|
+
handler: async (args, _extra) => {
|
|
7653
|
+
return withErrorHandling("read file", async () => {
|
|
7654
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7655
|
+
if (isToolError(resolved))
|
|
7656
|
+
return resolved;
|
|
7657
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7658
|
+
const result = await pkgseerService.fetchCodeContext(tv.repoUrl, tv.gitRef, args.file_path, {
|
|
7659
|
+
startLine: args.start_line,
|
|
7660
|
+
endLine: args.end_line,
|
|
7661
|
+
registry: tv.registry,
|
|
7662
|
+
packageName: tv.packageName,
|
|
7663
|
+
version: tv.version,
|
|
7664
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7665
|
+
});
|
|
7666
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7667
|
+
if (graphqlError)
|
|
7668
|
+
return graphqlError;
|
|
7669
|
+
if (!result.data?.fetchCodeContext) {
|
|
7670
|
+
return errorResult(`File not found: ${args.file_path}. ` + "Check that the file path and target are correct. " + "Use list_files to discover available files.");
|
|
7671
|
+
}
|
|
7672
|
+
return textResult(JSON.stringify(result.data.fetchCodeContext, null, 2));
|
|
7673
|
+
});
|
|
7674
|
+
}
|
|
7675
|
+
};
|
|
7676
|
+
}
|
|
7677
|
+
// src/tools/search.ts
|
|
7678
|
+
import { z as z14 } from "zod";
|
|
7679
|
+
var targetInputSchema = z14.object({
|
|
7680
|
+
registry: z14.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (npm, pypi, hex, etc.). Required for package scope."),
|
|
7681
|
+
package_name: z14.string().min(1).optional().describe("Package name. Required for package scope."),
|
|
7682
|
+
version: z14.string().optional().describe("Specific version (defaults to latest). Package scope only."),
|
|
7683
|
+
repo_url: z14.string().optional().describe("Repository URL (GitHub). Required for repo scope. Example: https://github.com/expressjs/express"),
|
|
7684
|
+
git_ref: z14.string().optional().describe("Git ref — tag, branch, or commit. Required for repo scope. Use HEAD for latest.")
|
|
7685
|
+
}).describe("Search target: provide registry + package_name (package scope) OR repo_url + git_ref (repo scope).");
|
|
7686
|
+
var argsSchema16 = {
|
|
7687
|
+
targets: z14.array(targetInputSchema, {
|
|
7688
|
+
error: 'targets is required. Provide 1-20 targets as [{registry: "npm", package_name: "express"}] ' + 'or [{repo_url: "https://github.com/user/repo", git_ref: "HEAD"}]. ' + "Use package_summary to verify a package exists. " + "For project-wide doc search without specifying targets, use search_project_docs instead."
|
|
7689
|
+
}).min(1).max(20).describe("Targets to search (1-20). Each uses registry + package_name (package scope) or repo_url + git_ref (repo scope)."),
|
|
7690
|
+
query: z14.string({
|
|
7409
7691
|
error: "query is required. Provide search terms as natural language or keywords, " + "e.g., 'error handling middleware'."
|
|
7410
7692
|
}).min(1).describe("Search query - natural language or keywords"),
|
|
7411
|
-
mode:
|
|
7412
|
-
limit:
|
|
7413
|
-
|
|
7693
|
+
mode: z14.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
|
|
7694
|
+
limit: z14.coerce.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
|
|
7695
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7414
7696
|
};
|
|
7415
7697
|
function toSearchMode2(mode) {
|
|
7416
7698
|
if (!mode)
|
|
@@ -7422,6 +7704,47 @@ function toSearchMode2(mode) {
|
|
|
7422
7704
|
};
|
|
7423
7705
|
return map[mode.toLowerCase()];
|
|
7424
7706
|
}
|
|
7707
|
+
function validateAndConvertTargets(targets) {
|
|
7708
|
+
const inputs = [];
|
|
7709
|
+
for (let i = 0;i < targets.length; i++) {
|
|
7710
|
+
const t = targets[i];
|
|
7711
|
+
const hasPackage = t.registry || t.package_name;
|
|
7712
|
+
const hasRepo = t.repo_url || t.git_ref;
|
|
7713
|
+
if (hasPackage && hasRepo) {
|
|
7714
|
+
return {
|
|
7715
|
+
error: `Target ${i + 1}: provide either registry + package_name or repo_url + git_ref, not both.`
|
|
7716
|
+
};
|
|
7717
|
+
}
|
|
7718
|
+
if (!hasPackage && !hasRepo) {
|
|
7719
|
+
return {
|
|
7720
|
+
error: `Target ${i + 1}: provide registry + package_name (package scope) or repo_url + git_ref (repo scope).`
|
|
7721
|
+
};
|
|
7722
|
+
}
|
|
7723
|
+
if (hasPackage) {
|
|
7724
|
+
if (!t.registry || !t.package_name) {
|
|
7725
|
+
return {
|
|
7726
|
+
error: `Target ${i + 1}: both registry and package_name are required for package scope.`
|
|
7727
|
+
};
|
|
7728
|
+
}
|
|
7729
|
+
inputs.push({
|
|
7730
|
+
registry: toGraphQLRegistry(t.registry),
|
|
7731
|
+
name: t.package_name,
|
|
7732
|
+
version: t.version
|
|
7733
|
+
});
|
|
7734
|
+
} else {
|
|
7735
|
+
if (!t.repo_url || !t.git_ref) {
|
|
7736
|
+
return {
|
|
7737
|
+
error: `Target ${i + 1}: both repo_url and git_ref are required for repo scope.`
|
|
7738
|
+
};
|
|
7739
|
+
}
|
|
7740
|
+
inputs.push({
|
|
7741
|
+
repoUrl: t.repo_url,
|
|
7742
|
+
gitRef: t.git_ref
|
|
7743
|
+
});
|
|
7744
|
+
}
|
|
7745
|
+
}
|
|
7746
|
+
return { inputs };
|
|
7747
|
+
}
|
|
7425
7748
|
function formatIndexingWarnings2(indexingStatus) {
|
|
7426
7749
|
if (!indexingStatus || indexingStatus.length === 0)
|
|
7427
7750
|
return null;
|
|
@@ -7440,7 +7763,7 @@ function formatIndexingWarnings2(indexingStatus) {
|
|
|
7440
7763
|
if (warnings.length === 0)
|
|
7441
7764
|
return null;
|
|
7442
7765
|
return `
|
|
7443
|
-
Note: Some
|
|
7766
|
+
Note: Some targets are not fully indexed:
|
|
7444
7767
|
` + warnings.join(`
|
|
7445
7768
|
`) + `
|
|
7446
7769
|
Results may be incomplete. Retry later for more complete results.`;
|
|
@@ -7448,38 +7771,37 @@ Results may be incomplete. Retry later for more complete results.`;
|
|
|
7448
7771
|
function createSearchTool(pkgseerService) {
|
|
7449
7772
|
return {
|
|
7450
7773
|
name: "search",
|
|
7451
|
-
description: "Search code and documentation across packages using full-text search. " + "Returns code chunks and doc pages matching your query with relevance scores and snippets. " + "Use mode='code' for code only, mode='docs' for docs only, or mode='all' (default). " + "Provide 1-20
|
|
7452
|
-
schema:
|
|
7774
|
+
description: "Search code and documentation across packages or repositories using full-text search. " + "Returns code chunks and doc pages matching your query with relevance scores and snippets. " + "Each target can use package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Use mode='code' for code only, mode='docs' for docs only, or mode='all' (default). " + "Provide 1-20 targets. For symbol-level results that feed into symbol_callers/symbol_callees, " + "use search_symbols instead. " + "For full source of code results, use find_symbol(name=<title>, include_code=true). " + "Code results include repoUrl and filePath for use with fetch_code_context. " + "If targets need indexing, waits up to wait_timeout_ms (default 10s) or returns searchRef — use search_status to poll.",
|
|
7775
|
+
schema: argsSchema16,
|
|
7453
7776
|
annotations: { readOnlyHint: true },
|
|
7454
|
-
handler: async ({
|
|
7455
|
-
return withErrorHandling("search
|
|
7777
|
+
handler: async ({ targets, query, mode, limit, wait_timeout_ms }, _extra) => {
|
|
7778
|
+
return withErrorHandling("search", async () => {
|
|
7456
7779
|
const normalizedQuery = query.trim();
|
|
7457
7780
|
if (normalizedQuery.length === 0) {
|
|
7458
7781
|
return errorResult("Search query is required.");
|
|
7459
7782
|
}
|
|
7460
|
-
const
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
const result = await pkgseerService.combinedSearch(graphqlPackages, normalizedQuery, {
|
|
7783
|
+
const validated = validateAndConvertTargets(targets);
|
|
7784
|
+
if ("error" in validated) {
|
|
7785
|
+
return errorResult(validated.error);
|
|
7786
|
+
}
|
|
7787
|
+
const result = await pkgseerService.combinedSearch(validated.inputs, normalizedQuery, {
|
|
7466
7788
|
mode: toSearchMode2(mode),
|
|
7467
7789
|
limit,
|
|
7468
|
-
waitTimeoutMs:
|
|
7790
|
+
waitTimeoutMs: wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7469
7791
|
});
|
|
7470
7792
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7471
7793
|
if (graphqlError)
|
|
7472
7794
|
return graphqlError;
|
|
7473
7795
|
const asyncResult = result.data?.combinedSearch;
|
|
7474
7796
|
if (!asyncResult) {
|
|
7475
|
-
return errorResult("No search results returned. Check
|
|
7797
|
+
return errorResult("No search results returned. Check target names and registries.");
|
|
7476
7798
|
}
|
|
7477
7799
|
if (!asyncResult.completed) {
|
|
7478
7800
|
const progressInfo = {
|
|
7479
7801
|
completed: false,
|
|
7480
7802
|
searchRef: asyncResult.searchRef,
|
|
7481
7803
|
progress: asyncResult.progress,
|
|
7482
|
-
message: "Search is still indexing.
|
|
7804
|
+
message: "Search is still indexing. Use search_status with the searchRef to poll, " + "or retry with a longer wait_timeout_ms."
|
|
7483
7805
|
};
|
|
7484
7806
|
return textResult(JSON.stringify(progressInfo, null, 2));
|
|
7485
7807
|
}
|
|
@@ -7489,7 +7811,7 @@ function createSearchTool(pkgseerService) {
|
|
|
7489
7811
|
}
|
|
7490
7812
|
const entries = searchResult.entries ?? [];
|
|
7491
7813
|
if (entries.length === 0) {
|
|
7492
|
-
return errorResult(`No results found for "${normalizedQuery}". ` + "Try broader terms or different
|
|
7814
|
+
return errorResult(`No results found for "${normalizedQuery}". ` + "Try broader terms or different targets.");
|
|
7493
7815
|
}
|
|
7494
7816
|
let response = JSON.stringify(searchResult, null, 2);
|
|
7495
7817
|
const indexingWarning = formatIndexingWarnings2(searchResult.indexingStatus);
|
|
@@ -7502,21 +7824,21 @@ function createSearchTool(pkgseerService) {
|
|
|
7502
7824
|
};
|
|
7503
7825
|
}
|
|
7504
7826
|
// src/tools/search-project-docs.ts
|
|
7505
|
-
import { z as
|
|
7506
|
-
var
|
|
7507
|
-
project_directory:
|
|
7508
|
-
project:
|
|
7509
|
-
terms:
|
|
7510
|
-
match_mode:
|
|
7511
|
-
include_snippets:
|
|
7512
|
-
limit:
|
|
7827
|
+
import { z as z15 } from "zod";
|
|
7828
|
+
var argsSchema17 = {
|
|
7829
|
+
project_directory: z15.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."),
|
|
7830
|
+
project: z15.string().optional().describe("Project name to search. Overrides value from pkgseer.yml if provided."),
|
|
7831
|
+
terms: z15.array(z15.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
|
|
7832
|
+
match_mode: z15.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
|
|
7833
|
+
include_snippets: z15.boolean().optional().describe("Include content excerpts around matches"),
|
|
7834
|
+
limit: z15.coerce.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
|
|
7513
7835
|
};
|
|
7514
7836
|
function createSearchProjectDocsTool(deps) {
|
|
7515
7837
|
const { pkgseerService, configService, defaultProjectDir } = deps;
|
|
7516
7838
|
return {
|
|
7517
7839
|
name: "search_project_docs",
|
|
7518
7840
|
description: "Search documentation across all dependencies in a PkgSeer project — " + "use when you need to find information but don't know which dependency has it. " + "Requires a pkgseer.yml project config (or pass project name directly). " + "Returns ranked results with snippets from multiple packages. " + "Use project_directory to specify which project's context to use. " + "For single-package doc search, use search(mode='docs') instead.",
|
|
7519
|
-
schema:
|
|
7841
|
+
schema: argsSchema17,
|
|
7520
7842
|
annotations: { readOnlyHint: true },
|
|
7521
7843
|
handler: async ({
|
|
7522
7844
|
project_directory,
|
|
@@ -7565,15 +7887,15 @@ function createSearchProjectDocsTool(deps) {
|
|
|
7565
7887
|
};
|
|
7566
7888
|
}
|
|
7567
7889
|
// src/tools/search-status.ts
|
|
7568
|
-
import { z as
|
|
7569
|
-
var
|
|
7570
|
-
searchRef:
|
|
7890
|
+
import { z as z16 } from "zod";
|
|
7891
|
+
var argsSchema18 = {
|
|
7892
|
+
searchRef: z16.string().min(1).describe("Search reference from a previous incomplete search")
|
|
7571
7893
|
};
|
|
7572
7894
|
function createSearchStatusTool(pkgseerService) {
|
|
7573
7895
|
return {
|
|
7574
7896
|
name: "search_status",
|
|
7575
7897
|
description: "Check the status of an async search and get results if complete. " + "Use after search returns completed=false with a searchRef. Sessions expire after 1 hour. " + "Returns status (PENDING, INDEXING, SEARCHING, COMPLETED, TIMEOUT, FAILED), " + "progress info (packagesReady/packagesTotal), and results when COMPLETED.",
|
|
7576
|
-
schema:
|
|
7898
|
+
schema: argsSchema18,
|
|
7577
7899
|
annotations: { readOnlyHint: true },
|
|
7578
7900
|
handler: async ({ searchRef }, _extra) => {
|
|
7579
7901
|
return withErrorHandling("check search status", async () => {
|
|
@@ -7615,14 +7937,13 @@ function createSearchStatusTool(pkgseerService) {
|
|
|
7615
7937
|
};
|
|
7616
7938
|
}
|
|
7617
7939
|
// src/tools/search-symbols.ts
|
|
7618
|
-
import { z as
|
|
7619
|
-
var
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
kind: z16.enum([
|
|
7940
|
+
import { z as z17 } from "zod";
|
|
7941
|
+
var argsSchema19 = {
|
|
7942
|
+
target: schemas.codeTarget,
|
|
7943
|
+
query: z17.string().max(500).optional().describe("Search query for full-text code search (max 500 chars). Required if keywords not provided."),
|
|
7944
|
+
keywords: z17.array(z17.string()).max(20).optional().describe("Search keywords (max 20). Combined using match_mode. Alternative to query."),
|
|
7945
|
+
match_mode: z17.enum(["or", "and"]).optional().describe("How to combine keywords: or (any match) or and (all must match)"),
|
|
7946
|
+
kind: z17.enum([
|
|
7626
7947
|
"function",
|
|
7627
7948
|
"method",
|
|
7628
7949
|
"class",
|
|
@@ -7631,30 +7952,35 @@ var argsSchema18 = {
|
|
|
7631
7952
|
"type",
|
|
7632
7953
|
"doc_section"
|
|
7633
7954
|
]).optional().describe("Filter results by code chunk type"),
|
|
7634
|
-
file_path:
|
|
7635
|
-
|
|
7636
|
-
limit: z16.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
|
|
7955
|
+
file_path: z17.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
|
|
7956
|
+
limit: z17.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
|
|
7637
7957
|
mode: schemas.navigationMode,
|
|
7638
7958
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7639
7959
|
};
|
|
7640
7960
|
function createSearchSymbolsTool(pkgseerService) {
|
|
7641
7961
|
return {
|
|
7642
7962
|
name: "search_symbols",
|
|
7643
|
-
description: "Search a dependency's source code by text using the code navigation index — " + "find where error messages, exceptions, or patterns appear across functions, classes, and modules. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns symbol-level results that can feed directly into symbol_callers, symbol_callees, or call_path. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source. " + "For free-form text search across multiple packages, use search(mode='code') instead.",
|
|
7644
|
-
schema:
|
|
7963
|
+
description: "Search a dependency's source code by text using the code navigation index — " + "find where error messages, exceptions, or patterns appear across functions, classes, and modules. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns symbol-level results that can feed directly into symbol_callers, symbol_callees, or call_path. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source. " + "For free-form text search across multiple packages, use search(mode='code') instead.",
|
|
7964
|
+
schema: argsSchema19,
|
|
7645
7965
|
annotations: { readOnlyHint: true },
|
|
7646
7966
|
handler: async (args, _extra) => {
|
|
7647
7967
|
return withErrorHandling("search symbols", async () => {
|
|
7648
|
-
const
|
|
7968
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7969
|
+
if (isToolError(resolved))
|
|
7970
|
+
return resolved;
|
|
7971
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7972
|
+
const result = await pkgseerService.searchSymbols(tv.registry, tv.packageName, {
|
|
7649
7973
|
query: args.query,
|
|
7650
7974
|
keywords: args.keywords,
|
|
7651
7975
|
matchMode: toMatchMode(args.match_mode),
|
|
7652
7976
|
kind: toSymbolKind(args.kind),
|
|
7653
7977
|
filePath: args.file_path,
|
|
7654
|
-
version:
|
|
7978
|
+
version: tv.version,
|
|
7655
7979
|
limit: args.limit,
|
|
7656
7980
|
mode: toNavigationMode(args.mode),
|
|
7657
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7981
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7982
|
+
repoUrl: tv.repoUrl,
|
|
7983
|
+
gitRef: tv.gitRef
|
|
7658
7984
|
});
|
|
7659
7985
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7660
7986
|
if (graphqlError)
|
|
@@ -7676,27 +8002,27 @@ function createSearchSymbolsTool(pkgseerService) {
|
|
|
7676
8002
|
};
|
|
7677
8003
|
}
|
|
7678
8004
|
// src/tools/symbol-callees.ts
|
|
7679
|
-
import { z as
|
|
7680
|
-
var
|
|
7681
|
-
symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide
|
|
7682
|
-
max_depth:
|
|
7683
|
-
limit:
|
|
7684
|
-
include_external:
|
|
7685
|
-
include_builtins:
|
|
8005
|
+
import { z as z18 } from "zod";
|
|
8006
|
+
var argsSchema20 = {
|
|
8007
|
+
symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
|
|
8008
|
+
max_depth: z18.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
|
|
8009
|
+
limit: z18.coerce.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
|
|
8010
|
+
include_external: z18.boolean().optional().describe("Include calls to symbols in other indexed packages. " + "Default (false) shows only calls within the same package."),
|
|
8011
|
+
include_builtins: z18.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
|
|
7686
8012
|
mode: schemas.navigationMode,
|
|
7687
8013
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7688
8014
|
};
|
|
7689
8015
|
function createSymbolCalleesTool(pkgseerService) {
|
|
7690
8016
|
return {
|
|
7691
8017
|
name: "symbol_callees",
|
|
7692
|
-
description: "Trace what a function calls internally — " + "understand dependency behavior by following its execution path. " + "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. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callers for the reverse.",
|
|
7693
|
-
schema:
|
|
8018
|
+
description: "Trace what a function calls internally — " + "understand dependency behavior by following its execution path. " + "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. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callers for the reverse.",
|
|
8019
|
+
schema: argsSchema20,
|
|
7694
8020
|
annotations: { readOnlyHint: true },
|
|
7695
8021
|
handler: async (args, _extra) => {
|
|
7696
8022
|
return withErrorHandling("find symbol callees", async () => {
|
|
7697
8023
|
const symbolInput = toSymbolReferenceInput(args.symbol);
|
|
7698
|
-
if (!symbolInput.symbolRef && (
|
|
7699
|
-
return errorResult("Provide
|
|
8024
|
+
if (!symbolInput.symbolRef && !(symbolInput.symbolName && symbolInput.registry && symbolInput.packageName) && !(symbolInput.symbolName && symbolInput.repoUrl && symbolInput.gitRef)) {
|
|
8025
|
+
return errorResult("Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
7700
8026
|
}
|
|
7701
8027
|
const result = await pkgseerService.symbolDependencies(symbolInput, {
|
|
7702
8028
|
maxDepth: args.max_depth,
|
|
@@ -7715,26 +8041,26 @@ function createSymbolCalleesTool(pkgseerService) {
|
|
|
7715
8041
|
};
|
|
7716
8042
|
}
|
|
7717
8043
|
// src/tools/symbol-callers.ts
|
|
7718
|
-
import { z as
|
|
7719
|
-
var
|
|
7720
|
-
symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide
|
|
7721
|
-
same_package_only:
|
|
7722
|
-
max_depth:
|
|
7723
|
-
limit:
|
|
8044
|
+
import { z as z19 } from "zod";
|
|
8045
|
+
var argsSchema21 = {
|
|
8046
|
+
symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
|
|
8047
|
+
same_package_only: z19.boolean().optional().describe("Only return callers from the same package. " + "Default (false) includes callers from other indexed packages."),
|
|
8048
|
+
max_depth: z19.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
|
|
8049
|
+
limit: z19.coerce.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
|
|
7724
8050
|
mode: schemas.navigationMode,
|
|
7725
8051
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7726
8052
|
};
|
|
7727
8053
|
function createSymbolCallersTool(pkgseerService) {
|
|
7728
8054
|
return {
|
|
7729
8055
|
name: "symbol_callers",
|
|
7730
|
-
description: "Trace what calls a function in a dependency's source code — " + "find entry points or debug why behavior triggers. " + "Returns callers with file locations and call line numbers. " + "Use same_package_only for within-package callers only. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callees for the reverse. " + "Use find_symbol(include_code=true) on any caller to read its source.",
|
|
7731
|
-
schema:
|
|
8056
|
+
description: "Trace what calls a function in a dependency's source code — " + "find entry points or debug why behavior triggers. " + "Returns callers with file locations and call line numbers. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Use same_package_only for within-package callers only. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callees for the reverse. " + "Use find_symbol(include_code=true) on any caller to read its source.",
|
|
8057
|
+
schema: argsSchema21,
|
|
7732
8058
|
annotations: { readOnlyHint: true },
|
|
7733
8059
|
handler: async (args, _extra) => {
|
|
7734
8060
|
return withErrorHandling("find symbol callers", async () => {
|
|
7735
8061
|
const symbolInput = toSymbolReferenceInput(args.symbol);
|
|
7736
|
-
if (!symbolInput.symbolRef && (
|
|
7737
|
-
return errorResult("Provide
|
|
8062
|
+
if (!symbolInput.symbolRef && !(symbolInput.symbolName && symbolInput.registry && symbolInput.packageName) && !(symbolInput.symbolName && symbolInput.repoUrl && symbolInput.gitRef)) {
|
|
8063
|
+
return errorResult("Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
7738
8064
|
}
|
|
7739
8065
|
const result = await pkgseerService.symbolDependents(symbolInput, {
|
|
7740
8066
|
samePackageOnly: args.same_package_only,
|
|
@@ -7752,26 +8078,26 @@ function createSymbolCallersTool(pkgseerService) {
|
|
|
7752
8078
|
};
|
|
7753
8079
|
}
|
|
7754
8080
|
// src/tools/trigger-indexing.ts
|
|
7755
|
-
import { z as
|
|
7756
|
-
var
|
|
8081
|
+
import { z as z20 } from "zod";
|
|
8082
|
+
var packageInputSchema2 = z20.object({
|
|
7757
8083
|
registry: schemas.registry,
|
|
7758
|
-
name:
|
|
7759
|
-
version:
|
|
8084
|
+
name: z20.string().max(255).describe("Package name"),
|
|
8085
|
+
version: z20.string().max(100).optional().describe("Specific version to index")
|
|
7760
8086
|
});
|
|
7761
|
-
var repositoryInputSchema =
|
|
7762
|
-
url:
|
|
7763
|
-
ref:
|
|
7764
|
-
discover_packages:
|
|
8087
|
+
var repositoryInputSchema = z20.object({
|
|
8088
|
+
url: z20.string().max(2000).describe("GitHub repository URL"),
|
|
8089
|
+
ref: z20.string().max(200).optional().describe("Git ref to index (tag, branch, commit). Defaults to HEAD"),
|
|
8090
|
+
discover_packages: z20.boolean().optional().describe("If true, discover packages published from this repo and trigger their metadata fetch")
|
|
7765
8091
|
});
|
|
7766
|
-
var
|
|
7767
|
-
packages:
|
|
7768
|
-
repositories:
|
|
8092
|
+
var argsSchema22 = {
|
|
8093
|
+
packages: z20.array(packageInputSchema2).max(100).optional().describe("Package versions to index (max 100)"),
|
|
8094
|
+
repositories: z20.array(repositoryInputSchema).max(50).optional().describe("Repository URLs to index (max 50)")
|
|
7769
8095
|
};
|
|
7770
8096
|
function createTriggerIndexingTool(pkgseerService) {
|
|
7771
8097
|
return {
|
|
7772
8098
|
name: "trigger_indexing",
|
|
7773
8099
|
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 or doc requests to ensure packages are indexed. " + "Code tools auto-wait via wait_timeout_ms on subsequent calls. Most packages index within 10-30s. " + "Rate limited to 10 requests per minute.",
|
|
7774
|
-
schema:
|
|
8100
|
+
schema: argsSchema22,
|
|
7775
8101
|
annotations: { readOnlyHint: false, idempotentHint: true },
|
|
7776
8102
|
handler: async (args, _extra) => {
|
|
7777
8103
|
return withErrorHandling("trigger indexing", async () => {
|
|
@@ -7809,14 +8135,13 @@ function createTriggerIndexingTool(pkgseerService) {
|
|
|
7809
8135
|
};
|
|
7810
8136
|
}
|
|
7811
8137
|
// src/tools/version-diff.ts
|
|
7812
|
-
import { z as
|
|
7813
|
-
var
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
kind: z20.enum([
|
|
8138
|
+
import { z as z21 } from "zod";
|
|
8139
|
+
var argsSchema23 = {
|
|
8140
|
+
target: schemas.codeTarget,
|
|
8141
|
+
from_version: z21.string().max(100).describe("Source version (git ref, e.g., 'v4.18.2')"),
|
|
8142
|
+
to_version: z21.string().max(100).describe("Target version (git ref, e.g., 'v5.0.0')"),
|
|
8143
|
+
include_private: z21.boolean().optional().describe("Include private/non-exported symbols in the diff"),
|
|
8144
|
+
kind: z21.enum([
|
|
7820
8145
|
"function",
|
|
7821
8146
|
"method",
|
|
7822
8147
|
"class",
|
|
@@ -7825,22 +8150,28 @@ var argsSchema22 = {
|
|
|
7825
8150
|
"type",
|
|
7826
8151
|
"doc_section"
|
|
7827
8152
|
]).optional().describe("Filter by symbol kind"),
|
|
7828
|
-
limit:
|
|
8153
|
+
limit: z21.coerce.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
|
|
7829
8154
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7830
8155
|
};
|
|
7831
8156
|
function createVersionDiffTool(pkgseerService) {
|
|
7832
8157
|
return {
|
|
7833
8158
|
name: "version_diff",
|
|
7834
|
-
description: "Compare two versions of a dependency to understand what changed — " + "use when debugging issues after upgrades or planning migrations. " + "Detects added, removed, moved, and modified symbols with severity " + "(breaking, behavior_change, non_breaking, internal). " + "Returns summary counts and per-symbol changes with file locations.",
|
|
7835
|
-
schema:
|
|
8159
|
+
description: "Compare two versions of a dependency to understand what changed — " + "use when debugging issues after upgrades or planning migrations. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "With repo scope, from_version and to_version are literal git refs (tags, branches, commits) — " + "the backend does not normalize them. Use target.git_ref=HEAD to identify the repository. " + "Detects added, removed, moved, and modified symbols with severity " + "(breaking, behavior_change, non_breaking, internal). " + "Returns summary counts and per-symbol changes with file locations.",
|
|
8160
|
+
schema: argsSchema23,
|
|
7836
8161
|
annotations: { readOnlyHint: true },
|
|
7837
8162
|
handler: async (args, _extra) => {
|
|
7838
8163
|
return withErrorHandling("version diff", async () => {
|
|
7839
|
-
const
|
|
8164
|
+
const resolved = resolveCodeTarget(args.target);
|
|
8165
|
+
if (isToolError(resolved))
|
|
8166
|
+
return resolved;
|
|
8167
|
+
const tv = buildCodeTargetVars(resolved);
|
|
8168
|
+
const result = await pkgseerService.versionDiff(tv.registry, tv.packageName, args.from_version, args.to_version, {
|
|
7840
8169
|
includePrivate: args.include_private,
|
|
7841
8170
|
kind: toSymbolKind(args.kind),
|
|
7842
8171
|
limit: args.limit,
|
|
7843
|
-
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
8172
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
8173
|
+
repoUrl: tv.repoUrl,
|
|
8174
|
+
gitRef: tv.gitRef
|
|
7844
8175
|
});
|
|
7845
8176
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7846
8177
|
if (graphqlError)
|
|
@@ -7861,9 +8192,17 @@ Use PkgSeer when:
|
|
|
7861
8192
|
- You need to understand what changed between package versions
|
|
7862
8193
|
|
|
7863
8194
|
Instead of guessing library behavior from training data, use find_symbol(include_code=true) to read actual source.
|
|
7864
|
-
Instead of cloning repos to search code, use search_symbols or
|
|
8195
|
+
Instead of cloning repos to search code, use search_symbols or grep_file.
|
|
7865
8196
|
Instead of manually tracing call chains on GitHub, use symbol_callers and symbol_callees.
|
|
7866
8197
|
|
|
8198
|
+
Dual addressing — code tools accept a target object with two modes:
|
|
8199
|
+
- Package scope: target: { registry: "npm", package_name: "express" } (optional version)
|
|
8200
|
+
In monorepos, results are scoped to the package's subdirectory.
|
|
8201
|
+
- Repo scope: target: { repo_url: "https://github.com/expressjs/express", git_ref: "v4.18.2" }
|
|
8202
|
+
Operates on the full repository, not filtered to a package subdirectory.
|
|
8203
|
+
|
|
8204
|
+
Use package scope when you know the package name. Use repo scope when you have a repo URL (e.g., from package_summary) and need full-repo access or the repo isn't published as a package.
|
|
8205
|
+
|
|
7867
8206
|
Data availability — tools are grouped by what backend data they need:
|
|
7868
8207
|
|
|
7869
8208
|
1. Registry metadata (available immediately, no indexing):
|
|
@@ -7874,33 +8213,32 @@ Data availability — tools are grouped by what backend data they need:
|
|
|
7874
8213
|
list_package_docs, fetch_package_doc, search(mode='docs'), search_project_docs
|
|
7875
8214
|
If results are empty, docs may not be crawled yet — use trigger_indexing first, then retry.
|
|
7876
8215
|
|
|
7877
|
-
3.
|
|
8216
|
+
3. Code navigation (requires code repo indexing, dual addressing via target):
|
|
7878
8217
|
find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path,
|
|
7879
|
-
|
|
7880
|
-
These wait up to wait_timeout_ms (default 10s) for indexing. If indexing takes longer,
|
|
7881
|
-
|
|
7882
|
-
4. Repository (full repo scope, not package-filtered):
|
|
7883
|
-
fetch_code_context
|
|
7884
|
-
Uses repo_url (get from package_summary) + git_ref (version tag) + file_path. Operates on the full repository, not filtered to a package subdirectory.
|
|
8218
|
+
list_imports, version_diff, list_files, grep_file, read_file, search(mode='code')
|
|
8219
|
+
These wait up to wait_timeout_ms (default 10s) for indexing. If indexing takes longer, the response includes an indexingRef — use indexing_status to poll progress, then retry the original query when status is INDEXED.
|
|
7885
8220
|
|
|
7886
|
-
|
|
7887
|
-
|
|
8221
|
+
Symbol reference tools (symbol_callers, symbol_callees, call_path) accept a symbol object with either:
|
|
8222
|
+
- symbol_ref from a previous find_symbol/search_symbols result (preferred, fastest)
|
|
8223
|
+
- Package lookup: registry + package_name + symbol_name
|
|
8224
|
+
- Repo lookup: repo_url + git_ref + symbol_name
|
|
8225
|
+
symbol_callers/symbol_callees can show cross-package results from other indexed packages.
|
|
7888
8226
|
|
|
7889
8227
|
Choosing a code search tool:
|
|
7890
8228
|
- search_symbols: single package, symbol-level → results feed symbol_callers/callees/call_path
|
|
7891
8229
|
- search(mode='code'): multi-package, full-text → code chunks with snippets
|
|
7892
|
-
-
|
|
8230
|
+
- grep_file: single file, pattern match → when you know the file path
|
|
7893
8231
|
|
|
7894
|
-
Utility: trigger_indexing (pre-warm indexes), search_status (poll async search).
|
|
8232
|
+
Utility: trigger_indexing (pre-warm indexes), search_status (poll async search), indexing_status (poll navigation indexing).
|
|
7895
8233
|
|
|
7896
|
-
Quick start: find_symbol(registry
|
|
8234
|
+
Quick start: find_symbol(target={registry:"npm", package_name:"<pkg>"}, name="<function>", include_code=true) often answers the question in one call.
|
|
7897
8235
|
|
|
7898
8236
|
Common workflows (pass symbolRef between tools for chaining):
|
|
7899
|
-
- Read source: find_symbol(name=<fn>, include_code=true)
|
|
8237
|
+
- Read source: find_symbol(target={registry, package_name}, name=<fn>, include_code=true)
|
|
7900
8238
|
- Trace calls: find_symbol → symbol_callees(symbol={symbol_ref: <symbolRef>})
|
|
7901
8239
|
- Find callers: find_symbol → symbol_callers(symbol={symbol_ref: <symbolRef>})
|
|
7902
|
-
- Read file:
|
|
7903
|
-
- Search code: search_symbols (single pkg, feeds callers/callees) or search(mode='code',
|
|
8240
|
+
- Read file: read_file(target={registry, package_name}, file_path=<path>) or read_file(target={repo_url, git_ref}, file_path=<path>)
|
|
8241
|
+
- Search code: search_symbols (single pkg, feeds callers/callees) or search(mode='code', targets=[...]) (multi-target)
|
|
7904
8242
|
- Browse docs: list_package_docs → fetch_package_doc(page_id)`;
|
|
7905
8243
|
var TOOL_FACTORIES = {
|
|
7906
8244
|
package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
|
|
@@ -7912,7 +8250,7 @@ var TOOL_FACTORIES = {
|
|
|
7912
8250
|
fetch_package_doc: ({ pkgseerService }) => createFetchPackageDocTool(pkgseerService),
|
|
7913
8251
|
search: ({ pkgseerService }) => createSearchTool(pkgseerService),
|
|
7914
8252
|
search_status: ({ pkgseerService }) => createSearchStatusTool(pkgseerService),
|
|
7915
|
-
|
|
8253
|
+
read_file: ({ pkgseerService }) => createReadFileTool(pkgseerService),
|
|
7916
8254
|
search_project_docs: ({ pkgseerService, configService, defaultProjectDir }) => createSearchProjectDocsTool({
|
|
7917
8255
|
pkgseerService,
|
|
7918
8256
|
configService,
|
|
@@ -7923,11 +8261,12 @@ var TOOL_FACTORIES = {
|
|
|
7923
8261
|
list_symbols: ({ pkgseerService }) => createListSymbolsTool(pkgseerService),
|
|
7924
8262
|
symbol_callers: ({ pkgseerService }) => createSymbolCallersTool(pkgseerService),
|
|
7925
8263
|
symbol_callees: ({ pkgseerService }) => createSymbolCalleesTool(pkgseerService),
|
|
7926
|
-
|
|
8264
|
+
list_imports: ({ pkgseerService }) => createListImportsTool(pkgseerService),
|
|
7927
8265
|
call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
|
|
7928
8266
|
trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService),
|
|
7929
|
-
|
|
7930
|
-
|
|
8267
|
+
indexing_status: ({ pkgseerService }) => createIndexingStatusTool(pkgseerService),
|
|
8268
|
+
list_files: ({ pkgseerService }) => createListFilesTool(pkgseerService),
|
|
8269
|
+
grep_file: ({ pkgseerService }) => createGrepFileTool(pkgseerService),
|
|
7931
8270
|
version_diff: ({ pkgseerService }) => createVersionDiffTool(pkgseerService)
|
|
7932
8271
|
};
|
|
7933
8272
|
var PUBLIC_READ_TOOLS = [
|
|
@@ -7940,24 +8279,25 @@ var PUBLIC_READ_TOOLS = [
|
|
|
7940
8279
|
"fetch_package_doc",
|
|
7941
8280
|
"search",
|
|
7942
8281
|
"search_status",
|
|
7943
|
-
"
|
|
8282
|
+
"read_file",
|
|
7944
8283
|
"find_symbol",
|
|
7945
8284
|
"search_symbols",
|
|
7946
8285
|
"list_symbols",
|
|
7947
8286
|
"symbol_callers",
|
|
7948
8287
|
"symbol_callees",
|
|
7949
|
-
"
|
|
8288
|
+
"list_imports",
|
|
7950
8289
|
"call_path",
|
|
7951
8290
|
"trigger_indexing",
|
|
7952
|
-
"
|
|
7953
|
-
"
|
|
8291
|
+
"indexing_status",
|
|
8292
|
+
"list_files",
|
|
8293
|
+
"grep_file",
|
|
7954
8294
|
"version_diff"
|
|
7955
8295
|
];
|
|
7956
8296
|
var PROJECT_READ_TOOLS = ["search_project_docs"];
|
|
7957
8297
|
var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
|
|
7958
8298
|
function createMcpServer(deps) {
|
|
7959
8299
|
const { pkgseerService, configService, config, fileSystemService } = deps;
|
|
7960
|
-
const server = new McpServer({ name: "pkgseer", version: "0.
|
|
8300
|
+
const server = new McpServer({ name: "pkgseer", version: "0.5.0" }, { instructions: PKGSEER_INSTRUCTIONS });
|
|
7961
8301
|
const defaultProjectDir = fileSystemService.getCwd();
|
|
7962
8302
|
const enabledToolNames = config.enabled_tools ?? ALL_TOOLS;
|
|
7963
8303
|
const toolsToRegister = enabledToolNames.filter((name) => ALL_TOOLS.includes(name));
|
|
@@ -8017,19 +8357,20 @@ function showMcpSetupInstructions(deps) {
|
|
|
8017
8357
|
console.log("Alternative: Use CLI directly (no MCP setup needed)");
|
|
8018
8358
|
console.log(` ${highlight("pkgseer pkg info <package>", useColors)}`);
|
|
8019
8359
|
}
|
|
8020
|
-
|
|
8021
|
-
const mcpCommand = program.command("mcp").summary("Show setup instructions or start MCP server").description(`Start the Model Context Protocol (MCP) server using STDIO transport.
|
|
8360
|
+
var MCP_COMMAND_DESCRIPTION = `Start the Model Context Protocol (MCP) server using STDIO transport.
|
|
8022
8361
|
|
|
8023
8362
|
When run interactively (TTY), shows setup instructions.
|
|
8024
8363
|
When run via stdio (non-TTY), starts the MCP server.
|
|
8025
8364
|
|
|
8026
|
-
Available tools (
|
|
8365
|
+
Available tools (23):
|
|
8027
8366
|
Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
|
|
8028
|
-
Browse files:
|
|
8367
|
+
Browse files: list_files, grep_file, read_file
|
|
8029
8368
|
Search: search, search_project_docs
|
|
8030
8369
|
Docs: list_package_docs, fetch_package_doc
|
|
8031
8370
|
Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
|
|
8032
|
-
Utility: trigger_indexing, search_status,
|
|
8371
|
+
Utility: trigger_indexing, indexing_status, search_status, list_imports`;
|
|
8372
|
+
function registerMcpCommand(program) {
|
|
8373
|
+
const mcpCommand = program.command("mcp").summary("Show setup instructions or start MCP server").description(MCP_COMMAND_DESCRIPTION).action(async () => {
|
|
8033
8374
|
const deps = await createContainer();
|
|
8034
8375
|
if (process.stdout.isTTY && process.stdin.isTTY) {
|
|
8035
8376
|
showMcpSetupInstructions(deps);
|