agents-kit 0.0.1

Rust agent control Kit for Codex, OpenCode, and provider-backed Custom runtimes
Documentation
use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use serde::Deserialize;
use serde_json::Value;
use std::path::PathBuf;

use crate::{FileRead, KitError};

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct CodexFsReadFileResponse {
    data_base64: String,
}

pub(crate) struct CodexFileRead {
    relative_path: PathBuf,
    absolute_path: PathBuf,
}

impl CodexFileRead {
    pub(crate) fn new(relative_path: PathBuf, absolute_path: PathBuf) -> Result<Self, KitError> {
        if !absolute_path.is_absolute() {
            return Err(KitError::invalid_state(
                "file adapter received a relative native path",
            ));
        }
        Ok(Self {
            relative_path,
            absolute_path,
        })
    }

    pub(crate) fn params(&self) -> Result<Value, KitError> {
        let path = self.absolute_path.to_str().ok_or_else(|| {
            KitError::unsupported("selected runtime cannot represent a non-UTF-8 backend-host path")
        })?;
        Ok(serde_json::json!({ "path": path }))
    }

    pub(crate) fn decode(self, value: Value) -> Result<FileRead, KitError> {
        let response: CodexFsReadFileResponse = serde_json::from_value(value)
            .map_err(|_| KitError::protocol("file response is malformed"))?;
        let bytes = STANDARD
            .decode(response.data_base64.as_bytes())
            .map_err(|_| KitError::protocol("file response contains invalid base64"))?;
        FileRead::from_bytes(self.relative_path, bytes)
    }
}