lwc 0.17.11

Agent-driven proactive memory CLI for AI agents — autonomously recall, maintain, and evolve persistent, source-grounded knowledge across sessions.
#![cfg(windows)]

use serde_json::Value;
use std::process::{Command, Output};
use std::{
    fs,
    path::{Path, PathBuf},
    thread,
    time::{Duration, Instant},
};
use tempfile::TempDir;

struct TransWorld {
    _temp: TempDir,
    project: PathBuf,
    home: PathBuf,
    bin: PathBuf,
}

impl TransWorld {
    fn new() -> Self {
        let temp = tempfile::tempdir().unwrap();
        let project = temp.path().join("project");
        let home = temp.path().join("home");
        let bin = temp.path().join("bin");
        fs::create_dir_all(&project).unwrap();
        fs::create_dir_all(&home).unwrap();
        fs::create_dir_all(&bin).unwrap();
        Self {
            _temp: temp,
            project,
            home,
            bin,
        }
    }

    fn init(&self) {
        let output = self.command(&["init"]);
        assert!(
            output.status.success(),
            "init failed\nstdout: {}\nstderr: {}",
            String::from_utf8_lossy(&output.stdout),
            String::from_utf8_lossy(&output.stderr)
        );
    }

    fn command(&self, args: &[&str]) -> Output {
        let system32 = PathBuf::from(std::env::var_os("SystemRoot").unwrap()).join("System32");
        let path = std::env::join_paths([&self.bin, &system32]).unwrap();
        Command::new(env!("CARGO_BIN_EXE_lwc"))
            .current_dir(&self.project)
            .env("HOME", &self.home)
            .env("PATH", path)
            .args(args)
            .output()
            .unwrap()
    }

    fn ok(&self, args: &[&str]) -> Value {
        let output = self.command(args);
        assert!(
            output.status.success(),
            "command {args:?} failed\nstdout: {}\nstderr: {}",
            String::from_utf8_lossy(&output.stdout),
            String::from_utf8_lossy(&output.stderr)
        );
        serde_json::from_slice(&output.stdout).unwrap()
    }

    fn err(&self, args: &[&str]) -> Value {
        let output = self.command(args);
        assert!(
            !output.status.success(),
            "command {args:?} unexpectedly succeeded\nstdout: {}",
            String::from_utf8_lossy(&output.stdout)
        );
        serde_json::from_slice(&output.stderr).unwrap()
    }

    fn write_project(&self, relative: &str, content: &str) -> PathBuf {
        self.write_path(&self.project.join(relative), content.as_bytes())
    }

    fn write_path(&self, path: &Path, content: &[u8]) -> PathBuf {
        if let Some(parent) = path.parent() {
            fs::create_dir_all(parent).unwrap();
        }
        fs::write(path, content).unwrap();
        path.to_path_buf()
    }

    fn install_cmd_script(&self, name: &str, body: &str) -> PathBuf {
        let path = self.bin.join(format!("{name}.cmd"));
        fs::write(&path, body).unwrap();
        path
    }
}

fn as_str(path: &Path) -> &str {
    path.to_str().unwrap()
}

#[test]
fn trans_kills_windows_descendants_on_timeout() {
    let world = TransWorld::new();
    world.init();
    let marker = world.bin.join("markitdown.desc.survived");
    world.install_cmd_script(
        "markitdown",
        &format!(
            "@echo off\r\n\
setlocal\r\n\
start \"\" /B cmd /c \"ping -n 4 127.0.0.1 >nul && echo survived>\\\"{}\\\"\"\r\n\
ping -n 9 127.0.0.1 >nul\r\n",
            marker.display()
        ),
    );
    world.ok(&[
        "config",
        "set",
        "--trans",
        "markitdown",
        "--trans-timeout",
        "1",
    ]);
    let input = world.write_project("docs/source.pdf", "stub");
    let output = world.project.join("out/descendant.md");

    let started = Instant::now();
    let error = world.err(&["trans", as_str(&input), "--output", as_str(&output)]);
    assert_eq!(error["error"]["code"], "trans_timeout");
    assert!(started.elapsed() < Duration::from_secs(5));
    assert!(!output.exists());
    thread::sleep(Duration::from_secs(4));
    assert!(
        !marker.exists(),
        "descendant should not survive to write its marker"
    );
}