diff --git a/src/setup/README.md b/src/setup/README.md index b94b3d0b..4b734e36 100644 --- a/src/setup/README.md +++ b/src/setup/README.md @@ -209,19 +209,18 @@ env-var mode or skipped secrets. | Anthropic | API key | `anthropic_api_key` | `ANTHROPIC_API_KEY` | | OpenAI | API key | `openai_api_key` | `OPENAI_API_KEY` | | Ollama | None | - | - | -| OpenRouter¹ | API key | `llm_compatible_api_key` | `LLM_API_KEY` | -| OpenAI-compatible¹ | Optional API key | `llm_compatible_api_key` | `LLM_API_KEY` | +| OpenRouter | API key | `llm_openrouter_api_key` | `OPENROUTER_API_KEY` | +| OpenAI-compatible | Optional API key | `llm_compatible_api_key` | `LLM_API_KEY` | | AWS Bedrock | AWS credentials (IAM, SSO, instance roles) | - | - | -¹ OpenRouter and OpenAI-compatible share the same secret name and env var because -OpenRouter is stored as `llm_backend = "openai_compatible"` under the hood. -Switching between them overwrites the same credential slot. +**OpenRouter** is a standalone registry provider (`providers.json` id `"openrouter"`) +with its own secret name and env var. It is **not** stored as `openai_compatible`. -**OpenRouter** (`setup_openrouter`): -- Pre-configured OpenAI-compatible preset with base URL `https://openrouter.ai/api/v1` -- Delegates to `setup_api_key_provider()` with a display name override ("OpenRouter") -- Sets `llm_backend = "openai_compatible"` and `openai_compatible_base_url` automatically -- Clears `selected_model` so Step 4 prompts for a model name (manual text input, no API-based model fetching) +**OpenRouter** (`setup.kind = "api_key"` in `providers.json`): +- Standalone provider with base URL `https://openrouter.ai/api/v1` +- Delegates to `setup_api_key_provider()` with display name "OpenRouter" +- API key is required (`api_key_required: true`) +- Default model: `openai/gpt-4o` **API-key providers** (`setup_api_key_provider`): 1. Check env var → if set, ask to reuse, persist to secrets store diff --git a/src/setup/prompts.rs b/src/setup/prompts.rs index df4cbbc2..a52a8b68 100644 --- a/src/setup/prompts.rs +++ b/src/setup/prompts.rs @@ -200,6 +200,16 @@ fn read_secret_line() -> io::Result { let mut input = String::new(); let mut stdout = io::stdout(); + // Drain any residual key events (e.g. Enter from a prior `read_line` prompt) + // that are already queued before we start reading. Without this, on + // Windows the leftover Enter is immediately consumed and the function + // returns an empty string before the user can type anything. + // Uses Duration::ZERO so we never block waiting for new input — only + // events already in the queue are consumed. + while event::poll(std::time::Duration::ZERO)? { + let _ = event::read()?; + } + loop { if let Event::Key(KeyEvent { code, modifiers, ..