use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use super::ids::{IdeaId, NodeId, PlanId, RunId};
pub type Source = String;
pub type Target = String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum NodeStatus {
Pending,
Ready,
InProgress,
Done,
Blocked,
Failed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PlanStatus {
Draft,
Active,
Done,
Abandoned,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ItemKind {
#[default]
Idea,
Error,
Test,
}
impl ItemKind {
pub fn as_str(&self) -> &'static str {
match self {
ItemKind::Idea => "idea",
ItemKind::Error => "error",
ItemKind::Test => "test",
}
}
pub fn parse(s: &str) -> Self {
match s {
"error" => ItemKind::Error,
"test" => ItemKind::Test,
_ => ItemKind::Idea,
}
}
pub fn node_kind(&self) -> &'static str {
match self {
ItemKind::Idea => "code:write",
ItemKind::Error => "code:fix",
ItemKind::Test => "test:write",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TriageDecision {
Accept,
Drop,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RunOutcome {
Ok,
Failed,
Aborted,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum Event {
IdeaSubmitted {
id: IdeaId,
source: Source,
text: String,
#[serde(default)]
refs: Vec<String>,
#[serde(default)]
item_kind: ItemKind,
ts: DateTime<Utc>,
},
IdeaTriaged {
idea_id: IdeaId,
decision: TriageDecision,
#[serde(default)]
why: Option<String>,
ts: DateTime<Utc>,
},
PlanCreated {
id: PlanId,
idea_id: IdeaId,
summary: String,
planner: String,
ts: DateTime<Utc>,
},
NodeAdded {
plan_id: PlanId,
node_id: NodeId,
#[serde(rename = "node_kind")]
kind: String,
#[serde(default)]
params: serde_json::Map<String, serde_json::Value>,
#[serde(default)]
targets: Vec<Target>,
#[serde(default)]
prompt_excerpt: Option<String>,
ts: DateTime<Utc>,
},
EdgeAdded {
plan_id: PlanId,
from_node: NodeId,
to_node: NodeId,
ts: DateTime<Utc>,
},
NodeStatusChanged {
plan_id: PlanId,
node_id: NodeId,
status: NodeStatus,
#[serde(default)]
why: Option<String>,
ts: DateTime<Utc>,
},
RunRecorded {
plan_id: PlanId,
node_id: NodeId,
run_id: RunId,
ran_by: String,
outcome: RunOutcome,
#[serde(default)]
log_ref: Option<String>,
#[serde(default)]
produced_commits: Vec<CommitRef>,
#[serde(default)]
produced_test_runs: Vec<String>,
ts: DateTime<Utc>,
},
PlanStatusChanged {
plan_id: PlanId,
status: PlanStatus,
#[serde(default)]
why: Option<String>,
ts: DateTime<Utc>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitRef {
pub repo: String,
pub sha: String,
}
impl Event {
pub fn ts(&self) -> DateTime<Utc> {
match self {
Event::IdeaSubmitted { ts, .. }
| Event::IdeaTriaged { ts, .. }
| Event::PlanCreated { ts, .. }
| Event::NodeAdded { ts, .. }
| Event::EdgeAdded { ts, .. }
| Event::NodeStatusChanged { ts, .. }
| Event::RunRecorded { ts, .. }
| Event::PlanStatusChanged { ts, .. } => *ts,
}
}
}