orchestral-runtime 0.2.0

Thread Runtime with concurrency, interruption, scheduling, LLM planners, actions, and API for Orchestral
Documentation
use std::collections::HashMap;

use async_trait::async_trait;
use serde_json::{json, Value};

use orchestral_core::action::{Action, ActionContext, ActionInput, ActionMeta, ActionResult};
use orchestral_core::config::ActionSpec;

pub(crate) struct JsonStdoutAction {
    name: String,
    description: String,
}

impl JsonStdoutAction {
    pub(crate) fn from_spec(spec: &ActionSpec) -> Self {
        Self {
            name: spec.name.clone(),
            description: spec.description_or(
                "Serializes payload to stdout as one JSON object without side effects",
            ),
        }
    }

    pub(crate) fn internal() -> Self {
        Self {
            name: "json_stdout".to_string(),
            description: "Serializes payload to stdout as one JSON object without side effects"
                .to_string(),
        }
    }
}

#[async_trait]
impl Action for JsonStdoutAction {
    fn name(&self) -> &str {
        &self.name
    }

    fn description(&self) -> &str {
        &self.description
    }

    fn metadata(&self) -> ActionMeta {
        ActionMeta::new(self.name(), self.description())
            .with_category("utility")
            .with_capabilities(["pure", "structured_output"])
            .with_input_kinds(["runtime.payload"])
            .with_output_kinds(["runtime.stdout_json", "text"])
            .with_input_schema(json!({
                "type": "object",
                "properties": {
                    "payload": {
                        "description": "Arbitrary JSON object to serialize to stdout."
                    }
                },
                "required": ["payload"]
            }))
            .with_output_schema(json!({
                "type": "object",
                "properties": {
                    "stdout": { "type": "string" },
                    "stderr": { "type": "string" },
                    "status": { "type": "integer" }
                },
                "required": ["stdout", "stderr", "status"]
            }))
    }

    async fn run(&self, input: ActionInput, _ctx: ActionContext) -> ActionResult {
        let payload = input
            .params
            .get("payload")
            .cloned()
            .unwrap_or(Value::Object(Default::default()));
        let stdout = match serde_json::to_string(&payload) {
            Ok(value) => value,
            Err(error) => {
                return ActionResult::error(format!("Failed to serialize payload: {}", error))
            }
        };
        let mut exports = HashMap::new();
        exports.insert("stdout".to_string(), Value::String(stdout));
        exports.insert("stderr".to_string(), Value::String(String::new()));
        exports.insert("status".to_string(), Value::Number(0.into()));
        ActionResult::success_with(exports)
    }
}