Commit de2102c
Changed files (5)
lib
elelem
lib/elelem/agent.rb
@@ -2,14 +2,24 @@
module Elelem
class Agent
- attr_reader :configuration, :current_state
+ attr_reader :api, :conversation, :logger
def initialize(configuration)
+ @api = configuration.api
@configuration = configuration
+ @conversation = configuration.conversation
+ @logger = configuration.logger
transition_to(Idle.new)
end
+ def repl
+ loop do
+ current_state.run(self)
+ end
+ end
+
def transition_to(next_state)
+ logger.debug("Transition to: #{next_state.class.name}")
@current_state = next_state
end
@@ -22,17 +32,17 @@ module Elelem
end
def execute(tool_call)
+ logger.debug("Execute: #{tool_call}")
configuration.tools.execute(tool_call)
end
def quit
+ logger.debug("Exiting...")
exit
end
- def repl
- loop do
- current_state.run(self)
- end
- end
+ private
+
+ attr_reader :configuration, :current_state
end
end
lib/elelem/api.rb
@@ -17,6 +17,7 @@ module Elelem
options: { temperature: 0.1 },
tools: configuration.tools.to_h
}
+ configuration.logger.debug(JSON.pretty_generate(body))
json_body = body.to_json
req = Net::HTTP::Post.new(configuration.uri)
@@ -28,8 +29,7 @@ module Elelem
raise response.inspect unless response.code == "200"
response.read_body do |chunk|
- yield(chunk) if block_given?
- $stdout.flush
+ yield(chunk)
end
end
end
lib/elelem/configuration.rb
@@ -27,8 +27,8 @@ module Elelem
end
def logger
- @logger ||= Logger.new(debug ? $stderr : "/dev/null").tap do |logger|
- logger.formatter = ->(_, _, _, msg) { msg }
+ @logger ||= Logger.new(debug ? "elelem.log" : "/dev/null").tap do |logger|
+ logger.formatter = ->(_, _, _, message) { message.strip + "\n" }
end
end
lib/elelem/state.rb
@@ -3,22 +3,25 @@
module Elelem
class Idle
def run(agent)
+ agent.logger.debug("Idling...")
input = agent.prompt("\n> ")
agent.quit if input.nil? || input.empty? || input == "exit"
- agent.configuration.conversation.add(role: "user", content: input)
- agent.transition_to(ProcessingInput.new)
+ agent.conversation.add(role: "user", content: input)
+ agent.transition_to(Working.new)
end
end
- class ProcessingInput
- class Waiting
+ class Working
+ class State
attr_reader :agent
def initialize(agent)
@agent = agent
end
+ end
+ class Waiting < State
def process(message)
state = self
@@ -38,13 +41,7 @@ module Elelem
end
end
- class Thinking
- attr_reader :agent
-
- def initialize(agent)
- @agent = agent
- end
-
+ class Thinking < State
def process(message)
if message["thinking"]
agent.say(message["thinking"], colour: :gray, newline: false)
@@ -56,17 +53,11 @@ module Elelem
end
end
- class Executing
- attr_reader :agent
-
- def initialize(agent)
- @agent = agent
- end
-
+ class Executing < State
def process(message)
if message["tool_calls"]&.any?
message["tool_calls"].each do |tool_call|
- agent.configuration.conversation.add(role: "tool", content: agent.execute(tool_call))
+ agent.conversation.add(role: "tool", content: agent.execute(tool_call))
end
end
@@ -74,13 +65,7 @@ module Elelem
end
end
- class Talking
- attr_reader :agent
-
- def initialize(agent)
- @agent = agent
- end
-
+ class Talking < State
def process(message)
if message["content"]
agent.say(message["content"], colour: :default, newline: false)
@@ -93,13 +78,14 @@ module Elelem
end
def run(agent)
+ agent.logger.debug("Working...")
state = Waiting.new(agent)
loop do
- agent.configuration.api.chat(agent.configuration.conversation.history) do |chunk|
+ agent.api.chat(agent.conversation.history) do |chunk|
response = JSON.parse(chunk)
message = response["message"] || {}
-
+ agent.logger.debug("#{state.class.name}: #{message}")
state = state.process(message)
end
.gitignore
@@ -12,6 +12,7 @@
*.a
mkmf.log
target/
+*.log
# rspec failure tracking
.rspec_status