use std::{borrow::Cow, fmt, sync::Arc};
use serde::{Deserialize, Serialize};
use crate::{
completion::{CompletionRequest, CompletionResponse, ModelRef, ProviderCapabilities},
embeddings::EmbeddingResponse,
error::ErrorReport,
operation::RerankRequest,
rerank::RerankResponse,
streaming::StreamRecord,
tool::ToolResult,
vector_store::request::{Filter, VectorSearchRequest},
wasm_compat::WasmCompatSend,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct EffectId(u64);
impl EffectId {
pub const fn from_raw(raw: u64) -> Self {
Self(raw)
}
pub const fn as_u64(self) -> u64 {
self.0
}
}
impl fmt::Display for EffectId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "effect:{}", self.0)
}
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct HandlerKey(Arc<str>);
impl HandlerKey {
pub fn new(key: impl Into<Arc<str>>) -> Self {
Self(key.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn parts(&self) -> KeyParts {
KeyParts::parse(&self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyParts {
pub owner: Option<Arc<str>>,
pub kind: Option<Arc<str>>,
pub label: Arc<str>,
pub generation: Option<u64>,
}
impl KeyParts {
pub fn parse(key: &str) -> Self {
let (owner, rest) = match key.split_once('/') {
Some((owner, rest)) if !owner.is_empty() && !rest.is_empty() => {
(Some(Arc::from(owner)), rest)
}
_ => (None, key),
};
let (rest, generation) = match rest.rsplit_once('#') {
Some((head, digits))
if !digits.is_empty()
&& (digits.len() == 1 || !digits.starts_with('0'))
&& digits.bytes().all(|b| b.is_ascii_digit()) =>
{
match digits.parse::<u64>() {
Ok(generation) => (head, Some(generation)),
Err(_) => (rest, None),
}
}
_ => (rest, None),
};
let (kind, label) = match rest.split_once(':') {
Some((kind, label)) if !kind.is_empty() && !label.is_empty() => {
(Some(Arc::from(kind)), label)
}
_ => (None, rest),
};
Self {
owner,
kind,
label: Arc::from(label),
generation,
}
}
}
impl fmt::Display for KeyParts {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(owner) = &self.owner {
write!(f, "{owner}/")?;
}
if let Some(kind) = &self.kind {
write!(f, "{kind}:")?;
}
f.write_str(&self.label)?;
if let Some(generation) = self.generation {
write!(f, "#{generation}")?;
}
Ok(())
}
}
impl fmt::Debug for HandlerKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "HandlerKey({:?})", &*self.0)
}
}
impl fmt::Display for HandlerKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl From<&str> for HandlerKey {
fn from(key: &str) -> Self {
Self(Arc::from(key))
}
}
impl From<String> for HandlerKey {
fn from(key: String) -> Self {
Self(Arc::from(key))
}
}
impl AsRef<str> for HandlerKey {
fn as_ref(&self) -> &str {
&self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EffectFamily {
Completion,
Tool,
Embed,
Rerank,
Retrieve,
Custom,
}
impl EffectFamily {
pub const fn name(self) -> &'static str {
match self {
Self::Completion => "completion",
Self::Tool => "tool_call",
Self::Embed => "embed",
Self::Rerank => "rerank",
Self::Retrieve => "retrieve",
Self::Custom => "custom",
}
}
}
impl fmt::Display for EffectFamily {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
pub trait Family: sealed::Sealed + Clone + Copy + Send + Sync + 'static {
const FAMILY: EffectFamily;
type Request: WasmCompatSend + 'static;
type Answer: WasmCompatSend + 'static;
fn wrap(request: Self::Request) -> Result<EffectKind, ErrorReport>;
fn unwrap(outcome: Answered) -> Result<Self::Answer, ErrorReport>;
fn mismatch(outcome: &Answered) -> ErrorReport {
ErrorReport::new(
crate::error::ErrorKind::Internal,
format!(
"expected a {} outcome, the handler answered {}",
Self::FAMILY,
outcome.family()
),
)
}
}
mod sealed {
pub trait Sealed {}
}
pub trait Served: sealed::Sealed + 'static {
const SERVED: Option<EffectFamily>;
}
#[diagnostic::do_not_recommend]
impl<F: Family> Served for F {
const SERVED: Option<EffectFamily> = Some(F::FAMILY);
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolCallRequest {
pub name: String,
pub args: String,
}
pub trait CustomEffect: Serialize + serde::de::DeserializeOwned + WasmCompatSend + 'static {
const KIND: &'static str;
type Answer: Serialize + serde::de::DeserializeOwned + WasmCompatSend + 'static;
}
mod key;
pub use key::Key;
pub fn model_key(label: &str) -> HandlerKey {
HandlerKey::from(format!("model:{label}"))
}
pub fn tool_key(name: &str) -> HandlerKey {
HandlerKey::from(format!("tool:{name}"))
}
pub fn embed_key(label: &str) -> HandlerKey {
HandlerKey::from(format!("embed:{label}"))
}
pub fn rerank_key(label: &str) -> HandlerKey {
HandlerKey::from(format!("rerank:{label}"))
}
pub fn retrieve_key(label: &str) -> HandlerKey {
HandlerKey::from(format!("retrieve:{label}"))
}
pub mod family {
use std::marker::PhantomData;
use super::{
Answered, CustomEffect, EffectFamily, EffectKind, EmbedInputs, EmbedOutputs, Family,
RetrieveQuery, RetrievedDocuments, ToolCallRequest, sealed::Sealed,
};
use crate::{
completion::{CompletionRequest, CompletionResponse},
error::{ErrorKind, ErrorReport},
operation::RerankRequest,
rerank::RerankResponse,
tool::ToolResult,
};
macro_rules! marker {
($($(#[$doc:meta])* $name:ident => $family:ident, $request:ty, $answer:ty, $wrap:expr, $unwrap:expr;)+) => {$(
$(#[$doc])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct $name;
impl Sealed for $name {}
impl Family for $name {
const FAMILY: EffectFamily = EffectFamily::$family;
type Request = $request;
type Answer = $answer;
fn wrap(request: Self::Request) -> Result<EffectKind, ErrorReport> {
let wrap: fn(Self::Request) -> EffectKind = $wrap;
Ok(wrap(request))
}
fn unwrap(outcome: Answered) -> Result<Self::Answer, ErrorReport> {
let unwrap: fn(Answered) -> Result<Self::Answer, ErrorReport> = $unwrap;
unwrap(outcome)
}
}
)+};
}
marker! {
Completion => Completion, CompletionRequest, CompletionResponse,
|request| EffectKind::Completion { request: std::sync::Arc::new(request), stream: false },
|outcome| match outcome {
Answered::Completion(response) => Ok(std::sync::Arc::unwrap_or_clone(response)),
other => Err(Completion::mismatch(&other)),
};
Tool => Tool, ToolCallRequest, ToolResult,
|request| EffectKind::ToolCall { name: request.name, args: request.args },
|outcome| match outcome {
Answered::ToolResult { result } => Ok(result),
other => Err(Tool::mismatch(&other)),
};
Embed => Embed, EmbedInputs, EmbedOutputs,
|inputs| EffectKind::Embed { inputs },
|outcome| match outcome {
Answered::Embeddings(outputs) => Ok(outputs),
other => Err(Embed::mismatch(&other)),
};
Rerank => Rerank, RerankRequest, RerankResponse,
|request| EffectKind::Rerank { request },
|outcome| match outcome {
Answered::Reranked(response) => Ok(response),
other => Err(Rerank::mismatch(&other)),
};
Retrieve => Retrieve, RetrieveQuery, RetrievedDocuments,
|query| EffectKind::Retrieve { query },
|outcome| match outcome {
Answered::Documents(documents) => Ok(documents),
other => Err(Retrieve::mismatch(&other)),
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Dynamic;
impl Sealed for Dynamic {}
impl super::Served for Dynamic {
const SERVED: Option<EffectFamily> = None;
}
pub struct Custom<E: CustomEffect>(PhantomData<fn() -> E>);
impl<E: CustomEffect> Custom<E> {
pub const fn new() -> Self {
Self(PhantomData)
}
}
impl<E: CustomEffect> Clone for Custom<E> {
fn clone(&self) -> Self {
*self
}
}
impl<E: CustomEffect> Copy for Custom<E> {}
impl<E: CustomEffect> Default for Custom<E> {
fn default() -> Self {
Self::new()
}
}
impl<E: CustomEffect> std::fmt::Debug for Custom<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Custom<{}>", E::KIND)
}
}
impl<E: CustomEffect> PartialEq for Custom<E> {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl<E: CustomEffect> Eq for Custom<E> {}
impl<E: CustomEffect> std::hash::Hash for Custom<E> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
E::KIND.hash(state);
}
}
impl<E: CustomEffect> Sealed for Custom<E> {}
impl<E: CustomEffect> Family for Custom<E> {
const FAMILY: EffectFamily = EffectFamily::Custom;
type Request = E;
type Answer = E::Answer;
fn wrap(request: E) -> Result<EffectKind, ErrorReport> {
serde_json::to_value(&request)
.map(|payload| EffectKind::Custom {
kind: std::sync::Arc::from(E::KIND),
payload,
})
.map_err(|error| {
ErrorReport::new(
ErrorKind::Request,
format!("the `{}` effect did not serialize: {error}", E::KIND),
)
})
}
fn unwrap(outcome: Answered) -> Result<E::Answer, ErrorReport> {
match outcome {
Answered::Custom { payload: value } => {
serde_json::from_value(value).map_err(|error| {
ErrorReport::new(
ErrorKind::Internal,
format!(
"the answer to the `{}` effect did not deserialize: {error}",
E::KIND
),
)
})
}
other => Err(Self::mismatch(&other)),
}
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HandlerDescriptor {
pub key: HandlerKey,
pub family: FamilyDescriptor,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub layers: Vec<String>,
}
impl HandlerDescriptor {
pub fn tool(name: &str, description: impl Into<String>, parameters: serde_json::Value) -> Self {
Self {
key: tool_key(name),
family: FamilyDescriptor::Tool {
name: name.to_owned(),
description: description.into(),
parameters,
embedding: None,
},
layers: Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "family", rename_all = "snake_case")]
pub enum FamilyDescriptor {
Completion {
model: ModelRef,
capabilities: ProviderCapabilities,
},
Tool {
name: String,
description: String,
parameters: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
embedding: Option<ToolEmbeddingDescriptor>,
},
Embed {
model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
dims: Option<usize>,
max_documents: usize,
modality: EmbedModality,
},
Rerank {
model: String,
max_documents: usize,
},
Retrieve {},
Custom {
kind: String,
},
}
impl FamilyDescriptor {
pub const fn family(&self) -> EffectFamily {
match self {
Self::Completion { .. } => EffectFamily::Completion,
Self::Tool { .. } => EffectFamily::Tool,
Self::Embed { .. } => EffectFamily::Embed,
Self::Rerank { .. } => EffectFamily::Rerank,
Self::Retrieve {} => EffectFamily::Retrieve,
Self::Custom { .. } => EffectFamily::Custom,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolEmbeddingDescriptor {
pub context: serde_json::Value,
pub embedding_docs: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EmbedModality {
Text,
Image,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "effect", rename_all = "snake_case")]
pub enum EffectKind {
Completion {
request: Arc<CompletionRequest>,
stream: bool,
},
ToolCall {
name: String,
args: String,
},
Embed {
inputs: EmbedInputs,
},
Rerank {
request: RerankRequest,
},
Retrieve {
query: RetrieveQuery,
},
Custom {
kind: Arc<str>,
payload: serde_json::Value,
},
}
impl From<&crate::message::ToolCall> for EffectKind {
fn from(call: &crate::message::ToolCall) -> Self {
Self::ToolCall {
name: call.function.name.as_str().to_owned(),
args: call.function.raw_arguments(),
}
}
}
impl EffectKind {
pub const fn family(&self) -> EffectFamily {
match self {
Self::Completion { .. } => EffectFamily::Completion,
Self::ToolCall { .. } => EffectFamily::Tool,
Self::Embed { .. } => EffectFamily::Embed,
Self::Rerank { .. } => EffectFamily::Rerank,
Self::Retrieve { .. } => EffectFamily::Retrieve,
Self::Custom { .. } => EffectFamily::Custom,
}
}
pub fn name(&self) -> &str {
match self {
Self::Custom { kind, .. } => kind,
Self::Completion { .. }
| Self::ToolCall { .. }
| Self::Embed { .. }
| Self::Rerank { .. }
| Self::Retrieve { .. } => self.family().name(),
}
}
pub const fn streams(&self) -> bool {
match self {
Self::Completion { stream, .. } => *stream,
Self::ToolCall { .. }
| Self::Embed { .. }
| Self::Rerank { .. }
| Self::Retrieve { .. }
| Self::Custom { .. } => false,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "modality", content = "inputs", rename_all = "snake_case")]
pub enum EmbedInputs {
Texts(Vec<String>),
Images(Vec<Vec<u8>>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "query", rename_all = "snake_case")]
pub enum RetrieveQuery {
TopN {
req: VectorSearchRequest<Filter<serde_json::Value>>,
},
TopNIds {
req: VectorSearchRequest<Filter<serde_json::Value>>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "outcome", rename_all = "snake_case")]
pub enum Answered {
Completion(Arc<CompletionResponse>),
ToolResult {
result: ToolResult,
},
Embeddings(EmbedOutputs),
Reranked(RerankResponse),
Documents(RetrievedDocuments),
Custom {
payload: serde_json::Value,
},
}
impl Answered {
pub const fn family(&self) -> EffectFamily {
match self {
Self::Completion(_) => EffectFamily::Completion,
Self::ToolResult { .. } => EffectFamily::Tool,
Self::Embeddings(_) => EffectFamily::Embed,
Self::Reranked(_) => EffectFamily::Rerank,
Self::Documents(_) => EffectFamily::Retrieve,
Self::Custom { .. } => EffectFamily::Custom,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "modality", content = "response", rename_all = "snake_case")]
pub enum EmbedOutputs {
Texts(EmbeddingResponse),
Images(EmbeddingResponse),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "retrieved", content = "results", rename_all = "snake_case")]
pub enum RetrievedDocuments {
Scored(Vec<(f64, String, serde_json::Value)>),
Ids(Vec<(f64, String)>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EffectRecord {
#[serde(rename = "tool_output", deserialize_with = "Option::deserialize")]
pub published: Option<crate::tool::ToolResultContext>,
pub id: EffectId,
pub key: HandlerKey,
pub kind: EffectKind,
pub outcome: Result<Answered, ErrorReport>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub events: Option<StreamRecord>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_origin: Option<crate::message::Origin>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<EffectId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub scope: Option<std::sync::Arc<str>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub purpose: Option<std::borrow::Cow<'static, str>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub turn: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_ms: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub finished_ms: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reviewed: Option<Result<Answered, ErrorReport>>,
#[serde(default, skip_serializing_if = "Disposition::is_ran")]
pub disposition: Disposition,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub decided_by: Option<Decider>,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Decider {
Person,
Plugin(Cow<'static, str>),
}
impl Decider {
pub fn plugin(name: impl Into<Cow<'static, str>>) -> Self {
Self::Plugin(name.into())
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Disposition {
#[default]
Ran,
AnsweredBeforeStart,
AnsweredWhileRunning,
Superseded,
Cancelled,
}
impl EffectRecord {
pub fn new(
id: EffectId,
key: HandlerKey,
kind: EffectKind,
outcome: Result<Answered, ErrorReport>,
) -> Self {
Self {
published: None,
id,
key,
kind,
outcome,
events: None,
stream_origin: None,
parent: None,
scope: None,
purpose: None,
turn: None,
started_ms: None,
finished_ms: None,
reviewed: None,
disposition: Disposition::Ran,
decided_by: None,
}
}
}
impl Disposition {
fn is_ran(&self) -> bool {
*self == Self::Ran
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct EffectRow(std::collections::BTreeMap<HandlerKey, EffectFamily>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RowGap {
pub key: HandlerKey,
pub needed: EffectFamily,
pub served: Option<EffectFamily>,
}
impl std::fmt::Display for RowGap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.served {
Some(served) => write!(
f,
"`{}` is needed as {} but served as {served}",
self.key, self.needed
),
None => write!(f, "`{}` ({}) is not served", self.key, self.needed),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RowDiff {
Missing {
key: HandlerKey,
family: EffectFamily,
},
Extra {
key: HandlerKey,
family: EffectFamily,
},
Family {
key: HandlerKey,
this: EffectFamily,
other: EffectFamily,
},
}
impl std::fmt::Display for RowDiff {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Missing { key, family } => write!(f, "`{key}` ({family}) is missing"),
Self::Extra { key, family } => write!(f, "`{key}` ({family}) is extra"),
Self::Family { key, this, other } => {
write!(f, "`{key}` is {this} here and {other} there")
}
}
}
}
impl EffectRow {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, key: HandlerKey, family: EffectFamily) -> Option<EffectFamily> {
self.0.insert(key, family)
}
pub fn insert_if_absent(&mut self, key: HandlerKey, family: EffectFamily) {
self.0.entry(key).or_insert(family);
}
pub fn remove(&mut self, key: &HandlerKey) -> Option<EffectFamily> {
self.0.remove(key)
}
pub fn get(&self, key: &HandlerKey) -> Option<&EffectFamily> {
self.0.get(key)
}
pub fn contains_key(&self, key: &HandlerKey) -> bool {
self.0.contains_key(key)
}
pub fn keys(&self) -> impl Iterator<Item = &HandlerKey> {
self.0.keys()
}
pub fn iter(&self) -> impl Iterator<Item = (&HandlerKey, &EffectFamily)> {
self.0.iter()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn is_subset_of(&self, handlers: &[HandlerDescriptor]) -> Result<(), RowGap> {
for (key, needed) in &self.0 {
let served = handlers
.iter()
.find(|descriptor| &descriptor.key == key)
.map(|descriptor| descriptor.family.family());
match served {
Some(served) if served == *needed => {}
served => {
return Err(RowGap {
key: key.clone(),
needed: *needed,
served,
});
}
}
}
Ok(())
}
pub fn diff(&self, other: &EffectRow) -> Vec<RowDiff> {
let mut diffs = Vec::new();
for (key, family) in &self.0 {
match other.0.get(key) {
None => diffs.push(RowDiff::Missing {
key: key.clone(),
family: *family,
}),
Some(theirs) if theirs != family => diffs.push(RowDiff::Family {
key: key.clone(),
this: *family,
other: *theirs,
}),
Some(_) => {}
}
}
for (key, family) in &other.0 {
if !self.0.contains_key(key) {
diffs.push(RowDiff::Extra {
key: key.clone(),
family: *family,
});
}
}
diffs
}
}
impl FromIterator<(HandlerKey, EffectFamily)> for EffectRow {
fn from_iter<I: IntoIterator<Item = (HandlerKey, EffectFamily)>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl<'a> IntoIterator for &'a EffectRow {
type Item = (&'a HandlerKey, &'a EffectFamily);
type IntoIter = std::collections::btree_map::Iter<'a, HandlerKey, EffectFamily>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for EffectRow {
type Item = (HandlerKey, EffectFamily);
type IntoIter = std::collections::btree_map::IntoIter<HandlerKey, EffectFamily>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
const _: fn() = || {
fn assert_wire<T: Clone + Send + Sync + 'static + Serialize + serde::de::DeserializeOwned>() {}
assert_wire::<EffectId>();
assert_wire::<HandlerKey>();
assert_wire::<EffectFamily>();
assert_wire::<HandlerDescriptor>();
assert_wire::<FamilyDescriptor>();
assert_wire::<ToolEmbeddingDescriptor>();
assert_wire::<EmbedModality>();
assert_wire::<EffectKind>();
assert_wire::<EmbedInputs>();
assert_wire::<RerankRequest>();
assert_wire::<RetrieveQuery>();
assert_wire::<Answered>();
assert_wire::<EmbedOutputs>();
assert_wire::<RetrievedDocuments>();
assert_wire::<EffectRecord>();
assert_wire::<Decider>();
assert_wire::<EffectRow>();
assert_wire::<StreamRecord>();
};
#[cfg(test)]
mod tests;