use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
pub const ENVELOPE_VERSION: u32 = 1;
pub const MAX_PAYLOAD_TEXT_BYTES: usize = 4096;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Envelope {
pub v: u32,
pub ts: String,
pub stream: String,
pub seq: u64,
pub source: Source,
pub kind: EventKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub phase: Option<Phase>,
#[serde(default)]
pub labels: Labels,
#[serde(default)]
pub payload: Map<String, Value>,
#[serde(default)]
pub artifacts: Vec<ArtifactRef>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Phase {
Development,
Integrate,
Review,
Release,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Source {
Agentgraph,
Vcs,
Pipeline,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct EventKind(pub String);
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
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 persona: Option<String>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[non_exhaustive]
pub enum PipelineKind {
RunStarted,
ConcurrentAcknowledged,
NodeReady,
NodeDispatched,
NodeSettled,
EditCommitted,
EditRejected,
PlannerSurfaceQueued,
PlannerSurfaced,
PlannerReplied,
HumanAttested,
DriverAdopted,
RunStopped,
QuietWorker,
NodeHeld,
NodeUnheld,
DecisionPending,
DecisionCleared,
CrossDagSatisfied,
UpstreamModified,
CompletionRequested,
ReleaseWait,
ReleaseArrived,
ReleaseAdopted,
CriterionChecked,
BodyNotDrafted,
}
impl PipelineKind {
pub const fn as_str(self) -> &'static str {
match self {
Self::RunStarted => "run-started",
Self::ConcurrentAcknowledged => "concurrent-acknowledged",
Self::NodeReady => "node-ready",
Self::NodeDispatched => "node-dispatched",
Self::NodeSettled => "node-settled",
Self::EditCommitted => "edit-committed",
Self::EditRejected => "edit-rejected",
Self::PlannerSurfaceQueued => "planner-surface-queued",
Self::PlannerSurfaced => "planner-surfaced",
Self::PlannerReplied => "planner-replied",
Self::HumanAttested => "human-attested",
Self::DriverAdopted => "driver-adopted",
Self::RunStopped => "run-stopped",
Self::QuietWorker => "quiet-worker",
Self::NodeHeld => "node-held",
Self::NodeUnheld => "node-unheld",
Self::DecisionPending => "decision-pending",
Self::DecisionCleared => "decision-cleared",
Self::CrossDagSatisfied => "cross-dag-satisfied",
Self::UpstreamModified => "upstream-modified",
Self::CompletionRequested => "completion-requested",
Self::ReleaseWait => "release-wait",
Self::ReleaseArrived => "release-arrived",
Self::ReleaseAdopted => "release-adopted",
Self::CriterionChecked => "criterion-checked",
Self::BodyNotDrafted => "body-not-drafted",
}
}
pub fn from_wire(kind: &EventKind) -> Option<Self> {
PIPELINE_KINDS
.iter()
.copied()
.find(|candidate| candidate.as_str() == kind.0)
}
}
impl std::fmt::Display for PipelineKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl From<PipelineKind> for EventKind {
fn from(kind: PipelineKind) -> Self {
Self(kind.as_str().to_string())
}
}
pub const PIPELINE_KINDS: &[PipelineKind] = &[
PipelineKind::RunStarted,
PipelineKind::ConcurrentAcknowledged,
PipelineKind::NodeReady,
PipelineKind::NodeDispatched,
PipelineKind::NodeSettled,
PipelineKind::EditCommitted,
PipelineKind::EditRejected,
PipelineKind::PlannerSurfaceQueued,
PipelineKind::PlannerSurfaced,
PipelineKind::PlannerReplied,
PipelineKind::HumanAttested,
PipelineKind::DriverAdopted,
PipelineKind::RunStopped,
PipelineKind::QuietWorker,
PipelineKind::NodeHeld,
PipelineKind::NodeUnheld,
PipelineKind::DecisionPending,
PipelineKind::DecisionCleared,
PipelineKind::CrossDagSatisfied,
PipelineKind::UpstreamModified,
PipelineKind::CompletionRequested,
PipelineKind::ReleaseWait,
PipelineKind::ReleaseArrived,
PipelineKind::ReleaseAdopted,
PipelineKind::CriterionChecked,
PipelineKind::BodyNotDrafted,
];
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArtifactRef {
pub id: ArtifactId,
pub kind: String,
pub bytes: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ArtifactId(pub String);