use camino::Utf8PathBuf;
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde_json")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde_json")))]
pub mod json;
pub const ORTHO_AGENT_CONTEXT_SCHEMA_VERSION: &str = "1";
pub const AGENT_CONTEXT_KIND_SUFFIX: &str = "agent_context";
#[must_use]
pub fn agent_context_kind(package: &str) -> String {
format!("{package}.{AGENT_CONTEXT_KIND_SUFFIX}")
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgentContext {
pub schema_version: String,
pub kind: String,
pub package: String,
pub commands: Vec<AgentCommand>,
#[serde(default)]
pub profiles: SupportDeclaration,
#[serde(default)]
pub feedback: SupportDeclaration,
#[serde(default)]
pub policy: AgentPolicy,
#[serde(default)]
pub skill_manifests: Vec<SkillManifest>,
}
impl AgentContext {
#[must_use]
pub fn new(package: impl Into<String>) -> Self {
let package_name = package.into();
Self {
schema_version: ORTHO_AGENT_CONTEXT_SCHEMA_VERSION.to_owned(),
kind: agent_context_kind(&package_name),
package: package_name,
commands: Vec::new(),
profiles: SupportDeclaration::default(),
feedback: SupportDeclaration::default(),
policy: AgentPolicy::default(),
skill_manifests: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgentCommand {
pub path: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(default)]
pub canonical_verb: Option<String>,
#[serde(default)]
pub inputs: Vec<AgentInput>,
#[serde(default)]
pub output_modes: Vec<String>,
#[serde(default)]
pub interaction_mode: InteractionMode,
#[serde(default)]
pub mutation_effect: MutationEffect,
#[serde(default)]
pub async_submission: Option<AsyncSubmission>,
#[serde(default)]
pub delivery_route: Option<DeliveryRoute>,
#[serde(default)]
pub pagination: Option<PaginationContract>,
#[serde(default)]
pub examples: Vec<AgentExample>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AsyncSubmission {
pub mode: AsyncSubmissionMode,
#[serde(default)]
pub noun: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum AsyncSubmissionMode {
Inline,
Submit,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DeliveryRoute {
pub supported: bool,
#[serde(default)]
pub target: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgentInput {
pub name: String,
#[serde(default)]
pub long: Option<String>,
#[serde(default)]
pub value_type: Option<String>,
#[serde(default)]
pub required: bool,
#[serde(default)]
pub default: Option<String>,
#[serde(default)]
pub enum_values: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgentExample {
pub command: String,
#[serde(default)]
pub output_mode: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct SupportDeclaration {
pub supported: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgentPolicy {
pub agent_native: PolicyMode,
}
impl Default for AgentPolicy {
fn default() -> Self {
Self {
agent_native: PolicyMode::Warn,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PolicyMode {
Off,
Warn,
Deny,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum InteractionMode {
Unknown,
NonInteractive,
Interactive,
}
impl Default for InteractionMode {
fn default() -> Self {
Self::Unknown
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum MutationEffect {
Unknown,
ReadOnly,
Write,
Delete,
Submit,
}
impl Default for MutationEffect {
fn default() -> Self {
Self::Unknown
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct PaginationContract {
#[serde(default)]
pub limit_input: Option<String>,
#[serde(default)]
pub cursor_input: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SkillManifest {
pub id: String,
pub path: Utf8PathBuf,
pub manifest_schema_version: String,
#[serde(default)]
pub commands: Vec<SkillCommandRef>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SkillCommandRef {
pub path: Vec<String>,
#[serde(default)]
pub flags: Vec<String>,
}
#[cfg(test)]
mod tests;