fix(sessions): tell the user when a delete is refused for a live turn
The browse picker swallowed SessionActiveWriteGuardError into a generic "Delete failed.", and the dashboard bulk delete only reported the deleted count, silently keeping rows a live turn owns. Surface both: the picker flashes that the session is active, and SessionsPage shows a toast with the skipped_active count (new en key; other locales fall back to English via defineLocale). Also move the api_server import into its sorted slot.
This commit is contained in:
@@ -156,9 +156,9 @@ from gateway.browser_control_broker import (
|
||||
browser_control_protocol_supported, filter_browser_control_capabilities, get_browser_control_broker)
|
||||
|
||||
from gateway.platforms._shared import coerce_port as _coerce_port
|
||||
from hermes_state_errors import SessionActiveWriteGuardError
|
||||
from gateway.platforms._shared import get_scoped_secret as _get_scoped_secret
|
||||
from gateway.platforms.tcp_site import start_tcp_site
|
||||
from hermes_state_errors import SessionActiveWriteGuardError
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -4,6 +4,7 @@ delete-with-confirmation; numbered-list fallback when curses is unavailable (Win
|
||||
from typing import Optional
|
||||
|
||||
from hermes_cli.timefmt import relative_time as _relative_time
|
||||
from hermes_state_errors import SessionActiveWriteGuardError
|
||||
|
||||
|
||||
def _session_status_tag(status: Optional[str]) -> str:
|
||||
@@ -152,7 +153,12 @@ class _CursesBrowser:
|
||||
target, self.confirm_delete = self.confirm_delete, None
|
||||
if key not in {ord("y"), ord("Y")}:
|
||||
return False
|
||||
if not self.delete_fn(target["id"]):
|
||||
try:
|
||||
ok = self.delete_fn(target["id"])
|
||||
except SessionActiveWriteGuardError:
|
||||
self.flash = "Session is active (a live turn owns it); try again when it finishes."
|
||||
return False
|
||||
if not ok:
|
||||
self.flash = "Delete failed."
|
||||
return False
|
||||
self.sessions[:] = [s for s in self.sessions if s["id"] != target["id"]]
|
||||
@@ -255,6 +261,8 @@ def _session_browse_picker(sessions: list, session_db=None) -> Optional[str]:
|
||||
sessions_dir = None
|
||||
try:
|
||||
return bool(session_db.delete_session(session_id, sessions_dir=sessions_dir, exclude_active_write_guards=True))
|
||||
except SessionActiveWriteGuardError:
|
||||
raise # the browser tells the user the session is busy instead of a generic failure
|
||||
except Exception:
|
||||
return False
|
||||
try: # curses first; any failure (no curses module, odd terminal) falls back
|
||||
|
||||
@@ -193,6 +193,8 @@ export const en: Translations = {
|
||||
deleteSelectedConfirmMessage:
|
||||
"This permanently removes {count} selected sessions and all their messages. This cannot be undone.",
|
||||
selectedSessionsDeleted: "{count} sessions deleted",
|
||||
selectedSessionsSkippedActive:
|
||||
"{count} sessions kept: a live turn is still running in them",
|
||||
failedToDeleteSelected: "Failed to delete selected sessions",
|
||||
resumeInChat: "Resume in Chat",
|
||||
newChat: "New chat",
|
||||
|
||||
@@ -207,6 +207,7 @@ export interface Translations {
|
||||
deleteSelectedConfirmTitle: string;
|
||||
deleteSelectedConfirmMessage: string;
|
||||
selectedSessionsDeleted: string;
|
||||
selectedSessionsSkippedActive: string;
|
||||
failedToDeleteSelected: string;
|
||||
resumeInChat: string;
|
||||
newChat: string;
|
||||
|
||||
@@ -1403,6 +1403,16 @@ export default function SessionsPage() {
|
||||
),
|
||||
"success",
|
||||
);
|
||||
if (resp.skipped_active?.length) {
|
||||
// Rows a live turn owns were refused server-side; say so instead of implying all went.
|
||||
showToast(
|
||||
t.sessions.selectedSessionsSkippedActive.replace(
|
||||
"{count}",
|
||||
String(resp.skipped_active.length),
|
||||
),
|
||||
"error",
|
||||
);
|
||||
}
|
||||
setDeleteSelectedOpen(false);
|
||||
// Drop deleted rows out of the visible list immediately rather
|
||||
// than waiting for the reload. The reload still runs so total /
|
||||
|
||||
Reference in New Issue
Block a user