Class: AgentHarness::OpenAICompatibleTransport

Inherits:
Object
  • Object
show all
Defined in:
lib/agent_harness/openai_compatible_transport.rb

Overview

OpenAI-compatible HTTP transport for multi-turn chat completions.

Supports any endpoint that implements the OpenAI chat completions API, including OpenAI, GitHub Models, OpenRouter, and other compatible services.

Examples:

Non-streaming

transport = AgentHarness::OpenAICompatibleTransport.new(
  base_url: "https://api.openai.com/v1",
  api_key: "sk-...",
  model: "gpt-4o"
)
response = transport.chat(messages: [{ role: "user", content: "Hello" }])

Streaming

transport.chat(messages: msgs, stream: true) do |chunk|
  case chunk[:type]
  when :text    then print chunk[:content]
  when :usage   then puts "\nTokens: #{chunk[:input_tokens]}+#{chunk[:output_tokens]}"
  when :done    then puts "Stream complete"
  end
end

Constant Summary collapse

DEFAULT_TIMEOUT =
300
DEFAULT_MAX_TOKENS =
4096
USER_AGENT =
"AgentHarness/1.0"

Instance Method Summary collapse

Constructor Details

#initialize(base_url:, api_key:, model:, logger: nil) ⇒ OpenAICompatibleTransport

Returns a new instance of OpenAICompatibleTransport.

Parameters:

  • base_url (String)

    API base URL (e.g. “api.openai.com/v1”)

  • api_key (String)

    bearer token for authentication

  • model (String)

    default model identifier

  • logger (Logger, nil) (defaults to: nil)

    optional logger



38
39
40
41
42
43
# File 'lib/agent_harness/openai_compatible_transport.rb', line 38

def initialize(base_url:, api_key:, model:, logger: nil)
  @base_url = base_url.chomp("/")
  @api_key = api_key
  @model = model
  @logger = logger
end

Instance Method Details

#chat(messages:, tools: nil, stream: false, max_tokens: nil, temperature: nil, model: nil, on_chat_chunk: nil, observer: nil) {|Hash| ... } ⇒ Response

Send a chat completion request.

Streaming chunks can be received via block, on_chat_chunk proc, or an observer that responds to on_chat_chunk. When multiple receivers are provided, all receive every event.

Parameters:

  • messages (Array<Hash>)

    conversation messages

  • tools (Array<Hash>, nil) (defaults to: nil)

    tool/function definitions

  • stream (Boolean) (defaults to: false)

    whether to stream the response

  • max_tokens (Integer, nil) (defaults to: nil)

    maximum tokens in the response

  • temperature (Float, nil) (defaults to: nil)

    sampling temperature

  • model (String, nil) (defaults to: nil)

    model override for this request

  • on_chat_chunk (Proc, nil) (defaults to: nil)

    callback for structured streaming events

  • observer (#on_chat_chunk, nil) (defaults to: nil)

    observer receiving streaming events

Yields:

  • (Hash)

    streaming chunks when stream: true

Returns:

Raises:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/agent_harness/openai_compatible_transport.rb', line 65

def chat(messages:, tools: nil, stream: false, max_tokens: nil, temperature: nil,
  model: nil, on_chat_chunk: nil, observer: nil, &on_chunk)
  max_tokens ||= DEFAULT_MAX_TOKENS
  model ||= @model
  uri = URI("#{@base_url}/chat/completions")

  has_stream_receiver = on_chunk || on_chat_chunk || observer_responds_to?(observer, :on_chat_chunk)
  request_stream = stream && has_stream_receiver

  body = build_request_body(
    messages: messages, tools: tools, stream: request_stream,
    max_tokens: max_tokens, temperature: temperature, model: model
  )

  start_time = Time.now

  if request_stream
    combined = build_chat_chunk_callback(on_chunk, on_chat_chunk, observer)
    result = make_streaming_request(uri, body, &combined)
    duration = Time.now - start_time
    build_streaming_response(result, duration: duration, model: model)
  else
    http_response = make_request(uri, body)
    duration = Time.now - start_time
    parse_response(http_response, duration: duration, model: model)
  end
end