Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:36:00.498Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

setup_webrtc.rs

266 lines · 8.4 KB · rust
1#![allow(clippy::disallowed_methods, reason = "tooling is exempt")]
2
3use std::fs;
4use std::path::{Path, PathBuf};
5use std::process::Command;
6
7use anyhow::{Context as _, Result, bail};
8use cargo_toml::Manifest;
9use clap::Parser;
10use regex::Regex;
11use toml_edit::{DocumentMut, Item, Table, value};
12
13use crate::workspace::load_workspace;
14
15const GITIGNORE_ENTRY: &str = ".webrtc-sys/";
16const LOCAL_DIR_NAME: &str = ".webrtc-sys";
17const ENV_VAR: &str = "LK_CUSTOM_WEBRTC";
18
19#[derive(Parser)]
20pub struct SetupWebrtcArgs {
21    /// Re-download even if the target directory already exists.
22    #[arg(long)]
23    force: bool,
24
25    /// Override the host triple component used for the release artifact
26    /// (e.g. `mac-arm64-release`). Defaults to the current host.
27    #[arg(long)]
28    triple: Option<String>,
29
30    /// Skip writing to `~/.cargo/config.toml`. Useful when you only want the
31    /// archive on disk and intend to set `LK_CUSTOM_WEBRTC` yourself.
32    #[arg(long)]
33    no_cargo_config: bool,
34}
35
36pub fn run_setup_webrtc(args: SetupWebrtcArgs) -> Result<()> {
37    let metadata = load_workspace()?;
38    let workspace_root = metadata.workspace_root.as_std_path().to_path_buf();
39
40    let rev = read_webrtc_sys_rev(&workspace_root)?;
41    eprintln!("Pinned livekit-rust-sdks rev: {rev}");
42
43    let tag = fetch_webrtc_tag(&rev)?;
44    eprintln!("WEBRTC_TAG for that rev: {tag}");
45
46    let triple = match args.triple {
47        Some(triple) => triple,
48        None => host_webrtc_triple()?,
49    };
50    eprintln!("Target triple: {triple}");
51
52    let local_root = workspace_root.join(LOCAL_DIR_NAME);
53    let tag_dir = local_root.join(&tag);
54    let extracted_dir = tag_dir.join(&triple);
55
56    if extracted_dir.exists() && !args.force {
57        eprintln!(
58            "Already present at {}, skipping download.",
59            extracted_dir.display()
60        );
61    } else {
62        if extracted_dir.exists() {
63            fs::remove_dir_all(&extracted_dir)
64                .with_context(|| format!("removing stale {}", extracted_dir.display()))?;
65        }
66        fs::create_dir_all(&tag_dir).with_context(|| format!("creating {}", tag_dir.display()))?;
67        download_and_extract(&tag, &triple, &tag_dir)?;
68    }
69
70    let absolute = extracted_dir
71        .canonicalize()
72        .with_context(|| format!("canonicalizing {}", extracted_dir.display()))?;
73
74    ensure_gitignore_entry(&workspace_root)?;
75
76    if args.no_cargo_config {
77        eprintln!(
78            "Skipping ~/.cargo/config.toml update. Set {ENV_VAR}={} yourself.",
79            absolute.display()
80        );
81    } else {
82        update_cargo_config(&absolute)?;
83    }
84
85    eprintln!();
86    eprintln!("Done. {ENV_VAR} -> {}", absolute.display());
87    Ok(())
88}
89
90fn read_webrtc_sys_rev(workspace_root: &Path) -> Result<String> {
91    let manifest_path = workspace_root.join("Cargo.toml");
92    let manifest = Manifest::from_path(&manifest_path)
93        .with_context(|| format!("parsing {}", manifest_path.display()))?;
94
95    let patch = manifest
96        .patch
97        .get("crates-io")
98        .context("workspace Cargo.toml has no [patch.crates-io] section")?;
99    let dep = patch
100        .get("webrtc-sys")
101        .context("[patch.crates-io] is missing webrtc-sys")?;
102    let detail = dep
103        .detail()
104        .context("webrtc-sys patch entry is not a table")?;
105    detail
106        .git
107        .as_ref()
108        .context("webrtc-sys patch is missing a git source")?;
109    detail
110        .rev
111        .clone()
112        .context("webrtc-sys patch is missing a `rev`")
113}
114
115fn fetch_webrtc_tag(rev: &str) -> Result<String> {
116    let url = format!(
117        "https://raw.githubusercontent.com/zed-industries/livekit-rust-sdks/{rev}/webrtc-sys/build/src/lib.rs"
118    );
119    let body = curl_text(&url).with_context(|| format!("fetching {url}"))?;
120
121    let re =
122        Regex::new(r#"pub\s+const\s+WEBRTC_TAG\s*:\s*&str\s*=\s*"([^"]+)""#).expect("static regex");
123    let captures = re
124        .captures(&body)
125        .with_context(|| format!("could not find WEBRTC_TAG in {url}"))?;
126    Ok(captures[1].to_string())
127}
128
129fn host_webrtc_triple() -> Result<String> {
130    let os = match std::env::consts::OS {
131        "macos" => "mac",
132        "linux" => "linux",
133        "windows" => "win",
134        other => bail!("unsupported host OS: {other}"),
135    };
136    let arch = match std::env::consts::ARCH {
137        "aarch64" => "arm64",
138        "x86_64" => "x64",
139        other => bail!("unsupported host arch: {other}"),
140    };
141    Ok(format!("{os}-{arch}-release"))
142}
143
144fn download_and_extract(tag: &str, triple: &str, into: &Path) -> Result<()> {
145    let url = format!(
146        "https://github.com/zed-industries/livekit-rust-sdks/releases/download/{tag}/webrtc-{triple}.zip"
147    );
148    let zip_path = into.join(format!("webrtc-{triple}.zip"));
149
150    eprintln!("Downloading {url}");
151    let status = Command::new("curl")
152        .args(["-fL", "--retry", "3", "--progress-bar", "-o"])
153        .arg(&zip_path)
154        .arg(&url)
155        .status()
156        .context("running curl")?;
157    if !status.success() {
158        bail!("curl exited with {status} while downloading {url}");
159    }
160
161    eprintln!("Extracting into {}", into.display());
162    let status = Command::new("unzip")
163        .arg("-q")
164        .arg("-o")
165        .arg(&zip_path)
166        .arg("-d")
167        .arg(into)
168        .status()
169        .context("running unzip")?;
170    if !status.success() {
171        bail!(
172            "unzip exited with {status} while extracting {}",
173            zip_path.display()
174        );
175    }
176
177    fs::remove_file(&zip_path).ok();
178    Ok(())
179}
180
181fn curl_text(url: &str) -> Result<String> {
182    let output = Command::new("curl")
183        .args(["-fsSL", url])
184        .output()
185        .context("running curl")?;
186    if !output.status.success() {
187        bail!(
188            "curl failed for {url} (exit {}): {}",
189            output.status,
190            String::from_utf8_lossy(&output.stderr).trim(),
191        );
192    }
193    String::from_utf8(output.stdout).context("curl returned non-UTF-8 body")
194}
195
196fn ensure_gitignore_entry(workspace_root: &Path) -> Result<()> {
197    let path = workspace_root.join(".gitignore");
198    let existing =
199        fs::read_to_string(&path).with_context(|| format!("reading {}", path.display()))?;
200    if existing
201        .lines()
202        .any(|line| line.trim() == GITIGNORE_ENTRY || line.trim() == LOCAL_DIR_NAME)
203    {
204        return Ok(());
205    }
206    let mut updated = existing;
207    if !updated.ends_with('\n') {
208        updated.push('\n');
209    }
210    updated.push_str(GITIGNORE_ENTRY);
211    updated.push('\n');
212    fs::write(&path, updated).with_context(|| format!("writing {}", path.display()))?;
213    eprintln!("Added {GITIGNORE_ENTRY} to .gitignore");
214    Ok(())
215}
216
217fn update_cargo_config(webrtc_path: &Path) -> Result<()> {
218    let home = std::env::var_os("HOME")
219        .or_else(|| std::env::var_os("USERPROFILE"))
220        .context("could not determine home directory")?;
221    let config_path = PathBuf::from(home).join(".cargo").join("config.toml");
222
223    if let Some(parent) = config_path.parent() {
224        fs::create_dir_all(parent).with_context(|| format!("creating {}", parent.display()))?;
225    }
226
227    let existing_content = if config_path.exists() {
228        fs::read_to_string(&config_path)
229            .with_context(|| format!("reading {}", config_path.display()))?
230    } else {
231        String::new()
232    };
233
234    let mut doc = existing_content
235        .parse::<DocumentMut>()
236        .with_context(|| format!("parsing existing {}", config_path.display()))?;
237
238    let env_table = doc
239        .entry("env")
240        .or_insert(Item::Table(Table::new()))
241        .as_table_mut()
242        .context("`env` entry is not a table")?;
243
244    let cleaned_path = clean_webrtc_path(webrtc_path)?;
245    env_table.insert(ENV_VAR, value(cleaned_path.clone()));
246
247    fs::write(&config_path, doc.to_string())
248        .with_context(|| format!("writing {}", config_path.display()))?;
249
250    eprintln!(
251        "Updated {} with {ENV_VAR}={cleaned_path}",
252        config_path.display()
253    );
254    Ok(())
255}
256
257fn clean_webrtc_path(path: &Path) -> Result<String> {
258    let path_str = path.to_str().context("webrtc path is not valid UTF-8")?;
259    let mut cleaned = path_str.to_string();
260    if cleaned.starts_with(r"\\?\") {
261        cleaned = cleaned[4..].to_string();
262    }
263    cleaned = cleaned.replace('\\', "/");
264    Ok(cleaned)
265}
266
Served at tenant.openagents/omega Member data and write actions are omitted.