Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion agent/title_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def auto_title_session(
assistant_response: str,
failure_callback: Optional[FailureCallback] = None,
main_runtime: dict = None,
on_title=None,
) -> None:
"""Generate and set a session title if one doesn't already exist.

Expand Down Expand Up @@ -119,6 +120,11 @@ def auto_title_session(
try:
session_db.set_session_title(session_id, title)
logger.debug("Auto-generated session title: %s", title)
if on_title:
try:
on_title(title)
except Exception:
pass
except Exception as e:
logger.debug("Failed to set auto-generated title: %s", e)

Expand All @@ -131,6 +137,7 @@ def maybe_auto_title(
conversation_history: list,
failure_callback: Optional[FailureCallback] = None,
main_runtime: dict = None,
on_title=None,
) -> None:
"""Fire-and-forget title generation after the first exchange.

Expand All @@ -152,7 +159,7 @@ def maybe_auto_title(
thread = threading.Thread(
target=auto_title_session,
args=(session_db, session_id, user_message, assistant_response),
kwargs={"failure_callback": failure_callback, "main_runtime": main_runtime},
kwargs={"failure_callback": failure_callback, "main_runtime": main_runtime, "on_title": on_title},
daemon=True,
name="auto-title",
)
Expand Down
18 changes: 18 additions & 0 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3498,6 +3498,7 @@ def _init_agent(self, *, model_override: str = None, runtime_override: dict = No
try:
self._session_db.set_session_title(self.session_id, self._pending_title)
_cprint(f" Session title applied: {self._pending_title}")
self._set_terminal_title(self._pending_title)
self._pending_title = None
except (ValueError, Exception) as e:
_cprint(f" Could not apply pending title: {e}")
Expand Down Expand Up @@ -4119,6 +4120,11 @@ def _write_osc52_clipboard(self, text: str) -> None:
sys.stdout.write(seq)
sys.stdout.flush()

def _set_terminal_title(self, title: str) -> None:
"""Set the terminal tab/window title via OSC 0 escape sequence."""
sys.stdout.write(f"\x1b]0;Hermes: {title}\x07")
sys.stdout.flush()

def _handle_copy_command(self, cmd_original: str) -> None:
"""Handle /copy [number] — copy assistant output to clipboard."""
parts = cmd_original.split(maxsplit=1)
Expand Down Expand Up @@ -4899,6 +4905,8 @@ def _handle_resume_command(self, cmd_original: str) -> None:
self.agent._invalidate_system_prompt()

title_part = f" \"{session_meta['title']}\"" if session_meta.get("title") else ""
if session_meta.get("title"):
self._set_terminal_title(session_meta["title"])
msg_count = len([m for m in self.conversation_history if m.get("role") == "user"])
if self.conversation_history:
_cprint(
Expand Down Expand Up @@ -6137,6 +6145,7 @@ def process_command(self, command: str) -> bool:
try:
if self._session_db.set_session_title(self.session_id, new_title):
_cprint(f" Session title set: {new_title}")
self._set_terminal_title(new_title)
else:
_cprint(" Session not found in database.")
except ValueError as e:
Expand Down Expand Up @@ -8844,6 +8853,7 @@ def run_agent():
"api_key": self.api_key,
"api_mode": self.api_mode,
},
on_title=self._set_terminal_title,
)
except Exception:
pass
Expand Down Expand Up @@ -9256,6 +9266,14 @@ def run(self):
if self._resumed:
if self._preload_resumed_session():
self._display_resumed_history()
# Set terminal title from loaded session if it has one
if self._session_db:
try:
t = self._session_db.get_session_title(self.session_id)
if t:
self._set_terminal_title(t)
except Exception:
pass

try:
from hermes_cli.skin_engine import get_active_skin
Expand Down