mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-11-08 00:54:17 +00:00
fix(openai-ws): exclude terminal events from TTFT
This commit is contained in:
1 parent
a19c9f8d8a
commit
ab326c96eb
3 files changed
+84
-21
No files matched your search
@@ -953,23 +953,7 @@ func shouldParseUsage(eventType string) bool {
|
||||
}
|
||||
|
||||
func isTokenEvent(eventType string) bool {
|
||||
if eventType == "" {
|
||||
return false
|
||||
}
|
||||
switch eventType {
|
||||
case "response.created", "response.in_progress", "response.output_item.added", "response.output_item.done":
|
||||
return false
|
||||
}
|
||||
if strings.Contains(eventType, ".delta") {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(eventType, "response.output_text") {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(eventType, "response.output") {
|
||||
return true
|
||||
}
|
||||
return eventType == "response.completed" || eventType == "response.done"
|
||||
return strings.HasSuffix(strings.TrimSpace(eventType), ".delta")
|
||||
}
|
||||
|
||||
func minDuration(a, b time.Duration) time.Duration {
|
||||
|
||||
@@ -246,7 +246,7 @@ func TestHelperFunctionsCoverage(t *testing.T) {
|
||||
|
||||
require.True(t, isTokenEvent("response.output_text.delta"))
|
||||
require.True(t, isTokenEvent("response.output_audio.delta"))
|
||||
require.True(t, isTokenEvent("response.completed"))
|
||||
require.False(t, isTokenEvent("response.completed"))
|
||||
require.False(t, isTokenEvent(""))
|
||||
require.False(t, isTokenEvent("response.created"))
|
||||
|
||||
@@ -407,8 +407,29 @@ func TestIsTokenEventCoverageBranches(t *testing.T) {
|
||||
require.False(t, isTokenEvent("response.in_progress"))
|
||||
require.False(t, isTokenEvent("response.output_item.added"))
|
||||
require.True(t, isTokenEvent("response.output_audio.delta"))
|
||||
require.True(t, isTokenEvent("response.output"))
|
||||
require.True(t, isTokenEvent("response.done"))
|
||||
require.True(t, isTokenEvent("response.function_call_arguments.delta"))
|
||||
require.True(t, isTokenEvent("response.reasoning_summary_text.delta"))
|
||||
require.False(t, isTokenEvent("response.output"))
|
||||
require.False(t, isTokenEvent("response.output_text.done"))
|
||||
require.False(t, isTokenEvent("response.output_audio.done"))
|
||||
require.False(t, isTokenEvent("response.output_text.annotation.added"))
|
||||
require.False(t, isTokenEvent("response.done"))
|
||||
}
|
||||
|
||||
func TestTerminalAndTokenEventSetsAreDisjoint(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, eventType := range []string{
|
||||
"response.completed",
|
||||
"response.done",
|
||||
"response.failed",
|
||||
"response.incomplete",
|
||||
"response.cancelled",
|
||||
"response.canceled",
|
||||
} {
|
||||
require.True(t, isTerminalEvent(eventType), eventType)
|
||||
require.False(t, isTokenEvent(eventType), eventType)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldParseUsageTerminalEvents(t *testing.T) {
|
||||
|
||||
@@ -202,7 +202,7 @@ func TestRelay_BasicRelayAndUsage(t *testing.T) {
|
||||
require.Equal(t, 7, result.Usage.InputTokens)
|
||||
require.Equal(t, 3, result.Usage.OutputTokens)
|
||||
require.Equal(t, 2, result.Usage.CacheReadInputTokens)
|
||||
require.NotNil(t, result.FirstTokenMs)
|
||||
require.Nil(t, result.FirstTokenMs)
|
||||
require.Equal(t, int64(1), result.ClientToUpstreamFrames)
|
||||
require.Equal(t, int64(1), result.UpstreamToClientFrames)
|
||||
require.Equal(t, int64(0), result.DroppedDownstreamFrames)
|
||||
@@ -865,6 +865,64 @@ func (c *errorOnWriteFrameConn) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestRelay_NoDeltaTerminalSequence_FirstTokenMsNil(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, terminalEvent := range []string{"response.completed", "response.done"} {
|
||||
terminalEvent := terminalEvent
|
||||
t.Run(terminalEvent, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
clientConn := newPassthroughTestFrameConn(nil, false)
|
||||
upstreamConn := newPassthroughTestFrameConn([]passthroughTestFrame{
|
||||
{
|
||||
msgType: coderws.MessageText,
|
||||
payload: []byte(`{"type":"response.created","response":{"id":"resp_no_delta"}}`),
|
||||
},
|
||||
{
|
||||
msgType: coderws.MessageText,
|
||||
payload: []byte(`{"type":"response.in_progress","response":{"id":"resp_no_delta"}}`),
|
||||
},
|
||||
{
|
||||
msgType: coderws.MessageText,
|
||||
payload: []byte(`{"type":"response.output_text.done","response_id":"resp_no_delta","text":""}`),
|
||||
},
|
||||
{
|
||||
msgType: coderws.MessageText,
|
||||
payload: []byte(`{"type":"response.content_part.done","response_id":"resp_no_delta"}`),
|
||||
},
|
||||
{
|
||||
msgType: coderws.MessageText,
|
||||
payload: []byte(`{"type":"response.output_item.done","response_id":"resp_no_delta"}`),
|
||||
},
|
||||
{
|
||||
msgType: coderws.MessageText,
|
||||
payload: []byte(`{"type":"` + terminalEvent + `","response":{"id":"resp_no_delta","usage":{"input_tokens":2,"output_tokens":0}}}`),
|
||||
},
|
||||
}, true)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var turn RelayTurnResult
|
||||
result, relayExit := Relay(
|
||||
ctx,
|
||||
clientConn,
|
||||
upstreamConn,
|
||||
[]byte(`{"type":"response.create","model":"gpt-5.3-codex","input":[]}`),
|
||||
RelayOptions{OnTurnComplete: func(current RelayTurnResult) { turn = current }},
|
||||
)
|
||||
|
||||
require.Nil(t, relayExit)
|
||||
require.Equal(t, terminalEvent, turn.TerminalEventType)
|
||||
require.Nil(t, turn.FirstTokenMs)
|
||||
require.Equal(t, terminalEvent, result.TerminalEventType)
|
||||
require.Nil(t, result.FirstTokenMs)
|
||||
require.Equal(t, int64(6), result.UpstreamToClientFrames)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRelay_OnTurnComplete_RealOpenAIStream_FirstTokenMs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in new issue
Block a user