mcp-vector-search 0.4.14__py3-none-any.whl → 0.5.1__py3-none-any.whl

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.

Potentially problematic release.


This version of mcp-vector-search might be problematic. Click here for more details.

Files changed (30) hide show
  1. mcp_vector_search/__init__.py +2 -2
  2. mcp_vector_search/cli/commands/index.py +73 -31
  3. mcp_vector_search/cli/commands/init.py +189 -113
  4. mcp_vector_search/cli/commands/install.py +525 -113
  5. mcp_vector_search/cli/commands/mcp.py +201 -151
  6. mcp_vector_search/cli/commands/reset.py +41 -41
  7. mcp_vector_search/cli/commands/search.py +73 -14
  8. mcp_vector_search/cli/commands/status.py +51 -17
  9. mcp_vector_search/cli/didyoumean.py +254 -246
  10. mcp_vector_search/cli/main.py +114 -43
  11. mcp_vector_search/cli/output.py +152 -0
  12. mcp_vector_search/cli/suggestions.py +246 -197
  13. mcp_vector_search/core/database.py +81 -49
  14. mcp_vector_search/core/indexer.py +10 -4
  15. mcp_vector_search/core/search.py +17 -6
  16. mcp_vector_search/mcp/__main__.py +1 -1
  17. mcp_vector_search/mcp/server.py +211 -203
  18. mcp_vector_search/parsers/__init__.py +7 -0
  19. mcp_vector_search/parsers/dart.py +605 -0
  20. mcp_vector_search/parsers/html.py +413 -0
  21. mcp_vector_search/parsers/php.py +694 -0
  22. mcp_vector_search/parsers/registry.py +21 -1
  23. mcp_vector_search/parsers/ruby.py +678 -0
  24. mcp_vector_search/parsers/text.py +32 -26
  25. mcp_vector_search/utils/gitignore.py +72 -71
  26. {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.1.dist-info}/METADATA +76 -5
  27. {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.1.dist-info}/RECORD +30 -26
  28. {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.1.dist-info}/WHEEL +0 -0
  29. {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.1.dist-info}/entry_points.txt +0 -0
  30. {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,50 +1,62 @@
1
1
  """Enhanced CLI with 'did you mean' functionality for better user experience."""
2
2
 
3
+ import difflib
4
+
3
5
  import click
4
6
  import typer
5
7
  from click_didyoumean import DYMGroup
6
- from typing import Any, Dict, List, Optional, Tuple
7
- import difflib
8
- from pathlib import Path
9
- import sys
10
8
 
11
9
 
12
10
  class EnhancedDidYouMeanTyper(typer.Typer):
13
11
  """Enhanced Typer class with advanced 'did you mean' functionality."""
14
-
12
+
15
13
  def __init__(self, *args, **kwargs):
16
14
  """Initialize with enhanced did-you-mean support."""
17
15
  # Extract Typer-specific kwargs
18
16
  typer_kwargs = {}
19
17
  click_kwargs = {}
20
-
18
+
21
19
  # Separate Typer and Click kwargs
22
20
  typer_specific = {
23
- 'name', 'help', 'epilog', 'short_help', 'options_metavar',
24
- 'add_completion', 'context_settings', 'callback', 'invoke_without_command',
25
- 'no_args_is_help', 'subcommand_metavar', 'chain', 'result_callback',
26
- 'deprecated', 'rich_markup_mode', 'rich_help_panel', 'pretty_exceptions_enable',
27
- 'pretty_exceptions_show_locals', 'pretty_exceptions_short'
21
+ "name",
22
+ "help",
23
+ "epilog",
24
+ "short_help",
25
+ "options_metavar",
26
+ "add_completion",
27
+ "context_settings",
28
+ "callback",
29
+ "invoke_without_command",
30
+ "no_args_is_help",
31
+ "subcommand_metavar",
32
+ "chain",
33
+ "result_callback",
34
+ "deprecated",
35
+ "rich_markup_mode",
36
+ "rich_help_panel",
37
+ "pretty_exceptions_enable",
38
+ "pretty_exceptions_show_locals",
39
+ "pretty_exceptions_short",
28
40
  }
29
-
41
+
30
42
  for key, value in kwargs.items():
31
43
  if key in typer_specific:
32
44
  typer_kwargs[key] = value
33
45
  else:
34
46
  click_kwargs[key] = value
35
-
47
+
36
48
  # Initialize Typer with its specific kwargs
37
49
  super().__init__(*args, **typer_kwargs)
38
-
50
+
39
51
  # Store click kwargs for later use
40
52
  self._click_kwargs = click_kwargs
41
53
  self.command_aliases = {} # Store command aliases
42
-
54
+
43
55
  def __call__(self, *args, **kwargs):
44
56
  """Override call to use enhanced DYMGroup."""
45
57
  # Get the underlying click group
46
58
  click_group = super().__call__(*args, **kwargs)
47
-
59
+
48
60
  # Create enhanced DYM group with original group's properties
49
61
  enhanced_group = EnhancedDidYouMeanGroup(
50
62
  name=click_group.name,
@@ -62,18 +74,18 @@ class EnhancedDidYouMeanTyper(typer.Typer):
62
74
  chain=click_group.chain,
63
75
  result_callback=click_group.result_callback,
64
76
  deprecated=click_group.deprecated,
65
- **self._click_kwargs
77
+ **self._click_kwargs,
66
78
  )
67
-
79
+
68
80
  # Additional attributes that might be needed
69
- if hasattr(click_group, 'options_metavar'):
81
+ if hasattr(click_group, "options_metavar"):
70
82
  enhanced_group.options_metavar = click_group.options_metavar
71
-
83
+
72
84
  return enhanced_group
73
-
85
+
74
86
  def add_alias(self, command_name: str, alias: str) -> None:
75
87
  """Add an alias for a command.
76
-
88
+
77
89
  Args:
78
90
  command_name: The original command name
79
91
  alias: The alias to add
@@ -83,12 +95,12 @@ class EnhancedDidYouMeanTyper(typer.Typer):
83
95
 
84
96
  class EnhancedDidYouMeanGroup(DYMGroup):
85
97
  """Enhanced Click group with advanced 'did you mean' functionality."""
86
-
98
+
87
99
  def __init__(self, *args, **kwargs):
88
100
  """Initialize with better error messages and fuzzy matching."""
89
101
  super().__init__(*args, **kwargs)
90
102
  self.max_suggestions = 3 # Maximum number of suggestions to show
91
-
103
+
92
104
  def resolve_command(self, ctx: click.Context, args: list) -> tuple:
93
105
  """Resolve command with enhanced error handling and suggestions."""
94
106
  try:
@@ -97,26 +109,26 @@ class EnhancedDidYouMeanGroup(DYMGroup):
97
109
  # Enhanced error handling with better suggestions
98
110
  if "No such command" in str(e) and args:
99
111
  command_name = args[0]
100
-
112
+
101
113
  # Use our enhanced suggestion system
102
114
  add_common_suggestions(ctx, command_name)
103
-
115
+
104
116
  # Re-raise with original message (suggestions already printed)
105
117
  raise click.UsageError(str(e), ctx=ctx)
106
118
  raise
107
-
119
+
108
120
  def get_command(self, ctx: click.Context, cmd_name: str):
109
121
  """Get command with support for aliases and shortcuts."""
110
122
  # First try exact match
111
123
  rv = super().get_command(ctx, cmd_name)
112
124
  if rv is not None:
113
125
  return rv
114
-
126
+
115
127
  # Try common typo mappings
116
128
  suggestion = COMMON_TYPOS.get(cmd_name.lower())
117
- if suggestion and ' ' not in suggestion: # Only single commands, not flags
129
+ if suggestion and " " not in suggestion: # Only single commands, not flags
118
130
  return super().get_command(ctx, suggestion)
119
-
131
+
120
132
  return None
121
133
 
122
134
 
@@ -124,17 +136,17 @@ def create_enhanced_typer(**kwargs) -> typer.Typer:
124
136
  """Create a Typer instance with enhanced 'did you mean' functionality."""
125
137
  # Set default values for better UX
126
138
  defaults = {
127
- 'no_args_is_help': True,
128
- 'add_completion': False,
129
- 'rich_markup_mode': 'rich',
139
+ "no_args_is_help": True,
140
+ "add_completion": False,
141
+ "rich_markup_mode": "rich",
130
142
  }
131
-
143
+
132
144
  # Merge with provided kwargs
133
145
  final_kwargs = {**defaults, **kwargs}
134
-
146
+
135
147
  # Create the enhanced Typer
136
148
  app = EnhancedDidYouMeanTyper(**final_kwargs)
137
-
149
+
138
150
  return app
139
151
 
140
152
 
@@ -142,13 +154,13 @@ def enhance_existing_typer(app: typer.Typer) -> typer.Typer:
142
154
  """Enhance an existing Typer app with advanced 'did you mean' functionality."""
143
155
  # This is a bit tricky since we need to modify the underlying Click group
144
156
  # We'll create a wrapper that intercepts the click group creation
145
-
157
+
146
158
  original_call = app.__call__
147
-
159
+
148
160
  def enhanced_call(*args, **kwargs):
149
161
  """Enhanced call that uses EnhancedDidYouMeanGroup."""
150
162
  click_group = original_call(*args, **kwargs)
151
-
163
+
152
164
  # Create enhanced group
153
165
  enhanced_group = EnhancedDidYouMeanGroup(
154
166
  name=click_group.name,
@@ -168,9 +180,9 @@ def enhance_existing_typer(app: typer.Typer) -> typer.Typer:
168
180
  result_callback=click_group.result_callback,
169
181
  deprecated=click_group.deprecated,
170
182
  )
171
-
183
+
172
184
  return enhanced_group
173
-
185
+
174
186
  app.__call__ = enhanced_call
175
187
  return app
176
188
 
@@ -178,226 +190,204 @@ def enhance_existing_typer(app: typer.Typer) -> typer.Typer:
178
190
  # Enhanced typo mapping with comprehensive variations
179
191
  COMMON_TYPOS = {
180
192
  # Search command variations
181
- 'serach': 'search',
182
- 'seach': 'search',
183
- 'searh': 'search',
184
- 'sarch': 'search',
185
- 'serch': 'search',
186
- 'searhc': 'search',
187
- 'find': 'search',
188
- 'query': 'search',
189
- 'lookup': 'search',
190
- 'grep': 'search',
191
- 's': 'search', # Single letter shortcut
192
- 'f': 'search', # Alternative shortcut for find
193
-
193
+ "serach": "search",
194
+ "seach": "search",
195
+ "searh": "search",
196
+ "sarch": "search",
197
+ "serch": "search",
198
+ "searhc": "search",
199
+ "find": "search",
200
+ "query": "search",
201
+ "lookup": "search",
202
+ "grep": "search",
203
+ "s": "search", # Single letter shortcut
204
+ "f": "search", # Alternative shortcut for find
194
205
  # Index command variations
195
- 'indx': 'index',
196
- 'idx': 'index',
197
- 'indexx': 'index',
198
- 'indez': 'index',
199
- 'inedx': 'index',
200
- 'reindex': 'index --force',
201
- 'rebuild': 'index --force',
202
- 'refresh': 'index --force',
203
- 'scan': 'index',
204
- 'build': 'index',
205
- 'i': 'index', # Single letter shortcut
206
- 'b': 'index', # Alternative shortcut for build
207
-
206
+ "indx": "index",
207
+ "idx": "index",
208
+ "indexx": "index",
209
+ "indez": "index",
210
+ "inedx": "index",
211
+ "reindex": "index --force",
212
+ "rebuild": "index --force",
213
+ "refresh": "index --force",
214
+ "scan": "index",
215
+ "build": "index",
216
+ "i": "index", # Single letter shortcut
217
+ "b": "index", # Alternative shortcut for build
208
218
  # Status command variations
209
- 'stat': 'status',
210
- 'stats': 'status',
211
- 'info': 'status',
212
- 'information': 'status',
213
- 'details': 'status',
214
- 'summary': 'status',
215
- 'overview': 'status',
216
- 'st': 'status', # Common abbreviation
217
- 'status': 'status',
218
-
219
+ "stat": "status",
220
+ "stats": "status",
221
+ "info": "status",
222
+ "information": "status",
223
+ "details": "status",
224
+ "summary": "status",
225
+ "overview": "status",
226
+ "st": "status", # Common abbreviation
227
+ "status": "status",
219
228
  # Config command variations
220
- 'conf': 'config',
221
- 'cfg': 'config',
222
- 'configure': 'config',
223
- 'configuration': 'config',
224
- 'setting': 'config',
225
- 'settings': 'config',
226
- 'preferences': 'config',
227
- 'prefs': 'config',
228
- 'c': 'config', # Single letter shortcut
229
-
229
+ "conf": "config",
230
+ "cfg": "config",
231
+ "configure": "config",
232
+ "configuration": "config",
233
+ "setting": "config",
234
+ "settings": "config",
235
+ "preferences": "config",
236
+ "prefs": "config",
237
+ "c": "config", # Single letter shortcut
230
238
  # Init command variations
231
- 'initialize': 'init',
232
- 'setup': 'init',
233
- 'start': 'init',
234
- 'create': 'init',
235
- 'new': 'init',
236
- 'begin': 'init',
237
- 'initalize': 'init', # Common misspelling
238
- 'initalise': 'init',
239
- 'initialise': 'init',
240
-
239
+ "initialize": "init",
240
+ "setup": "init",
241
+ "start": "init",
242
+ "create": "init",
243
+ "new": "init",
244
+ "begin": "init",
245
+ "initalize": "init", # Common misspelling
246
+ "initalise": "init",
247
+ "initialise": "init",
241
248
  # Watch command variations
242
- 'monitor': 'watch',
243
- 'observe': 'watch',
244
- 'track': 'watch',
245
- 'listen': 'watch',
246
- 'follow': 'watch',
247
- 'w': 'watch', # Single letter shortcut
248
-
249
+ "monitor": "watch",
250
+ "observe": "watch",
251
+ "track": "watch",
252
+ "listen": "watch",
253
+ "follow": "watch",
254
+ "w": "watch", # Single letter shortcut
249
255
  # Auto-index command variations
250
- 'auto': 'auto-index',
251
- 'automatic': 'auto-index',
252
- 'autoindex': 'auto-index',
253
- 'auto_index': 'auto-index',
254
- 'ai': 'auto-index', # Abbreviation
255
-
256
+ "auto": "auto-index",
257
+ "automatic": "auto-index",
258
+ "autoindex": "auto-index",
259
+ "auto_index": "auto-index",
260
+ "ai": "auto-index", # Abbreviation
256
261
  # MCP command variations
257
- 'claude': 'mcp',
258
- 'server': 'mcp',
259
- 'protocol': 'mcp',
260
- 'model-context': 'mcp',
261
- 'context': 'mcp',
262
- 'm': 'mcp', # Single letter shortcut
263
-
262
+ "claude": "mcp",
263
+ "server": "mcp",
264
+ "protocol": "mcp",
265
+ "model-context": "mcp",
266
+ "context": "mcp",
267
+ "m": "mcp", # Single letter shortcut
264
268
  # Install command variations
265
- 'setup': 'install',
266
- 'deploy': 'install',
267
- 'add': 'install',
268
- 'instal': 'install', # Common typo
269
- 'install': 'install',
270
-
269
+ "setup": "install",
270
+ "deploy": "install",
271
+ "add": "install",
272
+ "instal": "install", # Common typo
273
+ "install": "install",
271
274
  # Demo command variations
272
- 'example': 'demo',
273
- 'sample': 'demo',
274
- 'test': 'demo',
275
- 'try': 'demo',
276
- 'd': 'demo', # Single letter shortcut
277
-
275
+ "example": "demo",
276
+ "sample": "demo",
277
+ "test": "demo",
278
+ "try": "demo",
279
+ "d": "demo", # Single letter shortcut
278
280
  # Health/Doctor command variations
279
- 'check': 'doctor',
280
- 'health': 'doctor',
281
- 'diagnose': 'doctor',
282
- 'verify': 'doctor',
283
- 'validate': 'doctor',
284
- 'repair': 'doctor',
285
- 'fix': 'doctor',
286
- 'dr': 'doctor', # Common abbreviation
287
-
281
+ "check": "doctor",
282
+ "health": "doctor",
283
+ "diagnose": "doctor",
284
+ "verify": "doctor",
285
+ "validate": "doctor",
286
+ "repair": "doctor",
287
+ "fix": "doctor",
288
+ "dr": "doctor", # Common abbreviation
288
289
  # Version command variations
289
- 'ver': 'version',
290
- 'v': 'version',
291
- '--version': 'version',
292
- '-v': 'version',
293
-
290
+ "ver": "version",
291
+ "v": "version",
292
+ "--version": "version",
293
+ "-v": "version",
294
294
  # Help command variations
295
- 'help': '--help',
296
- 'h': '--help',
297
- '--help': '--help',
298
- '-h': '--help',
299
- '?': '--help',
300
-
295
+ "help": "--help",
296
+ "h": "--help",
297
+ "--help": "--help",
298
+ "-h": "--help",
299
+ "?": "--help",
301
300
  # History command variations
302
- 'hist': 'history',
303
- 'log': 'history',
304
- 'logs': 'history',
305
- 'recent': 'history',
306
-
301
+ "hist": "history",
302
+ "log": "history",
303
+ "logs": "history",
304
+ "recent": "history",
307
305
  # Reset command variations
308
- 'clear': 'reset',
309
- 'clean': 'reset',
310
- 'purge': 'reset',
311
- 'wipe': 'reset',
312
- 'remove': 'reset',
313
- 'delete': 'reset',
314
-
306
+ "clear": "reset",
307
+ "clean": "reset",
308
+ "purge": "reset",
309
+ "wipe": "reset",
310
+ "remove": "reset",
311
+ "delete": "reset",
315
312
  # Interactive command variations
316
- 'interact': 'interactive',
317
- 'session': 'interactive',
318
- 'repl': 'interactive',
319
- 'console': 'interactive',
320
- 'ui': 'interactive',
313
+ "interact": "interactive",
314
+ "session": "interactive",
315
+ "repl": "interactive",
316
+ "console": "interactive",
317
+ "ui": "interactive",
321
318
  }
322
319
 
323
320
  # Command descriptions and examples for better error messages
324
321
  COMMAND_INFO = {
325
- 'search': {
326
- 'description': 'Search for code patterns semantically',
327
- 'examples': [
322
+ "search": {
323
+ "description": "Search for code patterns semantically",
324
+ "examples": [
328
325
  'mcp-vector-search search "authentication function"',
329
326
  'mcp-vector-search search "error handling" --limit 5',
330
- 'mcp-vector-search find "database connection"'
327
+ 'mcp-vector-search find "database connection"',
331
328
  ],
332
- 'related': ['search-similar', 'search-context', 'find', 'interactive']
329
+ "related": ["search-similar", "search-context", "find", "interactive"],
333
330
  },
334
- 'index': {
335
- 'description': 'Index codebase for semantic search',
336
- 'examples': [
337
- 'mcp-vector-search index',
338
- 'mcp-vector-search index --force',
339
- 'mcp-vector-search index --include "*.py,*.js"'
331
+ "index": {
332
+ "description": "Index codebase for semantic search",
333
+ "examples": [
334
+ "mcp-vector-search index",
335
+ "mcp-vector-search index --force",
336
+ 'mcp-vector-search index --include "*.py,*.js"',
340
337
  ],
341
- 'related': ['auto-index', 'watch', 'reset']
338
+ "related": ["auto-index", "watch", "reset"],
342
339
  },
343
- 'status': {
344
- 'description': 'Show project status and statistics',
345
- 'examples': [
346
- 'mcp-vector-search status',
347
- 'mcp-vector-search status --verbose'
348
- ],
349
- 'related': ['doctor', 'history', 'version']
340
+ "status": {
341
+ "description": "Show project status and statistics",
342
+ "examples": ["mcp-vector-search status", "mcp-vector-search status --verbose"],
343
+ "related": ["doctor", "history", "version"],
350
344
  },
351
- 'config': {
352
- 'description': 'Manage project configuration',
353
- 'examples': [
354
- 'mcp-vector-search config show',
355
- 'mcp-vector-search config set model all-MiniLM-L6-v2'
345
+ "config": {
346
+ "description": "Manage project configuration",
347
+ "examples": [
348
+ "mcp-vector-search config show",
349
+ "mcp-vector-search config set model all-MiniLM-L6-v2",
356
350
  ],
357
- 'related': ['init', 'status']
351
+ "related": ["init", "status"],
358
352
  },
359
- 'init': {
360
- 'description': 'Initialize project for semantic search',
361
- 'examples': [
362
- 'mcp-vector-search init',
363
- 'mcp-vector-search init --model sentence-transformers/all-MiniLM-L6-v2'
353
+ "init": {
354
+ "description": "Initialize project for semantic search",
355
+ "examples": [
356
+ "mcp-vector-search init",
357
+ "mcp-vector-search init --model sentence-transformers/all-MiniLM-L6-v2",
364
358
  ],
365
- 'related': ['config', 'install', 'index']
359
+ "related": ["config", "install", "index"],
366
360
  },
367
- 'mcp': {
368
- 'description': 'Manage Claude Code MCP integration',
369
- 'examples': [
370
- 'mcp-vector-search mcp',
371
- 'mcp-vector-search mcp test'
372
- ],
373
- 'related': ['init-mcp', 'install']
361
+ "mcp": {
362
+ "description": "Manage Claude Code MCP integration",
363
+ "examples": ["mcp-vector-search mcp", "mcp-vector-search mcp test"],
364
+ "related": ["init-mcp", "install"],
374
365
  },
375
- 'doctor': {
376
- 'description': 'Check system dependencies and configuration',
377
- 'examples': [
378
- 'mcp-vector-search doctor',
366
+ "doctor": {
367
+ "description": "Check system dependencies and configuration",
368
+ "examples": [
369
+ "mcp-vector-search doctor",
379
370
  ],
380
- 'related': ['status', 'health']
371
+ "related": ["status", "health"],
372
+ },
373
+ "version": {
374
+ "description": "Show version information",
375
+ "examples": ["mcp-vector-search version", "mcp-vector-search --version"],
376
+ "related": ["status", "doctor"],
381
377
  },
382
- 'version': {
383
- 'description': 'Show version information',
384
- 'examples': [
385
- 'mcp-vector-search version',
386
- 'mcp-vector-search --version'
387
- ],
388
- 'related': ['status', 'doctor']
389
- }
390
378
  }
391
379
 
392
380
 
393
- def get_fuzzy_matches(command: str, available_commands: List[str], cutoff: float = 0.6) -> List[Tuple[str, float]]:
381
+ def get_fuzzy_matches(
382
+ command: str, available_commands: list[str], cutoff: float = 0.6
383
+ ) -> list[tuple[str, float]]:
394
384
  """Get fuzzy matches for a command using difflib.
395
-
385
+
396
386
  Args:
397
387
  command: The command to match
398
388
  available_commands: List of available commands
399
389
  cutoff: Minimum similarity ratio (0.0 to 1.0)
400
-
390
+
401
391
  Returns:
402
392
  List of tuples (command, similarity_ratio) sorted by similarity
403
393
  """
@@ -406,28 +396,28 @@ def get_fuzzy_matches(command: str, available_commands: List[str], cutoff: float
406
396
  ratio = difflib.SequenceMatcher(None, command.lower(), cmd.lower()).ratio()
407
397
  if ratio >= cutoff:
408
398
  matches.append((cmd, ratio))
409
-
399
+
410
400
  # Sort by similarity ratio (highest first)
411
401
  return sorted(matches, key=lambda x: x[1], reverse=True)
412
402
 
413
403
 
414
404
  def format_command_suggestion(command: str, show_examples: bool = True) -> str:
415
405
  """Format a command suggestion with description and examples.
416
-
406
+
417
407
  Args:
418
408
  command: The command to format
419
409
  show_examples: Whether to include usage examples
420
-
410
+
421
411
  Returns:
422
412
  Formatted suggestion string
423
413
  """
424
414
  if command in COMMAND_INFO:
425
415
  info = COMMAND_INFO[command]
426
416
  suggestion = f" [bold cyan]{command}[/bold cyan] - {info['description']}"
427
-
428
- if show_examples and info['examples']:
417
+
418
+ if show_examples and info["examples"]:
429
419
  suggestion += f"\n Example: [dim]{info['examples'][0]}[/dim]"
430
-
420
+
431
421
  return suggestion
432
422
  else:
433
423
  return f" [bold cyan]{command}[/bold cyan]"
@@ -435,49 +425,67 @@ def format_command_suggestion(command: str, show_examples: bool = True) -> str:
435
425
 
436
426
  def add_common_suggestions(ctx: click.Context, command_name: str) -> None:
437
427
  """Add enhanced command suggestions to error messages.
438
-
428
+
439
429
  Args:
440
430
  ctx: Click context
441
431
  command_name: The invalid command name that was entered
442
432
  """
443
433
  from rich.console import Console
434
+
444
435
  console = Console(stderr=True)
445
-
436
+
446
437
  # First, check for exact typo matches
447
438
  direct_suggestion = COMMON_TYPOS.get(command_name.lower())
448
439
  if direct_suggestion:
449
- console.print(f"\n[yellow]Did you mean:[/yellow]")
440
+ console.print("\n[yellow]Did you mean:[/yellow]")
450
441
  console.print(format_command_suggestion(direct_suggestion.split()[0]))
451
-
452
- if '--' not in direct_suggestion: # Don't show examples for flags
453
- console.print(f"\n[dim]Try: [bold]mcp-vector-search {direct_suggestion}[/bold][/dim]")
442
+
443
+ if "--" not in direct_suggestion: # Don't show examples for flags
444
+ console.print(
445
+ f"\n[dim]Try: [bold]mcp-vector-search {direct_suggestion}[/bold][/dim]"
446
+ )
454
447
  return
455
-
448
+
456
449
  # Get available commands from the context
457
450
  available_commands = []
458
- if hasattr(ctx, 'command') and hasattr(ctx.command, 'commands'):
451
+ if hasattr(ctx, "command") and hasattr(ctx.command, "commands"):
459
452
  available_commands = list(ctx.command.commands.keys())
460
-
453
+
461
454
  if not available_commands:
462
455
  # Fallback to common commands
463
- available_commands = ['search', 'index', 'status', 'config', 'init', 'mcp', 'doctor', 'version']
464
-
456
+ available_commands = [
457
+ "search",
458
+ "index",
459
+ "status",
460
+ "config",
461
+ "init",
462
+ "mcp",
463
+ "doctor",
464
+ "version",
465
+ ]
466
+
465
467
  # Get fuzzy matches
466
468
  fuzzy_matches = get_fuzzy_matches(command_name, available_commands, cutoff=0.4)
467
-
469
+
468
470
  if fuzzy_matches:
469
- console.print(f"\n[yellow]Did you mean one of these?[/yellow]")
470
-
471
+ console.print("\n[yellow]Did you mean one of these?[/yellow]")
472
+
471
473
  # Show up to 3 best matches
472
474
  for cmd, ratio in fuzzy_matches[:3]:
473
475
  console.print(format_command_suggestion(cmd, show_examples=False))
474
-
476
+
475
477
  # Show example for the best match
476
478
  if fuzzy_matches:
477
479
  best_match = fuzzy_matches[0][0]
478
- if best_match in COMMAND_INFO and COMMAND_INFO[best_match]['examples']:
479
- console.print(f"\n[dim]Example: [bold]{COMMAND_INFO[best_match]['examples'][0]}[/bold][/dim]")
480
-
480
+ if best_match in COMMAND_INFO and COMMAND_INFO[best_match]["examples"]:
481
+ console.print(
482
+ f"\n[dim]Example: [bold]{COMMAND_INFO[best_match]['examples'][0]}[/bold][/dim]"
483
+ )
484
+
481
485
  # Show related commands for context
482
- console.print(f"\n[dim]Available commands: {', '.join(sorted(available_commands))}[/dim]")
483
- console.print(f"[dim]Use [bold]mcp-vector-search --help[/bold] for more information[/dim]")
486
+ console.print(
487
+ f"\n[dim]Available commands: {', '.join(sorted(available_commands))}[/dim]"
488
+ )
489
+ console.print(
490
+ "[dim]Use [bold]mcp-vector-search --help[/bold] for more information[/dim]"
491
+ )