Add deterministic agent context compiler

Signed-off-by: Salman Mohammed <smohammed@squareup.com>
This commit is contained in:
Salman Mohammed
2026-08-21 13:54:22 -04:00
parent 7da8f9abf3
commit 33909a352f
22 changed files with 2522 additions and 1340 deletions

View File

@@ -0,0 +1,29 @@
use clap::Parser;
use super::Cli;
#[test]
fn messages_thread_accepts_link_or_explicit_identifiers() {
let channel = "123e4567-e89b-12d3-a456-426614174000";
let event = "a".repeat(64);
let link = format!("buzz://message?channel={channel}&id={event}");
assert!(Cli::try_parse_from(["buzz", "messages", "thread", "--link", link.as_str(),]).is_ok());
assert!(Cli::try_parse_from([
"buzz",
"messages",
"thread",
"--channel",
channel,
"--event",
event.as_str(),
])
.is_ok());
}
#[test]
fn messages_raw_requires_an_event_id_argument() {
let event = "a".repeat(64);
assert!(Cli::try_parse_from(["buzz", "messages", "raw", "--event", event.as_str()]).is_ok());
assert!(Cli::try_parse_from(["buzz", "messages", "raw"]).is_err());
}

View File

@@ -12,6 +12,8 @@ use buzz_sdk::mentions::{
extract_at_mentions_with_known, extract_nostr_uris, strip_code_regions, MENTION_CAP,
};
use super::messages_fetch::{cmd_get_raw_event, fetch_event};
/// Extract the thread root event ID from a Nostr tag array.
///
/// Delegates marker parsing and collapse to [`buzz_core::nip10`] (shared with
@@ -55,26 +57,6 @@ fn thread_ref_from_parent_tags(
})
}
/// Build a `ThreadRef` for a reply, given the immediate parent's event ID.
///
/// Fetches the parent event from the relay and inspects its NIP-10 `e` tags to
/// determine the thread root:
/// - Direct reply (parent is top-level): `root == parent`.
/// - Nested reply: `root` is the parent's own root marker; `parent` is unchanged.
///
/// Ensures CLI-sent replies thread correctly using the same NIP-10 logic.
async fn fetch_event(client: &BuzzClient, event_id: &str) -> Result<serde_json::Value, CliError> {
let filter = serde_json::json!({ "ids": [event_id], "limit": 1 });
let raw = client.query(&filter).await?;
let events: serde_json::Value = serde_json::from_str(&raw)
.map_err(|e| CliError::Other(format!("failed to parse query response: {e}")))?;
events
.as_array()
.and_then(|events| events.first())
.cloned()
.ok_or_else(|| CliError::NotFound(format!("event {event_id} not found")))
}
async fn resolve_thread_ref(
client: &BuzzClient,
parent_event_id: &str,
@@ -999,6 +981,7 @@ pub async fn dispatch(
)
.await
}
MessagesCmd::Raw { event } => cmd_get_raw_event(client, &event).await,
MessagesCmd::Thread {
channel,
event,

View File

@@ -0,0 +1,35 @@
//! Shared signed-event retrieval for message commands.
use crate::client::BuzzClient;
use crate::error::CliError;
use crate::validate::validate_hex64;
/// Fetch a message event while preserving its signed relay representation.
pub(super) async fn fetch_event(
client: &BuzzClient,
event_id: &str,
) -> Result<serde_json::Value, CliError> {
let filter = serde_json::json!({
"ids": [event_id],
"kinds": [9, 40002, 40003, 40008, 45001, 45003],
"limit": 1
});
let raw = client.query(&filter).await?;
let events: serde_json::Value = serde_json::from_str(&raw)
.map_err(|error| CliError::Other(format!("failed to parse query response: {error}")))?;
events
.as_array()
.and_then(|events| events.first())
.cloned()
.ok_or_else(|| CliError::NotFound(format!("event {event_id} not found")))
}
/// Print a signed message event without model-oriented normalization.
pub(super) async fn cmd_get_raw_event(client: &BuzzClient, event_id: &str) -> Result<(), CliError> {
validate_hex64(event_id)?;
let event = fetch_event(client, event_id).await?;
let json = serde_json::to_string(&event)
.map_err(|error| CliError::Other(format!("failed to serialize raw event: {error}")))?;
println!("{json}");
Ok(())
}

View File

@@ -7,6 +7,7 @@ pub mod feed;
pub mod issues;
pub mod mem;
pub mod messages;
mod messages_fetch;
pub mod moderation;
pub mod notes;
pub mod pack;

View File

@@ -5,6 +5,9 @@ mod error;
mod links;
mod validate;
#[cfg(test)]
mod cli_message_command_tests;
use clap::{Parser, Subcommand};
use client::BuzzClient;
use error::CliError;
@@ -480,6 +483,12 @@ pub enum MessagesCmd {
#[arg(long)]
kinds: Option<String>,
},
/// Retrieve one signed message event without stripping tags or signature
Raw {
/// Event ID (64-char hex)
#[arg(long)]
event: String,
},
/// Get the containing thread for a message or Buzz message link
#[command(
after_help = "Examples:\n buzz messages thread --channel <UUID> --event <EVENT_ID>\n buzz messages thread --link 'buzz://message?channel=<UUID>&id=<EVENT_ID>&thread=<ROOT_ID>'"
@@ -2126,27 +2135,6 @@ mod tests {
Cli::command().debug_assert();
}
#[test]
fn messages_thread_accepts_link_or_explicit_identifiers() {
let channel = "123e4567-e89b-12d3-a456-426614174000";
let event = "a".repeat(64);
let link = format!("buzz://message?channel={channel}&id={event}");
assert!(
Cli::try_parse_from(["buzz", "messages", "thread", "--link", link.as_str(),]).is_ok()
);
assert!(Cli::try_parse_from([
"buzz",
"messages",
"thread",
"--channel",
channel,
"--event",
event.as_str(),
])
.is_ok());
}
#[test]
fn messages_thread_rejects_partial_or_mixed_targets() {
let channel = "123e4567-e89b-12d3-a456-426614174000";
@@ -2273,6 +2261,7 @@ mod tests {
"delete",
"edit",
"get",
"raw",
"search",
"send",
"send-diff",
@@ -2410,7 +2399,7 @@ mod tests {
("feed", 1),
("issues", 6),
("media", 1),
("messages", 8),
("messages", 9),
("pack", 2),
("patches", 4),
("pr", 5),