use std::sync::{Arc, Mutex};
use crate::normalizer::ToolDispatchAction;
#[derive(Debug, Clone, PartialEq)]
pub enum DispatchTraceEvent {
HookBefore {
invocation_index: usize,
hook_index: usize,
decision: TracedAction,
},
HookBeforeError {
invocation_index: usize,
hook_index: usize,
message: String,
},
HookCleanup {
invocation_index: usize,
hook_index: usize,
},
HookAfter {
invocation_index: usize,
hook_index: usize,
},
InvocationOutcome {
invocation_index: usize,
outcome: TracedOutcome,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum TracedAction {
Continue,
Skip { reason: Option<String> },
Terminate { reason: String },
}
impl From<&ToolDispatchAction> for TracedAction {
fn from(value: &ToolDispatchAction) -> Self {
match value {
ToolDispatchAction::Continue => TracedAction::Continue,
ToolDispatchAction::Skip { reason, .. } => TracedAction::Skip {
reason: reason.clone(),
},
ToolDispatchAction::Terminate { reason } => TracedAction::Terminate {
reason: reason.clone(),
},
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TracedOutcome {
Completed,
Skipped { reason: Option<String> },
Terminated { reason: String },
Failed { message: String },
}
#[derive(Debug, Default, Clone)]
pub struct DispatchTrace {
inner: Arc<Mutex<Vec<DispatchTraceEvent>>>,
}
impl DispatchTrace {
pub fn new() -> Self {
Self::default()
}
pub(crate) fn push(&self, event: DispatchTraceEvent) {
if let Ok(mut guard) = self.inner.lock() {
guard.push(event);
}
}
pub fn events(&self) -> Vec<DispatchTraceEvent> {
self.inner
.lock()
.map(|guard| guard.clone())
.unwrap_or_default()
}
pub fn len(&self) -> usize {
self.inner.lock().map(|g| g.len()).unwrap_or(0)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}