Class: Rubino::CLI::OnboardingWizard

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/cli/onboarding_wizard.rb

Overview

First-run onboarding (#93). A small, skippable interactive wizard that takes a brand-new user from an empty home to a working model: pick a provider/model, paste the key (written to .env, never echoed back), and persist the matching model.default / model.provider / providers.<name> block to config.yml. The catalog mirrors DOCS-BLUEPRINT models-and-keys.

It is only invoked when no usable credential is configured AND we are on a real TTY (ChatCommand#ensure_model_configured!); non-interactive contexts get the actionable guidance instead. #run returns true on a completed setup, false if the user skipped — the caller re-checks usability either way, so a partial/declined run safely falls through to the guidance+exit.

Constant Summary collapse

PROVIDERS =

Each provider: the model.provider to write, a default model id, the .env key var, and any providers.<name> config block to persist. Ordered so the recommended default comes first and matches the seeded config default (config/defaults.rb model.default => openai/gpt-4.1), keeping the from-zero experience consistent between the wizard and the non-interactive fail-fast guidance.

[
  {
    key: "openai",
    label: "OpenAI (GPT) — recommended default",
    provider: "openai",
    model: "gpt-4.1",
    env_var: "OPENAI_API_KEY",
    config: {}
  },
  {
    key: "minimax",
    label: "MiniMax (Anthropic-compatible)",
    provider: "minimax",
    model: "MiniMax-M2.7",
    env_var: "MINIMAX_API_KEY",
    config: {
      "anthropic_compatible" => true,
      "base_url" => "https://api.minimax.io/anthropic",
      "api_key" => "${MINIMAX_API_KEY}"
    }
  },
  {
    key: "anthropic",
    label: "Anthropic (Claude)",
    provider: "anthropic",
    model: "claude-sonnet-4-5",
    env_var: "ANTHROPIC_API_KEY",
    config: {}
  },
  {
    key: "gemini",
    label: "Google (Gemini)",
    provider: "google",
    model: "gemini-2.5-pro",
    env_var: "GEMINI_API_KEY",
    config: {}
  },
  {
    key: "gateway",
    label: "OpenAI-compatible gateway",
    provider: "gateway",
    model: "auto",
    env_var: "OPENAI_API_KEY",
    config: {
      "openai_compatible" => true,
      "assume_model_exists" => true,
      "base_url" => nil # filled in interactively
    }
  }
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(ui: Rubino.ui, input: $stdin, output: $stdout) ⇒ OnboardingWizard

Returns a new instance of OnboardingWizard.



76
77
78
79
80
# File 'lib/rubino/cli/onboarding_wizard.rb', line 76

def initialize(ui: Rubino.ui, input: $stdin, output: $stdout)
  @ui     = ui
  @input  = input
  @output = output
end

Instance Method Details

#runObject

Drives the wizard. Returns true when a provider was configured, false when the user skipped (empty/‘s`/`skip` at the provider prompt).



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/rubino/cli/onboarding_wizard.rb', line 84

def run
  @ui.blank_line
  @ui.info("Welcome to rubino — let's get you connected to a model.")
  @ui.status("No API key is configured yet. Pick a provider (or press Enter to skip).")
  @ui.blank_line

  choice = ask_provider
  return false unless choice

  api_key = ask_api_key(choice)
  return false if api_key.nil? || api_key.empty?

  base_url = ask_base_url(choice)

  persist!(choice, api_key, base_url)
  Rubino.reload_configuration!

  @ui.blank_line
  @ui.success("Configured #{choice[:label]} with model #{choice[:model]}.")
  @ui.status("Saved to #{config_loader.config_path} and #{config_loader.env_path}.")
  @ui.blank_line
  true
end