Răsfoiți Sursa

merge: clawcode-issue-9410-cli-ux-progress-status-clear into main

Jobdori 2 luni în urmă
părinte
comite
06a93a57c7

+ 32 - 2
rust/crates/rusty-claude-cli/src/main.rs

@@ -1338,12 +1338,17 @@ fn run_resume_command(
                     ),
                 });
             }
+            let backup_path = write_session_clear_backup(session, session_path)?;
+            let previous_session_id = session.session_id.clone();
             let cleared = Session::new();
+            let new_session_id = cleared.session_id.clone();
             cleared.save_to_path(session_path)?;
             Ok(ResumeCommandOutcome {
                 session: cleared,
                 message: Some(format!(
-                    "Cleared resumed session file {}.",
+                    "Session cleared\n  Mode             resumed session reset\n  Previous session {previous_session_id}\n  Backup           {}\n  Resume previous  claw --resume {}\n  New session      {new_session_id}\n  Session file     {}",
+                    backup_path.display(),
+                    backup_path.display(),
                     session_path.display()
                 )),
             })
@@ -2111,6 +2116,7 @@ impl LiveCli {
             return Ok(false);
         }
 
+        let previous_session = self.session.clone();
         let session_state = Session::new();
         self.session = create_managed_session_handle(&session_state.session_id)?;
         let runtime = build_runtime(
@@ -2126,10 +2132,13 @@ impl LiveCli {
         )?;
         self.replace_runtime(runtime)?;
         println!(
-            "Session cleared\n  Mode             fresh session\n  Preserved model  {}\n  Permission mode  {}\n  Session          {}",
+            "Session cleared\n  Mode             fresh session\n  Previous session {}\n  Resume previous  /resume {}\n  Preserved model  {}\n  Permission mode  {}\n  New session      {}\n  Session file     {}",
+            previous_session.id,
+            previous_session.id,
             self.model,
             self.permission_mode.as_str(),
             self.session.id,
+            self.session.path.display(),
         );
         Ok(true)
     }
@@ -2665,6 +2674,27 @@ fn format_session_modified_age(modified_epoch_millis: u128) -> String {
     }
 }
 
+fn write_session_clear_backup(
+    session: &Session,
+    session_path: &Path,
+) -> Result<PathBuf, Box<dyn std::error::Error>> {
+    let backup_path = session_clear_backup_path(session_path);
+    session.save_to_path(&backup_path)?;
+    Ok(backup_path)
+}
+
+fn session_clear_backup_path(session_path: &Path) -> PathBuf {
+    let timestamp = std::time::SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .ok()
+        .map_or(0, |duration| duration.as_millis());
+    let file_name = session_path
+        .file_name()
+        .and_then(|value| value.to_str())
+        .unwrap_or("session.jsonl");
+    session_path.with_file_name(format!("{file_name}.before-clear-{timestamp}.bak"))
+}
+
 fn render_repl_help() -> String {
     [
         "REPL".to_string(),

+ 19 - 1
rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs

@@ -5,6 +5,7 @@ use std::process::{Command, Output};
 use std::sync::atomic::{AtomicU64, Ordering};
 use std::time::{SystemTime, UNIX_EPOCH};
 
+use runtime::ContentBlock;
 use runtime::Session;
 
 static TEMP_COUNTER: AtomicU64 = AtomicU64::new(0);
@@ -51,7 +52,12 @@ fn resumed_binary_accepts_slash_commands_with_arguments() {
     assert!(stdout.contains("Export"));
     assert!(stdout.contains("wrote transcript"));
     assert!(stdout.contains(export_path.to_str().expect("utf8 path")));
-    assert!(stdout.contains("Cleared resumed session file"));
+    assert!(stdout.contains("Session cleared"));
+    assert!(stdout.contains("Mode             resumed session reset"));
+    assert!(stdout.contains("Previous session"));
+    assert!(stdout.contains("Resume previous  claw --resume"));
+    assert!(stdout.contains("Backup           "));
+    assert!(stdout.contains("Session file     "));
 
     let export = fs::read_to_string(&export_path).expect("export file should exist");
     assert!(export.contains("# Conversation Export"));
@@ -59,6 +65,18 @@ fn resumed_binary_accepts_slash_commands_with_arguments() {
 
     let restored = Session::load_from_path(&session_path).expect("cleared session should load");
     assert!(restored.messages.is_empty());
+
+    let backup_path = stdout
+        .lines()
+        .find_map(|line| line.strip_prefix("  Backup           "))
+        .map(PathBuf::from)
+        .expect("clear output should include backup path");
+    let backup = Session::load_from_path(&backup_path).expect("backup session should load");
+    assert_eq!(backup.messages.len(), 1);
+    assert!(matches!(
+        backup.messages[0].blocks.first(),
+        Some(ContentBlock::Text { text }) if text == "ship the slash command harness"
+    ));
 }
 
 #[test]