Skip to content

Commit 4524973

Browse files
feat(console): add focusable scrollable detail/chat pane (v shortcut) (#135)
1 parent c037861 commit 4524973

14 files changed

Lines changed: 929 additions & 63 deletions
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
---
2+
phase: design
3+
title: Agent Console Detail Chat View - System Design
4+
description: Technical design for focused and scrollable chat content in the interactive agent console
5+
---
6+
7+
# System Design & Architecture
8+
9+
## Architecture Overview
10+
11+
The feature extends the existing Ink console focus model. The agent list continues to own selection; the right-side preview/detail pane becomes a focus target that can consume scroll keys without changing list selection.
12+
13+
```mermaid
14+
graph TD
15+
Input["ConsoleApp useInput"]
16+
Focus["ConsoleFocus: list | detail | input"]
17+
List["AgentListPane"]
18+
PreviewSection["PreviewSection"]
19+
PreviewPane["PreviewPane"]
20+
Conversation["useAgentConversation"]
21+
Adapter["AgentAdapter.getConversation()"]
22+
23+
Input -->|v| Focus
24+
Input -->|list focus arrows/j/k| List
25+
Input -->|detail focus arrows/j/k| PreviewSection
26+
Focus -->|focused prop| PreviewSection
27+
PreviewSection --> PreviewPane
28+
PreviewSection --> Conversation
29+
Conversation --> Adapter
30+
```
31+
32+
Responsibilities:
33+
34+
- `ConsoleApp`: owns focus state, global key routing, selected agent, and detail scroll offset.
35+
- `PreviewSection`: receives focus and scroll offset props, keeps fetching selected-agent messages, computes/clamps the valid viewport range, and passes render constraints to `PreviewPane`.
36+
- `PreviewPane`: renders metadata, chat rows, empty/error states, and scroll affordances from a supplied clamped viewport.
37+
- `useAgentConversation`: remains responsible only for polling/caching conversation messages.
38+
39+
## Data Models
40+
41+
Extend console focus:
42+
43+
```typescript
44+
export type ConsoleFocus = 'list' | 'detail' | 'input';
45+
```
46+
47+
Add scroll state in `ConsoleApp`:
48+
49+
```typescript
50+
const [detailScrollOffset, setDetailScrollOffset] = useState(0);
51+
```
52+
53+
The offset represents logical rendered lines above the current detail viewport. A value of `0` means the viewport is pinned to the newest/latest rendered content at the bottom. Positive values move the viewport upward into older chat content.
54+
55+
`PreviewPane` should expose pure helpers for testable rendering math:
56+
57+
```typescript
58+
interface DetailViewport {
59+
lines: string[];
60+
clampedOffset: number;
61+
maxOffset: number;
62+
hasAbove: boolean;
63+
hasBelow: boolean;
64+
}
65+
```
66+
67+
`clampedOffset` is returned so `PreviewSection` can notify `ConsoleApp` when the current offset is no longer valid after a message update or terminal resize.
68+
69+
## API Design
70+
71+
No external API changes.
72+
73+
Internal prop changes:
74+
75+
```typescript
76+
interface PreviewSectionProps {
77+
selectedName: string | null;
78+
height: number;
79+
focused?: boolean;
80+
scrollOffset?: number;
81+
onScrollOffsetClamp?: (offset: number) => void;
82+
}
83+
84+
interface PreviewPaneProps {
85+
agent: AgentInfo | null;
86+
messages: ConversationMessage[];
87+
error: ConversationFetchError | null;
88+
isLoading: boolean;
89+
maxLines?: number;
90+
channelStatus?: AgentChannelStatus;
91+
scrollOffset?: number;
92+
onScrollOffsetClamp?: (offset: number) => void;
93+
}
94+
```
95+
96+
`ConsoleApp` key behavior:
97+
98+
- `v` from list focus: set focus to `detail` if an agent is selected and wide preview is visible.
99+
- `Esc` or left arrow from detail focus: set focus to `list`.
100+
- Up/down arrows and `j/k` from detail focus: adjust `detailScrollOffset` within `[0, maxOffset]`.
101+
- Because `ConsoleApp` does not own rendered-line calculation, scroll key handling may increment/decrement the requested offset and rely on `PreviewSection`/`PreviewPane` to clamp and report the valid value.
102+
- Up/down arrows and `j/k` from list focus: keep existing selected-agent navigation.
103+
- `i`/`m` from detail focus: may enter input focus when an agent is selected, same as list focus.
104+
105+
## Component Breakdown
106+
107+
Console components:
108+
109+
- `packages/cli/src/tui/console/types.ts`
110+
- Add `detail` to `ConsoleFocus`.
111+
- `packages/cli/src/tui/console/ConsoleApp.tsx`
112+
- Route `v`, scroll, escape, and left-arrow behavior.
113+
- Reset detail scroll offset when selected agent changes.
114+
- Pass `focused={focus === 'detail'}` into `PreviewSection`.
115+
- `packages/cli/src/tui/console/PreviewSection.tsx`
116+
- Apply focused panel styling to the preview panel.
117+
- Pass scroll offset and message budget into `PreviewPane`.
118+
- Clamp scroll offset when messages or height change and report the clamped offset upward.
119+
- `packages/cli/src/tui/console/PreviewPane.tsx`
120+
- Render a viewport over chat content instead of truncating only from the newest message.
121+
- Show simple `↑`/`↓` affordances in the header when more content exists.
122+
- Preserve current metadata, channel status, loading, empty, and error output.
123+
- Tests under `packages/cli/src/__tests__/tui/console`
124+
- Add helper tests for viewport calculations and update focus/layout tests where needed.
125+
126+
## Design Decisions
127+
128+
| Decision | Choice | Rationale |
129+
| --- | --- | --- |
130+
| Focus model | Add `detail` to `ConsoleFocus` | Matches existing focus routing and panel styling without a new modal mode. |
131+
| Shortcut | `v` enters detail focus | Matches the requested workflow and avoids existing console shortcuts. |
132+
| Scroll ownership | `ConsoleApp` owns requested offset; preview clamps it | Key handling and selected-agent reset stay centralized while rendered-line math stays near preview rendering. |
133+
| Rendering math | Pure helper in preview module | Keeps Ink rendering simple and gives unit tests deterministic coverage. |
134+
| Narrow mode | Keep `v` inactive while preview is hidden | Avoids focusing invisible UI; future full-screen transcript can be designed separately. |
135+
136+
Alternatives considered:
137+
138+
- Reuse `agent detail` command output inside the console: rejected because it would duplicate formatting and bypass existing preview polling.
139+
- Add a replacement-pane mode for detail: deferred because the requested workflow specifically highlights the detail pane and current wide layout already has one.
140+
- Fetch full session history by default: deferred to avoid changing polling cost; basic scrolling can operate on the current conversation tail first, then increase tail if needed during implementation review.
141+
142+
## Non-Functional Requirements
143+
144+
Performance:
145+
146+
- Scroll keypresses must not read session files or call `getConversation()`.
147+
- Viewport calculation should be linear in the currently loaded message count.
148+
- Existing polling interval and cache behavior should remain unchanged unless implementation proves the 20-message tail is too limiting for the feature.
149+
150+
Reliability:
151+
152+
- Missing session files, unsupported adapters, parse errors, empty message sets, and loading states must render with existing behavior while focused.
153+
- Scroll offset must be clamped when terminal height changes or message count changes.
154+
155+
Security:
156+
157+
- No new file paths, shell commands, network calls, or permissions are introduced.
158+
- Conversation content is already local session content exposed by the console; this feature changes navigation only.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
phase: implementation
3+
title: Agent Console Detail Chat View - Implementation Guide
4+
description: Implementation notes for focused and scrollable chat content in the interactive agent console
5+
---
6+
7+
# Implementation Guide
8+
9+
## Development Setup
10+
11+
- Active worktree: `.worktrees/feature-agent-console-detail-chat-view`
12+
- Branch: `feature-agent-console-detail-chat-view`
13+
- Dependencies: bootstrapped with `npm ci`
14+
- Feature docs: `docs/ai/*/2026-07-02-feature-agent-console-detail-chat-view.md`
15+
16+
## Code Structure
17+
18+
- `packages/cli/src/tui/console/types.ts`
19+
- `packages/cli/src/tui/console/ConsoleApp.tsx`
20+
- `packages/cli/src/tui/console/PreviewSection.tsx`
21+
- `packages/cli/src/tui/console/PreviewPane.tsx`
22+
- `packages/cli/src/tui/console/consoleKeyRouting.ts`
23+
- `packages/cli/src/__tests__/tui/console/PreviewPane.test.ts`
24+
- `packages/cli/src/__tests__/tui/console/focusRouting.test.ts`
25+
- `packages/cli/src/__tests__/tui/console/HelpPane.test.ts`
26+
27+
## Implementation Notes
28+
29+
### Core Features
30+
31+
- Add `detail` as a third console focus state instead of adding a new right-pane mode.
32+
- Keep `PreviewSection` visible in wide mode and focused via the existing `Panel` `focused` prop.
33+
- Keep scroll state in `ConsoleApp`; avoid coupling scroll behavior to conversation polling.
34+
- Prefer pure helper functions for scroll math so tests do not depend on terminal rendering snapshots.
35+
- Added `resolveConsoleKeyAction()` as a pure helper for list/detail/input key routing.
36+
- Added `buildPreviewViewport()` as a pure helper for visible chat lines, offset clamping, and scroll affordance state.
37+
- Added `v view` to console help/footer shortcuts.
38+
39+
### Patterns & Best Practices
40+
41+
- Follow existing Ink component patterns and panel design-system usage.
42+
- Keep new helpers exported only when tests need direct access.
43+
- Avoid introducing new session parsing or file access in UI components.
44+
- Clamp scroll offsets whenever viewport size or message count changes.
45+
46+
## Integration Points
47+
48+
- `useAgentConversation` continues to fetch selected-agent conversation data.
49+
- `PreviewPane` receives already-loaded `ConversationMessage[]`; scroll changes must not fetch.
50+
- `ConsoleApp` owns key routing and passes scroll/focus props down the preview tree.
51+
- `PreviewSection` forwards clamped offsets from `PreviewPane` back to `ConsoleApp`.
52+
53+
## Error Handling
54+
55+
- Preserve current `PreviewPane` error states for missing session files, unsupported adapters, and parse errors.
56+
- Detail focus with an error/empty/loading state should still render a focused panel and treat scroll as a no-op.
57+
- Do not add console logging for normal key routing.
58+
59+
## Performance Considerations
60+
61+
- Scroll updates should be state-only UI updates.
62+
- Keep existing conversation cache and polling interval unchanged unless implementation review identifies a functional gap.
63+
- Avoid recalculating viewport structures more broadly than the loaded message array and current viewport need.
64+
65+
## Security Notes
66+
67+
- No new command execution, network calls, or writes.
68+
- The feature only changes local display of already accessible agent session content.
69+
70+
## Implementation Results
71+
72+
Changed files:
73+
74+
- `packages/cli/src/tui/console/types.ts`: added `detail` focus state.
75+
- `packages/cli/src/tui/console/consoleKeyRouting.ts`: added pure key-routing helper.
76+
- `packages/cli/src/tui/console/ConsoleApp.tsx`: added detail scroll state, focus transitions, selected-agent scroll reset, and scroll-key handling.
77+
- `packages/cli/src/tui/console/PreviewSection.tsx`: forwards focus, scroll offset, and clamp callback into the preview panel.
78+
- `packages/cli/src/tui/console/PreviewPane.tsx`: added viewport helper, clamped offset reporting, scroll affordances, and line-based chat viewport rendering.
79+
- `packages/cli/src/tui/console/HelpPane.tsx`: added `v view` hotkey.
80+
- `packages/cli/src/__tests__/tui/console/PreviewPane.test.ts`: covers viewport helper behavior.
81+
- `packages/cli/src/__tests__/tui/console/focusRouting.test.ts`: covers list/detail/input key routing.
82+
- `packages/cli/src/__tests__/tui/console/HelpPane.test.ts`: covers new help/footer shortcut.
83+
84+
Simplification pass:
85+
86+
- `PreviewViewport` now returns typed rows instead of strings, so rendering uses `row.role` directly rather than inferring color from string prefixes.
87+
- `ConsoleApp` key action handling now uses a `switch` to keep focus, scroll, and selection actions grouped in one dispatch block.
88+
- `focusRouting.test.ts` now uses a local setup helper to remove repeated default key-routing inputs.
89+
90+
Design deviations:
91+
92+
- None. The implementation follows the reviewed design split: `ConsoleApp` owns requested offset and preview rendering clamps/report valid offsets.
93+
94+
Verification evidence:
95+
96+
- `npx vitest run src/__tests__/tui/console/PreviewPane.test.ts src/__tests__/tui/console/focusRouting.test.ts src/__tests__/tui/console/HelpPane.test.ts` passed: 3 files, 18 tests.
97+
- `npx vitest run src/__tests__/tui/console` passed: 16 files, 106 tests.
98+
- `npm run build` passed for all 6 projects.
99+
- `npm run lint --workspace packages/cli` exited 0 with 5 pre-existing warnings outside touched files.
100+
- `npx ai-devkit@latest lint --feature agent-console-detail-chat-view` passed after simplification.
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
phase: planning
3+
title: Agent Console Detail Chat View - Project Planning
4+
description: Initial task breakdown for focused and scrollable chat content in the interactive agent console
5+
---
6+
7+
# Project Planning & Task Breakdown
8+
9+
## Milestones
10+
11+
- [x] Milestone 1: Requirements/design/testing reviewed and accepted
12+
- [x] Milestone 2: Focus and scroll behavior implemented with tests
13+
- [x] Milestone 3: Console regression tests complete; manual terminal smoke test deferred (PTY scan returns 0 agents; real-terminal verification recommended before broad rollout)
14+
15+
## Task Breakdown
16+
17+
### Phase 1: Focus Model
18+
19+
- [x] Task 1.1: Add `detail` to `ConsoleFocus` and route focus transitions in `ConsoleApp`.
20+
- Outcome: pressing `v` from list focus in wide mode enters detail focus when an agent is selected; `Esc` and left arrow return to list focus.
21+
- Dependencies: none.
22+
- Validation: focused key-routing helper tests cover `v`, `Esc`, left arrow, no-agent, and narrow-mode no-op behavior.
23+
- Related tests: ConsoleApp focus/key helper scenarios.
24+
- [x] Task 1.2: Preserve existing list and input keyboard behavior.
25+
- Outcome: up/down and `j/k` still change selected agent in list focus; `i`/`m` still enter input focus; input cancel still returns to list focus.
26+
- Dependencies: Task 1.1.
27+
- Validation: regression tests for list navigation and input focus routing.
28+
- Related tests: ConsoleApp focus/key helper scenarios and existing console tests.
29+
- [x] Task 1.3: Reset detail scroll offset when selected agent changes.
30+
- Outcome: switching agents returns the detail pane to latest content instead of carrying the prior agent's scroll position.
31+
- Dependencies: Task 1.1.
32+
- Validation: helper or component test verifies selected-agent change resets offset.
33+
- Related tests: ConsoleApp focus/key helper scenarios.
34+
35+
### Phase 2: Scrollable Preview Rendering
36+
37+
- [x] Task 2.1: Add pure viewport/scroll helper logic for preview chat content.
38+
- Outcome: helper converts `ConversationMessage[]`, message budget, and requested scroll offset into visible lines, clamped offset, max offset, and above/below affordance state.
39+
- Dependencies: none, but implement before wiring Ink rendering.
40+
- Validation: unit tests cover newest view, older view, negative offset, too-large offset, long conversations, and multi-line messages.
41+
- Related tests: PreviewPane viewport helper scenarios.
42+
- [x] Task 2.2: Pass focus and scroll offset through `PreviewSection` to `PreviewPane`.
43+
- Outcome: focused preview uses existing `Panel` focus styling and receives the requested detail scroll offset.
44+
- Dependencies: Tasks 1.1 and 2.1.
45+
- Validation: component/helper test verifies focused panel prop and visible content changes with offset.
46+
- Related tests: integration scenarios for focused `PreviewSection`.
47+
- [x] Task 2.3: Render scroll affordances when older/newer content exists outside the viewport.
48+
- Outcome: preview header shows subtle up/down indicators only when scrolling is possible.
49+
- Dependencies: Task 2.1.
50+
- Validation: unit tests verify `hasAbove`/`hasBelow` states and snapshot-light text assertions for header indicators.
51+
- Related tests: PreviewPane viewport helper scenarios.
52+
- [x] Task 2.4: Clamp requested detail scroll offset when messages or terminal height change.
53+
- Outcome: preview reports clamped offsets upward so `ConsoleApp` state cannot remain outside the valid viewport range.
54+
- Dependencies: Tasks 2.1 and 2.2.
55+
- Validation: test covers shrinking content/height and verifies the callback receives the valid offset.
56+
- Related tests: integration scenarios for changing message count or `maxLines`.
57+
58+
### Phase 3: Tests & Polish
59+
60+
- [x] Task 3.1: Add unit tests for viewport clamping, visible-line selection, and affordance state.
61+
- Outcome: pure scroll math has deterministic coverage.
62+
- Dependencies: Task 2.1.
63+
- Validation: targeted `PreviewPane.test.ts` or new helper test passes.
64+
- [x] Task 3.2: Add or update console focus/key routing tests.
65+
- Outcome: list/detail/input key behavior has regression coverage.
66+
- Dependencies: Tasks 1.1-1.3.
67+
- Validation: targeted console tests pass.
68+
- [x] Task 3.3: Run feature lint and targeted console test suites.
69+
- Outcome: docs and changed console code pass validation.
70+
- Dependencies: implementation tasks complete.
71+
- Validation: `npx ai-devkit@latest lint --feature agent-console-detail-chat-view` and `npm test -- --run packages/cli/src/__tests__/tui/console`.
72+
- [x] Task 3.4: Perform manual terminal smoke test with a running agent when available.
73+
- Outcome: real Ink focus styling and scroll behavior are visually confirmed.
74+
- Dependencies: implementation tasks complete and at least one running agent available.
75+
- Validation: manual notes in testing doc; if no running agent is available, record as deferred with reason.
76+
77+
## Dependencies
78+
79+
- Task 1.1 precedes all detail focus and scroll behavior.
80+
- Task 2.1 should be implemented before changing Ink rendering so tests can cover the behavior directly.
81+
- Task 2.4 depends on Task 2.1 because clamping should use the same helper that computes the viewport range.
82+
- Task 3.2 depends on the chosen key-routing shape in `ConsoleApp`.
83+
- No external services or API changes are required.
84+
85+
## Test Scenario Coverage
86+
87+
| Testing scenario | Covered by tasks |
88+
| --- | --- |
89+
| Newest content appears at offset 0 | 2.1, 3.1 |
90+
| Older content appears at positive offset | 2.1, 3.1 |
91+
| Offset clamping | 2.1, 2.4, 3.1 |
92+
| Focused panel styling | 1.1, 2.2, 3.2 |
93+
| Scroll keys do not move list selection in detail focus | 1.1, 1.2, 3.2 |
94+
| Existing list/input behavior is unchanged | 1.2, 3.2 |
95+
| No hidden focus trap in narrow mode | 1.1, 3.2, 3.4 |
96+
| Scroll keypresses do not fetch conversation data | 2.2, 2.4, 3.3 |
97+
98+
## Timeline & Estimates
99+
100+
- Focus model: small.
101+
- Scrollable preview rendering: medium, mainly due to line accounting in terminal UI.
102+
- Tests and manual smoke: small to medium.
103+
104+
## Risks & Mitigation
105+
106+
| Risk | Impact | Mitigation |
107+
| --- | --- | --- |
108+
| Focus trap in hidden narrow preview | High | Keep `v` inactive in narrow mode for this iteration. |
109+
| Scroll keys break list navigation | High | Centralize key routing and add regression tests for both focus states. |
110+
| Line accounting differs from Ink wrapping | Medium | Base helper on explicit rendered lines and keep content clipping conservative. |
111+
| Conversation tail of 20 feels too short | Medium | Keep existing behavior initially; revisit tail size during implementation review if scrolling is not useful enough. |
112+
113+
## Resources Needed
114+
115+
- Existing console TUI components under `packages/cli/src/tui/console`.
116+
- Existing conversation parsing through `@ai-devkit/agent-manager`.
117+
- Existing console tests and manual terminal run of `ai-devkit agent console`.
118+
119+
## Planning Status
120+
121+
All tasks complete. 16 console test files (106 tests) pass. CLI lint exits 0. Feature lint passes. Manual PTY smoke verified two-pane layout and clean exit; selected-agent detail focus deferred due to PTY agent-scan limitation — recommended for real-terminal verification before broad rollout.

0 commit comments

Comments
 (0)