use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use starweaver_core::{RunId, SessionId};
pub const CONTINUATION_EFFECT_METADATA_KEY: &str = "starweaver.continuation.effect";
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum HitlResumeClaimState {
Preflight,
Admitted,
Started,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum HitlResumeAbortOutcome {
AbortedBeforeEffect,
EffectStarted,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ContinuationEffectPhase {
Started,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ContinuationEffectOutcome {
Indeterminate,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ContinuationEffectState {
pub phase: ContinuationEffectPhase,
pub outcome: ContinuationEffectOutcome,
}
impl ContinuationEffectState {
#[must_use]
pub const fn indeterminate() -> Self {
Self {
phase: ContinuationEffectPhase::Started,
outcome: ContinuationEffectOutcome::Indeterminate,
}
}
pub fn insert_into(&self, metadata: &mut Map<String, Value>) -> Result<(), serde_json::Error> {
metadata.insert(
CONTINUATION_EFFECT_METADATA_KEY.to_string(),
serde_json::to_value(self)?,
);
Ok(())
}
pub fn from_metadata(metadata: &Map<String, Value>) -> Result<Option<Self>, serde_json::Error> {
metadata
.get(CONTINUATION_EFFECT_METADATA_KEY)
.map(|value| serde_json::from_value(value.clone()))
.transpose()
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct HitlResumeClaim {
pub claim_id: String,
pub session_id: SessionId,
pub run_id: RunId,
pub state: HitlResumeClaimState,
pub created_at: DateTime<Utc>,
}
impl starweaver_core::VersionedRecord for HitlResumeClaim {
const SCHEMA: &'static str = "starweaver.session.hitl_resume_claim";
}
impl HitlResumeClaim {
#[must_use]
pub const fn new(
claim_id: String,
session_id: SessionId,
run_id: RunId,
created_at: DateTime<Utc>,
) -> Self {
Self {
claim_id,
session_id,
run_id,
state: HitlResumeClaimState::Preflight,
created_at,
}
}
#[must_use]
pub fn is_valid_preflight(&self) -> bool {
self.state == HitlResumeClaimState::Preflight && !self.claim_id.trim().is_empty()
}
}