Skip to main content

mur_common/
local_llm.rs

1//! Location and accessors for the bundled local-model base URL.
2//!
3//! Hub starts an MLX inference server on an ephemeral port and writes its
4//! OpenAI-compatible base URL here. Agents — started by launchd and therefore
5//! NOT inheriting Hub's environment — read it back from this file.
6
7use std::path::{Path, PathBuf};
8
9/// Path to the file holding the local model base URL, under `<mur_home>`.
10pub fn base_url_path(mur_home: &Path) -> PathBuf {
11    mur_home.join("runtime").join("local_llm.url")
12}
13
14/// Atomically write the base URL (temp file + rename).
15pub fn write_base_url(mur_home: &Path, url: &str) -> std::io::Result<()> {
16    let path = base_url_path(mur_home);
17    if let Some(parent) = path.parent() {
18        std::fs::create_dir_all(parent)?;
19    }
20    let tmp = path.with_extension("url.tmp");
21    std::fs::write(&tmp, url.as_bytes())?;
22    std::fs::rename(&tmp, &path)
23}
24
25/// Read the base URL, trimming whitespace. `None` if absent/empty.
26pub fn read_base_url(mur_home: &Path) -> Option<String> {
27    let s = std::fs::read_to_string(base_url_path(mur_home)).ok()?;
28    let t = s.trim();
29    if t.is_empty() {
30        None
31    } else {
32        Some(t.to_string())
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use tempfile::TempDir;
40
41    #[test]
42    fn write_then_read_roundtrips() {
43        let tmp = TempDir::new().unwrap();
44        assert_eq!(read_base_url(tmp.path()), None);
45        write_base_url(tmp.path(), "http://127.0.0.1:50321/v1").unwrap();
46        assert_eq!(
47            read_base_url(tmp.path()),
48            Some("http://127.0.0.1:50321/v1".to_string())
49        );
50    }
51
52    #[test]
53    fn blank_file_reads_as_none() {
54        let tmp = TempDir::new().unwrap();
55        write_base_url(tmp.path(), "   \n").unwrap();
56        assert_eq!(read_base_url(tmp.path()), None);
57    }
58}