rain-engine-runtime 0.1.0

Reference runtime library for embedding RainEngine over HTTP
Documentation
use async_trait::async_trait;
use rain_engine_core::{
    AgentAction, AgentEngine, AgentTrigger, MockLlmProvider, PlannedSkillCall, ProcessRequest,
    SkillExecutor, SkillInvocation, SkillManifestDescriptor,
};
use rain_engine_runtime::run_until_terminal;
use rain_engine_store_sqlite::SqliteMemoryStore;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::sync::Arc;

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, rain_engine_macros::SkillManifest)]
#[skill(
    name = "echo_input",
    description = "Echo the provided payload back to the caller.",
    scopes("tool:run"),
    capabilities("log")
)]
struct EchoInput {
    value: String,
}

struct EchoExecutor;

#[async_trait]
impl SkillExecutor for EchoExecutor {
    async fn execute(
        &self,
        invocation: SkillInvocation,
    ) -> Result<serde_json::Value, rain_engine_core::SkillExecutionError> {
        Ok(json!({
            "echoed": invocation.args,
        }))
    }

    fn executor_kind(&self) -> &'static str {
        "wasm"
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let store = Arc::new(SqliteMemoryStore::connect("sqlite::memory:").await?);
    let llm = Arc::new(MockLlmProvider::scripted(vec![
        AgentAction::CallSkills(vec![PlannedSkillCall {
            call_id: "call-1".to_string(),
            name: EchoInput::skill_manifest().name,
            args: json!({"value": "hello"}),
            priority: 0,
            depends_on: Vec::new(),
            retry_policy: Default::default(),
            dry_run: false,
        }]),
        AgentAction::Respond {
            content: "completed".to_string(),
        },
    ]));
    let engine = AgentEngine::new(llm, store);
    engine.register_wasm_skill(EchoInput::skill_manifest(), Arc::new(EchoExecutor));

    let outcome = run_until_terminal(
        &engine,
        ProcessRequest::new(
            "example-session",
            AgentTrigger::Message {
                user_id: "u1".to_string(),
                content: "Run the skill".to_string(),
                attachments: Vec::new(),
            },
        )
        .with_scope("tool:run"),
    )
    .await?;

    println!("embedded_sqlite outcome: {:?}", outcome);
    Ok(())
}