feat: TUIに他Podからの通知を表示する
This commit is contained in:
@@ -312,6 +312,14 @@ impl App {
|
||||
self.blocks.push(Block::UserMessage { segments });
|
||||
self.assistant_streaming = false;
|
||||
}
|
||||
Event::Notify { message } => {
|
||||
self.blocks.push(Block::Notify { message });
|
||||
self.assistant_streaming = false;
|
||||
}
|
||||
Event::PodEvent(event) => {
|
||||
self.blocks.push(Block::PodEvent { event });
|
||||
self.assistant_streaming = false;
|
||||
}
|
||||
Event::TurnStart { .. } => {
|
||||
self.running = true;
|
||||
self.paused = false;
|
||||
|
||||
+12
-1
@@ -9,7 +9,7 @@
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
use protocol::{AlertLevel, AlertSource, Greeting, Segment};
|
||||
use protocol::{AlertLevel, AlertSource, Greeting, PodEvent, Segment};
|
||||
|
||||
pub enum Block {
|
||||
Greeting(Greeting),
|
||||
@@ -19,6 +19,17 @@ pub enum Block {
|
||||
UserMessage {
|
||||
segments: Vec<Segment>,
|
||||
},
|
||||
/// Echo of `Method::Notify` received by this Pod, surfaced as a log
|
||||
/// element so subscribers see the external input that drove any
|
||||
/// following auto-kicked turn.
|
||||
Notify {
|
||||
message: String,
|
||||
},
|
||||
/// Echo of `Method::PodEvent` received by this Pod. Same role as
|
||||
/// `Notify` — an input log element, not a turn-control signal.
|
||||
PodEvent {
|
||||
event: PodEvent,
|
||||
},
|
||||
AssistantText {
|
||||
text: String,
|
||||
},
|
||||
|
||||
+43
-1
@@ -22,7 +22,7 @@ use ratatui::widgets::{
|
||||
};
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
|
||||
use protocol::{AlertLevel, CompletionEntry, Greeting, Segment};
|
||||
use protocol::{AlertLevel, CompletionEntry, Greeting, PodEvent, Segment};
|
||||
|
||||
use crate::app::{App, CompletionState, alert_source_label, fmt_tokens};
|
||||
use crate::block::{Block, CompactEvent, ThinkingBlock, ThinkingState};
|
||||
@@ -361,6 +361,20 @@ fn render_block_into(lines: &mut Vec<Line<'static>>, block: &Block, width: u16,
|
||||
)));
|
||||
}
|
||||
Block::UserMessage { segments } => render_user_message(lines, segments, width, mode),
|
||||
Block::Notify { message } => {
|
||||
let text = format!("[notify] {message}");
|
||||
match mode {
|
||||
Mode::Overview => push_overview_line(lines, &text, width, MessageKind::Notify, ""),
|
||||
_ => push_padded_lines(lines, &text, MessageKind::Notify),
|
||||
}
|
||||
}
|
||||
Block::PodEvent { event } => {
|
||||
let text = format_pod_event(event);
|
||||
match mode {
|
||||
Mode::Overview => push_overview_line(lines, &text, width, MessageKind::Notify, ""),
|
||||
_ => push_padded_lines(lines, &text, MessageKind::Notify),
|
||||
}
|
||||
}
|
||||
Block::AssistantText { text } => match mode {
|
||||
Mode::Overview => push_overview_line(lines, text, width, MessageKind::Assistant, ""),
|
||||
_ => push_padded_lines(lines, text, MessageKind::Assistant),
|
||||
@@ -913,6 +927,10 @@ fn greeting_lines(g: &Greeting) -> Vec<Line<'static>> {
|
||||
pub enum MessageKind {
|
||||
TurnHeader,
|
||||
User,
|
||||
/// External-input echoes (`Method::Notify` / `Method::PodEvent`).
|
||||
/// Visually distinct from User / Assistant / Notice so it's clear
|
||||
/// the line came from another Pod or operator, not the local user.
|
||||
Notify,
|
||||
Assistant,
|
||||
Thinking,
|
||||
TurnStats,
|
||||
@@ -924,6 +942,7 @@ pub fn kind_style(kind: MessageKind) -> Style {
|
||||
match kind {
|
||||
MessageKind::TurnHeader => Style::default().fg(Color::DarkGray),
|
||||
MessageKind::User => Style::default().fg(Color::Green),
|
||||
MessageKind::Notify => Style::default().fg(Color::Yellow),
|
||||
MessageKind::Assistant => Style::default().fg(Color::White),
|
||||
MessageKind::Thinking => Style::default()
|
||||
.fg(Color::Magenta)
|
||||
@@ -939,3 +958,26 @@ pub fn kind_style(kind: MessageKind) -> Style {
|
||||
.add_modifier(Modifier::BOLD),
|
||||
}
|
||||
}
|
||||
|
||||
/// One-line summary of a `PodEvent` for display in the activity log.
|
||||
/// Independent from the LLM-injection wrapper (`crate::ipc::event::render_event`
|
||||
/// in the pod crate) — that path applies prompt-pack wrapping, while
|
||||
/// this is the human-facing rendering of the raw structured event.
|
||||
fn format_pod_event(event: &PodEvent) -> String {
|
||||
match event {
|
||||
PodEvent::TurnEnded { pod_name } => {
|
||||
format!("[pod_event] {pod_name} → turn_ended")
|
||||
}
|
||||
PodEvent::Errored { pod_name, message } => {
|
||||
format!("[pod_event] {pod_name} → errored: {message}")
|
||||
}
|
||||
PodEvent::ShutDown { pod_name } => {
|
||||
format!("[pod_event] {pod_name} → shut_down")
|
||||
}
|
||||
PodEvent::ScopeSubDelegated {
|
||||
parent_pod, sub_pod, ..
|
||||
} => {
|
||||
format!("[pod_event] {parent_pod} → scope_sub_delegated: {sub_pod}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user