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:
@@ -0,0 +1,172 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::app::state::rest::AppStateRest;
|
||||
use crate::app::state::types::{AgentMode, Origin, Toast, ToastKind};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub enum Confidence {
|
||||
Human,
|
||||
Verified,
|
||||
Unverified,
|
||||
Auto,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub enum LessonLifecycle {
|
||||
New,
|
||||
Active,
|
||||
Stale,
|
||||
Contradicted,
|
||||
Superseded,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub enum LessonScope {
|
||||
Project,
|
||||
Global,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Provenance {
|
||||
pub session_turn: String,
|
||||
pub session_id: String,
|
||||
pub reviewer: Origin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Lesson {
|
||||
pub name: String,
|
||||
pub content: String,
|
||||
pub confidence: Confidence,
|
||||
pub outcome: Option<String>,
|
||||
pub lifecycle: LessonLifecycle,
|
||||
pub scope: LessonScope,
|
||||
pub contradiction_with: Option<String>,
|
||||
pub provenance: Provenance,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ViolationEscalation {
|
||||
None,
|
||||
Warning,
|
||||
Escalate,
|
||||
Block,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ShadowStatus {
|
||||
Trial,
|
||||
Graduated,
|
||||
Rejected,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ShadowCheck {
|
||||
pub pattern: String,
|
||||
pub trial_window: u32,
|
||||
pub trial_count: u32,
|
||||
pub trial_passed: u32,
|
||||
pub status: ShadowStatus,
|
||||
}
|
||||
|
||||
pub struct ReviewSystem {
|
||||
pub pending: bool,
|
||||
pub queue_capacity: usize,
|
||||
pub repeated_violations: HashMap<String, u32>,
|
||||
pub shadow_violations: Vec<ShadowCheck>,
|
||||
pub violation_window: u32,
|
||||
}
|
||||
|
||||
impl ReviewSystem {
|
||||
pub fn new() -> Self {
|
||||
ReviewSystem {
|
||||
pending: false,
|
||||
queue_capacity: 1,
|
||||
repeated_violations: HashMap::new(),
|
||||
shadow_violations: Vec::new(),
|
||||
violation_window: 10,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.pending = false;
|
||||
}
|
||||
|
||||
pub fn check_escalation(&self, pattern: &str) -> ViolationEscalation {
|
||||
let count = self.repeated_violations.get(pattern).copied().unwrap_or(0);
|
||||
match count {
|
||||
0 | 1 => ViolationEscalation::None,
|
||||
2 => ViolationEscalation::Warning,
|
||||
3 | 4 => ViolationEscalation::Escalate,
|
||||
_ => ViolationEscalation::Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn increment_violation(&mut self, pattern: &str) -> ViolationEscalation {
|
||||
let entry = self.repeated_violations.entry(pattern.to_string()).or_insert(0);
|
||||
*entry += 1;
|
||||
self.check_escalation(pattern)
|
||||
}
|
||||
|
||||
pub fn should_skip_review(consecutive_empty: u32) -> bool {
|
||||
consecutive_empty >= 3
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_pending_lesson(name: &str, content: &str, provenance: Provenance) -> Lesson {
|
||||
Lesson {
|
||||
name: name.to_string(),
|
||||
content: content.to_string(),
|
||||
confidence: Confidence::Unverified,
|
||||
outcome: None,
|
||||
lifecycle: LessonLifecycle::New,
|
||||
scope: LessonScope::Project,
|
||||
contradiction_with: None,
|
||||
provenance,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_lesson_calibration(state: &mut AppStateRest, lesson: &Lesson) {
|
||||
if lesson.confidence != Confidence::Unverified {
|
||||
return;
|
||||
}
|
||||
if state.mode.auto_approve() {
|
||||
return;
|
||||
}
|
||||
state.push_toast(Toast::new(
|
||||
ToastKind::Lesson,
|
||||
format!("Lesson '{}' is pending review. Keep or discard?", lesson.name),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn should_trigger_review(state: &AppStateRest, origin: Origin) -> bool {
|
||||
if state.mode == AgentMode::Plan {
|
||||
return false;
|
||||
}
|
||||
if origin != Origin::Main {
|
||||
return false;
|
||||
}
|
||||
let runtime = match &state.session_runtime {
|
||||
Some(r) => r,
|
||||
None => return false,
|
||||
};
|
||||
if !state.settings.review_enabled {
|
||||
return false;
|
||||
}
|
||||
if runtime.edit_count > 0 && runtime.edit_count % 5 == 0 {
|
||||
return true;
|
||||
}
|
||||
if runtime.consecutive_empty_reviews >= state.settings.adaptive_review_max_skip {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn trigger_review(state: &mut AppStateRest) -> anyhow::Result<()> {
|
||||
let _origin = Origin::Reviewer;
|
||||
state.push_transcript(crate::app::state::rest::ChatMessageDisplay::new(
|
||||
crate::dto::chat::message::Role::System,
|
||||
"review triggered".to_string(),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user