use serde::{Deserialize, Serialize};
use super::lifecycle::{AgentLifecycleEvent, AgentLifecycleState};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SubagentTerminalStatus {
Success,
Failure,
Cancellation,
Timeout,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct AgentRunRef {
pub session_id: String,
pub run_id: String,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct DelegatedRunLineage {
pub parent: AgentRunRef,
pub child: AgentRunRef,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct DelegatedJoinBoundaries {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wait_started_at_ms: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub result_processing_started_at_ms: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub result_processing_completed_at_ms: Option<i64>,
}
impl DelegatedJoinBoundaries {
#[must_use]
pub fn wait_ms(&self, joined_at_ms: i64) -> Option<u64> {
u64::try_from(joined_at_ms.checked_sub(self.wait_started_at_ms?)?).ok()
}
#[must_use]
pub fn result_processing_ms(&self) -> Option<u64> {
u64::try_from(
self.result_processing_completed_at_ms?
.checked_sub(self.result_processing_started_at_ms?)?,
)
.ok()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FsWatchEvent {
pub kind: String,
pub paths: Vec<String>,
pub relative_paths: Vec<String>,
pub raw_kind: String,
pub error: Option<String>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum WorkerEvent {
WorkerSpawned,
WorkerProgressed,
WorkerWaitingForInput,
WorkerSuspended,
WorkerResumed,
WorkerCompleted,
WorkerFailed,
WorkerStopped,
WorkerCancelled,
}
impl WorkerEvent {
pub const ALL: [Self; 9] = [
Self::WorkerSpawned,
Self::WorkerProgressed,
Self::WorkerWaitingForInput,
Self::WorkerSuspended,
Self::WorkerResumed,
Self::WorkerCompleted,
Self::WorkerFailed,
Self::WorkerStopped,
Self::WorkerCancelled,
];
pub const fn lifecycle_event(self) -> AgentLifecycleEvent {
match self {
Self::WorkerSpawned => AgentLifecycleEvent::Spawned,
Self::WorkerProgressed => AgentLifecycleEvent::Progressed,
Self::WorkerWaitingForInput => AgentLifecycleEvent::WaitingForInput,
Self::WorkerSuspended => AgentLifecycleEvent::Suspended,
Self::WorkerResumed => AgentLifecycleEvent::Resumed,
Self::WorkerCompleted => AgentLifecycleEvent::Completed,
Self::WorkerFailed => AgentLifecycleEvent::Failed,
Self::WorkerStopped => AgentLifecycleEvent::Stopped,
Self::WorkerCancelled => AgentLifecycleEvent::Cancelled,
}
}
pub fn as_status(self) -> &'static str {
self.lifecycle_event()
.target_state()
.expect("worker events always target a lifecycle state")
.wire_name()
}
pub fn as_str(self) -> &'static str {
match self {
Self::WorkerSpawned => "WorkerSpawned",
Self::WorkerProgressed => "WorkerProgressed",
Self::WorkerWaitingForInput => "WorkerWaitingForInput",
Self::WorkerSuspended => "WorkerSuspended",
Self::WorkerResumed => "WorkerResumed",
Self::WorkerCompleted => "WorkerCompleted",
Self::WorkerFailed => "WorkerFailed",
Self::WorkerStopped => "WorkerStopped",
Self::WorkerCancelled => "WorkerCancelled",
}
}
pub fn is_terminal(self) -> bool {
self.lifecycle_event()
.target_state()
.is_some_and(AgentLifecycleState::is_terminal)
}
pub fn from_status(status: &str) -> Option<Self> {
match AgentLifecycleState::from_wire(status)? {
AgentLifecycleState::Running => Some(Self::WorkerSpawned),
AgentLifecycleState::Progressed => Some(Self::WorkerProgressed),
AgentLifecycleState::AwaitingInput => Some(Self::WorkerWaitingForInput),
AgentLifecycleState::Suspended => Some(Self::WorkerSuspended),
AgentLifecycleState::Completed => Some(Self::WorkerCompleted),
AgentLifecycleState::Failed => Some(Self::WorkerFailed),
AgentLifecycleState::Stopped => Some(Self::WorkerStopped),
AgentLifecycleState::Cancelled => Some(Self::WorkerCancelled),
}
}
pub fn status_is_terminal(status: &str) -> bool {
AgentLifecycleState::status_is_terminal(status)
}
}