Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions crates/buzz-cli/src/commands/agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,55 @@ pub async fn dispatch(command: AgentsCmd, client: &BuzzClient) -> Result<(), Cli
}

AgentsCmd::Archived => cmd_archived(client).await,

AgentsCmd::PublishProfile {
name,
agent_type,
channel_ids,
status,
respond_to,
respond_to_allowlist,
channel_add_policy,
} => {
match respond_to.as_str() {
"owner-only" | "allowlist" | "anyone" => {}
_ => {
return Err(CliError::Usage(format!(
"--respond-to must be 'owner-only', 'allowlist', or 'anyone' (got: {respond_to})"
)))
}
}
match channel_add_policy.as_str() {
"anyone" | "owner_only" | "nobody" => {}
_ => {
return Err(CliError::Usage(format!(
"--channel-add-policy must be 'anyone', 'owner_only', or 'nobody' (got: {channel_add_policy})"
)))
}
}
let content = json!({
"name": name,
"agent_type": agent_type,
"channels": [],
"channel_ids": channel_ids,
"capabilities": [],
"status": status,
"respond_to": respond_to,
"respond_to_allowlist": respond_to_allowlist,
"channel_add_policy": channel_add_policy,
})
.to_string();
use nostr::{EventBuilder, Kind};
let builder = EventBuilder::new(
Kind::Custom(buzz_sdk::kind::KIND_AGENT_PROFILE as u16),
&content,
)
.tags([]);
let event = client.sign_event(builder)?;
let resp = client.submit_event(event).await?;
println!("{resp}");
Ok(())
}
}
}

Expand Down
35 changes: 34 additions & 1 deletion crates/buzz-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,38 @@ Examples:\n \
buzz agents archived"
)]
Archived,
/// Publish this identity's relay agent profile (kind:10100) — makes a headless
/// (non-managed) agent discoverable and @mentionable by Buzz Desktop clients.
#[command(
after_help = "kind:10100 is a replaceable event: this fully overwrites any \
previous agent profile for the signing identity.\n\n\
Examples:\n \
buzz agents publish-profile --name Coder --channel-ids <UUID> --respond-to allowlist \
--respond-to-allowlist <PUBKEY1>,<PUBKEY2> --channel-add-policy owner_only"
)]
PublishProfile {
/// Display name shown in Buzz Desktop
#[arg(long)]
name: String,
/// Free-form agent type label (default: "agent")
#[arg(long, default_value = "agent")]
agent_type: String,
/// Channel UUIDs this agent should be considered mentionable in (comma-separated)
#[arg(long, value_delimiter = ',')]
channel_ids: Vec<String>,
/// Presence status to report
#[arg(long, default_value = "online")]
status: String,
/// Who this agent responds to: owner-only, allowlist, or anyone
#[arg(long, default_value = "allowlist")]
respond_to: String,
/// Pubkeys allowed to trigger this agent when --respond-to=allowlist (comma-separated)
#[arg(long, value_delimiter = ',')]
respond_to_allowlist: Vec<String>,
/// Who may add this agent to new channels: anyone, owner_only, or nobody
#[arg(long, default_value = "owner_only")]
channel_add_policy: String,
},
}

#[derive(Subcommand)]
Expand Down Expand Up @@ -2175,6 +2207,7 @@ mod tests {
"archived",
"draft-create",
"draft-update",
"publish-profile",
"unarchive"
]
);
Expand Down Expand Up @@ -2313,7 +2346,7 @@ mod tests {
#[test]
fn subcommand_counts_are_stable() {
let expected: Vec<(&str, usize)> = vec![
("agents", 5),
("agents", 6),
("canvas", 2),
("channels", 16),
("dms", 4),
Expand Down