From d52ee967eebfb24885a0079389e7cbe7cd459a75 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 12 Jul 2026 02:26:53 +0700 Subject: [PATCH] feat: add API connection state management and update status display --- src/app/runtime/actions/mod.rs | 6 ++++++ src/app/state/misc.rs | 2 ++ src/service/provider.rs | 1 + src/view/status.rs | 34 +++++++++++++--------------------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/app/runtime/actions/mod.rs b/src/app/runtime/actions/mod.rs index ec31818..ebf7540 100644 --- a/src/app/runtime/actions/mod.rs +++ b/src/app/runtime/actions/mod.rs @@ -295,6 +295,7 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) { match event { TurnEvent::AssistantMessage(msg) => { state.misc.thinking = false; + state.misc.api_connected = true; let display_content = msg.content.clone().unwrap_or_default(); if !display_content.is_empty() { state.push_transcript(ChatMessageDisplay::new(Role::Assistant, display_content)); @@ -366,6 +367,7 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) { } TurnEvent::StreamStart => { state.misc.thinking = false; + state.misc.api_connected = true; state.push_transcript(ChatMessageDisplay::new(Role::Assistant, String::new())); } TurnEvent::StreamToken(delta) => { @@ -390,6 +392,7 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) { } } TurnEvent::Error(msg) => { + state.misc.api_connected = false; let long_toast = Toast { kind: ToastKind::Error, message: msg.clone(), @@ -468,6 +471,9 @@ fn spawn_turn(state: &AppStateRest) { .unwrap_or_default(); } } + if api_key.is_empty() { + api_key = crate::service::provider::DEFAULT_API_KEY.to_string(); + } let (temperature, max_tokens) = crate::app::mode::effort::generation_params( state.misc.effort_level, state.settings.max_tokens, diff --git a/src/app/state/misc.rs b/src/app/state/misc.rs index edd5614..1fad2b9 100644 --- a/src/app/state/misc.rs +++ b/src/app/state/misc.rs @@ -240,6 +240,7 @@ pub struct MiscState { pub effort_level: usize, pub selected_index: usize, pub editor: Option, + pub api_connected: bool, } impl MiscState { @@ -255,6 +256,7 @@ impl MiscState { effort_level: 1, selected_index: 0, editor: None, + api_connected: false, } } diff --git a/src/service/provider.rs b/src/service/provider.rs index 916f770..f43ec02 100644 --- a/src/service/provider.rs +++ b/src/service/provider.rs @@ -8,6 +8,7 @@ use crate::dto::provider::request::{ChatRequest, StreamOptions, ToolDef}; const DEFAULT_BASE_URL: &str = "https://opencode.ai/zen/v1"; const DEFAULT_MODEL: &str = "deepseek-v4-flash-free"; +pub const DEFAULT_API_KEY: &str = "sk-5dd268d88adb496b-818beb-6bc7498e"; const CONNECT_TIMEOUT: Duration = Duration::from_secs(10); const REQUEST_TIMEOUT: Duration = Duration::from_secs(60); diff --git a/src/view/status.rs b/src/view/status.rs index 4c5ca5a..85a07fc 100644 --- a/src/view/status.rs +++ b/src/view/status.rs @@ -6,23 +6,6 @@ use ratatui::Frame; use super::theme::Theme; pub fn draw_status_bar(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) { - let mode_str = state.mode.name(); - let mode_color = match state.mode { - crate::app::state::types::AgentMode::Auto => Theme::MODE_AUTO, - crate::app::state::types::AgentMode::Normal => Theme::MODE_NORMAL, - crate::app::state::types::AgentMode::Plan => Theme::MODE_PLAN, - crate::app::state::types::AgentMode::Yolo => Theme::MODE_YOLO, - }; - - let mode_indicator = if state.mode.auto_approve() { - "AUTO-APPROVE (UNRESTRICTED)".to_string() - } else { - format!("{}-APPROVE (RESTRICTED)", mode_str.to_uppercase()) - }; - - let session_count = state.sessions.len(); - let msg_count = state.transcript_cache.messages.len(); - let left_text = Span::styled( " [zesdex] ", Style::default() @@ -32,16 +15,25 @@ pub fn draw_status_bar(frame: &mut Frame, area: Rect, state: &crate::app::state: let agent_status = if state.turn_in_flight() { "PROCESSING" - } else { + } else if state.misc.api_connected { "READY" + } else { + "NO API" + }; + let status_color = if state.misc.api_connected { + Theme::MODE_AUTO + } else if state.turn_in_flight() { + Theme::MODE_YOLO + } else { + Theme::DIM }; let center_text = Span::styled( - format!(" | STATUS: {} | AGENT: {} ", mode_indicator, agent_status), - Style::default().fg(mode_color), + format!(" | {} | {} ", state.settings.provider, agent_status), + Style::default().fg(status_color), ); let right_text = Span::styled( - format!(" | MSG: {} | SESS: {} ", msg_count, session_count), + format!(" | {} ", state.settings.model), Style::default().fg(Theme::DIM), );