agent_first_http/cli/cmd/
ui.rs1use clap::Args as ClapArgs;
4use serde::Serialize;
5
6use crate::cli::output;
7use crate::sdk::endpoint::Endpoint;
8use crate::shared::error::Error;
9
10#[derive(ClapArgs, Debug)]
11pub struct Args {
12 #[arg(long = "endpoint-url")]
14 pub endpoint: String,
15 #[arg(long = "token-secret")]
17 pub token: Option<String>,
18}
19
20#[derive(Serialize)]
21struct UiResult {
22 panel_url: String,
23 display_url: String,
24}
25
26pub async fn run(args: Args) -> Result<(), Error> {
27 let result = build_result(&args.endpoint, args.token.as_deref())?;
28 output::emit("ui", &result)
29}
30
31fn build_result(endpoint: &str, token: Option<&str>) -> Result<UiResult, Error> {
32 let endpoint = Endpoint::parse(endpoint)?;
33 let base = endpoint.http_base();
34 let mut panel_url = url::Url::parse(&format!("{base}/ops")).map_err(|e| {
35 crate::shared::error::Error::new(
36 crate::shared::error::ErrorCode::InvalidEndpoint,
37 format!("ui panel URL from endpoint {base:?}: {e}"),
38 )
39 })?;
40 let mut display_url = url::Url::parse(&format!("{base}/ops/display")).map_err(|e| {
41 crate::shared::error::Error::new(
42 crate::shared::error::ErrorCode::InvalidEndpoint,
43 format!("ui display URL from endpoint {base:?}: {e}"),
44 )
45 })?;
46 if let Some(token) = token {
47 panel_url
48 .query_pairs_mut()
49 .append_pair("token_secret", token);
50 display_url
51 .query_pairs_mut()
52 .append_pair("token_secret", token);
53 }
54 Ok(UiResult {
55 panel_url: panel_url.to_string(),
56 display_url: display_url.to_string(),
57 })
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn ui_result_has_no_url_alias() {
66 let value = serde_json::to_value(UiResult {
67 panel_url: "http://localhost:9222/ops".into(),
68 display_url: "http://localhost:9222/ops/display".into(),
69 })
70 .unwrap();
71 assert!(value.get("url").is_none());
72 assert!(value.get("panel_url").is_some());
73 assert!(value.get("display_url").is_some());
74 }
75
76 #[test]
77 fn ui_token_query_is_percent_encoded() {
78 let result = build_result("http://localhost:9222", Some("a+b&c%20")).unwrap();
79 assert_eq!(
80 result.panel_url,
81 "http://localhost:9222/ops?token_secret=a%2Bb%26c%2520"
82 );
83 assert_eq!(
84 result.display_url,
85 "http://localhost:9222/ops/display?token_secret=a%2Bb%26c%2520"
86 );
87 }
88}