hud-python 0.4.22__py3-none-any.whl → 0.4.24__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 hud-python might be problematic. Click here for more details.
- hud/agents/base.py +85 -59
- hud/agents/claude.py +5 -1
- hud/agents/grounded_openai.py +3 -1
- hud/agents/misc/response_agent.py +3 -2
- hud/agents/openai.py +2 -2
- hud/agents/openai_chat_generic.py +3 -1
- hud/cli/__init__.py +34 -24
- hud/cli/analyze.py +27 -26
- hud/cli/build.py +50 -46
- hud/cli/debug.py +7 -7
- hud/cli/dev.py +107 -99
- hud/cli/eval.py +31 -29
- hud/cli/hf.py +53 -53
- hud/cli/init.py +28 -28
- hud/cli/list_func.py +22 -22
- hud/cli/pull.py +36 -36
- hud/cli/push.py +76 -74
- hud/cli/remove.py +42 -40
- hud/cli/rl/__init__.py +2 -2
- hud/cli/rl/init.py +41 -41
- hud/cli/rl/pod.py +97 -91
- hud/cli/rl/ssh.py +42 -40
- hud/cli/rl/train.py +75 -73
- hud/cli/rl/utils.py +10 -10
- hud/cli/tests/test_analyze.py +1 -1
- hud/cli/tests/test_analyze_metadata.py +2 -2
- hud/cli/tests/test_pull.py +45 -45
- hud/cli/tests/test_push.py +31 -29
- hud/cli/tests/test_registry.py +15 -15
- hud/cli/utils/environment.py +11 -11
- hud/cli/utils/interactive.py +17 -17
- hud/cli/utils/logging.py +12 -12
- hud/cli/utils/metadata.py +12 -12
- hud/cli/utils/registry.py +5 -5
- hud/cli/utils/runner.py +23 -23
- hud/cli/utils/server.py +16 -16
- hud/clients/mcp_use.py +19 -5
- hud/clients/utils/__init__.py +25 -0
- hud/clients/utils/retry.py +186 -0
- hud/datasets/execution/parallel.py +71 -46
- hud/shared/hints.py +7 -7
- hud/tools/grounding/grounder.py +2 -1
- hud/types.py +4 -4
- hud/utils/__init__.py +3 -3
- hud/utils/{design.py → hud_console.py} +39 -33
- hud/utils/pretty_errors.py +6 -6
- hud/utils/tests/test_version.py +1 -1
- hud/version.py +1 -1
- {hud_python-0.4.22.dist-info → hud_python-0.4.24.dist-info}/METADATA +3 -1
- {hud_python-0.4.22.dist-info → hud_python-0.4.24.dist-info}/RECORD +53 -52
- {hud_python-0.4.22.dist-info → hud_python-0.4.24.dist-info}/WHEEL +0 -0
- {hud_python-0.4.22.dist-info → hud_python-0.4.24.dist-info}/entry_points.txt +0 -0
- {hud_python-0.4.22.dist-info → hud_python-0.4.24.dist-info}/licenses/LICENSE +0 -0
hud/cli/analyze.py
CHANGED
|
@@ -13,10 +13,10 @@ from rich.table import Table
|
|
|
13
13
|
from rich.tree import Tree
|
|
14
14
|
|
|
15
15
|
from hud.clients import MCPClient
|
|
16
|
-
from hud.utils.
|
|
16
|
+
from hud.utils.hud_console import HUDConsole
|
|
17
17
|
|
|
18
18
|
console = Console()
|
|
19
|
-
|
|
19
|
+
hud_console = HUDConsole()
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def parse_docker_command(docker_cmd: list[str]) -> dict:
|
|
@@ -28,14 +28,14 @@ def parse_docker_command(docker_cmd: list[str]) -> dict:
|
|
|
28
28
|
|
|
29
29
|
async def analyze_environment(docker_cmd: list[str], output_format: str, verbose: bool) -> None:
|
|
30
30
|
"""Analyze MCP environment and display results."""
|
|
31
|
-
|
|
31
|
+
hud_console.header("MCP Environment Analysis", icon="🔍")
|
|
32
32
|
|
|
33
33
|
# Convert Docker command to MCP config
|
|
34
34
|
mcp_config = parse_docker_command(docker_cmd)
|
|
35
35
|
|
|
36
36
|
# Display command being analyzed
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
hud_console.dim_info("Command:", " ".join(docker_cmd))
|
|
38
|
+
hud_console.info("") # Empty line
|
|
39
39
|
|
|
40
40
|
# Create client
|
|
41
41
|
with Progress(
|
|
@@ -85,9 +85,9 @@ async def analyze_environment(docker_cmd: list[str], output_format: str, verbose
|
|
|
85
85
|
def display_interactive(analysis: dict) -> None:
|
|
86
86
|
"""Display analysis results in interactive format."""
|
|
87
87
|
# Server metadata
|
|
88
|
-
|
|
88
|
+
hud_console.section_title("📊 Environment Overview")
|
|
89
89
|
meta_table = Table(show_header=False, box=None)
|
|
90
|
-
meta_table.add_column("Property", style="
|
|
90
|
+
meta_table.add_column("Property", style="bright_black")
|
|
91
91
|
meta_table.add_column("Value")
|
|
92
92
|
|
|
93
93
|
# Check if this is a live analysis (has metadata) or metadata-only analysis
|
|
@@ -126,19 +126,19 @@ def display_interactive(analysis: dict) -> None:
|
|
|
126
126
|
console.print(meta_table)
|
|
127
127
|
|
|
128
128
|
# Tools
|
|
129
|
-
|
|
130
|
-
tools_tree = Tree("Tools")
|
|
129
|
+
hud_console.section_title("🔧 Available Tools")
|
|
130
|
+
tools_tree = Tree("[bold bright_white]Tools[/bold bright_white]")
|
|
131
131
|
|
|
132
132
|
# Check if we have hub_tools info (live analysis) or not (metadata-only)
|
|
133
133
|
if "hub_tools" in analysis:
|
|
134
134
|
# Live analysis format - separate regular and hub tools
|
|
135
135
|
# Regular tools
|
|
136
|
-
regular_tools = tools_tree.add("Regular Tools")
|
|
136
|
+
regular_tools = tools_tree.add("[bright_white]Regular Tools[/bright_white]")
|
|
137
137
|
for tool in analysis["tools"]:
|
|
138
138
|
if tool["name"] not in analysis["hub_tools"]:
|
|
139
|
-
tool_node = regular_tools.add(f"[
|
|
139
|
+
tool_node = regular_tools.add(f"[bright_white]{tool['name']}[/bright_white]")
|
|
140
140
|
if tool["description"]:
|
|
141
|
-
tool_node.add(f"[
|
|
141
|
+
tool_node.add(f"[bright_black]{tool['description']}[/bright_black]")
|
|
142
142
|
|
|
143
143
|
# Show input schema if verbose
|
|
144
144
|
if analysis.get("verbose") and tool.get("input_schema"):
|
|
@@ -148,17 +148,17 @@ def display_interactive(analysis: dict) -> None:
|
|
|
148
148
|
|
|
149
149
|
# Hub tools
|
|
150
150
|
if analysis["hub_tools"]:
|
|
151
|
-
hub_tools = tools_tree.add("Hub Tools")
|
|
151
|
+
hub_tools = tools_tree.add("[bright_white]Hub Tools[/bright_white]")
|
|
152
152
|
for hub_name, functions in analysis["hub_tools"].items():
|
|
153
|
-
hub_node = hub_tools.add(f"[
|
|
153
|
+
hub_node = hub_tools.add(f"[rgb(181,137,0)]{hub_name}[/rgb(181,137,0)]")
|
|
154
154
|
for func in functions:
|
|
155
|
-
hub_node.add(f"[
|
|
155
|
+
hub_node.add(f"[bright_white]{func}[/bright_white]")
|
|
156
156
|
else:
|
|
157
157
|
# Metadata-only format - just list all tools
|
|
158
158
|
for tool in analysis["tools"]:
|
|
159
|
-
tool_node = tools_tree.add(f"[
|
|
159
|
+
tool_node = tools_tree.add(f"[bright_white]{tool['name']}[/bright_white]")
|
|
160
160
|
if tool.get("description"):
|
|
161
|
-
tool_node.add(f"[
|
|
161
|
+
tool_node.add(f"[bright_black]{tool['description']}[/bright_black]")
|
|
162
162
|
|
|
163
163
|
# Show input schema if verbose
|
|
164
164
|
if tool.get("inputSchema"):
|
|
@@ -170,11 +170,11 @@ def display_interactive(analysis: dict) -> None:
|
|
|
170
170
|
|
|
171
171
|
# Resources
|
|
172
172
|
if analysis["resources"]:
|
|
173
|
-
|
|
173
|
+
hud_console.section_title("📚 Available Resources")
|
|
174
174
|
resources_table = Table()
|
|
175
|
-
resources_table.add_column("URI", style="
|
|
176
|
-
resources_table.add_column("Name", style="
|
|
177
|
-
resources_table.add_column("Type", style="
|
|
175
|
+
resources_table.add_column("URI", style="bright_white")
|
|
176
|
+
resources_table.add_column("Name", style="bright_white")
|
|
177
|
+
resources_table.add_column("Type", style="bright_black")
|
|
178
178
|
|
|
179
179
|
for resource in analysis["resources"][:10]:
|
|
180
180
|
resources_table.add_row(
|
|
@@ -184,11 +184,12 @@ def display_interactive(analysis: dict) -> None:
|
|
|
184
184
|
console.print(resources_table)
|
|
185
185
|
|
|
186
186
|
if len(analysis["resources"]) > 10:
|
|
187
|
-
|
|
187
|
+
remaining = len(analysis["resources"]) - 10
|
|
188
|
+
console.print(f"[bright_black]... and {remaining} more resources[/bright_black]")
|
|
188
189
|
|
|
189
190
|
# Telemetry (only for live analysis)
|
|
190
191
|
if analysis.get("telemetry"):
|
|
191
|
-
|
|
192
|
+
hud_console.section_title("📡 Telemetry Data")
|
|
192
193
|
telemetry_table = Table(show_header=False, box=None)
|
|
193
194
|
telemetry_table.add_column("Key", style="dim")
|
|
194
195
|
telemetry_table.add_column("Value")
|
|
@@ -206,7 +207,7 @@ def display_interactive(analysis: dict) -> None:
|
|
|
206
207
|
|
|
207
208
|
# Environment variables (for metadata-only analysis)
|
|
208
209
|
if analysis.get("env_vars"):
|
|
209
|
-
|
|
210
|
+
hud_console.section_title("🔑 Environment Variables")
|
|
210
211
|
env_table = Table(show_header=False, box=None)
|
|
211
212
|
env_table.add_column("Type", style="dim")
|
|
212
213
|
env_table.add_column("Variables")
|
|
@@ -309,7 +310,7 @@ async def analyze_environment_from_config(
|
|
|
309
310
|
config_path: Path, output_format: str, verbose: bool
|
|
310
311
|
) -> None:
|
|
311
312
|
"""Analyze MCP environment from a JSON config file."""
|
|
312
|
-
|
|
313
|
+
hud_console.header("MCP Environment Analysis", icon="🔍")
|
|
313
314
|
|
|
314
315
|
# Load config from file
|
|
315
316
|
try:
|
|
@@ -327,7 +328,7 @@ async def analyze_environment_from_mcp_config(
|
|
|
327
328
|
mcp_config: dict[str, Any], output_format: str, verbose: bool
|
|
328
329
|
) -> None:
|
|
329
330
|
"""Analyze MCP environment from MCP config dict."""
|
|
330
|
-
|
|
331
|
+
hud_console.header("MCP Environment Analysis", icon="🔍")
|
|
331
332
|
await _analyze_with_config(mcp_config, output_format, verbose)
|
|
332
333
|
|
|
333
334
|
|
hud/cli/build.py
CHANGED
|
@@ -14,7 +14,7 @@ import typer
|
|
|
14
14
|
import yaml
|
|
15
15
|
|
|
16
16
|
from hud.clients import MCPClient
|
|
17
|
-
from hud.utils.
|
|
17
|
+
from hud.utils.hud_console import HUDConsole
|
|
18
18
|
from hud.version import __version__ as hud_version
|
|
19
19
|
|
|
20
20
|
from .utils.registry import save_to_registry
|
|
@@ -156,7 +156,7 @@ async def analyze_mcp_environment(
|
|
|
156
156
|
image: str, verbose: bool = False, env_vars: dict[str, str] | None = None
|
|
157
157
|
) -> dict[str, Any]:
|
|
158
158
|
"""Analyze an MCP environment to extract metadata."""
|
|
159
|
-
|
|
159
|
+
hud_console = HUDConsole()
|
|
160
160
|
env_vars = env_vars or {}
|
|
161
161
|
|
|
162
162
|
# Build Docker command to run the image
|
|
@@ -180,7 +180,7 @@ async def analyze_mcp_environment(
|
|
|
180
180
|
|
|
181
181
|
try:
|
|
182
182
|
if verbose:
|
|
183
|
-
|
|
183
|
+
hud_console.info(f"Initializing MCP client with command: {' '.join(docker_cmd)}")
|
|
184
184
|
|
|
185
185
|
await client.initialize()
|
|
186
186
|
initialized = True
|
|
@@ -215,7 +215,7 @@ async def analyze_mcp_environment(
|
|
|
215
215
|
await client.shutdown()
|
|
216
216
|
except Exception:
|
|
217
217
|
# Ignore shutdown errors
|
|
218
|
-
|
|
218
|
+
hud_console.warning("Failed to shutdown MCP client")
|
|
219
219
|
|
|
220
220
|
|
|
221
221
|
def build_docker_image(
|
|
@@ -226,13 +226,13 @@ def build_docker_image(
|
|
|
226
226
|
build_args: dict[str, str] | None = None,
|
|
227
227
|
) -> bool:
|
|
228
228
|
"""Build a Docker image from a directory."""
|
|
229
|
-
|
|
229
|
+
hud_console = HUDConsole()
|
|
230
230
|
build_args = build_args or {}
|
|
231
231
|
|
|
232
232
|
# Check if Dockerfile exists
|
|
233
233
|
dockerfile = directory / "Dockerfile"
|
|
234
234
|
if not dockerfile.exists():
|
|
235
|
-
|
|
235
|
+
hud_console.error(f"No Dockerfile found in {directory}")
|
|
236
236
|
return False
|
|
237
237
|
|
|
238
238
|
# Build command
|
|
@@ -247,14 +247,14 @@ def build_docker_image(
|
|
|
247
247
|
cmd.append(str(directory))
|
|
248
248
|
|
|
249
249
|
# Always show build output
|
|
250
|
-
|
|
250
|
+
hud_console.info(f"Running: {' '.join(cmd)}")
|
|
251
251
|
|
|
252
252
|
try:
|
|
253
253
|
# Use Docker's native output formatting - no capture, let Docker handle display
|
|
254
254
|
result = subprocess.run(cmd, check=False) # noqa: S603
|
|
255
255
|
return result.returncode == 0
|
|
256
256
|
except Exception as e:
|
|
257
|
-
|
|
257
|
+
hud_console.error(f"Build error: {e}")
|
|
258
258
|
return False
|
|
259
259
|
|
|
260
260
|
|
|
@@ -266,20 +266,20 @@ def build_environment(
|
|
|
266
266
|
env_vars: dict[str, str] | None = None,
|
|
267
267
|
) -> None:
|
|
268
268
|
"""Build a HUD environment and generate lock file."""
|
|
269
|
-
|
|
269
|
+
hud_console = HUDConsole()
|
|
270
270
|
env_vars = env_vars or {}
|
|
271
|
-
|
|
271
|
+
hud_console.header("HUD Environment Build")
|
|
272
272
|
|
|
273
273
|
# Resolve directory
|
|
274
274
|
env_dir = Path(directory).resolve()
|
|
275
275
|
if not env_dir.exists():
|
|
276
|
-
|
|
276
|
+
hud_console.error(f"Directory not found: {directory}")
|
|
277
277
|
raise typer.Exit(1)
|
|
278
278
|
|
|
279
279
|
# Check for pyproject.toml
|
|
280
280
|
pyproject_path = env_dir / "pyproject.toml"
|
|
281
281
|
if not pyproject_path.exists():
|
|
282
|
-
|
|
282
|
+
hud_console.error(f"No pyproject.toml found in {directory}")
|
|
283
283
|
raise typer.Exit(1)
|
|
284
284
|
|
|
285
285
|
# Read pyproject.toml to get image name
|
|
@@ -301,17 +301,17 @@ def build_environment(
|
|
|
301
301
|
# Build temporary image first
|
|
302
302
|
temp_tag = f"hud-build-temp:{int(time.time())}"
|
|
303
303
|
|
|
304
|
-
|
|
304
|
+
hud_console.progress_message(f"Building Docker image: {temp_tag}")
|
|
305
305
|
|
|
306
306
|
# Build the image (env vars are for runtime, not build time)
|
|
307
307
|
if not build_docker_image(env_dir, temp_tag, no_cache, verbose):
|
|
308
|
-
|
|
308
|
+
hud_console.error("Docker build failed")
|
|
309
309
|
raise typer.Exit(1)
|
|
310
310
|
|
|
311
|
-
|
|
311
|
+
hud_console.success(f"Built temporary image: {temp_tag}")
|
|
312
312
|
|
|
313
313
|
# Analyze the environment
|
|
314
|
-
|
|
314
|
+
hud_console.progress_message("Analyzing MCP environment...")
|
|
315
315
|
|
|
316
316
|
loop = asyncio.new_event_loop()
|
|
317
317
|
asyncio.set_event_loop(loop)
|
|
@@ -320,7 +320,7 @@ def build_environment(
|
|
|
320
320
|
finally:
|
|
321
321
|
loop.close()
|
|
322
322
|
|
|
323
|
-
|
|
323
|
+
hud_console.success(f"Analyzed environment: {analysis['toolCount']} tools found")
|
|
324
324
|
|
|
325
325
|
# Extract environment variables from Dockerfile
|
|
326
326
|
dockerfile_path = env_dir / "Dockerfile"
|
|
@@ -335,14 +335,18 @@ def build_environment(
|
|
|
335
335
|
missing_required = [e for e in required_env if e not in env_vars]
|
|
336
336
|
|
|
337
337
|
# Show what env vars were provided
|
|
338
|
-
|
|
338
|
+
hud_console.success(f"Using provided environment variables: {', '.join(env_vars.keys())}")
|
|
339
339
|
else:
|
|
340
340
|
missing_required = required_env[:]
|
|
341
341
|
|
|
342
342
|
# Warn about missing required variables
|
|
343
343
|
if missing_required:
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
hud_console.warning(
|
|
345
|
+
f"Missing required environment variables: {', '.join(missing_required)}"
|
|
346
|
+
)
|
|
347
|
+
hud_console.info(
|
|
348
|
+
"These can be added to the lock file after build or provided with -e flags"
|
|
349
|
+
)
|
|
346
350
|
|
|
347
351
|
# Check for existing version and increment
|
|
348
352
|
lock_path = env_dir / "hud.lock.yaml"
|
|
@@ -351,11 +355,11 @@ def build_environment(
|
|
|
351
355
|
if existing_version:
|
|
352
356
|
# Increment existing version
|
|
353
357
|
new_version = increment_version(existing_version)
|
|
354
|
-
|
|
358
|
+
hud_console.info(f"Incrementing version: {existing_version} → {new_version}")
|
|
355
359
|
else:
|
|
356
360
|
# Start with 0.1.0 for new environments
|
|
357
361
|
new_version = "0.1.0"
|
|
358
|
-
|
|
362
|
+
hud_console.info(f"Setting initial version: {new_version}")
|
|
359
363
|
|
|
360
364
|
# Create lock file content - minimal and useful
|
|
361
365
|
lock_content = {
|
|
@@ -406,7 +410,7 @@ def build_environment(
|
|
|
406
410
|
with open(lock_path, "w") as f:
|
|
407
411
|
yaml.dump(lock_content, f, default_flow_style=False, sort_keys=False)
|
|
408
412
|
|
|
409
|
-
|
|
413
|
+
hud_console.success("Created lock file: hud.lock.yaml")
|
|
410
414
|
|
|
411
415
|
# Calculate lock file hash
|
|
412
416
|
lock_content_str = yaml.dump(lock_content, default_flow_style=False, sort_keys=True)
|
|
@@ -414,7 +418,7 @@ def build_environment(
|
|
|
414
418
|
lock_size = len(lock_content_str)
|
|
415
419
|
|
|
416
420
|
# Rebuild with label containing lock file hash
|
|
417
|
-
|
|
421
|
+
hud_console.progress_message("Rebuilding with lock file metadata...")
|
|
418
422
|
|
|
419
423
|
# Build final image with label (uses cache from first build)
|
|
420
424
|
# Also tag with version
|
|
@@ -447,10 +451,10 @@ def build_environment(
|
|
|
447
451
|
)
|
|
448
452
|
|
|
449
453
|
if result.returncode != 0:
|
|
450
|
-
|
|
454
|
+
hud_console.error("Failed to rebuild with label")
|
|
451
455
|
raise typer.Exit(1)
|
|
452
456
|
|
|
453
|
-
|
|
457
|
+
hud_console.success("Built final image with lock file metadata")
|
|
454
458
|
|
|
455
459
|
# NOW get the image ID after the final build
|
|
456
460
|
image_id = get_docker_image_id(tag) # type: ignore
|
|
@@ -466,9 +470,9 @@ def build_environment(
|
|
|
466
470
|
with open(lock_path, "w") as f:
|
|
467
471
|
yaml.dump(lock_content, f, default_flow_style=False, sort_keys=False)
|
|
468
472
|
|
|
469
|
-
|
|
473
|
+
hud_console.success("Updated lock file with image ID")
|
|
470
474
|
else:
|
|
471
|
-
|
|
475
|
+
hud_console.warning("Could not retrieve image ID for lock file")
|
|
472
476
|
|
|
473
477
|
# Remove temp image after we're done
|
|
474
478
|
subprocess.run(["docker", "rmi", temp_tag], capture_output=True) # noqa: S603, S607
|
|
@@ -479,30 +483,30 @@ def build_environment(
|
|
|
479
483
|
save_to_registry(lock_content, lock_content.get("image", tag), verbose)
|
|
480
484
|
|
|
481
485
|
# Print summary
|
|
482
|
-
|
|
486
|
+
hud_console.section_title("Build Complete")
|
|
483
487
|
|
|
484
488
|
# Show the version tag as primary since that's what will be pushed
|
|
485
|
-
|
|
489
|
+
hud_console.status_item("Built image", version_tag, primary=True)
|
|
486
490
|
if tag:
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
+
hud_console.status_item("Also tagged", tag)
|
|
492
|
+
hud_console.status_item("Version", new_version)
|
|
493
|
+
hud_console.status_item("Lock file", "hud.lock.yaml")
|
|
494
|
+
hud_console.status_item("Tools found", str(analysis["toolCount"]))
|
|
491
495
|
|
|
492
496
|
# Show the digest info separately if we have it
|
|
493
497
|
if image_id:
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
498
|
+
hud_console.dim_info("\nImage digest", image_id)
|
|
499
|
+
|
|
500
|
+
hud_console.section_title("Next Steps")
|
|
501
|
+
hud_console.info("Test locally:")
|
|
502
|
+
hud_console.command_example("hud dev", "Hot-reload development")
|
|
503
|
+
hud_console.command_example(f"hud run {tag}", "Run the built image")
|
|
504
|
+
hud_console.info("")
|
|
505
|
+
hud_console.info("Publish to registry:")
|
|
506
|
+
hud_console.command_example("hud push", f"Push as {version_tag}")
|
|
507
|
+
hud_console.command_example("hud push --tag latest", "Push with custom tag")
|
|
508
|
+
hud_console.info("")
|
|
509
|
+
hud_console.info("The lock file can be used to reproduce this exact environment.")
|
|
506
510
|
|
|
507
511
|
|
|
508
512
|
def build_command(
|
hud/cli/debug.py
CHANGED
|
@@ -12,7 +12,7 @@ import time
|
|
|
12
12
|
from rich.console import Console
|
|
13
13
|
|
|
14
14
|
from hud.clients import MCPClient
|
|
15
|
-
from hud.utils.
|
|
15
|
+
from hud.utils.hud_console import HUDConsole
|
|
16
16
|
|
|
17
17
|
from .utils.logging import CaptureLogger, Colors, analyze_error_for_hints
|
|
18
18
|
|
|
@@ -31,15 +31,15 @@ async def debug_mcp_stdio(command: list[str], logger: CaptureLogger, max_phase:
|
|
|
31
31
|
Returns:
|
|
32
32
|
Number of phases completed (0-5)
|
|
33
33
|
"""
|
|
34
|
-
# Create
|
|
34
|
+
# Create hud_console instance for initial output (before logger takes over)
|
|
35
35
|
if logger.print_output:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
hud_console = HUDConsole()
|
|
37
|
+
hud_console.header("MCP Server Debugger", icon="🔍")
|
|
38
|
+
hud_console.dim_info("Command:", " ".join(command))
|
|
39
|
+
hud_console.dim_info("Time:", time.strftime("%Y-%m-%d %H:%M:%S"))
|
|
40
40
|
|
|
41
41
|
# Explain color coding using Rich formatting
|
|
42
|
-
|
|
42
|
+
hud_console.info("\nColor Key:")
|
|
43
43
|
console.print(" [bold]■[/bold] Commands (bold)")
|
|
44
44
|
console.print(" [rgb(192,150,12)]■[/rgb(192,150,12)] STDIO (MCP protocol)")
|
|
45
45
|
console.print(" [dim]■[/dim] STDERR (server logs)")
|