From 79e2bfcc9ca67424ca2b34a5652d3c2bb93291bf Mon Sep 17 00:00:00 2001 From: asepharyana Date: Tue, 14 Jul 2026 09:37:53 +0700 Subject: [PATCH] feat(tool): tambah abort_flag ke ToolCtx dan sambungkan dari session state Co-Authored-By: Claude Sonnet 5 --- src/app/state/rest.rs | 23 +++++++++++++++++++++++ src/tool/mod.rs | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/app/state/rest.rs b/src/app/state/rest.rs index fbeb388..e88ddaf 100644 --- a/src/app/state/rest.rs +++ b/src/app/state/rest.rs @@ -283,6 +283,29 @@ impl AppStateRest { lsp_manager: self.lsp_manager.clone(), turn_events: Some(self.turn_events.clone()), workflow_findings: None, + abort_flag: Some(self.abort_flag.clone()), } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tool_ctx_for_shares_the_session_abort_flag() { + let tmp = std::env::temp_dir().join(format!("zesdex-rest-test-{}", uuid::Uuid::new_v4())); + std::fs::create_dir_all(&tmp).unwrap(); + let state = AppStateRest::new(vec![tmp.clone()], &tmp, tmp.join("memory")); + + let ctx = state.tool_ctx_for(Origin::Main); + + assert!(ctx.abort_flag.is_some()); + assert!(std::sync::Arc::ptr_eq( + ctx.abort_flag.as_ref().unwrap(), + &state.abort_flag, + )); + + std::fs::remove_dir_all(&tmp).ok(); + } +} diff --git a/src/tool/mod.rs b/src/tool/mod.rs index 4e830c3..69b7d35 100644 --- a/src/tool/mod.rs +++ b/src/tool/mod.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; use std::sync::{Arc, Mutex}; +use std::sync::atomic::AtomicBool; use serde_json::Value; use anyhow::Result; @@ -56,6 +57,11 @@ pub struct ToolCtx { /// reference earlier results. `None` means "not inside a workflow" — /// `note_finding` becomes a no-op. pub workflow_findings: Option>>>, + /// The current turn's abort flag, threaded through so tools that + /// delegate to long-running orchestration (e.g. the `hive_mind` tool) + /// can be cancelled the same way the main agent loop is. `None` when + /// no turn-level abort flag is available. + pub abort_flag: Option>, } /// Find which graduated checks apply to a given file path/content pair. @@ -93,6 +99,7 @@ pub struct ToolCtxBuilder { pub lsp_manager: Arc>, pub turn_events: Option>>>, pub workflow_findings: Option>>>, + pub abort_flag: Option>, } impl Default for ToolCtxBuilder { @@ -108,6 +115,7 @@ impl Default for ToolCtxBuilder { lsp_manager: Arc::new(Mutex::new(crate::app::lsp::LspManager::new())), turn_events: None, workflow_findings: None, + abort_flag: None, } } } @@ -135,6 +143,7 @@ impl ToolCtxBuilder { lsp_manager: self.lsp_manager, turn_events: self.turn_events, workflow_findings: self.workflow_findings, + abort_flag: self.abort_flag, } } } @@ -264,3 +273,14 @@ pub fn resolve_path(workspaces: &[PathBuf], rel: &str) -> Result { anyhow::bail!("path '{rel}' is outside all workspace roots") } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tool_ctx_builder_defaults_abort_flag_to_none() { + let ctx = ToolCtx::builder().build(); + assert!(ctx.abort_flag.is_none()); + } +}