ferrum-interfaces 0.8.4

Core trait contracts for the Ferrum LLM inference engine
Documentation
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::fmt;

use super::{ContractVersion, VNextError};

pub const EXECUTION_IDENTITY_VERSION: ContractVersion = ContractVersion::new(3, 0);
pub const MAX_EXECUTION_EVENT_WIRE_BYTES: usize = 1024 * 1024;
pub const MAX_REPLAY_IDENTITY_WIRE_BYTES: usize = 1024 * 1024;
pub const MAX_RESOURCE_POOL_EVENT_WIRE_BYTES: usize = 16 * 1024 * 1024;

pub(super) fn invalid_event(reason: impl Into<String>) -> VNextError {
    VNextError::InvalidExecutionPlan {
        reason: reason.into(),
    }
}

pub(super) fn canonical_fingerprint(value: &impl Serialize) -> String {
    format!(
        "{:x}",
        Sha256::digest(serde_json::to_vec(value).expect("trusted event evidence must serialize"))
    )
}

pub(super) fn sha256_bytes(bytes: &[u8]) -> String {
    format!("{:x}", Sha256::digest(bytes))
}

pub(super) fn validate_sha256(value: &str, label: &str) -> Result<(), VNextError> {
    if value.len() != 64
        || !value
            .bytes()
            .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
    {
        return Err(invalid_event(format!(
            "{label} must be a canonical lowercase SHA256"
        )));
    }
    Ok(())
}

macro_rules! nonzero_execution_id {
    ($name:ident, $label:literal) => {
        #[derive(
            Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
        )]
        #[serde(try_from = "u64", into = "u64")]
        pub struct $name(u64);

        impl $name {
            pub const fn get(self) -> u64 {
                self.0
            }
        }

        impl TryFrom<u64> for $name {
            type Error = VNextError;

            fn try_from(value: u64) -> Result<Self, Self::Error> {
                if value == 0 {
                    return Err(invalid_event(concat!($label, " must be non-zero")));
                }
                Ok(Self(value))
            }
        }

        impl From<$name> for u64 {
            fn from(value: $name) -> Self {
                value.0
            }
        }

        impl fmt::Display for $name {
            fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(formatter, "{}", self.0)
            }
        }
    };
}

nonzero_execution_id!(ExecutionFrameId, "execution frame id");
nonzero_execution_id!(BatchStepId, "batch step id");
nonzero_execution_id!(BatchInvocationId, "batch invocation id");
nonzero_execution_id!(NodeInvocationId, "node invocation id");

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExecutionEventKind {
    RequestAccepted,
    PlanBuilt,
    FrameStarted,
    NodeStarted,
    OperationSubmitted,
    NodeRetired,
    FrameCompleted,
    FailureObserved,
    SequenceCompleted,
    SequenceAborted,
    RequestCompleted,
    RequestFailed,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExecutionPhase {
    Resolution,
    Planning,
    Execution,
    Completion,
}

impl ExecutionPhase {
    pub(super) const fn rank(self) -> u8 {
        match self {
            Self::Resolution => 0,
            Self::Planning => 1,
            Self::Execution => 2,
            Self::Completion => 3,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MonotonicTimestamp {
    pub nanos_since_run_start: u64,
}