Refactor scrolling methods in ScrollState to accept an amount parameter
- Updated `scroll_up` and `scroll_down` methods to take an `amount` parameter for more flexible scrolling. - Removed the `AgentMode` enum and related methods from the types module to simplify state management. - Modified `AppStateRest` to remove the `mode` field and adjusted related logic. - Enhanced `run_subagent` to build tool definitions and handle API key resolution from configuration. - Updated command parsing to reflect changes in login handling. - Removed onboarding overlays and related logic from input handling and rendering. - Improved status bar to reflect connection status and agent readiness. - Adjusted workflow panel rendering to simplify phase status display. - Refactored edit log initialization to load from disk if available. - Updated settings structure to use a HashMap for API keys. - Enhanced error handling in LlmClient for authentication issues.
This commit is contained in:
+4
-91
@@ -39,14 +39,7 @@ pub fn draw(frame: &mut Frame, state: &crate::app::state::rest::AppStateRest) {
|
||||
}
|
||||
|
||||
fn render_main_panel(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) {
|
||||
match state.mode {
|
||||
crate::app::state::types::AgentMode::Auto
|
||||
| crate::app::state::types::AgentMode::Normal
|
||||
| crate::app::state::types::AgentMode::Plan
|
||||
| crate::app::state::types::AgentMode::Yolo => {
|
||||
chat::draw_chat(frame, area, state);
|
||||
}
|
||||
}
|
||||
chat::draw_chat(frame, area, state);
|
||||
}
|
||||
|
||||
fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::types::Overlay, state: &crate::app::state::rest::AppStateRest) {
|
||||
@@ -159,57 +152,7 @@ fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::typ
|
||||
crate::app::state::types::Overlay::Workflow => {
|
||||
workflow::draw_workflow_panel(frame, overlay_area, state);
|
||||
}
|
||||
crate::app::state::types::Overlay::Onboard => {
|
||||
let block = block.title(" Welcome to Zesdex ");
|
||||
let content = "Press Ctrl+H for help, Ctrl+P for settings, or start typing to chat.";
|
||||
let paragraph = Paragraph::new(content)
|
||||
.block(block)
|
||||
.wrap(Wrap { trim: false });
|
||||
frame.render_widget(paragraph, overlay_area);
|
||||
}
|
||||
crate::app::state::types::Overlay::OnboardProvider => {
|
||||
let block = block.title(" Select Provider ");
|
||||
let lines = vec![
|
||||
Line::from(Span::styled(
|
||||
"Configure AI Provider",
|
||||
Style::default().fg(Theme::TEXT).add_modifier(Modifier::BOLD),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
"",
|
||||
Style::default(),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
"Available providers:",
|
||||
Style::default().fg(Theme::DIM),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
" Zen API - opencode.ai free model",
|
||||
Style::default().fg(Theme::TEXT),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
" Anthropic - Direct Claude API",
|
||||
Style::default().fg(Theme::TEXT),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
" OpenAI - Direct GPT API",
|
||||
Style::default().fg(Theme::TEXT),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
"",
|
||||
Style::default(),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
format!("Current: {} / {}", state.settings.provider, state.settings.model),
|
||||
Style::default().fg(Theme::INFO),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
"Press Ctrl+P to change settings.",
|
||||
Style::default().fg(Theme::DIM),
|
||||
)),
|
||||
];
|
||||
let paragraph = Paragraph::new(lines).block(block);
|
||||
frame.render_widget(paragraph, overlay_area);
|
||||
}
|
||||
|
||||
crate::app::state::types::Overlay::KeyInput => {
|
||||
let block = block.title(" Input ");
|
||||
let input_text = &state.input.buffer;
|
||||
@@ -364,10 +307,7 @@ fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::typ
|
||||
format!("Messages: {}", msg_count),
|
||||
Style::default().fg(Theme::INFO),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
format!("Mode: {}", state.mode.name()),
|
||||
Style::default().fg(Theme::TEXT),
|
||||
)),
|
||||
|
||||
Line::from(Span::styled(
|
||||
format!("Overlay: {:?}", state.misc.overlay),
|
||||
Style::default().fg(Theme::DIM),
|
||||
@@ -608,34 +548,7 @@ fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::typ
|
||||
let paragraph = Paragraph::new(lines).block(block);
|
||||
frame.render_widget(paragraph, overlay_area);
|
||||
}
|
||||
crate::app::state::types::Overlay::LoginPicker => {
|
||||
let block = block.title(" Login ");
|
||||
let providers = crate::app::mode::onboard_provider::PROVIDERS;
|
||||
let mut lines: Vec<Line> = vec![
|
||||
Line::from(Span::styled(
|
||||
"Select a provider to log in:",
|
||||
Style::default().fg(Theme::TEXT),
|
||||
)),
|
||||
Line::from(Span::styled("", Style::default())),
|
||||
];
|
||||
for (i, p) in providers.iter().enumerate() {
|
||||
let is_selected = i == state.misc.selected_index;
|
||||
let prefix = if is_selected { "▸ " } else { " " };
|
||||
let style = if is_selected {
|
||||
Style::default().fg(Theme::BG).bg(Theme::HIGHLIGHT)
|
||||
} else {
|
||||
Style::default().fg(Theme::TEXT)
|
||||
};
|
||||
lines.push(Line::from(Span::styled(format!("{}{}", prefix, p), style)));
|
||||
}
|
||||
lines.push(Line::from(Span::styled("", Style::default())));
|
||||
lines.push(Line::from(Span::styled(
|
||||
"↑↓ navigate · Enter select · Esc close",
|
||||
Style::default().fg(Theme::DIM),
|
||||
)));
|
||||
let paragraph = Paragraph::new(lines).block(block);
|
||||
frame.render_widget(paragraph, overlay_area);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+25
-25
@@ -6,38 +6,38 @@ use ratatui::Frame;
|
||||
use super::theme::Theme;
|
||||
|
||||
pub fn draw_status_bar(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) {
|
||||
let left_text = Span::styled(
|
||||
" [zesdex] ",
|
||||
// Connection status — reflects actual agent readiness:
|
||||
// PROG → turn is in flight
|
||||
// READY → connected and ready
|
||||
// NOAPI → disconnected
|
||||
let (agent_status, conn_color) = if state.turn_in_flight() {
|
||||
("PROG", Theme::MODE_YOLO)
|
||||
} else if state.misc.api_connected {
|
||||
("READY", Theme::MODE_AUTO)
|
||||
} else {
|
||||
("NOAPI", Theme::DIM)
|
||||
};
|
||||
let status = Span::styled(
|
||||
format!(" {} ", agent_status),
|
||||
Style::default()
|
||||
.fg(Theme::TEXT)
|
||||
.fg(if agent_status == "NOAPI" { Theme::DIM } else { Theme::BG })
|
||||
.bg(conn_color)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
|
||||
let agent_status = if state.turn_in_flight() {
|
||||
"PROCESSING"
|
||||
} 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!(" | {} | {} ", state.settings.provider, agent_status),
|
||||
Style::default().fg(status_color),
|
||||
);
|
||||
// Left chunk: [zesdex] STATUS
|
||||
let mut spans = vec![
|
||||
Span::styled(" [zesdex] ", Style::default().fg(Theme::TEXT).add_modifier(Modifier::BOLD)),
|
||||
status,
|
||||
];
|
||||
|
||||
let right_text = Span::styled(
|
||||
format!(" | {} ", state.settings.model),
|
||||
// Right chunk: provider · model
|
||||
spans.push(Span::styled(
|
||||
format!(" {} · {} ", state.settings.provider, state.settings.model),
|
||||
Style::default().fg(Theme::DIM),
|
||||
);
|
||||
));
|
||||
|
||||
let line = Line::from(vec![left_text, center_text, right_text]);
|
||||
let line = Line::from(spans);
|
||||
|
||||
let block = Block::default()
|
||||
.style(
|
||||
|
||||
@@ -69,11 +69,10 @@ pub fn draw_workflow_panel(frame: &mut Frame, area: Rect, state: &crate::app::st
|
||||
))));
|
||||
}
|
||||
|
||||
let phase_status = match state.mode {
|
||||
crate::app::state::types::AgentMode::Auto => "Auto-running",
|
||||
crate::app::state::types::AgentMode::Normal => "Awaiting input",
|
||||
crate::app::state::types::AgentMode::Plan => "Planning",
|
||||
crate::app::state::types::AgentMode::Yolo => "Full autonomy",
|
||||
let phase_status = if state.turn_in_flight() {
|
||||
"Auto-running"
|
||||
} else {
|
||||
"Awaiting input"
|
||||
};
|
||||
|
||||
items.push(ListItem::new(Line::from(Span::styled(
|
||||
|
||||
Reference in New Issue
Block a user