Say which kind of delete this is, and stop offering what is already open
**Deleting was one word for two different acts.** An imported session's real transcript belongs to Claude Code and outlives anything this app does, so removing it here undoes a view. A session started here has no copy anywhere, and removing it ends the conversation. The dialog warned "this can't be undone" of both, which makes the warning worthless on the one where it is true -- and frightening on the one where it is not, since what it actually deletes is a cache of a conversation still sitting on the machine. Sessions now report whether they were imported, and the dialog says which act this is. No new mechanism: the soft delete already existed, it was just indistinguishable from the hard one. **And a session already open here is no longer offered for import.** Importing one twice would leave two `--resume` processes appending to the same transcript, each seeing the other's writes as work done elsewhere and replaying them -- both sessions then showing a conversation neither is having. The route refuses it as well, so the rule holds for anything not going through the app. Left out of the list rather than shown and disabled. The usual argument says absence is ambiguous, and it is wrong here: an imported session has not disappeared, it has moved to the session list, which is where it now belongs. Absence means "already somewhere you can reach it". Deleting the app's copy puts it straight back -- verified: 68 offered, 67 after importing one, 68 again after the soft delete, which is also the clearest demonstration that a soft delete keeps the conversation.
This commit is contained in:
1 parent
d2915c12fa
commit
3f8805a610
4 files changed
+78
-5
No files matched your search
+17
-1
@@ -397,9 +397,18 @@ async fn list_importable(
|
||||
) -> Result<axum::Json<Vec<crate::session::import::Importable>>, ApiError> {
|
||||
let setup = setup_by_id(&manager, &id)?;
|
||||
let transport = crate::session::transport::Transport::for_setup(&setup);
|
||||
let found = crate::session::import::list(&transport)
|
||||
let mut found = crate::session::import::list(&transport)
|
||||
.await
|
||||
.map_err(bad_request)?;
|
||||
// Anything this app is already continuing is not offered again. Left
|
||||
// out rather than shown-and-disabled, because it has not disappeared:
|
||||
// it is in the session list, which is where it now belongs. Absence
|
||||
// here means "already somewhere you can reach it", not "gone".
|
||||
//
|
||||
// Joined here because the importer knows about files and the manager
|
||||
// knows about sessions, and putting the two together is the route's
|
||||
// job rather than either one's.
|
||||
found.retain(|candidate| manager.session_importing(&candidate.id).is_none());
|
||||
Ok(axum::Json(found))
|
||||
}
|
||||
|
||||
@@ -445,6 +454,13 @@ async fn spawn_session(
|
||||
body.setup
|
||||
))
|
||||
})?;
|
||||
if let Some(existing) = manager.session_importing(want) {
|
||||
return Err(ApiError::BadRequest(format!(
|
||||
"session {existing} is already continuing that one -- delete it first if you \
|
||||
want a fresh copy. Deleting it here does not touch the conversation itself, \
|
||||
only this app's view of it."
|
||||
)));
|
||||
}
|
||||
let events = crate::session::import::replay(&transport, &chosen.path)
|
||||
.await
|
||||
.map_err(bad_request)?;
|
||||
|
||||
Reference in new issue
Block a user