use crate::types::contract::DelegationContract;
use crate::types::error::LdpError;
use async_trait::async_trait;
use futures::Stream;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::pin::Pin;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoteSkill {
pub name: String,
pub description: Option<String>,
pub input_schema: Option<Value>,
pub output_schema: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoteCapabilities {
pub name: String,
pub description: Option<String>,
pub skills: Vec<RemoteSkill>,
pub protocols: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskRequest {
pub skill: String,
pub input: Value,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub contract: Option<DelegationContract>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskHandle {
pub task_id: String,
pub remote_url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskEvent {
Progress {
message: String,
progress: Option<f32>,
},
Completed { output: Value },
Failed { error: LdpError },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskStatus {
Submitted,
Working,
Completed { output: Value },
Failed { error: LdpError },
}
pub type TaskStream = Pin<Box<dyn Stream<Item = TaskEvent> + Send>>;
#[async_trait]
pub trait ProtocolAdapter: Send + Sync {
async fn discover(&self, url: &str) -> Result<RemoteCapabilities, String>;
async fn invoke(&self, url: &str, task: TaskRequest) -> Result<TaskHandle, String>;
async fn stream(&self, url: &str, task: TaskRequest) -> Result<TaskStream, String>;
async fn status(&self, url: &str, task_id: &str) -> Result<TaskStatus, String>;
async fn cancel(&self, url: &str, task_id: &str) -> Result<(), String>;
}
pub struct ProtocolRegistry {
adapters: Vec<(String, std::sync::Arc<dyn ProtocolAdapter>, Vec<String>)>,
}
impl ProtocolRegistry {
pub fn new() -> Self {
Self {
adapters: Vec::new(),
}
}
pub fn register(
&mut self,
name: &str,
adapter: std::sync::Arc<dyn ProtocolAdapter>,
url_prefixes: Vec<&str>,
) {
self.adapters.push((
name.to_string(),
adapter,
url_prefixes.iter().map(|s| s.to_string()).collect(),
));
}
pub fn adapter(&self, name: &str) -> Option<&dyn ProtocolAdapter> {
self.adapters
.iter()
.find(|(n, _, _)| n == name)
.map(|(_, a, _)| a.as_ref())
}
pub fn adapter_for_url(&self, url: &str) -> Option<&dyn ProtocolAdapter> {
self.adapters
.iter()
.find(|(_, _, prefixes)| prefixes.iter().any(|p| url.starts_with(p)))
.map(|(_, a, _)| a.as_ref())
}
pub fn protocols(&self) -> Vec<&str> {
self.adapters.iter().map(|(n, _, _)| n.as_str()).collect()
}
}
impl Default for ProtocolRegistry {
fn default() -> Self {
Self::new()
}
}