use comfy_table::{Attribute, Cell, Color, Table};
use super::presets::{AgentSlot, fmt_price};
use crate::brand;
pub(super) fn shell_quote(s: &str) -> String {
if !s.is_empty()
&& s.chars()
.all(|c| c.is_ascii_alphanumeric() || "-_.:/@".contains(c))
{
return s.to_string();
}
format!("'{}'", s.replace('\'', "'\\''"))
}
pub(super) fn print_share_with_workers(app_port: u16, worker_secret: &str) {
let quoted_token = shell_quote(worker_secret);
println!(" {} Share with agent runners:", brand::dim("4."));
println!();
println!(
" Orchestrator URL: {}",
brand::teal(&format!("http://<this-host>:{app_port}"))
);
println!(" Worker token: {}", brand::teal(worker_secret));
println!();
println!(" {}", brand::dim("They run:"));
println!(
" {}",
brand::teal(&format!(
"nsed-agent init --orchestrator http://<this-host>:{app_port} --auth {quoted_token}"
))
);
println!();
}
pub(super) fn print_list_agents(app_port: u16, api_secret: &str) {
let auth_header = format!("Authorization: Bearer {api_secret}");
let quoted_header = shell_quote(&auth_header);
println!(" {} List connected agents:", brand::dim("5."));
println!();
println!(
" {}",
brand::teal(&format!("curl -s http://localhost:{app_port}/agents \\"))
);
println!(" {}", brand::teal(&format!(" -H {quoted_header}")));
println!();
}
pub(super) fn print_submit_guidance(app_port: u16, api_secret: &str, agents: &[AgentSlot]) {
let auth_header = format!("Authorization: Bearer {api_secret}");
let quoted_header = shell_quote(&auth_header);
let agent_names: Vec<String> = agents.iter().map(|a| a.name.clone()).collect();
let names_json = serde_json::to_string(&agent_names).unwrap_or_else(|_| "[]".to_string());
let quoted_body = shell_quote(&format!(
r#"{{"room_id": "test", "user_query": "Hello world", "deliberation_rounds": 2, "agent_names": {names_json}}}"#
));
println!(" {} Submit your first deliberation:", brand::dim("6."));
println!();
println!(
" {}",
brand::teal(&format!(
"curl -X POST http://localhost:{app_port}/deliberation \\"
))
);
println!(
" {}",
brand::teal(&format!(" -H {quoted_header} \\"))
);
println!(
" {}",
brand::teal(" -H 'Content-Type: application/json' \\")
);
println!(" {}", brand::teal(&format!(" -d {quoted_body}")));
println!();
}
pub(super) fn print_security_notice() {
brand::section("security");
brand::warn("Two tokens are generated in .env:");
println!();
println!(
" {} admin token (TOKENS__0) — full access, keep private",
brand::orange("•")
);
println!(
" {} worker token (TOKENS__1) — safe to share with agent runners",
brand::teal("•")
);
println!();
println!(
" {}",
brand::dim("The worker token can submit jobs, view results, list agents,")
);
println!(
" {}",
brand::dim("and stream events. It cannot delete jobs or access admin")
);
println!(
" {}",
brand::dim("endpoints — those require the admin role.")
);
println!();
println!(
" {}",
brand::dim("• Keep .env out of version control (already gitignored)")
);
println!(
" {}",
brand::dim("• Use TLS (HTTPS) in production to protect tokens in transit")
);
println!(
" {}",
brand::dim("• Rotate tokens by updating their SECRET values in .env")
);
println!();
}
pub(super) fn print_pricing_table(agents: &[AgentSlot]) {
brand::section("pricing summary");
println!(
" {}",
brand::dim("Prices are USD per million tokens ($/Mtok)")
);
let mut table = Table::new();
table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY);
table.set_header(vec![
Cell::new("#").add_attribute(Attribute::Bold),
Cell::new("persona").add_attribute(Attribute::Bold),
Cell::new("model").add_attribute(Attribute::Bold),
Cell::new("provider").add_attribute(Attribute::Bold),
Cell::new("input $/Mtok").add_attribute(Attribute::Bold),
Cell::new("output $/Mtok").add_attribute(Attribute::Bold),
]);
for (i, agent) in agents.iter().enumerate() {
let inp_str = fmt_price(agent.input_price);
let out_str = fmt_price(agent.output_price);
let model_display = {
let count = agent.model_name.chars().count();
if count > 30 {
let tail: String = agent.model_name.chars().skip(count - 29).collect();
format!("…{tail}")
} else {
agent.model_name.clone()
}
};
let inp_cell = match agent.input_price {
Some(v) if v > 0.0 => Cell::new(&inp_str).fg(Color::AnsiValue(208)),
_ => Cell::new(&inp_str),
};
let out_cell = match agent.output_price {
Some(v) if v > 0.0 => Cell::new(&out_str).fg(Color::AnsiValue(208)),
_ => Cell::new(&out_str),
};
table.add_row(vec![
Cell::new(format!("{}", i + 1)),
Cell::new(&agent.name).fg(Color::AnsiValue(135)), Cell::new(&model_display),
Cell::new(&agent.provider_id),
inp_cell,
out_cell,
]);
}
for line in table.to_string().lines() {
println!(" {line}");
}
println!();
}