Compare commits

...

1 Commits

Author SHA1 Message Date
pr-merge-worker 7ede76d811 fix(tui): correct preset cycling keybinding to ctrl+tab and add persona tab-cycling 2026-05-09 20:41:37 +00:00
3 changed files with 39 additions and 2 deletions
+6 -1
View File
@@ -93,7 +93,8 @@ if _TEXTUAL_AVAILABLE:
BINDINGS: ClassVar[list[tuple[str, str, str]]] = [
("ctrl+q", "quit", "Quit"),
("f1", "help", "Help"),
("ctrl+t", "cycle_preset", "Cycle Preset"),
("ctrl+tab", "cycle_preset", "Cycle Preset"),
("shift+tab", "cycle_persona", "Cycle Persona"),
]
def __init__(
@@ -153,6 +154,10 @@ if _TEXTUAL_AVAILABLE:
self._persona_state.cycle_preset(self._session.session_id)
self._refresh_persona_bar()
def action_cycle_persona(self) -> None:
self._persona_state.cycle_persona(self._session.session_id)
self._refresh_persona_bar()
def _refresh_persona_bar(self) -> None:
persona = self._persona_state.active_persona(self._session.session_id)
preset = self._persona_state.current_preset(self._session.session_id)
+31
View File
@@ -63,6 +63,37 @@ class PersonaState:
self.preset_by_session[session_id] = next_name
return next_name
def cycle_persona(self, session_id: str) -> str:
"""Cycle to the next available persona.
Returns the name of the newly active persona. Only personas with
``cycle_order > 0`` are included in the cycling list, sorted by
ascending cycle_order.
"""
personas = [p for p in self.registry.list_personas() if p.cycle_order > 0]
if not personas:
default = self.registry.ensure_default()
self.active_by_session[session_id] = default.name
return default.name
# Sort by cycle_order ascending, then fall back to name for stable ordering
ordered = sorted(personas, key=lambda p: (p.cycle_order, p.name))
names = [p.name for p in ordered]
current = self.active_name(session_id)
if current not in names:
self.active_by_session[session_id] = names[0]
self.registry.set_last_persona(names[0])
self.preset_by_session[session_id] = "default"
return names[0]
idx = names.index(current)
next_name = names[(idx + 1) % len(names)]
self.active_by_session[session_id] = next_name
self.registry.set_last_persona(next_name)
self.preset_by_session[session_id] = "default"
return next_name
def effective_arguments(self, session_id: str) -> dict[str, object]:
persona = self.active_persona(session_id)
preset = self.current_preset(session_id)
@@ -32,7 +32,8 @@ _GLOBAL_ITEMS = (
_CONTEXT_ITEMS: dict[str, tuple[tuple[str, str], ...]] = {
"Main Screen": (
("enter", "Submit prompt"),
("ctrl+t", "Cycle to next argument preset"),
("ctrl+tab", "Cycle to next argument preset"),
("shift+tab", "Cycle personas in registry"),
("@", "Open Reference Picker overlay"),
("/", "Open Slash Command overlay"),
("! / $", "Activate shell mode"),