| 76 | } |
| 77 | |
| 78 | fn resolve_gateway( |
| 79 | gateway_flag: &Option<String>, |
| 80 | gateway_endpoint: &Option<String>, |
| 81 | ) -> Result<GatewayContext> { |
| 82 | if let Some(endpoint) = gateway_endpoint { |
| 83 | // When a gateway name is explicitly provided (via flag or env var), |
| 84 | // trust it directly — don't require metadata to exist yet. This |
| 85 | // avoids a race condition where mTLS certs are stored under the |
| 86 | // real gateway name but the CLI falls back to using the raw |
| 87 | // endpoint URL (producing a mangled path like `https___...`). |
| 88 | let name = gateway_flag |
| 89 | .clone() |
| 90 | .or_else(|| find_gateway_by_endpoint(endpoint)) |
| 91 | .unwrap_or_else(|| endpoint.clone()); |
| 92 | return Ok(GatewayContext { |
| 93 | name, |
| 94 | endpoint: endpoint.clone(), |
| 95 | }); |
| 96 | } |
| 97 | |
| 98 | let name = gateway_flag |
| 99 | .clone() |
| 100 | .or_else(|| { |
| 101 | std::env::var("OPENSHELL_GATEWAY") |
| 102 | .ok() |
| 103 | .filter(|v| !v.trim().is_empty()) |
| 104 | }) |
| 105 | .or_else(load_active_gateway) |
| 106 | .ok_or_else(|| { |
| 107 | miette::miette!( |
| 108 | "No active gateway.\n\ |
| 109 | Set one with: openshell gateway select <name>\n\ |
| 110 | Or register one with: openshell gateway add <endpoint>" |
| 111 | ) |
| 112 | })?; |
| 113 | |
| 114 | let metadata = load_gateway_metadata(&name).map_err(|_| { |
| 115 | miette::miette!( |
| 116 | "Unknown gateway '{name}'.\n\ |
| 117 | Register it first: openshell gateway add <endpoint> --name {name}\n\ |
| 118 | Or list available gateways: openshell gateway select" |
| 119 | ) |
| 120 | })?; |
| 121 | |
| 122 | Ok(GatewayContext { |
| 123 | name: metadata.name, |
| 124 | endpoint: metadata.gateway_endpoint, |
| 125 | }) |
| 126 | } |
| 127 | |
| 128 | fn parse_gpu_request(value: &str) -> std::result::Result<GpuCliRequest, String> { |
| 129 | if value.is_empty() { |