mcp-vector-search 0.15.7__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.
- mcp_vector_search/__init__.py +10 -0
- mcp_vector_search/cli/__init__.py +1 -0
- mcp_vector_search/cli/commands/__init__.py +1 -0
- mcp_vector_search/cli/commands/auto_index.py +397 -0
- mcp_vector_search/cli/commands/chat.py +534 -0
- mcp_vector_search/cli/commands/config.py +393 -0
- mcp_vector_search/cli/commands/demo.py +358 -0
- mcp_vector_search/cli/commands/index.py +762 -0
- mcp_vector_search/cli/commands/init.py +658 -0
- mcp_vector_search/cli/commands/install.py +869 -0
- mcp_vector_search/cli/commands/install_old.py +700 -0
- mcp_vector_search/cli/commands/mcp.py +1254 -0
- mcp_vector_search/cli/commands/reset.py +393 -0
- mcp_vector_search/cli/commands/search.py +796 -0
- mcp_vector_search/cli/commands/setup.py +1133 -0
- mcp_vector_search/cli/commands/status.py +584 -0
- mcp_vector_search/cli/commands/uninstall.py +404 -0
- mcp_vector_search/cli/commands/visualize/__init__.py +39 -0
- mcp_vector_search/cli/commands/visualize/cli.py +265 -0
- mcp_vector_search/cli/commands/visualize/exporters/__init__.py +12 -0
- mcp_vector_search/cli/commands/visualize/exporters/html_exporter.py +33 -0
- mcp_vector_search/cli/commands/visualize/exporters/json_exporter.py +29 -0
- mcp_vector_search/cli/commands/visualize/graph_builder.py +709 -0
- mcp_vector_search/cli/commands/visualize/layout_engine.py +469 -0
- mcp_vector_search/cli/commands/visualize/server.py +201 -0
- mcp_vector_search/cli/commands/visualize/state_manager.py +428 -0
- mcp_vector_search/cli/commands/visualize/templates/__init__.py +16 -0
- mcp_vector_search/cli/commands/visualize/templates/base.py +218 -0
- mcp_vector_search/cli/commands/visualize/templates/scripts.py +3670 -0
- mcp_vector_search/cli/commands/visualize/templates/styles.py +779 -0
- mcp_vector_search/cli/commands/visualize.py.original +2536 -0
- mcp_vector_search/cli/commands/watch.py +287 -0
- mcp_vector_search/cli/didyoumean.py +520 -0
- mcp_vector_search/cli/export.py +320 -0
- mcp_vector_search/cli/history.py +295 -0
- mcp_vector_search/cli/interactive.py +342 -0
- mcp_vector_search/cli/main.py +484 -0
- mcp_vector_search/cli/output.py +414 -0
- mcp_vector_search/cli/suggestions.py +375 -0
- mcp_vector_search/config/__init__.py +1 -0
- mcp_vector_search/config/constants.py +24 -0
- mcp_vector_search/config/defaults.py +200 -0
- mcp_vector_search/config/settings.py +146 -0
- mcp_vector_search/core/__init__.py +1 -0
- mcp_vector_search/core/auto_indexer.py +298 -0
- mcp_vector_search/core/config_utils.py +394 -0
- mcp_vector_search/core/connection_pool.py +360 -0
- mcp_vector_search/core/database.py +1237 -0
- mcp_vector_search/core/directory_index.py +318 -0
- mcp_vector_search/core/embeddings.py +294 -0
- mcp_vector_search/core/exceptions.py +89 -0
- mcp_vector_search/core/factory.py +318 -0
- mcp_vector_search/core/git_hooks.py +345 -0
- mcp_vector_search/core/indexer.py +1002 -0
- mcp_vector_search/core/llm_client.py +453 -0
- mcp_vector_search/core/models.py +294 -0
- mcp_vector_search/core/project.py +350 -0
- mcp_vector_search/core/scheduler.py +330 -0
- mcp_vector_search/core/search.py +952 -0
- mcp_vector_search/core/watcher.py +322 -0
- mcp_vector_search/mcp/__init__.py +5 -0
- mcp_vector_search/mcp/__main__.py +25 -0
- mcp_vector_search/mcp/server.py +752 -0
- mcp_vector_search/parsers/__init__.py +8 -0
- mcp_vector_search/parsers/base.py +296 -0
- mcp_vector_search/parsers/dart.py +605 -0
- mcp_vector_search/parsers/html.py +413 -0
- mcp_vector_search/parsers/javascript.py +643 -0
- mcp_vector_search/parsers/php.py +694 -0
- mcp_vector_search/parsers/python.py +502 -0
- mcp_vector_search/parsers/registry.py +223 -0
- mcp_vector_search/parsers/ruby.py +678 -0
- mcp_vector_search/parsers/text.py +186 -0
- mcp_vector_search/parsers/utils.py +265 -0
- mcp_vector_search/py.typed +1 -0
- mcp_vector_search/utils/__init__.py +42 -0
- mcp_vector_search/utils/gitignore.py +250 -0
- mcp_vector_search/utils/gitignore_updater.py +212 -0
- mcp_vector_search/utils/monorepo.py +339 -0
- mcp_vector_search/utils/timing.py +338 -0
- mcp_vector_search/utils/version.py +47 -0
- mcp_vector_search-0.15.7.dist-info/METADATA +884 -0
- mcp_vector_search-0.15.7.dist-info/RECORD +86 -0
- mcp_vector_search-0.15.7.dist-info/WHEEL +4 -0
- mcp_vector_search-0.15.7.dist-info/entry_points.txt +3 -0
- mcp_vector_search-0.15.7.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
"""Main CLI application for MCP Vector Search."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from loguru import logger
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.traceback import install
|
|
9
|
+
|
|
10
|
+
from .. import __build__, __version__
|
|
11
|
+
from .didyoumean import add_common_suggestions, create_enhanced_typer
|
|
12
|
+
from .output import print_warning, setup_logging
|
|
13
|
+
from .suggestions import get_contextual_suggestions
|
|
14
|
+
|
|
15
|
+
# Install rich traceback handler
|
|
16
|
+
install(show_locals=True)
|
|
17
|
+
|
|
18
|
+
# Create console for rich output
|
|
19
|
+
console = Console()
|
|
20
|
+
|
|
21
|
+
# Create main Typer app with "did you mean" functionality
|
|
22
|
+
app = create_enhanced_typer(
|
|
23
|
+
name="mcp-vector-search",
|
|
24
|
+
help="""
|
|
25
|
+
🔍 [bold]MCP Vector Search - Semantic Code Search CLI[/bold]
|
|
26
|
+
|
|
27
|
+
Search your codebase by meaning, not just keywords. Find similar code patterns,
|
|
28
|
+
explore unfamiliar projects, and integrate with AI coding tools via MCP.
|
|
29
|
+
|
|
30
|
+
[bold cyan]QUICK START:[/bold cyan]
|
|
31
|
+
mcp-vector-search setup # One-time setup (recommended)
|
|
32
|
+
mcp-vector-search search "query" # Search by meaning
|
|
33
|
+
mcp-vector-search chat "question" # Ask AI about your code
|
|
34
|
+
|
|
35
|
+
[bold cyan]MAIN COMMANDS:[/bold cyan]
|
|
36
|
+
setup 🚀 Zero-config setup (indexes + configures MCP)
|
|
37
|
+
search 🔍 Semantic search (finds code by meaning)
|
|
38
|
+
chat 🤖 LLM-powered Q&A about your code (needs API key)
|
|
39
|
+
status 📊 Show project status
|
|
40
|
+
visualize 📊 Interactive code graph
|
|
41
|
+
|
|
42
|
+
[bold cyan]AI CHAT SETUP:[/bold cyan]
|
|
43
|
+
The 'chat' command requires an OpenRouter API key:
|
|
44
|
+
1. Get key: [cyan]https://openrouter.ai/keys[/cyan]
|
|
45
|
+
2. Set: [yellow]export OPENROUTER_API_KEY='your-key'[/yellow]
|
|
46
|
+
|
|
47
|
+
[bold cyan]EXAMPLES:[/bold cyan]
|
|
48
|
+
mcp-vector-search search "error handling"
|
|
49
|
+
mcp-vector-search search --files "*.ts" "authentication"
|
|
50
|
+
mcp-vector-search chat "where is the database configured?"
|
|
51
|
+
mcp-vector-search chat "how does auth work in this project?"
|
|
52
|
+
|
|
53
|
+
[bold cyan]MORE COMMANDS:[/bold cyan]
|
|
54
|
+
install 📦 Install project and MCP integrations
|
|
55
|
+
uninstall 🗑️ Remove MCP integrations
|
|
56
|
+
init 🔧 Initialize project (advanced)
|
|
57
|
+
demo 🎬 Run interactive demo
|
|
58
|
+
doctor 🩺 Check system health
|
|
59
|
+
index 📇 Index codebase
|
|
60
|
+
mcp 🔌 MCP server operations
|
|
61
|
+
config ⚙️ Configure settings
|
|
62
|
+
help ❓ Get help
|
|
63
|
+
version ℹ️ Show version
|
|
64
|
+
|
|
65
|
+
[dim]For more: [cyan]mcp-vector-search COMMAND --help[/cyan][/dim]
|
|
66
|
+
""",
|
|
67
|
+
add_completion=False,
|
|
68
|
+
rich_markup_mode="rich",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Import command modules
|
|
72
|
+
from .commands.chat import chat_app # noqa: E402
|
|
73
|
+
from .commands.config import config_app # noqa: E402
|
|
74
|
+
from .commands.demo import demo_app # noqa: E402
|
|
75
|
+
from .commands.index import index_app # noqa: E402
|
|
76
|
+
from .commands.init import init_app # noqa: E402
|
|
77
|
+
from .commands.install import install_app # noqa: E402
|
|
78
|
+
from .commands.mcp import mcp_app # noqa: E402
|
|
79
|
+
from .commands.search import search_app, search_main # noqa: E402, F401
|
|
80
|
+
from .commands.setup import setup_app # noqa: E402
|
|
81
|
+
from .commands.status import main as status_main # noqa: E402
|
|
82
|
+
from .commands.uninstall import uninstall_app # noqa: E402
|
|
83
|
+
from .commands.visualize import app as visualize_app # noqa: E402
|
|
84
|
+
|
|
85
|
+
# ============================================================================
|
|
86
|
+
# MAIN COMMANDS - Clean hierarchy
|
|
87
|
+
# ============================================================================
|
|
88
|
+
|
|
89
|
+
# 0. SETUP - Smart zero-config setup (RECOMMENDED!)
|
|
90
|
+
app.add_typer(setup_app, name="setup", help="🚀 Smart zero-config setup (recommended)")
|
|
91
|
+
|
|
92
|
+
# 1. INSTALL - Install project and MCP integrations (NEW!)
|
|
93
|
+
app.add_typer(
|
|
94
|
+
install_app, name="install", help="📦 Install project and MCP integrations"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# 2. UNINSTALL - Remove MCP integrations (NEW!)
|
|
98
|
+
app.add_typer(uninstall_app, name="uninstall", help="🗑️ Remove MCP integrations")
|
|
99
|
+
app.add_typer(uninstall_app, name="remove", help="🗑️ Remove MCP integrations (alias)")
|
|
100
|
+
|
|
101
|
+
# 3. INIT - Initialize project (simplified)
|
|
102
|
+
# Use Typer group for init to support both direct call and subcommands
|
|
103
|
+
app.add_typer(init_app, name="init", help="🔧 Initialize project for semantic search")
|
|
104
|
+
|
|
105
|
+
# 4. DEMO - Interactive demo
|
|
106
|
+
app.add_typer(demo_app, name="demo", help="🎬 Run interactive demo with sample project")
|
|
107
|
+
|
|
108
|
+
# 5. DOCTOR - System health check
|
|
109
|
+
# (defined below inline)
|
|
110
|
+
|
|
111
|
+
# 6. STATUS - Project status
|
|
112
|
+
app.command("status", help="📊 Show project status and statistics")(status_main)
|
|
113
|
+
|
|
114
|
+
# 7. SEARCH - Search code
|
|
115
|
+
# Register search as both a command and a typer group
|
|
116
|
+
app.add_typer(search_app, name="search", help="🔍 Search code semantically")
|
|
117
|
+
|
|
118
|
+
# 7.5. CHAT - LLM-powered intelligent search
|
|
119
|
+
app.add_typer(chat_app, name="chat", help="🤖 Ask questions about code with LLM")
|
|
120
|
+
|
|
121
|
+
# 8. INDEX - Index codebase
|
|
122
|
+
app.add_typer(index_app, name="index", help="📇 Index codebase for semantic search")
|
|
123
|
+
|
|
124
|
+
# 9. MCP - MCP server operations (RESERVED for server ops only!)
|
|
125
|
+
app.add_typer(mcp_app, name="mcp", help="🔌 MCP server operations")
|
|
126
|
+
|
|
127
|
+
# 10. CONFIG - Configuration
|
|
128
|
+
app.add_typer(config_app, name="config", help="⚙️ Manage project configuration")
|
|
129
|
+
|
|
130
|
+
# 11. VISUALIZE - Code graph visualization
|
|
131
|
+
app.add_typer(
|
|
132
|
+
visualize_app, name="visualize", help="📊 Visualize code chunk relationships"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# 12. HELP - Enhanced help
|
|
136
|
+
# (defined below inline)
|
|
137
|
+
|
|
138
|
+
# 13. VERSION - Version info
|
|
139
|
+
# (defined below inline)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# ============================================================================
|
|
143
|
+
# DEPRECATED COMMANDS - With helpful suggestions
|
|
144
|
+
# ============================================================================
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _deprecated_command(old_cmd: str, new_cmd: str):
|
|
148
|
+
"""Helper to create deprecated command with suggestion."""
|
|
149
|
+
|
|
150
|
+
def wrapper(*args, **kwargs):
|
|
151
|
+
print_warning(
|
|
152
|
+
f"⚠️ The command '{old_cmd}' is deprecated.\n"
|
|
153
|
+
f" Please use '{new_cmd}' instead.\n"
|
|
154
|
+
f" Run: [cyan]mcp-vector-search {new_cmd} --help[/cyan] for details."
|
|
155
|
+
)
|
|
156
|
+
raise typer.Exit(1)
|
|
157
|
+
|
|
158
|
+
return wrapper
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# NOTE: 'install' command is now the primary command for project installation
|
|
162
|
+
# Old 'install' was deprecated in favor of 'init' in v0.7.0
|
|
163
|
+
# Now 'install' is back as the hierarchical installation command in v0.13.0
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# Deprecated: find -> search
|
|
167
|
+
@app.command("find", hidden=True)
|
|
168
|
+
def deprecated_find():
|
|
169
|
+
"""[DEPRECATED] Use 'search' instead."""
|
|
170
|
+
_deprecated_command("find", "search")()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# Deprecated: search-similar -> search --similar
|
|
174
|
+
@app.command("search-similar", hidden=True)
|
|
175
|
+
def deprecated_search_similar():
|
|
176
|
+
"""[DEPRECATED] Use 'search --similar' instead."""
|
|
177
|
+
_deprecated_command("search-similar", "search --similar")()
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# Deprecated: search-context -> search --context
|
|
181
|
+
@app.command("search-context", hidden=True)
|
|
182
|
+
def deprecated_search_context():
|
|
183
|
+
"""[DEPRECATED] Use 'search --context' instead."""
|
|
184
|
+
_deprecated_command("search-context", "search --context")()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# Deprecated: interactive -> search interactive
|
|
188
|
+
@app.command("interactive", hidden=True)
|
|
189
|
+
def deprecated_interactive():
|
|
190
|
+
"""[DEPRECATED] Use 'search interactive' instead."""
|
|
191
|
+
_deprecated_command("interactive", "search interactive")()
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# Deprecated: history -> search history
|
|
195
|
+
@app.command("history", hidden=True)
|
|
196
|
+
def deprecated_history():
|
|
197
|
+
"""[DEPRECATED] Use 'search history' instead."""
|
|
198
|
+
_deprecated_command("history", "search history")()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# Deprecated: favorites -> search favorites
|
|
202
|
+
@app.command("favorites", hidden=True)
|
|
203
|
+
def deprecated_favorites():
|
|
204
|
+
"""[DEPRECATED] Use 'search favorites' instead."""
|
|
205
|
+
_deprecated_command("favorites", "search favorites")()
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# Deprecated: add-favorite -> search favorites add
|
|
209
|
+
@app.command("add-favorite", hidden=True)
|
|
210
|
+
def deprecated_add_favorite():
|
|
211
|
+
"""[DEPRECATED] Use 'search favorites add' instead."""
|
|
212
|
+
_deprecated_command("add-favorite", "search favorites add")()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# Deprecated: remove-favorite -> search favorites remove
|
|
216
|
+
@app.command("remove-favorite", hidden=True)
|
|
217
|
+
def deprecated_remove_favorite():
|
|
218
|
+
"""[DEPRECATED] Use 'search favorites remove' instead."""
|
|
219
|
+
_deprecated_command("remove-favorite", "search favorites remove")()
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Deprecated: health -> index health
|
|
223
|
+
@app.command("health", hidden=True)
|
|
224
|
+
def deprecated_health():
|
|
225
|
+
"""[DEPRECATED] Use 'index health' instead."""
|
|
226
|
+
_deprecated_command("health", "index health")()
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# Deprecated: watch -> index watch
|
|
230
|
+
@app.command("watch", hidden=True)
|
|
231
|
+
def deprecated_watch():
|
|
232
|
+
"""[DEPRECATED] Use 'index watch' instead."""
|
|
233
|
+
_deprecated_command("watch", "index watch")()
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# Deprecated: auto-index -> index auto
|
|
237
|
+
@app.command("auto-index", hidden=True)
|
|
238
|
+
def deprecated_auto_index():
|
|
239
|
+
"""[DEPRECATED] Use 'index auto' instead."""
|
|
240
|
+
_deprecated_command("auto-index", "index auto")()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
# Deprecated: reset -> mcp reset or config reset
|
|
244
|
+
@app.command("reset", hidden=True)
|
|
245
|
+
def deprecated_reset():
|
|
246
|
+
"""[DEPRECATED] Use 'mcp reset' or 'config reset' instead."""
|
|
247
|
+
print_warning(
|
|
248
|
+
"⚠️ The 'reset' command is deprecated.\n"
|
|
249
|
+
" Use [cyan]mcp-vector-search mcp reset[/cyan] for MCP reset\n"
|
|
250
|
+
" Use [cyan]mcp-vector-search config reset[/cyan] for config reset"
|
|
251
|
+
)
|
|
252
|
+
raise typer.Exit(1)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
# Deprecated: init-check -> init check
|
|
256
|
+
@app.command("init-check", hidden=True)
|
|
257
|
+
def deprecated_init_check():
|
|
258
|
+
"""[DEPRECATED] Use 'init check' instead."""
|
|
259
|
+
_deprecated_command("init-check", "init check")()
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
# Deprecated: init-mcp -> mcp install
|
|
263
|
+
@app.command("init-mcp", hidden=True)
|
|
264
|
+
def deprecated_init_mcp():
|
|
265
|
+
"""[DEPRECATED] Use 'mcp install' instead."""
|
|
266
|
+
_deprecated_command("init-mcp", "mcp install")()
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# Deprecated: init-models -> config models
|
|
270
|
+
@app.command("init-models", hidden=True)
|
|
271
|
+
def deprecated_init_models():
|
|
272
|
+
"""[DEPRECATED] Use 'config models' instead."""
|
|
273
|
+
_deprecated_command("init-models", "config models")()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# ============================================================================
|
|
277
|
+
# MAIN INLINE COMMANDS
|
|
278
|
+
# ============================================================================
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@app.command("doctor")
|
|
282
|
+
def doctor_command() -> None:
|
|
283
|
+
"""🩺 Check system dependencies and configuration.
|
|
284
|
+
|
|
285
|
+
Runs diagnostic checks to ensure all required dependencies are installed
|
|
286
|
+
and properly configured. Use this to troubleshoot installation issues.
|
|
287
|
+
|
|
288
|
+
Examples:
|
|
289
|
+
mcp-vector-search doctor
|
|
290
|
+
"""
|
|
291
|
+
from .commands.status import check_dependencies
|
|
292
|
+
|
|
293
|
+
console.print("[bold blue]🩺 MCP Vector Search - System Check[/bold blue]\n")
|
|
294
|
+
|
|
295
|
+
# Check dependencies
|
|
296
|
+
deps_ok = check_dependencies()
|
|
297
|
+
|
|
298
|
+
if deps_ok:
|
|
299
|
+
console.print("\n[green]✓ All dependencies are available[/green]")
|
|
300
|
+
else:
|
|
301
|
+
console.print("\n[red]✗ Some dependencies are missing[/red]")
|
|
302
|
+
console.print(
|
|
303
|
+
"Run [code]pip install mcp-vector-search[/code] to install missing dependencies"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@app.command("help")
|
|
308
|
+
def help_command(
|
|
309
|
+
command: str | None = typer.Argument(
|
|
310
|
+
None, help="Command to get help for (optional)"
|
|
311
|
+
),
|
|
312
|
+
) -> None:
|
|
313
|
+
"""❓ Show contextual help and suggestions.
|
|
314
|
+
|
|
315
|
+
Get detailed help about specific commands or general usage guidance
|
|
316
|
+
based on your project state.
|
|
317
|
+
|
|
318
|
+
Examples:
|
|
319
|
+
mcp-vector-search help # General help
|
|
320
|
+
mcp-vector-search help search # Help for search command
|
|
321
|
+
mcp-vector-search help init # Help for init command
|
|
322
|
+
"""
|
|
323
|
+
try:
|
|
324
|
+
project_root = Path.cwd()
|
|
325
|
+
console.print(
|
|
326
|
+
f"[bold blue]mcp-vector-search[/bold blue] version [green]{__version__}[/green]"
|
|
327
|
+
)
|
|
328
|
+
console.print("[dim]CLI-first semantic code search with MCP integration[/dim]")
|
|
329
|
+
|
|
330
|
+
if command:
|
|
331
|
+
# Show help for specific command
|
|
332
|
+
console.print(
|
|
333
|
+
f"\n[dim]Run: [bold]mcp-vector-search {command} --help[/bold] for detailed help[/dim]"
|
|
334
|
+
)
|
|
335
|
+
else:
|
|
336
|
+
# Show general contextual suggestions
|
|
337
|
+
get_contextual_suggestions(project_root)
|
|
338
|
+
except Exception as e:
|
|
339
|
+
logger.debug(f"Failed to show contextual help: {e}")
|
|
340
|
+
console.print(
|
|
341
|
+
"\n[dim]Use [bold]mcp-vector-search --help[/bold] for more information.[/dim]"
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
@app.command("version")
|
|
346
|
+
def version_command() -> None:
|
|
347
|
+
"""ℹ️ Show version information."""
|
|
348
|
+
console.print(
|
|
349
|
+
f"[bold blue]mcp-vector-search[/bold blue] version [green]{__version__}[/green] [dim](build {__build__})[/dim]"
|
|
350
|
+
)
|
|
351
|
+
console.print("\n[dim]CLI-first semantic code search with MCP integration[/dim]")
|
|
352
|
+
console.print("[dim]Built with ChromaDB, Tree-sitter, and modern Python[/dim]")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@app.callback()
|
|
356
|
+
def main(
|
|
357
|
+
ctx: typer.Context,
|
|
358
|
+
version: bool = typer.Option(
|
|
359
|
+
False,
|
|
360
|
+
"--version",
|
|
361
|
+
"-v",
|
|
362
|
+
help="Show version and exit",
|
|
363
|
+
rich_help_panel="ℹ️ Information",
|
|
364
|
+
),
|
|
365
|
+
verbose: bool = typer.Option(
|
|
366
|
+
False,
|
|
367
|
+
"--verbose",
|
|
368
|
+
help="Enable verbose logging",
|
|
369
|
+
rich_help_panel="🔧 Global Options",
|
|
370
|
+
),
|
|
371
|
+
quiet: bool = typer.Option(
|
|
372
|
+
False,
|
|
373
|
+
"--quiet",
|
|
374
|
+
help="Suppress non-error output",
|
|
375
|
+
rich_help_panel="🔧 Global Options",
|
|
376
|
+
),
|
|
377
|
+
project_root: Path | None = typer.Option(
|
|
378
|
+
None,
|
|
379
|
+
"--project-root",
|
|
380
|
+
"-p",
|
|
381
|
+
help="Project root directory (auto-detected if not specified)",
|
|
382
|
+
exists=True,
|
|
383
|
+
file_okay=False,
|
|
384
|
+
dir_okay=True,
|
|
385
|
+
readable=True,
|
|
386
|
+
rich_help_panel="🔧 Global Options",
|
|
387
|
+
),
|
|
388
|
+
) -> None:
|
|
389
|
+
"""MCP Vector Search - CLI-first semantic code search with MCP integration.
|
|
390
|
+
|
|
391
|
+
A modern, lightweight tool for semantic code search using ChromaDB and Tree-sitter.
|
|
392
|
+
Designed for local development with optional MCP server integration.
|
|
393
|
+
"""
|
|
394
|
+
if version:
|
|
395
|
+
console.print(f"mcp-vector-search version {__version__} (build {__build__})")
|
|
396
|
+
raise typer.Exit()
|
|
397
|
+
|
|
398
|
+
# Setup logging
|
|
399
|
+
log_level = "DEBUG" if verbose else "ERROR" if quiet else "WARNING"
|
|
400
|
+
setup_logging(log_level)
|
|
401
|
+
|
|
402
|
+
# Store global options in context
|
|
403
|
+
ctx.ensure_object(dict)
|
|
404
|
+
ctx.obj["verbose"] = verbose
|
|
405
|
+
ctx.obj["quiet"] = quiet
|
|
406
|
+
ctx.obj["project_root"] = project_root
|
|
407
|
+
|
|
408
|
+
if verbose:
|
|
409
|
+
logger.info(f"MCP Vector Search v{__version__} (build {__build__})")
|
|
410
|
+
if project_root:
|
|
411
|
+
logger.info(f"Using project root: {project_root}")
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
# ============================================================================
|
|
415
|
+
# CLI ENTRY POINT WITH ERROR HANDLING
|
|
416
|
+
# ============================================================================
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def cli_with_suggestions():
|
|
420
|
+
"""CLI wrapper that catches errors and provides suggestions."""
|
|
421
|
+
import sys
|
|
422
|
+
|
|
423
|
+
import click
|
|
424
|
+
|
|
425
|
+
try:
|
|
426
|
+
# Call the app with standalone_mode=False to get exceptions instead of sys.exit
|
|
427
|
+
app(standalone_mode=False)
|
|
428
|
+
except click.UsageError as e:
|
|
429
|
+
# Check if it's a "No such command" error
|
|
430
|
+
if "No such command" in str(e):
|
|
431
|
+
# Extract the command name from the error
|
|
432
|
+
import re
|
|
433
|
+
|
|
434
|
+
match = re.search(r"No such command '([^']+)'", str(e))
|
|
435
|
+
if match:
|
|
436
|
+
command_name = match.group(1)
|
|
437
|
+
|
|
438
|
+
# Show enhanced suggestions
|
|
439
|
+
from rich.console import Console
|
|
440
|
+
|
|
441
|
+
console = Console(stderr=True)
|
|
442
|
+
console.print(f"\\n[red]Error:[/red] {e}")
|
|
443
|
+
|
|
444
|
+
# Show enhanced suggestions
|
|
445
|
+
add_common_suggestions(None, command_name)
|
|
446
|
+
|
|
447
|
+
# Show contextual suggestions too
|
|
448
|
+
try:
|
|
449
|
+
project_root = Path.cwd()
|
|
450
|
+
get_contextual_suggestions(project_root, command_name)
|
|
451
|
+
except Exception as e:
|
|
452
|
+
logger.debug(
|
|
453
|
+
f"Failed to get contextual suggestions for error handling: {e}"
|
|
454
|
+
)
|
|
455
|
+
pass
|
|
456
|
+
|
|
457
|
+
sys.exit(2) # Exit with error code
|
|
458
|
+
|
|
459
|
+
# For other usage errors, show the default message and exit
|
|
460
|
+
click.echo(f"Error: {e}", err=True)
|
|
461
|
+
sys.exit(2)
|
|
462
|
+
except click.Abort:
|
|
463
|
+
# User interrupted (Ctrl+C)
|
|
464
|
+
sys.exit(1)
|
|
465
|
+
except (SystemExit, click.exceptions.Exit):
|
|
466
|
+
# Re-raise system exits and typer.Exit
|
|
467
|
+
raise
|
|
468
|
+
except Exception as e:
|
|
469
|
+
# For other exceptions, show error and exit if verbose logging is enabled
|
|
470
|
+
# Suppress internal framework errors in normal operation
|
|
471
|
+
|
|
472
|
+
# Suppress harmless didyoumean framework AttributeError (known issue)
|
|
473
|
+
# This occurs during Click/Typer cleanup after successful command completion
|
|
474
|
+
if isinstance(e, AttributeError) and "attribute" in str(e) and "name" in str(e):
|
|
475
|
+
pass # Ignore - this is a harmless framework cleanup error
|
|
476
|
+
elif "--verbose" in sys.argv or "-v" in sys.argv:
|
|
477
|
+
click.echo(f"Unexpected error: {e}", err=True)
|
|
478
|
+
sys.exit(1)
|
|
479
|
+
# Otherwise, just exit silently to avoid confusing error messages
|
|
480
|
+
pass
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
if __name__ == "__main__":
|
|
484
|
+
cli_with_suggestions()
|