diff options
Diffstat (limited to 'crates/dinggerd/src/restore.rs')
| -rw-r--r-- | crates/dinggerd/src/restore.rs | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/crates/dinggerd/src/restore.rs b/crates/dinggerd/src/restore.rs index 1dca955..23d166e 100644 --- a/crates/dinggerd/src/restore.rs +++ b/crates/dinggerd/src/restore.rs @@ -10,8 +10,9 @@ //! pane. Everything is addressed by tmux id, so names with `.` or `:` work. //! //! Then, once each new shell shows its prompt: agents with a session -//! reference are resumed (`pi --session <file>`, run), and every other -//! saved command line is typed but not run, for the user to press Enter. +//! reference are resumed (`pi --session <file>`, `claude --resume <id>`, +//! run), and every other saved command line is typed but not run, for the +//! user to press Enter. use std::time::{Duration, Instant}; @@ -48,10 +49,20 @@ pub enum Typed { Retype(String), } -/// The command that resumes an agent's session. +/// The command that resumes an agent's session, from its session file. +/// `None` when the file does not exist: a session that never got a message +/// has nothing to resume (`claude --resume` would fail), so its command +/// line is retyped instead, like any other. fn resume_command(agent: &str, session: &str) -> Option<String> { + let file = std::path::Path::new(session); + if !file.is_file() { + return None; + } match agent { "pi" => Some(format!("pi --session {}", shell_quote(session))), + // By id, the transcript's name. It must run in the directory the + // session ran in (the pane's), or Claude moves the conversation. + "claude" => file.file_stem()?.to_str().map(|id| format!("claude --resume {}", shell_quote(id))), _ => None, } } @@ -657,18 +668,27 @@ mod tests { assert_eq!(typed_for(&pane), Some(Typed::Retype("nvim 'my file.sh'".into()))); pane.command = Some("echo one\necho two".into()); assert_eq!(typed_for(&pane), None, "a newline would run it"); - pane.agent = Some(AgentSnap { - agent: "pi".into(), - name: "x".into(), - state: "idle".into(), - session: Some("/s/a b.jsonl".into()), - }); - assert_eq!(typed_for(&pane), Some(Typed::Resume("pi --session '/s/a b.jsonl'".into()))); - if let Some(agent) = pane.agent.as_mut() { - agent.session = None; - } + let dir = std::env::temp_dir().join(format!("dingger-typed-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let file = |name: &str| dir.join(name).to_string_lossy().into_owned(); + std::fs::write(file("a b.jsonl"), "").unwrap(); + std::fs::write(file("4f1c-9e.jsonl"), "").unwrap(); + let agent = |agent: &str, session: Option<String>| { + Some(AgentSnap { agent: agent.into(), name: "x".into(), state: "idle".into(), session }) + }; pane.command = Some("pi --model x".into()); + pane.agent = agent("pi", Some(file("a b.jsonl"))); + assert_eq!(typed_for(&pane), Some(Typed::Resume(format!("pi --session '{}'", file("a b.jsonl"))))); + pane.agent = agent("pi", None); assert_eq!(typed_for(&pane), Some(Typed::Retype("pi --model x".into())), "no session: retyped"); + pane.agent = agent("pi", Some(file("never-written.jsonl"))); + assert_eq!(typed_for(&pane), Some(Typed::Retype("pi --model x".into())), "no session file: retyped"); + pane.command = Some("claude --model opus".into()); + pane.agent = agent("claude", Some(file("4f1c-9e.jsonl"))); + assert_eq!(typed_for(&pane), Some(Typed::Resume("claude --resume 4f1c-9e".into())), "by id"); + pane.agent = agent("claude", Some(file("no-messages.jsonl"))); + assert_eq!(typed_for(&pane), Some(Typed::Retype("claude --model opus".into())), "no transcript: retyped"); + std::fs::remove_dir_all(&dir).unwrap(); } #[test] |
