mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-10 07:55:21 +02:00
Rework Assistant, Provider, and tests for better domain boundaries
This commit is contained in:
parent
56d78b50ce
commit
b9681d9cee
10 changed files with 420 additions and 212 deletions
|
@ -30,8 +30,8 @@ class Assistant
|
|||
result = fn.call(args)
|
||||
|
||||
ToolCall::Function.new(
|
||||
provider_id: function_request.provider_id,
|
||||
provider_call_id: function_request.provider_call_id,
|
||||
provider_id: function_request.id,
|
||||
provider_call_id: function_request.call_id,
|
||||
function_name: name,
|
||||
function_arguments: args,
|
||||
function_result: result
|
||||
|
@ -70,7 +70,19 @@ class Assistant
|
|||
ai_model: message.ai_model
|
||||
)
|
||||
|
||||
streamer = proc do |chunk|
|
||||
streamer2 = proc do |chunk|
|
||||
case chunk.type
|
||||
when "output_text"
|
||||
stop_thinking
|
||||
assistant_response.content += chunk.data
|
||||
assistant_response.save!
|
||||
when "response"
|
||||
stop_thinking
|
||||
chat.update!(latest_assistant_response_id: chunk.data.id)
|
||||
end
|
||||
end
|
||||
|
||||
streamer1 = proc do |chunk|
|
||||
case chunk.type
|
||||
when "output_text"
|
||||
stop_thinking
|
||||
|
@ -93,7 +105,7 @@ class Assistant
|
|||
instructions: instructions,
|
||||
functions: functions.map(&:to_h),
|
||||
function_results: tool_calls.map(&:to_h),
|
||||
streamer: streamer
|
||||
streamer: streamer2
|
||||
)
|
||||
else
|
||||
stop_thinking
|
||||
|
@ -109,7 +121,7 @@ class Assistant
|
|||
instructions: instructions,
|
||||
functions: functions.map(&:to_h),
|
||||
function_results: [],
|
||||
streamer: streamer
|
||||
streamer: streamer1
|
||||
)
|
||||
rescue => e
|
||||
chat.add_error(e)
|
||||
|
@ -151,7 +163,7 @@ class Assistant
|
|||
|
||||
- Format all responses in markdown
|
||||
- Format all monetary values according to the user's preferred currency
|
||||
- Format dates in the user's preferred format
|
||||
- Format dates in the user's preferred format: #{preferred_date_format}
|
||||
|
||||
#### User's preferred currency
|
||||
|
||||
|
@ -165,7 +177,6 @@ class Assistant
|
|||
- Default format: #{preferred_currency.default_format}
|
||||
- Separator: #{preferred_currency.separator}
|
||||
- Delimiter: #{preferred_currency.delimiter}
|
||||
- Date format: #{preferred_date_format}
|
||||
|
||||
### Rules about financial advice
|
||||
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
module Provider::LlmProvider
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def chat_response(message, instructions: nil, available_functions: [], streamer: nil)
|
||||
def chat_response(prompt, model:, instructions: nil, functions: [], function_results: [], streamer: nil, previous_response_id: nil)
|
||||
raise NotImplementedError, "Subclasses must implement #chat_response"
|
||||
end
|
||||
|
||||
private
|
||||
StreamChunk = Data.define(:provider_type, :data)
|
||||
ChatResponse = Data.define(:provider_id, :model, :messages, :function_calls) do
|
||||
def final?
|
||||
function_calls.empty?
|
||||
end
|
||||
end
|
||||
Message = Data.define(:provider_id, :content)
|
||||
FunctionCall = Data.define(:provider_id, :provider_call_id, :name, :arguments, :result)
|
||||
Message = Data.define(:id, :output_text)
|
||||
StreamChunk = Data.define(:type, :data)
|
||||
ChatResponse = Data.define(:id, :model, :messages, :function_requests)
|
||||
FunctionRequest = Data.define(:id, :call_id, :function_name, :function_args)
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Provider::Openai < Provider
|
||||
include LlmProvider
|
||||
include LlmProvider, Parser
|
||||
|
||||
# Subclass so errors caught in this provider are raised as Provider::Openai::Error
|
||||
Error = Class.new(Provider::Error)
|
||||
|
@ -14,10 +14,42 @@ class Provider::Openai < Provider
|
|||
MODELS.include?(model)
|
||||
end
|
||||
|
||||
def chat_response(prompt, model:, instructions: nil, functions: [], function_results: [], previous_response_id: nil)
|
||||
def chat_response(prompt, model:, instructions: nil, functions: [], function_results: [], streamer: nil, previous_response_id: nil)
|
||||
with_provider_response do
|
||||
proxy_streamer = proc do |chunk|
|
||||
type = chunk.dig("type")
|
||||
|
||||
case type
|
||||
when "response.output_text.delta", "response.refusal.delta"
|
||||
streamer.call(StreamChunk.new(type: "output_text", data: chunk.dig("delta")))
|
||||
when "response.completed"
|
||||
raw_response = chunk.dig("response")
|
||||
|
||||
messages = extract_messages(raw_response).map do |message|
|
||||
Message.new(
|
||||
id: message[:id],
|
||||
output_text: message[:output_text]
|
||||
)
|
||||
end
|
||||
|
||||
function_requests = extract_function_requests(raw_response).map do |function_request|
|
||||
FunctionRequest.new(
|
||||
id: function_request[:id],
|
||||
call_id: function_request[:call_id],
|
||||
function_name: function_request[:name],
|
||||
function_args: function_request[:arguments]
|
||||
)
|
||||
end
|
||||
|
||||
response = ChatResponse.new(
|
||||
id: extract_id(raw_response),
|
||||
model: extract_model(raw_response),
|
||||
messages: messages,
|
||||
function_requests: function_requests
|
||||
)
|
||||
|
||||
streamer.call(StreamChunk.new(type: "response", data: response))
|
||||
end
|
||||
end
|
||||
|
||||
function_results_input = function_results.map do |fn_result|
|
||||
|
@ -40,14 +72,37 @@ class Provider::Openai < Provider
|
|||
}
|
||||
end
|
||||
|
||||
client.responses.create(parameters: {
|
||||
raw_response = client.responses.create(parameters: {
|
||||
model: model,
|
||||
input: prompt_input + function_results_input,
|
||||
instructions: instructions,
|
||||
tools: tools,
|
||||
previous_response_id: previous_response_id,
|
||||
stream: streamer
|
||||
stream: streamer.present? ? proxy_streamer : nil
|
||||
})
|
||||
|
||||
messages = extract_messages(raw_response).map do |message|
|
||||
Message.new(
|
||||
id: message[:id],
|
||||
output_text: message[:output_text]
|
||||
)
|
||||
end
|
||||
|
||||
function_requests = extract_function_requests(raw_response).map do |function_request|
|
||||
FunctionRequest.new(
|
||||
id: function_request[:id],
|
||||
call_id: function_request[:call_id],
|
||||
function_name: function_request[:name],
|
||||
function_args: function_request[:arguments]
|
||||
)
|
||||
end
|
||||
|
||||
ChatResponse.new(
|
||||
id: extract_id(raw_response),
|
||||
model: extract_model(raw_response),
|
||||
messages: messages,
|
||||
function_requests: function_requests
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -19,19 +19,14 @@ class AssistantTest < ActiveSupport::TestCase
|
|||
test "responds to basic prompt" do
|
||||
text_chunk = OpenStruct.new(type: "output_text", data: "Hello from assistant")
|
||||
response_chunk = OpenStruct.new(
|
||||
type: "response",
|
||||
data: OpenStruct.new(
|
||||
id: "1",
|
||||
model: "gpt-4o",
|
||||
messages: [
|
||||
OpenStruct.new(
|
||||
id: "1",
|
||||
content: "Hello from assistant",
|
||||
)
|
||||
],
|
||||
functions: []
|
||||
type: "response",
|
||||
data: OpenStruct.new(
|
||||
id: "1",
|
||||
model: "gpt-4o",
|
||||
messages: [ OpenStruct.new(id: "1", output_text: "Hello from assistant") ],
|
||||
function_requests: []
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@provider.expects(:chat_response).with do |message, **options|
|
||||
options[:streamer].call(text_chunk)
|
||||
|
@ -45,37 +40,57 @@ class AssistantTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test "responds with tool function calls" do
|
||||
function_request_chunk = OpenStruct.new(type: "function_request", data: "get_net_worth")
|
||||
text_chunk = OpenStruct.new(type: "output_text", data: "Your net worth is $124,200")
|
||||
response_chunk = OpenStruct.new(
|
||||
Assistant::Function::GetAccounts.any_instance.stubs(:call).returns("test value")
|
||||
|
||||
# Call #1: Function requests
|
||||
call1_response_chunk = OpenStruct.new(
|
||||
type: "response",
|
||||
data: OpenStruct.new(
|
||||
id: "1",
|
||||
model: "gpt-4o",
|
||||
messages: [
|
||||
OpenStruct.new(
|
||||
id: "1",
|
||||
content: "Your net worth is $124,200",
|
||||
)
|
||||
],
|
||||
functions: [
|
||||
messages: [],
|
||||
function_requests: [
|
||||
OpenStruct.new(
|
||||
id: "1",
|
||||
call_id: "1",
|
||||
name: "get_net_worth",
|
||||
arguments: "{}",
|
||||
result: "$124,200"
|
||||
function_name: "get_accounts",
|
||||
function_arguments: "{}",
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# Call #2: Text response (that uses function results)
|
||||
call2_text_chunk = OpenStruct.new(type: "output_text", data: "Your net worth is $124,200")
|
||||
call2_response_chunk = OpenStruct.new(type: "response", data: OpenStruct.new(
|
||||
id: "2",
|
||||
model: "gpt-4o",
|
||||
messages: [ OpenStruct.new(id: "1", output_text: "Your net worth is $124,200") ],
|
||||
function_requests: [],
|
||||
function_results: [
|
||||
OpenStruct.new(
|
||||
provider_id: "1",
|
||||
provider_call_id: "1",
|
||||
name: "get_accounts",
|
||||
arguments: "{}",
|
||||
result: "test value"
|
||||
)
|
||||
],
|
||||
previous_response_id: "1"
|
||||
))
|
||||
|
||||
sequence = sequence("provider_chat_response")
|
||||
|
||||
@provider.expects(:chat_response).with do |message, **options|
|
||||
options[:streamer].call(function_request_chunk)
|
||||
options[:streamer].call(text_chunk)
|
||||
options[:streamer].call(response_chunk)
|
||||
options[:streamer].call(call2_text_chunk)
|
||||
options[:streamer].call(call2_response_chunk)
|
||||
true
|
||||
end
|
||||
end.returns(nil).once.in_sequence(sequence)
|
||||
|
||||
@provider.expects(:chat_response).with do |message, **options|
|
||||
options[:streamer].call(call1_response_chunk)
|
||||
true
|
||||
end.returns(nil).once.in_sequence(sequence)
|
||||
|
||||
assert_difference "AssistantMessage.count", 1 do
|
||||
@assistant.respond_to(@message)
|
||||
|
|
|
@ -6,16 +6,11 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
|
|||
setup do
|
||||
@subject = @openai = Provider::Openai.new(ENV.fetch("OPENAI_ACCESS_TOKEN", "test-openai-token"))
|
||||
@subject_model = "gpt-4o"
|
||||
@chat = chats(:two)
|
||||
end
|
||||
|
||||
test "openai errors are automatically raised" do
|
||||
VCR.use_cassette("openai/chat/error") do
|
||||
response = @openai.chat_response(UserMessage.new(
|
||||
chat: @chat,
|
||||
content: "Error test",
|
||||
ai_model: "invalid-model-that-will-trigger-api-error"
|
||||
))
|
||||
response = @openai.chat_response("Test", model: "invalid-model-that-will-trigger-api-error")
|
||||
|
||||
assert_not response.success?
|
||||
assert_kind_of Provider::Openai::Error, response.error
|
||||
|
@ -24,19 +19,14 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
|
|||
|
||||
test "basic chat response" do
|
||||
VCR.use_cassette("openai/chat/basic_response") do
|
||||
message = @chat.messages.create!(
|
||||
type: "UserMessage",
|
||||
content: "This is a chat test. If it's working, respond with a single word: Yes",
|
||||
ai_model: @subject_model
|
||||
response = @subject.chat_response(
|
||||
"This is a chat test. If it's working, respond with a single word: Yes",
|
||||
model: @subject_model
|
||||
)
|
||||
|
||||
response = @subject.chat_response(message)
|
||||
|
||||
assert response.success?
|
||||
assert_equal 1, response.data.size
|
||||
assert response.data.first.final?
|
||||
assert_equal 1, response.data.first.messages.size
|
||||
assert_includes response.data.first.messages.first.content, "Yes"
|
||||
assert_equal 1, response.data.messages.size
|
||||
assert_includes response.data.messages.first.output_text, "Yes"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -44,89 +34,120 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
|
|||
VCR.use_cassette("openai/chat/basic_streaming_response") do
|
||||
collected_chunks = []
|
||||
|
||||
mock_subscriber = proc do |chunk|
|
||||
mock_streamer = proc do |chunk|
|
||||
collected_chunks << chunk
|
||||
end
|
||||
|
||||
message = @chat.messages.create!(
|
||||
type: "UserMessage",
|
||||
content: "This is a chat test. If it's working, respond with a single word: Yes",
|
||||
ai_model: @subject_model
|
||||
@subject.chat_response(
|
||||
"This is a chat test. If it's working, respond with a single word: Yes",
|
||||
model: @subject_model,
|
||||
streamer: mock_streamer
|
||||
)
|
||||
|
||||
@subject.chat_response(message, stream_subscriber: mock_subscriber)
|
||||
|
||||
tool_call_chunks = collected_chunks.select { |chunk| chunk.provider_type == "function_request" }
|
||||
text_chunks = collected_chunks.select { |chunk| chunk.provider_type == "output_text" }
|
||||
response_chunks = collected_chunks.select { |chunk| chunk.provider_type == "response" }
|
||||
text_chunks = collected_chunks.select { |chunk| chunk.type == "output_text" }
|
||||
response_chunks = collected_chunks.select { |chunk| chunk.type == "response" }
|
||||
|
||||
assert_equal 1, text_chunks.size
|
||||
assert_equal 1, response_chunks.size
|
||||
assert_equal 0, tool_call_chunks.size
|
||||
assert_equal "Yes", text_chunks.first.data
|
||||
assert_equal "Yes", response_chunks.first.data.messages.first.content
|
||||
assert_equal "Yes", response_chunks.first.data.messages.first.output_text
|
||||
end
|
||||
end
|
||||
|
||||
test "chat response with tool calls" do
|
||||
VCR.use_cassette("openai/chat/tool_calls") do
|
||||
response = @subject.chat_response(
|
||||
tool_call_message,
|
||||
test "chat response with function calls" do
|
||||
VCR.use_cassette("openai/chat/function_calls") do
|
||||
first_response = @subject.chat_response(
|
||||
"What is my net worth?",
|
||||
model: @subject_model,
|
||||
instructions: "Use the tools available to you to answer the user's question.",
|
||||
available_functions: [ PredictableToolFunction.new(@chat) ]
|
||||
functions: [ PredictableToolFunction.new.to_h ]
|
||||
)
|
||||
|
||||
# Two responses: one for function requests, one follow-up for text output
|
||||
assert response.success?
|
||||
assert_equal 2, response.data.size
|
||||
assert first_response.success?
|
||||
|
||||
# First response has function requests / results
|
||||
assert_not response.data.first.final?
|
||||
assert_equal 1, response.data.first.function_calls.size
|
||||
function_request = first_response.data.function_requests.first
|
||||
|
||||
# Second response has text output that uses the function results
|
||||
assert response.data.last.final?
|
||||
assert_equal 0, response.data.last.function_calls.size
|
||||
assert_equal 1, response.data.last.messages.size
|
||||
assert_includes response.data.last.messages.first.content, PredictableToolFunction.expected_test_result
|
||||
assert function_request.present?
|
||||
|
||||
second_response = @subject.chat_response(
|
||||
"What is my net worth?",
|
||||
model: @subject_model,
|
||||
function_results: [
|
||||
{
|
||||
provider_id: function_request.id,
|
||||
provider_call_id: function_request.call_id,
|
||||
name: function_request.function_name,
|
||||
arguments: function_request.function_args,
|
||||
result: PredictableToolFunction.expected_test_result
|
||||
}
|
||||
],
|
||||
previous_response_id: first_response.data.id
|
||||
)
|
||||
|
||||
assert second_response.success?
|
||||
assert_equal 1, second_response.data.messages.size
|
||||
assert_includes second_response.data.messages.first.output_text, PredictableToolFunction.expected_test_result
|
||||
end
|
||||
end
|
||||
|
||||
test "streams chat response with tool calls" do
|
||||
VCR.use_cassette("openai/chat/streaming_tool_calls") do
|
||||
VCR.use_cassette("openai/chat/streaming_tool_calls", record: :all) do
|
||||
collected_chunks = []
|
||||
|
||||
mock_streamer = proc do |chunk|
|
||||
collected_chunks << chunk
|
||||
end
|
||||
|
||||
# Call #1: First streaming call, will return a function request
|
||||
@subject.chat_response(
|
||||
tool_call_message,
|
||||
"What is my net worth?",
|
||||
model: @subject_model,
|
||||
instructions: "Use the tools available to you to answer the user's question.",
|
||||
available_functions: [ PredictableToolFunction.new(@chat) ],
|
||||
functions: [ PredictableToolFunction.new.to_h ],
|
||||
streamer: mock_streamer
|
||||
)
|
||||
|
||||
text_chunks = collected_chunks.select { |chunk| chunk.provider_type == "output_text" }
|
||||
tool_call_chunks = collected_chunks.select { |chunk| chunk.provider_type == "function_request" }
|
||||
response_chunks = collected_chunks.select { |chunk| chunk.provider_type == "response" }
|
||||
text_chunks = collected_chunks.select { |chunk| chunk.type == "output_text" }
|
||||
response_chunks = collected_chunks.select { |chunk| chunk.type == "response" }
|
||||
|
||||
assert_equal 1, tool_call_chunks.count
|
||||
assert text_chunks.count >= 1
|
||||
assert_equal 2, response_chunks.count
|
||||
assert_equal 0, text_chunks.size
|
||||
assert_equal 1, response_chunks.size
|
||||
|
||||
assert_not response_chunks.first.data.final?
|
||||
assert response_chunks.last.data.final?
|
||||
assert_includes response_chunks.last.data.messages.first.content, PredictableToolFunction.expected_test_result
|
||||
first_response = response_chunks.first.data
|
||||
function_request = first_response.function_requests.first
|
||||
|
||||
# Reset collected chunks
|
||||
collected_chunks = []
|
||||
|
||||
# Call #2: Second streaming call, will return a function result
|
||||
@subject.chat_response(
|
||||
"What is my net worth?",
|
||||
model: @subject_model,
|
||||
function_results: [
|
||||
{
|
||||
provider_id: function_request.id,
|
||||
provider_call_id: function_request.call_id,
|
||||
name: function_request.function_name,
|
||||
arguments: function_request.function_args,
|
||||
result: PredictableToolFunction.expected_test_result
|
||||
}
|
||||
],
|
||||
previous_response_id: first_response.id,
|
||||
streamer: mock_streamer
|
||||
)
|
||||
|
||||
text_chunks = collected_chunks.select { |chunk| chunk.type == "output_text" }
|
||||
response_chunks = collected_chunks.select { |chunk| chunk.type == "response" }
|
||||
|
||||
assert text_chunks.size >= 1
|
||||
assert_equal 1, response_chunks.size
|
||||
|
||||
assert_includes response_chunks.first.data.messages.first.output_text, PredictableToolFunction.expected_test_result
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def tool_call_message
|
||||
UserMessage.new(chat: @chat, content: "What is my net worth?", ai_model: @subject_model)
|
||||
end
|
||||
|
||||
class PredictableToolFunction < Assistant::Function
|
||||
class PredictableToolFunction
|
||||
class << self
|
||||
def expected_test_result
|
||||
"$124,200"
|
||||
|
@ -144,5 +165,19 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
|
|||
def call(params = {})
|
||||
self.class.expected_test_result
|
||||
end
|
||||
|
||||
def to_h
|
||||
{
|
||||
name: self.class.name,
|
||||
description: self.class.description,
|
||||
params_schema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
required: [],
|
||||
additionalProperties: false
|
||||
},
|
||||
strict: true
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,7 +24,7 @@ http_interactions:
|
|||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Fri, 28 Mar 2025 14:23:22 GMT
|
||||
- Fri, 28 Mar 2025 23:39:00 GMT
|
||||
Content-Type:
|
||||
- application/json
|
||||
Transfer-Encoding:
|
||||
|
@ -36,34 +36,34 @@ http_interactions:
|
|||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_13900312235c86dca9983c43f884612f
|
||||
- req_689cf45740d3775a003632347b9a99dd
|
||||
Openai-Processing-Ms:
|
||||
- '1103'
|
||||
- '783'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=ZxtRGPPVT3H1qcGwlqfVjC13JJboKjEOkFsJoUfcduA-1743171802-1.0.1.1-PKolgwX6T_lqh6cFQXy9f3CPACskAir7Sfyt1ZNEKIHPDz3Ehn7lNILDASLxhBRmYBDKTMQqaUeyvSolvp1U00OhqfgSr51HxKIZNeEDglg;
|
||||
path=/; expires=Fri, 28-Mar-25 14:53:22 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=dxhkvZmDt5CfO7l2sGWpb8NwK.mPMPhQk2s4iFSZ8L4-1743205140-1.0.1.1-KJ6xz1oZ.qGlgSe.OAhABVxRSZDurVEDB4iFjzkrzEPT_cieb1YukIYJ_SK4hd_K6OrU2GgO9cn.1rTOUQLZdmzuS1GqRWn44is2Q8QdzZw;
|
||||
path=/; expires=Sat, 29-Mar-25 00:09:00 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=.uHFzkeaG4pJ9kcwsDW9PIfdKQgoEAz4Voe6QjxyH7E-1743171802602-0.0.1.1-604800000;
|
||||
- _cfuvid=LVN78sd.dSrLtZPVzcO8KZ9oDBKuC3_qGMfcWvwWsbY-1743205140700-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 9277c8eafdbe10c3-ORD
|
||||
- 927af6dbba55cf77-CMH
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: |-
|
||||
{
|
||||
"id": "resp_67e6b0d97d34819296bd4e0d24c6f3db00ff3778b60aa4aa",
|
||||
"id": "resp_67e73313e5ac8192b922490a56ce01e70bdc541b107b1aea",
|
||||
"object": "response",
|
||||
"created_at": 1743171801,
|
||||
"created_at": 1743205139,
|
||||
"status": "completed",
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
|
@ -73,7 +73,7 @@ http_interactions:
|
|||
"output": [
|
||||
{
|
||||
"type": "message",
|
||||
"id": "msg_67e6b0da49b48192a610e3f3493f056600ff3778b60aa4aa",
|
||||
"id": "msg_67e73314588881928506df6ae0995e700bdc541b107b1aea",
|
||||
"status": "completed",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
|
@ -103,7 +103,7 @@ http_interactions:
|
|||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 43,
|
||||
"input_tokens": 25,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
|
@ -111,10 +111,10 @@ http_interactions:
|
|||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 45
|
||||
"total_tokens": 27
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
recorded_at: Fri, 28 Mar 2025 14:23:22 GMT
|
||||
recorded_at: Fri, 28 Mar 2025 23:39:00 GMT
|
||||
recorded_with: VCR 6.3.1
|
||||
|
|
|
@ -24,7 +24,7 @@ http_interactions:
|
|||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Fri, 28 Mar 2025 15:39:24 GMT
|
||||
- Fri, 28 Mar 2025 23:38:59 GMT
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Transfer-Encoding:
|
||||
|
@ -36,57 +36,57 @@ http_interactions:
|
|||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_d322d0e3734ad9d7556c6acb446fc5f0
|
||||
- req_052d0a691b0e031851c4d3259a02d240
|
||||
Openai-Processing-Ms:
|
||||
- '108'
|
||||
- '182'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=i3l062va7vbmU7I3NufOoYNcofDavIJwJDRXwQ0CXck-1743176364-1.0.1.1-BWKA2yUjk0GI0pHrKSQ0eaTFa6Ysu5ysjy__ArpQaO1b3LEMatIliQ6rQEMN6M_eH7XfbV.nokO3hqCjRcg9yPgzKLjbQ3hpRcvQwMWObCE;
|
||||
path=/; expires=Fri, 28-Mar-25 16:09:24 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=YtPVnUeLdKYDtnmKDmgjZqr4sv2ZB5xVj_XbYgpG4X4-1743205139-1.0.1.1-OERpBfzzhUctMtyx6RnJBUiSH2R.iW0Kl7GL5IYUuL8Mz3J1sVPVkLWQnNb0NUjEi1a247UUAJzGTJp1Np07nxSUEMEmfIRj2wqQENwoxg8;
|
||||
path=/; expires=Sat, 29-Mar-25 00:08:59 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=1VMIq2Dlu_MQEWybPb9LkaURnoyi7_O2ueZQyKKUGss-1743176364050-0.0.1.1-604800000;
|
||||
- _cfuvid=KzP7deBboQLeJCUnhcX2p2DrFANiz7VPWoHgBXdtf4M-1743205139131-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 9278384d09ec0042-ORD
|
||||
- 927af6d5b9651267-ORD
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: |+
|
||||
event: response.created
|
||||
data: {"type":"response.created","response":{"id":"resp_67e6c2abe9188192aad5b26bece9136f0e544b3cddf93be3","object":"response","created_at":1743176363,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
data: {"type":"response.created","response":{"id":"resp_67e73312ebbc819296653e382c38b2de001b591cdf0f77e0","object":"response","created_at":1743205138,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","response":{"id":"resp_67e6c2abe9188192aad5b26bece9136f0e544b3cddf93be3","object":"response","created_at":1743176363,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
data: {"type":"response.in_progress","response":{"id":"resp_67e73312ebbc819296653e382c38b2de001b591cdf0f77e0","object":"response","created_at":1743205138,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"message","id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","status":"in_progress","role":"assistant","content":[]}}
|
||||
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"message","id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","status":"in_progress","role":"assistant","content":[]}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}
|
||||
data: {"type":"response.content_part.added","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"delta":"Yes"}
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"delta":"Yes"}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"text":"Yes"}
|
||||
data: {"type":"response.output_text.done","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"text":"Yes"}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Yes","annotations":[]}}
|
||||
data: {"type":"response.content_part.done","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Yes","annotations":[]}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"message","id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}}
|
||||
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"message","id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","response":{"id":"resp_67e6c2abe9188192aad5b26bece9136f0e544b3cddf93be3","object":"response","created_at":1743176363,"status":"completed","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"message","id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":43,"input_tokens_details":{"cached_tokens":0},"output_tokens":2,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":45},"user":null,"metadata":{}}}
|
||||
data: {"type":"response.completed","response":{"id":"resp_67e73312ebbc819296653e382c38b2de001b591cdf0f77e0","object":"response","created_at":1743205138,"status":"completed","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"message","id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":25,"input_tokens_details":{"cached_tokens":0},"output_tokens":2,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":27},"user":null,"metadata":{}}}
|
||||
|
||||
recorded_at: Fri, 28 Mar 2025 15:39:24 GMT
|
||||
recorded_at: Fri, 28 Mar 2025 23:38:59 GMT
|
||||
recorded_with: VCR 6.3.1
|
||||
...
|
||||
|
|
|
@ -5,8 +5,7 @@ http_interactions:
|
|||
uri: https://api.openai.com/v1/responses
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"model":"invalid-model-that-will-trigger-api-error","input":[{"role":"user","content":"Error
|
||||
test"}],"instructions":null,"tools":[],"previous_response_id":null,"stream":true}'
|
||||
string: '{"model":"invalid-model-that-will-trigger-api-error","input":[{"role":"user","content":"Test"}],"instructions":null,"tools":[],"previous_response_id":null,"stream":null}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json
|
||||
|
@ -24,7 +23,7 @@ http_interactions:
|
|||
message: Bad Request
|
||||
headers:
|
||||
Date:
|
||||
- Wed, 26 Mar 2025 21:27:19 GMT
|
||||
- Fri, 28 Mar 2025 23:39:02 GMT
|
||||
Content-Type:
|
||||
- application/json
|
||||
Content-Length:
|
||||
|
@ -36,25 +35,25 @@ http_interactions:
|
|||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_2b86e02f664e790dfa475f111402b722
|
||||
- req_9c80c15dd6b50d198b621a05e3dd3c9d
|
||||
Openai-Processing-Ms:
|
||||
- '146'
|
||||
- '115'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=gAU0gS_ZQBfQmFkc_jKM73dhkNISbBY9FlQjGnZ6CfU-1743024439-1.0.1.1-bWRoC737.SOJPZrP90wTJLVmelTpxFqIsrunq2Lqgy4J3VvLtYBEBrqY0v4d94F5fMcm0Ju.TfQi0etmvqZtUSMRn6rvkMLmXexRcxP.1jE;
|
||||
path=/; expires=Wed, 26-Mar-25 21:57:19 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=w8NWB2SOQcLDDgXm2hVuP3Ik71FMhI28xRfzC9U4SAo-1743205142-1.0.1.1-lDe_WqVCTDI1eF7W2.8tS6ErxBo1kX6lUjoMZh1fnpUzr.fyLJfLsFqiU31FuoYrqX1YOCLF6qUlUttZ5iZbuPSO5wPLkbNIMVVgSFG8flI;
|
||||
path=/; expires=Sat, 29-Mar-25 00:09:02 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=XnxX4KU80himuKAUavZYtkQasOjXJDJD.QLyMrfBSUU-1743024439792-0.0.1.1-604800000;
|
||||
- _cfuvid=VQL2pQzIck2z8GzmzR3ZFHfkya6Cd2TO82aGFDZDOBs-1743205142788-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 9269bb3b2c14cf74-CMH
|
||||
- 927af6ed3b7f1050-ORD
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
|
@ -68,5 +67,5 @@ http_interactions:
|
|||
"code": "model_not_found"
|
||||
}
|
||||
}
|
||||
recorded_at: Wed, 26 Mar 2025 21:27:19 GMT
|
||||
recorded_at: Fri, 28 Mar 2025 23:39:03 GMT
|
||||
recorded_with: VCR 6.3.1
|
||||
|
|
|
@ -26,7 +26,7 @@ http_interactions:
|
|||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Fri, 28 Mar 2025 14:26:28 GMT
|
||||
- Fri, 28 Mar 2025 23:39:03 GMT
|
||||
Content-Type:
|
||||
- application/json
|
||||
Transfer-Encoding:
|
||||
|
@ -38,34 +38,34 @@ http_interactions:
|
|||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_a248d37b03c551b1c46bd378bb1222df
|
||||
- req_acb002a07726b73124003bc11961db12
|
||||
Openai-Processing-Ms:
|
||||
- '844'
|
||||
- '692'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=z02SQd3cf0pSyMSllLTxVBBxPnoCRo.246XvQI3uWt8-1743171988-1.0.1.1-hR7THce0m_rGv7n1VCoCEziHmALE_MlWvIn6g3U70rjidYTqMkk4sui43cwZcBowvzGu51QGYgqGxYcNujkCU7otQh.6rJ7xwhluERZ1dVQ;
|
||||
path=/; expires=Fri, 28-Mar-25 14:56:28 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=yktQTGvoMAowiz7E3sLQgydW3Cy6tmHY_KGgLVGm.iE-1743205143-1.0.1.1-XGhvweZhPNRuqFMRcaIvMOyVb.Z1VOf4AtZmc4gPTArM1sU4T3mya2c0QwixjuCSJYuw2BwmWIKnZrDe_xdx6OtV6HQfwB1xASqg79FI6Bw;
|
||||
path=/; expires=Sat, 29-Mar-25 00:09:03 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=uydeMYssjSrN96Tp7VCbfJ_0P.t29RCD.hgjMqpo4Ys-1743171988305-0.0.1.1-604800000;
|
||||
- _cfuvid=I23nR.I1jT11eBu6591kDu2RxoXpHGpOn27Syvx7Zr8-1743205143976-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 9277cd78fa721167-ORD
|
||||
- 927af6f0ef5ccf7c-CMH
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: |-
|
||||
{
|
||||
"id": "resp_67e6b19371d08192912d64ea220597a40a63c04976d80348",
|
||||
"id": "resp_67e733174818819294a51c6bc4e0814c08d69b77f6076b69",
|
||||
"object": "response",
|
||||
"created_at": 1743171987,
|
||||
"created_at": 1743205143,
|
||||
"status": "completed",
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
|
@ -75,8 +75,8 @@ http_interactions:
|
|||
"output": [
|
||||
{
|
||||
"type": "function_call",
|
||||
"id": "fc_67e6b19421dc8192bea1cbade015ebf60a63c04976d80348",
|
||||
"call_id": "call_nSDlhJck6mchpjJ7YtjRLPJ3",
|
||||
"id": "fc_67e73317d104819287a21542e2484a4708d69b77f6076b69",
|
||||
"call_id": "call_IoG6NAK8MNIoY6x9bzfHnpp6",
|
||||
"name": "get_net_worth",
|
||||
"arguments": "{}",
|
||||
"status": "completed"
|
||||
|
@ -113,7 +113,7 @@ http_interactions:
|
|||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 271,
|
||||
"input_tokens": 55,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
|
@ -121,21 +121,19 @@ http_interactions:
|
|||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 284
|
||||
"total_tokens": 68
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
recorded_at: Fri, 28 Mar 2025 14:26:28 GMT
|
||||
recorded_at: Fri, 28 Mar 2025 23:39:03 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.openai.com/v1/responses
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"model":"gpt-4o","input":[{"role":"user","content":"What is my net
|
||||
worth?"},{"type":"function_call_output","call_id":"call_nSDlhJck6mchpjJ7YtjRLPJ3","output":"\"$124,200\""}],"instructions":"Use
|
||||
the tools available to you to answer the user''s question.","tools":[{"type":"function","name":"get_net_worth","description":"Gets
|
||||
user net worth data","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"previous_response_id":"resp_67e6b19371d08192912d64ea220597a40a63c04976d80348","stream":null}'
|
||||
worth?"},{"type":"function_call_output","call_id":"call_IoG6NAK8MNIoY6x9bzfHnpp6","output":"\"$124,200\""}],"instructions":null,"tools":[],"previous_response_id":"resp_67e733174818819294a51c6bc4e0814c08d69b77f6076b69","stream":null}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json
|
||||
|
@ -153,7 +151,7 @@ http_interactions:
|
|||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Fri, 28 Mar 2025 14:26:29 GMT
|
||||
- Fri, 28 Mar 2025 23:39:04 GMT
|
||||
Content-Type:
|
||||
- application/json
|
||||
Transfer-Encoding:
|
||||
|
@ -165,44 +163,44 @@ http_interactions:
|
|||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_f98ef29da61f92624043f8811022723f
|
||||
- req_107c55eac5d356ea6a092e179644be74
|
||||
Openai-Processing-Ms:
|
||||
- '955'
|
||||
- '666'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=c6fqCfvVVdaYCZkLcuE.7OouNNV80j6MO8EU00mTjrY-1743171989-1.0.1.1-ktPAaO3lTpJTpMCzUjPnsJmCc.30YWDEi4.yrCjvrrIULg.ipK29VdpexmtH_jo87DlQ1kndA3INl_gyhCra_zJYb0nJkfJD9vXkA6oHG3A;
|
||||
path=/; expires=Fri, 28-Mar-25 14:56:29 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=l1y3jPeCKUdL4YW9VR8SZAYbPJygY.O5iv8GEmHYyo0-1743205144-1.0.1.1-tuO_26bpHCwjp40gloE4Pu.Pi6wN7K9yV5rFTNDF.PhDjBb8N6TW5POC9qEhbSWWLzNV3nYn.U0E8ft3iXTOMX7i3mXGJOVb1t7TK6T5rVo;
|
||||
path=/; expires=Sat, 29-Mar-25 00:09:04 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=IZ3AyFlt2EHqyn4B4VQp_xuendIynQkbNd1EvOcjBIg-1743171989763-0.0.1.1-604800000;
|
||||
- _cfuvid=Vv42lFdIhJxtY593j4tNCHE5WmPd8d3kwT3Fe.CRYwU-1743205144880-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 9277cd7fba29e82d-ORD
|
||||
- 927af6f6affe114d-ORD
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: |-
|
||||
{
|
||||
"id": "resp_67e6b194cca08192af11a393c165ab300a63c04976d80348",
|
||||
"id": "resp_67e733182f5c8192917aa9ffaf3f26e508d69b77f6076b69",
|
||||
"object": "response",
|
||||
"created_at": 1743171988,
|
||||
"created_at": 1743205144,
|
||||
"status": "completed",
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": "Use the tools available to you to answer the user's question.",
|
||||
"instructions": null,
|
||||
"max_output_tokens": null,
|
||||
"model": "gpt-4o-2024-08-06",
|
||||
"output": [
|
||||
{
|
||||
"type": "message",
|
||||
"id": "msg_67e6b1957b5081928709cedc2b7d3f110a63c04976d80348",
|
||||
"id": "msg_67e73318a7448192b0cc40fd88d9881408d69b77f6076b69",
|
||||
"status": "completed",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
|
@ -215,7 +213,7 @@ http_interactions:
|
|||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": "resp_67e6b19371d08192912d64ea220597a40a63c04976d80348",
|
||||
"previous_response_id": "resp_67e733174818819294a51c6bc4e0814c08d69b77f6076b69",
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"generate_summary": null
|
||||
|
@ -228,35 +226,22 @@ http_interactions:
|
|||
}
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"description": "Gets user net worth data",
|
||||
"name": "get_net_worth",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": [],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"strict": true
|
||||
}
|
||||
],
|
||||
"tools": [],
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 309,
|
||||
"input_tokens": 51,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 11,
|
||||
"output_tokens": 10,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 320
|
||||
"total_tokens": 61
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
recorded_at: Fri, 28 Mar 2025 14:26:29 GMT
|
||||
recorded_at: Fri, 28 Mar 2025 23:39:04 GMT
|
||||
recorded_with: VCR 6.3.1
|
|
@ -26,7 +26,7 @@ http_interactions:
|
|||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Fri, 28 Mar 2025 16:00:21 GMT
|
||||
- Fri, 28 Mar 2025 23:39:20 GMT
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Transfer-Encoding:
|
||||
|
@ -38,51 +38,163 @@ http_interactions:
|
|||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_ad078d9f7585eeca17c02cefb4c42180
|
||||
- req_416a3bb3593376c1829980cc11557c9e
|
||||
Openai-Processing-Ms:
|
||||
- '148'
|
||||
- '171'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=DeYZEoQ8_t7.BWV67SmSSxrDr9sFE5nnkoANG7Nlg9E-1743177621-1.0.1.1-ymQrM3gryBLo9KRlSh4lzlyMPwqDX1SeHkwfiWOKaNct.cKs.WBfgURo.mAmK14ZjlbbuwfPOf7FShuzpS2Irud6C3woK9juoi2rOtdcYGo;
|
||||
path=/; expires=Fri, 28-Mar-25 16:30:21 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=2mv3jCpb0SZRXFvlWu28X1mr3Oa6z9QgwtmcclI9J_g-1743205160-1.0.1.1-1P22aYvtQqY_byLJMPyJEYff2m.rYivVXc313sCETck2g4NIg66SHPLTkjOiyqHBYMyifOJ_EVXNFK3QeEDYlPbvB9OzNr_Vo.S.UqPYpJI;
|
||||
path=/; expires=Sat, 29-Mar-25 00:09:20 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=WpIK2gkR1WKCUZWHMZKlTwVW73ibegrhn1ZhIpdswe0-1743177621976-0.0.1.1-604800000;
|
||||
- _cfuvid=KTcsmNHnsQWuGiwS1hyyOm7vtycPv3d6yh6pOLElMAg-1743205160250-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 92785706590bcf4e-CMH
|
||||
- 927af7582c5ffa19-ORD
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: |+
|
||||
event: response.created
|
||||
data: {"type":"response.created","response":{"id":"resp_67e6c795ca8c8192b015934c18b8abe602f810c3e60dc7d6","object":"response","created_at":1743177621,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
data: {"type":"response.created","response":{"id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","object":"response","created_at":1743205160,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","response":{"id":"resp_67e6c795ca8c8192b015934c18b8abe602f810c3e60dc7d6","object":"response","created_at":1743177621,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
data: {"type":"response.in_progress","response":{"id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","object":"response","created_at":1743205160,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"function_call","id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","call_id":"call_ZpaYGc3RGRfles9vnoFgVQ1m","name":"get_net_worth","arguments":"","status":"in_progress"}}
|
||||
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"function_call","id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","name":"get_net_worth","arguments":"","status":"in_progress"}}
|
||||
|
||||
event: response.function_call_arguments.delta
|
||||
data: {"type":"response.function_call_arguments.delta","item_id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","output_index":0,"delta":"{}"}
|
||||
data: {"type":"response.function_call_arguments.delta","item_id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","output_index":0,"delta":"{}"}
|
||||
|
||||
event: response.function_call_arguments.done
|
||||
data: {"type":"response.function_call_arguments.done","item_id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","output_index":0,"arguments":"{}"}
|
||||
data: {"type":"response.function_call_arguments.done","item_id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","output_index":0,"arguments":"{}"}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"function_call","id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","call_id":"call_ZpaYGc3RGRfles9vnoFgVQ1m","name":"get_net_worth","arguments":"{}","status":"completed"}}
|
||||
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"function_call","id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","name":"get_net_worth","arguments":"{}","status":"completed"}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","response":{"id":"resp_67e6c795ca8c8192b015934c18b8abe602f810c3e60dc7d6","object":"response","created_at":1743177621,"status":"completed","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"function_call","id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","call_id":"call_ZpaYGc3RGRfles9vnoFgVQ1m","name":"get_net_worth","arguments":"{}","status":"completed"}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":271,"input_tokens_details":{"cached_tokens":0},"output_tokens":13,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":284},"user":null,"metadata":{}}}
|
||||
data: {"type":"response.completed","response":{"id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","object":"response","created_at":1743205160,"status":"completed","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"function_call","id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","name":"get_net_worth","arguments":"{}","status":"completed"}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":55,"input_tokens_details":{"cached_tokens":0},"output_tokens":13,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":68},"user":null,"metadata":{}}}
|
||||
|
||||
recorded_at: Fri, 28 Mar 2025 16:00:23 GMT
|
||||
recorded_at: Fri, 28 Mar 2025 23:39:22 GMT
|
||||
- request:
|
||||
method: post
|
||||
uri: https://api.openai.com/v1/responses
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"model":"gpt-4o","input":[{"role":"user","content":"What is my net
|
||||
worth?"},{"type":"function_call_output","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","output":"\"$124,200\""}],"instructions":null,"tools":[],"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","stream":true}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json
|
||||
Authorization:
|
||||
- Bearer <OPENAI_ACCESS_TOKEN>
|
||||
Accept-Encoding:
|
||||
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
||||
Accept:
|
||||
- "*/*"
|
||||
User-Agent:
|
||||
- Ruby
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Fri, 28 Mar 2025 23:39:22 GMT
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Connection:
|
||||
- keep-alive
|
||||
Openai-Version:
|
||||
- '2020-10-01'
|
||||
Openai-Organization:
|
||||
- "<OPENAI_ORGANIZATION_ID>"
|
||||
X-Request-Id:
|
||||
- req_96db0e490c091fd28d3849cb2b7494dd
|
||||
Openai-Processing-Ms:
|
||||
- '127'
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Cf-Cache-Status:
|
||||
- DYNAMIC
|
||||
Set-Cookie:
|
||||
- __cf_bm=uCEzdEuc0NlONCs9_aE4Zlk_.gTSlFJ8f1Wih1A8C.4-1743205162-1.0.1.1-3O16QsxbyafPXR1z4aXLAf.s9MlH8j1NF_DLrC.5MvWO3j6c7X2Xao1ro6jiM8QSE62d5TnzfnWaqz.HPmtpaBOdD4l3r3Uf_7vKltr27T4;
|
||||
path=/; expires=Sat, 29-Mar-25 00:09:22 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=Daug1DTioODhGs.oCPbiMGRU8rN4cooGraWTg30zUH4-1743205162681-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
Server:
|
||||
- cloudflare
|
||||
Cf-Ray:
|
||||
- 927af7696faa10ee-ORD
|
||||
Alt-Svc:
|
||||
- h3=":443"; ma=86400
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: |+
|
||||
event: response.created
|
||||
data: {"type":"response.created","response":{"id":"resp_67e7332a89f48192a7c5da3f21bd48940c494b972720dd48","object":"response","created_at":1743205162,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","response":{"id":"resp_67e7332a89f48192a7c5da3f21bd48940c494b972720dd48","object":"response","created_at":1743205162,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"message","id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","status":"in_progress","role":"assistant","content":[]}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"Your"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" net"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" worth"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" is"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" $"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"124"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":","}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"200"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"."}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"text":"Your net worth is $124,200."}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Your net worth is $124,200.","annotations":[]}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"message","id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Your net worth is $124,200.","annotations":[]}]}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","response":{"id":"resp_67e7332a89f48192a7c5da3f21bd48940c494b972720dd48","object":"response","created_at":1743205162,"status":"completed","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"message","id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Your net worth is $124,200.","annotations":[]}]}],"parallel_tool_calls":true,"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":51,"input_tokens_details":{"cached_tokens":0},"output_tokens":10,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":61},"user":null,"metadata":{}}}
|
||||
|
||||
recorded_at: Fri, 28 Mar 2025 23:39:23 GMT
|
||||
recorded_with: VCR 6.3.1
|
||||
...
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue