core/cli: update display and state for streaming, error, cancel events

This commit is contained in:
2026-07-14 22:11:30 +08:00
parent 42b50716f4
commit ed028dc00b
3 changed files with 15 additions and 8 deletions
+8 -2
View File
@@ -5,6 +5,8 @@ from typing import TYPE_CHECKING
import click
from plyngent.agent import (
CancelledEvent,
ErrorEvent,
MaxRoundsEvent,
TextDeltaEvent,
ToolCallEvent,
@@ -20,7 +22,7 @@ if TYPE_CHECKING:
_TOOL_RESULT_PREVIEW = 200
async def render_events(events: AsyncIterator[AgentEvent]) -> None:
async def render_events(events: AsyncIterator[AgentEvent]) -> None: # noqa: C901, PLR0912
"""Print agent events to the terminal."""
printed_text = False
async for event in events:
@@ -47,6 +49,10 @@ async def render_events(events: AsyncIterator[AgentEvent]) -> None:
else content[:_TOOL_RESULT_PREVIEW] + ""
)
click.secho(f"[tool result] {preview}", fg="magenta")
elif isinstance(event, ErrorEvent):
click.secho(f"\n[error] {event.message}", fg="bright_red")
elif isinstance(event, CancelledEvent):
click.secho("\n[cancelled]", fg="yellow")
elif isinstance(event, MaxRoundsEvent):
if event.continued:
click.secho(
@@ -60,5 +66,5 @@ async def render_events(events: AsyncIterator[AgentEvent]) -> None:
_ = event
if printed_text:
click.echo()
# Blank line before the next readline prompt so log and input are not jammed.
click.echo()
+3 -2
View File
@@ -34,7 +34,7 @@ class ReplState:
def __post_init__(self) -> None:
# DeepSeek client uses a compatible but distinct param type; treat as ChatClient.
self.client = cast("ChatClient", create_client(self.provider))
self.client = cast("ChatClient", cast("object", create_client(self.provider)))
self.agent = self._make_agent()
def _tool_registry(self) -> ToolRegistry | None:
@@ -53,12 +53,13 @@ class ReplState:
session_id=self.session_id,
max_rounds=self.max_rounds,
on_limit=prompt_continue_limit,
stream=True,
)
def rebuild_client(self) -> None:
"""Recreate client and agent after provider/model/tools change."""
messages = list(self.agent.messages)
self.client = cast("ChatClient", create_client(self.provider))
self.client = cast("ChatClient", cast("object", create_client(self.provider)))
self.agent = self._make_agent()
self.agent.messages = messages
+4 -4
View File
@@ -96,10 +96,10 @@ async def test_run_chat_loop_text_only() -> None:
]
)
messages: list[AnyChatMessage] = [UserChatMessage(content="hi")]
events = [e async for e in run_chat_loop(client, messages, model="m")]
assert isinstance(events[0], AssistantMessageEvent)
assert isinstance(events[1], TextDeltaEvent)
assert events[1].content == "hello"
events = [e async for e in run_chat_loop(client, messages, model="m", stream=False)]
assert isinstance(events[0], TextDeltaEvent)
assert events[0].content == "hello"
assert isinstance(events[1], AssistantMessageEvent)
assert len(messages) == 2 # noqa: PLR2004
assert len(client.calls) == 1