use std::time::Duration;
use netsky_core::agent::AgentId;
use netsky_core::consts::RESTART_AGENT0_TOS_WAIT_S;
use netsky_core::runtime::CodexConfig;
use netsky_core::runtime::Runtime;
use netsky_core::spawn::{self, SpawnOptions, SpawnOutcome};
pub fn run(n: u32, fresh: bool) -> netsky_core::Result<()> {
spawn_resident(n, fresh, RuntimeKind::Claude)
}
pub fn run_codex_resident(n: u32, fresh: bool) -> netsky_core::Result<()> {
spawn_resident(n, fresh, RuntimeKind::Codex)
}
#[derive(Clone, Copy)]
enum RuntimeKind {
Claude,
Codex,
}
fn spawn_resident(n: u32, fresh: bool, kind: RuntimeKind) -> netsky_core::Result<()> {
let agent = AgentId::from_number(n);
let cwd = netsky_core::paths::netsky_root_or_cwd()?;
let runtime = match kind {
RuntimeKind::Claude => Runtime::defaults_for(agent),
RuntimeKind::Codex => Runtime::Codex(CodexConfig::defaults_for()),
};
let opts = SpawnOptions {
runtime,
cwd: cwd.clone(),
};
if fresh && spawn::is_up(agent) {
spawn::kill(agent)?;
println!("[agent] killed existing session '{agent}' for fresh spawn");
}
match spawn::spawn(agent, &opts)? {
SpawnOutcome::AlreadyUp => {
println!("[agent] session '{agent}' already up; skipping spawn");
}
SpawnOutcome::Spawned => {
let tag = if fresh { "fresh" } else { "spawned" };
println!("[agent] {tag} '{agent}' ({})", opts.runtime.describe());
if matches!(kind, RuntimeKind::Claude)
&& spawn::dismiss_tos(
&agent.name(),
Duration::from_secs(RESTART_AGENT0_TOS_WAIT_S),
)
{
println!("[agent] {agent}: TOS dismissed");
}
}
}
Ok(())
}