- _test_connection() now returns the (possibly changed) model name and
offers a "Change model" option when the error is model-related
- _show_local_model_status() prints which models are currently loaded
immediately after selecting a local provider
- Draft persistence: each completed wizard step is saved to
~/.pyra/setup.draft.json (chmod 600); on the next run a yellow panel
summarises progress and offers [Resume / Start fresh]; draft is
deleted on successful completion or Ctrl-C with no completed steps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add _classify_error() that maps litellm/httpx exceptions to human-readable
labels and resolution hints without requiring a top-level litellm import.
_check_local_server() now loops with Retry / Continue anyway / Abort instead
of printing a one-shot warning and silently continuing.
_test_connection() now loops with Retry / Re-enter API key (auth errors only) /
Skip test / Abort instead of printing the raw exception string and falling through.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the static model text prompt with live API queries:
- _fetch_local_models(): queries /v1/models (LM Studio, llama.cpp) or
/api/tags (Ollama) and returns a questionary.select list
- _fetch_lmstudio_available_models(): queries LM Studio's beta
/api/v0/models to list downloaded-but-not-loaded models
- _load_lmstudio_model(): tries /api/v0/models/load to load a model
in-place; falls back to telling the user to load manually
- Cloud providers keep the existing text-input behaviour
Also replace hardcoded LMSTUDIO_MODEL in integration tests with a
lmstudio_model fixture that queries the API at runtime and uses
whichever model is currently loaded (skips if none).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a personalization step to `pyra setup` that asks for the user's name,
a one-sentence purpose, and interest areas, then surfaces relevant planned
plugins. Store purpose in GeneralConfig and use it in the system prompt so
Pyra stays task-focused rather than acting as a generic chatbot.
- config/schema.py: add `purpose: str = ""` to GeneralConfig
- setup/wizard.py: add _collect_user_profile(), _suggest_plugins(), _USE_CASE_PLUGINS
- chat/history.py: replace hardcoded _SYSTEM_BASE with _build_system_base() using config values
- config/tui.py: expose purpose field in /config General tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
litellm requires the api_key field even for local OpenAI-compatible
servers (LM Studio, llama.cpp). Use "local" as a sentinel value for
providers that don't require a real key.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>