mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-08 18:33:28 +08:00
feat: persist ecc2 auto-dispatch policy
This commit is contained in:
@@ -73,11 +73,15 @@ impl Config {
|
|||||||
block: 0.85,
|
block: 0.85,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn load() -> Result<Self> {
|
pub fn config_path() -> PathBuf {
|
||||||
let config_path = dirs::home_dir()
|
dirs::home_dir()
|
||||||
.unwrap_or_else(|| PathBuf::from("."))
|
.unwrap_or_else(|| PathBuf::from("."))
|
||||||
.join(".claude")
|
.join(".claude")
|
||||||
.join("ecc2.toml");
|
.join("ecc2.toml")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load() -> Result<Self> {
|
||||||
|
let config_path = Self::config_path();
|
||||||
|
|
||||||
if config_path.exists() {
|
if config_path.exists() {
|
||||||
let content = std::fs::read_to_string(&config_path)?;
|
let content = std::fs::read_to_string(&config_path)?;
|
||||||
@@ -87,6 +91,20 @@ impl Config {
|
|||||||
Ok(Config::default())
|
Ok(Config::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> Result<()> {
|
||||||
|
self.save_to_path(&Self::config_path())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_to_path(&self, path: &std::path::Path) -> Result<()> {
|
||||||
|
if let Some(parent) = path.parent() {
|
||||||
|
std::fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = toml::to_string_pretty(self)?;
|
||||||
|
std::fs::write(path, content)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RiskThresholds {
|
impl Default for RiskThresholds {
|
||||||
@@ -98,6 +116,7 @@ impl Default for RiskThresholds {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{Config, PaneLayout};
|
use super::{Config, PaneLayout};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_includes_positive_budget_thresholds() {
|
fn default_includes_positive_budget_thresholds() {
|
||||||
@@ -153,4 +172,21 @@ theme = "Dark"
|
|||||||
fn default_risk_thresholds_are_applied() {
|
fn default_risk_thresholds_are_applied() {
|
||||||
assert_eq!(Config::default().risk_thresholds, Config::RISK_THRESHOLDS);
|
assert_eq!(Config::default().risk_thresholds, Config::RISK_THRESHOLDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn save_round_trips_auto_dispatch_settings() {
|
||||||
|
let path = std::env::temp_dir().join(format!("ecc2-config-{}.toml", Uuid::new_v4()));
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.auto_dispatch_unread_handoffs = true;
|
||||||
|
config.auto_dispatch_limit_per_session = 9;
|
||||||
|
|
||||||
|
config.save_to_path(&path).unwrap();
|
||||||
|
let content = std::fs::read_to_string(&path).unwrap();
|
||||||
|
let loaded: Config = toml::from_str(&content).unwrap();
|
||||||
|
|
||||||
|
assert!(loaded.auto_dispatch_unread_handoffs);
|
||||||
|
assert_eq!(loaded.auto_dispatch_limit_per_session, 9);
|
||||||
|
|
||||||
|
let _ = std::fs::remove_file(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ pub async fn run(db: StateStore, cfg: Config) -> Result<()> {
|
|||||||
(_, KeyCode::Char('b')) => dashboard.rebalance_selected_team().await,
|
(_, KeyCode::Char('b')) => dashboard.rebalance_selected_team().await,
|
||||||
(_, KeyCode::Char('i')) => dashboard.drain_inbox_selected().await,
|
(_, KeyCode::Char('i')) => dashboard.drain_inbox_selected().await,
|
||||||
(_, KeyCode::Char('g')) => dashboard.auto_dispatch_backlog().await,
|
(_, KeyCode::Char('g')) => dashboard.auto_dispatch_backlog().await,
|
||||||
|
(_, KeyCode::Char('p')) => dashboard.toggle_auto_dispatch_policy(),
|
||||||
(_, KeyCode::Char('s')) => dashboard.stop_selected().await,
|
(_, KeyCode::Char('s')) => dashboard.stop_selected().await,
|
||||||
(_, KeyCode::Char('u')) => dashboard.resume_selected().await,
|
(_, KeyCode::Char('u')) => dashboard.resume_selected().await,
|
||||||
(_, KeyCode::Char('x')) => dashboard.cleanup_selected_worktree().await,
|
(_, KeyCode::Char('x')) => dashboard.cleanup_selected_worktree().await,
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ impl Dashboard {
|
|||||||
|
|
||||||
fn render_status_bar(&self, frame: &mut Frame, area: Rect) {
|
fn render_status_bar(&self, frame: &mut Frame, area: Rect) {
|
||||||
let text = format!(
|
let text = format!(
|
||||||
" [n]ew session [a]ssign re[b]alance dra[i]n inbox [g]lobal dispatch [s]top [u]resume [x]cleanup [d]elete [r]efresh [Tab] switch pane [j/k] scroll [+/-] resize [{}] layout [?] help [q]uit ",
|
" [n]ew session [a]ssign re[b]alance dra[i]n inbox [g]lobal dispatch toggle [p]olicy [s]top [u]resume [x]cleanup [d]elete [r]efresh [Tab] switch pane [j/k] scroll [+/-] resize [{}] layout [?] help [q]uit ",
|
||||||
self.layout_label()
|
self.layout_label()
|
||||||
);
|
);
|
||||||
let text = if let Some(note) = self.operator_note.as_ref() {
|
let text = if let Some(note) = self.operator_note.as_ref() {
|
||||||
@@ -449,6 +449,7 @@ impl Dashboard {
|
|||||||
" b Rebalance backed-up delegate inboxes for selected lead",
|
" b Rebalance backed-up delegate inboxes for selected lead",
|
||||||
" i Drain unread task handoffs from selected session inbox",
|
" i Drain unread task handoffs from selected session inbox",
|
||||||
" g Auto-dispatch unread handoffs across lead sessions",
|
" g Auto-dispatch unread handoffs across lead sessions",
|
||||||
|
" p Toggle daemon auto-dispatch policy and persist config",
|
||||||
" s Stop selected session",
|
" s Stop selected session",
|
||||||
" u Resume selected session",
|
" u Resume selected session",
|
||||||
" x Cleanup selected worktree",
|
" x Cleanup selected worktree",
|
||||||
@@ -910,6 +911,27 @@ impl Dashboard {
|
|||||||
self.show_help = !self.show_help;
|
self.show_help = !self.show_help;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_auto_dispatch_policy(&mut self) {
|
||||||
|
self.cfg.auto_dispatch_unread_handoffs = !self.cfg.auto_dispatch_unread_handoffs;
|
||||||
|
match self.cfg.save() {
|
||||||
|
Ok(()) => {
|
||||||
|
let state = if self.cfg.auto_dispatch_unread_handoffs {
|
||||||
|
"enabled"
|
||||||
|
} else {
|
||||||
|
"disabled"
|
||||||
|
};
|
||||||
|
self.set_operator_note(format!(
|
||||||
|
"daemon auto-dispatch {state} | saved to {}",
|
||||||
|
crate::config::Config::config_path().display()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
self.cfg.auto_dispatch_unread_handoffs = !self.cfg.auto_dispatch_unread_handoffs;
|
||||||
|
self.set_operator_note(format!("failed to persist auto-dispatch policy: {error}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn tick(&mut self) {
|
pub async fn tick(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
match self.output_rx.try_recv() {
|
match self.output_rx.try_recv() {
|
||||||
|
|||||||
Reference in New Issue
Block a user