From 1c7a783c42ee20bbe0b563227141cc5336ab871f Mon Sep 17 00:00:00 2001 From: Claw Assistant Date: Mon, 25 May 2026 00:44:17 -0700 Subject: [PATCH] fix(cli,gateway): strip outer brackets/quotes from /resume args + accept session IDs in gateway The /resume usage hint shows '' which a few users have typed verbatim, including the angle brackets. Strip outer <>, [], "", and '' from the argument before lookup so '/resume ' works the same as '/resume abc123'. Mirrors the new bracket-stripping in the CLI handler. Also let the gateway resolve a bare session ID. Previously the gateway only called resolve_session_by_title, so '/resume ' always returned 'Session not found' even for valid IDs. Try get_session() first, fall back to title resolution second. Surgical reapply of PR #10215 (branch was based on a many-months-old main and reverted ~3100 unrelated files; original commit by claw@openclaw.ai preserved via --author). --- cli.py | 13 +++++++++++++ gateway/run.py | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cli.py b/cli.py index 63f7e31096f..759c09b4619 100644 --- a/cli.py +++ b/cli.py @@ -6527,6 +6527,19 @@ class HermesCLI: parts = cmd_original.split(None, 1) target = parts[1].strip() if len(parts) > 1 else "" + # Strip common outer brackets/quotes users may type literally from the + # usage hint (e.g. ``/resume `` or ``/resume [abc123]``). The + # `/resume` help text shows angle brackets as a placeholder and a few + # users copy them through verbatim. Stripping them keeps the lookup + # working without changing the help string. + if len(target) >= 2 and ( + (target[0] == "<" and target[-1] == ">") + or (target[0] == "[" and target[-1] == "]") + or (target[0] == '"' and target[-1] == '"') + or (target[0] == "'" and target[-1] == "'") + ): + target = target[1:-1].strip() + if not target: _cprint(" Usage: /resume ") if self._show_recent_sessions(reason="resume"): diff --git a/gateway/run.py b/gateway/run.py index 367adbe61db..cb8b60e556d 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -12743,6 +12743,16 @@ class GatewayRunner: session_key = self._session_key_for_source(source) name = event.get_command_args().strip() + # Strip common outer brackets/quotes users may type literally from the + # usage hint (e.g. ``/resume ``). Mirrors the CLI behavior. + if len(name) >= 2 and ( + (name[0] == "<" and name[-1] == ">") + or (name[0] == "[" and name[-1] == "]") + or (name[0] == '"' and name[-1] == '"') + or (name[0] == "'" and name[-1] == "'") + ): + name = name[1:-1].strip() + def _list_titled_sessions() -> list[dict]: user_source = source.platform.value if source.platform else None sessions = self._session_db.list_sessions_rich(source=user_source, limit=10) @@ -12780,7 +12790,13 @@ class GatewayRunner: target_id = target.get("id") name = target.get("title") or name else: - target_id = self._session_db.resolve_session_by_title(name) + # Try direct session ID lookup first (so `/resume ` + # works in the gateway, not just `/resume `). + session = self._session_db.get_session(name) + if session: + target_id = session["id"] + else: + target_id = self._session_db.resolve_session_by_title(name) if not target_id: return t("gateway.resume.not_found", name=name) # Compression creates child continuations that hold the live transcript.