@pkgseer/cli 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  version
4
- } from "./shared/chunk-kh5enjt9.js";
4
+ } from "./shared/chunk-x6hqsn93.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -335,6 +335,8 @@ var FetchCodeContextDocument = gql`
335
335
  endLine
336
336
  repoUrl
337
337
  gitRef
338
+ indexingStatus
339
+ indexingRef
338
340
  }
339
341
  }
340
342
  `;
@@ -363,6 +365,16 @@ var TriggerIndexingDocument = gql`
363
365
  }
364
366
  }
365
367
  `;
368
+ var IndexingProgressDocument = gql`
369
+ query IndexingProgress($ref: String!) {
370
+ indexingProgress(ref: $ref) {
371
+ status
372
+ filesIndexed
373
+ chunksCreated
374
+ elapsedMs
375
+ }
376
+ }
377
+ `;
366
378
  var CreateProjectDocument = gql`
367
379
  mutation CreateProject($input: CreateProjectInput!) {
368
380
  createProject(input: $input) {
@@ -699,6 +711,8 @@ var FindSymbolDocument = gql`
699
711
  indexedAt
700
712
  hint
701
713
  }
714
+ indexingStatus
715
+ indexingRef
702
716
  }
703
717
  }
704
718
  `;
@@ -747,6 +761,8 @@ var SearchSymbolsDocument = gql`
747
761
  hint
748
762
  }
749
763
  warning
764
+ indexingStatus
765
+ indexingRef
750
766
  }
751
767
  }
752
768
  `;
@@ -786,6 +802,8 @@ var ListSymbolsDocument = gql`
786
802
  path
787
803
  language
788
804
  }
805
+ indexingStatus
806
+ indexingRef
789
807
  }
790
808
  }
791
809
  `;
@@ -825,6 +843,8 @@ var SymbolDependenciesDocument = gql`
825
843
  missingPackages
826
844
  total
827
845
  hasMore
846
+ indexingStatus
847
+ indexingRef
828
848
  }
829
849
  }
830
850
  `;
@@ -854,6 +874,8 @@ var SymbolDependentsDocument = gql`
854
874
  }
855
875
  total
856
876
  hasMore
877
+ indexingStatus
878
+ indexingRef
857
879
  }
858
880
  }
859
881
  `;
@@ -888,6 +910,8 @@ var PackageImportsDocument = gql`
888
910
  }
889
911
  uniqueDependencies
890
912
  unresolvedCount
913
+ indexingStatus
914
+ indexingRef
891
915
  }
892
916
  }
893
917
  `;
@@ -921,6 +945,8 @@ var CallPathDocument = gql`
921
945
  callLine
922
946
  }
923
947
  }
948
+ indexingStatus
949
+ indexingRef
924
950
  }
925
951
  }
926
952
  `;
@@ -981,6 +1007,8 @@ var ListRepoFilesDocument = gql`
981
1007
  indexedAt
982
1008
  hint
983
1009
  }
1010
+ indexingStatus
1011
+ indexingRef
984
1012
  }
985
1013
  }
986
1014
  `;
@@ -1017,6 +1045,8 @@ var GrepRepoFileDocument = gql`
1017
1045
  indexedAt
1018
1046
  hint
1019
1047
  }
1048
+ indexingStatus
1049
+ indexingRef
1020
1050
  }
1021
1051
  }
1022
1052
  `;
@@ -1074,6 +1104,8 @@ var VersionDiffDocument = gql`
1074
1104
  }
1075
1105
  }
1076
1106
  hasMore
1107
+ indexingStatus
1108
+ indexingRef
1077
1109
  }
1078
1110
  }
1079
1111
  `;
@@ -1092,6 +1124,7 @@ var SearchResultsDocumentString = print(SearchResultsDocument);
1092
1124
  var FetchCodeContextDocumentString = print(FetchCodeContextDocument);
1093
1125
  var CliDocsGetDocumentString = print(CliDocsGetDocument);
1094
1126
  var TriggerIndexingDocumentString = print(TriggerIndexingDocument);
1127
+ var IndexingProgressDocumentString = print(IndexingProgressDocument);
1095
1128
  var CreateProjectDocumentString = print(CreateProjectDocument);
1096
1129
  var PackageSummaryDocumentString = print(PackageSummaryDocument);
1097
1130
  var PackageVulnerabilitiesDocumentString = print(PackageVulnerabilitiesDocument);
@@ -1157,6 +1190,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
1157
1190
  TriggerIndexing(variables, requestHeaders) {
1158
1191
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(TriggerIndexingDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "TriggerIndexing", "mutation", variables);
1159
1192
  },
1193
+ IndexingProgress(variables, requestHeaders) {
1194
+ return withWrapper((wrappedRequestHeaders) => client.rawRequest(IndexingProgressDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "IndexingProgress", "query", variables);
1195
+ },
1160
1196
  CreateProject(variables, requestHeaders) {
1161
1197
  return withWrapper((wrappedRequestHeaders) => client.rawRequest(CreateProjectDocumentString, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
1162
1198
  },
@@ -1671,6 +1707,7 @@ var TOOL_NAMES = [
1671
1707
  "list_imports",
1672
1708
  "call_path",
1673
1709
  "trigger_indexing",
1710
+ "indexing_status",
1674
1711
  "version_diff"
1675
1712
  ];
1676
1713
  var TOOL_NAME_MIGRATION = {
@@ -2405,6 +2442,10 @@ class PkgseerServiceImpl {
2405
2442
  });
2406
2443
  return { data: result.data, errors: result.errors };
2407
2444
  }
2445
+ async getIndexingProgress(ref) {
2446
+ const result = await this.client.IndexingProgress({ ref });
2447
+ return { data: result.data, errors: result.errors };
2448
+ }
2408
2449
  async triggerIndexing(input) {
2409
2450
  const result = await this.client.TriggerIndexing({ input });
2410
2451
  return { data: result.data, errors: result.errors };
@@ -6804,7 +6845,7 @@ var schemas = {
6804
6845
  packageName: z2.string().max(255).describe("Name of the package"),
6805
6846
  version: z2.string().max(100).optional().describe("Specific version, e.g. '4.18.2' (defaults to latest)"),
6806
6847
  navigationMode: z2.enum(["summary", "detailed"]).optional().describe("Response detail level. summary (default) returns core fields; detailed adds all optional fields."),
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."),
6848
+ waitTimeoutMs: z2.coerce.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (0-60000, default 10000). Set 0 to error immediately if not indexed."),
6808
6849
  symbolReference: z2.object({
6809
6850
  symbol_ref: z2.string().optional().describe("Compound symbol reference (registry:package:version:id) from find_symbol or list_symbols results. Self-contained — no additional fields needed."),
6810
6851
  registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry. For package-scoped lookup (with package_name + symbol_name)."),
@@ -6893,7 +6934,7 @@ function buildCodeTargetVars(resolved) {
6893
6934
  }
6894
6935
  var DEFAULT_WAIT_TIMEOUT_MS2 = 1e4;
6895
6936
  var MCP_HINTS = {
6896
- being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
6937
+ being_indexed: "Hint: target is being indexed. Retry with a longer wait_timeout_ms (e.g., 30000) or use indexing_status to poll progress.",
6897
6938
  timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
6898
6939
  };
6899
6940
  function buildHintedMessage(operation, message) {
@@ -6922,14 +6963,50 @@ function buildHintedMessage(operation, message) {
6922
6963
  return `Failed to ${operation}: ${message}`;
6923
6964
  }
6924
6965
  var MCP_GRAPHQL_HINTS = {
6925
- not_found: "Hint: verify the package name and registry are correct.",
6926
- being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
6966
+ not_found: "Hint: verify the package name, registry, or repository URL are correct.",
6967
+ being_indexed: "Hint: target is being indexed. Retry with a longer wait_timeout_ms (e.g., 30000) or use indexing_status to poll progress.",
6927
6968
  timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
6928
6969
  };
6970
+ function getExtensionCode(errors) {
6971
+ for (const error2 of errors) {
6972
+ const ext = error2.extensions;
6973
+ if (ext?.code && typeof ext.code === "string") {
6974
+ return ext.code;
6975
+ }
6976
+ }
6977
+ return;
6978
+ }
6979
+ function getExtensionIndexingRef(errors) {
6980
+ for (const error2 of errors) {
6981
+ const ext = error2.extensions;
6982
+ const ref = ext?.indexing_ref ?? ext?.indexingRef;
6983
+ if (ref && typeof ref === "string") {
6984
+ return ref;
6985
+ }
6986
+ }
6987
+ return;
6988
+ }
6989
+ var EXTENSION_CODE_HINTS = {
6990
+ PACKAGE_INDEXING: "Hint: target is being indexed. Use indexing_status to poll progress, or retry with a longer wait_timeout_ms.",
6991
+ NOT_FOUND: "Hint: verify the package name, registry, or repository URL are correct."
6992
+ };
6929
6993
  function handleGraphQLErrors(errors) {
6930
6994
  if (errors && errors.length > 0) {
6931
6995
  const combined = errors.map((e) => e.message).filter(Boolean).join(", ");
6932
- const hint = MCP_GRAPHQL_HINTS[classifyError(combined)];
6996
+ const extensionCode = getExtensionCode(errors);
6997
+ const indexingRef = getExtensionIndexingRef(errors);
6998
+ if (extensionCode === "PACKAGE_INDEXING" && indexingRef) {
6999
+ return errorResult(JSON.stringify({
7000
+ error: combined,
7001
+ indexingStatus: "INDEXING",
7002
+ indexingRef,
7003
+ message: "Target is being indexed. Use indexing_status tool with this indexingRef to poll progress, " + "or retry the original query after indexing completes."
7004
+ }));
7005
+ }
7006
+ if (extensionCode === "PACKAGE_INDEXING") {
7007
+ return errorResult(`Error: ${combined}. ` + "Hint: target is being indexed (background refresh). Retry the query in a few seconds.");
7008
+ }
7009
+ const hint = extensionCode ? EXTENSION_CODE_HINTS[extensionCode] : MCP_GRAPHQL_HINTS[classifyError(combined)];
6933
7010
  const suffix = hint ? `. ${hint}` : "";
6934
7011
  return errorResult(`Error: ${combined}${suffix}`);
6935
7012
  }
@@ -7144,19 +7221,67 @@ function createGrepFileTool(pkgseerService) {
7144
7221
  }
7145
7222
  };
7146
7223
  }
7147
- // src/tools/list-files.ts
7224
+ // src/tools/indexing-status.ts
7148
7225
  import { z as z8 } from "zod";
7149
7226
  var argsSchema6 = {
7227
+ ref: z8.string().min(1).describe("Indexing reference from a previous tool result (returned when indexing times out).")
7228
+ };
7229
+ function createIndexingStatusTool(pkgseerService) {
7230
+ return {
7231
+ name: "indexing_status",
7232
+ description: "Check indexing progress for a code navigation target. " + "Use after any code navigation tool returns an indexingRef (when indexing exceeded wait_timeout_ms). " + "Returns status (PENDING, INDEXING, INDEXED, FAILED, NOT_FOUND) with progress details. " + "When status is INDEXED, retry the original query to get results.",
7233
+ schema: argsSchema6,
7234
+ annotations: { readOnlyHint: true },
7235
+ handler: async ({ ref }, _extra) => {
7236
+ return withErrorHandling("check indexing status", async () => {
7237
+ const result = await pkgseerService.getIndexingProgress(ref);
7238
+ const graphqlError = handleGraphQLErrors(result.errors);
7239
+ if (graphqlError)
7240
+ return graphqlError;
7241
+ const progress = result.data?.indexingProgress;
7242
+ if (!progress) {
7243
+ return errorResult("Indexing session not found. The reference may be invalid or the session may have expired.");
7244
+ }
7245
+ const response = {
7246
+ status: progress.status,
7247
+ ref
7248
+ };
7249
+ if (progress.filesIndexed != null) {
7250
+ response.filesIndexed = progress.filesIndexed;
7251
+ }
7252
+ if (progress.chunksCreated != null) {
7253
+ response.chunksCreated = progress.chunksCreated;
7254
+ }
7255
+ if (progress.elapsedMs != null) {
7256
+ response.elapsedMs = progress.elapsedMs;
7257
+ }
7258
+ if (progress.status === "INDEXED") {
7259
+ response.message = "Indexing is complete. Retry your original query to get results.";
7260
+ } else if (progress.status === "INDEXING" || progress.status === "PENDING") {
7261
+ response.message = "Indexing is in progress. Poll again to check status.";
7262
+ } else if (progress.status === "FAILED") {
7263
+ response.message = "Indexing failed.";
7264
+ } else if (progress.status === "NOT_FOUND") {
7265
+ response.message = "Indexing reference not found. The ref may be invalid or the session may have expired.";
7266
+ }
7267
+ return textResult(JSON.stringify(response, null, 2));
7268
+ });
7269
+ }
7270
+ };
7271
+ }
7272
+ // src/tools/list-files.ts
7273
+ import { z as z9 } from "zod";
7274
+ var argsSchema7 = {
7150
7275
  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)"),
7276
+ path_prefix: z9.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
7277
+ limit: z9.coerce.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
7153
7278
  wait_timeout_ms: schemas.waitTimeoutMs
7154
7279
  };
7155
7280
  function createListFilesTool(pkgseerService) {
7156
7281
  return {
7157
7282
  name: "list_files",
7158
7283
  description: "Explore a dependency's file structure — " + "see what source files, configs, and docs exist. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals. " + "In monorepos with package scope, returns only files within this package's subdirectory. " + "Requires code indexing.",
7159
- schema: argsSchema6,
7284
+ schema: argsSchema7,
7160
7285
  annotations: { readOnlyHint: true },
7161
7286
  handler: async (args, _extra) => {
7162
7287
  return withErrorHandling("list files", async () => {
@@ -7185,12 +7310,12 @@ function createListFilesTool(pkgseerService) {
7185
7310
  };
7186
7311
  }
7187
7312
  // src/tools/list-imports.ts
7188
- import { z as z9 } from "zod";
7189
- var argsSchema7 = {
7313
+ import { z as z10 } from "zod";
7314
+ var argsSchema8 = {
7190
7315
  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"),
7316
+ file_path: z10.string().max(1000).optional().describe("Filter to a specific file path"),
7317
+ resolved_only: z10.boolean().optional().describe("Only return imports resolved to a known package"),
7318
+ limit: z10.coerce.number().int().min(1).max(500).optional().describe("Max imports to return"),
7194
7319
  mode: schemas.navigationMode,
7195
7320
  wait_timeout_ms: schemas.waitTimeoutMs
7196
7321
  };
@@ -7198,7 +7323,7 @@ function createListImportsTool(pkgseerService) {
7198
7323
  return {
7199
7324
  name: "list_imports",
7200
7325
  description: "See what a dependency imports — understand its internal dependencies and external package usage. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns parsed import/require/use statements with optional resolution to known packages. " + "Use resolved_only=true to see only imports that map to packages in the PkgSeer registry. " + "Includes: source path, imported names, and de-duplicated dependency list.",
7201
- schema: argsSchema7,
7326
+ schema: argsSchema8,
7202
7327
  annotations: { readOnlyHint: true },
7203
7328
  handler: async (args, _extra) => {
7204
7329
  return withErrorHandling("list imports", async () => {
@@ -7225,7 +7350,7 @@ function createListImportsTool(pkgseerService) {
7225
7350
  };
7226
7351
  }
7227
7352
  // src/tools/list-package-docs.ts
7228
- var argsSchema8 = {
7353
+ var argsSchema9 = {
7229
7354
  registry: schemas.registry,
7230
7355
  package_name: schemas.packageName.describe("Name of the package to list documentation for"),
7231
7356
  version: schemas.version
@@ -7234,7 +7359,7 @@ function createListPackageDocsTool(pkgseerService) {
7234
7359
  return {
7235
7360
  name: "list_package_docs",
7236
7361
  description: "Discover available documentation pages for a package. Start here before fetching or searching docs. " + "Returns: page titles, unique IDs (needed for fetch_package_doc), word counts, and update timestamps. " + "Workflow: list_package_docs → fetch_package_doc for full content, or search(mode='docs') to find specific topics. " + "Requires documentation to have been crawled — if results are empty, use trigger_indexing first, then retry.",
7237
- schema: argsSchema8,
7362
+ schema: argsSchema9,
7238
7363
  annotations: { readOnlyHint: true },
7239
7364
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7240
7365
  return withErrorHandling("list package documentation", async () => {
@@ -7251,15 +7376,15 @@ function createListPackageDocsTool(pkgseerService) {
7251
7376
  };
7252
7377
  }
7253
7378
  // src/tools/list-symbols.ts
7254
- import { z as z10 } from "zod";
7255
- var argsSchema9 = {
7379
+ import { z as z11 } from "zod";
7380
+ var argsSchema10 = {
7256
7381
  target: schemas.codeTarget,
7257
- scope: z10.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
7258
- file_path: z10.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
7259
- namespace: z10.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
7260
- public_only: z10.boolean().optional().describe("Only return public symbols"),
7261
- include_popularity: z10.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
7262
- limit: z10.coerce.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
7382
+ scope: z11.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
7383
+ file_path: z11.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
7384
+ namespace: z11.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
7385
+ public_only: z11.boolean().optional().describe("Only return public symbols"),
7386
+ include_popularity: z11.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
7387
+ limit: z11.coerce.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
7263
7388
  mode: schemas.navigationMode,
7264
7389
  wait_timeout_ms: schemas.waitTimeoutMs
7265
7390
  };
@@ -7267,7 +7392,7 @@ function createListSymbolsTool(pkgseerService) {
7267
7392
  return {
7268
7393
  name: "list_symbols",
7269
7394
  description: "Browse a dependency's public API or file-level symbols. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Use scope='exports' for the public API with optional popularity ranking. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbol refs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to read source for any result.",
7270
- schema: argsSchema9,
7395
+ schema: argsSchema10,
7271
7396
  annotations: { readOnlyHint: true },
7272
7397
  handler: async (args, _extra) => {
7273
7398
  return withErrorHandling("list symbols", async () => {
@@ -7308,13 +7433,13 @@ function createListSymbolsTool(pkgseerService) {
7308
7433
  };
7309
7434
  }
7310
7435
  // src/tools/package-dependencies.ts
7311
- import { z as z11 } from "zod";
7312
- var argsSchema10 = {
7436
+ import { z as z12 } from "zod";
7437
+ var argsSchema11 = {
7313
7438
  registry: schemas.registry,
7314
7439
  package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
7315
7440
  version: schemas.version,
7316
- include_transitive: z11.boolean().optional().describe("Whether to include transitive dependency DAG"),
7317
- max_depth: z11.coerce.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
7441
+ include_transitive: z12.boolean().optional().describe("Whether to include transitive dependency DAG"),
7442
+ max_depth: z12.coerce.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
7318
7443
  };
7319
7444
  function decodeDag(rawDag) {
7320
7445
  if (!rawDag || typeof rawDag !== "object")
@@ -7392,7 +7517,7 @@ function createPackageDependenciesTool(pkgseerService) {
7392
7517
  return {
7393
7518
  name: "package_dependencies",
7394
7519
  description: "Analyze package dependencies. By default returns direct dependencies only. " + "Set include_transitive=true to get the full dependency tree (use max_depth to limit large trees). " + "Returns: dependency names, version constraints, and for transitive deps, a graph with depth levels. " + "Use this to understand complexity before adding a package, or to find nested dependencies.",
7395
- schema: argsSchema10,
7520
+ schema: argsSchema11,
7396
7521
  annotations: { readOnlyHint: true },
7397
7522
  handler: async ({ registry, package_name, version: version2, include_transitive, max_depth }, _extra) => {
7398
7523
  return withErrorHandling("fetch package dependencies", async () => {
@@ -7431,7 +7556,7 @@ function createPackageDependenciesTool(pkgseerService) {
7431
7556
  };
7432
7557
  }
7433
7558
  // src/tools/package-quality.ts
7434
- var argsSchema11 = {
7559
+ var argsSchema12 = {
7435
7560
  registry: schemas.registry,
7436
7561
  package_name: schemas.packageName.describe("Name of the package to analyze"),
7437
7562
  version: schemas.version
@@ -7440,7 +7565,7 @@ function createPackageQualityTool(pkgseerService) {
7440
7565
  return {
7441
7566
  name: "package_quality",
7442
7567
  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,
7568
+ schema: argsSchema12,
7444
7569
  annotations: { readOnlyHint: true },
7445
7570
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7446
7571
  return withErrorHandling("fetch package quality", async () => {
@@ -7457,7 +7582,7 @@ function createPackageQualityTool(pkgseerService) {
7457
7582
  };
7458
7583
  }
7459
7584
  // src/tools/package-summary.ts
7460
- var argsSchema12 = {
7585
+ var argsSchema13 = {
7461
7586
  registry: schemas.registry,
7462
7587
  package_name: schemas.packageName.describe("Name of the package to retrieve summary for")
7463
7588
  };
@@ -7465,7 +7590,7 @@ function createPackageSummaryTool(pkgseerService) {
7465
7590
  return {
7466
7591
  name: "package_summary",
7467
7592
  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,
7593
+ schema: argsSchema13,
7469
7594
  annotations: { readOnlyHint: true },
7470
7595
  handler: async ({ registry, package_name }, _extra) => {
7471
7596
  return withErrorHandling("fetch package summary", async () => {
@@ -7482,7 +7607,7 @@ function createPackageSummaryTool(pkgseerService) {
7482
7607
  };
7483
7608
  }
7484
7609
  // src/tools/package-vulnerabilities.ts
7485
- var argsSchema13 = {
7610
+ var argsSchema14 = {
7486
7611
  registry: schemas.registry,
7487
7612
  package_name: schemas.packageName.describe("Name of the package to inspect for vulnerabilities"),
7488
7613
  version: schemas.version
@@ -7491,7 +7616,7 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
7491
7616
  return {
7492
7617
  name: "package_vulnerabilities",
7493
7618
  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,
7619
+ schema: argsSchema14,
7495
7620
  annotations: { readOnlyHint: true },
7496
7621
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7497
7622
  return withErrorHandling("fetch package vulnerabilities", async () => {
@@ -7508,21 +7633,21 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
7508
7633
  };
7509
7634
  }
7510
7635
  // src/tools/read-file.ts
7511
- import { z as z12 } from "zod";
7512
- var argsSchema14 = {
7636
+ import { z as z13 } from "zod";
7637
+ var argsSchema15 = {
7513
7638
  target: schemas.codeTarget,
7514
- file_path: z12.string({
7639
+ file_path: z13.string({
7515
7640
  error: "file_path is required. Get file paths from find_symbol (returns file locations) " + "or list_files (browse file structure)."
7516
7641
  }).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."),
7642
+ start_line: z13.coerce.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
7643
+ end_line: z13.coerce.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file."),
7519
7644
  wait_timeout_ms: schemas.waitTimeoutMs
7520
7645
  };
7521
7646
  function createReadFileTool(pkgseerService) {
7522
7647
  return {
7523
7648
  name: "read_file",
7524
7649
  description: "Read source code from a dependency's repository by file path and line range — " + "use when you have a file path from a stack trace or symbol lookup. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns full file or a specific line range. " + "Prefer find_symbol(include_code=true) for function/class lookup. " + "Use list_files to discover file paths. " + "With repo scope, operates on the full repository. " + "With package scope, scoped to the package subdirectory in monorepos.",
7525
- schema: argsSchema14,
7650
+ schema: argsSchema15,
7526
7651
  annotations: { readOnlyHint: true },
7527
7652
  handler: async (args, _extra) => {
7528
7653
  return withErrorHandling("read file", async () => {
@@ -7550,22 +7675,24 @@ function createReadFileTool(pkgseerService) {
7550
7675
  };
7551
7676
  }
7552
7677
  // src/tools/search.ts
7553
- import { z as z13 } from "zod";
7554
- var packageInputSchema2 = z13.object({
7555
- registry: schemas.registry,
7556
- name: z13.string().min(1).describe("Package name"),
7557
- version: z13.string().optional().describe("Specific version (defaults to latest)")
7558
- });
7559
- var argsSchema15 = {
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({
7678
+ import { z as z14 } from "zod";
7679
+ var targetInputSchema = z14.object({
7680
+ registry: z14.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (npm, pypi, hex, etc.). Required for package scope."),
7681
+ package_name: z14.string().min(1).optional().describe("Package name. Required for package scope."),
7682
+ version: z14.string().optional().describe("Specific version (defaults to latest). Package scope only."),
7683
+ repo_url: z14.string().optional().describe("Repository URL (GitHub). Required for repo scope. Example: https://github.com/expressjs/express"),
7684
+ git_ref: z14.string().optional().describe("Git ref — tag, branch, or commit. Required for repo scope. Use HEAD for latest.")
7685
+ }).describe("Search target: provide registry + package_name (package scope) OR repo_url + git_ref (repo scope).");
7686
+ var argsSchema16 = {
7687
+ targets: z14.array(targetInputSchema, {
7688
+ error: 'targets is required. Provide 1-20 targets as [{registry: "npm", package_name: "express"}] ' + 'or [{repo_url: "https://github.com/user/repo", git_ref: "HEAD"}]. ' + "Use package_summary to verify a package exists. " + "For project-wide doc search without specifying targets, use search_project_docs instead."
7689
+ }).min(1).max(20).describe("Targets to search (1-20). Each uses registry + package_name (package scope) or repo_url + git_ref (repo scope)."),
7690
+ query: z14.string({
7564
7691
  error: "query is required. Provide search terms as natural language or keywords, " + "e.g., 'error handling middleware'."
7565
7692
  }).min(1).describe("Search query - natural language or keywords"),
7566
- mode: z13.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
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)")
7693
+ mode: z14.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
7694
+ limit: z14.coerce.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
7695
+ wait_timeout_ms: schemas.waitTimeoutMs
7569
7696
  };
7570
7697
  function toSearchMode2(mode) {
7571
7698
  if (!mode)
@@ -7577,6 +7704,47 @@ function toSearchMode2(mode) {
7577
7704
  };
7578
7705
  return map[mode.toLowerCase()];
7579
7706
  }
7707
+ function validateAndConvertTargets(targets) {
7708
+ const inputs = [];
7709
+ for (let i = 0;i < targets.length; i++) {
7710
+ const t = targets[i];
7711
+ const hasPackage = t.registry || t.package_name;
7712
+ const hasRepo = t.repo_url || t.git_ref;
7713
+ if (hasPackage && hasRepo) {
7714
+ return {
7715
+ error: `Target ${i + 1}: provide either registry + package_name or repo_url + git_ref, not both.`
7716
+ };
7717
+ }
7718
+ if (!hasPackage && !hasRepo) {
7719
+ return {
7720
+ error: `Target ${i + 1}: provide registry + package_name (package scope) or repo_url + git_ref (repo scope).`
7721
+ };
7722
+ }
7723
+ if (hasPackage) {
7724
+ if (!t.registry || !t.package_name) {
7725
+ return {
7726
+ error: `Target ${i + 1}: both registry and package_name are required for package scope.`
7727
+ };
7728
+ }
7729
+ inputs.push({
7730
+ registry: toGraphQLRegistry(t.registry),
7731
+ name: t.package_name,
7732
+ version: t.version
7733
+ });
7734
+ } else {
7735
+ if (!t.repo_url || !t.git_ref) {
7736
+ return {
7737
+ error: `Target ${i + 1}: both repo_url and git_ref are required for repo scope.`
7738
+ };
7739
+ }
7740
+ inputs.push({
7741
+ repoUrl: t.repo_url,
7742
+ gitRef: t.git_ref
7743
+ });
7744
+ }
7745
+ }
7746
+ return { inputs };
7747
+ }
7580
7748
  function formatIndexingWarnings2(indexingStatus) {
7581
7749
  if (!indexingStatus || indexingStatus.length === 0)
7582
7750
  return null;
@@ -7595,7 +7763,7 @@ function formatIndexingWarnings2(indexingStatus) {
7595
7763
  if (warnings.length === 0)
7596
7764
  return null;
7597
7765
  return `
7598
- Note: Some packages are not fully indexed:
7766
+ Note: Some targets are not fully indexed:
7599
7767
  ` + warnings.join(`
7600
7768
  `) + `
7601
7769
  Results may be incomplete. Retry later for more complete results.`;
@@ -7603,38 +7771,37 @@ Results may be incomplete. Retry later for more complete results.`;
7603
7771
  function createSearchTool(pkgseerService) {
7604
7772
  return {
7605
7773
  name: "search",
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.",
7607
- schema: argsSchema15,
7774
+ description: "Search code and documentation across packages or repositories using full-text search. " + "Returns code chunks and doc pages matching your query with relevance scores and snippets. " + "Each target can use package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Use mode='code' for code only, mode='docs' for docs only, or mode='all' (default). " + "Provide 1-20 targets. For symbol-level results that feed into symbol_callers/symbol_callees, " + "use search_symbols instead. " + "For full source of code results, use find_symbol(name=<title>, include_code=true). " + "Code results include repoUrl and filePath for use with fetch_code_context. " + "If targets need indexing, waits up to wait_timeout_ms (default 10s) or returns searchRef — use search_status to poll.",
7775
+ schema: argsSchema16,
7608
7776
  annotations: { readOnlyHint: true },
7609
- handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
7610
- return withErrorHandling("search packages", async () => {
7777
+ handler: async ({ targets, query, mode, limit, wait_timeout_ms }, _extra) => {
7778
+ return withErrorHandling("search", async () => {
7611
7779
  const normalizedQuery = query.trim();
7612
7780
  if (normalizedQuery.length === 0) {
7613
7781
  return errorResult("Search query is required.");
7614
7782
  }
7615
- const graphqlPackages = packages.map((pkg) => ({
7616
- registry: toGraphQLRegistry(pkg.registry),
7617
- name: pkg.name,
7618
- version: pkg.version
7619
- }));
7620
- const result = await pkgseerService.combinedSearch(graphqlPackages, normalizedQuery, {
7783
+ const validated = validateAndConvertTargets(targets);
7784
+ if ("error" in validated) {
7785
+ return errorResult(validated.error);
7786
+ }
7787
+ const result = await pkgseerService.combinedSearch(validated.inputs, normalizedQuery, {
7621
7788
  mode: toSearchMode2(mode),
7622
7789
  limit,
7623
- waitTimeoutMs: waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS2
7790
+ waitTimeoutMs: wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7624
7791
  });
7625
7792
  const graphqlError = handleGraphQLErrors(result.errors);
7626
7793
  if (graphqlError)
7627
7794
  return graphqlError;
7628
7795
  const asyncResult = result.data?.combinedSearch;
7629
7796
  if (!asyncResult) {
7630
- return errorResult("No search results returned. Check package names and registries.");
7797
+ return errorResult("No search results returned. Check target names and registries.");
7631
7798
  }
7632
7799
  if (!asyncResult.completed) {
7633
7800
  const progressInfo = {
7634
7801
  completed: false,
7635
7802
  searchRef: asyncResult.searchRef,
7636
7803
  progress: asyncResult.progress,
7637
- message: "Search is still indexing. Retry with same query for results, " + "or increase waitTimeoutMs to wait longer."
7804
+ message: "Search is still indexing. Use search_status with the searchRef to poll, " + "or retry with a longer wait_timeout_ms."
7638
7805
  };
7639
7806
  return textResult(JSON.stringify(progressInfo, null, 2));
7640
7807
  }
@@ -7644,7 +7811,7 @@ function createSearchTool(pkgseerService) {
7644
7811
  }
7645
7812
  const entries = searchResult.entries ?? [];
7646
7813
  if (entries.length === 0) {
7647
- return errorResult(`No results found for "${normalizedQuery}". ` + "Try broader terms or different packages.");
7814
+ return errorResult(`No results found for "${normalizedQuery}". ` + "Try broader terms or different targets.");
7648
7815
  }
7649
7816
  let response = JSON.stringify(searchResult, null, 2);
7650
7817
  const indexingWarning = formatIndexingWarnings2(searchResult.indexingStatus);
@@ -7657,21 +7824,21 @@ function createSearchTool(pkgseerService) {
7657
7824
  };
7658
7825
  }
7659
7826
  // src/tools/search-project-docs.ts
7660
- import { z as z14 } from "zod";
7661
- var argsSchema16 = {
7662
- project_directory: z14.string().optional().describe("Directory to search for pkgseer.yml configuration. " + "Use this to specify which project's context to use when the MCP server " + "is installed at user level. Defaults to MCP server's working directory."),
7663
- project: z14.string().optional().describe("Project name to search. Overrides value from pkgseer.yml if provided."),
7664
- terms: z14.array(z14.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
7665
- match_mode: z14.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
7666
- include_snippets: z14.boolean().optional().describe("Include content excerpts around matches"),
7667
- limit: z14.coerce.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
7827
+ import { z as z15 } from "zod";
7828
+ var argsSchema17 = {
7829
+ project_directory: z15.string().optional().describe("Directory to search for pkgseer.yml configuration. " + "Use this to specify which project's context to use when the MCP server " + "is installed at user level. Defaults to MCP server's working directory."),
7830
+ project: z15.string().optional().describe("Project name to search. Overrides value from pkgseer.yml if provided."),
7831
+ terms: z15.array(z15.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
7832
+ match_mode: z15.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
7833
+ include_snippets: z15.boolean().optional().describe("Include content excerpts around matches"),
7834
+ limit: z15.coerce.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
7668
7835
  };
7669
7836
  function createSearchProjectDocsTool(deps) {
7670
7837
  const { pkgseerService, configService, defaultProjectDir } = deps;
7671
7838
  return {
7672
7839
  name: "search_project_docs",
7673
7840
  description: "Search documentation across all dependencies in a PkgSeer project — " + "use when you need to find information but don't know which dependency has it. " + "Requires a pkgseer.yml project config (or pass project name directly). " + "Returns ranked results with snippets from multiple packages. " + "Use project_directory to specify which project's context to use. " + "For single-package doc search, use search(mode='docs') instead.",
7674
- schema: argsSchema16,
7841
+ schema: argsSchema17,
7675
7842
  annotations: { readOnlyHint: true },
7676
7843
  handler: async ({
7677
7844
  project_directory,
@@ -7720,15 +7887,15 @@ function createSearchProjectDocsTool(deps) {
7720
7887
  };
7721
7888
  }
7722
7889
  // src/tools/search-status.ts
7723
- import { z as z15 } from "zod";
7724
- var argsSchema17 = {
7725
- searchRef: z15.string().min(1).describe("Search reference from a previous incomplete search")
7890
+ import { z as z16 } from "zod";
7891
+ var argsSchema18 = {
7892
+ searchRef: z16.string().min(1).describe("Search reference from a previous incomplete search")
7726
7893
  };
7727
7894
  function createSearchStatusTool(pkgseerService) {
7728
7895
  return {
7729
7896
  name: "search_status",
7730
7897
  description: "Check the status of an async search and get results if complete. " + "Use after search returns completed=false with a searchRef. Sessions expire after 1 hour. " + "Returns status (PENDING, INDEXING, SEARCHING, COMPLETED, TIMEOUT, FAILED), " + "progress info (packagesReady/packagesTotal), and results when COMPLETED.",
7731
- schema: argsSchema17,
7898
+ schema: argsSchema18,
7732
7899
  annotations: { readOnlyHint: true },
7733
7900
  handler: async ({ searchRef }, _extra) => {
7734
7901
  return withErrorHandling("check search status", async () => {
@@ -7770,13 +7937,13 @@ function createSearchStatusTool(pkgseerService) {
7770
7937
  };
7771
7938
  }
7772
7939
  // src/tools/search-symbols.ts
7773
- import { z as z16 } from "zod";
7774
- var argsSchema18 = {
7940
+ import { z as z17 } from "zod";
7941
+ var argsSchema19 = {
7775
7942
  target: schemas.codeTarget,
7776
- query: z16.string().max(500).optional().describe("Search query for full-text code search (max 500 chars). Required if keywords not provided."),
7777
- keywords: z16.array(z16.string()).max(20).optional().describe("Search keywords (max 20). Combined using match_mode. Alternative to query."),
7778
- match_mode: z16.enum(["or", "and"]).optional().describe("How to combine keywords: or (any match) or and (all must match)"),
7779
- kind: z16.enum([
7943
+ query: z17.string().max(500).optional().describe("Search query for full-text code search (max 500 chars). Required if keywords not provided."),
7944
+ keywords: z17.array(z17.string()).max(20).optional().describe("Search keywords (max 20). Combined using match_mode. Alternative to query."),
7945
+ match_mode: z17.enum(["or", "and"]).optional().describe("How to combine keywords: or (any match) or and (all must match)"),
7946
+ kind: z17.enum([
7780
7947
  "function",
7781
7948
  "method",
7782
7949
  "class",
@@ -7785,8 +7952,8 @@ var argsSchema18 = {
7785
7952
  "type",
7786
7953
  "doc_section"
7787
7954
  ]).optional().describe("Filter results by code chunk type"),
7788
- file_path: z16.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
7789
- limit: z16.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
7955
+ file_path: z17.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
7956
+ limit: z17.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
7790
7957
  mode: schemas.navigationMode,
7791
7958
  wait_timeout_ms: schemas.waitTimeoutMs
7792
7959
  };
@@ -7794,7 +7961,7 @@ function createSearchSymbolsTool(pkgseerService) {
7794
7961
  return {
7795
7962
  name: "search_symbols",
7796
7963
  description: "Search a dependency's source code by text using the code navigation index — " + "find where error messages, exceptions, or patterns appear across functions, classes, and modules. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns symbol-level results that can feed directly into symbol_callers, symbol_callees, or call_path. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source. " + "For free-form text search across multiple packages, use search(mode='code') instead.",
7797
- schema: argsSchema18,
7964
+ schema: argsSchema19,
7798
7965
  annotations: { readOnlyHint: true },
7799
7966
  handler: async (args, _extra) => {
7800
7967
  return withErrorHandling("search symbols", async () => {
@@ -7835,13 +8002,13 @@ function createSearchSymbolsTool(pkgseerService) {
7835
8002
  };
7836
8003
  }
7837
8004
  // src/tools/symbol-callees.ts
7838
- import { z as z17 } from "zod";
7839
- var argsSchema19 = {
8005
+ import { z as z18 } from "zod";
8006
+ var argsSchema20 = {
7840
8007
  symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
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."),
7844
- include_builtins: z17.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
8008
+ max_depth: z18.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
8009
+ limit: z18.coerce.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
8010
+ include_external: z18.boolean().optional().describe("Include calls to symbols in other indexed packages. " + "Default (false) shows only calls within the same package."),
8011
+ include_builtins: z18.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
7845
8012
  mode: schemas.navigationMode,
7846
8013
  wait_timeout_ms: schemas.waitTimeoutMs
7847
8014
  };
@@ -7849,7 +8016,7 @@ function createSymbolCalleesTool(pkgseerService) {
7849
8016
  return {
7850
8017
  name: "symbol_callees",
7851
8018
  description: "Trace what a function calls internally — " + "understand dependency behavior by following its execution path. " + "Returns direct callees at max_depth=1, or transitive call chains at higher depths. " + "Includes callee names, qualified paths, file locations, call lines, and external package references. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callers for the reverse.",
7852
- schema: argsSchema19,
8019
+ schema: argsSchema20,
7853
8020
  annotations: { readOnlyHint: true },
7854
8021
  handler: async (args, _extra) => {
7855
8022
  return withErrorHandling("find symbol callees", async () => {
@@ -7874,12 +8041,12 @@ function createSymbolCalleesTool(pkgseerService) {
7874
8041
  };
7875
8042
  }
7876
8043
  // src/tools/symbol-callers.ts
7877
- import { z as z18 } from "zod";
7878
- var argsSchema20 = {
8044
+ import { z as z19 } from "zod";
8045
+ var argsSchema21 = {
7879
8046
  symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
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"),
8047
+ same_package_only: z19.boolean().optional().describe("Only return callers from the same package. " + "Default (false) includes callers from other indexed packages."),
8048
+ max_depth: z19.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
8049
+ limit: z19.coerce.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
7883
8050
  mode: schemas.navigationMode,
7884
8051
  wait_timeout_ms: schemas.waitTimeoutMs
7885
8052
  };
@@ -7887,7 +8054,7 @@ function createSymbolCallersTool(pkgseerService) {
7887
8054
  return {
7888
8055
  name: "symbol_callers",
7889
8056
  description: "Trace what calls a function in a dependency's source code — " + "find entry points or debug why behavior triggers. " + "Returns callers with file locations and call line numbers. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Use same_package_only for within-package callers only. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callees for the reverse. " + "Use find_symbol(include_code=true) on any caller to read its source.",
7890
- schema: argsSchema20,
8057
+ schema: argsSchema21,
7891
8058
  annotations: { readOnlyHint: true },
7892
8059
  handler: async (args, _extra) => {
7893
8060
  return withErrorHandling("find symbol callers", async () => {
@@ -7911,26 +8078,26 @@ function createSymbolCallersTool(pkgseerService) {
7911
8078
  };
7912
8079
  }
7913
8080
  // src/tools/trigger-indexing.ts
7914
- import { z as z19 } from "zod";
7915
- var packageInputSchema3 = z19.object({
8081
+ import { z as z20 } from "zod";
8082
+ var packageInputSchema2 = z20.object({
7916
8083
  registry: schemas.registry,
7917
- name: z19.string().max(255).describe("Package name"),
7918
- version: z19.string().max(100).optional().describe("Specific version to index")
8084
+ name: z20.string().max(255).describe("Package name"),
8085
+ version: z20.string().max(100).optional().describe("Specific version to index")
7919
8086
  });
7920
- var repositoryInputSchema = z19.object({
7921
- url: z19.string().max(2000).describe("GitHub repository URL"),
7922
- ref: z19.string().max(200).optional().describe("Git ref to index (tag, branch, commit). Defaults to HEAD"),
7923
- discover_packages: z19.boolean().optional().describe("If true, discover packages published from this repo and trigger their metadata fetch")
8087
+ var repositoryInputSchema = z20.object({
8088
+ url: z20.string().max(2000).describe("GitHub repository URL"),
8089
+ ref: z20.string().max(200).optional().describe("Git ref to index (tag, branch, commit). Defaults to HEAD"),
8090
+ discover_packages: z20.boolean().optional().describe("If true, discover packages published from this repo and trigger their metadata fetch")
7924
8091
  });
7925
- var argsSchema21 = {
7926
- packages: z19.array(packageInputSchema3).max(100).optional().describe("Package versions to index (max 100)"),
7927
- repositories: z19.array(repositoryInputSchema).max(50).optional().describe("Repository URLs to index (max 50)")
8092
+ var argsSchema22 = {
8093
+ packages: z20.array(packageInputSchema2).max(100).optional().describe("Package versions to index (max 100)"),
8094
+ repositories: z20.array(repositoryInputSchema).max(50).optional().describe("Repository URLs to index (max 50)")
7928
8095
  };
7929
8096
  function createTriggerIndexingTool(pkgseerService) {
7930
8097
  return {
7931
8098
  name: "trigger_indexing",
7932
8099
  description: "Pre-warm PkgSeer indexes by triggering indexing for packages and/or repositories. " + "Fire-and-forget: triggers jobs and returns immediately with accepted/skipped counts. " + "Use before search or doc requests to ensure packages are indexed. " + "Code tools auto-wait via wait_timeout_ms on subsequent calls. Most packages index within 10-30s. " + "Rate limited to 10 requests per minute.",
7933
- schema: argsSchema21,
8100
+ schema: argsSchema22,
7934
8101
  annotations: { readOnlyHint: false, idempotentHint: true },
7935
8102
  handler: async (args, _extra) => {
7936
8103
  return withErrorHandling("trigger indexing", async () => {
@@ -7968,13 +8135,13 @@ function createTriggerIndexingTool(pkgseerService) {
7968
8135
  };
7969
8136
  }
7970
8137
  // src/tools/version-diff.ts
7971
- import { z as z20 } from "zod";
7972
- var argsSchema22 = {
8138
+ import { z as z21 } from "zod";
8139
+ var argsSchema23 = {
7973
8140
  target: schemas.codeTarget,
7974
- from_version: z20.string().max(100).describe("Source version (git ref, e.g., 'v4.18.2')"),
7975
- to_version: z20.string().max(100).describe("Target version (git ref, e.g., 'v5.0.0')"),
7976
- include_private: z20.boolean().optional().describe("Include private/non-exported symbols in the diff"),
7977
- kind: z20.enum([
8141
+ from_version: z21.string().max(100).describe("Source version (git ref, e.g., 'v4.18.2')"),
8142
+ to_version: z21.string().max(100).describe("Target version (git ref, e.g., 'v5.0.0')"),
8143
+ include_private: z21.boolean().optional().describe("Include private/non-exported symbols in the diff"),
8144
+ kind: z21.enum([
7978
8145
  "function",
7979
8146
  "method",
7980
8147
  "class",
@@ -7983,14 +8150,14 @@ var argsSchema22 = {
7983
8150
  "type",
7984
8151
  "doc_section"
7985
8152
  ]).optional().describe("Filter by symbol kind"),
7986
- limit: z20.coerce.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
8153
+ limit: z21.coerce.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
7987
8154
  wait_timeout_ms: schemas.waitTimeoutMs
7988
8155
  };
7989
8156
  function createVersionDiffTool(pkgseerService) {
7990
8157
  return {
7991
8158
  name: "version_diff",
7992
8159
  description: "Compare two versions of a dependency to understand what changed — " + "use when debugging issues after upgrades or planning migrations. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "With repo scope, from_version and to_version are literal git refs (tags, branches, commits) — " + "the backend does not normalize them. Use target.git_ref=HEAD to identify the repository. " + "Detects added, removed, moved, and modified symbols with severity " + "(breaking, behavior_change, non_breaking, internal). " + "Returns summary counts and per-symbol changes with file locations.",
7993
- schema: argsSchema22,
8160
+ schema: argsSchema23,
7994
8161
  annotations: { readOnlyHint: true },
7995
8162
  handler: async (args, _extra) => {
7996
8163
  return withErrorHandling("version diff", async () => {
@@ -8049,7 +8216,7 @@ Data availability — tools are grouped by what backend data they need:
8049
8216
  3. Code navigation (requires code repo indexing, dual addressing via target):
8050
8217
  find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path,
8051
8218
  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.
8219
+ These wait up to wait_timeout_ms (default 10s) for indexing. If indexing takes longer, the response includes an indexingRefuse indexing_status to poll progress, then retry the original query when status is INDEXED.
8053
8220
 
8054
8221
  Symbol reference tools (symbol_callers, symbol_callees, call_path) accept a symbol object with either:
8055
8222
  - symbol_ref from a previous find_symbol/search_symbols result (preferred, fastest)
@@ -8062,7 +8229,7 @@ Choosing a code search tool:
8062
8229
  - search(mode='code'): multi-package, full-text → code chunks with snippets
8063
8230
  - grep_file: single file, pattern match → when you know the file path
8064
8231
 
8065
- Utility: trigger_indexing (pre-warm indexes), search_status (poll async search).
8232
+ Utility: trigger_indexing (pre-warm indexes), search_status (poll async search), indexing_status (poll navigation indexing).
8066
8233
 
8067
8234
  Quick start: find_symbol(target={registry:"npm", package_name:"<pkg>"}, name="<function>", include_code=true) often answers the question in one call.
8068
8235
 
@@ -8071,7 +8238,7 @@ Common workflows (pass symbolRef between tools for chaining):
8071
8238
  - Trace calls: find_symbol → symbol_callees(symbol={symbol_ref: <symbolRef>})
8072
8239
  - Find callers: find_symbol → symbol_callers(symbol={symbol_ref: <symbolRef>})
8073
8240
  - 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)
8241
+ - Search code: search_symbols (single pkg, feeds callers/callees) or search(mode='code', targets=[...]) (multi-target)
8075
8242
  - Browse docs: list_package_docs → fetch_package_doc(page_id)`;
8076
8243
  var TOOL_FACTORIES = {
8077
8244
  package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
@@ -8097,6 +8264,7 @@ var TOOL_FACTORIES = {
8097
8264
  list_imports: ({ pkgseerService }) => createListImportsTool(pkgseerService),
8098
8265
  call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
8099
8266
  trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService),
8267
+ indexing_status: ({ pkgseerService }) => createIndexingStatusTool(pkgseerService),
8100
8268
  list_files: ({ pkgseerService }) => createListFilesTool(pkgseerService),
8101
8269
  grep_file: ({ pkgseerService }) => createGrepFileTool(pkgseerService),
8102
8270
  version_diff: ({ pkgseerService }) => createVersionDiffTool(pkgseerService)
@@ -8120,6 +8288,7 @@ var PUBLIC_READ_TOOLS = [
8120
8288
  "list_imports",
8121
8289
  "call_path",
8122
8290
  "trigger_indexing",
8291
+ "indexing_status",
8123
8292
  "list_files",
8124
8293
  "grep_file",
8125
8294
  "version_diff"
@@ -8188,19 +8357,20 @@ function showMcpSetupInstructions(deps) {
8188
8357
  console.log("Alternative: Use CLI directly (no MCP setup needed)");
8189
8358
  console.log(` ${highlight("pkgseer pkg info <package>", useColors)}`);
8190
8359
  }
8191
- function registerMcpCommand(program) {
8192
- const mcpCommand = program.command("mcp").summary("Show setup instructions or start MCP server").description(`Start the Model Context Protocol (MCP) server using STDIO transport.
8360
+ var MCP_COMMAND_DESCRIPTION = `Start the Model Context Protocol (MCP) server using STDIO transport.
8193
8361
 
8194
8362
  When run interactively (TTY), shows setup instructions.
8195
8363
  When run via stdio (non-TTY), starts the MCP server.
8196
8364
 
8197
- Available tools (22):
8365
+ Available tools (23):
8198
8366
  Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
8199
8367
  Browse files: list_files, grep_file, read_file
8200
8368
  Search: search, search_project_docs
8201
8369
  Docs: list_package_docs, fetch_package_doc
8202
8370
  Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
8203
- Utility: trigger_indexing, search_status, list_imports`).action(async () => {
8371
+ Utility: trigger_indexing, indexing_status, search_status, list_imports`;
8372
+ function registerMcpCommand(program) {
8373
+ const mcpCommand = program.command("mcp").summary("Show setup instructions or start MCP server").description(MCP_COMMAND_DESCRIPTION).action(async () => {
8204
8374
  const deps = await createContainer();
8205
8375
  if (process.stdout.isTTY && process.stdin.isTTY) {
8206
8376
  showMcpSetupInstructions(deps);
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./shared/chunk-kh5enjt9.js";
3
+ } from "./shared/chunk-x6hqsn93.js";
4
4
  export {
5
5
  version
6
6
  };
@@ -1,4 +1,4 @@
1
1
  // package.json
2
- var version = "0.5.0";
2
+ var version = "0.5.1";
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.5.0",
4
+ "version": "0.5.1",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",