supercode_harness/
hermes_import.rs1use std::path::{Path, PathBuf};
14use std::process::Command;
15
16use serde::Serialize;
17use supercode_interchange::{Session, SessionFormat};
18
19use crate::Result;
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
23pub struct HermesImported {
24 pub session_id: String,
26 pub home: PathBuf,
28 pub rollout: PathBuf,
30 pub via: &'static str,
32}
33
34pub fn hermes_home() -> PathBuf {
36 std::env::var_os("HERMES_HOME")
37 .map(PathBuf::from)
38 .unwrap_or_else(|| {
39 let home = std::env::var_os("HOME")
40 .map(PathBuf::from)
41 .unwrap_or_default();
42 home.join(".hermes")
43 })
44}
45
46pub fn import_into_hermes(session: &Session, home: Option<&Path>) -> Result<HermesImported> {
49 let home = home.map(Path::to_path_buf).unwrap_or_else(hermes_home);
50 let rollout_dir = home.join("imports").join("supercode");
51 std::fs::create_dir_all(&rollout_dir)?;
52 let stamp = std::time::SystemTime::now()
53 .duration_since(std::time::UNIX_EPOCH)
54 .map(|d| d.as_millis())
55 .unwrap_or(0);
56 let stem = session
57 .meta
58 .session_id
59 .clone()
60 .unwrap_or_else(|| "session".into());
61 let rollout = rollout_dir.join(format!("rollout-{stamp}-{stem}.jsonl"));
62 std::fs::write(&rollout, session.to_jsonl(SessionFormat::Codex)?)?;
63 let output = Command::new("hermes")
64 .args(["sessions", "import", "--from", "codex"])
65 .arg(&rollout)
66 .env("HERMES_HOME", &home)
67 .env("HERMES_NO_ONBOARDING", "1")
68 .env("HERMES_NONINTERACTIVE", "1")
69 .output()
70 .map_err(|e| {
71 crate::Error::Other(format!("`hermes sessions import` could not start: {e}"))
72 })?;
73 let stdout = String::from_utf8_lossy(&output.stdout);
74 let session_id = stdout
75 .lines()
76 .find_map(|line| line.split(" session as ").nth(1))
77 .map(|rest| rest.trim().to_string())
78 .filter(|s| !s.is_empty());
79 match (output.status.success(), session_id) {
80 (true, Some(session_id)) => Ok(HermesImported {
81 session_id,
82 home,
83 rollout,
84 via: "hermes sessions import --from codex",
85 }),
86 _ => Err(crate::Error::Other(format!(
87 "`hermes sessions import --from codex {}` did not report a session id (exit {}): {}{}",
88 rollout.display(),
89 output.status,
90 stdout.trim(),
91 String::from_utf8_lossy(&output.stderr).trim()
92 ))),
93 }
94}