use serde::Deserialize;
use super::DaemonClient;
impl DaemonClient {
pub async fn launch_session(&self, workdir: &str) -> anyhow::Result<String> {
let fw = crate::core::paths::FrameworkPaths::default();
if let Err(err) =
crate::core::session_launch::prepare_session(&fw, std::path::Path::new(workdir))
{
tracing::warn!(%err, "session pre-launch preparation failed");
}
#[derive(Deserialize)]
struct Body {
#[serde(default)]
name: String,
}
let url = format!("{}/sessions", self.base);
let body: Body = self
.http
.post(&url)
.json(&serde_json::json!({
"project": workdir,
"project_path": workdir,
}))
.send()
.await?
.error_for_status()?
.json()
.await?;
let prompt =
crate::core::session_launch::build_system_prompt_for(std::path::Path::new(workdir));
let claude_cmd = {
let path = std::env::temp_dir().join(format!(
"trusty-mpm-system-prompt-{}.txt",
uuid::Uuid::new_v4()
));
match std::fs::write(&path, &prompt) {
Ok(()) => format!("claude --append-system-prompt-file {}", path.display()),
Err(err) => {
tracing::warn!(%err, "failed to write system prompt file; launching bare claude");
"claude".to_string()
}
}
};
let new_session = std::process::Command::new("tmux")
.args(["new-session", "-d", "-s", &body.name, "-c", workdir])
.status();
match new_session {
Ok(status) if status.success() => {
let send = std::process::Command::new("tmux")
.args(["send-keys", "-t", &body.name, &claude_cmd, "Enter"])
.status();
if !matches!(send, Ok(s) if s.success()) {
return Err(anyhow::anyhow!(
"tmux session {} created but failed to start claude",
body.name
));
}
}
Ok(_) | Err(_) => {
return Err(anyhow::anyhow!(
"failed to create tmux session {} in {}",
body.name,
workdir
));
}
}
Ok(body.name)
}
pub async fn connect_session(&self, workdir: &str) -> anyhow::Result<String> {
#[derive(Deserialize)]
struct Body {
#[serde(default)]
name: String,
}
let url = format!("{}/api/v1/sessions/connect", self.base);
let body: Body = self
.http
.post(&url)
.json(&serde_json::json!({
"project": workdir,
"project_path": workdir,
}))
.send()
.await?
.error_for_status()?
.json()
.await?;
let prompt =
crate::core::session_launch::build_system_prompt_for(std::path::Path::new(workdir));
let claude_cmd = {
let path = std::env::temp_dir().join(format!(
"trusty-mpm-system-prompt-{}.txt",
uuid::Uuid::new_v4()
));
match std::fs::write(&path, &prompt) {
Ok(()) => format!("claude --append-system-prompt-file {}", path.display()),
Err(err) => {
tracing::warn!(%err, "failed to write system prompt file; launching bare claude");
"claude".to_string()
}
}
};
let already_running = std::process::Command::new("tmux")
.args(["has-session", "-t", &body.name])
.status()
.map(|s| s.success())
.unwrap_or(false);
let new_session = std::process::Command::new("tmux")
.args(["new-session", "-A", "-d", "-s", &body.name, "-c", workdir])
.status();
match new_session {
Ok(status) if status.success() => {
if !already_running {
let send = std::process::Command::new("tmux")
.args(["send-keys", "-t", &body.name, &claude_cmd, "Enter"])
.status();
if !matches!(send, Ok(s) if s.success()) {
return Err(anyhow::anyhow!(
"tmux session {} created but failed to start claude",
body.name
));
}
}
}
Ok(_) | Err(_) => {
return Err(anyhow::anyhow!(
"failed to create tmux session {} in {}",
body.name,
workdir
));
}
}
Ok(body.name)
}
}