mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-30 10:52:15 +00:00
feat(cli): add error hints system
New hints.py with hint_no_config(), hint_no_engine(), hint_no_model(). Wire hint_no_engine into ask.py EngineConnectionError handlers to show actionable suggestions when engine is unreachable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
30a6aa585d
commit
d1d113c1b1
@@ -8,6 +8,7 @@ import sys
|
||||
import click
|
||||
from rich.console import Console
|
||||
|
||||
from openjarvis.cli.hints import hint_no_engine
|
||||
from openjarvis.core.config import load_config
|
||||
from openjarvis.core.events import EventBus
|
||||
from openjarvis.core.types import Message, Role
|
||||
@@ -268,6 +269,7 @@ def ask(
|
||||
)
|
||||
except EngineConnectionError as exc:
|
||||
console.print(f"[red]Engine error:[/red] {exc}")
|
||||
console.print(hint_no_engine())
|
||||
sys.exit(1)
|
||||
|
||||
if output_json:
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Rich-formatted error hints for common CLI failure modes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def hint_no_config() -> str:
|
||||
"""Return a suggestion when no config file is found."""
|
||||
return (
|
||||
"[yellow]Hint:[/yellow] No config file found.\n"
|
||||
" Run [bold]jarvis init[/bold] to detect hardware and generate "
|
||||
"[cyan]~/.openjarvis/config.toml[/cyan].\n"
|
||||
" Or run [bold]jarvis quickstart[/bold] for a guided setup."
|
||||
)
|
||||
|
||||
|
||||
def hint_no_engine(engine_name: Optional[str] = None) -> str:
|
||||
"""Return a suggestion when the inference engine is unreachable."""
|
||||
name = engine_name or "ollama"
|
||||
return (
|
||||
f"[yellow]Hint:[/yellow] Engine '{name}' is not reachable.\n"
|
||||
f" Make sure the {name} server is running.\n"
|
||||
" Run [bold]jarvis doctor[/bold] to check all engines.\n"
|
||||
" Run [bold]jarvis quickstart[/bold] for guided setup."
|
||||
)
|
||||
|
||||
|
||||
def hint_no_model(model_name: Optional[str] = None) -> str:
|
||||
"""Return a suggestion when no model is available."""
|
||||
if model_name:
|
||||
return (
|
||||
f"[yellow]Hint:[/yellow] Model '{model_name}' not found.\n"
|
||||
f" Try: [bold]ollama pull {model_name}[/bold]\n"
|
||||
" Run [bold]jarvis model list[/bold] to see available models."
|
||||
)
|
||||
return (
|
||||
"[yellow]Hint:[/yellow] No models available.\n"
|
||||
" Pull a model first: [bold]ollama pull qwen3:8b[/bold]\n"
|
||||
" Run [bold]jarvis model list[/bold] to see available models."
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
"""Tests for CLI error hint functions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from openjarvis.cli.hints import (
|
||||
hint_no_config,
|
||||
hint_no_engine,
|
||||
hint_no_model,
|
||||
)
|
||||
|
||||
|
||||
class TestHintFunctions:
|
||||
def test_hint_no_config_returns_string(self):
|
||||
msg = hint_no_config()
|
||||
assert isinstance(msg, str)
|
||||
assert len(msg) > 0
|
||||
assert "init" in msg.lower() or "config" in msg.lower()
|
||||
|
||||
def test_hint_no_engine_returns_string(self):
|
||||
msg = hint_no_engine()
|
||||
assert isinstance(msg, str)
|
||||
assert len(msg) > 0
|
||||
assert "engine" in msg.lower() or "ollama" in msg.lower()
|
||||
|
||||
def test_hint_no_engine_with_name(self):
|
||||
msg = hint_no_engine("vllm")
|
||||
assert "vllm" in msg.lower()
|
||||
|
||||
def test_hint_no_model_returns_string(self):
|
||||
msg = hint_no_model()
|
||||
assert isinstance(msg, str)
|
||||
assert len(msg) > 0
|
||||
assert "model" in msg.lower() or "pull" in msg.lower()
|
||||
|
||||
def test_hint_no_model_with_name(self):
|
||||
msg = hint_no_model("qwen3:8b")
|
||||
assert "qwen3:8b" in msg
|
||||
Reference in New Issue
Block a user