Commit 8d74a93
Changed files (2)
lib
elelem
lib/elelem/agent.rb
@@ -13,17 +13,54 @@ module Elelem
agent.quit if input.nil? || input.empty? || input == "exit"
configuration.conversation.add(role: "user", content: input)
+ agent.transition_to(ProcessingInput.new(configuration))
end
end
- class Agent
+ class ProcessingInput
attr_reader :configuration, :conversation, :tools
- attr_reader :current_state
def initialize(configuration)
@configuration = configuration
@conversation = configuration.conversation
@tools = configuration.tools
+ end
+
+ def run(agent)
+ done = false
+
+ loop do
+ configuration.api.chat(conversation.history, tools) do |chunk|
+ response = JSON.parse(chunk)
+ done = response["done"]
+ message = response["message"] || {}
+
+ if message["thinking"]
+ configuration.tui.say(message["thinking"], colour: :gray, newline: false)
+ elsif message["tool_calls"]&.any?
+ message["tool_calls"].each do |t|
+ conversation.add(role: "tool", content: tools.execute(t))
+ end
+ done = false
+ elsif message["content"].to_s.strip
+ configuration.tui.say(message["content"], colour: :default, newline: false)
+ else
+ raise chunk.inspect
+ end
+ end
+
+ break if done
+ end
+
+ agent.transition_to(Idle.new(configuration))
+ end
+ end
+
+ class Agent
+ attr_reader :configuration, :current_state
+
+ def initialize(configuration)
+ @configuration = configuration
transition_to(Idle.new(configuration))
end
@@ -32,8 +69,7 @@ module Elelem
end
def prompt(message)
- print(message)
- $stdin.gets&.chomp
+ configuration.tui.prompt(message)
end
def quit
@@ -43,31 +79,6 @@ module Elelem
def repl
loop do
current_state.run(self)
-
- done = false
- loop do
- configuration.api.chat(conversation.history, tools) do |chunk|
- response = JSON.parse(chunk)
- done = response["done"]
- message = response["message"] || {}
-
- if message["thinking"]
- print message["thinking"]
- elsif message["tool_calls"]&.any?
- message["tool_calls"].each do |t|
- conversation.add(role: "tool", content: tools.execute(t))
- end
- done = false
- elsif message["content"].to_s.strip
- print message["content"]
- else
- raise chunk.inspect
- end
- $stdout.flush
- end
-
- break if done
- end
end
end
end
lib/elelem/configuration.rb
@@ -1,6 +1,41 @@
# frozen_string_literal: true
module Elelem
+ class TUI
+ attr_reader :stdin, :stdout
+
+ def initialize(stdin = $stdin, stdout = $stdout)
+ @stdin = stdin
+ @stdout = stdout
+ end
+
+ def prompt(message)
+ say(message)
+ stdin.gets&.chomp
+ end
+
+ def say(message, colour: :default, newline: false)
+ formatted_message = colourize(message, colour: colour)
+ if newline
+ stdout.puts(formatted_message)
+ else
+ stdout.print(formatted_message)
+ end
+ stdout.flush
+ end
+
+ private
+
+ def colourize(text, colour: :default)
+ case colour
+ when :gray
+ "\e[90m#{text}\e[0m"
+ else
+ text
+ end
+ end
+ end
+
class Configuration
attr_reader :host, :model, :token, :debug
@@ -18,6 +53,10 @@ module Elelem
end
end
+ def tui
+ @tui ||= TUI.new
+ end
+
def api
@api ||= Api.new(self)
end