feat: introduce Rig agent runtime migration

This commit is contained in:
2026-08-04 02:15:18 -05:00
parent d9cf0d8ae3
commit 4c7270db8d
39 changed files with 2551 additions and 211 deletions
+144
View File
@@ -0,0 +1,144 @@
use std::error::Error;
use std::fmt;
use std::pin::Pin;
use async_channel::{Receiver, Sender, TrySendError};
use async_trait::async_trait;
use futures::Stream;
use serde::{Deserialize, Serialize};
use crate::{AgentEvent, TurnRequest};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum RuntimeKind {
Provider,
Acp,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct RuntimeCapabilities {
pub model_selection: bool,
pub session_resume: bool,
pub steering: bool,
pub tool_permissions: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct RuntimeDescriptor {
pub id: String,
pub display_name: String,
pub kind: RuntimeKind,
pub capabilities: RuntimeCapabilities,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TurnCommand {
Cancel,
Steer { text: String },
}
#[derive(Clone, Debug)]
pub struct TurnCommandSender(Sender<TurnCommand>);
impl TurnCommandSender {
pub async fn send(&self, command: TurnCommand) -> Result<(), TurnControlClosed> {
self.0.send(command).await.map_err(|_| TurnControlClosed)
}
pub fn try_send(&self, command: TurnCommand) -> Result<(), TrySendError<TurnCommand>> {
self.0.try_send(command)
}
}
#[derive(Clone, Debug)]
pub struct TurnControl(Receiver<TurnCommand>);
impl TurnControl {
pub async fn receive(&self) -> Result<TurnCommand, TurnControlClosed> {
self.0.recv().await.map_err(|_| TurnControlClosed)
}
pub fn try_receive(&self) -> Result<TurnCommand, async_channel::TryRecvError> {
self.0.try_recv()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TurnControlClosed;
impl fmt::Display for TurnControlClosed {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("turn control channel is closed")
}
}
impl Error for TurnControlClosed {}
pub fn turn_control() -> (TurnCommandSender, TurnControl) {
let (sender, receiver) = async_channel::unbounded();
(TurnCommandSender(sender), TurnControl(receiver))
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum AgentErrorKind {
Configuration,
Authentication,
RateLimited,
ContextWindowExceeded,
InvalidRequest,
Transport,
Provider,
Protocol,
Tool,
Cancelled,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct AgentError {
pub kind: AgentErrorKind,
pub message: String,
pub user_message: Option<String>,
pub recoverable: bool,
}
impl AgentError {
pub fn new(kind: AgentErrorKind, message: impl Into<String>) -> Self {
Self {
kind,
message: message.into(),
user_message: None,
recoverable: false,
}
}
}
impl fmt::Display for AgentError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl Error for AgentError {}
#[cfg(not(target_family = "wasm"))]
pub type AgentEventStream =
Pin<Box<dyn Stream<Item = Result<AgentEvent, AgentError>> + Send + 'static>>;
#[cfg(target_family = "wasm")]
pub type AgentEventStream = Pin<Box<dyn Stream<Item = Result<AgentEvent, AgentError>> + 'static>>;
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
#[cfg_attr(not(target_family = "wasm"), async_trait)]
pub trait AgentRuntime: Send + Sync {
fn descriptor(&self) -> &RuntimeDescriptor;
async fn start_turn(
&self,
request: TurnRequest,
control: TurnControl,
) -> Result<AgentEventStream, AgentError>;
}
#[cfg(test)]
#[path = "runtime_tests.rs"]
mod tests;