test/openagents/providers/open_ai/request_payload_test.exs

main at 58e6347eeb72 · 4 KB

defmodule OpenAgents.Providers.OpenAI.RequestPayloadTest do
  use ExUnit.Case, async: true

  alias OpenAgents.Providers.{OpenAI, Request, ToolDefinition, ToolOutput}

  test "encodes a serial OpenResponses function-call continuation" do
    request = %Request{
      model_id: "test-model",
      instructions: "Remain OpenAgents.",
      input: [],
      previous_response_id: "resp_previous",
      tool_definitions: [
        %ToolDefinition{
          name: "recall_messages",
          description: "Recall messages",
          strict: true,
          input_schema: %{
            "type" => "object",
            "properties" => %{"query" => %{"type" => "string"}},
            "required" => ["query"],
            "additionalProperties" => false
          }
        }
      ],
      tool_outputs: [
        %ToolOutput{
          call_id: "call_123",
          output: %{"status" => "succeeded", "result" => %{"matches" => []}}
        }
      ]
    }

    payload = OpenAI.request_payload(request)

    assert payload.previous_response_id == "resp_previous"
    assert payload.parallel_tool_calls == false

    assert payload.tools == [
             %{
               type: "function",
               name: "recall_messages",
               description: "Recall messages",
               parameters: %{
                 "type" => "object",
                 "properties" => %{"query" => %{"type" => "string"}},
                 "required" => ["query"],
                 "additionalProperties" => false
               },
               strict: true
             }
           ]

    assert [output] = payload.input
    assert output.type == "function_call_output"
    assert output.call_id == "call_123"

    assert Jason.decode!(output.output) == %{
             "status" => "succeeded",
             "result" => %{"matches" => []}
           }
  end

  test "without a previous response, replays a tool call as its item pair in place" do
    request = %Request{
      model_id: "test-model",
      instructions: "Remain OpenAgents.",
      input: [
        %{role: "user", content: "Read the file."},
        %{
          role: "assistant",
          content: "",
          tool_calls: [
            %{call_id: "call_read", name: "read_file", arguments: ~s({"path":"a.txt"})}
          ]
        },
        %{role: "user", content: "And then?"}
      ],
      tool_outputs: [
        %ToolOutput{call_id: "call_read", output: %{"content" => "hello"}}
      ]
    }

    payload = OpenAI.request_payload(request)

    refute Map.has_key?(payload, :previous_response_id)

    assert [
             %{role: "user", content: "Read the file."},
             %{
               type: "function_call",
               call_id: "call_read",
               name: "read_file",
               arguments: ~s({"path":"a.txt"})
             },
             %{type: "function_call_output", call_id: "call_read", output: encoded_output},
             %{role: "user", content: "And then?"}
           ] = payload.input

    assert Jason.decode!(encoded_output) == %{"content" => "hello"}
  end

  test "without a previous response, an output whose call was not replayed still travels" do
    request = %Request{
      model_id: "test-model",
      instructions: "",
      input: [%{role: "user", content: "Continue."}],
      tool_outputs: [
        %ToolOutput{call_id: "call_orphan", output: %{"status" => "succeeded"}}
      ]
    }

    assert [
             %{role: "user", content: "Continue."},
             %{type: "function_call_output", call_id: "call_orphan", output: _output}
           ] = OpenAI.request_payload(request).input
  end

  test "maps multimodal user content to Responses input parts" do
    image_url = "data:image/png;base64,iVBORw0KGgo="

    request = %Request{
      model_id: "test-model",
      instructions: "",
      input: [
        %{
          role: "user",
          content: [
            %{type: "text", text: "Describe this image."},
            %{type: "image_url", image_url: %{url: image_url}}
          ]
        }
      ]
    }

    assert OpenAI.request_payload(request).input == [
             %{
               role: "user",
               content: [
                 %{type: "input_text", text: "Describe this image."},
                 %{type: "input_image", image_url: image_url}
               ]
             }
           ]
  end
end