Commit de2102c

mo khan <mo@mokhan.ca>
2025-08-12 21:41:10
refactor: improve logging and output
1 parent 9b2ca20
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