use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use stateknot::{
core::{AgentSubmissionKey, BudgetLimits},
in_process_agent::{
InProcessAgentBinding, InProcessAgentDependencies, InProcessAgentRequest,
InProcessAgentRun, InProcessAgentRunOptions, InProcessAgentRuntime,
InProcessAgentRuntimeOptions,
},
runtime::{AgentServiceCaller, TypedAgent},
};
use std::{error::Error, io, time::Duration};
#[derive(JsonSchema, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ChatRequest {
pub message: String,
}
#[derive(Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ChatResponse {
pub answer: String,
}
pub async fn run_chat(
binding: InProcessAgentBinding,
dependencies: InProcessAgentDependencies,
codec: TypedAgent<ChatRequest, ChatResponse>,
caller: AgentServiceCaller,
submission_key: AgentSubmissionKey,
input: ChatRequest,
) -> Result<Option<ChatResponse>, Box<dyn Error>> {
let mut runtime = InProcessAgentRuntime::start(
binding,
dependencies,
InProcessAgentRuntimeOptions::default(),
)
.await?;
let agent = runtime
.agent(codec, caller)?
.with_options(InProcessAgentRunOptions::new(
Duration::from_millis(50),
Duration::from_secs(30),
)?);
let result = agent
.run(InProcessAgentRequest::new(
submission_key,
input,
BudgetLimits::empty(),
))
.await;
drop(agent);
let report = runtime.shutdown().await?;
if report.failure.is_some()
|| report.worker.is_none_or(|result| result.is_err())
|| report.maintenance.is_none_or(|result| result.is_err())
{
return Err(io::Error::other("in-process Agent roles did not drain cleanly").into());
}
match result? {
InProcessAgentRun::Succeeded { output, .. } => Ok(Some(output)),
InProcessAgentRun::Pending { .. } => Ok(None),
InProcessAgentRun::Failed { .. }
| InProcessAgentRun::Cancelled { .. }
| InProcessAgentRun::Quarantined { .. } => {
Err(io::Error::other("durable Agent run did not succeed").into())
}
_ => Err(io::Error::other("unsupported Agent run outcome").into()),
}
}
fn main() {
println!("assemble the qualified deployment, then call run_chat");
}