Skip to content

feat(minimald): track terminal meta, send in ListSessions RPC - #421

Merged
twitchyliquid64 merged 1 commit into
mainfrom
tom/minimald
Jun 15, 2026
Merged

feat(minimald): track terminal meta, send in ListSessions RPC#421
twitchyliquid64 merged 1 commit into
mainfrom
tom/minimald

Conversation

@twitchyliquid64

@twitchyliquid64 twitchyliquid64 commented Jun 15, 2026

Copy link
Copy Markdown
Member

Reports terminal information about a running session, which is super useful to the presentation layer.

  • Last time bytes were received from a client or from the process (activity)
  • Visual and audible bells
  • Terminal title, which a lot of agent harnesses use as a kind of status bar

Summary by CodeRabbit

Release Notes

  • New Features
    • Added tracking of running session host attributes: window title (with timestamp), audible/visual bell counts (with timestamps), and last stdin/stdout activity times.
    • Extended session listing (and “ListSessions” RPC) to include this data as optional metadata.
    • Introduced a new async API to fetch current host attributes for a running session.
  • Tests
    • Added/updated an integration test to validate window-title handling and stdin/stdout timestamp capture, and adjusted list/RPC expectations.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2656db93-8ba9-48d7-8402-22837e6f5840

📥 Commits

Reviewing files that changed from the base of the PR and between 2fc8e6d and c3f1d40.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • Cargo.toml
  • crates/minimald-rpc/Cargo.toml
  • crates/minimald-rpc/src/lib.rs
  • crates/minimald/Cargo.toml
  • crates/minimald/src/rpc.rs
  • crates/minimald/src/session.rs
  • crates/minimald/src/session_host.rs
  • crates/minimald/src/sessions.rs
🚧 Files skipped from review as they are similar to previous changes (7)
  • crates/minimald/src/sessions.rs
  • Cargo.toml
  • crates/minimald/Cargo.toml
  • crates/minimald-rpc/Cargo.toml
  • crates/minimald/src/session.rs
  • crates/minimald-rpc/src/lib.rs
  • crates/minimald/src/session_host.rs

📝 Walkthrough

Walkthrough

The PR introduces HostAttrs — a struct tracking terminal title, bell events, and stdin/stdout last-activity timestamps — into the session host actor with VT100 callback integration. A ParserEventHandler adapter forwards title and bell events from the parser into the host actor's persisted HostAttrs. A new get_attrs() async API is threaded from HostHandle through SessionHandle into the sessions manager, and the results are mapped into new RPC types (Bell, Title, RunningSessionAttrs) exposed via ListSessionsEntry.attrs. The chrono crate is added workspace-wide to support DateTime<Utc> fields.

Changes

Session Terminal Attribute Tracking

Layer / File(s) Summary
Workspace dependencies and RPC data contracts
Cargo.toml, crates/minimald-rpc/Cargo.toml, crates/minimald/Cargo.toml, crates/minimald-rpc/src/lib.rs
Adds chrono with serde and std features to workspace dependencies and both crates; introduces Bell, Title, and RunningSessionAttrs RPC types with DateTime<Utc> fields; extends ListSessionsEntry with optional attrs: Option<RunningSessionAttrs>.
session_host: HostAttrs struct, callbacks, actor protocol, and parser integration
crates/minimald/src/session_host.rs
Defines HostAttrs with title, bell counters, and stdin/stdout last-activity timestamps; implements ParserEventHandler and WeakHostHandle to forward VT100 parser events into the host actor; extends host actor protocol with title/bell callbacks and GetAttrs query; adds HostHandle::make_weak() and HostHandle::get_attrs() async API; updates Host struct initialization to use callback-aware VT100 parser; stamps attrs.stdout_last after PTY reads and attrs.stdin_last when consuming SSH input.
SessionHandle and session actor: get_attrs query propagation
crates/minimald/src/session.rs
Adds SessionMessage::GetHostAttrs variant returning Option<HostAttrs>; implements SessionHandle::get_attrs() to send the query through the session actor and await the result; handler replies with None if no host is running, otherwise delegates to HostHandle::get_attrs() and maps errors to None.
RPC serving, sessions manager, HostAttrs-to-RPC mapping, and integration test
crates/minimald/src/sessions.rs, crates/minimald/src/rpc.rs, crates/minimald/src/session_host.rs
Extends SessionInfo with optional attrs field; updates ManagerMessage::List handler to populate attrs by querying running sessions via get_attrs(); updates serve_list_sessions to map each session's HostAttrs into RunningSessionAttrs for the RPC response (converting timestamps, mapping bell counts to optional Bell, transforming title); updates test expectation to attrs: None; adds Tokio integration test that sends OSC title escape through host stdin, polls get_attrs() until title appears, and asserts stdin/stdout last-activity timestamps are recorded.

Sequence Diagram(s)

sequenceDiagram
  participant Client as RPC Client
  participant RpcHandler as serve_list_sessions
  participant SessionsMgr as SessionsManager
  participant SessionHandle
  participant HostActor as HostActor
  participant VT100 as VT100Parser

  VT100->>VT100: OSC Title event
  VT100->>HostActor: SetTitleCallback
  HostActor->>HostActor: update attrs.title, attrs.stdout_last
  Client->>RpcHandler: ListSessions()
  RpcHandler->>SessionsMgr: List request
  SessionsMgr->>SessionHandle: get_attrs()
  SessionHandle->>HostActor: GetHostAttrs (oneshot)
  HostActor->>SessionHandle: Some(HostAttrs)
  SessionHandle->>SessionsMgr: Option<HostAttrs>
  SessionsMgr->>RpcHandler: Vec<SessionInfo> with attrs
  RpcHandler->>RpcHandler: map HostAttrs → RunningSessionAttrs
  RpcHandler->>Client: ListSessionsResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • gominimal/minimal#420: Introduces the ListSessions RPC wiring and serve_list_sessions function that this PR extends with ListSessionsEntry.attrs population.

Suggested reviewers

  • 0chroma
  • evanspearman

Poem

🐇 Through terminal glass, my whiskers twitch with glee,
Tracking titles and bells in HostAttrs spree!
stdout_last and stdin_last mark the time so true,
VT100 callbacks dance—whoosh!—straight through.
Session attributes hop into RPC's gentle hand,
chrono-stamped and ready—the finest in the land! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: tracking terminal metadata and sending it in the ListSessions RPC response, which aligns with the core objectives of adding terminal metadata tracking.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/minimald-rpc/src/lib.rs`:
- Around line 115-121: The RunningSessionAttrs struct is missing fields to track
bell attributes (audible and visual bell events), which prevents the
ListSessions wire contract from carrying complete bell metadata despite the
host-side tracking this information. Add bell-related fields to the
RunningSessionAttrs struct following the same pattern as the existing
last_stdout and last_stdin fields, using Option<chrono::DateTime<Utc>> to
capture the last occurrence of audible and visual bell events so the complete
bell metadata can be transmitted through the wire protocol.

In `@crates/minimald/src/session_host.rs`:
- Around line 442-447: The get_attrs method panics when the host actor has
exited due to the recv.await.expect call on a closed channel, which causes actor
tasks to crash instead of gracefully handling the closed host. Change the return
type of get_attrs from HostAttrs to Option<HostAttrs>, and replace the
recv.await.expect call with error handling that returns None when the receiver
channel is closed (i.e., when the host task has already exited). This allows
callers like SessionMessage::GetHostAttrs to handle the None case gracefully
without panicking.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2ed6f18c-0154-422b-9da2-3a16d14c328c

📥 Commits

Reviewing files that changed from the base of the PR and between bfc61a8 and ea8e71f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • Cargo.toml
  • crates/minimald-rpc/Cargo.toml
  • crates/minimald-rpc/src/lib.rs
  • crates/minimald/Cargo.toml
  • crates/minimald/src/rpc.rs
  • crates/minimald/src/session.rs
  • crates/minimald/src/session_host.rs
  • crates/minimald/src/sessions.rs

Comment thread crates/minimald-rpc/src/lib.rs
Comment thread crates/minimald/src/session_host.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/minimald/src/rpc.rs`:
- Around line 92-104: The visual_bell and audible_bell match expressions use
unsafe .unwrap() calls on the timestamp field (a.visual_bell.1 and
a.audible_bell.1) when the count is non-zero, which will panic if the invariant
is violated. Replace both matches with defensive tuple destructuring patterns:
match (a.visual_bell.0, a.visual_bell.1) and match (a.audible_bell.0,
a.audible_bell.1), then handle each case explicitly including the
(non_zero_count, None) case by logging a warning and returning None instead of
unwrapping.
- Around line 99-104: The audible_bell mapping contains an unsafe unwrap on
a.audible_bell.1 that can panic if audible_bell.0 is non-zero but the timestamp
is None. In the match arm where audible_bell.0 is matched to a non-zero value,
apply the same defensive fix pattern that was used for the visual_bell case
above it. Replace the unwrap call on a.audible_bell.1 with appropriate pattern
matching or a safe alternative that handles the None case gracefully without
panicking.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eb9e9291-ca8b-41ee-8efc-11250d58caef

📥 Commits

Reviewing files that changed from the base of the PR and between ea8e71f and 2f12145.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • Cargo.toml
  • crates/minimald-rpc/Cargo.toml
  • crates/minimald-rpc/src/lib.rs
  • crates/minimald/Cargo.toml
  • crates/minimald/src/rpc.rs
  • crates/minimald/src/session.rs
  • crates/minimald/src/session_host.rs
  • crates/minimald/src/sessions.rs
✅ Files skipped from review due to trivial changes (2)
  • crates/minimald-rpc/Cargo.toml
  • Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (5)
  • crates/minimald/Cargo.toml
  • crates/minimald-rpc/src/lib.rs
  • crates/minimald/src/sessions.rs
  • crates/minimald/src/session.rs
  • crates/minimald/src/session_host.rs

Comment thread crates/minimald/src/rpc.rs Outdated
Comment thread crates/minimald/src/rpc.rs Outdated
@twitchyliquid64
twitchyliquid64 merged commit f45be10 into main Jun 15, 2026
33 checks passed
@twitchyliquid64
twitchyliquid64 deleted the tom/minimald branch June 15, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants