aion-server 0.31.0

Aion workflow server library: HTTP, gRPC, WebSocket, and worker endpoints. Run it with the `aion` binary from the aion-cli crate.
Documentation
//! The ASSISTANT-ONLY MCP surface: `/assistant/mcp`.
//!
//! A second MCP route beside the general `/mcp`, on the same listener and the
//! same protocol layer, with its OWN catalogue and its own credential. It
//! exists because its tools — the editing loop: `assistant_context`,
//! `assistant_document_edit`, `assistant_document_check` — are each about one
//! conversation and belong to nobody else.
//!
//! # Why they are not tools on the general catalogue
//!
//! The general catalogue is what any authorized caller sees listed, and its
//! tools are addressed by namespace. The session tools are addressed by
//! SESSION, and the only credential that can name a session is the bearer this
//! server minted for that session's own agent. Adding them to the general
//! catalogue would mean either publishing tools most callers cannot use, or
//! narrowing the catalogue per caller — and a catalogue that narrows is a
//! catalogue whose narrowing has to be got right on every request. Two routes
//! with two catalogues cannot be got wrong: the general dispatcher refuses
//! each session tool by NAME because the name is not in its catalogue at all.
//!
//! # Its only credential is a session bearer
//!
//! [`caller`] resolves `authorization: Bearer …` plus
//! `x-aion-assistant-session: <id>` into an [`AssistantSessionCaller`], and does
//! it by reading the STORE: the record's stored digest, and the session's
//! projected lifecycle. A human's token is refused because it is not a session
//! bearer; a session bearer presented against another session's id is refused
//! because the digest belongs to the other record; and a token whose session has
//! ENDED is refused because the projection says so — which is why revocation is
//! exactly as durable as the session and survives the restart of the process
//! that minted the token.
//!
//! - [`caller`] — the session-bearer resolution and its typed refusals.
//! - [`catalog`] — the three-tool catalogue.
//! - [`context_tool`] — `assistant_context` itself.
//! - [`document_edit_tool`] — `assistant_document_edit`.
//! - [`document_check_tool`] — `assistant_document_check`.
//! - [`route`] — the axum mount.
//! - [`runtime`] — the protocol server constructed at startup.

pub(crate) mod caller;
pub(crate) mod catalog;
pub(crate) mod context_tool;
pub(crate) mod document_check_tool;
pub(crate) mod document_edit_tool;
pub(crate) mod route;
pub(crate) mod runtime;
pub(crate) mod service;

#[cfg(test)]
mod caller_tests;

pub(crate) use catalog::SESSION_TOOL_NAMES;
/// The tools this route publishes. Exported so the descriptor, the doc pins
/// and the general catalogue's separation pin all name them from one place.
pub use catalog::{
    ASSISTANT_CONTEXT_TOOL, ASSISTANT_DOCUMENT_CHECK_TOOL, ASSISTANT_DOCUMENT_EDIT_TOOL,
};
/// The route the assistant's own catalogue is served on. Exported for the same
/// reason: the descriptor publishes it and the docs quote it.
pub use route::ASSISTANT_MCP_PATH;
pub(crate) use route::assistant_mcp_router;
pub(crate) use runtime::AssistantMcpRuntime;

/// One sentence describing the credential this route accepts.
///
/// THE source: the descriptor publishes it, `docs/operations/API.md` quotes it,
/// and `token.rs` points at it. A second sentence written beside one of those
/// would be a second description of one credential, and the two would drift.
pub const SESSION_TOKEN_DESCRIPTION: &str = "server-minted and session-scoped: this server mints one bearer per assistant session, hands \
     it only to that session's own agent process, stores only its digest, and stops honouring it \
     the moment the session's projected lifecycle reads `ended`. It authorizes exactly one \
     session's context and nothing else — not a namespace, not a workflow, and not the operator \
     who opened the session.";

/// The wire word for the credential kind, for a client that branches on it.
pub const SESSION_TOKEN_KIND: &str = "assistant_session_bearer";