Implement chat and markdown views, enhance status bar, and add workflow panel

- Added `chat.rs` for rendering chat messages with timestamps and roles.
- Introduced `markdown.rs` for rendering markdown content with styling.
- Created `status.rs` to display the application status bar with session and message counts.
- Developed `workflow.rs` to show the current workflow status, including tool calls and active jobs.
- Established a `theme.rs` for centralized color management across the UI.
- Updated `mod.rs` to include new modules and manage rendering logic.
This commit is contained in:
asepharyana
2026-07-11 13:16:10 +07:00
parent 7cb4ae6708
commit cc03bd79b6
131 changed files with 10994 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
use std::path::PathBuf;
use super::spawn::AgentDefinition;
pub const REVIEWER_ALLOWED: &[&str] = &["read", "grep", "glob", "recall", "remember"];
pub struct SubagentContext {
pub definition: AgentDefinition,
pub system_prompt: String,
pub allowed_tools: Vec<String>,
pub max_steps: usize,
pub session_dir: PathBuf,
pub origin: crate::app::state::types::Origin,
}
pub fn build_subagent_context(def: AgentDefinition) -> SubagentContext {
let allowed_tools = def.allowed_tools.clone().unwrap_or_else(|| {
if def.role == "reviewer" {
REVIEWER_ALLOWED.iter().map(|s| s.to_string()).collect()
} else {
Vec::new()
}
});
SubagentContext {
definition: def,
system_prompt: String::new(),
allowed_tools,
max_steps: 25,
session_dir: PathBuf::new(),
origin: crate::app::state::types::Origin::SubAgent,
}
}
+19
View File
@@ -0,0 +1,19 @@
use tokio::sync::mpsc;
use super::context::SubagentContext;
use super::event::SubagentEvent;
pub const MAX_AGENT_STEPS: usize = 25;
pub fn run_subagent(ctx: SubagentContext, tx: mpsc::Sender<SubagentEvent>) -> anyhow::Result<String> {
let mut output = String::new();
for step in 0..ctx.max_steps.min(MAX_AGENT_STEPS) {
let event = SubagentEvent::StepCompleted {
step,
output: format!("step {} completed", step),
};
let _ = tx.blocking_send(event);
output.push_str(&format!("step {} completed\n", step));
}
let _ = tx.blocking_send(SubagentEvent::Completed { output: output.clone() });
Ok(output)
}
+27
View File
@@ -0,0 +1,27 @@
use serde_json::Value;
#[derive(Debug, Clone)]
pub enum SubagentEvent {
StepCompleted {
step: usize,
output: String,
},
StepFailed {
step: usize,
error: String,
},
Completed {
output: String,
},
Failed {
error: String,
},
ToolCall {
tool: String,
args: Value,
},
ToolResult {
tool: String,
output: String,
},
}
+4
View File
@@ -0,0 +1,4 @@
pub mod context;
pub mod engine;
pub mod event;
pub mod spawn;
+55
View File
@@ -0,0 +1,55 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentDefinition {
pub name: String,
pub role: String,
pub system_prompt: Option<String>,
pub allowed_tools: Option<Vec<String>>,
pub max_steps: Option<usize>,
pub temperature: Option<f32>,
}
impl AgentDefinition {
pub fn new(name: String, role: String) -> Self {
AgentDefinition {
name,
role,
system_prompt: None,
allowed_tools: None,
max_steps: None,
temperature: None,
}
}
pub fn with_system_prompt(mut self, prompt: String) -> Self {
self.system_prompt = Some(prompt);
self
}
pub fn with_allowed_tools(mut self, tools: Vec<String>) -> Self {
self.allowed_tools = Some(tools);
self
}
pub fn with_max_steps(mut self, steps: usize) -> Self {
self.max_steps = Some(steps);
self
}
pub fn with_temperature(mut self, temp: f32) -> Self {
self.temperature = Some(temp);
self
}
}
pub fn merge_agent_defs(base: AgentDefinition, overrides: AgentDefinition) -> AgentDefinition {
AgentDefinition {
name: base.name,
role: base.role,
system_prompt: overrides.system_prompt.or(base.system_prompt),
allowed_tools: overrides.allowed_tools.or(base.allowed_tools),
max_steps: overrides.max_steps.or(base.max_steps),
temperature: overrides.temperature.or(base.temperature),
}
}