weavegraph 0.7.0

Graph-driven, concurrent agent workflow framework with versioned state, deterministic barrier merges, and rich diagnostics.
Documentation
/*!
Type-safe identifiers for runtime execution tracking.

Newtype wrappers that prevent mixing session IDs with step numbers or
with raw strings and integers. For core workflow types (node kinds,
channel types), see [`crate::types`].
*/

use serde::{Deserialize, Serialize};
use std::fmt;

/// A type-safe session identifier.
///
/// Wraps a `String` so the compiler rejects raw strings wherever a
/// `SessionId` is expected.
///
/// ```rust
/// use weavegraph::runtimes::types::SessionId;
///
/// let id = SessionId::new("my_session");
/// let generated = SessionId::generate();
/// assert_ne!(id.as_str(), generated.as_str());
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SessionId(String);

impl SessionId {
    /// Wrap a string as a session ID.
    #[must_use]
    pub fn new(id: impl Into<String>) -> Self {
        Self(id.into())
    }

    /// Generate a unique session ID.
    #[must_use]
    pub fn generate() -> Self {
        use crate::utils::id_generator::IdGenerator;
        Self(IdGenerator::new().generate_session_id())
    }

    /// Borrow the inner string slice.
    #[must_use]
    pub fn as_str(&self) -> &str {
        &self.0
    }

    /// Consume the wrapper, returning the inner `String`.
    #[must_use]
    pub fn into_string(self) -> String {
        self.0
    }
}

impl fmt::Display for SessionId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.0)
    }
}

impl From<String> for SessionId {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for SessionId {
    fn from(s: &str) -> Self {
        Self(s.to_owned())
    }
}

impl AsRef<str> for SessionId {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

/// A type-safe workflow step counter.
///
/// Wraps a `u64` to prevent mixing step numbers with other numeric values.
/// Ordering is derived so step numbers can be compared and sorted directly.
///
/// ```rust
/// use weavegraph::runtimes::types::StepNumber;
///
/// let step = StepNumber::new(5);
/// assert_eq!(step.next().value(), 6);
/// assert!(StepNumber::zero().is_initial());
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct StepNumber(u64);

impl StepNumber {
    /// Create a step number from a raw value.
    #[must_use]
    pub fn new(step: u64) -> Self {
        Self(step)
    }

    /// The initial step (step 0).
    #[must_use]
    pub fn zero() -> Self {
        Self(0)
    }

    /// The underlying `u64` value.
    #[must_use]
    pub fn value(self) -> u64 {
        self.0
    }

    /// The next step, saturating at `u64::MAX`.
    #[must_use]
    pub fn next(self) -> Self {
        Self(self.0.saturating_add(1))
    }

    /// Returns `true` if this is step 0.
    #[must_use]
    pub fn is_initial(self) -> bool {
        self.0 == 0
    }
}

impl fmt::Display for StepNumber {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl From<u64> for StepNumber {
    fn from(step: u64) -> Self {
        Self(step)
    }
}

impl From<StepNumber> for u64 {
    fn from(step: StepNumber) -> u64 {
        step.0
    }
}