everruns-builtins 0.18.8

Portable, backend-neutral built-in capabilities for Everruns
Documentation
use std::sync::Arc;

use crate::capabilities::{Capability, CapabilityLocalization, ToolCallHook, ToolDefinitionHook};
use crate::tool_narration::ToolNarrationPhase;
use crate::tool_types::{
    ToolCall, ToolDefinition, add_human_intent_to_tool_definitions, human_intent,
};

pub const HUMAN_INTENT_CAPABILITY_ID: &str = "human_intent";

pub struct HumanIntentCapability;

impl Capability for HumanIntentCapability {
    fn id(&self) -> &'static str {
        HUMAN_INTENT_CAPABILITY_ID
    }

    fn name(&self) -> &'static str {
        "Human Intent"
    }

    fn description(&self) -> &'static str {
        "Adds model-authored human_intent narration to every active tool call for UI rendering."
    }

    fn localizations(&self) -> Vec<CapabilityLocalization> {
        vec![CapabilityLocalization::text(
            "uk",
            "Людський намір",
            "Додає до кожного активного виклику інструмента написаний моделлю опис наміру human_intent для відображення в інтерфейсі.",
        )]
    }

    fn category(&self) -> Option<&'static str> {
        Some("Core")
    }

    fn tool_definition_hooks(&self) -> Vec<Arc<dyn ToolDefinitionHook>> {
        vec![Arc::new(HumanIntentToolDefinitionHook)]
    }

    fn tool_call_hooks(&self) -> Vec<Arc<dyn ToolCallHook>> {
        vec![Arc::new(HumanIntentToolCallHook)]
    }
}

struct HumanIntentToolDefinitionHook;

impl ToolDefinitionHook for HumanIntentToolDefinitionHook {
    fn transform(&self, tools: Vec<ToolDefinition>) -> Vec<ToolDefinition> {
        add_human_intent_to_tool_definitions(&tools)
    }
}

struct HumanIntentToolCallHook;

impl ToolCallHook for HumanIntentToolCallHook {
    fn narration(
        &self,
        _tool_def: Option<&ToolDefinition>,
        tool_call: &ToolCall,
        _phase: ToolNarrationPhase,
        _locale: Option<&str>,
        _ctx: crate::tool_narration::ToolNarrationContext<'_>,
    ) -> Option<String> {
        human_intent(&tool_call.arguments).map(truncate_intent)
    }

    fn transform_for_execution(&self, mut tool_call: ToolCall) -> ToolCall {
        tool_call.arguments = tool_call.execution_arguments();
        tool_call
    }
}

fn truncate_intent(intent: &str) -> String {
    const MAX_LEN: usize = 120;
    const ELLIPSIS: &str = "...";
    let clean = intent.trim();
    if clean.chars().count() <= MAX_LEN {
        return clean.to_string();
    }

    let truncated: String = clean
        .chars()
        .take(MAX_LEN - ELLIPSIS.chars().count())
        .collect();
    format!("{truncated}{ELLIPSIS}")
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tool_types::{BuiltinTool, DeferrablePolicy, ToolPolicy};
    use serde_json::json;

    #[test]
    fn human_intent_capability_adds_optional_schema_argument() {
        let capability = HumanIntentCapability;
        let hook = capability.tool_definition_hooks().pop().unwrap();
        let tool = ToolDefinition::Builtin(BuiltinTool {
            name: "manage_harnesses".to_string(),
            display_name: Some("Manage Harnesses".to_string()),
            description: "Manage harnesses".to_string(),
            parameters: json!({
                "type": "object",
                "properties": {
                    "operation": { "type": "string" }
                },
                "required": ["operation"],
                "additionalProperties": false
            }),
            policy: ToolPolicy::Auto,
            category: None,
            deferrable: DeferrablePolicy::default(),
            hints: Default::default(),
            full_parameters: None,
        });

        let original = serde_json::to_value(&tool).unwrap();
        let transformed = hook.transform(vec![tool]);
        assert_eq!(transformed.len(), 1);
        let mut restored = serde_json::to_value(&transformed[0]).unwrap();
        restored["parameters"]["properties"]
            .as_object_mut()
            .unwrap()
            .remove("human_intent");
        assert_eq!(restored, original);
        let params = transformed[0].parameters();

        assert_eq!(params["properties"]["human_intent"]["type"], "string");
        assert_eq!(params["properties"]["human_intent"]["maxLength"], 120);
        assert!(
            !params["required"]
                .as_array()
                .unwrap()
                .iter()
                .any(|item| item.as_str() == Some("human_intent"))
        );
        assert_eq!(params["additionalProperties"], false);
    }

    #[test]
    fn narration_trims_unicode_boundaries_and_execution_preserves_original_call() {
        let hook = HumanIntentCapability.tool_call_hooks().pop().unwrap();
        for (intent, expected) in [
            (json!(null), None),
            (json!(17), None),
            (json!("  "), None),
            (
                json!("  Listing harnesses  "),
                Some("Listing harnesses".to_owned()),
            ),
            (json!("".repeat(119)), Some("".repeat(119))),
            (json!("".repeat(120)), Some("".repeat(120))),
            (
                json!(format!("  {}  ", "".repeat(121))),
                Some(format!("{}...", "".repeat(117))),
            ),
        ] {
            let call = ToolCall {
                id: "call-original".into(),
                name: "manage_harnesses".into(),
                arguments: json!({"operation":"list","nested":{"keep":true},"human_intent":intent}),
            };
            for phase in [
                ToolNarrationPhase::Started,
                ToolNarrationPhase::Waiting,
                ToolNarrationPhase::Completed,
                ToolNarrationPhase::Failed,
            ] {
                assert_eq!(
                    hook.narration(None, &call, phase, Some("uk-UA"), Default::default()),
                    expected
                );
            }
            let execution = hook.transform_for_execution(call);
            assert_eq!(
                serde_json::to_value(execution).unwrap(),
                json!({"id":"call-original","name":"manage_harnesses","arguments":{"operation":"list","nested":{"keep":true}}})
            );
        }
        let call = ToolCall {
            id: "no-intent".into(),
            name: "plain".into(),
            arguments: json!({"operation":"list"}),
        };
        assert_eq!(
            hook.narration(
                None,
                &call,
                ToolNarrationPhase::Started,
                None,
                Default::default()
            ),
            None
        );
        assert_eq!(
            serde_json::to_value(hook.transform_for_execution(call.clone())).unwrap(),
            serde_json::to_value(call).unwrap()
        );
    }
}