refactor: enhance summarization widget with streaming support and text accumulation

This commit is contained in:
X-iZhang
2026-03-14 19:41:27 +00:00
parent 1bcc38ea16
commit 46a1de9dd6
6 changed files with 156 additions and 20 deletions
+67 -3
View File
@@ -1,6 +1,7 @@
"""Tests for the summarization event pipeline and display widgets."""
from EvoScientist.stream.emitter import StreamEventEmitter
from EvoScientist.stream.events import _extract_summarization_text
from EvoScientist.stream.state import StreamState
@@ -44,12 +45,12 @@ class TestSummarizationState:
assert etype == "summarization"
assert state.summarization_text == "summary"
def test_overwrites_previous(self):
"""Each summarization replaces (not appends) the previous text."""
def test_accumulates_chunks(self):
"""Summarization chunks are accumulated (streaming)."""
state = StreamState()
state.handle_event({"type": "summarization", "content": "first"})
state.handle_event({"type": "summarization", "content": "second"})
assert state.summarization_text == "second"
assert state.summarization_text == "firstsecond"
def test_get_display_args_includes_field(self):
state = StreamState()
@@ -158,6 +159,24 @@ class TestSummarizationWidget:
w._content = "x" * 2500
assert w._char_count_label() == "2.5k chars"
def test_append_text(self):
from EvoScientist.cli.widgets.summarization_widget import SummarizationWidget
w = SummarizationWidget()
w.append_text("hello ")
w.append_text("world")
assert w._content == "hello world"
assert w._is_active is True
def test_finalize(self):
from EvoScientist.cli.widgets.summarization_widget import SummarizationWidget
w = SummarizationWidget()
w.append_text("some summary")
w.finalize()
assert w._is_active is False
assert w._collapsed is True
def test_toggle_collapsed(self):
from EvoScientist.cli.widgets.summarization_widget import SummarizationWidget
@@ -167,3 +186,48 @@ class TestSummarizationWidget:
assert w._collapsed is False
w._collapsed = not w._collapsed
assert w._collapsed is True
# ---------------------------------------------------------------------------
# _extract_summarization_text helper
# ---------------------------------------------------------------------------
class TestExtractSummarizationText:
"""Content extraction from summarization chunks."""
def test_string_content(self):
class Msg:
content = "hello world"
assert _extract_summarization_text(Msg()) == "hello world"
def test_content_blocks(self):
class Msg:
content = [{"type": "text", "text": "part1"}, {"type": "text", "text": "part2"}]
assert _extract_summarization_text(Msg()) == "part1part2"
def test_content_blocks_with_index(self):
"""Content blocks may include 'index' field — should still extract text."""
class Msg:
content = [{"type": "text", "text": " vs", "index": 1}]
assert _extract_summarization_text(Msg()) == " vs"
def test_empty_list(self):
class Msg:
content = []
assert _extract_summarization_text(Msg()) == ""
def test_no_content_attr(self):
class Msg:
pass
assert _extract_summarization_text(Msg()) == ""
def test_mixed_block_types(self):
class Msg:
content = [{"type": "text", "text": "hello"}, {"type": "image", "url": "..."}]
assert _extract_summarization_text(Msg()) == "hello"
def test_string_blocks_in_list(self):
class Msg:
content = ["hello", "world"]
assert _extract_summarization_text(Msg()) == "helloworld"