depwire-cli 0.3.0 → 0.3.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.
@@ -2044,6 +2044,43 @@ function buildGraph(parsedFiles) {
2044
2044
  }
2045
2045
 
2046
2046
  // src/graph/queries.ts
2047
+ function findSymbols(graph, query) {
2048
+ if (query.includes("::")) {
2049
+ if (graph.hasNode(query)) {
2050
+ const attrs = graph.getNodeAttributes(query);
2051
+ return [{
2052
+ id: query,
2053
+ name: attrs.name,
2054
+ kind: attrs.kind,
2055
+ filePath: attrs.filePath,
2056
+ startLine: attrs.startLine,
2057
+ endLine: attrs.endLine,
2058
+ exported: attrs.exported,
2059
+ scope: attrs.scope,
2060
+ dependentCount: graph.inDegree(query)
2061
+ }];
2062
+ }
2063
+ }
2064
+ const queryLower = query.toLowerCase();
2065
+ const results = [];
2066
+ graph.forEachNode((nodeId, attrs) => {
2067
+ if (attrs.name.toLowerCase() === queryLower) {
2068
+ results.push({
2069
+ id: nodeId,
2070
+ name: attrs.name,
2071
+ kind: attrs.kind,
2072
+ filePath: attrs.filePath,
2073
+ startLine: attrs.startLine,
2074
+ endLine: attrs.endLine,
2075
+ exported: attrs.exported,
2076
+ scope: attrs.scope,
2077
+ dependentCount: graph.inDegree(nodeId)
2078
+ });
2079
+ }
2080
+ });
2081
+ results.sort((a, b) => b.dependentCount - a.dependentCount);
2082
+ return results;
2083
+ }
2047
2084
  function getDependencies(graph, symbolId) {
2048
2085
  if (!graph.hasNode(symbolId)) return [];
2049
2086
  const dependencies = [];
@@ -4520,13 +4557,13 @@ function getToolsList() {
4520
4557
  },
4521
4558
  {
4522
4559
  name: "get_symbol_info",
4523
- description: "Look up detailed information about a symbol (function, class, variable, type, etc.) by name. Returns file location, type, line numbers, and export status.",
4560
+ description: "Look up detailed information about a symbol (function, class, variable, type, etc.) by name. Pass a symbol name (e.g., 'Router') or a fully qualified ID (e.g., 'src/router.ts::Router') for exact matching. If multiple symbols share the same name, returns all matches for disambiguation.",
4524
4561
  inputSchema: {
4525
4562
  type: "object",
4526
4563
  properties: {
4527
4564
  name: {
4528
4565
  type: "string",
4529
- description: "The symbol name to look up (e.g., 'UserService', 'handleAuth')"
4566
+ description: "The symbol name to look up (e.g., 'UserService') or full ID (e.g., 'src/services/UserService.ts::UserService')"
4530
4567
  }
4531
4568
  },
4532
4569
  required: ["name"]
@@ -4534,13 +4571,13 @@ function getToolsList() {
4534
4571
  },
4535
4572
  {
4536
4573
  name: "get_dependencies",
4537
- description: "Get all symbols that a given symbol depends on (what does this symbol use/import/call?).",
4574
+ description: "Get all symbols that a given symbol depends on (what does this symbol use/import/call?). Pass a symbol name (e.g., 'Router') or a fully qualified ID (e.g., 'src/router.ts::Router') for exact matching. If multiple symbols share the same name, returns all matches for disambiguation.",
4538
4575
  inputSchema: {
4539
4576
  type: "object",
4540
4577
  properties: {
4541
4578
  symbol: {
4542
4579
  type: "string",
4543
- description: "Symbol name or ID to analyze"
4580
+ description: "Symbol name (e.g., 'Router') or full ID (e.g., 'src/router.ts::Router')"
4544
4581
  }
4545
4582
  },
4546
4583
  required: ["symbol"]
@@ -4548,13 +4585,13 @@ function getToolsList() {
4548
4585
  },
4549
4586
  {
4550
4587
  name: "get_dependents",
4551
- description: "Get all symbols that depend on a given symbol (what uses this symbol?).",
4588
+ description: "Get all symbols that depend on a given symbol (what uses this symbol?). Pass a symbol name (e.g., 'Router') or a fully qualified ID (e.g., 'src/router.ts::Router') for exact matching. If multiple symbols share the same name, returns all matches for disambiguation.",
4552
4589
  inputSchema: {
4553
4590
  type: "object",
4554
4591
  properties: {
4555
4592
  symbol: {
4556
4593
  type: "string",
4557
- description: "Symbol name or ID to analyze"
4594
+ description: "Symbol name (e.g., 'Router') or full ID (e.g., 'src/router.ts::Router')"
4558
4595
  }
4559
4596
  },
4560
4597
  required: ["symbol"]
@@ -4562,13 +4599,13 @@ function getToolsList() {
4562
4599
  },
4563
4600
  {
4564
4601
  name: "impact_analysis",
4565
- description: "Analyze what would break if a symbol is changed, renamed, or removed. Shows direct dependents, transitive dependents (chain reaction), and all affected files. Use this before making changes to understand the blast radius.",
4602
+ description: "Analyze what would break if a symbol is changed, renamed, or removed. Shows direct dependents, transitive dependents (chain reaction), and all affected files. Pass a symbol name (e.g., 'Router') or a fully qualified ID (e.g., 'src/router.ts::Router') for exact matching. If multiple symbols share the same name, returns all matches for disambiguation. Use this before making changes to understand the blast radius.",
4566
4603
  inputSchema: {
4567
4604
  type: "object",
4568
4605
  properties: {
4569
4606
  symbol: {
4570
4607
  type: "string",
4571
- description: "The symbol name or ID to analyze"
4608
+ description: "Symbol name (e.g., 'Router') or full ID (e.g., 'src/router.ts::Router')"
4572
4609
  }
4573
4610
  },
4574
4611
  required: ["symbol"]
@@ -4790,12 +4827,39 @@ async function handleToolCall(name, args, state) {
4790
4827
  };
4791
4828
  }
4792
4829
  }
4830
+ function createDisambiguationResponse(matches, queryName) {
4831
+ const suggestion = matches.length > 0 ? matches[0].id : "";
4832
+ return {
4833
+ ambiguous: true,
4834
+ message: `Found ${matches.length} symbols named '${queryName}'. Please specify which one by using the full ID (e.g., '${suggestion}').`,
4835
+ matches: matches.map((m, index) => ({
4836
+ id: m.id,
4837
+ kind: m.kind,
4838
+ filePath: m.filePath,
4839
+ line: m.startLine,
4840
+ dependents: m.dependentCount,
4841
+ hint: index === 0 && m.dependentCount > 0 ? "Most dependents \u2014 likely the one you want" : ""
4842
+ })),
4843
+ suggestion
4844
+ };
4845
+ }
4793
4846
  function handleGetSymbolInfo(name, graph) {
4794
- const matches = searchSymbols(graph, name);
4795
- const exactMatches = matches.filter((m) => m.name.toLowerCase() === name.toLowerCase());
4796
- const results = exactMatches.length > 0 ? exactMatches : matches.slice(0, 10);
4847
+ const matches = findSymbols(graph, name);
4848
+ if (matches.length === 0) {
4849
+ const fuzzyMatches = searchSymbols(graph, name).slice(0, 10);
4850
+ return {
4851
+ error: `Symbol '${name}' not found`,
4852
+ suggestion: fuzzyMatches.length > 0 ? `Did you mean: ${fuzzyMatches.map((m) => m.name).join(", ")}?` : "Try using search_symbols to find available symbols",
4853
+ fuzzyMatches: fuzzyMatches.map((m) => ({
4854
+ id: m.id,
4855
+ name: m.name,
4856
+ kind: m.kind,
4857
+ filePath: m.filePath
4858
+ }))
4859
+ };
4860
+ }
4797
4861
  return {
4798
- matches: results.map((m) => ({
4862
+ matches: matches.map((m) => ({
4799
4863
  id: m.id,
4800
4864
  name: m.name,
4801
4865
  kind: m.kind,
@@ -4803,19 +4867,24 @@ function handleGetSymbolInfo(name, graph) {
4803
4867
  startLine: m.startLine,
4804
4868
  endLine: m.endLine,
4805
4869
  exported: m.exported,
4806
- scope: m.scope
4870
+ scope: m.scope,
4871
+ dependents: m.dependentCount
4807
4872
  })),
4808
- count: results.length
4873
+ count: matches.length
4809
4874
  };
4810
4875
  }
4811
4876
  function handleGetDependencies(symbol, graph) {
4812
- const matches = searchSymbols(graph, symbol);
4877
+ const matches = findSymbols(graph, symbol);
4813
4878
  if (matches.length === 0) {
4879
+ const fuzzyMatches = searchSymbols(graph, symbol).slice(0, 10);
4814
4880
  return {
4815
4881
  error: `Symbol '${symbol}' not found`,
4816
- suggestion: "Try using search_symbols to find available symbols"
4882
+ suggestion: fuzzyMatches.length > 0 ? `Did you mean: ${fuzzyMatches.map((m) => m.name).join(", ")}?` : "Try using search_symbols to find available symbols"
4817
4883
  };
4818
4884
  }
4885
+ if (matches.length > 1) {
4886
+ return createDisambiguationResponse(matches, symbol);
4887
+ }
4819
4888
  const target = matches[0];
4820
4889
  const deps = getDependencies(graph, target.id);
4821
4890
  const grouped = {};
@@ -4833,19 +4902,23 @@ function handleGetDependencies(symbol, graph) {
4833
4902
  });
4834
4903
  const totalCount = Object.values(grouped).reduce((sum, arr) => sum + arr.length, 0);
4835
4904
  return {
4836
- symbol: `${target.filePath}::${target.name}`,
4905
+ symbol: target.id,
4837
4906
  dependencies: grouped,
4838
4907
  totalCount
4839
4908
  };
4840
4909
  }
4841
4910
  function handleGetDependents(symbol, graph) {
4842
- const matches = searchSymbols(graph, symbol);
4911
+ const matches = findSymbols(graph, symbol);
4843
4912
  if (matches.length === 0) {
4913
+ const fuzzyMatches = searchSymbols(graph, symbol).slice(0, 10);
4844
4914
  return {
4845
4915
  error: `Symbol '${symbol}' not found`,
4846
- suggestion: "Try using search_symbols to find available symbols"
4916
+ suggestion: fuzzyMatches.length > 0 ? `Did you mean: ${fuzzyMatches.map((m) => m.name).join(", ")}?` : "Try using search_symbols to find available symbols"
4847
4917
  };
4848
4918
  }
4919
+ if (matches.length > 1) {
4920
+ return createDisambiguationResponse(matches, symbol);
4921
+ }
4849
4922
  const target = matches[0];
4850
4923
  const deps = getDependents(graph, target.id);
4851
4924
  const grouped = {};
@@ -4863,19 +4936,23 @@ function handleGetDependents(symbol, graph) {
4863
4936
  });
4864
4937
  const totalCount = Object.values(grouped).reduce((sum, arr) => sum + arr.length, 0);
4865
4938
  return {
4866
- symbol: `${target.filePath}::${target.name}`,
4939
+ symbol: target.id,
4867
4940
  dependents: grouped,
4868
4941
  totalCount
4869
4942
  };
4870
4943
  }
4871
4944
  function handleImpactAnalysis(symbol, graph) {
4872
- const matches = searchSymbols(graph, symbol);
4945
+ const matches = findSymbols(graph, symbol);
4873
4946
  if (matches.length === 0) {
4947
+ const fuzzyMatches = searchSymbols(graph, symbol).slice(0, 10);
4874
4948
  return {
4875
4949
  error: `Symbol '${symbol}' not found`,
4876
- suggestion: "Try using search_symbols to find available symbols"
4950
+ suggestion: fuzzyMatches.length > 0 ? `Did you mean: ${fuzzyMatches.map((m) => m.name).join(", ")}?` : "Try using search_symbols to find available symbols"
4877
4951
  };
4878
4952
  }
4953
+ if (matches.length > 1) {
4954
+ return createDisambiguationResponse(matches, symbol);
4955
+ }
4879
4956
  const target = matches[0];
4880
4957
  const impact = getImpact(graph, target.id);
4881
4958
  const directWithKinds = impact.directDependents.map((dep) => {
@@ -4898,6 +4975,7 @@ function handleImpactAnalysis(symbol, graph) {
4898
4975
  const summary = `Changing ${target.name} would directly affect ${impact.directDependents.length} symbol(s) and transitively affect ${transitiveFormatted.length} more, across ${impact.affectedFiles.length} file(s).`;
4899
4976
  return {
4900
4977
  symbol: {
4978
+ id: target.id,
4901
4979
  name: target.name,
4902
4980
  filePath: target.filePath,
4903
4981
  kind: target.kind
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  startVizServer,
13
13
  updateFileInGraph,
14
14
  watchProject
15
- } from "./chunk-C3LAKUAJ.js";
15
+ } from "./chunk-LOX5NEND.js";
16
16
 
17
17
  // src/index.ts
18
18
  import { Command } from "commander";
@@ -6,7 +6,7 @@ import {
6
6
  startMcpServer,
7
7
  updateFileInGraph,
8
8
  watchProject
9
- } from "./chunk-C3LAKUAJ.js";
9
+ } from "./chunk-LOX5NEND.js";
10
10
 
11
11
  // src/mcpb-entry.ts
12
12
  import { resolve } from "path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "depwire-cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Code cross-reference visualization and AI context engine for TypeScript. Analyzes codebases to show dependencies, enables AI tools with MCP, and renders beautiful arc diagrams.",
5
5
  "type": "module",
6
6
  "bin": {