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:
Jon Saad-Falcon
2026-02-28 17:27:10 +00:00
co-authored by Claude Opus 4.6
parent 30a6aa585d
commit d1d113c1b1
3 changed files with 80 additions and 0 deletions
+2
View File
@@ -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:
+41
View File
@@ -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."
)
+37
View File
@@ -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