brokerd: recall and memory, decided under built-in grants

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-25 16:41:44 -07:00
committed by kyle
parent 0c8d136c6b
commit fcfd590687
10 changed files with 267 additions and 9 deletions
+37 -2
View File
@@ -5,6 +5,7 @@
//! was written by the model, so it is treated as hostile.
use proto::tools::{HttpFetchArgs, ReadFileArgs, ShellArgs, WriteFileArgs};
use proto::{MemoryArgs, RecallArgs};
use std::fmt;
/// Maximum length, in bytes, of a path.
@@ -12,17 +13,20 @@ pub const MAX_PATH: usize = 4096;
/// Maximum length, in bytes, of a URL.
pub const MAX_URL: usize = 2048;
/// The four tools the broker can dispatch to.
/// The tools the broker can dispatch to: four that run in a container, and the two memory
/// tools that `memoryd` runs (M5a spec, section 8).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolName {
ReadFile,
WriteFile,
Shell,
HttpFetch,
Recall,
Memory,
}
impl ToolName {
/// The four tools, in the order listed in the interface.
/// The four container tools, in the order listed in the interface.
pub const ALL: [ToolName; 4] = [
ToolName::ReadFile,
ToolName::WriteFile,
@@ -37,6 +41,8 @@ impl ToolName {
"write_file" => Some(ToolName::WriteFile),
"shell" => Some(ToolName::Shell),
"http_fetch" => Some(ToolName::HttpFetch),
"recall" => Some(ToolName::Recall),
"memory" => Some(ToolName::Memory),
_ => None,
}
}
@@ -48,8 +54,15 @@ impl ToolName {
ToolName::WriteFile => "write_file",
ToolName::Shell => "shell",
ToolName::HttpFetch => "http_fetch",
ToolName::Recall => "recall",
ToolName::Memory => "memory",
}
}
/// Whether `memoryd` runs this tool rather than a container.
pub fn is_memory(self) -> bool {
matches!(self, ToolName::Recall | ToolName::Memory)
}
}
/// A parsed set of tool arguments, one variant per tool.
@@ -67,6 +80,8 @@ pub enum ToolArgs {
cwd: Option<String>,
},
HttpFetch(FetchUrl),
Recall(RecallArgs),
Memory(MemoryArgs),
}
/// A URL that passed the checks, and its host. Only `parse` makes one, so the host policy matched
@@ -109,6 +124,8 @@ impl ToolArgs {
ToolArgs::WriteFile { .. } => ToolName::WriteFile,
ToolArgs::Shell { .. } => ToolName::Shell,
ToolArgs::HttpFetch(_) => ToolName::HttpFetch,
ToolArgs::Recall(_) => ToolName::Recall,
ToolArgs::Memory(_) => ToolName::Memory,
}
}
@@ -142,6 +159,12 @@ impl ToolArgs {
};
serde_json::to_string(&value).unwrap_or_else(|_| "{}".to_string())
}
ToolArgs::Recall(value) => {
serde_json::to_string(value).unwrap_or_else(|_| "{}".to_string())
}
ToolArgs::Memory(value) => {
serde_json::to_string(value).unwrap_or_else(|_| "{}".to_string())
}
}
}
}
@@ -228,6 +251,18 @@ pub fn parse(tool: ToolName, arguments: &str) -> Result<ToolArgs, ArgsError> {
host,
}))
}
ToolName::Recall => {
let value: RecallArgs = serde_json::from_str(arguments)
.map_err(|error| ArgsError::Shape(error.to_string()))?;
value.check().map_err(ArgsError::Shape)?;
Ok(ToolArgs::Recall(value))
}
ToolName::Memory => {
let value: MemoryArgs = serde_json::from_str(arguments)
.map_err(|error| ArgsError::Shape(error.to_string()))?;
value.check().map_err(ArgsError::Shape)?;
Ok(ToolArgs::Memory(value))
}
}
}