Class: RubyLLM::Providers::OpenAIResponses

Inherits:
Provider
  • Object
show all
Includes:
Chat, Media, Models, Streaming, Tools
Defined in:
lib/ruby_llm/providers/openai_responses.rb,
lib/ruby_llm/providers/openai_responses/base.rb,
lib/ruby_llm/providers/openai_responses/chat.rb,
lib/ruby_llm/providers/openai_responses/batch.rb,
lib/ruby_llm/providers/openai_responses/media.rb,
lib/ruby_llm/providers/openai_responses/state.rb,
lib/ruby_llm/providers/openai_responses/tools.rb,
lib/ruby_llm/providers/openai_responses/models.rb,
lib/ruby_llm/providers/openai_responses/batches.rb,
lib/ruby_llm/providers/openai_responses/streaming.rb,
lib/ruby_llm/providers/openai_responses/background.rb,
lib/ruby_llm/providers/openai_responses/compaction.rb,
lib/ruby_llm/providers/openai_responses/containers.rb,
lib/ruby_llm/providers/openai_responses/web_socket.rb,
lib/ruby_llm/providers/openai_responses/capabilities.rb,
lib/ruby_llm/providers/openai_responses/built_in_tools.rb,
lib/ruby_llm/providers/openai_responses/chat_extension.rb,
lib/ruby_llm/providers/openai_responses/model_registry.rb,
lib/ruby_llm/providers/openai_responses/message_extension.rb,
lib/ruby_llm/providers/openai_responses/active_record_extension.rb,
lib/ruby_llm/providers/openai_responses/stream_accumulator_extension.rb

Overview

OpenAI Responses API provider for RubyLLM. Implements the new Responses API which provides built-in tools, stateful conversations, background mode, and MCP support.

This base file defines the class structure before modules are loaded to avoid “superclass mismatch” errors.

Defined Under Namespace

Modules: Background, Batches, BuiltInTools, Capabilities, Chat, ChatExtension, ChatLegacyMethodsExtension, ChatMethodsExtension, Compaction, Containers, Media, MessageExtension, MessageLegacyMethodsExtension, MessageMethodsExtension, ModelRegistry, Models, State, StreamAccumulatorExtension, Streaming, Tools Classes: Batch, WebSocket

Constant Summary

Constants included from Tools

Tools::BUILT_IN_TOOLS, Tools::EMPTY_PARAMETERS_SCHEMA

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Media

detect_audio_format, extract_filename, format_attachment, format_audio, format_image, format_pdf, format_text_file

Methods included from Models

models_url, parse_list_models_response

Methods included from Tools

apply_patch_tool, build_schema_from_parameters, code_interpreter_tool, file_search_tool, format_tool_calls, image_generation_tool, mcp_tool, parameters_schema_for, parse_tool_call_arguments, parse_tool_calls, schema_from_parameters, shell_tool, tool_for, web_search_preview_tool, web_search_tool

Methods included from Streaming

build_chunk, build_streaming_tool_call, parse_streaming_error, stream_url

Methods included from Chat

apply_tools, build_schema_format, build_tool_choice, #completion_url, extract_last_response_id, extract_output_text, extract_text_content, extract_tool_calls, format_input, format_message_content, format_role, parse_arguments, parse_completion_response, render_payload, unchained_messages

Class Method Details

.apply_active_record_extensions!Object

Apply ActiveRecord extensions for response_id persistence. Called automatically when ActiveRecord loads, or can be called manually.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/ruby_llm/providers/openai_responses/active_record_extension.rb', line 93

def self.apply_active_record_extensions!
  return if @active_record_extensions_applied

  applied = false

  # Try to apply to NEW modules (RubyLLM 2.0+)
  begin
    require 'ruby_llm/active_record/message_methods'
    require 'ruby_llm/active_record/chat_methods'

    RubyLLM::ActiveRecord::MessageMethods.prepend(MessageMethodsExtension)
    RubyLLM::ActiveRecord::ChatMethods.prepend(ChatMethodsExtension)
    applied = true
  rescue LoadError, NameError
    # New modules not available
  end

  # Try to apply to LEGACY modules (RubyLLM 1.x)
  begin
    require 'ruby_llm/active_record/acts_as_legacy'

    if defined?(RubyLLM::ActiveRecord::MessageLegacyMethods)
      RubyLLM::ActiveRecord::MessageLegacyMethods.prepend(MessageLegacyMethodsExtension)
    end

    if defined?(RubyLLM::ActiveRecord::ChatLegacyMethods)
      RubyLLM::ActiveRecord::ChatLegacyMethods.prepend(ChatLegacyMethodsExtension)
    end
    applied = true
  rescue LoadError, NameError
    # Legacy modules not available
  end

  @active_record_extensions_applied = applied
end

.capabilitiesObject



228
229
230
# File 'lib/ruby_llm/providers/openai_responses.rb', line 228

def capabilities
  OpenAIResponses::Capabilities
end

.configuration_requirementsObject



232
233
234
# File 'lib/ruby_llm/providers/openai_responses.rb', line 232

def configuration_requirements
  %i[openai_api_key]
end

.slugObject



236
237
238
# File 'lib/ruby_llm/providers/openai_responses.rb', line 236

def slug
  'openai_responses'
end

Instance Method Details

#api_baseObject



15
16
17
# File 'lib/ruby_llm/providers/openai_responses.rb', line 15

def api_base
  @config.openai_api_base || 'https://api.openai.com/v1'
end

#cancel_response(response_id) ⇒ Hash

Cancel a background response

Parameters:

  • response_id (String)

    The response ID to cancel

Returns:

  • (Hash)

    The cancellation result



52
53
54
55
# File 'lib/ruby_llm/providers/openai_responses.rb', line 52

def cancel_response(response_id)
  response = @connection.post(Background.cancel_url(response_id), {})
  response.body
end

#compact_response(model:, input:, **params) ⇒ Hash

Run an explicit compaction pass over a response input.

Parameters:

  • model (String)

    Model ID used for compaction

  • input (String, Array<Hash>)

    Response input items to compact

  • params (Hash)

    Additional Responses API parameters

Returns:

  • (Hash)

    Compacted response data



98
99
100
101
# File 'lib/ruby_llm/providers/openai_responses.rb', line 98

def compact_response(model:, input:, **params)
  response = @connection.post(Compaction.compact_url, { model: model, input: input }.merge(params))
  response.body
end

#complete(messages, tools:, temperature:, model:, params: {}, headers: {}, schema: nil, thinking: nil, tool_prefs: nil, &block) ⇒ Object

Override to support WebSocket transport via with_params(transport: :websocket). rubocop:disable Metrics/ParameterLists



21
22
23
24
25
26
27
28
29
30
# File 'lib/ruby_llm/providers/openai_responses.rb', line 21

def complete(messages, tools:, temperature:, model:, params: {}, headers: {},
             schema: nil, thinking: nil, tool_prefs: nil, &block)
  if params[:transport]&.to_sym == :websocket
    ws_complete(messages, tools: tools, temperature: temperature, model: model,
                          params: params.except(:transport), schema: schema,
                          thinking: thinking, &block)
  else
    super
  end
end

#count_input_tokens(model:, input:, **params) ⇒ Hash

Count input tokens for a Responses API request without creating a response.

Parameters:

  • model (String)

    Model ID used for tokenization

  • input (String, Array<Hash>)

    Response input

  • params (Hash)

    Additional Responses API parameters

Returns:

  • (Hash)

    Token count data



108
109
110
111
# File 'lib/ruby_llm/providers/openai_responses.rb', line 108

def count_input_tokens(model:, input:, **params)
  response = @connection.post(Compaction.input_tokens_url, { model: model, input: input }.merge(params))
  response.body
end

#create_container(name: nil, expires_after: nil, file_ids: nil, memory_limit: nil) ⇒ Hash

Create a new container

Parameters:

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

    Container name

  • expires_after (Hash, nil) (defaults to: nil)

    Expiry configuration

  • file_ids (Array<String>, nil) (defaults to: nil)

    File IDs to copy into container

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

    Memory limit: ‘1g’, ‘4g’, ‘16g’, ‘64g’

Returns:

  • (Hash)

    Created container data



121
122
123
124
125
126
127
128
# File 'lib/ruby_llm/providers/openai_responses.rb', line 121

def create_container(name: nil, expires_after: nil, file_ids: nil, memory_limit: nil)
  payload = Containers.create_payload(
    name: name, expires_after: expires_after,
    file_ids: file_ids, memory_limit: memory_limit
  )
  response = @connection.post(Containers.containers_url, payload)
  response.body
end

#delete_container(container_id) ⇒ Hash

Delete a container

Parameters:

  • container_id (String)

    The container ID

Returns:

  • (Hash)

    Deletion result



141
142
143
144
# File 'lib/ruby_llm/providers/openai_responses.rb', line 141

def delete_container(container_id)
  response = delete_request(Containers.container_url(container_id))
  response.body
end

#delete_response(response_id) ⇒ Hash

Delete a stored response

Parameters:

  • response_id (String)

    The response ID to delete

Returns:

  • (Hash)

    The deletion result



60
61
62
63
# File 'lib/ruby_llm/providers/openai_responses.rb', line 60

def delete_response(response_id)
  response = delete_request(Background.retrieve_url(response_id))
  response.body
end

#headersObject

rubocop:enable Metrics/ParameterLists



33
34
35
36
37
38
39
# File 'lib/ruby_llm/providers/openai_responses.rb', line 33

def headers
  {
    'Authorization' => "Bearer #{@config.openai_api_key}",
    'OpenAI-Organization' => @config.openai_organization_id,
    'OpenAI-Project' => @config.openai_project_id
  }.compact
end

#list_batches(limit: 20, after: nil) ⇒ Hash

List batches

Parameters:

  • limit (Integer) (defaults to: 20)

    Number of batches to return (default: 20)

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

    Cursor for pagination

Returns:

  • (Hash)

    Batch listing with ‘data’ array



178
179
180
181
182
183
184
185
186
# File 'lib/ruby_llm/providers/openai_responses.rb', line 178

def list_batches(limit: 20, after: nil)
  url = Batches.batches_url
  params = { limit: limit }
  params[:after] = after if after
  response = @connection.get(url) do |req|
    req.params.merge!(params)
  end
  response.body
end

#list_container_files(container_id) ⇒ Hash

List files in a container

Parameters:

  • container_id (String)

    The container ID

Returns:

  • (Hash)

    File listing



149
150
151
152
# File 'lib/ruby_llm/providers/openai_responses.rb', line 149

def list_container_files(container_id)
  response = @connection.get(Containers.container_files_url(container_id))
  response.body
end

#list_input_items(response_id) ⇒ Hash

List input items for a response

Parameters:

  • response_id (String)

    The response ID

Returns:

  • (Hash)

    The input items



68
69
70
71
# File 'lib/ruby_llm/providers/openai_responses.rb', line 68

def list_input_items(response_id)
  response = @connection.get(Background.input_items_url(response_id))
  response.body
end

#poll_response(response_id, interval: 1.0, timeout: nil) {|Hash| ... } ⇒ Hash

Poll a background response until completion

Parameters:

  • response_id (String)

    The response ID to poll

  • interval (Float) (defaults to: 1.0)

    Polling interval in seconds

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

    Maximum time to wait in seconds

Yields:

  • (Hash)

    Called with response data on each poll

Returns:

  • (Hash)

    The final response data



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/ruby_llm/providers/openai_responses.rb', line 79

def poll_response(response_id, interval: 1.0, timeout: nil)
  start_time = Time.now
  loop do
    response_data = retrieve_response(response_id)
    yield response_data if block_given?

    return response_data if Background.complete?(response_data)

    raise Error, "Polling timeout after #{timeout} seconds" if timeout && (Time.now - start_time) > timeout

    sleep interval
  end
end

#retrieve_container(container_id) ⇒ Hash

Retrieve a container by ID

Parameters:

  • container_id (String)

    The container ID

Returns:

  • (Hash)

    Container data



133
134
135
136
# File 'lib/ruby_llm/providers/openai_responses.rb', line 133

def retrieve_container(container_id)
  response = @connection.get(Containers.container_url(container_id))
  response.body
end

#retrieve_container_file(container_id, file_id) ⇒ Hash

Retrieve a specific file from a container

Parameters:

  • container_id (String)

    The container ID

  • file_id (String)

    The file ID

Returns:

  • (Hash)

    File metadata



158
159
160
161
# File 'lib/ruby_llm/providers/openai_responses.rb', line 158

def retrieve_container_file(container_id, file_id)
  response = @connection.get(Containers.container_file_url(container_id, file_id))
  response.body
end

#retrieve_container_file_content(container_id, file_id) ⇒ String

Get file content from a container

Parameters:

  • container_id (String)

    The container ID

  • file_id (String)

    The file ID

Returns:

  • (String)

    File content



167
168
169
170
# File 'lib/ruby_llm/providers/openai_responses.rb', line 167

def retrieve_container_file_content(container_id, file_id)
  response = @connection.get(Containers.container_file_content_url(container_id, file_id))
  response.body
end

#retrieve_response(response_id) ⇒ Hash

Retrieve a stored response by ID

Parameters:

  • response_id (String)

    The response ID to retrieve

Returns:

  • (Hash)

    The response data



44
45
46
47
# File 'lib/ruby_llm/providers/openai_responses.rb', line 44

def retrieve_response(response_id)
  response = @connection.get(Background.retrieve_url(response_id))
  response.body
end