Class: PromptBuilder::Session
- Inherits:
-
Object
- Object
- PromptBuilder::Session
- Defined in:
- lib/prompt_builder/session.rb
Overview
The main DSL entry point for building Open Responses API request payloads. Manages conversation items, tool registration, and serialization to multiple API formats.
Instance Attribute Summary collapse
-
#background ⇒ Boolean?
Whether this is a background request.
-
#extra ⇒ Hash?
readonly
Provider-specific extra data for serializers.
-
#frequency_penalty ⇒ Float?
The frequency penalty.
-
#include ⇒ Array?
Fields to include in the response.
-
#instructions ⇒ String?
The system instructions.
-
#items ⇒ Array<Items::Base>
readonly
All conversation items.
-
#max_output_tokens ⇒ Integer?
The maximum output tokens.
-
#max_tool_calls ⇒ Integer?
The maximum number of tool calls.
-
#metadata ⇒ Hash?
Arbitrary metadata.
-
#model ⇒ String?
The model identifier.
-
#parallel_tool_calls ⇒ Boolean?
Whether parallel tool calls are enabled.
-
#presence_penalty ⇒ Float?
The presence penalty.
-
#previous_response_id ⇒ String?
The previous response identifier for server-side state.
-
#prompt_cache_key ⇒ String?
The prompt cache key.
-
#prompt_cache_retention ⇒ String?
The prompt cache retention policy.
-
#reasoning ⇒ Hash?
The reasoning configuration.
-
#response_boundary_index ⇒ Integer
readonly
The index in
itemsmarking the boundary after the last response. -
#safety_identifier ⇒ String?
The safety identifier.
-
#service_tier ⇒ String?
The service tier.
-
#store ⇒ Boolean?
Whether to store the response.
-
#stream ⇒ Boolean?
Whether to stream the response.
-
#stream_options ⇒ Hash?
Stream configuration options.
-
#temperature ⇒ Float?
The temperature.
-
#text ⇒ Hash?
Text output configuration.
-
#tool_choice ⇒ String, ...
The tool choice configuration.
-
#top_logprobs ⇒ Integer?
The number of top log probabilities to return.
-
#top_p ⇒ Float?
The top_p sampling parameter.
-
#truncation ⇒ String?
The truncation strategy.
Class Method Summary collapse
-
.from_h(hash) ⇒ Session
Deserialize a Session from a Hash produced by
to_hor parsed JSON.
Instance Method Summary collapse
-
#add_function_call_output(call_id:, result:) ⇒ Items::FunctionCallOutput
Add a tool call output to the conversation.
-
#add_item(item) ⇒ Items::Base
Add a raw item to the conversation.
-
#add_response(response) ⇒ void
Add a response to the conversation.
-
#assistant(content) ⇒ Items::Message
Add an assistant message to the conversation.
-
#clone_config ⇒ Session
Create a new Session with the same configuration and tools but no items.
-
#developer(content) ⇒ Items::Message
Add a developer message to the conversation.
-
#initialize(**attributes) ⇒ Session
constructor
Create a new Session with the given options.
-
#json_output(schema, name: "response", strict: nil, description: nil) ⇒ Hash
Configure JSON Schema structured output.
-
#local_state? ⇒ Boolean
Check if this session is in local state mode (no previous_response_id).
-
#register_tool(name, description: nil, parameters: nil, strict: false, **extra) ⇒ Tools::Definition
Register a tool on this session.
-
#register_tools(registry) ⇒ void
Register all tools from a ToolRegistry.
-
#request_payload(serializer_class) ⇒ Hash
Export this session to an alternate API format using the given serializer.
-
#system(content) ⇒ Items::Message
Add a system message to the conversation.
-
#think(enabled = true, effort: nil, budget_tokens: nil) ⇒ Hash?
Configure reasoning/extended thinking portably across serializers.
-
#to_h ⇒ Hash
Serialize to an Open Responses API request Hash with string keys.
-
#tool_definitions ⇒ Array<Tools::Definition>
Return all tool definitions registered on this session.
-
#use_tools(*names, registry: nil) ⇒ Array<Tools::Definition>
Copy tool definitions from a ToolRegistry onto this session by name.
-
#user(content) ⇒ Items::Message
Add a user message to the conversation.
Constructor Details
#initialize(**attributes) ⇒ Session
Create a new Session with the given options.
Accepts keyword arguments for all typed field groups (STRING_FIELDS,
FLOAT_FIELDS, INTEGER_FIELDS, BOOLEAN_FIELDS, JSONIFY_FIELDS); all default
to nil. The input (or user) shorthand auto-creates a user message
if provided. Unsupported keyword options raise an ArgumentError.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/prompt_builder/session.rb', line 171 def initialize(**attributes) unsupported = attributes.keys - INITIALIZE_OPTIONS unless unsupported.empty? raise ArgumentError, "unsupported option#{"s" if unsupported.size > 1}: #{unsupported.join(", ")}" end (STRING_FIELDS + FLOAT_FIELDS + INTEGER_FIELDS + BOOLEAN_FIELDS + JSONIFY_FIELDS).each do |f| send(:"#{f}=", attributes[f]) end @extra = PromptBuilder.jsonify(attributes[:extra]) if attributes[:extra] @items = [] @tool_definitions = {} @response_boundary_index = 0 user(attributes[:input]) if attributes[:input] end |
Instance Attribute Details
#background ⇒ Boolean?
Returns whether this is a background request.
96 97 98 99 100 |
# File 'lib/prompt_builder/session.rb', line 96 BOOLEAN_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v) } alias_method :"#{f}?", f end |
#extra ⇒ Hash? (readonly)
Returns provider-specific extra data for serializers. Recognized keys vary by target format. Unrecognized keys are silently ignored by each serializer.
128 129 130 |
# File 'lib/prompt_builder/session.rb', line 128 def extra @extra end |
#frequency_penalty ⇒ Float?
Returns the frequency penalty.
72 73 74 75 |
# File 'lib/prompt_builder/session.rb', line 72 FLOAT_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_f) } end |
#include ⇒ Array?
Returns fields to include in the response.
114 115 116 117 |
# File 'lib/prompt_builder/session.rb', line 114 JSONIFY_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : PromptBuilder.jsonify(v)) } end |
#instructions ⇒ String?
Returns the system instructions.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#items ⇒ Array<Items::Base> (readonly)
Returns all conversation items.
120 121 122 |
# File 'lib/prompt_builder/session.rb', line 120 def items @items end |
#max_output_tokens ⇒ Integer?
Returns the maximum output tokens.
83 84 85 86 |
# File 'lib/prompt_builder/session.rb', line 83 INTEGER_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_i) } end |
#max_tool_calls ⇒ Integer?
Returns the maximum number of tool calls.
83 84 85 86 |
# File 'lib/prompt_builder/session.rb', line 83 INTEGER_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_i) } end |
#metadata ⇒ Hash?
Returns arbitrary metadata.
114 115 116 117 |
# File 'lib/prompt_builder/session.rb', line 114 JSONIFY_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : PromptBuilder.jsonify(v)) } end |
#model ⇒ String?
Returns the model identifier.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#parallel_tool_calls ⇒ Boolean?
Returns whether parallel tool calls are enabled.
96 97 98 99 100 |
# File 'lib/prompt_builder/session.rb', line 96 BOOLEAN_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v) } alias_method :"#{f}?", f end |
#presence_penalty ⇒ Float?
Returns the presence penalty.
72 73 74 75 |
# File 'lib/prompt_builder/session.rb', line 72 FLOAT_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_f) } end |
#previous_response_id ⇒ String?
Returns the previous response identifier for server-side state.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#prompt_cache_key ⇒ String?
Returns the prompt cache key.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#prompt_cache_retention ⇒ String?
Returns the prompt cache retention policy.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#reasoning ⇒ Hash?
Returns the reasoning configuration.
114 115 116 117 |
# File 'lib/prompt_builder/session.rb', line 114 JSONIFY_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : PromptBuilder.jsonify(v)) } end |
#response_boundary_index ⇒ Integer (readonly)
Returns the index in items marking the boundary after the last response.
123 124 125 |
# File 'lib/prompt_builder/session.rb', line 123 def response_boundary_index @response_boundary_index end |
#safety_identifier ⇒ String?
Returns the safety identifier.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#service_tier ⇒ String?
Returns the service tier.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
#store ⇒ Boolean?
Returns whether to store the response.
96 97 98 99 100 |
# File 'lib/prompt_builder/session.rb', line 96 BOOLEAN_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v) } alias_method :"#{f}?", f end |
#stream ⇒ Boolean?
Returns whether to stream the response.
96 97 98 99 100 |
# File 'lib/prompt_builder/session.rb', line 96 BOOLEAN_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v) } alias_method :"#{f}?", f end |
#stream_options ⇒ Hash?
Returns stream configuration options.
114 115 116 117 |
# File 'lib/prompt_builder/session.rb', line 114 JSONIFY_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : PromptBuilder.jsonify(v)) } end |
#temperature ⇒ Float?
Returns the temperature.
72 73 74 75 |
# File 'lib/prompt_builder/session.rb', line 72 FLOAT_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_f) } end |
#text ⇒ Hash?
Returns text output configuration.
114 115 116 117 |
# File 'lib/prompt_builder/session.rb', line 114 JSONIFY_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : PromptBuilder.jsonify(v)) } end |
#tool_choice ⇒ String, ...
Returns the tool choice configuration.
114 115 116 117 |
# File 'lib/prompt_builder/session.rb', line 114 JSONIFY_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : PromptBuilder.jsonify(v)) } end |
#top_logprobs ⇒ Integer?
Returns the number of top log probabilities to return.
83 84 85 86 |
# File 'lib/prompt_builder/session.rb', line 83 INTEGER_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_i) } end |
#top_p ⇒ Float?
Returns the top_p sampling parameter.
72 73 74 75 |
# File 'lib/prompt_builder/session.rb', line 72 FLOAT_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_f) } end |
#truncation ⇒ String?
Returns the truncation strategy.
59 60 61 62 |
# File 'lib/prompt_builder/session.rb', line 59 STRING_FIELDS.each do |f| attr_reader f define_method(:"#{f}=") { |v| instance_variable_set(:"@#{f}", v.nil? ? nil : v.to_s) } end |
Class Method Details
.from_h(hash) ⇒ Session
Deserialize a Session from a Hash produced by to_h or parsed JSON.
Reconstructs all config fields and conversation items. Tool definitions
are restored without handlers; re-register handlers separately if you
need to invoke the tools.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/prompt_builder/session.rb', line 138 def from_h(hash) attrs = (STRING_FIELDS + FLOAT_FIELDS + INTEGER_FIELDS + BOOLEAN_FIELDS + JSONIFY_FIELDS) .each_with_object({}) { |f, acc| acc[f] = hash[f.to_s] } attrs[:extra] = hash["extra"] if hash["extra"] session = new(**attrs) Array(hash["input"]).each do |item_hash| session.add_item(Items::Base.from_h(item_hash)) end Array(hash["tools"]).each do |tool_hash| defn = Tools::Definition.from_h(tool_hash) extra = defn.extra.transform_keys(&:to_sym) session.register_tool(defn.name, description: defn.description, parameters: defn.parameters, strict: defn.strict, **extra) end session end |
Instance Method Details
#add_function_call_output(call_id:, result:) ⇒ Items::FunctionCallOutput
Add a tool call output to the conversation.
236 237 238 |
# File 'lib/prompt_builder/session.rb', line 236 def add_function_call_output(call_id:, result:) add_item(Items::FunctionCallOutput.new(call_id: call_id, output: result)) end |
#add_item(item) ⇒ Items::Base
Add a raw item to the conversation.
244 245 246 247 248 249 |
# File 'lib/prompt_builder/session.rb', line 244 def add_item(item) raise ArgumentError, "item must be an instance of Items::Base" unless item.is_a?(Items::Base) @items << item item end |
#add_response(response) ⇒ void
This method returns an undefined value.
Add a response to the conversation. Output items are always appended
to items so that the full history is available locally. When the
session is in server state mode (previous_response_id already set),
the id is also updated so to_h can use it as a serialization
optimization.
259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/prompt_builder/session.rb', line 259 def add_response(response) raise ArgumentError, "response must be an instance of Response" unless response.is_a?(Response) @items.concat(response.output) # Only refresh previous_response_id when the session is already in # server-state mode AND the response actually carries an id; otherwise # leave the existing pointer alone (responses from formats that don't # populate `id` would otherwise silently drop us back into local state). self.previous_response_id = response.id if !local_state? && response.id @response_boundary_index = @items.length end |
#assistant(content) ⇒ Items::Message
Add an assistant message to the conversation.
211 212 213 |
# File 'lib/prompt_builder/session.rb', line 211 def assistant(content) add_item(Items::Message.new(role: "assistant", content: content)) end |
#clone_config ⇒ Session
Create a new Session with the same configuration and tools but no items.
432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/prompt_builder/session.rb', line 432 def clone_config session = Session.new(**config_hash) @tool_definitions.each do |name, defn| extra = defn.extra.transform_keys(&:to_sym) session.register_tool( name, description: defn.description, parameters: defn.parameters, strict: defn.strict, **extra ) end session end |
#developer(content) ⇒ Items::Message
Add a developer message to the conversation.
227 228 229 |
# File 'lib/prompt_builder/session.rb', line 227 def developer(content) add_item(Items::Message.new(role: "developer", content: content)) end |
#json_output(schema, name: "response", strict: nil, description: nil) ⇒ Hash
Configure JSON Schema structured output. Writes the canonical
text.format wire hash consumed by all serializers, preserving any
other text keys (e.g. verbosity) already set.
361 362 363 364 365 366 |
# File 'lib/prompt_builder/session.rb', line 361 def json_output(schema, name: "response", strict: nil, description: nil) format = {"type" => "json_schema", "name" => name.to_s, "schema" => schema} format["strict"] = strict unless strict.nil? format["description"] = description.to_s if description self.text = (text || {}).merge("format" => format) end |
#local_state? ⇒ Boolean
Check if this session is in local state mode (no previous_response_id). This indicates that the full conversation history is stored in the session and will be sent with each request. Once a response with an id is added, the session switches to server state mode, where only new items after the last response are sent and the previous_response_id is used to reference the last response.
454 455 456 |
# File 'lib/prompt_builder/session.rb', line 454 def local_state? @previous_response_id.nil? end |
#register_tool(name, description: nil, parameters: nil, strict: false, **extra) ⇒ Tools::Definition
Register a tool on this session.
279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/prompt_builder/session.rb', line 279 def register_tool(name, description: nil, parameters: nil, strict: false, **extra) definition = Tools::Definition.new( name: name, description: description, parameters: parameters, strict: strict, **extra ) @tool_definitions[name] = definition definition end |
#register_tools(registry) ⇒ void
This method returns an undefined value.
Register all tools from a ToolRegistry.
295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/prompt_builder/session.rb', line 295 def register_tools(registry) raise ArgumentError, "registry must be an instance of ToolRegistry" unless registry.is_a?(ToolRegistry) registry.definitions.each do |defn| extra = defn.extra.transform_keys(&:to_sym) register_tool( defn.name, description: defn.description, parameters: defn.parameters, strict: defn.strict, **extra ) end end |
#request_payload(serializer_class) ⇒ Hash
Export this session to an alternate API format using the given serializer.
503 504 505 |
# File 'lib/prompt_builder/session.rb', line 503 def request_payload(serializer_class) Serializers.resolve(serializer_class).request_payload(self) end |
#system(content) ⇒ Items::Message
Add a system message to the conversation.
219 220 221 |
# File 'lib/prompt_builder/session.rb', line 219 def system(content) add_item(Items::Message.new(role: "system", content: content)) end |
#think(enabled = true, effort: nil, budget_tokens: nil) ⇒ Hash?
Configure reasoning/extended thinking portably across serializers.
Stores a normalized reasoning configuration; each serializer maps it
to its native parameter:
effort— Messages (+output_config.effort+), Chat Completions (+reasoning_effort+), Gemini (+thinkingConfig.thinkingLevel+), and Open Responses (+reasoning.effort+)budget_tokens— Messages (+thinking.budget_tokens+) and Gemini (+thinkingConfig.thinkingBudget+); ignored by effort-based APIs- Converse supports neither and warns once at serialization time
Pass either effort or budget_tokens, not both — providers reject
requests that set both controls. Direct session.reasoning = {...}
assignment keeps working for provider-specific keys.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/prompt_builder/session.rb', line 395 def think(enabled = true, effort: nil, budget_tokens: nil) unless enabled raise ArgumentError, "cannot combine think(false) with effort or budget_tokens" if effort || budget_tokens return self.reasoning = nil end if effort && budget_tokens raise ArgumentError, "pass either effort or budget_tokens, not both" elsif effort.nil? && budget_tokens.nil? raise ArgumentError, "think requires effort: or budget_tokens:" end if effort effort = effort.to_s unless THINK_EFFORT_LEVELS.include?(effort) raise ArgumentError, "effort must be one of: #{THINK_EFFORT_LEVELS.join(", ")}" end self.reasoning = {"effort" => effort} else budget_tokens = Integer(budget_tokens) raise ArgumentError, "budget_tokens must be positive" unless budget_tokens.positive? self.reasoning = {"budget_tokens" => budget_tokens} end end |
#to_h ⇒ Hash
Serialize to an Open Responses API request Hash with string keys.
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
# File 'lib/prompt_builder/session.rb', line 461 def to_h h = {} h["model"] = @model if @model h["instructions"] = @instructions if @instructions h["input"] = @items.map(&:to_h) unless @items.empty? h["previous_response_id"] = @previous_response_id if @previous_response_id h["tools"] = tool_definitions.map(&:to_h) unless @tool_definitions.empty? (STRING_FIELDS - %i[model instructions previous_response_id]).each do |f| val = send(f) h[f.to_s] = val if val end FLOAT_FIELDS.each { |f| val = send(f) h[f.to_s] = val if val } INTEGER_FIELDS.each { |f| val = send(f) h[f.to_s] = val if val } BOOLEAN_FIELDS.each { |f| val = send(f) h[f.to_s] = val unless val.nil? } JSONIFY_FIELDS.each { |f| val = send(f) h[f.to_s] = val if val } h["extra"] = @extra if @extra h end |
#tool_definitions ⇒ Array<Tools::Definition>
Return all tool definitions registered on this session.
425 426 427 |
# File 'lib/prompt_builder/session.rb', line 425 def tool_definitions @tool_definitions.values end |
#use_tools(*names, registry: nil) ⇒ Array<Tools::Definition>
Copy tool definitions from a ToolRegistry onto this session by name.
With no names, all tools in the registry are copied (same as
register_tools). Definitions are copied, so later registry changes do
not affect the session and the tools survive +to_h+/+from_h+ round-trips.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/prompt_builder/session.rb', line 324 def use_tools(*names, registry: nil) registry ||= PromptBuilder.tool_registry raise ArgumentError, "registry must be an instance of ToolRegistry" unless registry.is_a?(ToolRegistry) definitions = if names.empty? registry.definitions else names.map do |name| registry.definition_for(name.to_s) || raise(ToolNotFoundError, "No tool registered with name: #{name.to_s.inspect}") end end definitions.map do |defn| extra = defn.extra.transform_keys(&:to_sym) register_tool( defn.name, description: defn.description, parameters: defn.parameters, strict: defn.strict, **extra ) end end |
#user(content) ⇒ Items::Message
Add a user message to the conversation.
203 204 205 |
# File 'lib/prompt_builder/session.rb', line 203 def user(content) add_item(Items::Message.new(role: "user", content: content)) end |