Class: Kreator::InteractiveCLI

Inherits:
Object
  • Object
show all
Defined in:
lib/kreator/interactive_cli.rb

Defined Under Namespace

Classes: ChatModel, Command, Config, MatchedCommand, TranscriptEntry

Constant Summary collapse

PROMPT_MARKER =
"You"
DEFAULT_MODELS =
{
  "openai" => %w[gpt-4o-mini gpt-4o gpt-4.1-mini gpt-4.1],
  "anthropic" => %w[claude-3-5-haiku-latest claude-3-5-sonnet-latest claude-3-7-sonnet-latest]
}.freeze
COMMANDS =
[
  Command.new(pattern: %r{\A/(?:exit|quit)\z}, handler: :exit_command),
  Command.new(pattern: %r{\A/help\z}, handler: :help_command),
  Command.new(pattern: %r{\A/new\z}, handler: :new_session_command),
  Command.new(pattern: %r{\A/resume\z}, handler: :resume_recent_command),
  Command.new(pattern: %r{\A/model\s+(.+)\z}, handler: :select_model_command),
  Command.new(pattern: %r{\A/model\z}, handler: :current_model_command),
  Command.new(pattern: %r{\A/session\s+(.+)\z}, handler: :resume_session_command),
  Command.new(pattern: %r{\A/session\z}, handler: :current_session_command),
  Command.new(pattern: %r{\A/label\s+(.+)\z}, handler: :label_session_command),
  Command.new(pattern: %r{\A/search\s+(.+)\z}, handler: :search_sessions_command),
  Command.new(pattern: %r{\A/export(?:\s+(\S+))?\z}, handler: :export_session_command),
  Command.new(pattern: %r{\A/cleanup\z}, handler: :cleanup_empty_sessions_command),
  Command.new(pattern: %r{\A/branches\z}, handler: :branches_command),
  Command.new(pattern: %r{\A/fork\s+(\d+)\z}, handler: :fork_session_command),
  Command.new(pattern: %r{\A/prompts\z}, handler: :prompts_command),
  Command.new(pattern: %r{\A/skills\z}, handler: :skills_command),
  Command.new(pattern: %r{\A/(?:plugins|plugin list)\z}, handler: :plugins_command),
  Command.new(pattern: %r{\A/plugin\s+validate\s+(.+)\z}, handler: :validate_plugin_command),
  Command.new(pattern: %r{\A/prompt\s+(\S+)(?:\s+(.+))?\z}m, handler: :prompt_template_command),
  Command.new(pattern: %r{\A/compact\z}, handler: :compact_command)
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(config = nil) ⇒ InteractiveCLI

Returns a new instance of InteractiveCLI.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/kreator/interactive_cli.rb', line 51

def initialize(config = nil, **)
  config ||= Config.new(**)
  @provider_builder = config.provider_builder
  @provider_name = config.provider_name
  @model = config.model
  @tools = config.tools
  @context = config.context
  @session_manager = config.session_manager
  @session = config.session
  @stdin = config.stdin
  @stdout = config.stdout
  @stderr = config.stderr
  @resources = config.resources || Resources.new
  @compact_threshold = config.compact_threshold
end

Instance Method Details

#available_modelsObject



94
95
96
# File 'lib/kreator/interactive_cli.rb', line 94

def available_models
  (DEFAULT_MODELS.fetch(provider_name, []) | [model]).compact
end

#available_pluginsObject



110
111
112
# File 'lib/kreator/interactive_cli.rb', line 110

def available_plugins
  resources.plugins
end

#available_promptsObject



102
103
104
# File 'lib/kreator/interactive_cli.rb', line 102

def available_prompts
  resources.prompt_templates
end

#available_sessionsObject



98
99
100
# File 'lib/kreator/interactive_cli.rb', line 98

def available_sessions
  session_manager.list(cwd: Dir.pwd)
end

#available_skillsObject



106
107
108
# File 'lib/kreator/interactive_cli.rb', line 106

def available_skills
  resources.skills
end

#fork_session(entry_index) ⇒ Object



125
126
127
128
129
130
# File 'lib/kreator/interactive_cli.rb', line 125

def fork_session(entry_index)
  return system_line("Session persistence disabled") unless session

  @session = session_manager.fork(path: session.path, entry_index: entry_index)
  system_line("Forked session #{@session.id} from entry #{entry_index}")
end

#resume_session(path) ⇒ Object



120
121
122
123
# File 'lib/kreator/interactive_cli.rb', line 120

def resume_session(path)
  @session = @session_manager.open(path: path)
  system_line("Resumed session #{@session.id}")
end

#runObject



67
68
69
70
71
72
73
74
75
76
# File 'lib/kreator/interactive_cli.rb', line 67

def run
  return run_line_mode unless tty?

  load_charm!
  Bubbletea.run(ChatModel.new(runtime: self))
  0
rescue LoadError => e
  @stderr.puts "kreator: interactive mode requires Charm Ruby gems: #{e.message}"
  1
end

#select_model(model_name) ⇒ Object



114
115
116
117
118
# File 'lib/kreator/interactive_cli.rb', line 114

def select_model(model_name)
  @model = model_name
  @session&.append_model_change(provider: @provider_name, model: @model)
  system_line("Model set to #{@model}")
end

#submit(prompt) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/kreator/interactive_cli.rb', line 78

def submit(prompt)
  prompt = prompt.to_s.strip
  return [] if prompt.empty?

  command = matched_command(prompt)
  return send(command.handler, command.match) if command

  run_agent(prompt)
rescue StandardError => e
  [system_line("#{e.class}: #{e.message}")]
end

#transcriptObject



90
91
92
# File 'lib/kreator/interactive_cli.rb', line 90

def transcript
  messages.map { |message| format_message(message) }
end