-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathEvents.fs
More file actions
1097 lines (984 loc) · 38 KB
/
Copy pathEvents.fs
File metadata and controls
1097 lines (984 loc) · 38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
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
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
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
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
namespace rec RTOpenAI.Events
open System
open System.Text.Json
open System.Text.Json.Serialization
//generated by o1 from openai realtime api docs scraped from website
//default static properties added by github copilot
//default values added manually
(* Codegen notes
- o1 largely got all objects correct (almost 450 lines of code with no compile errors)
- However several corrections were needed to make event definitions correct as per API documentation
- Strongly typed properties and json converters added manually
- o1 missed response.audio_... and later events (maybe due to token limit set in the codegen api call)
- Update: Manually updated to match OpenAI realtime API version change
*)
/// Small helpers used across event types. Primarily exposes <see cref="M:RTOpenAI.Events.Utils.newId"/>
/// for generating URL-safe event IDs that round-trip cleanly through the OpenAI Realtime API.
module Utils =
/// Generate a short, URL-safe identifier suitable for the <c>event_id</c> field
/// on outgoing client events. Derived from a random GUID, then base64 encoded
/// with characters that have meaning in JSON or URLs (<c>/</c>, <c>\</c>, <c>+</c>)
/// remapped so the string is safe to embed without escaping.
let newId() =
Guid.NewGuid().ToByteArray()
|> Convert.ToBase64String
|> Seq.takeWhile (fun c -> c <> '=')
|> Seq.collect (function '/' -> ['_';'_'] | '\\' -> ['-';'-'] | '+' -> ['_';'-'] | c -> [c])
|> Seq.toArray
|> String
// Shared Types
type InputAudioTranscription =
{
model: string
}
static member Default = { model = "gpt-4o-mini-transcribe"}
type TurnDetection =
{
``type``: string option
threshold: float option
prefix_padding_ms: int option
silence_duration_ms: int option
}
static member Default = {
``type`` = Some "server_vad" // None to turn off
threshold = Some 0.5
prefix_padding_ms = Some 300 // How much audio to include in the audio stream before the speech starts.
silence_duration_ms = Some 200 //// How long to wait to mark the speech as stopped.
}
[<JsonFSharpConverter(SkippableOptionFields=SkippableOptionFields.Always)>]
type JsDesc = {description : string option}
[<JsonFSharpConverter(SkippableOptionFields=SkippableOptionFields.Always)>]
type JsString = {description : string option; enum : string list option}
[<JsonFSharpConverter(SkippableOptionFields=SkippableOptionFields.Always)>]
type JsObj =
{
description: string option
properties: Map<string, JsProperty>
required: string list
additionalProperties:bool
}
and [<JsonFSharpConverter(SkippableOptionFields=SkippableOptionFields.Always)>]
JsArray = {description: string option; items: JsProperty}
and [<RequireQualifiedAccess>]
JsProperty =
| [<JsonName "integer">] Integer of JsDesc
| [<JsonName "number">] Number of JsDesc
| [<JsonName "string">] String of JsString
| [<JsonName "boolean">] Boolean of JsDesc
| [<JsonName "array">] Array of JsArray
| [<JsonName "object">] Object of JsObj
type Parameters =
{
``type``: string
properties: Map<string, JsProperty>
required: string list
additionalProperties : bool
}
static member Default = { ``type`` = "object"; properties = Map.empty; required = []; additionalProperties = false }
type Tool =
{
name: string
description: string
parameters: Parameters
``type`` : string
}
static member Default = { ``type``= "function"; name = ""; description = ""; parameters = Parameters.Default}
type Client_Secret = {
expires_at : int64
value : string
}
[<JsonFSharpConverter>]
type Transcription = {
language : string
model : string
prompt : string option
}
[<JsonFSharpConverter(
BaseUnionEncoding = JsonUnionEncoding.InternalTag,
UnionTagName = "type",
UnionUnwrapRecordCases = true
)>]
//voice activity detection
type VAD =
| [<JsonName "server_vad">] Server_Vad of
{|create_response : bool
idle_timeout_ms : Skippable<int option>
interrupt_response : bool
prefix_padding_ms : int
silence_duration_ms : int
threshold : float
|}
| [<JsonName "semantic_vad">] Semantic_Vad of
{| create_response : bool
eagerness : string //high,medium,low, auto
interrupt_response : bool
|}
[<JsonFSharpConverter(
BaseUnionEncoding = JsonUnionEncoding.InternalTag,
UnionTagName = "type",
UnionUnwrapRecordCases = true
)>]
[<RequireQualifiedAccess>]
type AudioFormat =
| [<JsonName("audio/pcm")>] PCM of {|rate:int|} //24000
| [<JsonName("audio/pcmu")>] PCMU
| [<JsonName("audio/pcma")>] PCMA
type NoiseReduction = {``type`` : string}
[<JsonFSharpConverter>]
type AudioInput = {
format : AudioFormat
noise_reduction : Skippable<NoiseReduction option>
transcription : Skippable<Transcription option>
turn_detection : Skippable<VAD option>
}
with
static member Default =
{
noise_reduction = Skip
format = AudioFormat.PCM {|rate=24000|}
transcription = Skip
turn_detection = Skip
}
[<JsonFSharpConverter>]
type AudioOutput = {
format : AudioFormat
speed : Skippable<float option>
voice : string
}
with
static member Default =
{
format = AudioFormat.PCM {|rate=24000|}
speed = Include (Some 1.0)
voice = "alloy"
}
[<JsonFSharpConverter>]
type Audio = {
input: Skippable<AudioInput option>
output : Skippable<AudioOutput option> //don't need output for 'transcription' sessions
}
with
static member Default =
{
input = Skip
output = Skip
}
type Prompt = {
id : string
variables : Map<string,string>
version : string
}
[<JsonFSharpConverter(BaseUnionEncoding = JsonUnionEncoding.UnwrapRecordCases)>]
type Tracing =
| Auto
| Configuration of {|group_id:string; metadata:JsonElement; workflow_name:string |}
type TokenLimits = {
post_instructions : int
}
type OutputTokensTypeConverter() =
inherit JsonConverter<OutputTokens>()
override _.Read(reader, _, _) =
match reader.TokenType with
| JsonTokenType.String ->
match reader.GetString() with
| "inf" -> OutputTokens.Inf
| value -> OutputTokens.Value (Int32.Parse value)
| JsonTokenType.Number ->
let mutable value = 0
if reader.TryGetInt32(&value) then
OutputTokens.Value value
else
raise (JsonException("Expected max_output_tokens to be an integer or \"inf\"."))
| _ -> raise (JsonException("Expected max_output_tokens to be an integer or \"inf\"."))
override _.Write(writer, value, _) =
match value with
| Inf -> writer.WriteStringValue("inf")
| Value v -> writer.WriteNumberValue(v)
and [<JsonConverter(typeof<OutputTokensTypeConverter>)>]
OutputTokens =
| Inf
| Value of int
[<JsonFSharpConverter(BaseUnionEncoding = JsonUnionEncoding.UnwrapRecordCases)>]
type Truncation =
| [<JsonName "auto">] Auto
| [<JsonName "disabled">] Disabled
| Truncation of {|retention_ratio:float; ``type`` : string; token_limits : TokenLimits option|}
/// Realtime session configuration. Sent in <c>session.update</c> / returned in
/// <c>session.created</c> and <c>session.updated</c>. Most fields are
/// <see cref="T:Skippable`1"/> wrapping an <c>option</c>: use <c>Skip</c> to omit the
/// field, <c>Include None</c> to transmit <c>null</c>, and <c>Include (Some v)</c> to
/// set an explicit value.
[<JsonFSharpConverter>]
type Session =
{
``type`` : Skippable<string option>
id: Skippable<string option>
``object`` : Skippable<string option>
model: string option
audio : Skippable<Audio option>
``include`` : Skippable<string list option>
output_modalities: Skippable<string list option>
instructions: string option
prompt : Skippable<Prompt option>
tool_choice: Skippable<string option>
tools: Skippable<Tool list option>
tracing : Skippable<Tracing option>
truncation : Skippable<Truncation option>
max_output_tokens : Skippable<OutputTokens option>
client_secret : Skippable<Client_Secret option>
value : Skippable<string option>
expires_at : Skippable<int option>
}
static member Default =
{
``type`` = Include (Some "realtime")
id = Skip
``object`` = Skip
model = None
audio = Skip
``include`` = Include (Some [])
output_modalities = Skip
instructions = None
prompt = Skip
tool_choice = Skip //How the model chooses tools. Options are "auto", "none", "required", or specify a function.
tools = Skip
tracing = Skip
truncation = Skip
client_secret = Skip
max_output_tokens = Skip
value = Skip
expires_at = Skip
}
/// Unified shape used for both the client-side <c>response.create</c> payload and the
/// server-side <c>response</c> object returned in <c>response.created</c> /
/// <c>response.done</c>. Fields that apply only to one side are wrapped in
/// <see cref="T:Skippable`1"/> and default to <c>Skip</c>; populate them only where
/// the API documents them.
[<JsonFSharpConverter>]
type Response =
{
audio : Skippable<Audio option>
conversation : Skippable<string option>
conversation_id : Skippable<string option>
id : Skippable<string option>
input : Skippable<ConversationItem list option>
output : Skippable<ConversationItem list option>
instructions: Skippable<string option>
max_output_tokens : Skippable<OutputTokens option>
metadata : Skippable<Map<string,string> option>
output_modalities: Skippable<string list option>
prompt : Skippable<Prompt option>
tool_choice: Skippable<string option>
tools: Skippable<Tool list option>
object : Skippable<string option>
status : Skippable<string option>
status_details : Skippable<StatusDetails option>
usage : Skippable<Usage option>
}
static member Default : Response =
{
audio = Skip
id = Skip
conversation = Skip
conversation_id = Skip
input = Skip
output = Skip
instructions = Skip
max_output_tokens = Skip
metadata = Skip
output_modalities = Skip
prompt = Skip
tool_choice = Skip
tools = Skip
object = Skip
status = Skip
status_details = Skip
usage = Skip
}
type ErrorDetail =
{
``type``: string
code: string
message: string
param: Skippable<string option>
event_id: Skippable<string option>
}
static member Default = { ``type`` = ""; code = ""; message = ""; param = Skip; event_id = Skip }
type Usage = {
``type`` : Skippable<string option>
total_tokens : int
input_tokens : int
output_tokens : int
input_token_details : {|text_tokens:int; audio_tokens:int|}
}
with static member Default = { total_tokens = 0; input_tokens = 0; output_tokens = 0; input_token_details ={|text_tokens=0; audio_tokens=0|}; ``type`` = Include (Some "tokens")}
/// Patch the session's default configuration for future turns.
///
/// Send this whenever the client needs to change defaults such as instructions, tools,
/// audio settings, truncation, or turn detection. Only fields present in `session` are
/// updated; empty strings, empty arrays, and `null` clear existing values. These session
/// defaults are used unless a later `response.create` overrides them for one response.
[<JsonFSharpConverter>]
type SessionUpdate =
{
event_id: string
``type``: string // "session.update"
session: Session
}
static member Default = { event_id = ""; ``type`` = "session.update"; session = Session.Default }
/// Append audio bytes to the temporary input audio buffer.
///
/// Send this while streaming microphone audio. The buffer is later turned into a user
/// message by `input_audio_buffer.commit`, or committed automatically when server-side
/// turn detection is enabled. The server does not send an acknowledgement for each append.
type InputAudioBufferAppend =
{
event_id: string
``type``: string // "input_audio_buffer.append"
audio: string // Base64 encoded audio data
}
static member Default = { event_id = ""; ``type`` = "input_audio_buffer.append"; audio = "" }
/// Commit buffered audio into a new user message item.
///
/// Send this after the user finishes speaking when server-side VAD is off, or when the
/// client wants to force an early commit. This creates the user message and can trigger
/// input transcription, but it does not itself ask the model to respond.
type InputAudioBufferCommit =
{
event_id: string
``type``: string // "input_audio_buffer.commit"
}
static member Default = { event_id = ""; ``type`` = "input_audio_buffer.commit" }
/// Discard any uncommitted audio bytes in the input buffer.
///
/// Send this when buffered microphone audio should be dropped instead of committed into
/// conversation history. The server replies with `input_audio_buffer.cleared`.
type InputAudioBufferClear =
{
event_id: string
``type``: string // "input_audio_buffer.clear"
}
static member Default = { event_id = ""; ``type`` = "input_audio_buffer.clear" }
/// Add a new item to the conversation context.
///
/// Send this to seed prior history, insert a message/function item mid-conversation, or
/// otherwise add context before requesting inference. If `previous_item_id` is omitted the
/// item is appended; `root` inserts at the start. Current OpenAI limitation: this cannot
/// populate assistant audio messages.
type ConversationItemCreate =
{
event_id: string
``type``: string // "conversation.item.create"
previous_item_id: Skippable<string option>
item: ConversationItem
}
static member Default = { event_id = ""
``type`` = "conversation.item.create"
previous_item_id = Skip
item = ConversationItem.Message ContentMessage.Default
}
/// Retrieve the server's stored representation of a conversation item.
///
/// Send this when the client needs the canonical item as stored by OpenAI, for example to
/// inspect user audio after server-side noise reduction and VAD have been applied.
type ConversationItemRetrieve =
{
event_id: string
item_id : string
``type``: string // "conversation.item.retrieve"
}
static member Default = { event_id = ""; ``type`` = "conversation.item.retrieve"; item_id = ""}
/// Truncate audio that was already generated for an assistant message.
///
/// Send this when the user interrupts playback and the server has produced audio that the
/// client has not finished playing yet. This keeps server context aligned with playback and
/// removes the corresponding server-side transcript so unheard text does not remain in context.
/// Only assistant message items can be truncated, and OpenAI expects `content_index = 0`.
type ConversationItemTruncate =
{
event_id: string
``type``: string // "conversation.item.truncate"
item_id: string
content_index: int
audio_end_ms: int
}
static member Default = { event_id = ""; ``type`` = "conversation.item.truncate"; item_id = ""; content_index = 0; audio_end_ms = 0 }
/// WebRTC/SIP only: cut off output audio that is already buffered for playback.
///
/// Send this immediately after `response.cancel` when cancelling generation is not enough and
/// the client also needs already-buffered output audio to stop. The server replies with
/// `output_audio_buffer.cleared`.
type OutputAudioBufferClear = {
event_id : string
``type`` : string
}
with static member Default = {event_id=""; ``type``="output_audio_buffer.clear"}
/// Remove an item from the conversation history.
///
/// Send this to retract a previously stored item from model context. The server replies with
/// `conversation.item.deleted` if the item exists.
type ConversationItemDelete =
{
event_id: string
``type``: string // "conversation.item.delete"
item_id: string
}
static member Default = { event_id = ""; ``type`` = "conversation.item.delete"; item_id = "" }
/// Trigger model inference to create a response.
///
/// Send this when the model should answer now, especially if turn detection is disabled or
/// automatic response creation is turned off. Values inside `response` override the session
/// defaults for this response only, and the request can also run out-of-band from the default
/// conversation.
type ResponseCreate =
{
event_id: string
``type``: string // "response.create"
response: Skippable<Response option>
}
static member Default = { event_id = ""; ``type`` = "response.create"; response = Skip }
/// Cancel an in-progress response.
///
/// Send this when the user interrupts, navigates away, or the pending answer is no longer
/// wanted. If `response_id` is omitted, OpenAI cancels the active response in the default
/// conversation; otherwise the targeted response is cancelled.
type ResponseCancel =
{
event_id: string
``type``: string // "response.cancel"
response_id: Skippable<string option>
}
static member Default = { event_id = ""; ``type`` = "response.cancel"; response_id = Skip }
[<JsonFSharpConverter>]
type MessageAudioContent =
{
audio: Skippable<string option>
transcript: Skippable<string option>
format: Skippable<JsonElement option>
}
[<JsonFSharpConverter>]
type MessageTextContent =
{
text: Skippable<string option>
annotations: Skippable<JsonElement option>
}
type MessageContent =
| [<JsonName("input_audio")>] Input_audio of {|audio:Skippable<string option>; transcript:string|}
| [<JsonName("input_text")>] Input_text of {|text:string|}
| [<JsonName("input_image")>] Input_image of {|image_url:string; detail:string|}
| [<JsonName("output_audio")>] Output_audio of MessageAudioContent
| [<JsonName("audio")>] Audio of MessageAudioContent
| [<JsonName("text")>] Text of MessageTextContent
| [<JsonName("output_text")>] Output_text of MessageTextContent
type ContentMessage = {
content : MessageContent List
role : string
id : Skippable<string option>
object : Skippable<string option>
status : string
}
with static member Default : ContentMessage = {
role = "user"
id = Skip
object = Skip
status = "completed"
content = [Input_text {|text="hello"|}]
}
type ContentFunctionCall = {
name : string
arguments : string
call_id : string
id : string
object : Skippable<string option>
status : Skippable<string option>
}
type ContentFunctionCallOutput = {
call_id : string
output : string
id : string
object : Skippable<string option>
status : Skippable<string option>
} with static member Create callId output = {
call_id = callId
output = output
id = Utils.newId()
object = Skip
status = Include (Some "completed")
}
type ContentMcpApprovalResponse = {
approval_request_id : string
approve : bool
id : string
reason : string
}
type ContentMcpApprovalRequest = {
arguments : string
id : string
name : string
server_label : string
}
type McpTool = {
input_schema : JsonElement
name : string
annotations : JsonElement
description : string
}
type ContentMcpListTools = {
server_label : string
tools : McpTool list
id : string
}
type ContentMcpToolCall = {
arguments : string
id : string
name : string
server_label : string
approval_request_id : string
output : string
error : {|code:int; message:string; ``type``:string|}
}
/// An item in the Realtime conversation transcript. Covers user/assistant messages,
/// function calls and their outputs, and MCP-related approval / tool-call items.
/// Serialized with an internal <c>"type"</c> tag matching the OpenAI wire format.
[<JsonFSharpConverter(
BaseUnionEncoding = JsonUnionEncoding.InternalTag,
UnionTagName = "type",
UnionUnwrapRecordCases = true
)>]
type ConversationItem =
| [<JsonName "message">] Message of ContentMessage
| [<JsonName "function_call">] Function_call of ContentFunctionCall
| [<JsonName "function_call_output">] Function_call_output of ContentFunctionCallOutput
| [<JsonName "mcp_approval_response">] Mcp_approval_response of ContentMcpApprovalResponse
| [<JsonName "mcp_call">] Mcp_call of ContentMcpToolCall
| [<JsonName "mcp_list_tools">] Mcp_list_tools of ContentMcpListTools
| [<JsonName "mcp_approval_request">] Mcp_approval_request of ContentMcpApprovalRequest
//Error event
type Error =
{
event_id: string
``type``: string // "error"
error: ErrorDetail
}
///Returned when a session is created. Emitted automatically when a new connection is established.
type SessionCreated =
{
event_id: string
``type``: string // "session.created"
session: Session
}
///Returned when a session is updated.
type SessionUpdated =
{
event_id: string
``type``: string // "session.updated"
session: Session
}
///Overloaded: Sent by the server when an Item is added|done|retrieved to the default Conversation
type ConversationItemEvent =
{
event_id: string
item : ConversationItem
``type``: string // "conversation.item.[added|done|retrieved]"
previous_item_id : Skippable<string option>
}
type LogProbs = {bytes:int list; logprob:float; token:string}
///Returned when input audio transcription is enabled and a transcription succeeds.
type ConversationItemInputAudioTranscriptionCompleted =
{
event_id: string
``type``: string // "conversation.item.input_audio_transcription.completed"
item_id: string
content_index: int
transcript: string
usage : Usage
logprobs : Skippable<LogProbs list option>
}
type ConversationItemInputAudioTranscriptionDelta =
{
content_index: int
delta : string
event_id: string
item_id: string
logprobs : Skippable<LogProbs list option>
``type``: string // "conversation.item.input_audio_transcription.delta"
}
type ConversationItemInputAudioTranscriptionSegment =
{
content_index: int
``end`` : float
event_id: string
id : string //segment identifier
item_id: string
speaker : string
start : float
text : string
``type``: string // "conversation.item.input_audio_transcription.segment"
}
///Returned when input audio transcription is configured, and a transcription request for a user message failed.
type ConversationItemInputAudioTranscriptionFailed =
{
content_index: int
error: ErrorDetail
event_id: string
item_id: string
``type``: string // "conversation.item.input_audio_transcription.failed"
}
///Returned when an earlier assistant audio message item is truncated by the client.
type ConversationItemTruncated =
{
event_id: string
``type``: string // "conversation.item.truncated"
item_id: string
content_index: int
audio_end_ms: int
}
///Returned when an item in the conversation is deleted.
type ConversationItemDeleted =
{
event_id: string
``type``: string // "conversation.item.deleted"
item_id: string
}
///Returned when an input audio buffer is committed, either by the client or automatically in server VAD mode.
type InputAudioBufferCommitted =
{
event_id: string
``type``: string // "input_audio_buffer.committed"
previous_item_id: string option
item_id: string
}
///SIP Only: Returned when an DTMF event is received. A DTMF event is a message that represents a telephone keypad press (0–9, *, #, A–D).
type InputAudioBufferDtmfEventReceived =
{
event : string
received_at : int
item_id: Skippable<string option>
}
///Returned when the input audio buffer is cleared by the client.
type InputAudioBufferCleared =
{
event_id: string
``type``: string // "input_audio_buffer.cleared"
}
///Returned in server turn detection mode when speech is detected.
type InputAudioBufferSpeechStarted =
{
event_id: string
``type``: string // "input_audio_buffer.speech_started"
audio_start_ms: int
item_id: string
}
///Returned in server turn detection mode when speech stops.
type InputAudioBufferSpeechStopped =
{
event_id: string
``type``: string // "input_audio_buffer.speech_stopped"
audio_end_ms: int
item_id: string
}
///Returned when the Server VAD timeout is triggered for the input audio buffer. This is configured with idle_timeout_ms in the turn_detection settings of the session, and it indicates that there hasn't been any speech detected for the configured duration.
type InputAudioBufferTimeoutTriggered =
{
audio_end_ms: int
audio_start_ms : int
event_id: string
item_id: string
``type``: string // "input_audio_buffer.timeout_triggered"
}
///WebRTC/SIP Only: Emitted when the server begins streaming audio to the client. This event is emitted after an audio content part has been added (response.content_part.added) to the response.
type OutputAudioBufferStarted =
{
event_id: string
response_id: string
``type``: string // "output_audio_buffer.[started|stopped]"
}
type OutputAudioBufferStopped = OutputAudioBufferStarted
type OutputAudioBufferCleared = OutputAudioBufferStarted
///Returned when a new Response is created. The first event of response creation, where the response is in an initial state of "in_progress".
type ResponseCreated =
{
event_id: string
``type``: string // "response.created"
response: Response
}
///Returned when a Response is done streaming. Always emitted, no matter the final state.
type ResponseDone =
{
event_id: string
``type``: string // "response.done"
response: Response
}
///Returned when a new Item is created during response generation.
///Also when an Item is done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseOutputItem =
{
event_id: string
item: ConversationItem
output_index: int
response_id: string
``type``: string // "response.output_item.[added|done]"
}
///Returned when a new content part is added to an assistant message item during response generation.
///Also when a content part is done streaming in an assistant message item. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseContentPart =
{
content_index: int
event_id: string
item_id: string
output_index: int
part: ContentPart
response_id: string
``type``: string // "response.content_part.[added|done]"
}
///Returned when the text value of a "text" content part is updated.
type ResponseOutputTextDelta =
{
content_index: int
delta: string
event_id: string
item_id: string
output_index: int
response_id: string
``type``: string // "response.text.delta"
}
///Returned when the text value of a "text" content part is done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseOutputTextDone =
{
content_index: int
event_id: string
response_id: string
output_index: int
item_id: string
text: string
``type``: string // "response.text.done"
}
///Returned when the model-generated transcription of audio output is updated.
type ResponseOutputAudioTranscriptDelta =
{
content_index: int
delta: string
event_id: string
item_id: string
output_index: int
response_id: string
``type``: string // "response.text.done"
}
///Returned when the model-generated transcription of audio output is done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseOutputAudioTranscriptDone =
{
content_index: int
event_id: string
item_id: string
output_index: int
response_id: string
transcript: string
``type``: string // "response.text.done"
}
///Returned when the model-generated function call arguments are done streaming. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseFunctionCallArgumentsDone =
{
arguments: string
call_id: string
event_id: string
item_id: string
output_index: int
response_id: string
``type``: string
}
///Returned when the model-generated audio is done. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseFunctionCallArgumentsDelta =
{
call_id: string
delta: string
event_id: string
item_id: string
output_index: int
response_id: string
``type``: string
}
///Returned when the model-generated audio is updated.
type ResponseOutputAudioDelta =
{
content_index: int
delta: string
event_id: string
item_id: string
output_index: int
response_id: string
``type``: string //response.output_audio.delta
}
///Returned when the model-generated audio is done. Also emitted when a Response is interrupted, incomplete, or cancelled.
type ResponseOutputAudioDone =
{
content_index: int
event_id: string
item_id: string
output_index: int
response_id: string
``type``: string //response.output_audio.done
}
type ResponseMcpCallArgumentsDelta =
{
delta : string
event_id : string
item_id : string
obfuscation : Skippable<string option>
output_index : int
response_id : string
``type`` : string
}
type ResponseMcpCallArgumentsDone =
{
arguments : string
event_id : string
item_id : string
output_index : int
response_id : string
``type`` : string
}
//overloaded for multiple mcp events
type ResponseMcp =
{
event_id : string
item_id : string
output_index : Skippable<int option>
``type`` : string //mcp_call.[in_progress|completed|failed]
//mcp_list_tools.[in_progress|completed|failed]
}
type RateLimit =
{
limit : int
name : string
remaining : int
reset_seconds : float
}
///Emitted after every "response.done" event to indicate the updated rate limits.
type RateLimitsUpdated =
{
event_id: string
rate_limits: RateLimit list
``type``: string // "rate_limits.updated"
}
type Conversation =
{
id: string
``object``: string
}
type StatusError =
{
``type`` : string //usually "server_error"
code : string option
}
type StatusDetails =
{
``type`` : string
error : Skippable<StatusError option>
reason : string
}
///Returned when a new content part is added to an assistant message item during response generation.
type ContentPart =
{
audio : Skippable<string option>
text: Skippable<string option>
transcript: Skippable<string option>
``type``: string //[audio | text ]
}
/// Discriminated union of every server-to-client event produced by the OpenAI
/// Realtime API. Deserialization is handled by
/// <see cref="M:RTOpenAI.Events.SerDe.toEvent"/>: unrecognized or malformed