@pkgseer/cli 0.4.10 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +496 -354
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-5nhq42tx.js → chunk-kh5enjt9.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-kh5enjt9.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
|
|
@@ -656,10 +660,12 @@ var SearchPackageDocsDocument = gql`
|
|
|
656
660
|
}
|
|
657
661
|
`;
|
|
658
662
|
var FindSymbolDocument = gql`
|
|
659
|
-
query FindSymbol($registry: Registry
|
|
663
|
+
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
664
|
findSymbol(
|
|
661
665
|
registry: $registry
|
|
662
666
|
packageName: $packageName
|
|
667
|
+
repoUrl: $repoUrl
|
|
668
|
+
gitRef: $gitRef
|
|
663
669
|
name: $name
|
|
664
670
|
namespace: $namespace
|
|
665
671
|
kind: $kind
|
|
@@ -697,10 +703,12 @@ var FindSymbolDocument = gql`
|
|
|
697
703
|
}
|
|
698
704
|
`;
|
|
699
705
|
var SearchSymbolsDocument = gql`
|
|
700
|
-
query SearchSymbols($registry: Registry
|
|
706
|
+
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
707
|
searchSymbols(
|
|
702
708
|
registry: $registry
|
|
703
709
|
packageName: $packageName
|
|
710
|
+
repoUrl: $repoUrl
|
|
711
|
+
gitRef: $gitRef
|
|
704
712
|
query: $query
|
|
705
713
|
keywords: $keywords
|
|
706
714
|
matchMode: $matchMode
|
|
@@ -743,10 +751,12 @@ var SearchSymbolsDocument = gql`
|
|
|
743
751
|
}
|
|
744
752
|
`;
|
|
745
753
|
var ListSymbolsDocument = gql`
|
|
746
|
-
query ListSymbols($registry: Registry
|
|
754
|
+
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
755
|
listSymbols(
|
|
748
756
|
registry: $registry
|
|
749
757
|
packageName: $packageName
|
|
758
|
+
repoUrl: $repoUrl
|
|
759
|
+
gitRef: $gitRef
|
|
750
760
|
scope: $scope
|
|
751
761
|
filePath: $filePath
|
|
752
762
|
namespace: $namespace
|
|
@@ -848,10 +858,12 @@ var SymbolDependentsDocument = gql`
|
|
|
848
858
|
}
|
|
849
859
|
`;
|
|
850
860
|
var PackageImportsDocument = gql`
|
|
851
|
-
query PackageImports($registry: Registry
|
|
861
|
+
query PackageImports($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $filePath: String, $resolvedOnly: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
|
|
852
862
|
packageImports(
|
|
853
863
|
registry: $registry
|
|
854
864
|
packageName: $packageName
|
|
865
|
+
repoUrl: $repoUrl
|
|
866
|
+
gitRef: $gitRef
|
|
855
867
|
filePath: $filePath
|
|
856
868
|
resolvedOnly: $resolvedOnly
|
|
857
869
|
limit: $limit
|
|
@@ -941,10 +953,12 @@ var SearchProjectDocsDocument = gql`
|
|
|
941
953
|
}
|
|
942
954
|
`;
|
|
943
955
|
var ListRepoFilesDocument = gql`
|
|
944
|
-
query ListRepoFiles($registry: Registry
|
|
956
|
+
query ListRepoFiles($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $version: String, $pathPrefix: String, $limit: Int, $waitTimeoutMs: Int) {
|
|
945
957
|
listRepoFiles(
|
|
946
958
|
registry: $registry
|
|
947
959
|
packageName: $packageName
|
|
960
|
+
repoUrl: $repoUrl
|
|
961
|
+
gitRef: $gitRef
|
|
948
962
|
version: $version
|
|
949
963
|
pathPrefix: $pathPrefix
|
|
950
964
|
limit: $limit
|
|
@@ -971,10 +985,12 @@ var ListRepoFilesDocument = gql`
|
|
|
971
985
|
}
|
|
972
986
|
`;
|
|
973
987
|
var GrepRepoFileDocument = gql`
|
|
974
|
-
query GrepRepoFile($registry: Registry
|
|
988
|
+
query GrepRepoFile($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $filePath: String!, $pattern: String!, $contextLines: Int, $maxMatches: Int, $version: String, $waitTimeoutMs: Int) {
|
|
975
989
|
grepRepoFile(
|
|
976
990
|
registry: $registry
|
|
977
991
|
packageName: $packageName
|
|
992
|
+
repoUrl: $repoUrl
|
|
993
|
+
gitRef: $gitRef
|
|
978
994
|
filePath: $filePath
|
|
979
995
|
pattern: $pattern
|
|
980
996
|
contextLines: $contextLines
|
|
@@ -1005,10 +1021,12 @@ var GrepRepoFileDocument = gql`
|
|
|
1005
1021
|
}
|
|
1006
1022
|
`;
|
|
1007
1023
|
var VersionDiffDocument = gql`
|
|
1008
|
-
query VersionDiff($registry: Registry
|
|
1024
|
+
query VersionDiff($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $fromVersion: String!, $toVersion: String!, $includePrivate: Boolean, $kind: SymbolKind, $limit: Int, $waitTimeoutMs: Int) {
|
|
1009
1025
|
versionDiff(
|
|
1010
1026
|
registry: $registry
|
|
1011
1027
|
packageName: $packageName
|
|
1028
|
+
repoUrl: $repoUrl
|
|
1029
|
+
gitRef: $gitRef
|
|
1012
1030
|
fromVersion: $fromVersion
|
|
1013
1031
|
toVersion: $toVersion
|
|
1014
1032
|
includePrivate: $includePrivate
|
|
@@ -1641,20 +1659,26 @@ var TOOL_NAMES = [
|
|
|
1641
1659
|
"fetch_package_doc",
|
|
1642
1660
|
"search",
|
|
1643
1661
|
"search_status",
|
|
1644
|
-
"
|
|
1662
|
+
"read_file",
|
|
1645
1663
|
"search_project_docs",
|
|
1664
|
+
"list_files",
|
|
1665
|
+
"grep_file",
|
|
1646
1666
|
"find_symbol",
|
|
1647
1667
|
"search_symbols",
|
|
1648
1668
|
"list_symbols",
|
|
1649
1669
|
"symbol_callers",
|
|
1650
1670
|
"symbol_callees",
|
|
1651
|
-
"
|
|
1671
|
+
"list_imports",
|
|
1652
1672
|
"call_path",
|
|
1653
1673
|
"trigger_indexing",
|
|
1654
|
-
"list_repo_files",
|
|
1655
|
-
"grep_repo_file",
|
|
1656
1674
|
"version_diff"
|
|
1657
1675
|
];
|
|
1676
|
+
var TOOL_NAME_MIGRATION = {
|
|
1677
|
+
fetch_code_context: "read_file",
|
|
1678
|
+
list_package_files: "list_files",
|
|
1679
|
+
grep_package_file: "grep_file",
|
|
1680
|
+
package_imports: "list_imports"
|
|
1681
|
+
};
|
|
1658
1682
|
var ToolNameSchema = z.enum(TOOL_NAMES);
|
|
1659
1683
|
var SharedConfigFields = {
|
|
1660
1684
|
enabled_tools: z.array(ToolNameSchema).optional()
|
|
@@ -1762,6 +1786,24 @@ class ConfigServiceImpl {
|
|
|
1762
1786
|
if (parsed === null || parsed === undefined) {
|
|
1763
1787
|
return schema.parse({});
|
|
1764
1788
|
}
|
|
1789
|
+
if (parsed && typeof parsed === "object" && Array.isArray(parsed.enabled_tools)) {
|
|
1790
|
+
const migrated = [];
|
|
1791
|
+
let hasMigrations = false;
|
|
1792
|
+
for (const name of parsed.enabled_tools) {
|
|
1793
|
+
const replacement = TOOL_NAME_MIGRATION[name];
|
|
1794
|
+
if (replacement) {
|
|
1795
|
+
migrated.push(replacement);
|
|
1796
|
+
hasMigrations = true;
|
|
1797
|
+
} else {
|
|
1798
|
+
migrated.push(name);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
if (hasMigrations) {
|
|
1802
|
+
const oldNames = parsed.enabled_tools.filter((n) => TOOL_NAME_MIGRATION[n]);
|
|
1803
|
+
console.warn(`[pkgseer] Config at ${path}: migrating deprecated tool names: ${oldNames.join(", ")}. Update your config to use the new names.`);
|
|
1804
|
+
parsed.enabled_tools = migrated;
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1765
1807
|
const result = schema.safeParse(parsed);
|
|
1766
1808
|
if (result.success) {
|
|
1767
1809
|
return result.data;
|
|
@@ -2207,9 +2249,13 @@ class PkgseerServiceImpl {
|
|
|
2207
2249
|
const result = await this.client.FetchCodeContext({
|
|
2208
2250
|
repoUrl,
|
|
2209
2251
|
gitRef,
|
|
2252
|
+
registry: options?.registry,
|
|
2253
|
+
packageName: options?.packageName,
|
|
2254
|
+
version: options?.version,
|
|
2210
2255
|
filePath,
|
|
2211
2256
|
startLine: options?.startLine,
|
|
2212
|
-
endLine: options?.endLine
|
|
2257
|
+
endLine: options?.endLine,
|
|
2258
|
+
waitTimeoutMs: options?.waitTimeoutMs
|
|
2213
2259
|
});
|
|
2214
2260
|
return { data: result.data, errors: result.errors };
|
|
2215
2261
|
}
|
|
@@ -2217,6 +2263,8 @@ class PkgseerServiceImpl {
|
|
|
2217
2263
|
const result = await this.client.FindSymbol({
|
|
2218
2264
|
registry,
|
|
2219
2265
|
packageName,
|
|
2266
|
+
repoUrl: options?.repoUrl,
|
|
2267
|
+
gitRef: options?.gitRef,
|
|
2220
2268
|
name: options?.name,
|
|
2221
2269
|
namespace: options?.namespace,
|
|
2222
2270
|
kind: options?.kind,
|
|
@@ -2233,6 +2281,8 @@ class PkgseerServiceImpl {
|
|
|
2233
2281
|
const result = await this.client.SearchSymbols({
|
|
2234
2282
|
registry,
|
|
2235
2283
|
packageName,
|
|
2284
|
+
repoUrl: options?.repoUrl,
|
|
2285
|
+
gitRef: options?.gitRef,
|
|
2236
2286
|
query: options?.query,
|
|
2237
2287
|
keywords: options?.keywords,
|
|
2238
2288
|
matchMode: options?.matchMode,
|
|
@@ -2249,6 +2299,8 @@ class PkgseerServiceImpl {
|
|
|
2249
2299
|
const result = await this.client.ListSymbols({
|
|
2250
2300
|
registry,
|
|
2251
2301
|
packageName,
|
|
2302
|
+
repoUrl: options?.repoUrl,
|
|
2303
|
+
gitRef: options?.gitRef,
|
|
2252
2304
|
scope,
|
|
2253
2305
|
filePath: options?.filePath,
|
|
2254
2306
|
namespace: options?.namespace,
|
|
@@ -2289,6 +2341,8 @@ class PkgseerServiceImpl {
|
|
|
2289
2341
|
const result = await this.client.PackageImports({
|
|
2290
2342
|
registry,
|
|
2291
2343
|
packageName,
|
|
2344
|
+
repoUrl: options?.repoUrl,
|
|
2345
|
+
gitRef: options?.gitRef,
|
|
2292
2346
|
filePath: options?.filePath,
|
|
2293
2347
|
resolvedOnly: options?.resolvedOnly,
|
|
2294
2348
|
limit: options?.limit,
|
|
@@ -2312,6 +2366,8 @@ class PkgseerServiceImpl {
|
|
|
2312
2366
|
const result = await this.client.ListRepoFiles({
|
|
2313
2367
|
registry,
|
|
2314
2368
|
packageName,
|
|
2369
|
+
repoUrl: options?.repoUrl,
|
|
2370
|
+
gitRef: options?.gitRef,
|
|
2315
2371
|
version: options?.version,
|
|
2316
2372
|
pathPrefix: options?.pathPrefix,
|
|
2317
2373
|
limit: options?.limit,
|
|
@@ -2323,6 +2379,8 @@ class PkgseerServiceImpl {
|
|
|
2323
2379
|
const result = await this.client.GrepRepoFile({
|
|
2324
2380
|
registry,
|
|
2325
2381
|
packageName,
|
|
2382
|
+
repoUrl: options?.repoUrl,
|
|
2383
|
+
gitRef: options?.gitRef,
|
|
2326
2384
|
filePath,
|
|
2327
2385
|
pattern,
|
|
2328
2386
|
contextLines: options?.contextLines,
|
|
@@ -2336,6 +2394,8 @@ class PkgseerServiceImpl {
|
|
|
2336
2394
|
const result = await this.client.VersionDiff({
|
|
2337
2395
|
registry,
|
|
2338
2396
|
packageName,
|
|
2397
|
+
repoUrl: options?.repoUrl,
|
|
2398
|
+
gitRef: options?.gitRef,
|
|
2339
2399
|
fromVersion,
|
|
2340
2400
|
toVersion,
|
|
2341
2401
|
includePrivate: options?.includePrivate,
|
|
@@ -2749,8 +2809,8 @@ function outputError(message, json) {
|
|
|
2749
2809
|
}
|
|
2750
2810
|
var CLI_HINTS = {
|
|
2751
2811
|
being_indexed: " Hint: package is being indexed. Try again with a longer --wait value (e.g., --wait 30000).",
|
|
2752
|
-
timeout: " Hint:
|
|
2753
|
-
not_found: " Hint: verify the name
|
|
2812
|
+
timeout: " Hint: this may be transient — retry the same command. If the issue persists, try simplifying the query.",
|
|
2813
|
+
not_found: " Hint: verify the package name and registry are correct.",
|
|
2754
2814
|
auth: " Hint: check login or token validity (pkgseer auth-status).",
|
|
2755
2815
|
rate_limit: " Hint: wait and retry, or reduce request frequency.",
|
|
2756
2816
|
unknown: ""
|
|
@@ -3007,14 +3067,10 @@ async function codeCalleesAction(symbolArg, options, deps) {
|
|
|
3007
3067
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3008
3068
|
});
|
|
3009
3069
|
handleErrors(result.errors, options.json ?? false);
|
|
3010
|
-
if (!result.data?.symbolDependencies) {
|
|
3011
|
-
outputError("Symbol not found. Verify the symbol reference or use --ref.", options.json ?? false);
|
|
3012
|
-
return;
|
|
3013
|
-
}
|
|
3014
3070
|
if (options.json) {
|
|
3015
|
-
output(result.data
|
|
3071
|
+
output(result.data.symbolDependencies, true);
|
|
3016
3072
|
} else {
|
|
3017
|
-
console.log(formatCalleesResult(result.data
|
|
3073
|
+
console.log(formatCalleesResult(result.data.symbolDependencies));
|
|
3018
3074
|
}
|
|
3019
3075
|
}
|
|
3020
3076
|
var CALLEES_DESCRIPTION = `Find what a symbol calls.
|
|
@@ -3058,14 +3114,10 @@ async function codeCallersAction(symbolArg, options, deps) {
|
|
|
3058
3114
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3059
3115
|
});
|
|
3060
3116
|
handleErrors(result.errors, options.json ?? false);
|
|
3061
|
-
if (!result.data?.symbolDependents) {
|
|
3062
|
-
outputError("Symbol not found. Verify the symbol reference or use --ref.", options.json ?? false);
|
|
3063
|
-
return;
|
|
3064
|
-
}
|
|
3065
3117
|
if (options.json) {
|
|
3066
|
-
output(result.data
|
|
3118
|
+
output(result.data.symbolDependents, true);
|
|
3067
3119
|
} else {
|
|
3068
|
-
console.log(formatCallersResult(result.data
|
|
3120
|
+
console.log(formatCallersResult(result.data.symbolDependents));
|
|
3069
3121
|
}
|
|
3070
3122
|
}
|
|
3071
3123
|
var CALLERS_DESCRIPTION = `Find what calls a symbol.
|
|
@@ -3130,14 +3182,10 @@ async function codeDiffAction(packageArg, fromVersion, toVersion, options, deps)
|
|
|
3130
3182
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3131
3183
|
});
|
|
3132
3184
|
handleErrors(result.errors, options.json ?? false);
|
|
3133
|
-
if (!result.data?.versionDiff) {
|
|
3134
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3135
|
-
return;
|
|
3136
|
-
}
|
|
3137
3185
|
if (options.json) {
|
|
3138
|
-
output(result.data
|
|
3186
|
+
output(result.data.versionDiff, true);
|
|
3139
3187
|
} else {
|
|
3140
|
-
console.log(formatDiffResult(result.data
|
|
3188
|
+
console.log(formatDiffResult(result.data.versionDiff));
|
|
3141
3189
|
}
|
|
3142
3190
|
}
|
|
3143
3191
|
var DIFF_DESCRIPTION = `Compare symbols between two package versions.
|
|
@@ -3190,11 +3238,7 @@ async function codeFilesAction(packageArg, options, deps) {
|
|
|
3190
3238
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3191
3239
|
});
|
|
3192
3240
|
handleErrors(result.errors, options.json ?? false);
|
|
3193
|
-
|
|
3194
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3195
|
-
return;
|
|
3196
|
-
}
|
|
3197
|
-
const data = result.data?.listRepoFiles;
|
|
3241
|
+
const data = result.data.listRepoFiles;
|
|
3198
3242
|
if (options.json) {
|
|
3199
3243
|
output(data, true);
|
|
3200
3244
|
} else {
|
|
@@ -3255,11 +3299,7 @@ async function codeFindAction(packageArg, nameArg, options, deps) {
|
|
|
3255
3299
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3256
3300
|
});
|
|
3257
3301
|
handleErrors(result.errors, options.json ?? false);
|
|
3258
|
-
|
|
3259
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3260
|
-
return;
|
|
3261
|
-
}
|
|
3262
|
-
const data = result.data?.findSymbol;
|
|
3302
|
+
const data = result.data.findSymbol;
|
|
3263
3303
|
if (options.json) {
|
|
3264
3304
|
output(data, true);
|
|
3265
3305
|
} else {
|
|
@@ -3329,11 +3369,7 @@ async function codeGrepAction(packageArg, filePath, pattern, options, deps) {
|
|
|
3329
3369
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3330
3370
|
});
|
|
3331
3371
|
handleErrors(result.errors, options.json ?? false);
|
|
3332
|
-
|
|
3333
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3334
|
-
return;
|
|
3335
|
-
}
|
|
3336
|
-
const data = result.data?.grepRepoFile;
|
|
3372
|
+
const data = result.data.grepRepoFile;
|
|
3337
3373
|
if (options.json) {
|
|
3338
3374
|
output(data, true);
|
|
3339
3375
|
} else {
|
|
@@ -3416,14 +3452,10 @@ async function codeImportsAction(packageArg, options, deps) {
|
|
|
3416
3452
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3417
3453
|
});
|
|
3418
3454
|
handleErrors(result.errors, options.json ?? false);
|
|
3419
|
-
if (!result.data?.packageImports) {
|
|
3420
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3421
|
-
return;
|
|
3422
|
-
}
|
|
3423
3455
|
if (options.json) {
|
|
3424
|
-
output(result.data
|
|
3456
|
+
output(result.data.packageImports, true);
|
|
3425
3457
|
} else {
|
|
3426
|
-
console.log(formatImportsResult(result.data
|
|
3458
|
+
console.log(formatImportsResult(result.data.packageImports));
|
|
3427
3459
|
}
|
|
3428
3460
|
}
|
|
3429
3461
|
var IMPORTS_DESCRIPTION = `List import statements in a package.
|
|
@@ -3485,14 +3517,10 @@ async function codeListAction(packageArg, options, deps) {
|
|
|
3485
3517
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3486
3518
|
});
|
|
3487
3519
|
handleErrors(result.errors, options.json ?? false);
|
|
3488
|
-
if (!result.data?.listSymbols) {
|
|
3489
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3490
|
-
return;
|
|
3491
|
-
}
|
|
3492
3520
|
if (options.json) {
|
|
3493
|
-
output(result.data
|
|
3521
|
+
output(result.data.listSymbols, true);
|
|
3494
3522
|
} else {
|
|
3495
|
-
console.log(formatListResult(result.data
|
|
3523
|
+
console.log(formatListResult(result.data.listSymbols));
|
|
3496
3524
|
}
|
|
3497
3525
|
}
|
|
3498
3526
|
var LIST_DESCRIPTION = `Browse symbols in a package.
|
|
@@ -3550,14 +3578,10 @@ async function codePathAction(fromArg, toArg, options, deps) {
|
|
|
3550
3578
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3551
3579
|
});
|
|
3552
3580
|
handleErrors(result.errors, options.json ?? false);
|
|
3553
|
-
if (!result.data?.callPath) {
|
|
3554
|
-
outputError("Could not find call path. Verify the symbol references.", options.json ?? false);
|
|
3555
|
-
return;
|
|
3556
|
-
}
|
|
3557
3581
|
if (options.json) {
|
|
3558
|
-
output(result.data
|
|
3582
|
+
output(result.data.callPath, true);
|
|
3559
3583
|
} else {
|
|
3560
|
-
console.log(formatPathResult(result.data
|
|
3584
|
+
console.log(formatPathResult(result.data.callPath));
|
|
3561
3585
|
}
|
|
3562
3586
|
}
|
|
3563
3587
|
var PATH_DESCRIPTION = `Find call path between two symbols.
|
|
@@ -3630,11 +3654,7 @@ async function codeSearchAction(packageArg, query, options, deps) {
|
|
|
3630
3654
|
waitTimeoutMs: parseWaitTimeout(options.wait)
|
|
3631
3655
|
});
|
|
3632
3656
|
handleErrors(result.errors, options.json ?? false);
|
|
3633
|
-
|
|
3634
|
-
outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
|
|
3635
|
-
return;
|
|
3636
|
-
}
|
|
3637
|
-
const data = result.data?.searchSymbols;
|
|
3657
|
+
const data = result.data.searchSymbols;
|
|
3638
3658
|
if (options.json) {
|
|
3639
3659
|
output(data, true);
|
|
3640
3660
|
} else {
|
|
@@ -5118,7 +5138,7 @@ async function setupCodexViaCli(shellService) {
|
|
|
5118
5138
|
}
|
|
5119
5139
|
function showAvailableTools(hasProject, useColors) {
|
|
5120
5140
|
console.log(`
|
|
5121
|
-
Available MCP tools (
|
|
5141
|
+
Available MCP tools (22):`);
|
|
5122
5142
|
console.log("");
|
|
5123
5143
|
console.log(" Navigate source:");
|
|
5124
5144
|
console.log(" • find_symbol - Read source code of functions/classes");
|
|
@@ -5129,8 +5149,8 @@ Available MCP tools (21):`);
|
|
|
5129
5149
|
console.log(" • call_path - Find call path between two functions");
|
|
5130
5150
|
console.log("");
|
|
5131
5151
|
console.log(" Browse files:");
|
|
5132
|
-
console.log(" •
|
|
5133
|
-
console.log(" •
|
|
5152
|
+
console.log(" • list_package_files - Explore package file structure");
|
|
5153
|
+
console.log(" • grep_package_file - Search for patterns in source files");
|
|
5134
5154
|
console.log(" • fetch_code_context - Read source by file path and line range");
|
|
5135
5155
|
console.log("");
|
|
5136
5156
|
console.log(" Search & docs:");
|
|
@@ -6782,27 +6802,99 @@ function toListScope(scope) {
|
|
|
6782
6802
|
var schemas = {
|
|
6783
6803
|
registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).describe("Package registry (npm, pypi, hex, crates, nuget, maven, zig, or vcpkg)"),
|
|
6784
6804
|
packageName: z2.string().max(255).describe("Name of the package"),
|
|
6785
|
-
version: z2.string().max(100).optional().describe("Specific version (defaults to latest)"),
|
|
6805
|
+
version: z2.string().max(100).optional().describe("Specific version, e.g. '4.18.2' (defaults to latest)"),
|
|
6786
6806
|
navigationMode: z2.enum(["summary", "detailed"]).optional().describe("Response detail level. summary (default) returns core fields; detailed adds all optional fields."),
|
|
6787
|
-
waitTimeoutMs: z2.number().int().min(0).max(30000).optional().describe("Max milliseconds to wait for package indexing (0-30000). 0
|
|
6807
|
+
waitTimeoutMs: z2.coerce.number().int().min(0).max(30000).optional().describe("Max milliseconds to wait for package indexing (0-30000, default 10000). Set 0 to error immediately if not indexed."),
|
|
6788
6808
|
symbolReference: z2.object({
|
|
6789
6809
|
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."),
|
|
6790
|
-
registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (
|
|
6791
|
-
package_name: z2.string().max(255).optional().describe("Package name (
|
|
6792
|
-
symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath.")
|
|
6793
|
-
|
|
6810
|
+
registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry. For package-scoped lookup (with package_name + symbol_name)."),
|
|
6811
|
+
package_name: z2.string().max(255).optional().describe("Package name. For package-scoped lookup (with registry + symbol_name)."),
|
|
6812
|
+
symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath."),
|
|
6813
|
+
version: z2.string().max(100).optional().describe("Package version. For package-scoped lookup."),
|
|
6814
|
+
repo_url: z2.string().optional().describe("Repository URL (GitHub). For repo-scoped lookup (with git_ref + symbol_name)."),
|
|
6815
|
+
git_ref: z2.string().optional().describe("Git ref (tag, branch, commit, or HEAD). Required with repo_url.")
|
|
6816
|
+
}),
|
|
6817
|
+
codeTarget: z2.object({
|
|
6818
|
+
registry: z2.enum([
|
|
6819
|
+
"npm",
|
|
6820
|
+
"pypi",
|
|
6821
|
+
"hex",
|
|
6822
|
+
"crates",
|
|
6823
|
+
"nuget",
|
|
6824
|
+
"maven",
|
|
6825
|
+
"zig",
|
|
6826
|
+
"vcpkg"
|
|
6827
|
+
]).optional().describe("Package registry (npm, pypi, hex, etc.). Required for package scope."),
|
|
6828
|
+
package_name: z2.string().max(255).optional().describe("Package name. Required for package scope."),
|
|
6829
|
+
version: z2.string().max(100).optional().describe("Package version, e.g. '4.18.2' (defaults to latest). For package scope only."),
|
|
6830
|
+
repo_url: z2.string().optional().describe("Repository URL (GitHub). Required for repo scope. Example: https://github.com/expressjs/express"),
|
|
6831
|
+
git_ref: z2.string().optional().describe("Git ref — tag, branch, or commit. Required for repo scope. Use HEAD for latest.")
|
|
6832
|
+
}).describe("Target: provide registry + package_name (package scope) OR repo_url + git_ref (repo scope).")
|
|
6794
6833
|
};
|
|
6795
6834
|
function toSymbolReferenceInput(ref) {
|
|
6796
6835
|
return {
|
|
6797
6836
|
symbolRef: ref.symbol_ref,
|
|
6798
6837
|
registry: ref.registry ? toGraphQLRegistry(ref.registry) : undefined,
|
|
6799
6838
|
packageName: ref.package_name,
|
|
6800
|
-
symbolName: ref.symbol_name
|
|
6839
|
+
symbolName: ref.symbol_name,
|
|
6840
|
+
version: ref.version,
|
|
6841
|
+
repoUrl: ref.repo_url,
|
|
6842
|
+
gitRef: ref.git_ref
|
|
6843
|
+
};
|
|
6844
|
+
}
|
|
6845
|
+
function isToolError(value) {
|
|
6846
|
+
return "content" in value;
|
|
6847
|
+
}
|
|
6848
|
+
function resolveCodeTarget(target) {
|
|
6849
|
+
const hasPackage = target.registry || target.package_name;
|
|
6850
|
+
const hasRepo = target.repo_url || target.git_ref;
|
|
6851
|
+
if (hasPackage && hasRepo) {
|
|
6852
|
+
return errorResult("Invalid target: provide either registry + package_name (package scope) or repo_url + git_ref (repo scope), not both.");
|
|
6853
|
+
}
|
|
6854
|
+
if (!hasPackage && !hasRepo) {
|
|
6855
|
+
return errorResult("Missing target: provide registry + package_name (package scope) or repo_url + git_ref (repo scope).");
|
|
6856
|
+
}
|
|
6857
|
+
if (hasPackage) {
|
|
6858
|
+
if (!target.registry || !target.package_name) {
|
|
6859
|
+
return errorResult("Incomplete package target: both registry and package_name are required for package scope.");
|
|
6860
|
+
}
|
|
6861
|
+
return {
|
|
6862
|
+
mode: "package",
|
|
6863
|
+
registry: target.registry,
|
|
6864
|
+
packageName: target.package_name,
|
|
6865
|
+
version: target.version
|
|
6866
|
+
};
|
|
6867
|
+
}
|
|
6868
|
+
if (!target.repo_url) {
|
|
6869
|
+
return errorResult("Incomplete repo target: repo_url is required with git_ref.");
|
|
6870
|
+
}
|
|
6871
|
+
if (!target.git_ref) {
|
|
6872
|
+
return errorResult("Incomplete repo target: git_ref is required with repo_url (use HEAD for latest).");
|
|
6873
|
+
}
|
|
6874
|
+
return { mode: "repo", repoUrl: target.repo_url, gitRef: target.git_ref };
|
|
6875
|
+
}
|
|
6876
|
+
function buildCodeTargetVars(resolved) {
|
|
6877
|
+
if (resolved.mode === "package") {
|
|
6878
|
+
return {
|
|
6879
|
+
registry: toGraphQLRegistry(resolved.registry),
|
|
6880
|
+
packageName: resolved.packageName,
|
|
6881
|
+
version: resolved.version,
|
|
6882
|
+
repoUrl: undefined,
|
|
6883
|
+
gitRef: undefined
|
|
6884
|
+
};
|
|
6885
|
+
}
|
|
6886
|
+
return {
|
|
6887
|
+
registry: undefined,
|
|
6888
|
+
packageName: undefined,
|
|
6889
|
+
version: undefined,
|
|
6890
|
+
repoUrl: resolved.repoUrl,
|
|
6891
|
+
gitRef: resolved.gitRef
|
|
6801
6892
|
};
|
|
6802
6893
|
}
|
|
6894
|
+
var DEFAULT_WAIT_TIMEOUT_MS2 = 1e4;
|
|
6803
6895
|
var MCP_HINTS = {
|
|
6804
6896
|
being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
|
|
6805
|
-
timeout: "Hint:
|
|
6897
|
+
timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
|
|
6806
6898
|
};
|
|
6807
6899
|
function buildHintedMessage(operation, message) {
|
|
6808
6900
|
const kind = classifyError(message);
|
|
@@ -6830,9 +6922,9 @@ function buildHintedMessage(operation, message) {
|
|
|
6830
6922
|
return `Failed to ${operation}: ${message}`;
|
|
6831
6923
|
}
|
|
6832
6924
|
var MCP_GRAPHQL_HINTS = {
|
|
6833
|
-
not_found: "Hint: verify the name
|
|
6925
|
+
not_found: "Hint: verify the package name and registry are correct.",
|
|
6834
6926
|
being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
|
|
6835
|
-
timeout: "Hint:
|
|
6927
|
+
timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
|
|
6836
6928
|
};
|
|
6837
6929
|
function handleGraphQLErrors(errors) {
|
|
6838
6930
|
if (errors && errors.length > 0) {
|
|
@@ -6852,45 +6944,42 @@ async function withErrorHandling(operation, fn) {
|
|
|
6852
6944
|
}
|
|
6853
6945
|
}
|
|
6854
6946
|
function notFoundError(packageName, registry) {
|
|
6855
|
-
return errorResult(`Package not found: ${packageName} in ${registry}
|
|
6947
|
+
return errorResult(`Package not found: ${packageName} in ${registry}. Verify the package name and registry are correct.`);
|
|
6856
6948
|
}
|
|
6857
6949
|
|
|
6858
6950
|
// src/tools/call-path.ts
|
|
6859
6951
|
var argsSchema = {
|
|
6860
|
-
from: schemas.symbolReference.describe("Source symbol. Provide
|
|
6861
|
-
to: schemas.symbolReference.describe("Destination symbol. Provide
|
|
6862
|
-
max_depth: z3.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
|
|
6952
|
+
from: schemas.symbolReference.describe("Source symbol. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
|
|
6953
|
+
to: schemas.symbolReference.describe("Destination symbol. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
|
|
6954
|
+
max_depth: z3.coerce.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
|
|
6863
6955
|
mode: schemas.navigationMode,
|
|
6864
6956
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
6865
6957
|
};
|
|
6866
6958
|
function createCallPathTool(pkgseerService) {
|
|
6867
6959
|
return {
|
|
6868
6960
|
name: "call_path",
|
|
6869
|
-
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.",
|
|
6961
|
+
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.",
|
|
6870
6962
|
schema: argsSchema,
|
|
6871
6963
|
annotations: { readOnlyHint: true },
|
|
6872
6964
|
handler: async (args, _extra) => {
|
|
6873
6965
|
return withErrorHandling("find call path", async () => {
|
|
6874
6966
|
const fromInput = toSymbolReferenceInput(args.from);
|
|
6875
6967
|
const toInput = toSymbolReferenceInput(args.to);
|
|
6876
|
-
if (!fromInput.symbolRef && (
|
|
6877
|
-
return errorResult("Invalid 'from' symbol: provide
|
|
6968
|
+
if (!fromInput.symbolRef && !(fromInput.symbolName && fromInput.registry && fromInput.packageName) && !(fromInput.symbolName && fromInput.repoUrl && fromInput.gitRef)) {
|
|
6969
|
+
return errorResult("Invalid 'from' symbol: provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
6878
6970
|
}
|
|
6879
|
-
if (!toInput.symbolRef && (
|
|
6880
|
-
return errorResult("Invalid 'to' symbol: provide
|
|
6971
|
+
if (!toInput.symbolRef && !(toInput.symbolName && toInput.registry && toInput.packageName) && !(toInput.symbolName && toInput.repoUrl && toInput.gitRef)) {
|
|
6972
|
+
return errorResult("Invalid 'to' symbol: provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
6881
6973
|
}
|
|
6882
6974
|
const result = await pkgseerService.callPath(fromInput, toInput, {
|
|
6883
6975
|
maxDepth: args.max_depth,
|
|
6884
6976
|
mode: toNavigationMode(args.mode),
|
|
6885
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
6977
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
6886
6978
|
});
|
|
6887
6979
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
6888
6980
|
if (graphqlError)
|
|
6889
6981
|
return graphqlError;
|
|
6890
|
-
|
|
6891
|
-
return errorResult("Could not find call path. Verify the symbols exist and the package is indexed.");
|
|
6892
|
-
}
|
|
6893
|
-
return textResult(JSON.stringify(result.data?.callPath, null, 2));
|
|
6982
|
+
return textResult(JSON.stringify(result.data.callPath, null, 2));
|
|
6894
6983
|
});
|
|
6895
6984
|
}
|
|
6896
6985
|
};
|
|
@@ -6908,7 +6997,7 @@ var argsSchema2 = {
|
|
|
6908
6997
|
function createComparePackagesTool(pkgseerService) {
|
|
6909
6998
|
return {
|
|
6910
6999
|
name: "compare_packages",
|
|
6911
|
-
description: "Compare 2-10 packages side-by-side. Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex, crates). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
|
|
7000
|
+
description: "Compare 2-10 packages side-by-side (available immediately — no indexing required). " + "Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex, crates). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
|
|
6912
7001
|
schema: argsSchema2,
|
|
6913
7002
|
annotations: { readOnlyHint: true },
|
|
6914
7003
|
handler: async ({ packages }, _extra) => {
|
|
@@ -6930,48 +7019,16 @@ function createComparePackagesTool(pkgseerService) {
|
|
|
6930
7019
|
}
|
|
6931
7020
|
};
|
|
6932
7021
|
}
|
|
6933
|
-
// src/tools/fetch-
|
|
7022
|
+
// src/tools/fetch-package-doc.ts
|
|
6934
7023
|
import { z as z5 } from "zod";
|
|
6935
7024
|
var argsSchema3 = {
|
|
6936
|
-
|
|
6937
|
-
git_ref: z5.string().min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
|
|
6938
|
-
file_path: z5.string().min(1).describe("Path to file in repository. Example: src/router/index.js"),
|
|
6939
|
-
start_line: z5.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
|
|
6940
|
-
end_line: z5.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
|
|
6941
|
-
};
|
|
6942
|
-
function createFetchCodeContextTool(pkgseerService) {
|
|
6943
|
-
return {
|
|
6944
|
-
name: "fetch_code_context",
|
|
6945
|
-
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, git_ref, and file_path.",
|
|
6946
|
-
schema: argsSchema3,
|
|
6947
|
-
annotations: { readOnlyHint: true },
|
|
6948
|
-
handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
|
|
6949
|
-
return withErrorHandling("fetch code context", async () => {
|
|
6950
|
-
const result = await pkgseerService.fetchCodeContext(repo_url, git_ref, file_path, {
|
|
6951
|
-
startLine: start_line,
|
|
6952
|
-
endLine: end_line
|
|
6953
|
-
});
|
|
6954
|
-
const graphqlError = handleGraphQLErrors(result.errors);
|
|
6955
|
-
if (graphqlError)
|
|
6956
|
-
return graphqlError;
|
|
6957
|
-
if (!result.data?.fetchCodeContext) {
|
|
6958
|
-
return errorResult(`Code not found: ${file_path} at ${git_ref} in ${repo_url}. ` + "Check that the repository, file path, and git ref are correct.");
|
|
6959
|
-
}
|
|
6960
|
-
return textResult(JSON.stringify(result.data?.fetchCodeContext, null, 2));
|
|
6961
|
-
});
|
|
6962
|
-
}
|
|
6963
|
-
};
|
|
6964
|
-
}
|
|
6965
|
-
// src/tools/fetch-package-doc.ts
|
|
6966
|
-
import { z as z6 } from "zod";
|
|
6967
|
-
var argsSchema4 = {
|
|
6968
|
-
page_id: z6.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
|
|
7025
|
+
page_id: z5.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
|
|
6969
7026
|
};
|
|
6970
7027
|
function createFetchPackageDocTool(pkgseerService) {
|
|
6971
7028
|
return {
|
|
6972
7029
|
name: "fetch_package_doc",
|
|
6973
|
-
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.",
|
|
6974
|
-
schema:
|
|
7030
|
+
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.",
|
|
7031
|
+
schema: argsSchema3,
|
|
6975
7032
|
annotations: { readOnlyHint: true },
|
|
6976
7033
|
handler: async ({ page_id }, _extra) => {
|
|
6977
7034
|
return withErrorHandling("fetch documentation page", async () => {
|
|
@@ -6988,13 +7045,12 @@ function createFetchPackageDocTool(pkgseerService) {
|
|
|
6988
7045
|
};
|
|
6989
7046
|
}
|
|
6990
7047
|
// src/tools/find-symbol.ts
|
|
6991
|
-
import { z as
|
|
6992
|
-
var
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
kind: z7.enum([
|
|
7048
|
+
import { z as z6 } from "zod";
|
|
7049
|
+
var argsSchema4 = {
|
|
7050
|
+
target: schemas.codeTarget,
|
|
7051
|
+
name: z6.string().max(500).optional().describe("Symbol name to search for (exact match or prefix). Omit to return all public exports."),
|
|
7052
|
+
namespace: z6.string().max(500).optional().describe("Filter by namespace/module path prefix"),
|
|
7053
|
+
kind: z6.enum([
|
|
6998
7054
|
"function",
|
|
6999
7055
|
"method",
|
|
7000
7056
|
"class",
|
|
@@ -7003,39 +7059,41 @@ var argsSchema5 = {
|
|
|
7003
7059
|
"type",
|
|
7004
7060
|
"doc_section"
|
|
7005
7061
|
]).optional().describe("Filter by symbol kind"),
|
|
7006
|
-
public_only:
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
context_lines: z7.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
|
|
7062
|
+
public_only: z6.boolean().optional().describe("Only return public/exported symbols"),
|
|
7063
|
+
include_code: z6.boolean().optional().describe("Include source code in results"),
|
|
7064
|
+
context_lines: z6.coerce.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
|
|
7010
7065
|
mode: schemas.navigationMode,
|
|
7011
7066
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7012
7067
|
};
|
|
7013
7068
|
function createFindSymbolTool(pkgseerService) {
|
|
7014
7069
|
return {
|
|
7015
7070
|
name: "find_symbol",
|
|
7016
|
-
description: "Read source code of any function, class, or method
|
|
7017
|
-
schema:
|
|
7071
|
+
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.",
|
|
7072
|
+
schema: argsSchema4,
|
|
7018
7073
|
annotations: { readOnlyHint: true },
|
|
7019
7074
|
handler: async (args, _extra) => {
|
|
7020
7075
|
return withErrorHandling("find symbol", async () => {
|
|
7021
|
-
const
|
|
7076
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7077
|
+
if (isToolError(resolved))
|
|
7078
|
+
return resolved;
|
|
7079
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7080
|
+
const result = await pkgseerService.findSymbol(tv.registry, tv.packageName, {
|
|
7022
7081
|
name: args.name,
|
|
7023
7082
|
namespace: args.namespace,
|
|
7024
7083
|
kind: toSymbolKind(args.kind),
|
|
7025
7084
|
publicOnly: args.public_only,
|
|
7026
|
-
version:
|
|
7085
|
+
version: tv.version,
|
|
7027
7086
|
includeCode: args.include_code,
|
|
7028
7087
|
contextLines: args.context_lines,
|
|
7029
7088
|
mode: toNavigationMode(args.mode),
|
|
7030
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7089
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7090
|
+
repoUrl: tv.repoUrl,
|
|
7091
|
+
gitRef: tv.gitRef
|
|
7031
7092
|
});
|
|
7032
7093
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7033
7094
|
if (graphqlError)
|
|
7034
7095
|
return graphqlError;
|
|
7035
|
-
|
|
7036
|
-
return notFoundError(args.package_name, args.registry);
|
|
7037
|
-
}
|
|
7038
|
-
const data = result.data?.findSymbol;
|
|
7096
|
+
const data = result.data.findSymbol;
|
|
7039
7097
|
if (data.symbols.length === 0 && data.diagnostics?.hint) {
|
|
7040
7098
|
return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
|
|
7041
7099
|
}
|
|
@@ -7044,39 +7102,40 @@ function createFindSymbolTool(pkgseerService) {
|
|
|
7044
7102
|
}
|
|
7045
7103
|
};
|
|
7046
7104
|
}
|
|
7047
|
-
// src/tools/grep-
|
|
7048
|
-
import { z as
|
|
7049
|
-
var
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
max_matches: z8.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
|
|
7056
|
-
version: schemas.version,
|
|
7105
|
+
// src/tools/grep-file.ts
|
|
7106
|
+
import { z as z7 } from "zod";
|
|
7107
|
+
var argsSchema5 = {
|
|
7108
|
+
target: schemas.codeTarget,
|
|
7109
|
+
file_path: z7.string().describe("Path to the file (relative to package root)"),
|
|
7110
|
+
pattern: z7.string().max(200).describe("Case-insensitive substring to search for (max 200 chars)"),
|
|
7111
|
+
context_lines: z7.coerce.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
|
|
7112
|
+
max_matches: z7.coerce.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
|
|
7057
7113
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7058
7114
|
};
|
|
7059
|
-
function
|
|
7115
|
+
function createGrepFileTool(pkgseerService) {
|
|
7060
7116
|
return {
|
|
7061
|
-
name: "
|
|
7062
|
-
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. " + "
|
|
7063
|
-
schema:
|
|
7117
|
+
name: "grep_file",
|
|
7118
|
+
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.",
|
|
7119
|
+
schema: argsSchema5,
|
|
7064
7120
|
annotations: { readOnlyHint: true },
|
|
7065
7121
|
handler: async (args, _extra) => {
|
|
7066
|
-
return withErrorHandling("grep
|
|
7067
|
-
const
|
|
7122
|
+
return withErrorHandling("grep file", async () => {
|
|
7123
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7124
|
+
if (isToolError(resolved))
|
|
7125
|
+
return resolved;
|
|
7126
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7127
|
+
const result = await pkgseerService.grepRepoFile(tv.registry, tv.packageName, args.file_path, args.pattern, {
|
|
7068
7128
|
contextLines: args.context_lines,
|
|
7069
7129
|
maxMatches: args.max_matches,
|
|
7070
|
-
version:
|
|
7071
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7130
|
+
version: tv.version,
|
|
7131
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7132
|
+
repoUrl: tv.repoUrl,
|
|
7133
|
+
gitRef: tv.gitRef
|
|
7072
7134
|
});
|
|
7073
7135
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7074
7136
|
if (graphqlError)
|
|
7075
7137
|
return graphqlError;
|
|
7076
|
-
|
|
7077
|
-
return notFoundError(args.package_name, args.registry);
|
|
7078
|
-
}
|
|
7079
|
-
const data = result.data?.grepRepoFile;
|
|
7138
|
+
const data = result.data.grepRepoFile;
|
|
7080
7139
|
if (data.matches.length === 0 && data.diagnostics?.hint) {
|
|
7081
7140
|
return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
|
|
7082
7141
|
}
|
|
@@ -7085,67 +7144,108 @@ function createGrepRepoFileTool(pkgseerService) {
|
|
|
7085
7144
|
}
|
|
7086
7145
|
};
|
|
7087
7146
|
}
|
|
7088
|
-
// src/tools/list-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7147
|
+
// src/tools/list-files.ts
|
|
7148
|
+
import { z as z8 } from "zod";
|
|
7149
|
+
var argsSchema6 = {
|
|
7150
|
+
target: schemas.codeTarget,
|
|
7151
|
+
path_prefix: z8.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
|
|
7152
|
+
limit: z8.coerce.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
|
|
7153
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7093
7154
|
};
|
|
7094
|
-
function
|
|
7155
|
+
function createListFilesTool(pkgseerService) {
|
|
7095
7156
|
return {
|
|
7096
|
-
name: "
|
|
7097
|
-
description: "
|
|
7098
|
-
schema:
|
|
7157
|
+
name: "list_files",
|
|
7158
|
+
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.",
|
|
7159
|
+
schema: argsSchema6,
|
|
7099
7160
|
annotations: { readOnlyHint: true },
|
|
7100
|
-
handler: async (
|
|
7101
|
-
return withErrorHandling("list
|
|
7102
|
-
const
|
|
7161
|
+
handler: async (args, _extra) => {
|
|
7162
|
+
return withErrorHandling("list files", async () => {
|
|
7163
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7164
|
+
if (isToolError(resolved))
|
|
7165
|
+
return resolved;
|
|
7166
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7167
|
+
const result = await pkgseerService.listRepoFiles(tv.registry, tv.packageName, {
|
|
7168
|
+
version: tv.version,
|
|
7169
|
+
pathPrefix: args.path_prefix,
|
|
7170
|
+
limit: args.limit,
|
|
7171
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7172
|
+
repoUrl: tv.repoUrl,
|
|
7173
|
+
gitRef: tv.gitRef
|
|
7174
|
+
});
|
|
7103
7175
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7104
7176
|
if (graphqlError)
|
|
7105
7177
|
return graphqlError;
|
|
7106
|
-
|
|
7107
|
-
|
|
7178
|
+
const data = result.data.listRepoFiles;
|
|
7179
|
+
if (data.files.length === 0 && data.diagnostics?.hint) {
|
|
7180
|
+
return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
|
|
7108
7181
|
}
|
|
7109
|
-
return textResult(JSON.stringify(
|
|
7182
|
+
return textResult(JSON.stringify(data, null, 2));
|
|
7110
7183
|
});
|
|
7111
7184
|
}
|
|
7112
7185
|
};
|
|
7113
7186
|
}
|
|
7114
|
-
// src/tools/list-
|
|
7187
|
+
// src/tools/list-imports.ts
|
|
7115
7188
|
import { z as z9 } from "zod";
|
|
7116
|
-
var
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7189
|
+
var argsSchema7 = {
|
|
7190
|
+
target: schemas.codeTarget,
|
|
7191
|
+
file_path: z9.string().max(1000).optional().describe("Filter to a specific file path"),
|
|
7192
|
+
resolved_only: z9.boolean().optional().describe("Only return imports resolved to a known package"),
|
|
7193
|
+
limit: z9.coerce.number().int().min(1).max(500).optional().describe("Max imports to return"),
|
|
7194
|
+
mode: schemas.navigationMode,
|
|
7122
7195
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7123
7196
|
};
|
|
7124
|
-
function
|
|
7197
|
+
function createListImportsTool(pkgseerService) {
|
|
7125
7198
|
return {
|
|
7126
|
-
name: "
|
|
7127
|
-
description: "
|
|
7128
|
-
schema:
|
|
7199
|
+
name: "list_imports",
|
|
7200
|
+
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.",
|
|
7201
|
+
schema: argsSchema7,
|
|
7129
7202
|
annotations: { readOnlyHint: true },
|
|
7130
7203
|
handler: async (args, _extra) => {
|
|
7131
|
-
return withErrorHandling("list
|
|
7132
|
-
const
|
|
7133
|
-
|
|
7134
|
-
|
|
7204
|
+
return withErrorHandling("list imports", async () => {
|
|
7205
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7206
|
+
if (isToolError(resolved))
|
|
7207
|
+
return resolved;
|
|
7208
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7209
|
+
const result = await pkgseerService.packageImports(tv.registry, tv.packageName, {
|
|
7210
|
+
filePath: args.file_path,
|
|
7211
|
+
resolvedOnly: args.resolved_only,
|
|
7135
7212
|
limit: args.limit,
|
|
7136
|
-
|
|
7213
|
+
version: tv.version,
|
|
7214
|
+
mode: toNavigationMode(args.mode),
|
|
7215
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7216
|
+
repoUrl: tv.repoUrl,
|
|
7217
|
+
gitRef: tv.gitRef
|
|
7137
7218
|
});
|
|
7138
7219
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7139
7220
|
if (graphqlError)
|
|
7140
7221
|
return graphqlError;
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7222
|
+
return textResult(JSON.stringify(result.data.packageImports, null, 2));
|
|
7223
|
+
});
|
|
7224
|
+
}
|
|
7225
|
+
};
|
|
7226
|
+
}
|
|
7227
|
+
// src/tools/list-package-docs.ts
|
|
7228
|
+
var argsSchema8 = {
|
|
7229
|
+
registry: schemas.registry,
|
|
7230
|
+
package_name: schemas.packageName.describe("Name of the package to list documentation for"),
|
|
7231
|
+
version: schemas.version
|
|
7232
|
+
};
|
|
7233
|
+
function createListPackageDocsTool(pkgseerService) {
|
|
7234
|
+
return {
|
|
7235
|
+
name: "list_package_docs",
|
|
7236
|
+
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.",
|
|
7237
|
+
schema: argsSchema8,
|
|
7238
|
+
annotations: { readOnlyHint: true },
|
|
7239
|
+
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
7240
|
+
return withErrorHandling("list package documentation", async () => {
|
|
7241
|
+
const result = await pkgseerService.listPackageDocs(toGraphQLRegistry(registry), package_name, version2);
|
|
7242
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7243
|
+
if (graphqlError)
|
|
7244
|
+
return graphqlError;
|
|
7245
|
+
if (!result.data?.listPackageDocs) {
|
|
7246
|
+
return notFoundError(package_name, registry);
|
|
7147
7247
|
}
|
|
7148
|
-
return textResult(JSON.stringify(data, null, 2));
|
|
7248
|
+
return textResult(JSON.stringify(result.data?.listPackageDocs, null, 2));
|
|
7149
7249
|
});
|
|
7150
7250
|
}
|
|
7151
7251
|
};
|
|
@@ -7153,22 +7253,20 @@ function createListRepoFilesTool(pkgseerService) {
|
|
|
7153
7253
|
// src/tools/list-symbols.ts
|
|
7154
7254
|
import { z as z10 } from "zod";
|
|
7155
7255
|
var argsSchema9 = {
|
|
7156
|
-
|
|
7157
|
-
package_name: schemas.packageName.describe("Name of the package to browse symbols for"),
|
|
7256
|
+
target: schemas.codeTarget,
|
|
7158
7257
|
scope: z10.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
|
|
7159
7258
|
file_path: z10.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
|
|
7160
7259
|
namespace: z10.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
|
|
7161
7260
|
public_only: z10.boolean().optional().describe("Only return public symbols"),
|
|
7162
7261
|
include_popularity: z10.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
|
|
7163
|
-
limit: z10.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
|
|
7164
|
-
version: schemas.version,
|
|
7262
|
+
limit: z10.coerce.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
|
|
7165
7263
|
mode: schemas.navigationMode,
|
|
7166
7264
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7167
7265
|
};
|
|
7168
7266
|
function createListSymbolsTool(pkgseerService) {
|
|
7169
7267
|
return {
|
|
7170
7268
|
name: "list_symbols",
|
|
7171
|
-
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.",
|
|
7269
|
+
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.",
|
|
7172
7270
|
schema: argsSchema9,
|
|
7173
7271
|
annotations: { readOnlyHint: true },
|
|
7174
7272
|
handler: async (args, _extra) => {
|
|
@@ -7185,23 +7283,26 @@ function createListSymbolsTool(pkgseerService) {
|
|
|
7185
7283
|
isError: true
|
|
7186
7284
|
};
|
|
7187
7285
|
}
|
|
7188
|
-
const
|
|
7286
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7287
|
+
if (isToolError(resolved))
|
|
7288
|
+
return resolved;
|
|
7289
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7290
|
+
const result = await pkgseerService.listSymbols(tv.registry, tv.packageName, scope, {
|
|
7189
7291
|
filePath: args.file_path,
|
|
7190
7292
|
namespace: args.namespace,
|
|
7191
7293
|
publicOnly: args.public_only,
|
|
7192
7294
|
includePopularity: args.include_popularity,
|
|
7193
7295
|
limit: args.limit,
|
|
7194
|
-
version:
|
|
7296
|
+
version: tv.version,
|
|
7195
7297
|
mode: toNavigationMode(args.mode),
|
|
7196
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7298
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7299
|
+
repoUrl: tv.repoUrl,
|
|
7300
|
+
gitRef: tv.gitRef
|
|
7197
7301
|
});
|
|
7198
7302
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7199
7303
|
if (graphqlError)
|
|
7200
7304
|
return graphqlError;
|
|
7201
|
-
|
|
7202
|
-
return notFoundError(args.package_name, args.registry);
|
|
7203
|
-
}
|
|
7204
|
-
return textResult(JSON.stringify(result.data?.listSymbols, null, 2));
|
|
7305
|
+
return textResult(JSON.stringify(result.data.listSymbols, null, 2));
|
|
7205
7306
|
});
|
|
7206
7307
|
}
|
|
7207
7308
|
};
|
|
@@ -7213,7 +7314,7 @@ var argsSchema10 = {
|
|
|
7213
7314
|
package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
|
|
7214
7315
|
version: schemas.version,
|
|
7215
7316
|
include_transitive: z11.boolean().optional().describe("Whether to include transitive dependency DAG"),
|
|
7216
|
-
max_depth: z11.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
|
|
7317
|
+
max_depth: z11.coerce.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
|
|
7217
7318
|
};
|
|
7218
7319
|
function decodeDag(rawDag) {
|
|
7219
7320
|
if (!rawDag || typeof rawDag !== "object")
|
|
@@ -7329,47 +7430,8 @@ function createPackageDependenciesTool(pkgseerService) {
|
|
|
7329
7430
|
}
|
|
7330
7431
|
};
|
|
7331
7432
|
}
|
|
7332
|
-
// src/tools/package-imports.ts
|
|
7333
|
-
import { z as z12 } from "zod";
|
|
7334
|
-
var argsSchema11 = {
|
|
7335
|
-
registry: schemas.registry,
|
|
7336
|
-
package_name: schemas.packageName.describe("Name of the package to get imports for"),
|
|
7337
|
-
file_path: z12.string().max(1000).optional().describe("Filter to a specific file path"),
|
|
7338
|
-
resolved_only: z12.boolean().optional().describe("Only return imports resolved to a known package"),
|
|
7339
|
-
limit: z12.number().int().min(1).max(500).optional().describe("Max imports to return"),
|
|
7340
|
-
version: schemas.version,
|
|
7341
|
-
mode: schemas.navigationMode,
|
|
7342
|
-
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7343
|
-
};
|
|
7344
|
-
function createPackageImportsTool(pkgseerService) {
|
|
7345
|
-
return {
|
|
7346
|
-
name: "package_imports",
|
|
7347
|
-
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.",
|
|
7348
|
-
schema: argsSchema11,
|
|
7349
|
-
annotations: { readOnlyHint: true },
|
|
7350
|
-
handler: async (args, _extra) => {
|
|
7351
|
-
return withErrorHandling("fetch package imports", async () => {
|
|
7352
|
-
const result = await pkgseerService.packageImports(toGraphQLRegistry(args.registry), args.package_name, {
|
|
7353
|
-
filePath: args.file_path,
|
|
7354
|
-
resolvedOnly: args.resolved_only,
|
|
7355
|
-
limit: args.limit,
|
|
7356
|
-
version: args.version,
|
|
7357
|
-
mode: toNavigationMode(args.mode),
|
|
7358
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7359
|
-
});
|
|
7360
|
-
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7361
|
-
if (graphqlError)
|
|
7362
|
-
return graphqlError;
|
|
7363
|
-
if (!result.data?.packageImports) {
|
|
7364
|
-
return notFoundError(args.package_name, args.registry);
|
|
7365
|
-
}
|
|
7366
|
-
return textResult(JSON.stringify(result.data?.packageImports, null, 2));
|
|
7367
|
-
});
|
|
7368
|
-
}
|
|
7369
|
-
};
|
|
7370
|
-
}
|
|
7371
7433
|
// src/tools/package-quality.ts
|
|
7372
|
-
var
|
|
7434
|
+
var argsSchema11 = {
|
|
7373
7435
|
registry: schemas.registry,
|
|
7374
7436
|
package_name: schemas.packageName.describe("Name of the package to analyze"),
|
|
7375
7437
|
version: schemas.version
|
|
@@ -7377,8 +7439,8 @@ var argsSchema12 = {
|
|
|
7377
7439
|
function createPackageQualityTool(pkgseerService) {
|
|
7378
7440
|
return {
|
|
7379
7441
|
name: "package_quality",
|
|
7380
|
-
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.",
|
|
7381
|
-
schema:
|
|
7442
|
+
description: "Evaluate package maintenance health and code quality (available immediately — no indexing required). " + "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.",
|
|
7443
|
+
schema: argsSchema11,
|
|
7382
7444
|
annotations: { readOnlyHint: true },
|
|
7383
7445
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
7384
7446
|
return withErrorHandling("fetch package quality", async () => {
|
|
@@ -7395,15 +7457,15 @@ function createPackageQualityTool(pkgseerService) {
|
|
|
7395
7457
|
};
|
|
7396
7458
|
}
|
|
7397
7459
|
// src/tools/package-summary.ts
|
|
7398
|
-
var
|
|
7460
|
+
var argsSchema12 = {
|
|
7399
7461
|
registry: schemas.registry,
|
|
7400
7462
|
package_name: schemas.packageName.describe("Name of the package to retrieve summary for")
|
|
7401
7463
|
};
|
|
7402
7464
|
function createPackageSummaryTool(pkgseerService) {
|
|
7403
7465
|
return {
|
|
7404
7466
|
name: "package_summary",
|
|
7405
|
-
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).",
|
|
7406
|
-
schema:
|
|
7467
|
+
description: "Get a comprehensive overview of a package (available immediately — no indexing required). " + "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). " + "Use package.repositoryUrl + package.latestVersion as git_ref with fetch_code_context to read source files.",
|
|
7468
|
+
schema: argsSchema12,
|
|
7407
7469
|
annotations: { readOnlyHint: true },
|
|
7408
7470
|
handler: async ({ registry, package_name }, _extra) => {
|
|
7409
7471
|
return withErrorHandling("fetch package summary", async () => {
|
|
@@ -7420,7 +7482,7 @@ function createPackageSummaryTool(pkgseerService) {
|
|
|
7420
7482
|
};
|
|
7421
7483
|
}
|
|
7422
7484
|
// src/tools/package-vulnerabilities.ts
|
|
7423
|
-
var
|
|
7485
|
+
var argsSchema13 = {
|
|
7424
7486
|
registry: schemas.registry,
|
|
7425
7487
|
package_name: schemas.packageName.describe("Name of the package to inspect for vulnerabilities"),
|
|
7426
7488
|
version: schemas.version
|
|
@@ -7428,8 +7490,8 @@ var argsSchema14 = {
|
|
|
7428
7490
|
function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
7429
7491
|
return {
|
|
7430
7492
|
name: "package_vulnerabilities",
|
|
7431
|
-
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.",
|
|
7432
|
-
schema:
|
|
7493
|
+
description: "Check security vulnerabilities for a package (available immediately — no indexing required). " + "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.",
|
|
7494
|
+
schema: argsSchema13,
|
|
7433
7495
|
annotations: { readOnlyHint: true },
|
|
7434
7496
|
handler: async ({ registry, package_name, version: version2 }, _extra) => {
|
|
7435
7497
|
return withErrorHandling("fetch package vulnerabilities", async () => {
|
|
@@ -7445,6 +7507,48 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
|
|
|
7445
7507
|
}
|
|
7446
7508
|
};
|
|
7447
7509
|
}
|
|
7510
|
+
// src/tools/read-file.ts
|
|
7511
|
+
import { z as z12 } from "zod";
|
|
7512
|
+
var argsSchema14 = {
|
|
7513
|
+
target: schemas.codeTarget,
|
|
7514
|
+
file_path: z12.string({
|
|
7515
|
+
error: "file_path is required. Get file paths from find_symbol (returns file locations) " + "or list_files (browse file structure)."
|
|
7516
|
+
}).min(1).describe("Path to file in repository. Example: src/router/index.js"),
|
|
7517
|
+
start_line: z12.coerce.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
|
|
7518
|
+
end_line: z12.coerce.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file."),
|
|
7519
|
+
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7520
|
+
};
|
|
7521
|
+
function createReadFileTool(pkgseerService) {
|
|
7522
|
+
return {
|
|
7523
|
+
name: "read_file",
|
|
7524
|
+
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.",
|
|
7525
|
+
schema: argsSchema14,
|
|
7526
|
+
annotations: { readOnlyHint: true },
|
|
7527
|
+
handler: async (args, _extra) => {
|
|
7528
|
+
return withErrorHandling("read file", async () => {
|
|
7529
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7530
|
+
if (isToolError(resolved))
|
|
7531
|
+
return resolved;
|
|
7532
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7533
|
+
const result = await pkgseerService.fetchCodeContext(tv.repoUrl, tv.gitRef, args.file_path, {
|
|
7534
|
+
startLine: args.start_line,
|
|
7535
|
+
endLine: args.end_line,
|
|
7536
|
+
registry: tv.registry,
|
|
7537
|
+
packageName: tv.packageName,
|
|
7538
|
+
version: tv.version,
|
|
7539
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7540
|
+
});
|
|
7541
|
+
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7542
|
+
if (graphqlError)
|
|
7543
|
+
return graphqlError;
|
|
7544
|
+
if (!result.data?.fetchCodeContext) {
|
|
7545
|
+
return errorResult(`File not found: ${args.file_path}. ` + "Check that the file path and target are correct. " + "Use list_files to discover available files.");
|
|
7546
|
+
}
|
|
7547
|
+
return textResult(JSON.stringify(result.data.fetchCodeContext, null, 2));
|
|
7548
|
+
});
|
|
7549
|
+
}
|
|
7550
|
+
};
|
|
7551
|
+
}
|
|
7448
7552
|
// src/tools/search.ts
|
|
7449
7553
|
import { z as z13 } from "zod";
|
|
7450
7554
|
var packageInputSchema2 = z13.object({
|
|
@@ -7452,13 +7556,16 @@ var packageInputSchema2 = z13.object({
|
|
|
7452
7556
|
name: z13.string().min(1).describe("Package name"),
|
|
7453
7557
|
version: z13.string().optional().describe("Specific version (defaults to latest)")
|
|
7454
7558
|
});
|
|
7455
|
-
var DEFAULT_AGENT_WAIT_TIMEOUT_MS = 1e4;
|
|
7456
7559
|
var argsSchema15 = {
|
|
7457
|
-
packages: z13.array(packageInputSchema2
|
|
7458
|
-
|
|
7560
|
+
packages: z13.array(packageInputSchema2, {
|
|
7561
|
+
error: 'packages is required. Provide 1-20 packages as [{registry: "npm", name: "express"}]. ' + "Use package_summary to verify a package exists. " + "For project-wide doc search without specifying packages, use search_project_docs instead."
|
|
7562
|
+
}).min(1).max(20).describe('Packages to search (1-20). Format: [{"registry":"npm","name":"express"}]'),
|
|
7563
|
+
query: z13.string({
|
|
7564
|
+
error: "query is required. Provide search terms as natural language or keywords, " + "e.g., 'error handling middleware'."
|
|
7565
|
+
}).min(1).describe("Search query - natural language or keywords"),
|
|
7459
7566
|
mode: z13.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
|
|
7460
|
-
limit: z13.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
|
|
7461
|
-
waitTimeoutMs: z13.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
|
|
7567
|
+
limit: z13.coerce.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
|
|
7568
|
+
waitTimeoutMs: z13.coerce.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
|
|
7462
7569
|
};
|
|
7463
7570
|
function toSearchMode2(mode) {
|
|
7464
7571
|
if (!mode)
|
|
@@ -7496,7 +7603,7 @@ Results may be incomplete. Retry later for more complete results.`;
|
|
|
7496
7603
|
function createSearchTool(pkgseerService) {
|
|
7497
7604
|
return {
|
|
7498
7605
|
name: "search",
|
|
7499
|
-
description: "Search code and documentation across packages. Returns
|
|
7606
|
+
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 packages. 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 packages need indexing, waits up to waitTimeoutMs (default 10s) or returns searchRef — use search_status to poll.",
|
|
7500
7607
|
schema: argsSchema15,
|
|
7501
7608
|
annotations: { readOnlyHint: true },
|
|
7502
7609
|
handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
|
|
@@ -7513,7 +7620,7 @@ function createSearchTool(pkgseerService) {
|
|
|
7513
7620
|
const result = await pkgseerService.combinedSearch(graphqlPackages, normalizedQuery, {
|
|
7514
7621
|
mode: toSearchMode2(mode),
|
|
7515
7622
|
limit,
|
|
7516
|
-
waitTimeoutMs: waitTimeoutMs ??
|
|
7623
|
+
waitTimeoutMs: waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7517
7624
|
});
|
|
7518
7625
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7519
7626
|
if (graphqlError)
|
|
@@ -7557,7 +7664,7 @@ var argsSchema16 = {
|
|
|
7557
7664
|
terms: z14.array(z14.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
|
|
7558
7665
|
match_mode: z14.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
|
|
7559
7666
|
include_snippets: z14.boolean().optional().describe("Include content excerpts around matches"),
|
|
7560
|
-
limit: z14.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
|
|
7667
|
+
limit: z14.coerce.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
|
|
7561
7668
|
};
|
|
7562
7669
|
function createSearchProjectDocsTool(deps) {
|
|
7563
7670
|
const { pkgseerService, configService, defaultProjectDir } = deps;
|
|
@@ -7582,7 +7689,9 @@ function createSearchProjectDocsTool(deps) {
|
|
|
7582
7689
|
return errorResult(`No project specified and no pkgseer.yml found. To fix:
|
|
7583
7690
|
` + ` 1. Pass project_directory: '/path/to/project' (folder containing pkgseer.yml)
|
|
7584
7691
|
` + ` 2. Pass project: 'project-name' directly if you know the project name
|
|
7585
|
-
` +
|
|
7692
|
+
` + ` 3. Run 'pkgseer project init' to create pkgseer.yml in your project
|
|
7693
|
+
|
|
7694
|
+
` + "Or use search(mode='docs', packages=[{registry: 'npm', name: '...'}]) to search " + "specific packages without a project.");
|
|
7586
7695
|
}
|
|
7587
7696
|
const normalizedTerms = terms?.map((term) => term.trim()).filter((term) => term.length > 0) ?? [];
|
|
7588
7697
|
if (normalizedTerms.length === 0) {
|
|
@@ -7663,8 +7772,7 @@ function createSearchStatusTool(pkgseerService) {
|
|
|
7663
7772
|
// src/tools/search-symbols.ts
|
|
7664
7773
|
import { z as z16 } from "zod";
|
|
7665
7774
|
var argsSchema18 = {
|
|
7666
|
-
|
|
7667
|
-
package_name: schemas.packageName.describe("Name of the package to search within"),
|
|
7775
|
+
target: schemas.codeTarget,
|
|
7668
7776
|
query: z16.string().max(500).optional().describe("Search query for full-text code search (max 500 chars). Required if keywords not provided."),
|
|
7669
7777
|
keywords: z16.array(z16.string()).max(20).optional().describe("Search keywords (max 20). Combined using match_mode. Alternative to query."),
|
|
7670
7778
|
match_mode: z16.enum(["or", "and"]).optional().describe("How to combine keywords: or (any match) or and (all must match)"),
|
|
@@ -7678,37 +7786,39 @@ var argsSchema18 = {
|
|
|
7678
7786
|
"doc_section"
|
|
7679
7787
|
]).optional().describe("Filter results by code chunk type"),
|
|
7680
7788
|
file_path: z16.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
|
|
7681
|
-
|
|
7682
|
-
limit: z16.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
|
|
7789
|
+
limit: z16.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
|
|
7683
7790
|
mode: schemas.navigationMode,
|
|
7684
7791
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7685
7792
|
};
|
|
7686
7793
|
function createSearchSymbolsTool(pkgseerService) {
|
|
7687
7794
|
return {
|
|
7688
7795
|
name: "search_symbols",
|
|
7689
|
-
description: "Search a dependency's source code by text — " + "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
|
|
7796
|
+
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.",
|
|
7690
7797
|
schema: argsSchema18,
|
|
7691
7798
|
annotations: { readOnlyHint: true },
|
|
7692
7799
|
handler: async (args, _extra) => {
|
|
7693
7800
|
return withErrorHandling("search symbols", async () => {
|
|
7694
|
-
const
|
|
7801
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7802
|
+
if (isToolError(resolved))
|
|
7803
|
+
return resolved;
|
|
7804
|
+
const tv = buildCodeTargetVars(resolved);
|
|
7805
|
+
const result = await pkgseerService.searchSymbols(tv.registry, tv.packageName, {
|
|
7695
7806
|
query: args.query,
|
|
7696
7807
|
keywords: args.keywords,
|
|
7697
7808
|
matchMode: toMatchMode(args.match_mode),
|
|
7698
7809
|
kind: toSymbolKind(args.kind),
|
|
7699
7810
|
filePath: args.file_path,
|
|
7700
|
-
version:
|
|
7811
|
+
version: tv.version,
|
|
7701
7812
|
limit: args.limit,
|
|
7702
7813
|
mode: toNavigationMode(args.mode),
|
|
7703
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7814
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
7815
|
+
repoUrl: tv.repoUrl,
|
|
7816
|
+
gitRef: tv.gitRef
|
|
7704
7817
|
});
|
|
7705
7818
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7706
7819
|
if (graphqlError)
|
|
7707
7820
|
return graphqlError;
|
|
7708
|
-
|
|
7709
|
-
return notFoundError(args.package_name, args.registry);
|
|
7710
|
-
}
|
|
7711
|
-
const data = result.data?.searchSymbols;
|
|
7821
|
+
const data = result.data.searchSymbols;
|
|
7712
7822
|
const extra = {};
|
|
7713
7823
|
if (data.results.length === 0 && data.diagnostics?.hint) {
|
|
7714
7824
|
extra._hint = data.diagnostics.hint;
|
|
@@ -7727,10 +7837,10 @@ function createSearchSymbolsTool(pkgseerService) {
|
|
|
7727
7837
|
// src/tools/symbol-callees.ts
|
|
7728
7838
|
import { z as z17 } from "zod";
|
|
7729
7839
|
var argsSchema19 = {
|
|
7730
|
-
symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide
|
|
7731
|
-
max_depth: z17.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
|
|
7732
|
-
limit: z17.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
|
|
7733
|
-
include_external: z17.boolean().optional().describe("Include calls to symbols in other packages"),
|
|
7840
|
+
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."),
|
|
7841
|
+
max_depth: z17.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
|
|
7842
|
+
limit: z17.coerce.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
|
|
7843
|
+
include_external: z17.boolean().optional().describe("Include calls to symbols in other indexed packages. " + "Default (false) shows only calls within the same package."),
|
|
7734
7844
|
include_builtins: z17.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
|
|
7735
7845
|
mode: schemas.navigationMode,
|
|
7736
7846
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
@@ -7738,14 +7848,14 @@ var argsSchema19 = {
|
|
|
7738
7848
|
function createSymbolCalleesTool(pkgseerService) {
|
|
7739
7849
|
return {
|
|
7740
7850
|
name: "symbol_callees",
|
|
7741
|
-
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.",
|
|
7851
|
+
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.",
|
|
7742
7852
|
schema: argsSchema19,
|
|
7743
7853
|
annotations: { readOnlyHint: true },
|
|
7744
7854
|
handler: async (args, _extra) => {
|
|
7745
7855
|
return withErrorHandling("find symbol callees", async () => {
|
|
7746
7856
|
const symbolInput = toSymbolReferenceInput(args.symbol);
|
|
7747
|
-
if (!symbolInput.symbolRef && (
|
|
7748
|
-
return errorResult("Provide
|
|
7857
|
+
if (!symbolInput.symbolRef && !(symbolInput.symbolName && symbolInput.registry && symbolInput.packageName) && !(symbolInput.symbolName && symbolInput.repoUrl && symbolInput.gitRef)) {
|
|
7858
|
+
return errorResult("Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
7749
7859
|
}
|
|
7750
7860
|
const result = await pkgseerService.symbolDependencies(symbolInput, {
|
|
7751
7861
|
maxDepth: args.max_depth,
|
|
@@ -7753,15 +7863,12 @@ function createSymbolCalleesTool(pkgseerService) {
|
|
|
7753
7863
|
includeExternal: args.include_external,
|
|
7754
7864
|
includeBuiltins: args.include_builtins,
|
|
7755
7865
|
mode: toNavigationMode(args.mode),
|
|
7756
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7866
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7757
7867
|
});
|
|
7758
7868
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7759
7869
|
if (graphqlError)
|
|
7760
7870
|
return graphqlError;
|
|
7761
|
-
|
|
7762
|
-
return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
|
|
7763
|
-
}
|
|
7764
|
-
return textResult(JSON.stringify(result.data?.symbolDependencies, null, 2));
|
|
7871
|
+
return textResult(JSON.stringify(result.data.symbolDependencies, null, 2));
|
|
7765
7872
|
});
|
|
7766
7873
|
}
|
|
7767
7874
|
};
|
|
@@ -7769,39 +7876,36 @@ function createSymbolCalleesTool(pkgseerService) {
|
|
|
7769
7876
|
// src/tools/symbol-callers.ts
|
|
7770
7877
|
import { z as z18 } from "zod";
|
|
7771
7878
|
var argsSchema20 = {
|
|
7772
|
-
symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide
|
|
7773
|
-
same_package_only: z18.boolean().optional().describe("Only return callers from the same package"),
|
|
7774
|
-
max_depth: z18.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
|
|
7775
|
-
limit: z18.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
|
|
7879
|
+
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."),
|
|
7880
|
+
same_package_only: z18.boolean().optional().describe("Only return callers from the same package. " + "Default (false) includes callers from other indexed packages."),
|
|
7881
|
+
max_depth: z18.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
|
|
7882
|
+
limit: z18.coerce.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
|
|
7776
7883
|
mode: schemas.navigationMode,
|
|
7777
7884
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7778
7885
|
};
|
|
7779
7886
|
function createSymbolCallersTool(pkgseerService) {
|
|
7780
7887
|
return {
|
|
7781
7888
|
name: "symbol_callers",
|
|
7782
|
-
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.",
|
|
7889
|
+
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.",
|
|
7783
7890
|
schema: argsSchema20,
|
|
7784
7891
|
annotations: { readOnlyHint: true },
|
|
7785
7892
|
handler: async (args, _extra) => {
|
|
7786
7893
|
return withErrorHandling("find symbol callers", async () => {
|
|
7787
7894
|
const symbolInput = toSymbolReferenceInput(args.symbol);
|
|
7788
|
-
if (!symbolInput.symbolRef && (
|
|
7789
|
-
return errorResult("Provide
|
|
7895
|
+
if (!symbolInput.symbolRef && !(symbolInput.symbolName && symbolInput.registry && symbolInput.packageName) && !(symbolInput.symbolName && symbolInput.repoUrl && symbolInput.gitRef)) {
|
|
7896
|
+
return errorResult("Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
|
|
7790
7897
|
}
|
|
7791
7898
|
const result = await pkgseerService.symbolDependents(symbolInput, {
|
|
7792
7899
|
samePackageOnly: args.same_package_only,
|
|
7793
7900
|
maxDepth: args.max_depth,
|
|
7794
7901
|
maxResults: args.limit,
|
|
7795
7902
|
mode: toNavigationMode(args.mode),
|
|
7796
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
7903
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
|
|
7797
7904
|
});
|
|
7798
7905
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7799
7906
|
if (graphqlError)
|
|
7800
7907
|
return graphqlError;
|
|
7801
|
-
|
|
7802
|
-
return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
|
|
7803
|
-
}
|
|
7804
|
-
return textResult(JSON.stringify(result.data?.symbolDependents, null, 2));
|
|
7908
|
+
return textResult(JSON.stringify(result.data.symbolDependents, null, 2));
|
|
7805
7909
|
});
|
|
7806
7910
|
}
|
|
7807
7911
|
};
|
|
@@ -7825,7 +7929,7 @@ var argsSchema21 = {
|
|
|
7825
7929
|
function createTriggerIndexingTool(pkgseerService) {
|
|
7826
7930
|
return {
|
|
7827
7931
|
name: "trigger_indexing",
|
|
7828
|
-
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.",
|
|
7932
|
+
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.",
|
|
7829
7933
|
schema: argsSchema21,
|
|
7830
7934
|
annotations: { readOnlyHint: false, idempotentHint: true },
|
|
7831
7935
|
handler: async (args, _extra) => {
|
|
@@ -7866,8 +7970,7 @@ function createTriggerIndexingTool(pkgseerService) {
|
|
|
7866
7970
|
// src/tools/version-diff.ts
|
|
7867
7971
|
import { z as z20 } from "zod";
|
|
7868
7972
|
var argsSchema22 = {
|
|
7869
|
-
|
|
7870
|
-
package_name: schemas.packageName.describe("Name of the package to compare versions for"),
|
|
7973
|
+
target: schemas.codeTarget,
|
|
7871
7974
|
from_version: z20.string().max(100).describe("Source version (git ref, e.g., 'v4.18.2')"),
|
|
7872
7975
|
to_version: z20.string().max(100).describe("Target version (git ref, e.g., 'v5.0.0')"),
|
|
7873
7976
|
include_private: z20.boolean().optional().describe("Include private/non-exported symbols in the diff"),
|
|
@@ -7880,30 +7983,33 @@ var argsSchema22 = {
|
|
|
7880
7983
|
"type",
|
|
7881
7984
|
"doc_section"
|
|
7882
7985
|
]).optional().describe("Filter by symbol kind"),
|
|
7883
|
-
limit: z20.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
|
|
7986
|
+
limit: z20.coerce.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
|
|
7884
7987
|
wait_timeout_ms: schemas.waitTimeoutMs
|
|
7885
7988
|
};
|
|
7886
7989
|
function createVersionDiffTool(pkgseerService) {
|
|
7887
7990
|
return {
|
|
7888
7991
|
name: "version_diff",
|
|
7889
|
-
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.",
|
|
7992
|
+
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.",
|
|
7890
7993
|
schema: argsSchema22,
|
|
7891
7994
|
annotations: { readOnlyHint: true },
|
|
7892
7995
|
handler: async (args, _extra) => {
|
|
7893
7996
|
return withErrorHandling("version diff", async () => {
|
|
7894
|
-
const
|
|
7997
|
+
const resolved = resolveCodeTarget(args.target);
|
|
7998
|
+
if (isToolError(resolved))
|
|
7999
|
+
return resolved;
|
|
8000
|
+
const tv = buildCodeTargetVars(resolved);
|
|
8001
|
+
const result = await pkgseerService.versionDiff(tv.registry, tv.packageName, args.from_version, args.to_version, {
|
|
7895
8002
|
includePrivate: args.include_private,
|
|
7896
8003
|
kind: toSymbolKind(args.kind),
|
|
7897
8004
|
limit: args.limit,
|
|
7898
|
-
waitTimeoutMs: args.wait_timeout_ms
|
|
8005
|
+
waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
|
|
8006
|
+
repoUrl: tv.repoUrl,
|
|
8007
|
+
gitRef: tv.gitRef
|
|
7899
8008
|
});
|
|
7900
8009
|
const graphqlError = handleGraphQLErrors(result.errors);
|
|
7901
8010
|
if (graphqlError)
|
|
7902
8011
|
return graphqlError;
|
|
7903
|
-
|
|
7904
|
-
return notFoundError(args.package_name, args.registry);
|
|
7905
|
-
}
|
|
7906
|
-
return textResult(JSON.stringify(result.data?.versionDiff, null, 2));
|
|
8012
|
+
return textResult(JSON.stringify(result.data.versionDiff, null, 2));
|
|
7907
8013
|
});
|
|
7908
8014
|
}
|
|
7909
8015
|
};
|
|
@@ -7919,18 +8025,54 @@ Use PkgSeer when:
|
|
|
7919
8025
|
- You need to understand what changed between package versions
|
|
7920
8026
|
|
|
7921
8027
|
Instead of guessing library behavior from training data, use find_symbol(include_code=true) to read actual source.
|
|
7922
|
-
Instead of cloning repos to search code, use search_symbols or
|
|
8028
|
+
Instead of cloning repos to search code, use search_symbols or grep_file.
|
|
7923
8029
|
Instead of manually tracing call chains on GitHub, use symbol_callers and symbol_callees.
|
|
7924
8030
|
|
|
7925
|
-
|
|
7926
|
-
-
|
|
7927
|
-
|
|
7928
|
-
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
-
|
|
8031
|
+
Dual addressing — code tools accept a target object with two modes:
|
|
8032
|
+
- Package scope: target: { registry: "npm", package_name: "express" } (optional version)
|
|
8033
|
+
In monorepos, results are scoped to the package's subdirectory.
|
|
8034
|
+
- Repo scope: target: { repo_url: "https://github.com/expressjs/express", git_ref: "v4.18.2" }
|
|
8035
|
+
Operates on the full repository, not filtered to a package subdirectory.
|
|
8036
|
+
|
|
8037
|
+
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.
|
|
8038
|
+
|
|
8039
|
+
Data availability — tools are grouped by what backend data they need:
|
|
8040
|
+
|
|
8041
|
+
1. Registry metadata (available immediately, no indexing):
|
|
8042
|
+
package_summary, package_quality, package_vulnerabilities, package_dependencies, compare_packages
|
|
8043
|
+
Start here when researching a package — these always work instantly.
|
|
8044
|
+
|
|
8045
|
+
2. Documentation (requires doc site crawling):
|
|
8046
|
+
list_package_docs, fetch_package_doc, search(mode='docs'), search_project_docs
|
|
8047
|
+
If results are empty, docs may not be crawled yet — use trigger_indexing first, then retry.
|
|
8048
|
+
|
|
8049
|
+
3. Code navigation (requires code repo indexing, dual addressing via target):
|
|
8050
|
+
find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path,
|
|
8051
|
+
list_imports, version_diff, list_files, grep_file, read_file, search(mode='code')
|
|
8052
|
+
These wait up to wait_timeout_ms (default 10s) for indexing. If indexing takes longer, you'll get a "being indexed" response — retry the same call. Most packages index within 10-30 seconds.
|
|
8053
|
+
|
|
8054
|
+
Symbol reference tools (symbol_callers, symbol_callees, call_path) accept a symbol object with either:
|
|
8055
|
+
- symbol_ref from a previous find_symbol/search_symbols result (preferred, fastest)
|
|
8056
|
+
- Package lookup: registry + package_name + symbol_name
|
|
8057
|
+
- Repo lookup: repo_url + git_ref + symbol_name
|
|
8058
|
+
symbol_callers/symbol_callees can show cross-package results from other indexed packages.
|
|
8059
|
+
|
|
8060
|
+
Choosing a code search tool:
|
|
8061
|
+
- search_symbols: single package, symbol-level → results feed symbol_callers/callees/call_path
|
|
8062
|
+
- search(mode='code'): multi-package, full-text → code chunks with snippets
|
|
8063
|
+
- grep_file: single file, pattern match → when you know the file path
|
|
8064
|
+
|
|
8065
|
+
Utility: trigger_indexing (pre-warm indexes), search_status (poll async search).
|
|
8066
|
+
|
|
8067
|
+
Quick start: find_symbol(target={registry:"npm", package_name:"<pkg>"}, name="<function>", include_code=true) often answers the question in one call.
|
|
7932
8068
|
|
|
7933
|
-
|
|
8069
|
+
Common workflows (pass symbolRef between tools for chaining):
|
|
8070
|
+
- Read source: find_symbol(target={registry, package_name}, name=<fn>, include_code=true)
|
|
8071
|
+
- Trace calls: find_symbol → symbol_callees(symbol={symbol_ref: <symbolRef>})
|
|
8072
|
+
- Find callers: find_symbol → symbol_callers(symbol={symbol_ref: <symbolRef>})
|
|
8073
|
+
- Read file: read_file(target={registry, package_name}, file_path=<path>) or read_file(target={repo_url, git_ref}, file_path=<path>)
|
|
8074
|
+
- Search code: search_symbols (single pkg, feeds callers/callees) or search(mode='code', packages=[...]) (multi-pkg)
|
|
8075
|
+
- Browse docs: list_package_docs → fetch_package_doc(page_id)`;
|
|
7934
8076
|
var TOOL_FACTORIES = {
|
|
7935
8077
|
package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
|
|
7936
8078
|
package_vulnerabilities: ({ pkgseerService }) => createPackageVulnerabilitiesTool(pkgseerService),
|
|
@@ -7941,7 +8083,7 @@ var TOOL_FACTORIES = {
|
|
|
7941
8083
|
fetch_package_doc: ({ pkgseerService }) => createFetchPackageDocTool(pkgseerService),
|
|
7942
8084
|
search: ({ pkgseerService }) => createSearchTool(pkgseerService),
|
|
7943
8085
|
search_status: ({ pkgseerService }) => createSearchStatusTool(pkgseerService),
|
|
7944
|
-
|
|
8086
|
+
read_file: ({ pkgseerService }) => createReadFileTool(pkgseerService),
|
|
7945
8087
|
search_project_docs: ({ pkgseerService, configService, defaultProjectDir }) => createSearchProjectDocsTool({
|
|
7946
8088
|
pkgseerService,
|
|
7947
8089
|
configService,
|
|
@@ -7952,11 +8094,11 @@ var TOOL_FACTORIES = {
|
|
|
7952
8094
|
list_symbols: ({ pkgseerService }) => createListSymbolsTool(pkgseerService),
|
|
7953
8095
|
symbol_callers: ({ pkgseerService }) => createSymbolCallersTool(pkgseerService),
|
|
7954
8096
|
symbol_callees: ({ pkgseerService }) => createSymbolCalleesTool(pkgseerService),
|
|
7955
|
-
|
|
8097
|
+
list_imports: ({ pkgseerService }) => createListImportsTool(pkgseerService),
|
|
7956
8098
|
call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
|
|
7957
8099
|
trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService),
|
|
7958
|
-
|
|
7959
|
-
|
|
8100
|
+
list_files: ({ pkgseerService }) => createListFilesTool(pkgseerService),
|
|
8101
|
+
grep_file: ({ pkgseerService }) => createGrepFileTool(pkgseerService),
|
|
7960
8102
|
version_diff: ({ pkgseerService }) => createVersionDiffTool(pkgseerService)
|
|
7961
8103
|
};
|
|
7962
8104
|
var PUBLIC_READ_TOOLS = [
|
|
@@ -7969,24 +8111,24 @@ var PUBLIC_READ_TOOLS = [
|
|
|
7969
8111
|
"fetch_package_doc",
|
|
7970
8112
|
"search",
|
|
7971
8113
|
"search_status",
|
|
7972
|
-
"
|
|
8114
|
+
"read_file",
|
|
7973
8115
|
"find_symbol",
|
|
7974
8116
|
"search_symbols",
|
|
7975
8117
|
"list_symbols",
|
|
7976
8118
|
"symbol_callers",
|
|
7977
8119
|
"symbol_callees",
|
|
7978
|
-
"
|
|
8120
|
+
"list_imports",
|
|
7979
8121
|
"call_path",
|
|
7980
8122
|
"trigger_indexing",
|
|
7981
|
-
"
|
|
7982
|
-
"
|
|
8123
|
+
"list_files",
|
|
8124
|
+
"grep_file",
|
|
7983
8125
|
"version_diff"
|
|
7984
8126
|
];
|
|
7985
8127
|
var PROJECT_READ_TOOLS = ["search_project_docs"];
|
|
7986
8128
|
var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
|
|
7987
8129
|
function createMcpServer(deps) {
|
|
7988
8130
|
const { pkgseerService, configService, config, fileSystemService } = deps;
|
|
7989
|
-
const server = new McpServer({ name: "pkgseer", version: "0.
|
|
8131
|
+
const server = new McpServer({ name: "pkgseer", version: "0.5.0" }, { instructions: PKGSEER_INSTRUCTIONS });
|
|
7990
8132
|
const defaultProjectDir = fileSystemService.getCwd();
|
|
7991
8133
|
const enabledToolNames = config.enabled_tools ?? ALL_TOOLS;
|
|
7992
8134
|
const toolsToRegister = enabledToolNames.filter((name) => ALL_TOOLS.includes(name));
|
|
@@ -8052,13 +8194,13 @@ function registerMcpCommand(program) {
|
|
|
8052
8194
|
When run interactively (TTY), shows setup instructions.
|
|
8053
8195
|
When run via stdio (non-TTY), starts the MCP server.
|
|
8054
8196
|
|
|
8055
|
-
Available tools (
|
|
8197
|
+
Available tools (22):
|
|
8056
8198
|
Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
|
|
8057
|
-
Browse files:
|
|
8199
|
+
Browse files: list_files, grep_file, read_file
|
|
8058
8200
|
Search: search, search_project_docs
|
|
8059
8201
|
Docs: list_package_docs, fetch_package_doc
|
|
8060
8202
|
Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
|
|
8061
|
-
Utility: trigger_indexing, search_status,
|
|
8203
|
+
Utility: trigger_indexing, search_status, list_imports`).action(async () => {
|
|
8062
8204
|
const deps = await createContainer();
|
|
8063
8205
|
if (process.stdout.isTTY && process.stdin.isTTY) {
|
|
8064
8206
|
showMcpSetupInstructions(deps);
|