use async_trait::async_trait;
use turul_a2a_types::{Artifact, Message};
use crate::error::SinkError;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProgressState {
Working,
InputRequired,
AuthRequired,
}
#[async_trait]
pub trait SkillProgressSink: Send + Sync {
async fn set_status(
&self,
state: ProgressState,
message: Option<Message>,
) -> Result<(), SinkError>;
async fn emit_artifact(
&self,
artifact: Artifact,
append: bool,
last_chunk: bool,
) -> Result<(), SinkError>;
fn is_closed(&self) -> bool {
false
}
fn heartbeat(&self) {}
}
const _: fn() = || {
fn assert<T: ?Sized + SkillProgressSink>() {}
assert::<dyn SkillProgressSink>();
};
#[cfg(test)]
mod tests {
use super::ProgressState;
#[test]
fn progress_state_variant_set_is_fixed_and_non_terminal() {
fn label(state: ProgressState) -> &'static str {
match state {
ProgressState::Working => "working",
ProgressState::InputRequired => "input-required",
ProgressState::AuthRequired => "auth-required",
}
}
assert_eq!(
[
ProgressState::Working,
ProgressState::InputRequired,
ProgressState::AuthRequired,
]
.map(label),
["working", "input-required", "auth-required"]
);
}
}