package tui import "testing" func TestProcessStreamChunk_PlainText(t *testing.T) { main, think, inThinking, buf := processStreamChunk("hello world", false, "") if main != "hello world" { t.Errorf("main text = %q, want %q", main, "hello world") } if think != "" { t.Errorf("think text = %q, want empty", think) } if inThinking { t.Error("should not be in thinking mode") } if buf != "" { t.Errorf("search buf = %q, want empty", buf) } } func TestProcessStreamChunk_OpenTag(t *testing.T) { main, think, inThinking, _ := processStreamChunk("reasoning here", false, "") if main != "" { t.Errorf("main text = %q, want empty", main) } if think != "reasoning here" { t.Errorf("think text = %q, want %q", think, "reasoning here") } if !inThinking { t.Error("should be in thinking mode") } } func TestProcessStreamChunk_CloseTag(t *testing.T) { main, think, inThinking, _ := processStreamChunk("end of thoughtvisible text", true, "") if think != "end of thought" { t.Errorf("think text = %q, want %q", think, "end of thought") } if main != "visible text" { t.Errorf("main text = %q, want %q", main, "visible text") } if inThinking { t.Error("should not be in thinking mode after close tag") } } func TestProcessStreamChunk_FullCycle(t *testing.T) { main, think, inThinking, _ := processStreamChunk("thoughtresponse", false, "") if think != "thought" { t.Errorf("think text = %q, want %q", think, "thought") } if main != "response" { t.Errorf("main text = %q, want %q", main, "response") } if inThinking { t.Error("should not be in thinking mode") } } func TestProcessStreamChunk_SplitAcrossChunks(t *testing.T) { // First chunk ends with partial tag "reasoning", false, buf1) if main2 != "" { t.Errorf("chunk2 main = %q, want empty", main2) } if think2 != "reasoning" { t.Errorf("chunk2 think = %q, want %q", think2, "reasoning") } if !inThinking2 { t.Error("chunk2 should be in thinking mode") } } func TestProcessStreamChunk_NestedTags(t *testing.T) { // Nested should be treated as text inside thinking. main, think, _, _ := processStreamChunk("outerinnerafter", false, "") // The inner should be literal text inside thinking. // When we encounter the first , thinking ends. if main != "after" { t.Errorf("main = %q, want %q", main, "after") } // The think content should include "outerinner" if think != "outerinner" { t.Errorf("think = %q, want %q", think, "outerinner") } } func TestHasPartialTagSuffix(t *testing.T) { tests := []struct { s, tag string want int }{ {"hello<", "", 1}, {"hello", 2}, {"hello", 3}, {"hello", 4}, {"hello", 5}, {"hello", 6}, {"hello", "", 0}, // full match, not partial {"hello", "", 0}, {"", 5}, {"<", "", 1}, } for _, tt := range tests { got := hasPartialTagSuffix(tt.s, tt.tag) if got != tt.want { t.Errorf("hasPartialTagSuffix(%q, %q) = %d, want %d", tt.s, tt.tag, got, tt.want) } } }