mcp-vector-search 0.4.14__py3-none-any.whl → 0.5.0__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 +2 -2
- mcp_vector_search/cli/commands/index.py +73 -31
- mcp_vector_search/cli/commands/init.py +189 -113
- mcp_vector_search/cli/commands/install.py +525 -113
- mcp_vector_search/cli/commands/mcp.py +201 -151
- mcp_vector_search/cli/commands/reset.py +41 -41
- mcp_vector_search/cli/commands/search.py +73 -14
- mcp_vector_search/cli/commands/status.py +51 -17
- mcp_vector_search/cli/didyoumean.py +254 -246
- mcp_vector_search/cli/main.py +114 -43
- mcp_vector_search/cli/output.py +152 -0
- mcp_vector_search/cli/suggestions.py +246 -197
- mcp_vector_search/core/database.py +81 -49
- mcp_vector_search/core/indexer.py +10 -4
- mcp_vector_search/core/search.py +17 -6
- mcp_vector_search/mcp/__main__.py +1 -1
- mcp_vector_search/mcp/server.py +211 -203
- mcp_vector_search/parsers/__init__.py +6 -0
- mcp_vector_search/parsers/dart.py +605 -0
- mcp_vector_search/parsers/php.py +694 -0
- mcp_vector_search/parsers/registry.py +16 -1
- mcp_vector_search/parsers/ruby.py +678 -0
- mcp_vector_search/parsers/text.py +31 -25
- mcp_vector_search/utils/gitignore.py +72 -71
- {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.0.dist-info}/METADATA +59 -2
- {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.0.dist-info}/RECORD +29 -26
- {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.0.dist-info}/WHEEL +0 -0
- {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.0.dist-info}/entry_points.txt +0 -0
- {mcp_vector_search-0.4.14.dist-info → mcp_vector_search-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,306 +2,355 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Dict, List, Optional, Set, Tuple
|
|
6
|
-
from rich.console import Console
|
|
7
5
|
|
|
8
|
-
from
|
|
9
|
-
from ..core.exceptions import ProjectNotFoundError
|
|
6
|
+
from rich.console import Console
|
|
10
7
|
|
|
11
8
|
|
|
12
9
|
class ContextualSuggestionProvider:
|
|
13
10
|
"""Provides context-aware suggestions based on project state and user workflow."""
|
|
14
|
-
|
|
15
|
-
def __init__(self, project_root:
|
|
11
|
+
|
|
12
|
+
def __init__(self, project_root: Path | None = None):
|
|
16
13
|
"""Initialize the suggestion provider.
|
|
17
|
-
|
|
14
|
+
|
|
18
15
|
Args:
|
|
19
16
|
project_root: Root directory of the project (defaults to current directory)
|
|
20
17
|
"""
|
|
21
18
|
self.project_root = project_root or Path.cwd()
|
|
22
19
|
self.console = Console(stderr=True)
|
|
23
|
-
|
|
24
|
-
def get_project_state(self) ->
|
|
20
|
+
|
|
21
|
+
def get_project_state(self) -> dict[str, bool]:
|
|
25
22
|
"""Analyze the current project state.
|
|
26
|
-
|
|
23
|
+
|
|
27
24
|
Returns:
|
|
28
25
|
Dictionary with boolean flags indicating project state
|
|
29
26
|
"""
|
|
30
27
|
state = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
"is_initialized": False,
|
|
29
|
+
"has_index": False,
|
|
30
|
+
"has_config": False,
|
|
31
|
+
"has_recent_changes": False,
|
|
32
|
+
"is_git_repo": False,
|
|
33
|
+
"has_mcp_config": False,
|
|
37
34
|
}
|
|
38
|
-
|
|
35
|
+
|
|
39
36
|
try:
|
|
40
37
|
# Check if project is initialized
|
|
41
|
-
config_dir = self.project_root /
|
|
42
|
-
state[
|
|
43
|
-
|
|
44
|
-
if state[
|
|
38
|
+
config_dir = self.project_root / ".mcp-vector-search"
|
|
39
|
+
state["is_initialized"] = config_dir.exists()
|
|
40
|
+
|
|
41
|
+
if state["is_initialized"]:
|
|
45
42
|
# Check for config
|
|
46
|
-
config_file = config_dir /
|
|
47
|
-
state[
|
|
48
|
-
|
|
43
|
+
config_file = config_dir / "config.json"
|
|
44
|
+
state["has_config"] = config_file.exists()
|
|
45
|
+
|
|
49
46
|
# Check for index
|
|
50
|
-
index_dir = config_dir /
|
|
51
|
-
state[
|
|
52
|
-
|
|
47
|
+
index_dir = config_dir / "chroma_db"
|
|
48
|
+
state["has_index"] = index_dir.exists() and any(index_dir.iterdir())
|
|
49
|
+
|
|
53
50
|
# Check if it's a git repo
|
|
54
|
-
git_dir = self.project_root /
|
|
55
|
-
state[
|
|
56
|
-
|
|
51
|
+
git_dir = self.project_root / ".git"
|
|
52
|
+
state["is_git_repo"] = git_dir.exists()
|
|
53
|
+
|
|
57
54
|
# Check for MCP configuration (Claude Desktop config)
|
|
58
55
|
home = Path.home()
|
|
59
|
-
claude_config =
|
|
56
|
+
claude_config = (
|
|
57
|
+
home
|
|
58
|
+
/ "Library"
|
|
59
|
+
/ "Application Support"
|
|
60
|
+
/ "Claude"
|
|
61
|
+
/ "claude_desktop_config.json"
|
|
62
|
+
)
|
|
60
63
|
if claude_config.exists():
|
|
61
64
|
try:
|
|
62
65
|
with open(claude_config) as f:
|
|
63
66
|
config_data = json.load(f)
|
|
64
|
-
mcp_servers = config_data.get(
|
|
65
|
-
state[
|
|
66
|
-
except (json.JSONDecodeError
|
|
67
|
+
mcp_servers = config_data.get("mcpServers", {})
|
|
68
|
+
state["has_mcp_config"] = "mcp-vector-search" in mcp_servers
|
|
69
|
+
except (OSError, json.JSONDecodeError):
|
|
67
70
|
pass
|
|
68
|
-
|
|
71
|
+
|
|
69
72
|
# TODO: Check for recent file changes (would need file system monitoring)
|
|
70
73
|
# For now, we'll assume false
|
|
71
|
-
state[
|
|
72
|
-
|
|
74
|
+
state["has_recent_changes"] = False
|
|
75
|
+
|
|
73
76
|
except Exception:
|
|
74
77
|
# If we can't determine state, provide conservative defaults
|
|
75
78
|
pass
|
|
76
|
-
|
|
79
|
+
|
|
77
80
|
return state
|
|
78
|
-
|
|
79
|
-
def get_workflow_suggestions(self, failed_command: str) ->
|
|
81
|
+
|
|
82
|
+
def get_workflow_suggestions(self, failed_command: str) -> list[dict[str, str]]:
|
|
80
83
|
"""Get workflow-based suggestions for a failed command.
|
|
81
|
-
|
|
84
|
+
|
|
82
85
|
Args:
|
|
83
86
|
failed_command: The command that failed
|
|
84
|
-
|
|
87
|
+
|
|
85
88
|
Returns:
|
|
86
89
|
List of suggestion dictionaries with 'command', 'reason', and 'priority'
|
|
87
90
|
"""
|
|
88
91
|
suggestions = []
|
|
89
92
|
state = self.get_project_state()
|
|
90
|
-
|
|
93
|
+
|
|
91
94
|
# High priority suggestions based on project state
|
|
92
|
-
if not state[
|
|
93
|
-
suggestions.append(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
if not state["is_initialized"]:
|
|
96
|
+
suggestions.append(
|
|
97
|
+
{
|
|
98
|
+
"command": "init",
|
|
99
|
+
"reason": "Project is not initialized for vector search",
|
|
100
|
+
"priority": "high",
|
|
101
|
+
"description": "Set up the project configuration and create necessary directories",
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
elif not state["has_index"]:
|
|
105
|
+
suggestions.append(
|
|
106
|
+
{
|
|
107
|
+
"command": "index",
|
|
108
|
+
"reason": "No search index found - create one to enable searching",
|
|
109
|
+
"priority": "high",
|
|
110
|
+
"description": "Build the vector index for your codebase",
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
107
114
|
# Context-specific suggestions based on the failed command
|
|
108
|
-
if failed_command.lower() in [
|
|
109
|
-
if not state[
|
|
110
|
-
suggestions.append(
|
|
111
|
-
'command': 'index',
|
|
112
|
-
'reason': 'Cannot search without an index',
|
|
113
|
-
'priority': 'high',
|
|
114
|
-
'description': 'Build the search index first'
|
|
115
|
-
})
|
|
116
|
-
else:
|
|
117
|
-
suggestions.extend([
|
|
115
|
+
if failed_command.lower() in ["search", "find", "query", "s", "f"]:
|
|
116
|
+
if not state["has_index"]:
|
|
117
|
+
suggestions.append(
|
|
118
118
|
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
'command': 'interactive',
|
|
126
|
-
'reason': 'Try interactive search for better experience',
|
|
127
|
-
'priority': 'medium',
|
|
128
|
-
'description': 'Start an interactive search session'
|
|
119
|
+
"command": "index",
|
|
120
|
+
"reason": "Cannot search without an index",
|
|
121
|
+
"priority": "high",
|
|
122
|
+
"description": "Build the search index first",
|
|
129
123
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
suggestions.extend(
|
|
127
|
+
[
|
|
128
|
+
{
|
|
129
|
+
"command": "search",
|
|
130
|
+
"reason": "Correct command for semantic code search",
|
|
131
|
+
"priority": "high",
|
|
132
|
+
"description": "Search your codebase semantically",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"command": "interactive",
|
|
136
|
+
"reason": "Try interactive search for better experience",
|
|
137
|
+
"priority": "medium",
|
|
138
|
+
"description": "Start an interactive search session",
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
elif failed_command.lower() in ["index", "build", "scan", "i", "b"]:
|
|
144
|
+
suggestions.append(
|
|
145
|
+
{
|
|
146
|
+
"command": "index",
|
|
147
|
+
"reason": "Correct command for building search index",
|
|
148
|
+
"priority": "high",
|
|
149
|
+
"description": "Index your codebase for semantic search",
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
elif failed_command.lower() in ["status", "info", "stat", "st"]:
|
|
154
|
+
suggestions.append(
|
|
155
|
+
{
|
|
156
|
+
"command": "status",
|
|
157
|
+
"reason": "Show project status and statistics",
|
|
158
|
+
"priority": "high",
|
|
159
|
+
"description": "Display current project information",
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
elif failed_command.lower() in ["config", "configure", "settings", "c"]:
|
|
164
|
+
suggestions.append(
|
|
165
|
+
{
|
|
166
|
+
"command": "config",
|
|
167
|
+
"reason": "Manage project configuration",
|
|
168
|
+
"priority": "high",
|
|
169
|
+
"description": "View or modify project settings",
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
|
|
156
173
|
# MCP-related suggestions
|
|
157
|
-
if not state[
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
174
|
+
if not state["has_mcp_config"] and failed_command.lower() in [
|
|
175
|
+
"mcp",
|
|
176
|
+
"claude",
|
|
177
|
+
"server",
|
|
178
|
+
]:
|
|
179
|
+
suggestions.append(
|
|
180
|
+
{
|
|
181
|
+
"command": "init-mcp",
|
|
182
|
+
"reason": "Set up Claude Code MCP integration",
|
|
183
|
+
"priority": "medium",
|
|
184
|
+
"description": "Configure MCP server for Claude Code integration",
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
|
|
165
188
|
# Remove duplicates while preserving order
|
|
166
189
|
seen = set()
|
|
167
190
|
unique_suggestions = []
|
|
168
191
|
for suggestion in suggestions:
|
|
169
|
-
key = suggestion[
|
|
192
|
+
key = suggestion["command"]
|
|
170
193
|
if key not in seen:
|
|
171
194
|
seen.add(key)
|
|
172
195
|
unique_suggestions.append(suggestion)
|
|
173
|
-
|
|
196
|
+
|
|
174
197
|
return unique_suggestions
|
|
175
|
-
|
|
176
|
-
def get_next_steps(self) ->
|
|
198
|
+
|
|
199
|
+
def get_next_steps(self) -> list[dict[str, str]]:
|
|
177
200
|
"""Get suggested next steps based on current project state.
|
|
178
|
-
|
|
201
|
+
|
|
179
202
|
Returns:
|
|
180
203
|
List of suggested next step dictionaries
|
|
181
204
|
"""
|
|
182
205
|
state = self.get_project_state()
|
|
183
206
|
next_steps = []
|
|
184
|
-
|
|
185
|
-
if not state[
|
|
186
|
-
next_steps.append(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
207
|
+
|
|
208
|
+
if not state["is_initialized"]:
|
|
209
|
+
next_steps.append(
|
|
210
|
+
{
|
|
211
|
+
"command": "init",
|
|
212
|
+
"description": "Initialize the project for semantic search",
|
|
213
|
+
"priority": "high",
|
|
214
|
+
}
|
|
215
|
+
)
|
|
216
|
+
elif not state["has_index"]:
|
|
217
|
+
next_steps.append(
|
|
218
|
+
{
|
|
219
|
+
"command": "index",
|
|
220
|
+
"description": "Build the search index for your codebase",
|
|
221
|
+
"priority": "high",
|
|
222
|
+
}
|
|
223
|
+
)
|
|
197
224
|
else:
|
|
198
225
|
# Project is ready for use
|
|
199
|
-
next_steps.extend(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
226
|
+
next_steps.extend(
|
|
227
|
+
[
|
|
228
|
+
{
|
|
229
|
+
"command": 'search "your query here"',
|
|
230
|
+
"description": "Search your codebase semantically",
|
|
231
|
+
"priority": "high",
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"command": "status",
|
|
235
|
+
"description": "Check project statistics and index health",
|
|
236
|
+
"priority": "medium",
|
|
237
|
+
},
|
|
238
|
+
]
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
if state["has_recent_changes"]:
|
|
242
|
+
next_steps.insert(
|
|
243
|
+
0,
|
|
244
|
+
{
|
|
245
|
+
"command": "index --force",
|
|
246
|
+
"description": "Update the index with recent changes",
|
|
247
|
+
"priority": "high",
|
|
248
|
+
},
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
if not state["has_mcp_config"] and state["is_initialized"]:
|
|
252
|
+
next_steps.append(
|
|
205
253
|
{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
254
|
+
"command": "init-mcp",
|
|
255
|
+
"description": "Set up Claude Code integration",
|
|
256
|
+
"priority": "low",
|
|
209
257
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if state['has_recent_changes']:
|
|
213
|
-
next_steps.insert(0, {
|
|
214
|
-
'command': 'index --force',
|
|
215
|
-
'description': 'Update the index with recent changes',
|
|
216
|
-
'priority': 'high'
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
if not state['has_mcp_config'] and state['is_initialized']:
|
|
220
|
-
next_steps.append({
|
|
221
|
-
'command': 'init-mcp',
|
|
222
|
-
'description': 'Set up Claude Code integration',
|
|
223
|
-
'priority': 'low'
|
|
224
|
-
})
|
|
225
|
-
|
|
258
|
+
)
|
|
259
|
+
|
|
226
260
|
return next_steps
|
|
227
|
-
|
|
228
|
-
def show_contextual_help(self, failed_command:
|
|
261
|
+
|
|
262
|
+
def show_contextual_help(self, failed_command: str | None = None) -> None:
|
|
229
263
|
"""Show contextual help and suggestions.
|
|
230
|
-
|
|
264
|
+
|
|
231
265
|
Args:
|
|
232
266
|
failed_command: The command that failed (if any)
|
|
233
267
|
"""
|
|
234
268
|
if failed_command:
|
|
235
|
-
self.console.print(
|
|
236
|
-
|
|
269
|
+
self.console.print(
|
|
270
|
+
f"\n[yellow]Command '{failed_command}' not recognized.[/yellow]"
|
|
271
|
+
)
|
|
272
|
+
|
|
237
273
|
suggestions = self.get_workflow_suggestions(failed_command)
|
|
238
274
|
if suggestions:
|
|
239
|
-
self.console.print(
|
|
240
|
-
|
|
275
|
+
self.console.print(
|
|
276
|
+
"\n[bold]Based on your project state, you might want to try:[/bold]"
|
|
277
|
+
)
|
|
278
|
+
|
|
241
279
|
for i, suggestion in enumerate(suggestions[:3], 1): # Show top 3
|
|
242
280
|
priority_color = {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}.get(suggestion[
|
|
247
|
-
|
|
281
|
+
"high": "red",
|
|
282
|
+
"medium": "yellow",
|
|
283
|
+
"low": "dim",
|
|
284
|
+
}.get(suggestion["priority"], "white")
|
|
285
|
+
|
|
248
286
|
self.console.print(
|
|
249
287
|
f" [{priority_color}]{i}.[/{priority_color}] "
|
|
250
288
|
f"[bold cyan]mcp-vector-search {suggestion['command']}[/bold cyan]"
|
|
251
289
|
)
|
|
252
290
|
self.console.print(f" {suggestion['description']}")
|
|
253
|
-
if suggestion.get(
|
|
291
|
+
if suggestion.get("reason"):
|
|
254
292
|
self.console.print(f" [dim]({suggestion['reason']})[/dim]")
|
|
255
293
|
else:
|
|
256
294
|
# Show general next steps
|
|
257
295
|
next_steps = self.get_next_steps()
|
|
258
296
|
if next_steps:
|
|
259
297
|
self.console.print("\n[bold]Suggested next steps:[/bold]")
|
|
260
|
-
|
|
298
|
+
|
|
261
299
|
for i, step in enumerate(next_steps[:3], 1):
|
|
262
300
|
priority_color = {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}.get(step[
|
|
267
|
-
|
|
301
|
+
"high": "green",
|
|
302
|
+
"medium": "yellow",
|
|
303
|
+
"low": "dim",
|
|
304
|
+
}.get(step["priority"], "white")
|
|
305
|
+
|
|
268
306
|
self.console.print(
|
|
269
307
|
f" [{priority_color}]{i}.[/{priority_color}] "
|
|
270
308
|
f"[bold cyan]mcp-vector-search {step['command']}[/bold cyan]"
|
|
271
309
|
)
|
|
272
310
|
self.console.print(f" {step['description']}")
|
|
273
|
-
|
|
274
|
-
def get_command_completion_suggestions(self, partial_command: str) ->
|
|
311
|
+
|
|
312
|
+
def get_command_completion_suggestions(self, partial_command: str) -> list[str]:
|
|
275
313
|
"""Get command completion suggestions for a partial command.
|
|
276
|
-
|
|
314
|
+
|
|
277
315
|
Args:
|
|
278
316
|
partial_command: Partial command string
|
|
279
|
-
|
|
317
|
+
|
|
280
318
|
Returns:
|
|
281
319
|
List of possible command completions
|
|
282
320
|
"""
|
|
283
321
|
all_commands = [
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
322
|
+
"search",
|
|
323
|
+
"index",
|
|
324
|
+
"status",
|
|
325
|
+
"config",
|
|
326
|
+
"init",
|
|
327
|
+
"mcp",
|
|
328
|
+
"doctor",
|
|
329
|
+
"version",
|
|
330
|
+
"watch",
|
|
331
|
+
"auto-index",
|
|
332
|
+
"history",
|
|
333
|
+
"interactive",
|
|
334
|
+
"demo",
|
|
335
|
+
"install",
|
|
336
|
+
"reset",
|
|
337
|
+
"health",
|
|
287
338
|
]
|
|
288
|
-
|
|
339
|
+
|
|
289
340
|
# Add common aliases and shortcuts
|
|
290
|
-
all_commands.extend([
|
|
291
|
-
|
|
341
|
+
all_commands.extend(["s", "i", "st", "c", "f", "find"])
|
|
342
|
+
|
|
292
343
|
partial_lower = partial_command.lower()
|
|
293
|
-
matches = [
|
|
294
|
-
|
|
295
|
-
if cmd.startswith(partial_lower)
|
|
296
|
-
]
|
|
297
|
-
|
|
344
|
+
matches = [cmd for cmd in all_commands if cmd.startswith(partial_lower)]
|
|
345
|
+
|
|
298
346
|
return sorted(matches)
|
|
299
347
|
|
|
300
348
|
|
|
301
|
-
def get_contextual_suggestions(
|
|
302
|
-
|
|
349
|
+
def get_contextual_suggestions(
|
|
350
|
+
project_root: Path | None = None, failed_command: str | None = None
|
|
351
|
+
) -> None:
|
|
303
352
|
"""Get and display contextual suggestions.
|
|
304
|
-
|
|
353
|
+
|
|
305
354
|
Args:
|
|
306
355
|
project_root: Root directory of the project
|
|
307
356
|
failed_command: The command that failed
|
|
@@ -310,16 +359,16 @@ def get_contextual_suggestions(project_root: Optional[Path] = None,
|
|
|
310
359
|
provider.show_contextual_help(failed_command)
|
|
311
360
|
|
|
312
361
|
|
|
313
|
-
def suggest_workflow_commands(project_root:
|
|
362
|
+
def suggest_workflow_commands(project_root: Path | None = None) -> list[str]:
|
|
314
363
|
"""Get workflow command suggestions for the current project state.
|
|
315
|
-
|
|
364
|
+
|
|
316
365
|
Args:
|
|
317
366
|
project_root: Root directory of the project
|
|
318
|
-
|
|
367
|
+
|
|
319
368
|
Returns:
|
|
320
369
|
List of suggested commands in priority order
|
|
321
370
|
"""
|
|
322
371
|
provider = ContextualSuggestionProvider(project_root)
|
|
323
372
|
next_steps = provider.get_next_steps()
|
|
324
|
-
|
|
325
|
-
return [step[
|
|
373
|
+
|
|
374
|
+
return [step["command"] for step in next_steps]
|