mobius 0.16.25

A small, modular Rust framework for building coding agents
Documentation
use serde::Deserialize;
use serde_json::Value;

use super::{Basis, MAX_NOTE_BYTES, ScratchpadStore, WriteOutcome, publish_widgets, text};
use crate::backend::model::ToolDefinition;
use crate::middleware::FrontendEventSink;
use crate::middleware::tools::{ApprovalRequirement, Tool, ToolContext};
use crate::{BoxFuture, Result};

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct WriteArgs {
    note: String,
}

pub(super) struct WriteScratchpad {
    pub(super) store: ScratchpadStore,
    pub(super) frontend: FrontendEventSink,
}

impl Tool for WriteScratchpad {
    fn definition(&self) -> ToolDefinition {
        let mut tool = text::DEFINITION.write_scratchpad.tool.clone();
        tool.parameters["properties"]["note"]["maxLength"] = MAX_NOTE_BYTES.into();
        tool
    }

    fn approval(&self) -> ApprovalRequirement {
        ApprovalRequirement::Always
    }

    fn call<'a>(
        &'a self,
        _context: ToolContext,
        arguments: Value,
    ) -> BoxFuture<'a, Result<crate::protocol::ToolResponse>> {
        Box::pin(async move {
            let arguments: WriteArgs = serde_json::from_value(arguments)?;
            let access = self.store.lock_access().await;
            let outcome = self
                .store
                .write_locked(&arguments.note, Basis::AgentObservation, &access)
                .await?;
            if outcome != WriteOutcome::Existing {
                let snapshot = self.store.snapshot_locked(&access).await?;
                publish_widgets(&self.frontend, &snapshot)?;
            }
            Ok(match outcome {
                WriteOutcome::Added => text::DEFINITION.message_added.as_str(),
                WriteOutcome::Updated => text::DEFINITION.message_updated.as_str(),
                WriteOutcome::Existing => text::DEFINITION.message_existing.as_str(),
            }
            .into())
        })
    }
}