//go:build unit package service import ( "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" ) func TestIsOpenAINativeCompactionV2ReadsOnlyRequestMarker(t *testing.T) { c, _ := gin.CreateTestContext(nil) require.False(t, IsOpenAINativeCompactionV2(c)) MarkOpenAINativeCompactionV2(c) require.True(t, IsOpenAINativeCompactionV2(c)) require.False(t, IsOpenAINativeCompactionV2(nil)) } func TestHasCompactionTriggerInInput_DetectsCompactSignal(t *testing.T) { body := []byte(`{ "model":"gpt-5.5", "stream":true, "input":[ {"type":"message","role":"user","content":"hello"}, {"type":"compaction_trigger"} ] }`) require.True(t, HasCompactionTriggerInInput(body)) } func TestHasCompactionTriggerInInput_NoTrigger(t *testing.T) { body := []byte(`{ "model":"gpt-5.5", "input":[ {"type":"message","role":"user","content":"hello"} ] }`) require.False(t, HasCompactionTriggerInInput(body)) } func TestHasCompactionTriggerInInput_EmptyInput(t *testing.T) { body := []byte(`{"model":"gpt-5.5","input":[]}`) require.False(t, HasCompactionTriggerInInput(body)) } func TestHasCompactionTriggerInInput_NoInputField(t *testing.T) { body := []byte(`{"model":"gpt-5.5"}`) require.False(t, HasCompactionTriggerInInput(body)) } func TestHasCompactionTriggerInInput_EmptyBody(t *testing.T) { require.False(t, HasCompactionTriggerInInput(nil)) require.False(t, HasCompactionTriggerInInput([]byte{})) } func TestHasCompactionTriggerInInput_StringInput(t *testing.T) { body := []byte(`{"model":"gpt-5.5","input":"compaction_trigger"}`) require.False(t, HasCompactionTriggerInInput(body)) } func TestHasCompactionTriggerInInput_CompactTriggerOnly(t *testing.T) { body := []byte(`{"model":"gpt-5.5","input":[{"type":"compaction_trigger"}]}`) require.True(t, HasCompactionTriggerInInput(body)) } func TestNormalizeCompactionTriggerInputOrder_MovesAndCollapsesTriggers(t *testing.T) { body := []byte(`{"model":"gpt-5.5","input":[{"type":"compaction_trigger"},{"type":"message","role":"user","content":"tail"},{"type":"compaction_trigger"}]}`) normalized, changed, err := NormalizeCompactionTriggerInputOrder(body) require.NoError(t, err) require.True(t, changed) items := gjson.GetBytes(normalized, "input").Array() require.Len(t, items, 2) require.Equal(t, "message", items[0].Get("type").String()) require.Equal(t, "compaction_trigger", items[1].Get("type").String()) } func TestNormalizeCompactionTriggerInputOrder_AlreadyFinalPreservesBytes(t *testing.T) { body := []byte(`{"input":[{"type":"message"},{"type":"compaction_trigger"}]}`) normalized, changed, err := NormalizeCompactionTriggerInputOrder(body) require.NoError(t, err) require.False(t, changed) require.Equal(t, string(body), string(normalized)) } func TestNormalizeCompactionTriggerInputOrder_PreservesHistoryAndLargeNumbers(t *testing.T) { body := []byte(`{"input":[{"type":"compaction_trigger"},{"type":"message","id":"msg_1","content":"visible"},{"type":"function_call_output","call_id":"call_1","output":"result","sequence":9007199254740993}]}`) normalized, changed, err := NormalizeCompactionTriggerInputOrder(body) require.NoError(t, err) require.True(t, changed) require.Equal(t, "message", gjson.GetBytes(normalized, "input.0.type").String()) require.Equal(t, "function_call_output", gjson.GetBytes(normalized, "input.1.type").String()) require.Equal(t, "9007199254740993", gjson.GetBytes(normalized, "input.1.sequence").Raw) require.Equal(t, "compaction_trigger", gjson.GetBytes(normalized, "input.2.type").String()) second, changedAgain, err := NormalizeCompactionTriggerInputOrder(normalized) require.NoError(t, err) require.False(t, changedAgain) require.Equal(t, normalized, second) } func TestWebSocketCompatibilityNormalizesTriggerAfterPairedOutputCleanup(t *testing.T) { body := []byte(`{"type":"response.create","model":"gpt-5.4","input":[{"type":"compaction_trigger"},{"type":"function_call","call_id":"call_1","name":"lookup","arguments":"{}"},{"type":"function_call_output","call_id":"call_1","output":"ok"},{"type":"message","role":"user","content":"visible"}]}`) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeOAuth} normalized, changed, err := normalizeOpenAIResponsesWebSocketCompatibilityBody(body, account, false) require.NoError(t, err) require.True(t, changed) items := gjson.GetBytes(normalized, "input").Array() require.Len(t, items, 4) require.Equal(t, "function_call", items[0].Get("type").String()) require.Equal(t, "function_call_output", items[1].Get("type").String()) require.Equal(t, "message", items[2].Get("type").String()) require.Equal(t, "compaction_trigger", items[3].Get("type").String()) }