Class: BruteCLI::REPL

Inherits:
Object
  • Object
show all
Defined in:
lib/brute_cli/repl.rb,
lib/brute_cli/repl/banner.rb,
lib/brute_cli/repl/commands.rb,
lib/brute_cli/repl/fzf_menu.rb,
lib/brute_cli/repl/user_input.rb,
lib/brute_cli/repl/question_screen.rb

Overview

REPL wraps an Execution with an interactive read-eval-print loop: Reline prompt, Tab-based agent cycling, slash commands, fzf file picking, and banner display.

For non-interactive (pipe / single-prompt) use, use Execution directly.

Defined Under Namespace

Modules: Commands Classes: Banner, FzfMenu, PromptStatus, QuestionScreen, UserInput

Constant Summary collapse

PROVIDER_ENV_KEYS =

Mapping of provider name to the env var that indicates it’s configured.

{
  "anthropic"   => "ANTHROPIC_API_KEY",
  "openai"      => "OPENAI_API_KEY",
  "gemini"      => "GEMINI_API_KEY",
  "azure"       => "AZURE_API_KEY",
  "bedrock"     => "AWS_ACCESS_KEY_ID",
  "deepseek"    => "DEEPSEEK_API_KEY",
  "mistral"     => "MISTRAL_API_KEY",
  "ollama"      => "OLLAMA_API_KEY",
  "openrouter"  => "OPENROUTER_API_KEY",
  "perplexity"  => "PERPLEXITY_API_KEY",
  "xai"         => "XAI_API_KEY",
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ REPL

Returns a new instance of REPL.



36
37
38
39
40
# File 'lib/brute_cli/repl.rb', line 36

def initialize(options = {})
  @execution = Execution.new(options)
  @terminal = @execution.terminal
  @saved_provider = nil  # stashed LLM provider symbol when in shell-mode agent
end

Class Method Details

.configured_providersObject

Returns an array of provider name strings that have API keys configured. Ollama is always included (it doesn’t strictly require a key for local use).



30
31
32
33
34
# File 'lib/brute_cli/repl.rb', line 30

def self.configured_providers
  configured = PROVIDER_ENV_KEYS.select { |_name, key| ENV[key] && !ENV[key].empty? }.keys
  configured << "ollama" unless configured.include?("ollama")
  configured.sort
end

Instance Method Details

#runObject

Start the interactive REPL loop.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/brute_cli/repl.rb', line 43

def run
  @execution.ensure_session!

  Banner.new(
    terminal:     @terminal,
    session_id:   @execution.session_id,
    session_path: @execution.session_path,
  )

  @execution.resolve_provider_info
  @input = UserInput.new(@terminal)

  loop do
    status = build_prompt_status
    result = @input.read_prompt(status)

    case result
    when nil
      break
    when ->(r) { r[:type] == :cycle_agent }
      handle_cycle_agent(result[:direction])
      @input.refresh_model_line(build_prompt_status)
      next
    when ->(r) { r[:type] == :input }
      text = result[:text]
      next if text.empty?
      break if %w[exit quit].include?(text)

      if Commands.match?(text)
        break if handle_command(text) == :exit
        next
      end

      @execution.run(text)
    end
  end
rescue Interrupt
  @terminal.buffer << ""
end