contextvm-sdk 0.2.0

Rust SDK for the ContextVM protocol — MCP over Nostr
Documentation
//! Error taxonomy for CEP-41 open streams.
//!
//! Mirrors the TypeScript SDK's error classes
//! (`sdk/src/transport/open-stream/errors.ts`) so failure classification is
//! identical across implementations. Surfaced through the crate-level
//! [`crate::Error`] via a `#[from]` conversion.

/// Errors raised while reading, writing, or sequencing an open stream.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum OpenStreamError {
    /// The stream was aborted locally or by the remote peer (terminal).
    #[error("Open stream aborted (token: {token}){}", .reason.as_deref().map(|r| format!(": {r}")).unwrap_or_default())]
    Abort {
        /// The `progressToken` of the aborted stream.
        token: String,
        /// Optional advisory reason supplied in the `abort` frame.
        reason: Option<String>,
    },

    /// A stream violated local admission or buffering policy
    /// (concurrency, buffered-chunk count, buffered+queued byte budget).
    #[error("Open stream policy violation: {0}")]
    Policy(String),

    /// Frames violated CEP-41 lifecycle or ordering rules (non-increasing
    /// progress, stale/duplicate `chunkIndex`, frame before `start`, frame
    /// after a terminal close/abort, incomplete `close.lastChunkIndex`).
    #[error("Open stream sequence error: {0}")]
    Sequence(String),
}

impl OpenStreamError {
    /// Construct an [`OpenStreamError::Abort`].
    pub fn abort(token: impl Into<String>, reason: Option<String>) -> Self {
        Self::Abort {
            token: token.into(),
            reason,
        }
    }

    /// Returns `true` if this is a terminal [`abort`](OpenStreamError::Abort).
    pub fn is_abort(&self) -> bool {
        matches!(self, Self::Abort { .. })
    }
}

// The crate-level `From<OpenStreamError> for crate::Error` conversion is
// generated by the `#[from]` attribute on `Error::OpenStream` (see
// `src/core/error.rs`), mirroring `OversizedTransferError`.