use std::fmt;
use onemessagebus::{Message, SchemaId, Vocabulary};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use crate::Agent;
pub use onemessagebus::ArtifactRef;
pub type Envelope = onemessagebus::Envelope<Agent>;
pub type EventFilter = onemessagebus::Filter<Agent>;
pub type Matcher = onemessagebus::Matcher<Agent>;
pub type Emitter = onemessagebus::Emitter<Agent>;
pub type Reader = onemessagebus::Reader<Agent>;
pub type Merge = onemessagebus::Merge<Agent>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum Source {
Agentgraph,
Vcs,
Pipeline,
}
impl Source {
#[must_use]
pub const fn every() -> [Source; 3] {
[Source::Agentgraph, Source::Vcs, Source::Pipeline]
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Source::Agentgraph => "agentgraph",
Source::Vcs => "vcs",
Source::Pipeline => "pipeline",
}
}
#[must_use]
pub fn write_version(self) -> u32 {
Agent::write_version(&self)
}
}
impl fmt::Display for Source {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
)]
#[serde(rename_all = "kebab-case")]
pub enum Phase {
Development,
Integrate,
Review,
Release,
}
impl Phase {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Phase::Development => "development",
Phase::Integrate => "integrate",
Phase::Review => "review",
Phase::Release => "release",
}
}
#[must_use]
pub const fn every() -> [Phase; 4] {
[
Phase::Development,
Phase::Integrate,
Phase::Review,
Phase::Release,
]
}
}
impl fmt::Display for Phase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Dimensions {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub phase: Option<Phase>,
}
impl Dimensions {
#[must_use]
pub const fn none() -> Self {
Self { phase: None }
}
#[must_use]
pub const fn at(phase: Phase) -> Self {
Self { phase: Some(phase) }
}
}
impl From<Phase> for Dimensions {
fn from(phase: Phase) -> Self {
Self::at(phase)
}
}
impl From<Option<Phase>> for Dimensions {
fn from(phase: Option<Phase>) -> Self {
Self { phase }
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Labels {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub run_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub round: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub node: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub step: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub member: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub persona: Option<String>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
impl Message for Labels {
const SCHEMA: SchemaId = SchemaId::literal("agent", "labels", 1);
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct MatchFields {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub phase: Option<Phase>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub run_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub node: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub step: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub member: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub persona: Option<String>,
}
pub trait AgentEnvelope {
fn phase(&self) -> Option<Phase>;
}
impl AgentEnvelope for Envelope {
fn phase(&self) -> Option<Phase> {
self.dimensions.phase
}
}
pub trait AgentFilter {
fn admits(&self, source: Source, kind: &str, labels: &Labels, phase: Option<Phase>) -> bool;
}
impl AgentFilter for EventFilter {
fn admits(&self, source: Source, kind: &str, labels: &Labels, phase: Option<Phase>) -> bool {
self.allows(&source, kind, &Dimensions { phase }, labels)
}
}