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) tracker_adopted: Arc<AtomicBool>,
21    pub(super) decision_validator:
22        Arc<parking_lot::RwLock<Option<crate::core::agent::events::DecisionEvidenceValidator>>>,
23}
24
25impl std::fmt::Debug for HarnessContext {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        f.debug_struct("HarnessContext")
28            .field("session_id", &self.session_id())
29            .field("task_id", &self.task_id())
30            .finish_non_exhaustive()
31    }
32}
33
34impl Default for HarnessContext {
35    fn default() -> Self {
36        let session_id = SystemTime::now()
37            .duration_since(SystemTime::UNIX_EPOCH)
38            .map(|d| format!("session-{}", d.as_millis()))
39            .unwrap_or_else(|_| "session-unknown".to_string());
40
41        Self {
42            session_id: Arc::new(ArcSwap::from_pointee(session_id)),
43            task_id: Arc::new(ArcSwapOption::empty()),
44            tracker_adopted: Arc::default(),
45            decision_validator: Arc::default(),
46        }
47    }
48}
49
50impl HarnessContext {
51    /// Create a new harness context with a specific session ID.
52    pub fn with_session(session_id: impl Into<String>) -> Self {
53        Self {
54            session_id: Arc::new(ArcSwap::from_pointee(session_id.into())),
55            task_id: Arc::new(ArcSwapOption::empty()),
56            tracker_adopted: Arc::default(),
57            decision_validator: Arc::default(),
58        }
59    }
60
61    /// Set the session ID.
62    pub fn set_session_id(&self, session_id: impl Into<String>) {
63        self.session_id.store(Arc::new(session_id.into()));
64    }
65
66    /// Set the task ID.
67    pub fn set_task_id(&self, task_id: Option<String>) {
68        self.task_id.store(task_id.map(Arc::new));
69    }
70
71    /// Get the current session ID.
72    pub fn session_id(&self) -> String {
73        self.session_id.load().as_ref().clone()
74    }
75
76    /// Get the current task ID.
77    pub fn task_id(&self) -> Option<String> {
78        self.task_id.load_full().map(|task_id| (*task_id).clone())
79    }
80
81    /// Create a snapshot of the current context.
82    pub fn snapshot(&self) -> HarnessContextSnapshot {
83        HarnessContextSnapshot::new(self.session_id(), self.task_id())
84    }
85}