Skip to main content

vtcode_core/tools/registry/
harness.rs

1//! Harness context for tool execution tracking.
2//!
3//! This module provides the context wrapper for tracking sessions and tasks
4//! during tool execution.
5
6use arc_swap::{ArcSwap, ArcSwapOption};
7use std::sync::Arc;
8use std::sync::atomic::AtomicBool;
9use std::time::SystemTime;
10
11use super::execution_history::HarnessContextSnapshot;
12
13/// Thread-safe context for harness execution.
14///
15/// Tracks session and task IDs across tool invocations.
16#[derive(Clone)]
17pub struct HarnessContext {
18    session_id: Arc<ArcSwap<String>>,
19    task_id: Arc<ArcSwapOption<String>>,
20    pub(super) completion_verification: Arc<parking_lot::Mutex<super::completion_verification::CompletionVerification>>,
21    pub(super) tracker_adopted: Arc<AtomicBool>,
22    pub(super) decision_validator:
23        Arc<parking_lot::RwLock<Option<crate::core::agent::events::DecisionEvidenceValidator>>>,
24}
25
26impl std::fmt::Debug for HarnessContext {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        f.debug_struct("HarnessContext")
29            .field("session_id", &self.session_id())
30            .field("task_id", &self.task_id())
31            .finish_non_exhaustive()
32    }
33}
34
35impl Default for HarnessContext {
36    fn default() -> Self {
37        let session_id = SystemTime::now()
38            .duration_since(SystemTime::UNIX_EPOCH)
39            .map(|d| format!("session-{}", d.as_millis()))
40            .unwrap_or_else(|_| "session-unknown".to_string());
41
42        Self {
43            session_id: Arc::new(ArcSwap::from_pointee(session_id)),
44            task_id: Arc::new(ArcSwapOption::empty()),
45            tracker_adopted: Arc::default(),
46            completion_verification: Arc::default(),
47            decision_validator: Arc::default(),
48        }
49    }
50}
51
52impl HarnessContext {
53    /// Create a new harness context with a specific session ID.
54    pub fn with_session(session_id: impl Into<String>) -> Self {
55        Self {
56            session_id: Arc::new(ArcSwap::from_pointee(session_id.into())),
57            task_id: Arc::new(ArcSwapOption::empty()),
58            tracker_adopted: Arc::default(),
59            completion_verification: Arc::default(),
60            decision_validator: Arc::default(),
61        }
62    }
63
64    /// Set the session ID.
65    pub fn set_session_id(&self, session_id: impl Into<String>) {
66        self.session_id.store(Arc::new(session_id.into()));
67    }
68
69    /// Set the task ID.
70    pub fn set_task_id(&self, task_id: Option<String>) {
71        self.task_id.store(task_id.map(Arc::new));
72    }
73
74    /// Get the current session ID.
75    pub fn session_id(&self) -> String {
76        self.session_id.load().as_ref().clone()
77    }
78
79    /// Get the current task ID.
80    pub fn task_id(&self) -> Option<String> {
81        self.task_id.load_full().map(|task_id| (*task_id).clone())
82    }
83
84    /// Create a snapshot of the current context.
85    pub fn snapshot(&self) -> HarnessContextSnapshot {
86        HarnessContextSnapshot::new(self.session_id(), self.task_id())
87    }
88}