supercode-cli 0.5.84

Volter Harness — a lightweight, fully-customizable AI coding agent CLI in Rust. Any model via OpenRouter; natively continues Claude Code and Codex sessions.
//! Native adapter for OpenRouter's documented PKCE flow. Credentials are saved
//! by the CLI's existing login path, never by this module.
use anyhow::{bail, Context, Result};
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
use sha2::{Digest, Sha256};
use std::time::Duration;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use url::Url;

const API: &str = "https://openrouter.ai/api/v1/auth/keys";

fn random_token() -> Result<String> {
    let mut bytes = [0u8; 32];
    getrandom::getrandom(&mut bytes).map_err(|_| anyhow::anyhow!("OS randomness unavailable"))?;
    Ok(URL_SAFE_NO_PAD.encode(bytes))
}
fn authorization_url(verifier: &str, callback: Option<&str>) -> Result<Url> {
    let mut url = Url::parse("https://openrouter.ai/auth")?;
    {
        let mut params = url.query_pairs_mut();
        params.append_pair(
            "code_challenge",
            &URL_SAFE_NO_PAD.encode(Sha256::digest(verifier)),
        );
        params.append_pair("code_challenge_method", "S256");
        params.append_pair("key_label", "Volter Harness");
        if let Some(callback) = callback {
            params.append_pair("callback_url", callback);
        }
    }
    Ok(url)
}

pub async fn authorize(headless: bool) -> Result<String> {
    let verifier = random_token()?;
    let code = if headless {
        let url = authorization_url(&verifier, None)?;
        eprintln!(
            "Open this URL, authorize Volter Harness, then paste the authorization code:\n{url}"
        );
        crate::hidden_input::read_hidden_line().context("reading authorization code")?
    } else {
        let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
            .await
            .context("opening OAuth callback listener; use --oauth --headless over SSH")?;
        let path = format!("/callback/{}", random_token()?);
        let callback = format!("http://127.0.0.1:{}{path}", listener.local_addr()?.port());
        let url = authorization_url(&verifier, Some(&callback))?;
        eprintln!("Authorize Volter Harness in your browser:\n{url}");
        open_browser(url.as_str());
        tokio::time::timeout(Duration::from_secs(600), receive_callback(&listener, &path))
            .await
            .context("OpenRouter sign-in timed out; run login again")??
    };
    if code.trim().is_empty() || code.len() > 4096 {
        bail!("invalid authorization code");
    }
    exchange(API, code.trim(), &verifier).await
}

fn open_browser(url: &str) {
    #[cfg(target_os = "macos")]
    let command = Some(("open", vec![url]));
    #[cfg(target_os = "linux")]
    let command = Some(("xdg-open", vec![url]));
    #[cfg(target_os = "windows")]
    let command = Some(("rundll32", vec!["url.dll,FileProtocolHandler", url]));
    #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    let command: Option<(&str, Vec<&str>)> = None;
    if let Some((program, args)) = command {
        // URL remains visible if no desktop opener exists. Never invoke a shell.
        let _ = std::process::Command::new(program)
            .args(args)
            .stdin(std::process::Stdio::null())
            .stdout(std::process::Stdio::null())
            .stderr(std::process::Stdio::null())
            .spawn();
    }
}

fn callback_code(target: &str, path: &str) -> Result<Option<String>> {
    if !target.starts_with('/') || target.starts_with("//") {
        return Ok(None);
    }
    let url = Url::parse(&format!("http://localhost{target}"))?;
    if url.path() != path {
        return Ok(None);
    }
    if url.query_pairs().any(|(name, _)| name == "error") {
        bail!("OpenRouter authorization was declined");
    }
    let codes: Vec<_> = url
        .query_pairs()
        .filter(|(name, _)| name == "code")
        .map(|(_, code)| code.into_owned())
        .collect();
    if codes.len() != 1 || codes[0].is_empty() || codes[0].len() > 4096 {
        bail!("OpenRouter callback has no unique authorization code");
    }
    Ok(Some(codes[0].clone()))
}

async fn receive_callback(listener: &tokio::net::TcpListener, path: &str) -> Result<String> {
    loop {
        let (mut stream, _) = listener.accept().await?;
        let mut bytes = Vec::new();
        let read = tokio::time::timeout(Duration::from_secs(5), async {
            let mut byte = [0u8; 1];
            while bytes.len() < 8192 {
                if stream.read(&mut byte).await? == 0 {
                    break;
                }
                bytes.push(byte[0]);
                if bytes.ends_with(b"\r\n\r\n") {
                    break;
                }
            }
            Ok::<_, std::io::Error>(())
        })
        .await;
        if !matches!(read, Ok(Ok(()))) {
            continue;
        }
        let request = String::from_utf8_lossy(&bytes);
        let mut line = request
            .lines()
            .next()
            .unwrap_or_default()
            .split_whitespace();
        let method = line.next();
        let target = line.next().unwrap_or_default();
        let result = if method == Some("GET") {
            callback_code(target, path)
        } else {
            Ok(None)
        };
        let (status, message) = match &result {
            Ok(Some(_)) => (
                "200 OK",
                "Authorization received. Return to Volter Harness to finish signing in.",
            ),
            Ok(None) => ("404 Not Found", "Unknown callback."),
            Err(_) => (
                "400 Bad Request",
                "Authorization failed. Return to Volter Harness.",
            ),
        };
        let response = format!("HTTP/1.1 {status}\r\nContent-Type: text/plain\r\nCache-Control: no-store\r\nReferrer-Policy: no-referrer\r\nConnection: close\r\nContent-Length: {}\r\n\r\n{message}", message.len());
        let _ = stream.write_all(response.as_bytes()).await;
        if let Some(code) = result? {
            return Ok(code);
        }
    }
}

async fn exchange(endpoint: &str, code: &str, verifier: &str) -> Result<String> {
    let client = reqwest::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .timeout(Duration::from_secs(30))
        .build()?;
    let response = client
        .post(endpoint)
        .json(&serde_json::json!({
            "code": code, "code_verifier": verifier, "code_challenge_method": "S256"
        }))
        .send()
        .await
        .context("OpenRouter authorization exchange failed")?;
    if !response.status().is_success() {
        // Responses may contain sensitive values. Report only status, never body.
        bail!(
            "OpenRouter authorization exchange returned HTTP {}; run login again",
            response.status()
        );
    }
    let body: serde_json::Value = response
        .json()
        .await
        .context("invalid OpenRouter authorization response")?;
    let key = body
        .get("key")
        .and_then(|value| value.as_str())
        .filter(|key| {
            (8..=4096).contains(&key.len())
                && key
                    .bytes()
                    .all(|b| b.is_ascii_alphanumeric() || b == b'-' || b == b'_')
        })
        .context("OpenRouter returned no valid API key")?;
    Ok(key.to_owned())
}