Class: Nanobot::CLI::Commands

Inherits:
Thor
  • Object
show all
Defined in:
lib/nanobot/cli/commands.rb

Overview

Thor-based CLI providing commands for onboarding, running the agent, serving as a multi-channel service, and checking status. rubocop:disable Metrics/ClassLength

Constant Summary collapse

CHANNEL_TYPES =

Maps channel config keys to their class names for dynamic loading.

{
  telegram: 'Telegram',
  discord: 'Discord',
  gateway: 'Gateway',
  slack: 'Slack',
  email: 'Email'
}.freeze
PROVIDER_NAMES =

Display names for known LLM providers.

{
  'anthropic' => 'Anthropic', 'openai' => 'OpenAI', 'gemini' => 'Gemini',
  'deepseek' => 'DeepSeek', 'openrouter' => 'OpenRouter', 'mistral' => 'Mistral',
  'ollama' => 'Ollama', 'perplexity' => 'Perplexity', 'xai' => 'xAI',
  'gpustack' => 'GPUStack', 'bedrock' => 'Bedrock', 'vertexai' => 'VertexAI',
  'groq' => 'Groq'
}.freeze
BOOTSTRAP_FILES =

Default workspace files created during onboarding.

{
  'AGENTS.md' => <<~CONTENT,
  'SOUL.md' => <<~CONTENT,
  'USER.md' => <<~CONTENT,
  'TOOLS.md' => <<~CONTENT,
  'IDENTITY.md' => <<~CONTENT
    # Agent Identity

    - Name: Nanobot
    - Creature: AI
    - Vibe: warm
    - Emoji: 🤖
    - Avatar: (workspace-relative path, URL, or data URI)
  CONTENT
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.exit_on_failure? ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
# File 'lib/nanobot/cli/commands.rb', line 17

def self.exit_on_failure?
  true
end

Instance Method Details

#agent ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/nanobot/cli/commands.rb', line 37

def agent
  agent_loop = build_agent_loop(model: options[:model], debug: options[:debug])

  if options[:message]
    run_single_message(agent_loop, options[:message])
  else
    run_interactive(agent_loop)
  end
end

#onboard ⇒ Object



22
23
24
25
26
27
28
29
30
31
# File 'lib/nanobot/cli/commands.rb', line 22

def onboard
  config_path = Config::Loader.get_config_path
  config = load_or_create_config(config_path)

  workspace = Pathname.new(config.agents.defaults.workspace).expand_path
  setup_workspace(workspace)
  create_bootstrap_files(workspace)

  print_onboard_instructions(config_path, workspace)
end

#serve ⇒ Object



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
# File 'lib/nanobot/cli/commands.rb', line 49

def serve
  config, bus, logger = load_runtime(debug: options[:debug])

  # Initialize scheduler
  schedule_store = Scheduler::ScheduleStore.new
  scheduler_service = nil
  if config.scheduler.enabled
    scheduler_service = Scheduler::SchedulerService.new(
      store: schedule_store, bus: bus, logger: logger,
      tick_interval: config.scheduler.tick_interval
    )
  end

  agent_loop = build_agent_loop_from(config, bus, logger, schedule_store: schedule_store)

  require_relative '../channels/manager'
  manager = Channels::Manager.new(config: config, bus: bus, logger: logger)
  register_channels(manager, config, bus, logger)
  manager.start_all

  # Start scheduler after channels so response routing has subscribers
  scheduler_service&.start

  setup_signal_traps(manager, agent_loop, logger, scheduler_service: scheduler_service)

  puts 'Nanobot service started. Press Ctrl+C to stop.'
  agent_loop.run
end

#status ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/nanobot/cli/commands.rb', line 79

def status
  config_path = Config::Loader.get_config_path

  unless config_path.exist?
    puts "Configuration not found. Run 'nanobot onboard' first."
    return
  end

  config = Config::Loader.load
  print_status(config, config_path)
end

#version ⇒ Object



92
93
94
# File 'lib/nanobot/cli/commands.rb', line 92

def version
  puts "Nanobot version #{Nanobot::VERSION}"
end