feat: show scheduled prompts in session rows

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 09:04:26 -04:00
parent 7ebc3bf560
commit dfea5a5630
2 changed files with 64 additions and 1 deletions
+19 -1
View File
@@ -1,3 +1,6 @@
from datetime import datetime
from math import ceil
from rich.markup import escape
from textual.app import ComposeResult
from textual.message import Message
@@ -28,12 +31,23 @@ _STATUS_COLORS: dict[str, str] = {
}
def format_scheduled_prompt(due_at: datetime, now: datetime | None = None) -> str:
if now is None:
now = datetime.now()
seconds = max(0, (due_at - now).total_seconds())
if seconds < 3600:
return f"@ {max(1, ceil(seconds / 60))}m"
return f"@ {due_at.strftime('%H:%M')}"
def format_session_text(
nickname: str,
harness_name: str,
status_text: str,
symbol: str,
worktree_branch: str | None = None,
scheduled_prompt=None,
now: datetime | None = None,
) -> str:
color = _STATUS_COLORS.get(status_text, "#c6d0f5") # default: Text
name = nickname
@@ -47,7 +61,10 @@ def format_session_text(
else:
name = f"{nickname}{worktree_branch}"
label = escape(f"{name} [{harness_name}]")
return f"[{color}]{symbol}[/] {label} {status_text}"
schedule = ""
if scheduled_prompt is not None:
schedule = f" {format_scheduled_prompt(scheduled_prompt.due_at, now=now)}"
return f"[{color}]{symbol}[/] {label} {status_text}{schedule}"
class SessionList(Widget, can_focus=False):
@@ -71,6 +88,7 @@ class SessionList(Widget, can_focus=False):
status_text,
symbol,
getattr(s, "worktree_branch", None),
scheduled_prompt=getattr(info, "scheduled_prompt", None),
)
new_items.append((f"sess-{s.id}", text, s.id))
+45
View File
@@ -1032,6 +1032,51 @@ def test_format_session_text_status_colors():
) # Overlay0
def _make_scheduled_prompt(due_at):
prompt = MagicMock()
prompt.due_at = due_at
prompt.status = "pending"
return prompt
def test_format_session_text_shows_scheduled_prompt_countdown():
from datetime import datetime, timedelta
from hqt.tui.widgets.session_list import format_session_text
now = datetime(2026, 6, 11, 14, 0, 0)
scheduled = _make_scheduled_prompt(now + timedelta(minutes=12, seconds=1))
text = format_session_text(
"mywork",
"claude",
"idle",
"",
scheduled_prompt=scheduled,
now=now,
)
assert "@ 13m" in text
def test_format_session_text_shows_scheduled_prompt_clock_time():
from datetime import datetime, timedelta
from hqt.tui.widgets.session_list import format_session_text
now = datetime(2026, 6, 11, 14, 0, 0)
scheduled = _make_scheduled_prompt(now + timedelta(hours=2, minutes=30))
text = format_session_text(
"mywork",
"claude",
"idle",
"",
scheduled_prompt=scheduled,
now=now,
)
assert "@ 16:30" in text
@pytest.mark.asyncio
async def test_session_list_renders_harness_name_brackets():
"""Regression: '[claude]' must be visible, not swallowed as a markup tag."""