use std::sync::Arc;
use async_trait::async_trait;
use atomr_agents_callable::CallableHandle;
use crate::content::{InboundMessage, MessageContent};
use crate::error::Result;
#[derive(Clone)]
pub enum ThreadTarget {
Callable(CallableHandle),
Harness {
callable: CallableHandle,
adapter: Arc<dyn HarnessInputAdapter>,
},
}
impl ThreadTarget {
pub fn callable(handle: CallableHandle) -> Self {
Self::Callable(handle)
}
pub fn harness(callable: CallableHandle, adapter: Arc<dyn HarnessInputAdapter>) -> Self {
Self::Harness { callable, adapter }
}
pub fn label(&self) -> &str {
match self {
Self::Callable(c) => c.label(),
Self::Harness { callable, .. } => callable.label(),
}
}
pub fn kind(&self) -> &'static str {
match self {
Self::Callable(_) => "callable",
Self::Harness { .. } => "harness",
}
}
}
impl std::fmt::Debug for ThreadTarget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ThreadTarget")
.field("kind", &self.kind())
.field("label", &self.label())
.finish()
}
}
#[async_trait]
pub trait HarnessInputAdapter: Send + Sync + 'static {
async fn apply(&self, msg: &InboundMessage) -> Result<()>;
fn one_shot(&self) -> bool {
true
}
fn reply_from_result(&self, value: &serde_json::Value) -> Option<MessageContent> {
if let Some(s) = value.get("text").and_then(|v| v.as_str()) {
if !s.is_empty() {
return Some(MessageContent::text(s));
}
}
if let Some(s) = value.as_str() {
if !s.is_empty() {
return Some(MessageContent::text(s));
}
}
None
}
}