Files
go-openai-realtime/client_event_test.go
zeekayandClaude Opus 5 410e64940f Go 1.27.1, and the code it can say more simply
Modules declare go 1.27.1 and the build images follow. go fix applied the
modernizers, and the examples print streamed deltas with Print instead of
using them as format strings; omitzero is not applied, since it changes
what the JSON says.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-16 19:21:06 -07:00

410 lines
11 KiB
Go

package openairt_test
import (
"encoding/json"
"testing"
"github.com/hanzoai/go-openai"
openairt "github.com/hanzoai/go-openai-realtime"
"github.com/hanzoai/go-openai/jsonschema"
"github.com/stretchr/testify/require"
)
func TestSessionUpdateEvent(t *testing.T) {
temperature := float32(0.5)
message := openairt.SessionUpdateEvent{
EventID: "test-id",
Session: openairt.ClientSession{
Modalities: []openairt.Modality{openairt.ModalityText, openairt.ModalityAudio},
Instructions: "test-instructions",
Voice: openairt.VoiceAlloy,
InputAudioFormat: openairt.AudioFormatPcm16,
OutputAudioFormat: openairt.AudioFormatG711Ulaw,
InputAudioTranscription: &openairt.InputAudioTranscription{
Model: openai.Whisper1,
},
TurnDetection: &openairt.ClientTurnDetection{
Type: openairt.ClientTurnDetectionTypeServerVad,
Threshold: 0.5,
PrefixPaddingMs: 1000,
SilenceDurationMs: 2000,
},
Tools: []openairt.Tool{
{
Type: openairt.ToolTypeFunction,
Name: "test-tool",
Parameters: jsonschema.Definition{
Type: "object",
Properties: map[string]jsonschema.Definition{
"location": {
Type: jsonschema.String,
},
},
Required: []string{"location"},
},
},
},
ToolChoice: openairt.ToolChoice{
Type: openairt.ToolTypeFunction,
Function: openairt.ToolFunction{
Name: "test-tool",
},
},
Temperature: &temperature,
MaxOutputTokens: 100,
},
}
// data, err := json.MarshalIndent(message, "", "\t")
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{
"event_id": "test-id",
"session": {
"modalities": [
"text",
"audio"
],
"instructions": "test-instructions",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "g711_ulaw",
"input_audio_transcription": {
"model": "whisper-1"
},
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 1000,
"silence_duration_ms": 2000
},
"tools": [
{
"type": "function",
"name": "test-tool",
"description": "",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string"
}
},
"required": [
"location"
]
}
}
],
"tool_choice": {
"type": "function",
"function": {
"name": "test-tool"
}
},
"temperature": 0.5,
"max_response_output_tokens": 100
},
"type": "session.update"
}`
require.JSONEq(t, expected, string(data))
message.Session.MaxOutputTokens = 0
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{
"event_id": "test-id",
"session": {
"modalities": [
"text",
"audio"
],
"instructions": "test-instructions",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "g711_ulaw",
"input_audio_transcription": {
"model": "whisper-1"
},
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 1000,
"silence_duration_ms": 2000
},
"tools": [
{
"type": "function",
"name": "test-tool",
"description": "",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string"
}
},
"required": [
"location"
]
}
}
],
"tool_choice": {
"type": "function",
"function": {
"name": "test-tool"
}
},
"temperature": 0.5
},
"type": "session.update"
}`
require.JSONEq(t, expected, string(data))
}
func TestSessionUpdateEventSimple(t *testing.T) {
temperature := float32(0.5)
message := openairt.SessionUpdateEvent{
Session: openairt.ClientSession{
Modalities: []openairt.Modality{openairt.ModalityText},
Instructions: "test-instructions",
Voice: openairt.VoiceAlloy,
InputAudioFormat: openairt.AudioFormatPcm16,
OutputAudioFormat: openairt.AudioFormatG711Ulaw,
InputAudioTranscription: nil,
TurnDetection: nil,
Tools: nil,
ToolChoice: nil,
Temperature: &temperature,
MaxOutputTokens: 100,
},
}
// data, err := json.MarshalIndent(message, "", "\t")
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{
"session": {
"modalities": [
"text"
],
"instructions": "test-instructions",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "g711_ulaw",
"turn_detection": null,
"temperature": 0.5,
"max_response_output_tokens": 100
},
"type": "session.update"
}`
require.JSONEq(t, expected, string(data))
}
func TestInputAudioBufferAppendEvent(t *testing.T) {
message := openairt.InputAudioBufferAppendEvent{
Audio: "test-audio",
}
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{"audio":"test-audio","type":"input_audio_buffer.append"}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","audio":"test-audio","type":"input_audio_buffer.append"}`
require.JSONEq(t, expected, string(data))
}
func TestInputAudioBufferCommitEvent(t *testing.T) {
message := openairt.InputAudioBufferCommitEvent{}
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{"type":"input_audio_buffer.commit"}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","type":"input_audio_buffer.commit"}`
require.JSONEq(t, expected, string(data))
}
func TestInputAudioBufferClearEvent(t *testing.T) {
message := openairt.InputAudioBufferClearEvent{}
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{"type":"input_audio_buffer.clear"}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","type":"input_audio_buffer.clear"}`
require.JSONEq(t, expected, string(data))
}
func TestConversationItemCreateEvent(t *testing.T) {
message := openairt.ConversationItemCreateEvent{
PreviousItemID: "test-previous-item-id",
Item: openairt.MessageItem{
ID: "test-id",
Type: openairt.MessageItemTypeMessage,
Status: openairt.ItemStatusCompleted,
Role: openairt.MessageRoleUser,
Content: []openairt.MessageContentPart{
{Type: openairt.MessageContentTypeText, Text: "test-content"},
{Type: openairt.MessageContentTypeAudio, Audio: "test-audio"},
{Type: openairt.MessageContentTypeTranscript, Transcript: "test-transcript"},
},
},
}
data, err := json.MarshalIndent(message, "", "\t")
require.NoError(t, err)
expected := `{
"previous_item_id": "test-previous-item-id",
"item": {
"id": "test-id",
"type": "message",
"status": "completed",
"role": "user",
"content": [
{
"type": "text",
"text": "test-content"
},
{
"type": "audio",
"audio": "test-audio"
},
{
"type": "transcript",
"transcript": "test-transcript"
}
]
},
"type": "conversation.item.create"
}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{
"event_id": "test-id",
"previous_item_id": "test-previous-item-id",
"item": {
"id": "test-id",
"type": "message",
"status": "completed",
"role": "user",
"content": [
{
"type": "text",
"text": "test-content"
},
{
"type": "audio",
"audio": "test-audio"
},
{
"type": "transcript",
"transcript": "test-transcript"
}
]
},
"type": "conversation.item.create"
}`
require.JSONEq(t, expected, string(data))
}
func TestConversationItemTruncateEvent(t *testing.T) {
message := openairt.ConversationItemTruncateEvent{
ItemID: "test-item-id",
ContentIndex: 1,
AudioEndMs: 2000,
}
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{"item_id":"test-item-id","content_index":1,"audio_end_ms":2000,"type":"conversation.item.truncate"}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","item_id":"test-item-id","content_index":1,"audio_end_ms":2000,"type":"conversation.item.truncate"}`
require.JSONEq(t, expected, string(data))
}
func TestConversationItemDeleteEvent(t *testing.T) {
message := openairt.ConversationItemDeleteEvent{
ItemID: "test-item-id",
}
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{"item_id":"test-item-id","type":"conversation.item.delete"}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","item_id":"test-item-id","type":"conversation.item.delete"}`
require.JSONEq(t, expected, string(data))
}
func TestResponseCreateEvent(t *testing.T) {
message := openairt.ResponseCreateEvent{
Response: openairt.ResponseCreateParams{
Modalities: []openairt.Modality{openairt.ModalityText, openairt.ModalityAudio},
Instructions: "test-instructions",
Voice: openairt.VoiceAlloy,
OutputAudioFormat: openairt.AudioFormatG711Ulaw,
Tools: nil,
ToolChoice: openairt.ToolChoiceAuto,
Temperature: nil,
MaxOutputTokens: 100,
},
}
data, err := json.MarshalIndent(message, "", "\t")
require.NoError(t, err)
expected := `{
"response": {
"modalities": [
"text",
"audio"
],
"instructions": "test-instructions",
"voice": "alloy",
"output_audio_format": "g711_ulaw",
"tool_choice": "auto",
"max_output_tokens": 100
},
"type": "response.create"
}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
message.Response.MaxOutputTokens = openairt.Inf
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","response":{"modalities":["text","audio"],"instructions":"test-instructions","voice":"alloy","output_audio_format":"g711_ulaw","tool_choice":"auto","max_output_tokens":"inf"},"type":"response.create"}`
require.JSONEq(t, expected, string(data))
}
func TestResponseCancelEvent(t *testing.T) {
message := openairt.ResponseCancelEvent{
ResponseID: "test-response-id",
}
data, err := json.Marshal(message)
require.NoError(t, err)
expected := `{"response_id":"test-response-id","type":"response.cancel"}`
require.JSONEq(t, expected, string(data))
message.EventBase.EventID = "test-id"
data, err = json.Marshal(message)
require.NoError(t, err)
expected = `{"event_id":"test-id","response_id":"test-response-id","type":"response.cancel"}`
require.JSONEq(t, expected, string(data))
}