Skip to content
Open
66 changes: 66 additions & 0 deletions providers/internal/prompttest/cases.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ func Cases() []Case {
}},
},
},
{
Name: "user_text_file",
Model: "gpt-4o",
Prompt: fantasy.Prompt{
{Role: fantasy.MessageRoleUser, Content: []fantasy.MessagePart{
fantasy.TextPart{Text: "Summarize the notes."},
fantasy.FilePart{Filename: "notes.txt", MediaType: "text/plain", Data: []byte("hello")},
}},
},
},
{
Name: "user_unsupported_media",
Model: "gpt-4o",
Expand Down Expand Up @@ -307,6 +317,43 @@ func Cases() []Case {
}},
},
},
{
// A PDF result converts with the user file rules: a file part
// that keeps the tool's filename, in the deferred user message.
Name: "tool_result_media_pdf",
Model: "gpt-4o",
Prompt: fantasy.Prompt{
{Role: fantasy.MessageRoleAssistant, Content: []fantasy.MessagePart{
fantasy.ToolCallPart{ToolCallID: "c1", ToolName: "read", Input: "{}"},
}},
{Role: fantasy.MessageRoleTool, Content: []fantasy.MessagePart{
fantasy.ToolResultPart{ToolCallID: "c1", Output: fantasy.ToolResultOutputContentMedia{
Data: b64([]byte("%PDF-1.4")),
MediaType: "application/pdf",
Filename: "report.pdf",
}},
}},
},
},
{
// Text media is the exception to the user file rules, which would
// send it as a bare base64 file part that providers can reject.
// It gets the unsupported placeholder and warning instead.
Name: "tool_result_media_text",
Model: "gpt-4o",
Prompt: fantasy.Prompt{
{Role: fantasy.MessageRoleAssistant, Content: []fantasy.MessagePart{
fantasy.ToolCallPart{ToolCallID: "c1", ToolName: "read", Input: "{}"},
}},
{Role: fantasy.MessageRoleTool, Content: []fantasy.MessagePart{
fantasy.ToolResultPart{ToolCallID: "c1", Output: fantasy.ToolResultOutputContentMedia{
Data: b64([]byte("hello")),
MediaType: "text/plain",
Filename: "notes.txt",
}},
}},
},
},
{
// An unsupported media type still has to answer the tool_call, so
// the text message goes out alone with a warning naming the type.
Expand All @@ -324,6 +371,25 @@ func Cases() []Case {
}},
},
},
{
// Accompanying text is kept after the notice, which takes the
// media's place, so the model does not assume it saw the media
// the text describes.
Name: "tool_result_media_unsupported_with_text",
Model: "gpt-4o",
Prompt: fantasy.Prompt{
{Role: fantasy.MessageRoleAssistant, Content: []fantasy.MessagePart{
fantasy.ToolCallPart{ToolCallID: "c1", ToolName: "record", Input: "{}"},
}},
{Role: fantasy.MessageRoleTool, Content: []fantasy.MessagePart{
fantasy.ToolResultPart{ToolCallID: "c1", Output: fantasy.ToolResultOutputContentMedia{
Data: b64([]byte{1, 2, 3}),
MediaType: "video/mp4",
Text: "Recording of the session.",
}},
}},
},
},
{
// The ordering case from the media fix: a parallel batch must keep
// its tool messages contiguous.
Expand Down
37 changes: 37 additions & 0 deletions providers/internal/prompttest/testdata/tool_result_media_pdf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"openai,openaicompat,openrouter,vercel": {
"messages": [
{
"tool_calls": [
{
"id": "c1",
"function": {
"arguments": "{}",
"name": "read"
},
"type": "function"
}
],
"role": "assistant"
},
{
"content": "The tool returned application/pdf content; see the following user message.",
"tool_call_id": "c1",
"role": "tool"
},
{
"content": [
{
"file": {
"file_data": "data:application/pdf;base64,JVBERi0xLjQ=",
"filename": "report.pdf"
},
"type": "file"
}
],
"role": "user"
}
],
"warnings": []
}
}
27 changes: 27 additions & 0 deletions providers/internal/prompttest/testdata/tool_result_media_text.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"openai,openaicompat,openrouter,vercel": {
"messages": [
{
"tool_calls": [
{
"id": "c1",
"function": {
"arguments": "{}",
"name": "read"
},
"type": "function"
}
],
"role": "assistant"
},
{
"content": "The tool returned text/plain content, which cannot be displayed.",
"tool_call_id": "c1",
"role": "tool"
}
],
"warnings": [
"other: tool result media type text/plain not supported, sending text placeholder only"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"openai,openaicompat,openrouter,vercel": {
"messages": [
{
"tool_calls": [
{
"id": "c1",
"function": {
"arguments": "{}",
"name": "record"
},
"type": "function"
}
],
"role": "assistant"
},
{
"content": "The tool returned video/mp4 content, which cannot be displayed.\n\nRecording of the session.",
"tool_call_id": "c1",
"role": "tool"
}
],
"warnings": [
"other: tool result media type video/mp4 not supported, sending text placeholder only"
]
}
}
18 changes: 18 additions & 0 deletions providers/internal/prompttest/testdata/user_text_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"openai,openaicompat,openrouter,vercel": {
"messages": [
{
"content": [
{
"text": "Summarize the notes.",
"type": "text"
}
],
"role": "user"
}
],
"warnings": [
"other: file part media type text/plain not supported"
]
}
}
Loading
Loading