@pkgseer/cli 0.4.1 → 0.4.3
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 +756 -110
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-d340pysc.js → chunk-d3mfgdr9.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-d3mfgdr9.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -685,16 +685,26 @@ var FindSymbolDocument = gql`
|
|
|
685
685
|
totalMatches
|
|
686
686
|
hasMore
|
|
687
687
|
indexedVersion
|
|
688
|
+
diagnostics {
|
|
689
|
+
indexed
|
|
690
|
+
chunkCount
|
|
691
|
+
fileCount
|
|
692
|
+
indexedAt
|
|
693
|
+
hint
|
|
694
|
+
}
|
|
688
695
|
}
|
|
689
696
|
}
|
|
690
697
|
`;
|
|
691
698
|
var SearchSymbolsDocument = gql`
|
|
692
|
-
query SearchSymbols($registry: Registry!, $packageName: String!, $query: String
|
|
699
|
+
query SearchSymbols($registry: Registry!, $packageName: String!, $query: String, $keywords: [String!], $matchMode: MatchMode, $kind: SymbolKind, $filePath: String, $version: String, $limit: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
|
|
693
700
|
searchSymbols(
|
|
694
701
|
registry: $registry
|
|
695
702
|
packageName: $packageName
|
|
696
703
|
query: $query
|
|
704
|
+
keywords: $keywords
|
|
705
|
+
matchMode: $matchMode
|
|
697
706
|
kind: $kind
|
|
707
|
+
filePath: $filePath
|
|
698
708
|
version: $version
|
|
699
709
|
limit: $limit
|
|
700
710
|
mode: $mode
|
|
@@ -708,11 +718,26 @@ var SearchSymbolsDocument = gql`
|
|
|
708
718
|
endLine
|
|
709
719
|
preview
|
|
710
720
|
contentPreview
|
|
721
|
+
code
|
|
711
722
|
language
|
|
723
|
+
symbolId
|
|
724
|
+
qualifiedPath
|
|
725
|
+
kind
|
|
726
|
+
arity
|
|
727
|
+
isPublic
|
|
728
|
+
containedSymbols
|
|
712
729
|
}
|
|
713
730
|
totalMatches
|
|
714
731
|
hasMore
|
|
715
732
|
indexedVersion
|
|
733
|
+
diagnostics {
|
|
734
|
+
indexed
|
|
735
|
+
chunkCount
|
|
736
|
+
fileCount
|
|
737
|
+
indexedAt
|
|
738
|
+
hint
|
|
739
|
+
}
|
|
740
|
+
warning
|
|
716
741
|
}
|
|
717
742
|
}
|
|
718
743
|
`;
|
|
@@ -750,7 +775,6 @@ var ListSymbolsDocument = gql`
|
|
|
750
775
|
path
|
|
751
776
|
language
|
|
752
777
|
}
|
|
753
|
-
error
|
|
754
778
|
}
|
|
755
779
|
}
|
|
756
780
|
`;
|
|
@@ -913,6 +937,126 @@ var SearchProjectDocsDocument = gql`
|
|
|
913
937
|
}
|
|
914
938
|
}
|
|
915
939
|
`;
|
|
940
|
+
var ListRepoFilesDocument = gql`
|
|
941
|
+
query ListRepoFiles($registry: Registry!, $packageName: String!, $version: String, $pathPrefix: String, $limit: Int, $waitTimeoutMs: Int) {
|
|
942
|
+
listRepoFiles(
|
|
943
|
+
registry: $registry
|
|
944
|
+
packageName: $packageName
|
|
945
|
+
version: $version
|
|
946
|
+
pathPrefix: $pathPrefix
|
|
947
|
+
limit: $limit
|
|
948
|
+
waitTimeoutMs: $waitTimeoutMs
|
|
949
|
+
) {
|
|
950
|
+
files {
|
|
951
|
+
path
|
|
952
|
+
name
|
|
953
|
+
language
|
|
954
|
+
fileType
|
|
955
|
+
byteSize
|
|
956
|
+
}
|
|
957
|
+
total
|
|
958
|
+
hasMore
|
|
959
|
+
indexedVersion
|
|
960
|
+
diagnostics {
|
|
961
|
+
indexed
|
|
962
|
+
chunkCount
|
|
963
|
+
fileCount
|
|
964
|
+
indexedAt
|
|
965
|
+
hint
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
`;
|
|
970
|
+
var GrepRepoFileDocument = gql`
|
|
971
|
+
query GrepRepoFile($registry: Registry!, $packageName: String!, $filePath: String!, $pattern: String!, $contextLines: Int, $maxMatches: Int, $version: String, $waitTimeoutMs: Int) {
|
|
972
|
+
grepRepoFile(
|
|
973
|
+
registry: $registry
|
|
974
|
+
packageName: $packageName
|
|
975
|
+
filePath: $filePath
|
|
976
|
+
pattern: $pattern
|
|
977
|
+
contextLines: $contextLines
|
|
978
|
+
maxMatches: $maxMatches
|
|
979
|
+
version: $version
|
|
980
|
+
waitTimeoutMs: $waitTimeoutMs
|
|
981
|
+
) {
|
|
982
|
+
matches {
|
|
983
|
+
lineNumber
|
|
984
|
+
lineContent
|
|
985
|
+
contextBefore
|
|
986
|
+
contextAfter
|
|
987
|
+
}
|
|
988
|
+
totalMatches
|
|
989
|
+
hasMore
|
|
990
|
+
filePath
|
|
991
|
+
language
|
|
992
|
+
totalLines
|
|
993
|
+
indexedVersion
|
|
994
|
+
diagnostics {
|
|
995
|
+
indexed
|
|
996
|
+
chunkCount
|
|
997
|
+
fileCount
|
|
998
|
+
indexedAt
|
|
999
|
+
hint
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
`;
|
|
1004
|
+
var VersionDiffDocument = gql`
|
|
1005
|
+
query VersionDiff($registry: Registry!, $packageName: String!, $fromVersion: String!, $toVersion: String!, $includePrivate: Boolean, $kind: SymbolKind, $limit: Int, $waitTimeoutMs: Int) {
|
|
1006
|
+
versionDiff(
|
|
1007
|
+
registry: $registry
|
|
1008
|
+
packageName: $packageName
|
|
1009
|
+
fromVersion: $fromVersion
|
|
1010
|
+
toVersion: $toVersion
|
|
1011
|
+
includePrivate: $includePrivate
|
|
1012
|
+
kind: $kind
|
|
1013
|
+
limit: $limit
|
|
1014
|
+
waitTimeoutMs: $waitTimeoutMs
|
|
1015
|
+
) {
|
|
1016
|
+
fromVersion
|
|
1017
|
+
toVersion
|
|
1018
|
+
summary {
|
|
1019
|
+
added
|
|
1020
|
+
removed
|
|
1021
|
+
moved
|
|
1022
|
+
modified
|
|
1023
|
+
unchanged
|
|
1024
|
+
breaking
|
|
1025
|
+
behaviorChange
|
|
1026
|
+
}
|
|
1027
|
+
changes {
|
|
1028
|
+
qualifiedPath
|
|
1029
|
+
kind
|
|
1030
|
+
arity
|
|
1031
|
+
name
|
|
1032
|
+
changeType
|
|
1033
|
+
severity
|
|
1034
|
+
changedFields
|
|
1035
|
+
from {
|
|
1036
|
+
contentHash
|
|
1037
|
+
filePath
|
|
1038
|
+
arity
|
|
1039
|
+
startLine
|
|
1040
|
+
endLine
|
|
1041
|
+
isPublic
|
|
1042
|
+
minArity
|
|
1043
|
+
symbolId
|
|
1044
|
+
}
|
|
1045
|
+
to {
|
|
1046
|
+
contentHash
|
|
1047
|
+
filePath
|
|
1048
|
+
arity
|
|
1049
|
+
startLine
|
|
1050
|
+
endLine
|
|
1051
|
+
isPublic
|
|
1052
|
+
minArity
|
|
1053
|
+
symbolId
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
hasMore
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
`;
|
|
916
1060
|
var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
|
|
917
1061
|
var CliPackageInfoDocumentString = print(CliPackageInfoDocument);
|
|
918
1062
|
var CliPackageVulnsDocumentString = print(CliPackageVulnsDocument);
|
|
@@ -946,6 +1090,9 @@ var SymbolDependentsDocumentString = print(SymbolDependentsDocument);
|
|
|
946
1090
|
var PackageImportsDocumentString = print(PackageImportsDocument);
|
|
947
1091
|
var CallPathDocumentString = print(CallPathDocument);
|
|
948
1092
|
var SearchProjectDocsDocumentString = print(SearchProjectDocsDocument);
|
|
1093
|
+
var ListRepoFilesDocumentString = print(ListRepoFilesDocument);
|
|
1094
|
+
var GrepRepoFileDocumentString = print(GrepRepoFileDocument);
|
|
1095
|
+
var VersionDiffDocumentString = print(VersionDiffDocument);
|
|
949
1096
|
function getSdk(client, withWrapper = defaultWrapper) {
|
|
950
1097
|
return {
|
|
951
1098
|
CliPackageInfo(variables, requestHeaders) {
|
|
@@ -1043,6 +1190,15 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
1043
1190
|
},
|
|
1044
1191
|
SearchProjectDocs(variables, requestHeaders) {
|
|
1045
1192
|
return withWrapper((wrappedRequestHeaders) => client.rawRequest(SearchProjectDocsDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SearchProjectDocs", "query", variables);
|
|
1193
|
+
},
|
|
1194
|
+
ListRepoFiles(variables, requestHeaders) {
|
|
1195
|
+
return withWrapper((wrappedRequestHeaders) => client.rawRequest(ListRepoFilesDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "ListRepoFiles", "query", variables);
|
|
1196
|
+
},
|
|
1197
|
+
GrepRepoFile(variables, requestHeaders) {
|
|
1198
|
+
return withWrapper((wrappedRequestHeaders) => client.rawRequest(GrepRepoFileDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GrepRepoFile", "query", variables);
|
|
1199
|
+
},
|
|
1200
|
+
VersionDiff(variables, requestHeaders) {
|
|
1201
|
+
return withWrapper((wrappedRequestHeaders) => client.rawRequest(VersionDiffDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "VersionDiff", "query", variables);
|
|
1046
1202
|
}
|
|
1047
1203
|
};
|
|
1048
1204
|
}
|
|
@@ -1381,7 +1537,10 @@ var TOOL_NAMES = [
|
|
|
1381
1537
|
"symbol_callees",
|
|
1382
1538
|
"package_imports",
|
|
1383
1539
|
"call_path",
|
|
1384
|
-
"trigger_indexing"
|
|
1540
|
+
"trigger_indexing",
|
|
1541
|
+
"list_repo_files",
|
|
1542
|
+
"grep_repo_file",
|
|
1543
|
+
"version_diff"
|
|
1385
1544
|
];
|
|
1386
1545
|
var ToolNameSchema = z.enum(TOOL_NAMES);
|
|
1387
1546
|
var SharedConfigFields = {
|
|
@@ -1820,12 +1979,15 @@ class PkgseerServiceImpl {
|
|
|
1820
1979
|
});
|
|
1821
1980
|
return { data: result.data, errors: result.errors };
|
|
1822
1981
|
}
|
|
1823
|
-
async searchSymbols(registry, packageName,
|
|
1982
|
+
async searchSymbols(registry, packageName, options) {
|
|
1824
1983
|
const result = await this.client.SearchSymbols({
|
|
1825
1984
|
registry,
|
|
1826
1985
|
packageName,
|
|
1827
|
-
query,
|
|
1986
|
+
query: options?.query,
|
|
1987
|
+
keywords: options?.keywords,
|
|
1988
|
+
matchMode: options?.matchMode,
|
|
1828
1989
|
kind: options?.kind,
|
|
1990
|
+
filePath: options?.filePath,
|
|
1829
1991
|
version: options?.version,
|
|
1830
1992
|
limit: options?.limit,
|
|
1831
1993
|
mode: options?.mode,
|
|
@@ -1894,6 +2056,43 @@ class PkgseerServiceImpl {
|
|
|
1894
2056
|
});
|
|
1895
2057
|
return { data: result.data, errors: result.errors };
|
|
1896
2058
|
}
|
|
2059
|
+
async listRepoFiles(registry, packageName, options) {
|
|
2060
|
+
const result = await this.client.ListRepoFiles({
|
|
2061
|
+
registry,
|
|
2062
|
+
packageName,
|
|
2063
|
+
version: options?.version,
|
|
2064
|
+
pathPrefix: options?.pathPrefix,
|
|
2065
|
+
limit: options?.limit,
|
|
2066
|
+
waitTimeoutMs: options?.waitTimeoutMs
|
|
2067
|
+
});
|
|
2068
|
+
return { data: result.data, errors: result.errors };
|
|
2069
|
+
}
|
|
2070
|
+
async grepRepoFile(registry, packageName, filePath, pattern, options) {
|
|
2071
|
+
const result = await this.client.GrepRepoFile({
|
|
2072
|
+
registry,
|
|
2073
|
+
packageName,
|
|
2074
|
+
filePath,
|
|
2075
|
+
pattern,
|
|
2076
|
+
contextLines: options?.contextLines,
|
|
2077
|
+
maxMatches: options?.maxMatches,
|
|
2078
|
+
version: options?.version,
|
|
2079
|
+
waitTimeoutMs: options?.waitTimeoutMs
|
|
2080
|
+
});
|
|
2081
|
+
return { data: result.data, errors: result.errors };
|
|
2082
|
+
}
|
|
2083
|
+
async versionDiff(registry, packageName, fromVersion, toVersion, options) {
|
|
2084
|
+
const result = await this.client.VersionDiff({
|
|
2085
|
+
registry,
|
|
2086
|
+
packageName,
|
|
2087
|
+
fromVersion,
|
|
2088
|
+
toVersion,
|
|
2089
|
+
includePrivate: options?.includePrivate,
|
|
2090
|
+
kind: options?.kind,
|
|
2091
|
+
limit: options?.limit,
|
|
2092
|
+
waitTimeoutMs: options?.waitTimeoutMs
|
|
2093
|
+
});
|
|
2094
|
+
return { data: result.data, errors: result.errors };
|
|
2095
|
+
}
|
|
1897
2096
|
async triggerIndexing(input) {
|
|
1898
2097
|
const result = await this.client.TriggerIndexing({ input });
|
|
1899
2098
|
return { data: result.data, errors: result.errors };
|
|
@@ -2263,8 +2462,11 @@ function handleErrors(errors, json) {
|
|
|
2263
2462
|
const isNotFound = lower.includes("not found") || lower.includes("does not exist") || lower.includes("unknown");
|
|
2264
2463
|
const isAuth = lower.includes("unauthorized") || lower.includes("forbidden") || lower.includes("token") || lower.includes("authentication") || lower.includes("permission");
|
|
2265
2464
|
const isRateLimit = lower.includes("rate limit") || lower.includes("too many requests");
|
|
2465
|
+
const isBeingIndexed = lower.includes("being indexed") || lower.includes("retry with waittimeoutms");
|
|
2266
2466
|
let hint = "";
|
|
2267
|
-
if (
|
|
2467
|
+
if (isBeingIndexed) {
|
|
2468
|
+
hint = " Hint: package is being indexed. Try again with a longer --wait value (e.g., --wait 30000).";
|
|
2469
|
+
} else if (isTimeout) {
|
|
2268
2470
|
hint = " Hint: lower the limit or narrow the scope, then retry.";
|
|
2269
2471
|
} else if (isNotFound) {
|
|
2270
2472
|
hint = " Hint: verify the name/registry and that the resource exists.";
|
|
@@ -2302,14 +2504,20 @@ function formatSeverity(severity) {
|
|
|
2302
2504
|
return indicators[severity] || severity;
|
|
2303
2505
|
}
|
|
2304
2506
|
function extractGraphQLError(error) {
|
|
2305
|
-
if (error && typeof error === "object" && "response" in error && error.response && typeof error.response === "object" && "errors" in error.response
|
|
2306
|
-
const
|
|
2307
|
-
if (
|
|
2308
|
-
const messages =
|
|
2507
|
+
if (error && typeof error === "object" && "response" in error && error.response && typeof error.response === "object" && "errors" in error.response) {
|
|
2508
|
+
const respErrors = error.response.errors;
|
|
2509
|
+
if (Array.isArray(respErrors)) {
|
|
2510
|
+
const messages = respErrors.map((e) => e.message).filter((m) => typeof m === "string");
|
|
2309
2511
|
if (messages.length > 0) {
|
|
2310
2512
|
return messages.join("; ");
|
|
2311
2513
|
}
|
|
2312
2514
|
}
|
|
2515
|
+
if (respErrors && typeof respErrors === "object" && !Array.isArray(respErrors) && "detail" in respErrors) {
|
|
2516
|
+
const detail = respErrors.detail;
|
|
2517
|
+
if (typeof detail === "string") {
|
|
2518
|
+
return detail;
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2313
2521
|
}
|
|
2314
2522
|
if (error && typeof error === "object" && "errors" in error && Array.isArray(error.errors)) {
|
|
2315
2523
|
const errors = error.errors;
|
|
@@ -2358,6 +2566,10 @@ async function withCliErrorHandling(json, fn) {
|
|
|
2358
2566
|
}
|
|
2359
2567
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
2360
2568
|
const lower = message.toLowerCase();
|
|
2569
|
+
if (lower.includes("being indexed") || lower.includes("retry with waittimeoutms")) {
|
|
2570
|
+
outputError(`${message}. Hint: package is being indexed. Try again with a longer --wait value (e.g., --wait 30000).`, json);
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2361
2573
|
if (lower.includes("-32001") || lower.includes("timeout")) {
|
|
2362
2574
|
outputError(`${message}. Hint: lower the limit or narrow the scope, then retry.`, json);
|
|
2363
2575
|
return;
|
|
@@ -2599,6 +2811,145 @@ function registerCodeCallersCommand(program) {
|
|
|
2599
2811
|
});
|
|
2600
2812
|
});
|
|
2601
2813
|
}
|
|
2814
|
+
// src/commands/code/diff.ts
|
|
2815
|
+
function formatDiffResult(data) {
|
|
2816
|
+
const lines = [];
|
|
2817
|
+
lines.push(`Version diff: ${data.fromVersion} → ${data.toVersion}`);
|
|
2818
|
+
lines.push("");
|
|
2819
|
+
const s = data.summary;
|
|
2820
|
+
lines.push("Summary:");
|
|
2821
|
+
lines.push(` Added: ${s.added} Removed: ${s.removed} Modified: ${s.modified} Moved: ${s.moved}`);
|
|
2822
|
+
lines.push(` Unchanged: ${s.unchanged} Breaking: ${s.breaking} Behavior changes: ${s.behaviorChange}`);
|
|
2823
|
+
if (data.hasMore) {
|
|
2824
|
+
lines.push(" (more changes available, increase --limit)");
|
|
2825
|
+
}
|
|
2826
|
+
lines.push("");
|
|
2827
|
+
for (const change of data.changes) {
|
|
2828
|
+
const severity = change.severity ? ` [${change.severity}]` : "";
|
|
2829
|
+
const kindLabel = change.kind ? `[${change.kind}]` : "";
|
|
2830
|
+
const name = change.qualifiedPath ?? change.name ?? "unknown";
|
|
2831
|
+
lines.push(`${change.changeType}${severity} ${kindLabel} ${name}`.trim());
|
|
2832
|
+
if (change.from?.filePath) {
|
|
2833
|
+
const loc = change.from.startLine ? `${change.from.filePath}:${change.from.startLine}` : change.from.filePath;
|
|
2834
|
+
lines.push(` From: ${loc}`);
|
|
2835
|
+
}
|
|
2836
|
+
if (change.to?.filePath) {
|
|
2837
|
+
const loc = change.to.startLine ? `${change.to.filePath}:${change.to.startLine}` : change.to.filePath;
|
|
2838
|
+
lines.push(` To: ${loc}`);
|
|
2839
|
+
}
|
|
2840
|
+
if (change.changedFields?.length) {
|
|
2841
|
+
lines.push(` Changed: ${change.changedFields.join(", ")}`);
|
|
2842
|
+
}
|
|
2843
|
+
lines.push("");
|
|
2844
|
+
}
|
|
2845
|
+
return lines.join(`
|
|
2846
|
+
`).trimEnd();
|
|
2847
|
+
}
|
|
2848
|
+
async function codeDiffAction(packageArg, fromVersion, toVersion, options, deps) {
|
|
2849
|
+
const { pkgseerService } = deps;
|
|
2850
|
+
const parsed = parsePackageSpec(packageArg);
|
|
2851
|
+
const registry = toGraphQLRegistry(parsed.registry);
|
|
2852
|
+
const result = await pkgseerService.versionDiff(registry, parsed.name, fromVersion, toVersion, {
|
|
2853
|
+
includePrivate: options.includePrivate,
|
|
2854
|
+
kind: options.kind?.toUpperCase(),
|
|
2855
|
+
limit: parseIntOption(options.limit, "--limit"),
|
|
2856
|
+
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
2857
|
+
});
|
|
2858
|
+
handleErrors(result.errors, options.json ?? false);
|
|
2859
|
+
if (!result.data.versionDiff) {
|
|
2860
|
+
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
2861
|
+
return;
|
|
2862
|
+
}
|
|
2863
|
+
if (options.json) {
|
|
2864
|
+
output(result.data.versionDiff, true);
|
|
2865
|
+
} else {
|
|
2866
|
+
console.log(formatDiffResult(result.data.versionDiff));
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
var DIFF_DESCRIPTION = `Compare symbols between two package versions.
|
|
2870
|
+
|
|
2871
|
+
Detects added, removed, moved, and modified symbols with severity classification.
|
|
2872
|
+
Returns summary counts and per-symbol changes with file locations.
|
|
2873
|
+
|
|
2874
|
+
Examples:
|
|
2875
|
+
pkgseer code diff npm:express v4.18.2 v5.0.0
|
|
2876
|
+
pkgseer code diff npm:lodash 4.17.20 4.17.21 --include-private
|
|
2877
|
+
pkgseer code diff pypi:requests 2.30.0 2.31.0 --kind function`;
|
|
2878
|
+
function registerCodeDiffCommand(program) {
|
|
2879
|
+
program.command("diff <package> <from> <to>").summary("Compare symbols between versions").description(DIFF_DESCRIPTION).option("--include-private", "Include private/non-exported symbols").option("--kind <kind>", "Filter by symbol kind").option("--limit <n>", "Max changes to return (max 500)").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, fromVersion, toVersion, options) => {
|
|
2880
|
+
await withCliErrorHandling(options.json ?? false, async () => {
|
|
2881
|
+
const deps = await createContainer();
|
|
2882
|
+
await codeDiffAction(packageArg, fromVersion, toVersion, options, deps);
|
|
2883
|
+
});
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2886
|
+
// src/commands/code/files.ts
|
|
2887
|
+
function formatFilesResult(data) {
|
|
2888
|
+
const lines = [];
|
|
2889
|
+
lines.push(`${data.total} file(s)${data.hasMore ? " (more available)" : ""}`);
|
|
2890
|
+
if (data.indexedVersion) {
|
|
2891
|
+
lines.push(`Indexed version: ${data.indexedVersion}`);
|
|
2892
|
+
}
|
|
2893
|
+
lines.push("");
|
|
2894
|
+
for (const file of data.files) {
|
|
2895
|
+
const meta = [];
|
|
2896
|
+
if (file.language)
|
|
2897
|
+
meta.push(file.language);
|
|
2898
|
+
if (file.fileType)
|
|
2899
|
+
meta.push(file.fileType);
|
|
2900
|
+
if (file.byteSize != null)
|
|
2901
|
+
meta.push(`${file.byteSize}B`);
|
|
2902
|
+
const suffix = meta.length > 0 ? ` (${meta.join(", ")})` : "";
|
|
2903
|
+
lines.push(`${file.path}${suffix}`);
|
|
2904
|
+
}
|
|
2905
|
+
return lines.join(`
|
|
2906
|
+
`).trimEnd();
|
|
2907
|
+
}
|
|
2908
|
+
async function codeFilesAction(packageArg, options, deps) {
|
|
2909
|
+
const { pkgseerService } = deps;
|
|
2910
|
+
const parsed = parsePackageSpec(packageArg);
|
|
2911
|
+
const registry = toGraphQLRegistry(parsed.registry);
|
|
2912
|
+
const result = await pkgseerService.listRepoFiles(registry, parsed.name, {
|
|
2913
|
+
version: parsed.version,
|
|
2914
|
+
pathPrefix: options.pathPrefix,
|
|
2915
|
+
limit: parseIntOption(options.limit, "--limit"),
|
|
2916
|
+
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
2917
|
+
});
|
|
2918
|
+
handleErrors(result.errors, options.json ?? false);
|
|
2919
|
+
if (!result.data.listRepoFiles) {
|
|
2920
|
+
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
const data = result.data.listRepoFiles;
|
|
2924
|
+
if (options.json) {
|
|
2925
|
+
output(data, true);
|
|
2926
|
+
} else {
|
|
2927
|
+
const formatted = formatFilesResult(data);
|
|
2928
|
+
if (data.files.length === 0 && data.diagnostics?.hint) {
|
|
2929
|
+
console.log(`${formatted}
|
|
2930
|
+
Note: ${data.diagnostics.hint}`);
|
|
2931
|
+
} else {
|
|
2932
|
+
console.log(formatted);
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
var FILES_DESCRIPTION = `List files in a package's indexed repository.
|
|
2937
|
+
|
|
2938
|
+
Returns file paths, names, languages, types, and sizes.
|
|
2939
|
+
Use --path-prefix to filter by directory.
|
|
2940
|
+
|
|
2941
|
+
Examples:
|
|
2942
|
+
pkgseer code files npm:express
|
|
2943
|
+
pkgseer code files npm:express --path-prefix src/
|
|
2944
|
+
pkgseer code files pypi:requests --limit 50`;
|
|
2945
|
+
function registerCodeFilesCommand(program) {
|
|
2946
|
+
program.command("files <package>").summary("List files in package repository").description(FILES_DESCRIPTION).option("--path-prefix <prefix>", "Filter to files under this path").option("--limit <n>", "Max files to return (max 1000)").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, options) => {
|
|
2947
|
+
await withCliErrorHandling(options.json ?? false, async () => {
|
|
2948
|
+
const deps = await createContainer();
|
|
2949
|
+
await codeFilesAction(packageArg, options, deps);
|
|
2950
|
+
});
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2602
2953
|
// src/commands/code/find.ts
|
|
2603
2954
|
function formatFindResult(data) {
|
|
2604
2955
|
const lines = [];
|
|
@@ -2634,10 +2985,17 @@ async function codeFindAction(packageArg, nameArg, options, deps) {
|
|
|
2634
2985
|
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
2635
2986
|
return;
|
|
2636
2987
|
}
|
|
2988
|
+
const data = result.data.findSymbol;
|
|
2637
2989
|
if (options.json) {
|
|
2638
|
-
output(
|
|
2990
|
+
output(data, true);
|
|
2639
2991
|
} else {
|
|
2640
|
-
|
|
2992
|
+
const formatted = formatFindResult(data);
|
|
2993
|
+
if (data.symbols.length === 0 && data.diagnostics?.hint) {
|
|
2994
|
+
console.log(`${formatted}
|
|
2995
|
+
Note: ${data.diagnostics.hint}`);
|
|
2996
|
+
} else {
|
|
2997
|
+
console.log(formatted);
|
|
2998
|
+
}
|
|
2641
2999
|
}
|
|
2642
3000
|
}
|
|
2643
3001
|
var FIND_DESCRIPTION = `Find symbols (functions, classes, modules) by name.
|
|
@@ -2658,6 +3016,79 @@ function registerCodeFindCommand(program) {
|
|
|
2658
3016
|
});
|
|
2659
3017
|
});
|
|
2660
3018
|
}
|
|
3019
|
+
// src/commands/code/grep.ts
|
|
3020
|
+
function formatGrepResult(data) {
|
|
3021
|
+
const lines = [];
|
|
3022
|
+
lines.push(`${data.totalMatches} match(es) in ${data.filePath ?? "unknown"}${data.hasMore ? " (more available)" : ""}`);
|
|
3023
|
+
if (data.language)
|
|
3024
|
+
lines.push(`Language: ${data.language}`);
|
|
3025
|
+
if (data.totalLines != null)
|
|
3026
|
+
lines.push(`Total lines: ${data.totalLines}`);
|
|
3027
|
+
if (data.indexedVersion)
|
|
3028
|
+
lines.push(`Indexed version: ${data.indexedVersion}`);
|
|
3029
|
+
lines.push("");
|
|
3030
|
+
for (const match of data.matches) {
|
|
3031
|
+
if (match.contextBefore) {
|
|
3032
|
+
for (const line of match.contextBefore) {
|
|
3033
|
+
lines.push(` ${line}`);
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
lines.push(`${match.lineNumber}: ${match.lineContent}`);
|
|
3037
|
+
if (match.contextAfter) {
|
|
3038
|
+
for (const line of match.contextAfter) {
|
|
3039
|
+
lines.push(` ${line}`);
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
lines.push("");
|
|
3043
|
+
}
|
|
3044
|
+
return lines.join(`
|
|
3045
|
+
`).trimEnd();
|
|
3046
|
+
}
|
|
3047
|
+
async function codeGrepAction(packageArg, filePath, pattern, options, deps) {
|
|
3048
|
+
const { pkgseerService } = deps;
|
|
3049
|
+
const parsed = parsePackageSpec(packageArg);
|
|
3050
|
+
const registry = toGraphQLRegistry(parsed.registry);
|
|
3051
|
+
const result = await pkgseerService.grepRepoFile(registry, parsed.name, filePath, pattern, {
|
|
3052
|
+
contextLines: parseIntOption(options.contextLines, "--context-lines"),
|
|
3053
|
+
maxMatches: parseIntOption(options.maxMatches, "--max-matches"),
|
|
3054
|
+
version: parsed.version,
|
|
3055
|
+
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3056
|
+
});
|
|
3057
|
+
handleErrors(result.errors, options.json ?? false);
|
|
3058
|
+
if (!result.data.grepRepoFile) {
|
|
3059
|
+
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3060
|
+
return;
|
|
3061
|
+
}
|
|
3062
|
+
const data = result.data.grepRepoFile;
|
|
3063
|
+
if (options.json) {
|
|
3064
|
+
output(data, true);
|
|
3065
|
+
} else {
|
|
3066
|
+
const formatted = formatGrepResult(data);
|
|
3067
|
+
if (data.matches.length === 0 && data.diagnostics?.hint) {
|
|
3068
|
+
console.log(`${formatted}
|
|
3069
|
+
Note: ${data.diagnostics.hint}`);
|
|
3070
|
+
} else {
|
|
3071
|
+
console.log(formatted);
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
var GREP_DESCRIPTION = `Search for a pattern within a file in a package's repository.
|
|
3076
|
+
|
|
3077
|
+
Case-insensitive substring matching. Returns matching lines with context.
|
|
3078
|
+
Use 'code files' to discover available file paths.
|
|
3079
|
+
|
|
3080
|
+
Examples:
|
|
3081
|
+
pkgseer code grep npm:express "lib/router/index.js" "middleware"
|
|
3082
|
+
pkgseer code grep pypi:requests "requests/api.py" "timeout" --context-lines 3
|
|
3083
|
+
pkgseer code grep npm:lodash "lodash.js" "cloneDeep" --max-matches 5`;
|
|
3084
|
+
function registerCodeGrepCommand(program) {
|
|
3085
|
+
program.command("grep <package> <file> <pattern>").summary("Search for pattern in a package file").description(GREP_DESCRIPTION).option("--context-lines <n>", "Lines of context around each match (max 10)").option("--max-matches <n>", "Maximum matches to return (max 200)").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, filePath, pattern, options) => {
|
|
3086
|
+
await withCliErrorHandling(options.json ?? false, async () => {
|
|
3087
|
+
const deps = await createContainer();
|
|
3088
|
+
await codeGrepAction(packageArg, filePath, pattern, options, deps);
|
|
3089
|
+
});
|
|
3090
|
+
});
|
|
3091
|
+
}
|
|
2661
3092
|
// src/commands/code/imports.ts
|
|
2662
3093
|
function formatImport(entry) {
|
|
2663
3094
|
const parts = [];
|
|
@@ -2748,9 +3179,6 @@ function formatListResult(data) {
|
|
|
2748
3179
|
if (data.file) {
|
|
2749
3180
|
lines.push(`File: ${data.file.path}${data.file.language ? ` (${data.file.language})` : ""}`);
|
|
2750
3181
|
}
|
|
2751
|
-
if (data.error) {
|
|
2752
|
-
lines.push(`Warning: ${data.error}`);
|
|
2753
|
-
}
|
|
2754
3182
|
lines.push("");
|
|
2755
3183
|
for (const symbol of data.symbols) {
|
|
2756
3184
|
lines.push(formatSymbol(symbol));
|
|
@@ -2899,12 +3327,29 @@ function formatSearchResult(data) {
|
|
|
2899
3327
|
return lines.join(`
|
|
2900
3328
|
`).trimEnd();
|
|
2901
3329
|
}
|
|
3330
|
+
function parseMatchMode(mode) {
|
|
3331
|
+
if (!mode)
|
|
3332
|
+
return;
|
|
3333
|
+
const upper = mode.toUpperCase();
|
|
3334
|
+
if (upper === "OR" || upper === "AND")
|
|
3335
|
+
return upper;
|
|
3336
|
+
throw new Error("--match-mode must be 'or' or 'and'");
|
|
3337
|
+
}
|
|
2902
3338
|
async function codeSearchAction(packageArg, query, options, deps) {
|
|
2903
3339
|
const { pkgseerService } = deps;
|
|
2904
3340
|
const parsed = parsePackageSpec(packageArg);
|
|
2905
3341
|
const registry = toGraphQLRegistry(parsed.registry);
|
|
2906
|
-
const
|
|
3342
|
+
const keywords = options.keywords ? options.keywords.split(",").map((k) => k.trim()).filter(Boolean) : undefined;
|
|
3343
|
+
if (!query && !keywords?.length) {
|
|
3344
|
+
outputError("Either a query argument or --keywords must be provided", options.json ?? false);
|
|
3345
|
+
return;
|
|
3346
|
+
}
|
|
3347
|
+
const result = await pkgseerService.searchSymbols(registry, parsed.name, {
|
|
3348
|
+
query: query || undefined,
|
|
3349
|
+
keywords,
|
|
3350
|
+
matchMode: parseMatchMode(options.matchMode),
|
|
2907
3351
|
kind: options.kind?.toUpperCase(),
|
|
3352
|
+
filePath: options.filePath,
|
|
2908
3353
|
version: parsed.version,
|
|
2909
3354
|
limit: parseIntOption(options.limit, "--limit"),
|
|
2910
3355
|
mode: parseNavigationMode(options.mode),
|
|
@@ -2915,23 +3360,36 @@ async function codeSearchAction(packageArg, query, options, deps) {
|
|
|
2915
3360
|
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
2916
3361
|
return;
|
|
2917
3362
|
}
|
|
3363
|
+
const data = result.data.searchSymbols;
|
|
2918
3364
|
if (options.json) {
|
|
2919
|
-
output(
|
|
3365
|
+
output(data, true);
|
|
2920
3366
|
} else {
|
|
2921
|
-
|
|
3367
|
+
let formatted = formatSearchResult(data);
|
|
3368
|
+
if (data.warning) {
|
|
3369
|
+
formatted = `Warning: ${data.warning}
|
|
3370
|
+
|
|
3371
|
+
${formatted}`;
|
|
3372
|
+
}
|
|
3373
|
+
if (data.results.length === 0 && data.diagnostics?.hint) {
|
|
3374
|
+
formatted = `${formatted}
|
|
3375
|
+
Note: ${data.diagnostics.hint}`;
|
|
3376
|
+
}
|
|
3377
|
+
console.log(formatted);
|
|
2922
3378
|
}
|
|
2923
3379
|
}
|
|
2924
3380
|
var SEARCH_DESCRIPTION = `Full-text search within package code.
|
|
2925
3381
|
|
|
2926
3382
|
Searches across functions, classes, modules, and doc sections.
|
|
3383
|
+
Supports query string or keyword list with match mode.
|
|
2927
3384
|
Returns matching code chunks with names, types, and previews.
|
|
2928
3385
|
|
|
2929
3386
|
Examples:
|
|
2930
3387
|
pkgseer code search npm:express "middleware"
|
|
2931
3388
|
pkgseer code search pypi:requests "timeout" --kind function
|
|
2932
|
-
pkgseer code search npm:lodash "deep
|
|
3389
|
+
pkgseer code search npm:lodash --keywords "deep,clone" --match-mode and
|
|
3390
|
+
pkgseer code search npm:express "router" --file-path src/`;
|
|
2933
3391
|
function registerCodeSearchCommand(program) {
|
|
2934
|
-
program.command("search <package>
|
|
3392
|
+
program.command("search <package> [query]").summary("Full-text search in package code").description(SEARCH_DESCRIPTION).option("--kind <kind>", "Filter by chunk type (function, class, module, etc.)").option("--limit <n>", "Max results (default: 25, max: 50)").option("--keywords <words>", "Comma-separated keywords (alternative to query)").option("--match-mode <mode>", "How to combine keywords: or (any) or and (all)").option("--file-path <prefix>", "Filter to files matching path prefix").option("--mode <mode>", "Response detail: summary or detailed").option("--wait <ms>", "Max ms to wait for indexing (0-30000)").option("--json", "Output as JSON").action(async (packageArg, query, options) => {
|
|
2935
3393
|
await withCliErrorHandling(options.json ?? false, async () => {
|
|
2936
3394
|
const deps = await createContainer();
|
|
2937
3395
|
await codeSearchAction(packageArg, query, options, deps);
|
|
@@ -6006,6 +6464,14 @@ function toSymbolKind(kind) {
|
|
|
6006
6464
|
return upper;
|
|
6007
6465
|
return;
|
|
6008
6466
|
}
|
|
6467
|
+
function toMatchMode(mode) {
|
|
6468
|
+
if (!mode)
|
|
6469
|
+
return;
|
|
6470
|
+
const upper = mode.toUpperCase();
|
|
6471
|
+
if (upper === "OR" || upper === "AND")
|
|
6472
|
+
return upper;
|
|
6473
|
+
return;
|
|
6474
|
+
}
|
|
6009
6475
|
function toListScope(scope) {
|
|
6010
6476
|
if (!scope)
|
|
6011
6477
|
return;
|
|
@@ -6037,10 +6503,30 @@ function toSymbolReferenceInput(ref) {
|
|
|
6037
6503
|
}
|
|
6038
6504
|
function buildHintedMessage(operation, message) {
|
|
6039
6505
|
const lower = message.toLowerCase();
|
|
6506
|
+
const isBeingIndexed = lower.includes("being indexed") || lower.includes("retry with waittimeoutms");
|
|
6507
|
+
if (isBeingIndexed) {
|
|
6508
|
+
return `Failed to ${operation}: ${message}. ` + "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).";
|
|
6509
|
+
}
|
|
6040
6510
|
const isTimeout = lower.includes("-32001") || lower.includes("timeout") || lower.includes("timed out");
|
|
6041
6511
|
if (isTimeout) {
|
|
6042
6512
|
return `Failed to ${operation}: ${message}. ` + "Hint: try lowering the limit or narrowing the scope, then retry.";
|
|
6043
6513
|
}
|
|
6514
|
+
if (lower.includes("graphql error (code: 500)")) {
|
|
6515
|
+
try {
|
|
6516
|
+
const jsonMatch = message.match(/\{.*\}/s);
|
|
6517
|
+
if (jsonMatch) {
|
|
6518
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
6519
|
+
const detail = parsed.errors?.detail ?? parsed.detail;
|
|
6520
|
+
if (typeof detail === "string") {
|
|
6521
|
+
return `Failed to ${operation}: ${detail}`;
|
|
6522
|
+
}
|
|
6523
|
+
}
|
|
6524
|
+
} catch {}
|
|
6525
|
+
const detailMatch = message.match(/"detail"\s*:\s*"([^"]+)"/);
|
|
6526
|
+
if (detailMatch?.[1]) {
|
|
6527
|
+
return `Failed to ${operation}: ${detailMatch[1]}`;
|
|
6528
|
+
}
|
|
6529
|
+
}
|
|
6044
6530
|
return `Failed to ${operation}: ${message}`;
|
|
6045
6531
|
}
|
|
6046
6532
|
function handleGraphQLErrors(errors) {
|
|
@@ -6049,10 +6535,14 @@ function handleGraphQLErrors(errors) {
|
|
|
6049
6535
|
const combined = messages.join(", ");
|
|
6050
6536
|
const lower = combined.toLowerCase();
|
|
6051
6537
|
const hasNotFound = lower.includes("not found") || lower.includes("does not exist");
|
|
6538
|
+
const hasBeingIndexed = lower.includes("being indexed") || lower.includes("retry with waittimeoutms");
|
|
6052
6539
|
const hasTimeout = lower.includes("-32001") || lower.includes("timeout") || lower.includes("timed out");
|
|
6053
6540
|
if (hasNotFound) {
|
|
6054
6541
|
return errorResult(`Error: ${combined}. Hint: verify the name/registry and that the resource exists.`);
|
|
6055
6542
|
}
|
|
6543
|
+
if (hasBeingIndexed) {
|
|
6544
|
+
return errorResult(`Error: ${combined}. Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).`);
|
|
6545
|
+
}
|
|
6056
6546
|
if (hasTimeout) {
|
|
6057
6547
|
return errorResult(`Error: ${combined}. Hint: try lowering the limit or narrowing the scope, then retry.`);
|
|
6058
6548
|
}
|
|
@@ -6247,13 +6737,57 @@ function createFindSymbolTool(pkgseerService) {
|
|
|
6247
6737
|
if (!result.data.findSymbol) {
|
|
6248
6738
|
return notFoundError(args.package_name, args.registry);
|
|
6249
6739
|
}
|
|
6250
|
-
|
|
6740
|
+
const data = result.data.findSymbol;
|
|
6741
|
+
if (data.symbols.length === 0 && data.diagnostics?.hint) {
|
|
6742
|
+
return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
|
|
6743
|
+
}
|
|
6744
|
+
return textResult(JSON.stringify(data, null, 2));
|
|
6251
6745
|
});
|
|
6252
6746
|
}
|
|
6253
6747
|
};
|
|
6254
6748
|
}
|
|
6255
|
-
// src/tools/
|
|
6749
|
+
// src/tools/grep-repo-file.ts
|
|
6750
|
+
import { z as z8 } from "zod";
|
|
6256
6751
|
var argsSchema6 = {
|
|
6752
|
+
registry: schemas.registry,
|
|
6753
|
+
package_name: schemas.packageName.describe("Name of the package to search within"),
|
|
6754
|
+
file_path: z8.string().describe("Path to the file (relative to package root)"),
|
|
6755
|
+
pattern: z8.string().max(200).describe("Case-insensitive substring to search for (max 200 chars)"),
|
|
6756
|
+
context_lines: z8.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
|
|
6757
|
+
max_matches: z8.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
|
|
6758
|
+
version: schemas.version,
|
|
6759
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6760
|
+
};
|
|
6761
|
+
function createGrepRepoFileTool(pkgseerService) {
|
|
6762
|
+
return {
|
|
6763
|
+
name: "grep_repo_file",
|
|
6764
|
+
description: "Search for a pattern within a file in a package's repository. " + "Case-insensitive substring matching. Returns matching lines with context. " + "Faster than fetch_code_context for large files. " + "Use list_repo_files to discover available file paths.",
|
|
6765
|
+
schema: argsSchema6,
|
|
6766
|
+
handler: async (args, _extra) => {
|
|
6767
|
+
return withErrorHandling("grep repo file", async () => {
|
|
6768
|
+
const result = await pkgseerService.grepRepoFile(toGraphQLRegistry2(args.registry), args.package_name, args.file_path, args.pattern, {
|
|
6769
|
+
contextLines: args.context_lines,
|
|
6770
|
+
maxMatches: args.max_matches,
|
|
6771
|
+
version: args.version,
|
|
6772
|
+
waitTimeoutMs: args.wait_timeout_ms
|
|
6773
|
+
});
|
|
6774
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
6775
|
+
if (graphqlError)
|
|
6776
|
+
return graphqlError;
|
|
6777
|
+
if (!result.data.grepRepoFile) {
|
|
6778
|
+
return notFoundError(args.package_name, args.registry);
|
|
6779
|
+
}
|
|
6780
|
+
const data = result.data.grepRepoFile;
|
|
6781
|
+
if (data.matches.length === 0 && data.diagnostics?.hint) {
|
|
6782
|
+
return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
|
|
6783
|
+
}
|
|
6784
|
+
return textResult(JSON.stringify(data, null, 2));
|
|
6785
|
+
});
|
|
6786
|
+
}
|
|
6787
|
+
};
|
|
6788
|
+
}
|
|
6789
|
+
// src/tools/list-package-docs.ts
|
|
6790
|
+
var argsSchema7 = {
|
|
6257
6791
|
registry: schemas.registry,
|
|
6258
6792
|
package_name: schemas.packageName.describe("Name of the package to list documentation for"),
|
|
6259
6793
|
version: schemas.version
|
|
@@ -6262,7 +6796,7 @@ function createListPackageDocsTool(pkgseerService) {
|
|
|
6262
6796
|
return {
|
|
6263
6797
|
name: "list_package_docs",
|
|
6264
6798
|
description: "Discover available documentation pages for a package. Start here before fetching or searching docs. " + "Returns: page titles, unique IDs (needed for fetch_package_doc), word counts, and update timestamps. " + "Workflow: list_package_docs → fetch_package_doc for full content, or search_package_docs to find specific topics.",
|
|
6265
|
-
schema:
|
|
6799
|
+
schema: argsSchema7,
|
|
6266
6800
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
6267
6801
|
return withErrorHandling("list package documentation", async () => {
|
|
6268
6802
|
const result = await pkgseerService.listPackageDocs(toGraphQLRegistry2(registry), package_name, version2);
|
|
@@ -6277,17 +6811,55 @@ function createListPackageDocsTool(pkgseerService) {
|
|
|
6277
6811
|
}
|
|
6278
6812
|
};
|
|
6279
6813
|
}
|
|
6814
|
+
// src/tools/list-repo-files.ts
|
|
6815
|
+
import { z as z9 } from "zod";
|
|
6816
|
+
var argsSchema8 = {
|
|
6817
|
+
registry: schemas.registry,
|
|
6818
|
+
package_name: schemas.packageName.describe("Name of the package to list files for"),
|
|
6819
|
+
version: schemas.version,
|
|
6820
|
+
path_prefix: z9.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
|
|
6821
|
+
limit: z9.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
|
|
6822
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6823
|
+
};
|
|
6824
|
+
function createListRepoFilesTool(pkgseerService) {
|
|
6825
|
+
return {
|
|
6826
|
+
name: "list_repo_files",
|
|
6827
|
+
description: "List files in a package's indexed repository. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Useful for exploring package structure before searching or reading code.",
|
|
6828
|
+
schema: argsSchema8,
|
|
6829
|
+
handler: async (args, _extra) => {
|
|
6830
|
+
return withErrorHandling("list repo files", async () => {
|
|
6831
|
+
const result = await pkgseerService.listRepoFiles(toGraphQLRegistry2(args.registry), args.package_name, {
|
|
6832
|
+
version: args.version,
|
|
6833
|
+
pathPrefix: args.path_prefix,
|
|
6834
|
+
limit: args.limit,
|
|
6835
|
+
waitTimeoutMs: args.wait_timeout_ms
|
|
6836
|
+
});
|
|
6837
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
6838
|
+
if (graphqlError)
|
|
6839
|
+
return graphqlError;
|
|
6840
|
+
if (!result.data.listRepoFiles) {
|
|
6841
|
+
return notFoundError(args.package_name, args.registry);
|
|
6842
|
+
}
|
|
6843
|
+
const data = result.data.listRepoFiles;
|
|
6844
|
+
if (data.files.length === 0 && data.diagnostics?.hint) {
|
|
6845
|
+
return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
|
|
6846
|
+
}
|
|
6847
|
+
return textResult(JSON.stringify(data, null, 2));
|
|
6848
|
+
});
|
|
6849
|
+
}
|
|
6850
|
+
};
|
|
6851
|
+
}
|
|
6280
6852
|
// src/tools/list-symbols.ts
|
|
6281
|
-
import { z as
|
|
6282
|
-
var
|
|
6853
|
+
import { z as z10 } from "zod";
|
|
6854
|
+
var argsSchema9 = {
|
|
6283
6855
|
registry: schemas.registry,
|
|
6284
6856
|
package_name: schemas.packageName.describe("Name of the package to browse symbols for"),
|
|
6285
|
-
scope:
|
|
6286
|
-
file_path:
|
|
6287
|
-
namespace:
|
|
6288
|
-
public_only:
|
|
6289
|
-
include_popularity:
|
|
6290
|
-
limit:
|
|
6857
|
+
scope: z10.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
|
|
6858
|
+
file_path: z10.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
|
|
6859
|
+
namespace: z10.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
|
|
6860
|
+
public_only: z10.boolean().optional().describe("Only return public symbols"),
|
|
6861
|
+
include_popularity: z10.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
|
|
6862
|
+
limit: z10.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
|
|
6291
6863
|
version: schemas.version,
|
|
6292
6864
|
mode: schemas.navigationMode,
|
|
6293
6865
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
@@ -6296,7 +6868,7 @@ function createListSymbolsTool(pkgseerService) {
|
|
|
6296
6868
|
return {
|
|
6297
6869
|
name: "list_symbols",
|
|
6298
6870
|
description: "Browse symbols in a package by scope. " + "Use scope='exports' for public API with namespace grouping and optional popularity. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbols with IDs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to get source for any listed symbol.",
|
|
6299
|
-
schema:
|
|
6871
|
+
schema: argsSchema9,
|
|
6300
6872
|
handler: async (args, _extra) => {
|
|
6301
6873
|
return withErrorHandling("list symbols", async () => {
|
|
6302
6874
|
const scope = toListScope(args.scope);
|
|
@@ -6333,13 +6905,13 @@ function createListSymbolsTool(pkgseerService) {
|
|
|
6333
6905
|
};
|
|
6334
6906
|
}
|
|
6335
6907
|
// src/tools/package-dependencies.ts
|
|
6336
|
-
import { z as
|
|
6337
|
-
var
|
|
6908
|
+
import { z as z11 } from "zod";
|
|
6909
|
+
var argsSchema10 = {
|
|
6338
6910
|
registry: schemas.registry,
|
|
6339
6911
|
package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
|
|
6340
6912
|
version: schemas.version,
|
|
6341
|
-
include_transitive:
|
|
6342
|
-
max_depth:
|
|
6913
|
+
include_transitive: z11.boolean().optional().describe("Whether to include transitive dependency DAG"),
|
|
6914
|
+
max_depth: z11.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
|
|
6343
6915
|
};
|
|
6344
6916
|
function decodeDag(rawDag) {
|
|
6345
6917
|
if (!rawDag || typeof rawDag !== "object")
|
|
@@ -6417,7 +6989,7 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
6417
6989
|
return {
|
|
6418
6990
|
name: "package_dependencies",
|
|
6419
6991
|
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.",
|
|
6420
|
-
schema:
|
|
6992
|
+
schema: argsSchema10,
|
|
6421
6993
|
handler: async ({ registry, package_name, version: version2, include_transitive, max_depth }, _extra) => {
|
|
6422
6994
|
return withErrorHandling("fetch package dependencies", async () => {
|
|
6423
6995
|
const result = await pkgseerService.getPackageDependencies(toGraphQLRegistry2(registry), package_name, version2, include_transitive, max_depth);
|
|
@@ -6455,13 +7027,13 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
6455
7027
|
};
|
|
6456
7028
|
}
|
|
6457
7029
|
// src/tools/package-imports.ts
|
|
6458
|
-
import { z as
|
|
6459
|
-
var
|
|
7030
|
+
import { z as z12 } from "zod";
|
|
7031
|
+
var argsSchema11 = {
|
|
6460
7032
|
registry: schemas.registry,
|
|
6461
7033
|
package_name: schemas.packageName.describe("Name of the package to get imports for"),
|
|
6462
|
-
file_path:
|
|
6463
|
-
resolved_only:
|
|
6464
|
-
limit:
|
|
7034
|
+
file_path: z12.string().max(1000).optional().describe("Filter to a specific file path"),
|
|
7035
|
+
resolved_only: z12.boolean().optional().describe("Only return imports resolved to a known package"),
|
|
7036
|
+
limit: z12.number().int().min(1).max(500).optional().describe("Max imports to return"),
|
|
6465
7037
|
version: schemas.version,
|
|
6466
7038
|
mode: schemas.navigationMode,
|
|
6467
7039
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
@@ -6470,7 +7042,7 @@ function createPackageImportsTool(pkgseerService) {
|
|
|
6470
7042
|
return {
|
|
6471
7043
|
name: "package_imports",
|
|
6472
7044
|
description: "Get import statements in a package. " + "Returns parsed import/require/use statements with optional resolution to known packages. " + "Use resolved_only=true to see only imports that map to packages in the PkgSeer registry. " + "Includes: source path, imported names, and de-duplicated dependency list.",
|
|
6473
|
-
schema:
|
|
7045
|
+
schema: argsSchema11,
|
|
6474
7046
|
handler: async (args, _extra) => {
|
|
6475
7047
|
return withErrorHandling("fetch package imports", async () => {
|
|
6476
7048
|
const result = await pkgseerService.packageImports(toGraphQLRegistry2(args.registry), args.package_name, {
|
|
@@ -6493,7 +7065,7 @@ function createPackageImportsTool(pkgseerService) {
|
|
|
6493
7065
|
};
|
|
6494
7066
|
}
|
|
6495
7067
|
// src/tools/package-quality.ts
|
|
6496
|
-
var
|
|
7068
|
+
var argsSchema12 = {
|
|
6497
7069
|
registry: schemas.registry,
|
|
6498
7070
|
package_name: schemas.packageName.describe("Name of the package to analyze"),
|
|
6499
7071
|
version: schemas.version
|
|
@@ -6502,7 +7074,7 @@ function createPackageQualityTool(pkgseerService) {
|
|
|
6502
7074
|
return {
|
|
6503
7075
|
name: "package_quality",
|
|
6504
7076
|
description: "Evaluate package maintenance health and code quality. Use this to assess if a package is well-maintained " + "before adding it as a dependency. Returns: overall score (0-100), category scores (documentation, " + "testing, community, maintenance), and individual rule results with pass/fail status. " + "Useful for comparing quality between alternative packages.",
|
|
6505
|
-
schema:
|
|
7077
|
+
schema: argsSchema12,
|
|
6506
7078
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
6507
7079
|
return withErrorHandling("fetch package quality", async () => {
|
|
6508
7080
|
const result = await pkgseerService.getPackageQuality(toGraphQLRegistry2(registry), package_name, version2);
|
|
@@ -6518,7 +7090,7 @@ function createPackageQualityTool(pkgseerService) {
|
|
|
6518
7090
|
};
|
|
6519
7091
|
}
|
|
6520
7092
|
// src/tools/package-summary.ts
|
|
6521
|
-
var
|
|
7093
|
+
var argsSchema13 = {
|
|
6522
7094
|
registry: schemas.registry,
|
|
6523
7095
|
package_name: schemas.packageName.describe("Name of the package to retrieve summary for")
|
|
6524
7096
|
};
|
|
@@ -6526,7 +7098,7 @@ function createPackageSummaryTool(pkgseerService) {
|
|
|
6526
7098
|
return {
|
|
6527
7099
|
name: "package_summary",
|
|
6528
7100
|
description: "Get a comprehensive overview of a package. Use this as your first tool when researching a package. " + "Returns: description, latest version, license, repository URL, download stats, " + "active security advisories count, and quickstart/installation instructions. " + "For deeper analysis, follow up with package_quality (maintenance health) or " + "package_vulnerabilities (security details).",
|
|
6529
|
-
schema:
|
|
7101
|
+
schema: argsSchema13,
|
|
6530
7102
|
handler: async ({ registry, package_name }, _extra) => {
|
|
6531
7103
|
return withErrorHandling("fetch package summary", async () => {
|
|
6532
7104
|
const result = await pkgseerService.getPackageSummary(toGraphQLRegistry2(registry), package_name);
|
|
@@ -6542,7 +7114,7 @@ function createPackageSummaryTool(pkgseerService) {
|
|
|
6542
7114
|
};
|
|
6543
7115
|
}
|
|
6544
7116
|
// src/tools/package-vulnerabilities.ts
|
|
6545
|
-
var
|
|
7117
|
+
var argsSchema14 = {
|
|
6546
7118
|
registry: schemas.registry,
|
|
6547
7119
|
package_name: schemas.packageName.describe("Name of the package to inspect for vulnerabilities"),
|
|
6548
7120
|
version: schemas.version
|
|
@@ -6551,7 +7123,7 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
|
6551
7123
|
return {
|
|
6552
7124
|
name: "package_vulnerabilities",
|
|
6553
7125
|
description: "Check security vulnerabilities for a package. Use this before adding dependencies or when auditing existing ones. " + "Returns: list of CVEs/advisories with severity levels, affected version ranges, fixed versions, " + "and upgrade recommendations. If version is specified, shows only vulnerabilities affecting that version.",
|
|
6554
|
-
schema:
|
|
7126
|
+
schema: argsSchema14,
|
|
6555
7127
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
6556
7128
|
return withErrorHandling("fetch package vulnerabilities", async () => {
|
|
6557
7129
|
const result = await pkgseerService.getPackageVulnerabilities(toGraphQLRegistry2(registry), package_name, version2);
|
|
@@ -6567,19 +7139,19 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
|
6567
7139
|
};
|
|
6568
7140
|
}
|
|
6569
7141
|
// src/tools/search.ts
|
|
6570
|
-
import { z as
|
|
6571
|
-
var packageInputSchema2 =
|
|
7142
|
+
import { z as z13 } from "zod";
|
|
7143
|
+
var packageInputSchema2 = z13.object({
|
|
6572
7144
|
registry: schemas.registry,
|
|
6573
|
-
name:
|
|
6574
|
-
version:
|
|
7145
|
+
name: z13.string().min(1).describe("Package name"),
|
|
7146
|
+
version: z13.string().optional().describe("Specific version (defaults to latest)")
|
|
6575
7147
|
});
|
|
6576
7148
|
var DEFAULT_AGENT_WAIT_TIMEOUT_MS = 1e4;
|
|
6577
|
-
var
|
|
6578
|
-
packages:
|
|
6579
|
-
query:
|
|
6580
|
-
mode:
|
|
6581
|
-
limit:
|
|
6582
|
-
waitTimeoutMs:
|
|
7149
|
+
var argsSchema15 = {
|
|
7150
|
+
packages: z13.array(packageInputSchema2).min(1).max(20).describe("Packages to search (1-20). Each package needs registry and name."),
|
|
7151
|
+
query: z13.string().min(1).describe("Search query - natural language or keywords"),
|
|
7152
|
+
mode: z13.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
|
|
7153
|
+
limit: z13.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
|
|
7154
|
+
waitTimeoutMs: z13.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
|
|
6583
7155
|
};
|
|
6584
7156
|
function toSearchMode2(mode) {
|
|
6585
7157
|
if (!mode)
|
|
@@ -6618,7 +7190,7 @@ function createSearchTool(pkgseerService) {
|
|
|
6618
7190
|
return {
|
|
6619
7191
|
name: "search",
|
|
6620
7192
|
description: "Search code and documentation across packages. Returns functions, classes, and doc pages " + "matching your query. Use mode='code' for code only, mode='docs' for docs only, or " + "mode='all' (default). Provide 1-20 packages. Results include relevance scores and snippets. " + "For full source of code results, use find_symbol(name=<title>, include_code=true). " + "If packages need indexing, waits up to waitTimeoutMs (default 10s) or returns searchRef — use search_status to poll.",
|
|
6621
|
-
schema:
|
|
7193
|
+
schema: argsSchema15,
|
|
6622
7194
|
handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
|
|
6623
7195
|
return withErrorHandling("search packages", async () => {
|
|
6624
7196
|
const normalizedQuery = query.trim();
|
|
@@ -6670,21 +7242,21 @@ function createSearchTool(pkgseerService) {
|
|
|
6670
7242
|
};
|
|
6671
7243
|
}
|
|
6672
7244
|
// src/tools/search-project-docs.ts
|
|
6673
|
-
import { z as
|
|
6674
|
-
var
|
|
6675
|
-
project_directory:
|
|
6676
|
-
project:
|
|
6677
|
-
terms:
|
|
6678
|
-
match_mode:
|
|
6679
|
-
include_snippets:
|
|
6680
|
-
limit:
|
|
7245
|
+
import { z as z14 } from "zod";
|
|
7246
|
+
var argsSchema16 = {
|
|
7247
|
+
project_directory: z14.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."),
|
|
7248
|
+
project: z14.string().optional().describe("Project name to search. Overrides value from pkgseer.yml if provided."),
|
|
7249
|
+
terms: z14.array(z14.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
|
|
7250
|
+
match_mode: z14.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
|
|
7251
|
+
include_snippets: z14.boolean().optional().describe("Include content excerpts around matches"),
|
|
7252
|
+
limit: z14.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
|
|
6681
7253
|
};
|
|
6682
7254
|
function createSearchProjectDocsTool(deps) {
|
|
6683
7255
|
const { pkgseerService, configService, defaultProjectDir } = deps;
|
|
6684
7256
|
return {
|
|
6685
7257
|
name: "search_project_docs",
|
|
6686
7258
|
description: "Searches documentation across all dependencies in a PkgSeer project using search terms and match modes (any/all). Returns ranked results from multiple packages. Use project_directory to specify which project's context to use, or project to search a specific project directly.",
|
|
6687
|
-
schema:
|
|
7259
|
+
schema: argsSchema16,
|
|
6688
7260
|
handler: async ({
|
|
6689
7261
|
project_directory,
|
|
6690
7262
|
project,
|
|
@@ -6730,15 +7302,15 @@ function createSearchProjectDocsTool(deps) {
|
|
|
6730
7302
|
};
|
|
6731
7303
|
}
|
|
6732
7304
|
// src/tools/search-status.ts
|
|
6733
|
-
import { z as
|
|
6734
|
-
var
|
|
6735
|
-
searchRef:
|
|
7305
|
+
import { z as z15 } from "zod";
|
|
7306
|
+
var argsSchema17 = {
|
|
7307
|
+
searchRef: z15.string().min(1).describe("Search reference from a previous incomplete search")
|
|
6736
7308
|
};
|
|
6737
7309
|
function createSearchStatusTool(pkgseerService) {
|
|
6738
7310
|
return {
|
|
6739
7311
|
name: "search_status",
|
|
6740
7312
|
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.",
|
|
6741
|
-
schema:
|
|
7313
|
+
schema: argsSchema17,
|
|
6742
7314
|
handler: async ({ searchRef }, _extra) => {
|
|
6743
7315
|
return withErrorHandling("check search status", async () => {
|
|
6744
7316
|
const progressResult = await pkgseerService.getSearchProgress(searchRef);
|
|
@@ -6779,12 +7351,14 @@ function createSearchStatusTool(pkgseerService) {
|
|
|
6779
7351
|
};
|
|
6780
7352
|
}
|
|
6781
7353
|
// src/tools/search-symbols.ts
|
|
6782
|
-
import { z as
|
|
6783
|
-
var
|
|
7354
|
+
import { z as z16 } from "zod";
|
|
7355
|
+
var argsSchema18 = {
|
|
6784
7356
|
registry: schemas.registry,
|
|
6785
7357
|
package_name: schemas.packageName.describe("Name of the package to search within"),
|
|
6786
|
-
query:
|
|
6787
|
-
|
|
7358
|
+
query: z16.string().max(500).optional().describe("Search query for full-text code search (max 500 chars). Required if keywords not provided."),
|
|
7359
|
+
keywords: z16.array(z16.string()).max(20).optional().describe("Search keywords (max 20). Combined using match_mode. Alternative to query."),
|
|
7360
|
+
match_mode: z16.enum(["or", "and"]).optional().describe("How to combine keywords: or (any match) or and (all must match)"),
|
|
7361
|
+
kind: z16.enum([
|
|
6788
7362
|
"function",
|
|
6789
7363
|
"method",
|
|
6790
7364
|
"class",
|
|
@@ -6793,20 +7367,25 @@ var argsSchema16 = {
|
|
|
6793
7367
|
"type",
|
|
6794
7368
|
"doc_section"
|
|
6795
7369
|
]).optional().describe("Filter results by code chunk type"),
|
|
7370
|
+
file_path: z16.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
|
|
6796
7371
|
version: schemas.version,
|
|
6797
|
-
limit:
|
|
7372
|
+
limit: z16.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
|
|
6798
7373
|
mode: schemas.navigationMode,
|
|
6799
7374
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6800
7375
|
};
|
|
6801
7376
|
function createSearchSymbolsTool(pkgseerService) {
|
|
6802
7377
|
return {
|
|
6803
7378
|
name: "search_symbols",
|
|
6804
|
-
description: "Full-text search within package code. " + "Searches across functions, classes, modules, and doc sections. " + "Returns matching code chunks with name, type, file path, line numbers, and content previews. " + "Follow-up: use find_symbol(name=<result.name>, include_code=true) to get full source.",
|
|
6805
|
-
schema:
|
|
7379
|
+
description: "Full-text search within package code. " + "Searches across functions, classes, modules, and doc sections. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns matching code chunks with name, type, file path, line numbers, and content previews. " + "Follow-up: use find_symbol(name=<result.name>, include_code=true) to get full source.",
|
|
7380
|
+
schema: argsSchema18,
|
|
6806
7381
|
handler: async (args, _extra) => {
|
|
6807
7382
|
return withErrorHandling("search symbols", async () => {
|
|
6808
|
-
const result = await pkgseerService.searchSymbols(toGraphQLRegistry2(args.registry), args.package_name,
|
|
7383
|
+
const result = await pkgseerService.searchSymbols(toGraphQLRegistry2(args.registry), args.package_name, {
|
|
7384
|
+
query: args.query,
|
|
7385
|
+
keywords: args.keywords,
|
|
7386
|
+
matchMode: toMatchMode(args.match_mode),
|
|
6809
7387
|
kind: toSymbolKind(args.kind),
|
|
7388
|
+
filePath: args.file_path,
|
|
6810
7389
|
version: args.version,
|
|
6811
7390
|
limit: args.limit,
|
|
6812
7391
|
mode: toNavigationMode(args.mode),
|
|
@@ -6818,19 +7397,30 @@ function createSearchSymbolsTool(pkgseerService) {
|
|
|
6818
7397
|
if (!result.data.searchSymbols) {
|
|
6819
7398
|
return notFoundError(args.package_name, args.registry);
|
|
6820
7399
|
}
|
|
6821
|
-
|
|
7400
|
+
const data = result.data.searchSymbols;
|
|
7401
|
+
const extra = {};
|
|
7402
|
+
if (data.results.length === 0 && data.diagnostics?.hint) {
|
|
7403
|
+
extra._hint = data.diagnostics.hint;
|
|
7404
|
+
}
|
|
7405
|
+
if (data.warning) {
|
|
7406
|
+
extra._warning = data.warning;
|
|
7407
|
+
}
|
|
7408
|
+
if (Object.keys(extra).length > 0) {
|
|
7409
|
+
return textResult(JSON.stringify({ ...data, ...extra }, null, 2));
|
|
7410
|
+
}
|
|
7411
|
+
return textResult(JSON.stringify(data, null, 2));
|
|
6822
7412
|
});
|
|
6823
7413
|
}
|
|
6824
7414
|
};
|
|
6825
7415
|
}
|
|
6826
7416
|
// src/tools/symbol-callees.ts
|
|
6827
|
-
import { z as
|
|
6828
|
-
var
|
|
7417
|
+
import { z as z17 } from "zod";
|
|
7418
|
+
var argsSchema19 = {
|
|
6829
7419
|
symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide either symbol_id or registry + package_name + symbol_name."),
|
|
6830
|
-
max_depth:
|
|
6831
|
-
limit:
|
|
6832
|
-
include_external:
|
|
6833
|
-
include_builtins:
|
|
7420
|
+
max_depth: z17.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
|
|
7421
|
+
limit: z17.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
|
|
7422
|
+
include_external: z17.boolean().optional().describe("Include calls to symbols in other packages"),
|
|
7423
|
+
include_builtins: z17.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
|
|
6834
7424
|
mode: schemas.navigationMode,
|
|
6835
7425
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6836
7426
|
};
|
|
@@ -6838,7 +7428,7 @@ function createSymbolCalleesTool(pkgseerService) {
|
|
|
6838
7428
|
return {
|
|
6839
7429
|
name: "symbol_callees",
|
|
6840
7430
|
description: "Find what a symbol calls (its dependencies). " + "Returns direct callees at max_depth=1, or transitive call chains at higher depths. " + "Includes callee names, qualified paths, file locations, call lines, and external package references. " + "Get symbol_id from find_symbol or list_symbols results. See symbol_callers for the reverse.",
|
|
6841
|
-
schema:
|
|
7431
|
+
schema: argsSchema19,
|
|
6842
7432
|
handler: async (args, _extra) => {
|
|
6843
7433
|
return withErrorHandling("find symbol callees", async () => {
|
|
6844
7434
|
const symbolInput = toSymbolReferenceInput(args.symbol);
|
|
@@ -6865,11 +7455,11 @@ function createSymbolCalleesTool(pkgseerService) {
|
|
|
6865
7455
|
};
|
|
6866
7456
|
}
|
|
6867
7457
|
// src/tools/symbol-callers.ts
|
|
6868
|
-
import { z as
|
|
6869
|
-
var
|
|
7458
|
+
import { z as z18 } from "zod";
|
|
7459
|
+
var argsSchema20 = {
|
|
6870
7460
|
symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide either symbol_id or registry + package_name + symbol_name."),
|
|
6871
|
-
same_package_only:
|
|
6872
|
-
limit:
|
|
7461
|
+
same_package_only: z18.boolean().optional().describe("Only return callers from the same package"),
|
|
7462
|
+
limit: z18.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
|
|
6873
7463
|
mode: schemas.navigationMode,
|
|
6874
7464
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6875
7465
|
};
|
|
@@ -6877,7 +7467,7 @@ function createSymbolCallersTool(pkgseerService) {
|
|
|
6877
7467
|
return {
|
|
6878
7468
|
name: "symbol_callers",
|
|
6879
7469
|
description: "Find what calls a symbol (its dependents/callers). " + "Returns the target symbol and a list of callers with file locations and call line numbers. " + "Use same_package_only to limit to callers within the same package. " + "Get symbol_id from find_symbol or list_symbols results. See symbol_callees for the reverse.",
|
|
6880
|
-
schema:
|
|
7470
|
+
schema: argsSchema20,
|
|
6881
7471
|
handler: async (args, _extra) => {
|
|
6882
7472
|
return withErrorHandling("find symbol callers", async () => {
|
|
6883
7473
|
const symbolInput = toSymbolReferenceInput(args.symbol);
|
|
@@ -6902,26 +7492,26 @@ function createSymbolCallersTool(pkgseerService) {
|
|
|
6902
7492
|
};
|
|
6903
7493
|
}
|
|
6904
7494
|
// src/tools/trigger-indexing.ts
|
|
6905
|
-
import { z as
|
|
6906
|
-
var packageInputSchema3 =
|
|
7495
|
+
import { z as z19 } from "zod";
|
|
7496
|
+
var packageInputSchema3 = z19.object({
|
|
6907
7497
|
registry: schemas.registry,
|
|
6908
|
-
name:
|
|
6909
|
-
version:
|
|
7498
|
+
name: z19.string().max(255).describe("Package name"),
|
|
7499
|
+
version: z19.string().max(100).optional().describe("Specific version to index")
|
|
6910
7500
|
});
|
|
6911
|
-
var repositoryInputSchema =
|
|
6912
|
-
url:
|
|
6913
|
-
ref:
|
|
6914
|
-
discover_packages:
|
|
7501
|
+
var repositoryInputSchema = z19.object({
|
|
7502
|
+
url: z19.string().max(2000).describe("GitHub repository URL"),
|
|
7503
|
+
ref: z19.string().max(200).optional().describe("Git ref to index (tag, branch, commit). Defaults to HEAD"),
|
|
7504
|
+
discover_packages: z19.boolean().optional().describe("If true, discover packages published from this repo and trigger their metadata fetch")
|
|
6915
7505
|
});
|
|
6916
|
-
var
|
|
6917
|
-
packages:
|
|
6918
|
-
repositories:
|
|
7506
|
+
var argsSchema21 = {
|
|
7507
|
+
packages: z19.array(packageInputSchema3).max(100).optional().describe("Package versions to index (max 100)"),
|
|
7508
|
+
repositories: z19.array(repositoryInputSchema).max(50).optional().describe("Repository URLs to index (max 50)")
|
|
6919
7509
|
};
|
|
6920
7510
|
function createTriggerIndexingTool(pkgseerService) {
|
|
6921
7511
|
return {
|
|
6922
7512
|
name: "trigger_indexing",
|
|
6923
7513
|
description: "Pre-warm PkgSeer indexes by triggering indexing for packages and/or repositories. " + "Fire-and-forget: triggers jobs and returns immediately with accepted/skipped counts. " + "Use before search requests to ensure packages are indexed. " + "Rate limited to 10 requests per minute.",
|
|
6924
|
-
schema:
|
|
7514
|
+
schema: argsSchema21,
|
|
6925
7515
|
handler: async (args, _extra) => {
|
|
6926
7516
|
return withErrorHandling("trigger indexing", async () => {
|
|
6927
7517
|
const packages = args.packages?.map((p) => ({
|
|
@@ -6957,6 +7547,50 @@ function createTriggerIndexingTool(pkgseerService) {
|
|
|
6957
7547
|
}
|
|
6958
7548
|
};
|
|
6959
7549
|
}
|
|
7550
|
+
// src/tools/version-diff.ts
|
|
7551
|
+
import { z as z20 } from "zod";
|
|
7552
|
+
var argsSchema22 = {
|
|
7553
|
+
registry: schemas.registry,
|
|
7554
|
+
package_name: schemas.packageName.describe("Name of the package to compare versions for"),
|
|
7555
|
+
from_version: z20.string().max(100).describe("Source version (git ref, e.g., 'v4.18.2')"),
|
|
7556
|
+
to_version: z20.string().max(100).describe("Target version (git ref, e.g., 'v5.0.0')"),
|
|
7557
|
+
include_private: z20.boolean().optional().describe("Include private/non-exported symbols in the diff"),
|
|
7558
|
+
kind: z20.enum([
|
|
7559
|
+
"function",
|
|
7560
|
+
"method",
|
|
7561
|
+
"class",
|
|
7562
|
+
"module",
|
|
7563
|
+
"interface",
|
|
7564
|
+
"type",
|
|
7565
|
+
"doc_section"
|
|
7566
|
+
]).optional().describe("Filter by symbol kind"),
|
|
7567
|
+
limit: z20.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
|
|
7568
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7569
|
+
};
|
|
7570
|
+
function createVersionDiffTool(pkgseerService) {
|
|
7571
|
+
return {
|
|
7572
|
+
name: "version_diff",
|
|
7573
|
+
description: "Compare symbols between two package versions. " + "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.",
|
|
7574
|
+
schema: argsSchema22,
|
|
7575
|
+
handler: async (args, _extra) => {
|
|
7576
|
+
return withErrorHandling("version diff", async () => {
|
|
7577
|
+
const result = await pkgseerService.versionDiff(toGraphQLRegistry2(args.registry), args.package_name, args.from_version, args.to_version, {
|
|
7578
|
+
includePrivate: args.include_private,
|
|
7579
|
+
kind: toSymbolKind(args.kind),
|
|
7580
|
+
limit: args.limit,
|
|
7581
|
+
waitTimeoutMs: args.wait_timeout_ms
|
|
7582
|
+
});
|
|
7583
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7584
|
+
if (graphqlError)
|
|
7585
|
+
return graphqlError;
|
|
7586
|
+
if (!result.data.versionDiff) {
|
|
7587
|
+
return notFoundError(args.package_name, args.registry);
|
|
7588
|
+
}
|
|
7589
|
+
return textResult(JSON.stringify(result.data.versionDiff, null, 2));
|
|
7590
|
+
});
|
|
7591
|
+
}
|
|
7592
|
+
};
|
|
7593
|
+
}
|
|
6960
7594
|
// src/commands/mcp.ts
|
|
6961
7595
|
var TOOL_FACTORIES = {
|
|
6962
7596
|
package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
|
|
@@ -6981,7 +7615,10 @@ var TOOL_FACTORIES = {
|
|
|
6981
7615
|
symbol_callees: ({ pkgseerService }) => createSymbolCalleesTool(pkgseerService),
|
|
6982
7616
|
package_imports: ({ pkgseerService }) => createPackageImportsTool(pkgseerService),
|
|
6983
7617
|
call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
|
|
6984
|
-
trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService)
|
|
7618
|
+
trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService),
|
|
7619
|
+
list_repo_files: ({ pkgseerService }) => createListRepoFilesTool(pkgseerService),
|
|
7620
|
+
grep_repo_file: ({ pkgseerService }) => createGrepRepoFileTool(pkgseerService),
|
|
7621
|
+
version_diff: ({ pkgseerService }) => createVersionDiffTool(pkgseerService)
|
|
6985
7622
|
};
|
|
6986
7623
|
var PUBLIC_READ_TOOLS = [
|
|
6987
7624
|
"package_summary",
|
|
@@ -7001,7 +7638,10 @@ var PUBLIC_READ_TOOLS = [
|
|
|
7001
7638
|
"symbol_callees",
|
|
7002
7639
|
"package_imports",
|
|
7003
7640
|
"call_path",
|
|
7004
|
-
"trigger_indexing"
|
|
7641
|
+
"trigger_indexing",
|
|
7642
|
+
"list_repo_files",
|
|
7643
|
+
"grep_repo_file",
|
|
7644
|
+
"version_diff"
|
|
7005
7645
|
];
|
|
7006
7646
|
var PROJECT_READ_TOOLS = ["search_project_docs"];
|
|
7007
7647
|
var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
|
|
@@ -8003,8 +8643,11 @@ Documentation commands:
|
|
|
8003
8643
|
|
|
8004
8644
|
Code navigation commands:
|
|
8005
8645
|
pkgseer code find <pkg> [name] Find symbols by name
|
|
8006
|
-
pkgseer code search <pkg>
|
|
8646
|
+
pkgseer code search <pkg> [q] Search in package code
|
|
8007
8647
|
pkgseer code list <package> Browse package symbols
|
|
8648
|
+
pkgseer code files <package> List repository files
|
|
8649
|
+
pkgseer code grep <pkg> <f> <p> Search pattern in a file
|
|
8650
|
+
pkgseer code diff <pkg> <v> <v> Compare versions
|
|
8008
8651
|
pkgseer code callers <symbol> Find what calls a symbol
|
|
8009
8652
|
pkgseer code callees <symbol> Find what a symbol calls
|
|
8010
8653
|
pkgseer code imports <package> List package imports
|
|
@@ -8038,6 +8681,9 @@ var code = program.command("code").description("Code navigation commands");
|
|
|
8038
8681
|
registerCodeFindCommand(code);
|
|
8039
8682
|
registerCodeSearchCommand(code);
|
|
8040
8683
|
registerCodeListCommand(code);
|
|
8684
|
+
registerCodeFilesCommand(code);
|
|
8685
|
+
registerCodeGrepCommand(code);
|
|
8686
|
+
registerCodeDiffCommand(code);
|
|
8041
8687
|
registerCodeCallersCommand(code);
|
|
8042
8688
|
registerCodeCalleesCommand(code);
|
|
8043
8689
|
registerCodeImportsCommand(code);
|