use std::path::{Path, PathBuf};
use std::process::Command;
use serde::Serialize;
use supercode_interchange::{Session, SessionFormat};
use crate::Result;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct HermesImported {
pub session_id: String,
pub home: PathBuf,
pub rollout: PathBuf,
pub via: &'static str,
}
pub fn hermes_home() -> PathBuf {
std::env::var_os("HERMES_HOME")
.map(PathBuf::from)
.unwrap_or_else(|| {
let home = std::env::var_os("HOME")
.map(PathBuf::from)
.unwrap_or_default();
home.join(".hermes")
})
}
pub fn import_into_hermes(session: &Session, home: Option<&Path>) -> Result<HermesImported> {
let home = home.map(Path::to_path_buf).unwrap_or_else(hermes_home);
let rollout_dir = home.join("imports").join("supercode");
std::fs::create_dir_all(&rollout_dir)?;
let stamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_millis())
.unwrap_or(0);
let stem = session
.meta
.session_id
.clone()
.unwrap_or_else(|| "session".into());
let rollout = rollout_dir.join(format!("rollout-{stamp}-{stem}.jsonl"));
std::fs::write(&rollout, session.to_jsonl(SessionFormat::Codex)?)?;
let output = Command::new("hermes")
.args(["sessions", "import", "--from", "codex"])
.arg(&rollout)
.env("HERMES_HOME", &home)
.env("HERMES_NO_ONBOARDING", "1")
.env("HERMES_NONINTERACTIVE", "1")
.output()
.map_err(|e| {
crate::Error::Other(format!("`hermes sessions import` could not start: {e}"))
})?;
let stdout = String::from_utf8_lossy(&output.stdout);
let session_id = stdout
.lines()
.find_map(|line| line.split(" session as ").nth(1))
.map(|rest| rest.trim().to_string())
.filter(|s| !s.is_empty());
match (output.status.success(), session_id) {
(true, Some(session_id)) => Ok(HermesImported {
session_id,
home,
rollout,
via: "hermes sessions import --from codex",
}),
_ => Err(crate::Error::Other(format!(
"`hermes sessions import --from codex {}` did not report a session id (exit {}): {}{}",
rollout.display(),
output.status,
stdout.trim(),
String::from_utf8_lossy(&output.stderr).trim()
))),
}
}