huskies: merge 643_story_web_ui_consumer_for_the_unified_status_broadcaster
This commit is contained in:
@@ -9,11 +9,12 @@ use crate::service::notifications::format::stage_display_name;
|
||||
use crate::service::status::StatusEvent;
|
||||
|
||||
/// Render a [`StatusEvent`] into a human-readable plain-text string.
|
||||
#[allow(dead_code)]
|
||||
///
|
||||
/// This is the single formatter for all status event types. Every transport
|
||||
/// (chat, Web UI, agent context) calls this function rather than duplicating
|
||||
/// formatting logic.
|
||||
// Used by chat/agent transports (stories 642/644); the web UI uses StatusUpdate frames instead.
|
||||
#[allow(dead_code)]
|
||||
pub fn format_status_event(event: &StatusEvent) -> String {
|
||||
match event {
|
||||
StatusEvent::StageTransition {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
pub mod format;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Serialize;
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
@@ -44,7 +45,8 @@ const CHANNEL_CAPACITY: usize = 256;
|
||||
///
|
||||
/// Each variant carries enough context for [`format_status_event`] to render a
|
||||
/// human-readable message without additional lookups.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum StatusEvent {
|
||||
/// A work item moved between pipeline stages.
|
||||
StageTransition {
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::io::onboarding;
|
||||
use crate::io::watcher::WatcherEvent;
|
||||
use crate::io::wizard;
|
||||
use crate::log_buffer;
|
||||
use crate::service::status::Subscription;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
@@ -116,6 +117,21 @@ pub fn subscribe_watcher(
|
||||
});
|
||||
}
|
||||
|
||||
/// Spawn a background task that forwards status broadcaster events to the client.
|
||||
///
|
||||
/// Each [`StatusEvent`](crate::service::status::StatusEvent) is delivered as a
|
||||
/// [`WsResponse::StatusUpdate`] with the structured event fields intact, so the
|
||||
/// frontend can do per-type presentation without parsing strings.
|
||||
pub fn subscribe_status(tx: mpsc::UnboundedSender<WsResponse>, mut subscription: Subscription) {
|
||||
tokio::spawn(async move {
|
||||
while let Some(event) = subscription.recv().await {
|
||||
if tx.send(WsResponse::StatusUpdate { event }).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Spawn a background task that forwards reconciliation events to the client.
|
||||
pub fn subscribe_reconciliation(
|
||||
tx: mpsc::UnboundedSender<WsResponse>,
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::http::workflow::{PipelineState, UpcomingStory};
|
||||
use crate::io::watcher::WatcherEvent;
|
||||
use crate::llm::chat;
|
||||
use crate::llm::types::Message;
|
||||
use crate::service::status::StatusEvent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// WebSocket request messages sent by the client.
|
||||
@@ -153,6 +154,15 @@ pub enum WsResponse {
|
||||
level: String,
|
||||
message: String,
|
||||
},
|
||||
/// A structured pipeline status event forwarded from the status broadcaster.
|
||||
///
|
||||
/// The structured [`StatusEvent`] fields are preserved on the wire so
|
||||
/// frontend consumers can do per-type presentation without parsing strings.
|
||||
/// This frame intentionally does NOT call `format_status_event` — that
|
||||
/// formatter is reserved for chat transports (story 644).
|
||||
StatusUpdate {
|
||||
event: StatusEvent,
|
||||
},
|
||||
}
|
||||
|
||||
// ── Domain event conversions ────────────────────────────────────────────────
|
||||
|
||||
@@ -20,6 +20,6 @@ pub use dispatch::{
|
||||
};
|
||||
pub use io::{
|
||||
check_onboarding, load_initial_pipeline_state, load_recent_logs, load_wizard_state,
|
||||
subscribe_logs, subscribe_reconciliation, subscribe_watcher,
|
||||
subscribe_logs, subscribe_reconciliation, subscribe_status, subscribe_watcher,
|
||||
};
|
||||
pub use message::{WizardStepInfo, WsResponse};
|
||||
|
||||
Reference in New Issue
Block a user