@pkgseer/cli 0.4.9 → 0.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  version
4
- } from "./shared/chunk-bahf01jh.js";
4
+ } from "./shared/chunk-r3pnzy5b.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -1023,7 +1023,6 @@ var VersionDiffDocument = gql`
1023
1023
  removed
1024
1024
  moved
1025
1025
  modified
1026
- unchanged
1027
1026
  breaking
1028
1027
  behaviorChange
1029
1028
  }
@@ -1644,6 +1643,8 @@ var TOOL_NAMES = [
1644
1643
  "search_status",
1645
1644
  "fetch_code_context",
1646
1645
  "search_project_docs",
1646
+ "list_package_files",
1647
+ "grep_package_file",
1647
1648
  "find_symbol",
1648
1649
  "search_symbols",
1649
1650
  "list_symbols",
@@ -1652,8 +1653,6 @@ var TOOL_NAMES = [
1652
1653
  "package_imports",
1653
1654
  "call_path",
1654
1655
  "trigger_indexing",
1655
- "list_repo_files",
1656
- "grep_repo_file",
1657
1656
  "version_diff"
1658
1657
  ];
1659
1658
  var ToolNameSchema = z.enum(TOOL_NAMES);
@@ -2750,8 +2749,8 @@ function outputError(message, json) {
2750
2749
  }
2751
2750
  var CLI_HINTS = {
2752
2751
  being_indexed: " Hint: package is being indexed. Try again with a longer --wait value (e.g., --wait 30000).",
2753
- timeout: " Hint: lower the limit or narrow the scope, then retry.",
2754
- not_found: " Hint: verify the name/registry and that the resource exists.",
2752
+ timeout: " Hint: this may be transient — retry the same command. If the issue persists, try simplifying the query.",
2753
+ not_found: " Hint: verify the package name and registry are correct.",
2755
2754
  auth: " Hint: check login or token validity (pkgseer auth-status).",
2756
2755
  rate_limit: " Hint: wait and retry, or reduce request frequency.",
2757
2756
  unknown: ""
@@ -3008,14 +3007,10 @@ async function codeCalleesAction(symbolArg, options, deps) {
3008
3007
  waitTimeoutMs: parseWaitTimeout(options.wait)
3009
3008
  });
3010
3009
  handleErrors(result.errors, options.json ?? false);
3011
- if (!result.data?.symbolDependencies) {
3012
- outputError("Symbol not found. Verify the symbol reference or use --ref.", options.json ?? false);
3013
- return;
3014
- }
3015
3010
  if (options.json) {
3016
- output(result.data?.symbolDependencies, true);
3011
+ output(result.data.symbolDependencies, true);
3017
3012
  } else {
3018
- console.log(formatCalleesResult(result.data?.symbolDependencies));
3013
+ console.log(formatCalleesResult(result.data.symbolDependencies));
3019
3014
  }
3020
3015
  }
3021
3016
  var CALLEES_DESCRIPTION = `Find what a symbol calls.
@@ -3059,14 +3054,10 @@ async function codeCallersAction(symbolArg, options, deps) {
3059
3054
  waitTimeoutMs: parseWaitTimeout(options.wait)
3060
3055
  });
3061
3056
  handleErrors(result.errors, options.json ?? false);
3062
- if (!result.data?.symbolDependents) {
3063
- outputError("Symbol not found. Verify the symbol reference or use --ref.", options.json ?? false);
3064
- return;
3065
- }
3066
3057
  if (options.json) {
3067
- output(result.data?.symbolDependents, true);
3058
+ output(result.data.symbolDependents, true);
3068
3059
  } else {
3069
- console.log(formatCallersResult(result.data?.symbolDependents));
3060
+ console.log(formatCallersResult(result.data.symbolDependents));
3070
3061
  }
3071
3062
  }
3072
3063
  var CALLERS_DESCRIPTION = `Find what calls a symbol.
@@ -3094,7 +3085,7 @@ function formatDiffResult(data) {
3094
3085
  const s = data.summary;
3095
3086
  lines.push("Summary:");
3096
3087
  lines.push(` Added: ${s.added} Removed: ${s.removed} Modified: ${s.modified} Moved: ${s.moved}`);
3097
- lines.push(` Unchanged: ${s.unchanged} Breaking: ${s.breaking} Behavior changes: ${s.behaviorChange}`);
3088
+ lines.push(` Breaking: ${s.breaking} Behavior changes: ${s.behaviorChange}`);
3098
3089
  if (data.hasMore) {
3099
3090
  lines.push(" (more changes available, increase --limit)");
3100
3091
  }
@@ -3131,14 +3122,10 @@ async function codeDiffAction(packageArg, fromVersion, toVersion, options, deps)
3131
3122
  waitTimeoutMs: parseWaitTimeout(options.wait)
3132
3123
  });
3133
3124
  handleErrors(result.errors, options.json ?? false);
3134
- if (!result.data?.versionDiff) {
3135
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3136
- return;
3137
- }
3138
3125
  if (options.json) {
3139
- output(result.data?.versionDiff, true);
3126
+ output(result.data.versionDiff, true);
3140
3127
  } else {
3141
- console.log(formatDiffResult(result.data?.versionDiff));
3128
+ console.log(formatDiffResult(result.data.versionDiff));
3142
3129
  }
3143
3130
  }
3144
3131
  var DIFF_DESCRIPTION = `Compare symbols between two package versions.
@@ -3191,11 +3178,7 @@ async function codeFilesAction(packageArg, options, deps) {
3191
3178
  waitTimeoutMs: parseWaitTimeout(options.wait)
3192
3179
  });
3193
3180
  handleErrors(result.errors, options.json ?? false);
3194
- if (!result.data?.listRepoFiles) {
3195
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3196
- return;
3197
- }
3198
- const data = result.data?.listRepoFiles;
3181
+ const data = result.data.listRepoFiles;
3199
3182
  if (options.json) {
3200
3183
  output(data, true);
3201
3184
  } else {
@@ -3256,11 +3239,7 @@ async function codeFindAction(packageArg, nameArg, options, deps) {
3256
3239
  waitTimeoutMs: parseWaitTimeout(options.wait)
3257
3240
  });
3258
3241
  handleErrors(result.errors, options.json ?? false);
3259
- if (!result.data?.findSymbol) {
3260
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3261
- return;
3262
- }
3263
- const data = result.data?.findSymbol;
3242
+ const data = result.data.findSymbol;
3264
3243
  if (options.json) {
3265
3244
  output(data, true);
3266
3245
  } else {
@@ -3330,11 +3309,7 @@ async function codeGrepAction(packageArg, filePath, pattern, options, deps) {
3330
3309
  waitTimeoutMs: parseWaitTimeout(options.wait)
3331
3310
  });
3332
3311
  handleErrors(result.errors, options.json ?? false);
3333
- if (!result.data?.grepRepoFile) {
3334
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3335
- return;
3336
- }
3337
- const data = result.data?.grepRepoFile;
3312
+ const data = result.data.grepRepoFile;
3338
3313
  if (options.json) {
3339
3314
  output(data, true);
3340
3315
  } else {
@@ -3417,14 +3392,10 @@ async function codeImportsAction(packageArg, options, deps) {
3417
3392
  waitTimeoutMs: parseWaitTimeout(options.wait)
3418
3393
  });
3419
3394
  handleErrors(result.errors, options.json ?? false);
3420
- if (!result.data?.packageImports) {
3421
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3422
- return;
3423
- }
3424
3395
  if (options.json) {
3425
- output(result.data?.packageImports, true);
3396
+ output(result.data.packageImports, true);
3426
3397
  } else {
3427
- console.log(formatImportsResult(result.data?.packageImports));
3398
+ console.log(formatImportsResult(result.data.packageImports));
3428
3399
  }
3429
3400
  }
3430
3401
  var IMPORTS_DESCRIPTION = `List import statements in a package.
@@ -3486,14 +3457,10 @@ async function codeListAction(packageArg, options, deps) {
3486
3457
  waitTimeoutMs: parseWaitTimeout(options.wait)
3487
3458
  });
3488
3459
  handleErrors(result.errors, options.json ?? false);
3489
- if (!result.data?.listSymbols) {
3490
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3491
- return;
3492
- }
3493
3460
  if (options.json) {
3494
- output(result.data?.listSymbols, true);
3461
+ output(result.data.listSymbols, true);
3495
3462
  } else {
3496
- console.log(formatListResult(result.data?.listSymbols));
3463
+ console.log(formatListResult(result.data.listSymbols));
3497
3464
  }
3498
3465
  }
3499
3466
  var LIST_DESCRIPTION = `Browse symbols in a package.
@@ -3551,14 +3518,10 @@ async function codePathAction(fromArg, toArg, options, deps) {
3551
3518
  waitTimeoutMs: parseWaitTimeout(options.wait)
3552
3519
  });
3553
3520
  handleErrors(result.errors, options.json ?? false);
3554
- if (!result.data?.callPath) {
3555
- outputError("Could not find call path. Verify the symbol references.", options.json ?? false);
3556
- return;
3557
- }
3558
3521
  if (options.json) {
3559
- output(result.data?.callPath, true);
3522
+ output(result.data.callPath, true);
3560
3523
  } else {
3561
- console.log(formatPathResult(result.data?.callPath));
3524
+ console.log(formatPathResult(result.data.callPath));
3562
3525
  }
3563
3526
  }
3564
3527
  var PATH_DESCRIPTION = `Find call path between two symbols.
@@ -3631,11 +3594,7 @@ async function codeSearchAction(packageArg, query, options, deps) {
3631
3594
  waitTimeoutMs: parseWaitTimeout(options.wait)
3632
3595
  });
3633
3596
  handleErrors(result.errors, options.json ?? false);
3634
- if (!result.data?.searchSymbols) {
3635
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3636
- return;
3637
- }
3638
- const data = result.data?.searchSymbols;
3597
+ const data = result.data.searchSymbols;
3639
3598
  if (options.json) {
3640
3599
  output(data, true);
3641
3600
  } else {
@@ -5119,7 +5078,7 @@ async function setupCodexViaCli(shellService) {
5119
5078
  }
5120
5079
  function showAvailableTools(hasProject, useColors) {
5121
5080
  console.log(`
5122
- Available MCP tools (21):`);
5081
+ Available MCP tools (22):`);
5123
5082
  console.log("");
5124
5083
  console.log(" Navigate source:");
5125
5084
  console.log(" • find_symbol - Read source code of functions/classes");
@@ -5130,8 +5089,8 @@ Available MCP tools (21):`);
5130
5089
  console.log(" • call_path - Find call path between two functions");
5131
5090
  console.log("");
5132
5091
  console.log(" Browse files:");
5133
- console.log(" • list_repo_files - Explore package file structure");
5134
- console.log(" • grep_repo_file - Search for patterns in source files");
5092
+ console.log(" • list_package_files - Explore package file structure");
5093
+ console.log(" • grep_package_file - Search for patterns in source files");
5135
5094
  console.log(" • fetch_code_context - Read source by file path and line range");
5136
5095
  console.log("");
5137
5096
  console.log(" Search & docs:");
@@ -6783,9 +6742,9 @@ function toListScope(scope) {
6783
6742
  var schemas = {
6784
6743
  registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).describe("Package registry (npm, pypi, hex, crates, nuget, maven, zig, or vcpkg)"),
6785
6744
  packageName: z2.string().max(255).describe("Name of the package"),
6786
- version: z2.string().max(100).optional().describe("Specific version (defaults to latest)"),
6745
+ version: z2.string().max(100).optional().describe("Specific version, e.g. '4.18.2' (defaults to latest)"),
6787
6746
  navigationMode: z2.enum(["summary", "detailed"]).optional().describe("Response detail level. summary (default) returns core fields; detailed adds all optional fields."),
6788
- waitTimeoutMs: z2.number().int().min(0).max(30000).optional().describe("Max milliseconds to wait for package indexing (0-30000). 0 = error immediately if not indexed."),
6747
+ 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."),
6789
6748
  symbolReference: z2.object({
6790
6749
  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."),
6791
6750
  registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (required for name-based lookup)"),
@@ -6801,9 +6760,10 @@ function toSymbolReferenceInput(ref) {
6801
6760
  symbolName: ref.symbol_name
6802
6761
  };
6803
6762
  }
6763
+ var DEFAULT_WAIT_TIMEOUT_MS2 = 1e4;
6804
6764
  var MCP_HINTS = {
6805
6765
  being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
6806
- timeout: "Hint: try lowering the limit or narrowing the scope, then retry."
6766
+ timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
6807
6767
  };
6808
6768
  function buildHintedMessage(operation, message) {
6809
6769
  const kind = classifyError(message);
@@ -6831,9 +6791,9 @@ function buildHintedMessage(operation, message) {
6831
6791
  return `Failed to ${operation}: ${message}`;
6832
6792
  }
6833
6793
  var MCP_GRAPHQL_HINTS = {
6834
- not_found: "Hint: verify the name/registry and that the resource exists.",
6794
+ not_found: "Hint: verify the package name and registry are correct.",
6835
6795
  being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
6836
- timeout: "Hint: try lowering the limit or narrowing the scope, then retry."
6796
+ timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
6837
6797
  };
6838
6798
  function handleGraphQLErrors(errors) {
6839
6799
  if (errors && errors.length > 0) {
@@ -6853,14 +6813,14 @@ async function withErrorHandling(operation, fn) {
6853
6813
  }
6854
6814
  }
6855
6815
  function notFoundError(packageName, registry) {
6856
- return errorResult(`Package not found: ${packageName} in ${registry}`);
6816
+ return errorResult(`Package not found: ${packageName} in ${registry}. Verify the package name and registry are correct.`);
6857
6817
  }
6858
6818
 
6859
6819
  // src/tools/call-path.ts
6860
6820
  var argsSchema = {
6861
6821
  from: schemas.symbolReference.describe("Source symbol. Provide either symbol_ref or registry + package_name + symbol_name."),
6862
6822
  to: schemas.symbolReference.describe("Destination symbol. Provide either symbol_ref or registry + package_name + symbol_name."),
6863
- max_depth: z3.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
6823
+ max_depth: z3.coerce.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
6864
6824
  mode: schemas.navigationMode,
6865
6825
  wait_timeout_ms: schemas.waitTimeoutMs
6866
6826
  };
@@ -6883,15 +6843,12 @@ function createCallPathTool(pkgseerService) {
6883
6843
  const result = await pkgseerService.callPath(fromInput, toInput, {
6884
6844
  maxDepth: args.max_depth,
6885
6845
  mode: toNavigationMode(args.mode),
6886
- waitTimeoutMs: args.wait_timeout_ms
6846
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
6887
6847
  });
6888
6848
  const graphqlError = handleGraphQLErrors(result.errors);
6889
6849
  if (graphqlError)
6890
6850
  return graphqlError;
6891
- if (!result.data?.callPath) {
6892
- return errorResult("Could not find call path. Verify the symbols exist and the package is indexed.");
6893
- }
6894
- return textResult(JSON.stringify(result.data?.callPath, null, 2));
6851
+ return textResult(JSON.stringify(result.data.callPath, null, 2));
6895
6852
  });
6896
6853
  }
6897
6854
  };
@@ -6909,7 +6866,7 @@ var argsSchema2 = {
6909
6866
  function createComparePackagesTool(pkgseerService) {
6910
6867
  return {
6911
6868
  name: "compare_packages",
6912
- 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"}]',
6869
+ 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"}]',
6913
6870
  schema: argsSchema2,
6914
6871
  annotations: { readOnlyHint: true },
6915
6872
  handler: async ({ packages }, _extra) => {
@@ -6934,16 +6891,22 @@ function createComparePackagesTool(pkgseerService) {
6934
6891
  // src/tools/fetch-code-context.ts
6935
6892
  import { z as z5 } from "zod";
6936
6893
  var argsSchema3 = {
6937
- repo_url: z5.string().min(1).describe("Repository URL (GitHub). Example: https://github.com/expressjs/express"),
6938
- git_ref: z5.string().min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
6939
- file_path: z5.string().min(1).describe("Path to file in repository. Example: src/router/index.js"),
6940
- start_line: z5.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
6941
- end_line: z5.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
6894
+ repo_url: z5.string({
6895
+ error: "repo_url is required. Get it from package_summary (returns repository URL). " + "Or use find_symbol(include_code=true) to read source without needing repo_url."
6896
+ }).min(1).describe("Repository URL (GitHub). Example: https://github.com/expressjs/express"),
6897
+ git_ref: z5.string({
6898
+ error: "git_ref is required. Use the package version as a tag (e.g., 'v4.18.2'). " + "Get the latest version from package_summary."
6899
+ }).min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
6900
+ file_path: z5.string({
6901
+ error: "file_path is required. Get file paths from find_symbol (returns file locations) " + "or list_package_files (browse package file structure)."
6902
+ }).min(1).describe("Path to file in repository. Example: src/router/index.js"),
6903
+ start_line: z5.coerce.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
6904
+ end_line: z5.coerce.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
6942
6905
  };
6943
6906
  function createFetchCodeContextTool(pkgseerService) {
6944
6907
  return {
6945
6908
  name: "fetch_code_context",
6946
- 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.",
6909
+ description: "Read source code from a dependency's repository by file path and line range — " + "use when you have a file path from a stack trace or symbol lookup. " + "Returns full file or a specific line range. " + "Prefer find_symbol(include_code=true) for function/class lookup. " + "Requires repo_url (from package_summary), git_ref (version tag, e.g. 'v4.18.2'), " + "and file_path (from find_symbol or list_package_files). " + "Operates on the full repository — not filtered to package subdirectory in monorepos.",
6947
6910
  schema: argsSchema3,
6948
6911
  annotations: { readOnlyHint: true },
6949
6912
  handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
@@ -6971,7 +6934,7 @@ var argsSchema4 = {
6971
6934
  function createFetchPackageDocTool(pkgseerService) {
6972
6935
  return {
6973
6936
  name: "fetch_package_doc",
6974
- 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.",
6937
+ 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.",
6975
6938
  schema: argsSchema4,
6976
6939
  annotations: { readOnlyHint: true },
6977
6940
  handler: async ({ page_id }, _extra) => {
@@ -7007,14 +6970,14 @@ var argsSchema5 = {
7007
6970
  public_only: z7.boolean().optional().describe("Only return public/exported symbols"),
7008
6971
  version: schemas.version,
7009
6972
  include_code: z7.boolean().optional().describe("Include source code in results"),
7010
- context_lines: z7.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
6973
+ context_lines: z7.coerce.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
7011
6974
  mode: schemas.navigationMode,
7012
6975
  wait_timeout_ms: schemas.waitTimeoutMs
7013
6976
  };
7014
6977
  function createFindSymbolTool(pkgseerService) {
7015
6978
  return {
7016
6979
  name: "find_symbol",
7017
- description: "Read source code of any function, class, or method in a third-party package — " + "use instead of guessing implementations from training data. " + "Set include_code=true for full source inline. " + "Returns: symbol ref, name, qualified path, kind, file location, and optionally source code. " + "Omit name to get all public exports. Use namespace to filter by module path.",
6980
+ description: "Read source code of any function, class, or method in a third-party package — " + "use instead of guessing implementations from training data. " + "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.",
7018
6981
  schema: argsSchema5,
7019
6982
  annotations: { readOnlyHint: true },
7020
6983
  handler: async (args, _extra) => {
@@ -7028,15 +6991,12 @@ function createFindSymbolTool(pkgseerService) {
7028
6991
  includeCode: args.include_code,
7029
6992
  contextLines: args.context_lines,
7030
6993
  mode: toNavigationMode(args.mode),
7031
- waitTimeoutMs: args.wait_timeout_ms
6994
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7032
6995
  });
7033
6996
  const graphqlError = handleGraphQLErrors(result.errors);
7034
6997
  if (graphqlError)
7035
6998
  return graphqlError;
7036
- if (!result.data?.findSymbol) {
7037
- return notFoundError(args.package_name, args.registry);
7038
- }
7039
- const data = result.data?.findSymbol;
6999
+ const data = result.data.findSymbol;
7040
7000
  if (data.symbols.length === 0 && data.diagnostics?.hint) {
7041
7001
  return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7042
7002
  }
@@ -7045,39 +7005,36 @@ function createFindSymbolTool(pkgseerService) {
7045
7005
  }
7046
7006
  };
7047
7007
  }
7048
- // src/tools/grep-repo-file.ts
7008
+ // src/tools/grep-package-file.ts
7049
7009
  import { z as z8 } from "zod";
7050
7010
  var argsSchema6 = {
7051
7011
  registry: schemas.registry,
7052
7012
  package_name: schemas.packageName.describe("Name of the package to search within"),
7053
7013
  file_path: z8.string().describe("Path to the file (relative to package root)"),
7054
7014
  pattern: z8.string().max(200).describe("Case-insensitive substring to search for (max 200 chars)"),
7055
- context_lines: z8.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
7056
- max_matches: z8.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
7015
+ context_lines: z8.coerce.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
7016
+ max_matches: z8.coerce.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
7057
7017
  version: schemas.version,
7058
7018
  wait_timeout_ms: schemas.waitTimeoutMs
7059
7019
  };
7060
- function createGrepRepoFileTool(pkgseerService) {
7020
+ function createGrepPackageFileTool(pkgseerService) {
7061
7021
  return {
7062
- name: "grep_repo_file",
7063
- 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. " + "Faster than fetch_code_context for large files. " + "Use list_repo_files to discover file paths.",
7022
+ name: "grep_package_file",
7023
+ description: "Search for a pattern within a dependency's source file — " + "find error messages, config keys, or specific patterns without cloning the repo. " + "Case-insensitive substring matching with context lines. " + "Use when you know the file path and are looking for specific text. " + "Use list_package_files to discover file paths. " + "In monorepos, operates only within this package's subdirectory. " + "Requires code indexing.",
7064
7024
  schema: argsSchema6,
7065
7025
  annotations: { readOnlyHint: true },
7066
7026
  handler: async (args, _extra) => {
7067
- return withErrorHandling("grep repo file", async () => {
7027
+ return withErrorHandling("grep package file", async () => {
7068
7028
  const result = await pkgseerService.grepRepoFile(toGraphQLRegistry(args.registry), args.package_name, args.file_path, args.pattern, {
7069
7029
  contextLines: args.context_lines,
7070
7030
  maxMatches: args.max_matches,
7071
7031
  version: args.version,
7072
- waitTimeoutMs: args.wait_timeout_ms
7032
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7073
7033
  });
7074
7034
  const graphqlError = handleGraphQLErrors(result.errors);
7075
7035
  if (graphqlError)
7076
7036
  return graphqlError;
7077
- if (!result.data?.grepRepoFile) {
7078
- return notFoundError(args.package_name, args.registry);
7079
- }
7080
- const data = result.data?.grepRepoFile;
7037
+ const data = result.data.grepRepoFile;
7081
7038
  if (data.matches.length === 0 && data.diagnostics?.hint) {
7082
7039
  return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7083
7040
  }
@@ -7095,7 +7052,7 @@ var argsSchema7 = {
7095
7052
  function createListPackageDocsTool(pkgseerService) {
7096
7053
  return {
7097
7054
  name: "list_package_docs",
7098
- 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.",
7055
+ 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.",
7099
7056
  schema: argsSchema7,
7100
7057
  annotations: { readOnlyHint: true },
7101
7058
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
@@ -7112,37 +7069,34 @@ function createListPackageDocsTool(pkgseerService) {
7112
7069
  }
7113
7070
  };
7114
7071
  }
7115
- // src/tools/list-repo-files.ts
7072
+ // src/tools/list-package-files.ts
7116
7073
  import { z as z9 } from "zod";
7117
7074
  var argsSchema8 = {
7118
7075
  registry: schemas.registry,
7119
7076
  package_name: schemas.packageName.describe("Name of the package to list files for"),
7120
7077
  version: schemas.version,
7121
7078
  path_prefix: z9.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
7122
- limit: z9.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
7079
+ limit: z9.coerce.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
7123
7080
  wait_timeout_ms: schemas.waitTimeoutMs
7124
7081
  };
7125
- function createListRepoFilesTool(pkgseerService) {
7082
+ function createListPackageFilesTool(pkgseerService) {
7126
7083
  return {
7127
- name: "list_repo_files",
7128
- description: "Explore a dependency's file structure — " + "see what source files, configs, and docs exist. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals.",
7084
+ name: "list_package_files",
7085
+ description: "Explore a dependency's file structure — " + "see what source files, configs, and docs exist. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals. " + "In monorepos, returns only files within this package's subdirectory. " + "Requires code indexing.",
7129
7086
  schema: argsSchema8,
7130
7087
  annotations: { readOnlyHint: true },
7131
7088
  handler: async (args, _extra) => {
7132
- return withErrorHandling("list repo files", async () => {
7089
+ return withErrorHandling("list package files", async () => {
7133
7090
  const result = await pkgseerService.listRepoFiles(toGraphQLRegistry(args.registry), args.package_name, {
7134
7091
  version: args.version,
7135
7092
  pathPrefix: args.path_prefix,
7136
7093
  limit: args.limit,
7137
- waitTimeoutMs: args.wait_timeout_ms
7094
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7138
7095
  });
7139
7096
  const graphqlError = handleGraphQLErrors(result.errors);
7140
7097
  if (graphqlError)
7141
7098
  return graphqlError;
7142
- if (!result.data?.listRepoFiles) {
7143
- return notFoundError(args.package_name, args.registry);
7144
- }
7145
- const data = result.data?.listRepoFiles;
7099
+ const data = result.data.listRepoFiles;
7146
7100
  if (data.files.length === 0 && data.diagnostics?.hint) {
7147
7101
  return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7148
7102
  }
@@ -7161,7 +7115,7 @@ var argsSchema9 = {
7161
7115
  namespace: z10.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
7162
7116
  public_only: z10.boolean().optional().describe("Only return public symbols"),
7163
7117
  include_popularity: z10.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
7164
- limit: z10.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
7118
+ limit: z10.coerce.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
7165
7119
  version: schemas.version,
7166
7120
  mode: schemas.navigationMode,
7167
7121
  wait_timeout_ms: schemas.waitTimeoutMs
@@ -7194,15 +7148,12 @@ function createListSymbolsTool(pkgseerService) {
7194
7148
  limit: args.limit,
7195
7149
  version: args.version,
7196
7150
  mode: toNavigationMode(args.mode),
7197
- waitTimeoutMs: args.wait_timeout_ms
7151
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7198
7152
  });
7199
7153
  const graphqlError = handleGraphQLErrors(result.errors);
7200
7154
  if (graphqlError)
7201
7155
  return graphqlError;
7202
- if (!result.data?.listSymbols) {
7203
- return notFoundError(args.package_name, args.registry);
7204
- }
7205
- return textResult(JSON.stringify(result.data?.listSymbols, null, 2));
7156
+ return textResult(JSON.stringify(result.data.listSymbols, null, 2));
7206
7157
  });
7207
7158
  }
7208
7159
  };
@@ -7214,7 +7165,7 @@ var argsSchema10 = {
7214
7165
  package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
7215
7166
  version: schemas.version,
7216
7167
  include_transitive: z11.boolean().optional().describe("Whether to include transitive dependency DAG"),
7217
- max_depth: z11.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
7168
+ max_depth: z11.coerce.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
7218
7169
  };
7219
7170
  function decodeDag(rawDag) {
7220
7171
  if (!rawDag || typeof rawDag !== "object")
@@ -7337,7 +7288,7 @@ var argsSchema11 = {
7337
7288
  package_name: schemas.packageName.describe("Name of the package to get imports for"),
7338
7289
  file_path: z12.string().max(1000).optional().describe("Filter to a specific file path"),
7339
7290
  resolved_only: z12.boolean().optional().describe("Only return imports resolved to a known package"),
7340
- limit: z12.number().int().min(1).max(500).optional().describe("Max imports to return"),
7291
+ limit: z12.coerce.number().int().min(1).max(500).optional().describe("Max imports to return"),
7341
7292
  version: schemas.version,
7342
7293
  mode: schemas.navigationMode,
7343
7294
  wait_timeout_ms: schemas.waitTimeoutMs
@@ -7356,15 +7307,12 @@ function createPackageImportsTool(pkgseerService) {
7356
7307
  limit: args.limit,
7357
7308
  version: args.version,
7358
7309
  mode: toNavigationMode(args.mode),
7359
- waitTimeoutMs: args.wait_timeout_ms
7310
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7360
7311
  });
7361
7312
  const graphqlError = handleGraphQLErrors(result.errors);
7362
7313
  if (graphqlError)
7363
7314
  return graphqlError;
7364
- if (!result.data?.packageImports) {
7365
- return notFoundError(args.package_name, args.registry);
7366
- }
7367
- return textResult(JSON.stringify(result.data?.packageImports, null, 2));
7315
+ return textResult(JSON.stringify(result.data.packageImports, null, 2));
7368
7316
  });
7369
7317
  }
7370
7318
  };
@@ -7378,7 +7326,7 @@ var argsSchema12 = {
7378
7326
  function createPackageQualityTool(pkgseerService) {
7379
7327
  return {
7380
7328
  name: "package_quality",
7381
- 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.",
7329
+ 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.",
7382
7330
  schema: argsSchema12,
7383
7331
  annotations: { readOnlyHint: true },
7384
7332
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
@@ -7403,7 +7351,7 @@ var argsSchema13 = {
7403
7351
  function createPackageSummaryTool(pkgseerService) {
7404
7352
  return {
7405
7353
  name: "package_summary",
7406
- 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).",
7354
+ 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.",
7407
7355
  schema: argsSchema13,
7408
7356
  annotations: { readOnlyHint: true },
7409
7357
  handler: async ({ registry, package_name }, _extra) => {
@@ -7429,7 +7377,7 @@ var argsSchema14 = {
7429
7377
  function createPackageVulnerabilitiesTool(pkgseerService) {
7430
7378
  return {
7431
7379
  name: "package_vulnerabilities",
7432
- 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.",
7380
+ 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.",
7433
7381
  schema: argsSchema14,
7434
7382
  annotations: { readOnlyHint: true },
7435
7383
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
@@ -7453,13 +7401,16 @@ var packageInputSchema2 = z13.object({
7453
7401
  name: z13.string().min(1).describe("Package name"),
7454
7402
  version: z13.string().optional().describe("Specific version (defaults to latest)")
7455
7403
  });
7456
- var DEFAULT_AGENT_WAIT_TIMEOUT_MS = 1e4;
7457
7404
  var argsSchema15 = {
7458
- packages: z13.array(packageInputSchema2).min(1).max(20).describe("Packages to search (1-20). Each package needs registry and name."),
7459
- query: z13.string().min(1).describe("Search query - natural language or keywords"),
7405
+ packages: z13.array(packageInputSchema2, {
7406
+ 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."
7407
+ }).min(1).max(20).describe('Packages to search (1-20). Format: [{"registry":"npm","name":"express"}]'),
7408
+ query: z13.string({
7409
+ error: "query is required. Provide search terms as natural language or keywords, " + "e.g., 'error handling middleware'."
7410
+ }).min(1).describe("Search query - natural language or keywords"),
7460
7411
  mode: z13.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
7461
- limit: z13.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
7462
- waitTimeoutMs: z13.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
7412
+ limit: z13.coerce.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
7413
+ waitTimeoutMs: z13.coerce.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
7463
7414
  };
7464
7415
  function toSearchMode2(mode) {
7465
7416
  if (!mode)
@@ -7497,7 +7448,7 @@ Results may be incomplete. Retry later for more complete results.`;
7497
7448
  function createSearchTool(pkgseerService) {
7498
7449
  return {
7499
7450
  name: "search",
7500
- description: "Search code and documentation across packages. Returns functions, classes, and doc pages " + "matching your query. Use mode='code' for code only, mode='docs' for docs only, or " + "mode='all' (default). Provide 1-20 packages. Results include relevance scores and snippets. " + "For full source of code results, use find_symbol(name=<title>, include_code=true). " + "If packages need indexing, waits up to waitTimeoutMs (default 10s) or returns searchRef — use search_status to poll.",
7451
+ description: "Search code and documentation across packages using full-text search. " + "Returns code chunks and doc pages matching your query with relevance scores and snippets. " + "Use mode='code' for code only, mode='docs' for docs only, or mode='all' (default). " + "Provide 1-20 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.",
7501
7452
  schema: argsSchema15,
7502
7453
  annotations: { readOnlyHint: true },
7503
7454
  handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
@@ -7514,7 +7465,7 @@ function createSearchTool(pkgseerService) {
7514
7465
  const result = await pkgseerService.combinedSearch(graphqlPackages, normalizedQuery, {
7515
7466
  mode: toSearchMode2(mode),
7516
7467
  limit,
7517
- waitTimeoutMs: waitTimeoutMs ?? DEFAULT_AGENT_WAIT_TIMEOUT_MS
7468
+ waitTimeoutMs: waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS2
7518
7469
  });
7519
7470
  const graphqlError = handleGraphQLErrors(result.errors);
7520
7471
  if (graphqlError)
@@ -7558,7 +7509,7 @@ var argsSchema16 = {
7558
7509
  terms: z14.array(z14.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
7559
7510
  match_mode: z14.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
7560
7511
  include_snippets: z14.boolean().optional().describe("Include content excerpts around matches"),
7561
- limit: z14.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
7512
+ limit: z14.coerce.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
7562
7513
  };
7563
7514
  function createSearchProjectDocsTool(deps) {
7564
7515
  const { pkgseerService, configService, defaultProjectDir } = deps;
@@ -7583,7 +7534,9 @@ function createSearchProjectDocsTool(deps) {
7583
7534
  return errorResult(`No project specified and no pkgseer.yml found. To fix:
7584
7535
  ` + ` 1. Pass project_directory: '/path/to/project' (folder containing pkgseer.yml)
7585
7536
  ` + ` 2. Pass project: 'project-name' directly if you know the project name
7586
- ` + " 3. Run 'pkgseer project init' to create pkgseer.yml in your project");
7537
+ ` + ` 3. Run 'pkgseer project init' to create pkgseer.yml in your project
7538
+
7539
+ ` + "Or use search(mode='docs', packages=[{registry: 'npm', name: '...'}]) to search " + "specific packages without a project.");
7587
7540
  }
7588
7541
  const normalizedTerms = terms?.map((term) => term.trim()).filter((term) => term.length > 0) ?? [];
7589
7542
  if (normalizedTerms.length === 0) {
@@ -7680,14 +7633,14 @@ var argsSchema18 = {
7680
7633
  ]).optional().describe("Filter results by code chunk type"),
7681
7634
  file_path: z16.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
7682
7635
  version: schemas.version,
7683
- limit: z16.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
7636
+ limit: z16.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
7684
7637
  mode: schemas.navigationMode,
7685
7638
  wait_timeout_ms: schemas.waitTimeoutMs
7686
7639
  };
7687
7640
  function createSearchSymbolsTool(pkgseerService) {
7688
7641
  return {
7689
7642
  name: "search_symbols",
7690
- 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 matching code chunks with name, type, file path, line numbers, and content previews. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source.",
7643
+ description: "Search a dependency's source code by text using the code navigation index — " + "find where error messages, exceptions, or patterns appear across functions, classes, and modules. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns symbol-level results that can feed directly into symbol_callers, symbol_callees, or call_path. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source. " + "For free-form text search across multiple packages, use search(mode='code') instead.",
7691
7644
  schema: argsSchema18,
7692
7645
  annotations: { readOnlyHint: true },
7693
7646
  handler: async (args, _extra) => {
@@ -7701,15 +7654,12 @@ function createSearchSymbolsTool(pkgseerService) {
7701
7654
  version: args.version,
7702
7655
  limit: args.limit,
7703
7656
  mode: toNavigationMode(args.mode),
7704
- waitTimeoutMs: args.wait_timeout_ms
7657
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7705
7658
  });
7706
7659
  const graphqlError = handleGraphQLErrors(result.errors);
7707
7660
  if (graphqlError)
7708
7661
  return graphqlError;
7709
- if (!result.data?.searchSymbols) {
7710
- return notFoundError(args.package_name, args.registry);
7711
- }
7712
- const data = result.data?.searchSymbols;
7662
+ const data = result.data.searchSymbols;
7713
7663
  const extra = {};
7714
7664
  if (data.results.length === 0 && data.diagnostics?.hint) {
7715
7665
  extra._hint = data.diagnostics.hint;
@@ -7729,9 +7679,9 @@ function createSearchSymbolsTool(pkgseerService) {
7729
7679
  import { z as z17 } from "zod";
7730
7680
  var argsSchema19 = {
7731
7681
  symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide either symbol_ref or registry + package_name + symbol_name."),
7732
- max_depth: z17.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
7733
- limit: z17.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
7734
- include_external: z17.boolean().optional().describe("Include calls to symbols in other packages"),
7682
+ max_depth: z17.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
7683
+ limit: z17.coerce.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
7684
+ include_external: z17.boolean().optional().describe("Include calls to symbols in other indexed packages. " + "Default (false) shows only calls within the same package."),
7735
7685
  include_builtins: z17.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
7736
7686
  mode: schemas.navigationMode,
7737
7687
  wait_timeout_ms: schemas.waitTimeoutMs
@@ -7754,15 +7704,12 @@ function createSymbolCalleesTool(pkgseerService) {
7754
7704
  includeExternal: args.include_external,
7755
7705
  includeBuiltins: args.include_builtins,
7756
7706
  mode: toNavigationMode(args.mode),
7757
- waitTimeoutMs: args.wait_timeout_ms
7707
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7758
7708
  });
7759
7709
  const graphqlError = handleGraphQLErrors(result.errors);
7760
7710
  if (graphqlError)
7761
7711
  return graphqlError;
7762
- if (!result.data?.symbolDependencies) {
7763
- return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
7764
- }
7765
- return textResult(JSON.stringify(result.data?.symbolDependencies, null, 2));
7712
+ return textResult(JSON.stringify(result.data.symbolDependencies, null, 2));
7766
7713
  });
7767
7714
  }
7768
7715
  };
@@ -7771,16 +7718,16 @@ function createSymbolCalleesTool(pkgseerService) {
7771
7718
  import { z as z18 } from "zod";
7772
7719
  var argsSchema20 = {
7773
7720
  symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide either symbol_ref or registry + package_name + symbol_name."),
7774
- same_package_only: z18.boolean().optional().describe("Only return callers from the same package"),
7775
- max_depth: z18.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
7776
- limit: z18.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
7721
+ same_package_only: z18.boolean().optional().describe("Only return callers from the same package. " + "Default (false) includes callers from other indexed packages."),
7722
+ max_depth: z18.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
7723
+ limit: z18.coerce.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
7777
7724
  mode: schemas.navigationMode,
7778
7725
  wait_timeout_ms: schemas.waitTimeoutMs
7779
7726
  };
7780
7727
  function createSymbolCallersTool(pkgseerService) {
7781
7728
  return {
7782
7729
  name: "symbol_callers",
7783
- 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.",
7730
+ description: "Trace what calls a function in a dependency's source code — " + "find entry points or debug why behavior triggers. " + "Returns callers with file locations and call line numbers. " + "Use same_package_only for within-package callers only. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callees for the reverse. " + "Use find_symbol(include_code=true) on any caller to read its source.",
7784
7731
  schema: argsSchema20,
7785
7732
  annotations: { readOnlyHint: true },
7786
7733
  handler: async (args, _extra) => {
@@ -7794,15 +7741,12 @@ function createSymbolCallersTool(pkgseerService) {
7794
7741
  maxDepth: args.max_depth,
7795
7742
  maxResults: args.limit,
7796
7743
  mode: toNavigationMode(args.mode),
7797
- waitTimeoutMs: args.wait_timeout_ms
7744
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7798
7745
  });
7799
7746
  const graphqlError = handleGraphQLErrors(result.errors);
7800
7747
  if (graphqlError)
7801
7748
  return graphqlError;
7802
- if (!result.data?.symbolDependents) {
7803
- return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
7804
- }
7805
- return textResult(JSON.stringify(result.data?.symbolDependents, null, 2));
7749
+ return textResult(JSON.stringify(result.data.symbolDependents, null, 2));
7806
7750
  });
7807
7751
  }
7808
7752
  };
@@ -7826,7 +7770,7 @@ var argsSchema21 = {
7826
7770
  function createTriggerIndexingTool(pkgseerService) {
7827
7771
  return {
7828
7772
  name: "trigger_indexing",
7829
- 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.",
7773
+ 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.",
7830
7774
  schema: argsSchema21,
7831
7775
  annotations: { readOnlyHint: false, idempotentHint: true },
7832
7776
  handler: async (args, _extra) => {
@@ -7881,7 +7825,7 @@ var argsSchema22 = {
7881
7825
  "type",
7882
7826
  "doc_section"
7883
7827
  ]).optional().describe("Filter by symbol kind"),
7884
- limit: z20.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
7828
+ limit: z20.coerce.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
7885
7829
  wait_timeout_ms: schemas.waitTimeoutMs
7886
7830
  };
7887
7831
  function createVersionDiffTool(pkgseerService) {
@@ -7896,15 +7840,12 @@ function createVersionDiffTool(pkgseerService) {
7896
7840
  includePrivate: args.include_private,
7897
7841
  kind: toSymbolKind(args.kind),
7898
7842
  limit: args.limit,
7899
- waitTimeoutMs: args.wait_timeout_ms
7843
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7900
7844
  });
7901
7845
  const graphqlError = handleGraphQLErrors(result.errors);
7902
7846
  if (graphqlError)
7903
7847
  return graphqlError;
7904
- if (!result.data?.versionDiff) {
7905
- return notFoundError(args.package_name, args.registry);
7906
- }
7907
- return textResult(JSON.stringify(result.data?.versionDiff, null, 2));
7848
+ return textResult(JSON.stringify(result.data.versionDiff, null, 2));
7908
7849
  });
7909
7850
  }
7910
7851
  };
@@ -7920,18 +7861,47 @@ Use PkgSeer when:
7920
7861
  - You need to understand what changed between package versions
7921
7862
 
7922
7863
  Instead of guessing library behavior from training data, use find_symbol(include_code=true) to read actual source.
7923
- Instead of cloning repos to search code, use search_symbols or grep_repo_file.
7864
+ Instead of cloning repos to search code, use search_symbols or grep_package_file.
7924
7865
  Instead of manually tracing call chains on GitHub, use symbol_callers and symbol_callees.
7925
7866
 
7926
- Tool groups:
7927
- - Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
7928
- - Browse files: list_repo_files, grep_repo_file, fetch_code_context
7929
- - Search across packages: search, search_project_docs
7930
- - Browse docs: list_package_docs, fetch_package_doc
7931
- - Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
7932
- - Utility: trigger_indexing, search_status, package_imports
7867
+ Data availability — tools are grouped by what backend data they need:
7868
+
7869
+ 1. Registry metadata (available immediately, no indexing):
7870
+ package_summary, package_quality, package_vulnerabilities, package_dependencies, compare_packages
7871
+ Start here when researching a package — these always work instantly.
7872
+
7873
+ 2. Documentation (requires doc site crawling):
7874
+ list_package_docs, fetch_package_doc, search(mode='docs'), search_project_docs
7875
+ If results are empty, docs may not be crawled yet — use trigger_indexing first, then retry.
7876
+
7877
+ 3. Package code (requires code repo indexing):
7878
+ find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path,
7879
+ package_imports, version_diff, list_package_files, grep_package_file, search(mode='code')
7880
+ 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.
7881
+
7882
+ 4. Repository (full repo scope, not package-filtered):
7883
+ fetch_code_context
7884
+ Uses repo_url (get from package_summary) + git_ref (version tag) + file_path. Operates on the full repository, not filtered to a package subdirectory.
7885
+
7886
+ Scope — package vs repository:
7887
+ Package code tools (group 3) are scoped to a single package. In monorepos, they return only data from that package's subdirectory. fetch_code_context (group 4) operates on the full repository. symbol_callers/symbol_callees can show cross-package results from other indexed packages.
7888
+
7889
+ Choosing a code search tool:
7890
+ - search_symbols: single package, symbol-level → results feed symbol_callers/callees/call_path
7891
+ - search(mode='code'): multi-package, full-text → code chunks with snippets
7892
+ - grep_package_file: single file, pattern match → when you know the file path
7893
+
7894
+ Utility: trigger_indexing (pre-warm indexes), search_status (poll async search).
7895
+
7896
+ Quick start: find_symbol(registry="npm", name="<function>", package_name="<pkg>", include_code=true) often answers the question in one call.
7933
7897
 
7934
- Quick start: find_symbol(registry="npm", name="<function>", package_name="<pkg>", include_code=true) often answers the question in one call.`;
7898
+ Common workflows (pass symbolRef between tools for chaining):
7899
+ - Read source: find_symbol(name=<fn>, include_code=true)
7900
+ - Trace calls: find_symbol → symbol_callees(symbol={symbol_ref: <symbolRef>})
7901
+ - Find callers: find_symbol → symbol_callers(symbol={symbol_ref: <symbolRef>})
7902
+ - Read file: package_summary → fetch_code_context(repo_url, git_ref, file_path)
7903
+ - Search code: search_symbols (single pkg, feeds callers/callees) or search(mode='code', packages=[...]) (multi-pkg)
7904
+ - Browse docs: list_package_docs → fetch_package_doc(page_id)`;
7935
7905
  var TOOL_FACTORIES = {
7936
7906
  package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
7937
7907
  package_vulnerabilities: ({ pkgseerService }) => createPackageVulnerabilitiesTool(pkgseerService),
@@ -7956,8 +7926,8 @@ var TOOL_FACTORIES = {
7956
7926
  package_imports: ({ pkgseerService }) => createPackageImportsTool(pkgseerService),
7957
7927
  call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
7958
7928
  trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService),
7959
- list_repo_files: ({ pkgseerService }) => createListRepoFilesTool(pkgseerService),
7960
- grep_repo_file: ({ pkgseerService }) => createGrepRepoFileTool(pkgseerService),
7929
+ list_package_files: ({ pkgseerService }) => createListPackageFilesTool(pkgseerService),
7930
+ grep_package_file: ({ pkgseerService }) => createGrepPackageFileTool(pkgseerService),
7961
7931
  version_diff: ({ pkgseerService }) => createVersionDiffTool(pkgseerService)
7962
7932
  };
7963
7933
  var PUBLIC_READ_TOOLS = [
@@ -7979,8 +7949,8 @@ var PUBLIC_READ_TOOLS = [
7979
7949
  "package_imports",
7980
7950
  "call_path",
7981
7951
  "trigger_indexing",
7982
- "list_repo_files",
7983
- "grep_repo_file",
7952
+ "list_package_files",
7953
+ "grep_package_file",
7984
7954
  "version_diff"
7985
7955
  ];
7986
7956
  var PROJECT_READ_TOOLS = ["search_project_docs"];
@@ -8053,9 +8023,9 @@ function registerMcpCommand(program) {
8053
8023
  When run interactively (TTY), shows setup instructions.
8054
8024
  When run via stdio (non-TTY), starts the MCP server.
8055
8025
 
8056
- Available tools (21):
8026
+ Available tools (22):
8057
8027
  Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
8058
- Browse files: list_repo_files, grep_repo_file, fetch_code_context
8028
+ Browse files: list_package_files, grep_package_file, fetch_code_context
8059
8029
  Search: search, search_project_docs
8060
8030
  Docs: list_package_docs, fetch_package_doc
8061
8031
  Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./shared/chunk-bahf01jh.js";
3
+ } from "./shared/chunk-r3pnzy5b.js";
4
4
  export {
5
5
  version
6
6
  };
@@ -1,4 +1,4 @@
1
1
  // package.json
2
- var version = "0.4.9";
2
+ var version = "0.4.11";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pkgseer/cli",
3
3
  "description": "CLI companion for PkgSeer - package intelligence for developers and AI assistants",
4
- "version": "0.4.9",
4
+ "version": "0.4.11",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -27,6 +27,8 @@
27
27
  "dev": "bun run ./src/cli.ts",
28
28
  "inspector": "npx @modelcontextprotocol/inspector bun run dev mcp",
29
29
  "test": "bun test",
30
+ "e2e": "bun test ./e2e/code-navigation.e2e.ts ./e2e/code-graph.e2e.ts ./e2e/package-intel.e2e.ts ./e2e/docs.e2e.ts ./e2e/search.e2e.ts --timeout 60000",
31
+ "e2e:update": "UPDATE_BASELINES=1 bun test ./e2e/code-navigation.e2e.ts ./e2e/code-graph.e2e.ts ./e2e/package-intel.e2e.ts ./e2e/docs.e2e.ts ./e2e/search.e2e.ts --timeout 60000",
30
32
  "typecheck": "tsc",
31
33
  "format": "biome format --write .",
32
34
  "format:check": "biome format .",