diff options
| author | mo khan <mo@mokhan.ca> | 2025-09-08 23:33:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-09-08 23:33:08 -0600 |
| commit | 59db135e1478c80203c834177831c2a43f481bde (patch) | |
| tree | c6cfc0d494b312bce0f2340db182da69b38373f8 | |
| parent | 3b06f576b888048becf8a667b9d7cf2efa14a529 (diff) | |
refactor: simplify code
| -rw-r--r-- | main.rb | 71 |
1 files changed, 27 insertions, 44 deletions
@@ -1,15 +1,14 @@ #!/usr/bin/env ruby # GPT-5 Action-Oriented Agent - pure stdlib -require "net/http" require "json" -require "uri" +require "net/http" require "reline" +require "uri" API_KEY = ENV["OPENAI_API_KEY"] or abort("Set OPENAI_API_KEY") -MODEL = "gpt-5" +MODEL = ENV["MODEL"] || "gpt-5" -# Tools GPT-5 can use TOOLS = [ { type: "function", @@ -49,40 +48,26 @@ TOOLS = [ } ] -# Execute tools def run_tool(name, args) case name when "read_file" - begin - { content: File.read(args["path"]) } - rescue => e - { error: e.message } - end + { content: File.read(args["path"]) } when "write_file" - begin - File.write(args["path"], args["content"]) - { status: "ok" } - rescue => e - { error: e.message } - end + { bytes_written: File.write(args["path"], args["content"]) } when "run_command" - begin - { output: `#{args["command"]}`.strip } - rescue => e - { error: e.message } - end + { output: `#{args["command"]}`.strip } else { error: "unknown tool #{name}" } end +rescue => e + { error: e.message } end -# Call OpenAI -def openai_chat(messages, tools) +def openai_chat(messages, tools, timeout: 60) uri = URI("https://api.openai.com/v1/chat/completions") req = Net::HTTP::Post.new(uri) req["Authorization"] = "Bearer #{API_KEY}" req["Content-Type"] = "application/json" - req.body = { model: MODEL, messages: messages, @@ -90,21 +75,21 @@ def openai_chat(messages, tools) tool_choice: "auto" }.to_json - res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) } + http = Net::HTTP.new(uri.hostname, uri.port) + http.use_ssl = true + http.open_timeout = timeout + http.read_timeout = timeout + http.write_timeout = timeout if http.respond_to?(:write_timeout=) + + res = http.start { |h| h.request(req) } + code = res.code.to_i + raise "HTTP #{res.code}: #{res.body}" unless res.is_a?(Net::HTTPSuccess) + JSON.parse(res.body) end -# Conversation with bias-for-action -messages = [ - { role: "system", content: <<~MSG - You are a reasoning coding and system agent. Prioritize taking practical actions whenever possible. - Use read_file, write_file, and run_command proactively to achieve user goals. - Explain your reasoning briefly in content. Avoid unnecessary delays; act whenever sufficient info is available. - MSG - } -] - +messages = [{ role: "system", content: "You are a reasoning coding and system agent." }] puts ">> Type instructions (or 'exit')" loop do @@ -113,20 +98,18 @@ loop do messages << { role: "user", content: input } loop do - resp = openai_chat(messages, TOOLS) - msg = resp.dig("choices", 0, "message") - messages << msg + message = openai_chat(messages, TOOLS).dig("choices", 0, "message") + messages << message - # Print reasoning content immediately - if msg["content"] && !msg["content"].empty? - puts "\nAssistant> #{msg['content']}" + if message["content"] && !message["content"].empty? + puts "\nAssistant> #{message['content']}" end - # Execute any tool calls - if msg["tool_calls"] - msg["tool_calls"].each do |call| + if message["tool_calls"] + message["tool_calls"].each do |call| name = call.dig("function","name") args = JSON.parse(call.dig("function","arguments")) + puts "Tool> ▶ #{name}(#{args})" result = run_tool(name, args) messages << { role: "tool", tool_call_id: call["id"], content: JSON.dump(result) } end |
