From b51c542afa82820da23efe2faca087d13928e2a7 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Fri, 2 Jan 2026 12:48:54 -0300 Subject: [PATCH] Fix duplicate WS progress bug - rebuild tree on structure change - Normalize task ID comparison in retry logic for consistent lookups - Use normalized keys in pendingManifestUpdates Map - Skip manifest_update in ProgressPanel (already handled by tasks.js) - Clean up existing handler before registering new one in ProgressPanel.init - Add name-based fallback lookups for sections/children/items when IDs change - Detect structure changes (section count, children, items, names) and rebuild tree - Clear progress-empty placeholder before rendering tree - Add detailed BUILD_TREE logging for debugging - Add cache-busting version to tasks.js script tag --- src/ui_server/mod.rs | 36 +- ui/suite/index.html | 2 +- ui/suite/public/favicon.ico | Bin 0 -> 37710 bytes ui/suite/tasks/autotask.js | 46 +- ui/suite/tasks/progress-panel.js | 833 ++++++++++++++------------ ui/suite/tasks/taskmd.css | 253 +++++++- ui/suite/tasks/tasks.html | 70 +-- ui/suite/tasks/tasks.js | 992 ++++++++++++++++++++++++++++--- 8 files changed, 1659 insertions(+), 573 deletions(-) create mode 100644 ui/suite/public/favicon.ico diff --git a/src/ui_server/mod.rs b/src/ui_server/mod.rs index efe7913..d791a5a 100644 --- a/src/ui_server/mod.rs +++ b/src/ui_server/mod.rs @@ -246,8 +246,6 @@ struct WsQuery { #[derive(Debug, Default, Deserialize)] struct OptionalWsQuery { - session_id: Option, - user_id: Option, task_id: Option, } @@ -362,8 +360,23 @@ async fn handle_task_progress_ws_proxy( while let Some(msg) = backend_rx.next().await { match msg { Ok(TungsteniteMessage::Text(text)) => { - if client_tx.send(AxumMessage::Text(text)).await.is_err() { - break; + // Log manifest_update messages for debugging + let is_manifest = text.contains("manifest_update"); + if is_manifest { + info!("[WS_PROXY] Forwarding manifest_update to client: {}...", &text[..text.len().min(200)]); + } else if text.contains("task_progress") { + debug!("[WS_PROXY] Forwarding task_progress to client"); + } + match client_tx.send(AxumMessage::Text(text)).await { + Ok(()) => { + if is_manifest { + info!("[WS_PROXY] manifest_update SENT successfully to client"); + } + } + Err(e) => { + error!("[WS_PROXY] Failed to send message to client: {:?}", e); + break; + } } } Ok(TungsteniteMessage::Binary(data)) => { @@ -529,6 +542,18 @@ fn create_ui_router() -> Router { Router::new().fallback(any(proxy_api)) } +async fn serve_favicon() -> impl IntoResponse { + let favicon_path = PathBuf::from("./ui/suite/public/favicon.ico"); + match tokio::fs::read(&favicon_path).await { + Ok(bytes) => ( + StatusCode::OK, + [("content-type", "image/x-icon")], + bytes, + ).into_response(), + Err(_) => StatusCode::NOT_FOUND.into_response(), + } +} + fn add_static_routes(router: Router, suite_path: &Path) -> Router { let mut r = router; @@ -554,7 +579,8 @@ pub fn configure_router() -> Router { .nest("/apps", create_apps_router()) .route("/", get(index)) .route("/minimal", get(serve_minimal)) - .route("/suite", get(serve_suite)); + .route("/suite", get(serve_suite)) + .route("/favicon.ico", get(serve_favicon)); router = add_static_routes(router, &suite_path); diff --git a/ui/suite/index.html b/ui/suite/index.html index fe93e11..b5a78a5 100644 --- a/ui/suite/index.html +++ b/ui/suite/index.html @@ -968,7 +968,7 @@ - +