agent_profile/launch/mod.rs
1// Copyright (c) 2026 Costas Kirgoussios
2//
3// This software is licensed under the PolyForm Noncommercial License 1.0.0.
4// You may obtain a copy of the License at:
5// https://polyformproject.org/licenses/noncommercial/1.0.0/
6
7//! `LaunchPlan` (spec §4), environment overrides (spec §22), launch semantics (spec §23, §24)
8//! and the launcher API (spec §25).
9
10use std::ffi::OsString;
11use std::path::PathBuf;
12use std::process::Command;
13
14use crate::error::Result;
15
16#[cfg(unix)]
17mod unix;
18#[cfg(windows)]
19mod windows;
20
21/// What an adapter asks the launcher to run (spec §4). `env` is an override set, not a full environment.
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct LaunchPlan {
24 pub executable: PathBuf,
25 pub args: Vec<OsString>,
26 pub env: Vec<(OsString, OsString)>,
27 pub cwd: Option<PathBuf>,
28}
29
30impl LaunchPlan {
31 /// The single conversion both launchers use: the inherited environment plus the overrides, the
32 /// arguments verbatim, the working directory only when set, and inherited stdio.
33 pub fn command(&self) -> Command {
34 let mut command = Command::new(&self.executable);
35 command.args(&self.args);
36 for (key, value) in &self.env {
37 command.env(key, value);
38 }
39 if let Some(cwd) = &self.cwd {
40 command.current_dir(cwd);
41 }
42 command
43 }
44}
45
46/// How a launch ended (spec §25).
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum LaunchOutcome {
49 /// Unix: `exec` never returns on success, so this is never constructed there. Kept for spec §25.
50 ReplacedProcess,
51 /// Windows: the child's full 32-bit exit code.
52 Exited(i32),
53}
54
55/// Launches the plan: `exec` on Unix, a waited child on Windows. `verbose` enables diagnostics on stderr.
56pub fn launch(plan: &LaunchPlan, verbose: bool) -> Result<LaunchOutcome> {
57 #[cfg(unix)]
58 {
59 let _ = verbose;
60 unix::launch(plan)
61 }
62 #[cfg(windows)]
63 {
64 windows::launch(plan, verbose)
65 }
66}