luminarys-sdk 0.1.0

Rust SDK for building Luminarys WASM skills
Documentation
//! [`Context`] — request metadata and response annotations passed to every handler.

use crate::types::{InvokeRequest, InvokeResponse};

/// Passed to every skill handler that declares `&mut Context` as its first argument.
///
/// Provides read access to invocation metadata and write access to response annotations.
///
/// # Example
///
/// ```rust,no_run
/// use luminarys_sdk::prelude::*;
///
/// fn echo(ctx: &mut Context, message: String) -> Result<String, SkillError> {
///     ctx.set_llm_context("Echoed successfully");
///     Ok(message)
/// }
/// ```
pub struct Context<'a> {
    req: &'a InvokeRequest,
    res: &'a mut InvokeResponse,
}

impl<'a> Context<'a> {
    /// Create a [`Context`] bound to `req` and `res`.
    ///
    /// Called by generated dispatch code — not intended for direct use in handlers.
    pub fn new(req: &'a InvokeRequest, res: &'a mut InvokeResponse) -> Self {
        Context { req, res }
    }

    // ── Identity ──────────────────────────────────────────────────────────────

    /// Unique ID of this invocation.
    pub fn request_id(&self) -> &str { &self.req.request_id }

    /// Distributed trace ID (shared across a chain of calls).
    pub fn trace_id(&self) -> &str { &self.req.trace_id }

    /// User session ID.
    pub fn session_id(&self) -> &str { &self.req.session_id }

    /// LLM session ID (may differ from `session_id` when multiple LLM
    /// conversations share one user session).
    pub fn llm_session_id(&self) -> &str { &self.req.llm_session_id }

    /// ID of the skill being invoked.
    pub fn skill_id(&self) -> &str { &self.req.skill_id }

    /// Skill ID of the caller when invoked via `call_module`.  
    /// Empty when called directly by the host or LLM.
    pub fn caller_id(&self) -> &str { &self.req.caller_id }

    /// Method name being invoked.
    pub fn method(&self) -> &str { &self.req.method }

    // ── Response annotations ──────────────────────────────────────────────────

    /// Set additional text that the host will append to the MCP tool result.
    ///
    /// Use it to give the LLM context that is not part of the structured
    /// payload — e.g. warnings, hints, or human-readable summaries.
    ///
    /// ```rust,no_run
    /// # use luminarys_sdk::prelude::*;
    /// # fn example(ctx: &mut Context) {
    /// ctx.set_llm_context("File written. Note: directory was created automatically.");
    /// # }
    /// ```
    pub fn set_llm_context(&mut self, text: impl Into<String>) {
        self.res.llm_context = text.into();
    }

    /// Append text to any existing `llm_context`, separated by `"\n"`.
    pub fn append_llm_context(&mut self, text: impl Into<String>) {
        let text = text.into();
        if self.res.llm_context.is_empty() {
            self.res.llm_context = text;
        } else {
            self.res.llm_context.push('\n');
            self.res.llm_context.push_str(&text);
        }
    }
}