huskies: merge 898

This commit is contained in:
dave
2026-05-12 21:29:04 +00:00
parent d78dd9e8f9
commit 937792f208
10 changed files with 829 additions and 23 deletions
+53
View File
@@ -21,6 +21,12 @@ pub(crate) struct CliArgs {
pub(crate) join_token: Option<String>,
/// HTTP URL of the gateway to register with when a join token is provided (`--gateway-url`).
pub(crate) gateway_url: Option<String>,
/// WebSocket URL of the upstream gateway to forward permission requests to (`--upstream-gateway`).
///
/// When set, the sled spawns a background uplink task that holds `perm_rx` and
/// forwards all `prompt_permission` tool calls to the gateway over a WebSocket.
/// Also readable from the `HUSKIES_UPSTREAM_GATEWAY` env var.
pub(crate) upstream_gateway: Option<String>,
}
/// Parse CLI arguments into `CliArgs`, or exit early for `--help` / `--version`.
@@ -34,6 +40,7 @@ pub(crate) fn parse_cli_args(args: &[String]) -> Result<CliArgs, String> {
let mut rendezvous: Option<String> = None;
let mut join_token: Option<String> = None;
let mut gateway_url: Option<String> = None;
let mut upstream_gateway: Option<String> = None;
let mut i = 0;
while i < args.len() {
@@ -94,6 +101,16 @@ pub(crate) fn parse_cli_args(args: &[String]) -> Result<CliArgs, String> {
a if a.starts_with("--gateway-url=") => {
gateway_url = Some(a["--gateway-url=".len()..].to_string());
}
"--upstream-gateway" => {
i += 1;
if i >= args.len() {
return Err("--upstream-gateway requires a value".to_string());
}
upstream_gateway = Some(args[i].clone());
}
a if a.starts_with("--upstream-gateway=") => {
upstream_gateway = Some(a["--upstream-gateway=".len()..].to_string());
}
"--gateway" => {
gateway = true;
}
@@ -129,6 +146,7 @@ pub(crate) fn parse_cli_args(args: &[String]) -> Result<CliArgs, String> {
gateway,
join_token,
gateway_url,
upstream_gateway,
})
}
@@ -167,6 +185,11 @@ pub(crate) fn print_help() {
println!(" --gateway-url <URL> HTTP URL of the gateway to register with when");
println!(" --join-token is provided (agent mode only).");
println!(" Also readable from HUSKIES_GATEWAY_URL env var.");
println!(" --upstream-gateway <URL> WebSocket URL of an upstream gateway to forward");
println!(" permission requests to (sled mode). When set, the");
println!(" sled connects to WS URL and forwards all");
println!(" prompt_permission calls via the uplink protocol.");
println!(" Also readable from HUSKIES_UPSTREAM_GATEWAY env var.");
}
/// Resolve the optional positional path argument into an absolute `PathBuf`.
@@ -343,6 +366,36 @@ mod tests {
let result = parse_cli_args(&[]).unwrap();
assert_eq!(result.join_token, None);
assert_eq!(result.gateway_url, None);
assert_eq!(result.upstream_gateway, None);
}
#[test]
fn parse_upstream_gateway_flag() {
let args = vec![
"--upstream-gateway".to_string(),
"ws://gateway:3001/api/sled-uplink?token=abc".to_string(),
];
let result = parse_cli_args(&args).unwrap();
assert_eq!(
result.upstream_gateway,
Some("ws://gateway:3001/api/sled-uplink?token=abc".to_string())
);
}
#[test]
fn parse_upstream_gateway_equals_syntax() {
let args = vec!["--upstream-gateway=ws://gw:3001/api/sled-uplink?token=x".to_string()];
let result = parse_cli_args(&args).unwrap();
assert_eq!(
result.upstream_gateway,
Some("ws://gw:3001/api/sled-uplink?token=x".to_string())
);
}
#[test]
fn parse_upstream_gateway_missing_value_is_error() {
let args = vec!["--upstream-gateway".to_string()];
assert!(parse_cli_args(&args).is_err());
}
// ── resolve_path_arg ────────────────────────────────────────────