vtcode_core/tools/registry/
harness.rs1use 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#[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 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 pub fn set_session_id(&self, session_id: impl Into<String>) {
66 self.session_id.store(Arc::new(session_id.into()));
67 }
68
69 pub fn set_task_id(&self, task_id: Option<String>) {
71 self.task_id.store(task_id.map(Arc::new));
72 }
73
74 pub fn session_id(&self) -> String {
76 self.session_id.load().as_ref().clone()
77 }
78
79 pub fn task_id(&self) -> Option<String> {
81 self.task_id.load_full().map(|task_id| (*task_id).clone())
82 }
83
84 pub fn snapshot(&self) -> HarnessContextSnapshot {
86 HarnessContextSnapshot::new(self.session_id(), self.task_id())
87 }
88}