feat: add --agent-picker flag for agent selection UI#2937
Conversation
Add a --agent-picker flag to "docker agent run" that opens a full-screen pre-TUI to choose an agent from a comma-separated list of agent refs. When the list is omitted, it defaults to the built-in "default,coder" agents. The picker is hardened against untrusted (possibly remote) configs: descriptions and load errors are collapsed to a single line and truncated, the layout is responsive to narrow terminals, and the final-model type assertion is defensive against cancellation.
- Fix help bar to show '↑↓ move' instead of only listing up - Add '?' shortcut that opens scrollable dialog showing selected agent's raw config YAML - Dialog uses bubbles/viewport, dismissible with esc or ? - YAML is captured when loading each agent choice - Added tests for details toggle, content rendering, and scroll percentage
The YAML details dialog now maintains a fixed 90x28 size (clamped to fit small terminals), so it no longer moves or resizes while scrolling. Added a vertical scrollbar using pkg/tui/components/scrollbar, kept in sync with viewport scroll state. The viewport uses FillHeight for better layout control. Added test asserting dimensions stay constant while scrolling.
Sanitize YAML, descriptions, and error messages from potentially remote agent configs before display: normalize line endings, expand tabs, and strip control characters (ESC, etc.) to prevent terminal escape injection. Also enable SoftWrap in the YAML viewport so long lines wrap instead of scrolling off-screen. Adds tests for stripControl, sanitizeYAML, and escape-injection scenarios.
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟡 NEEDS ATTENTION
This PR adds a --agent-picker flag with a full-screen interactive TUI for selecting an agent before launching. The implementation is generally well-structured: flag wiring is correct, navigation guards are in place, the viewport/scrollbar sizing formula in renderDetails() is intentional and correct (title+help are sized to the full body width including the scrollbar column), and prependAgentRef is safe. One medium finding in the YAML sanitization logic.
| if r == '\n' { | ||
| return r | ||
| } | ||
| if r < 0x20 || r == 0x7f { |
There was a problem hiding this comment.
[MEDIUM] stripControl does not filter C1 control characters (U+0080–U+009F)
The stripControl function only removes C0 control characters (< 0x20) and DEL (0x7f), but entirely skips the C1 control range (U+0080–U+009F). Several characters in this range are meaningful on terminals: U+009B (CSI) is the 8-bit equivalent of ESC [ and can introduce ANSI escape sequences on terminals that support 8-bit control codes.
Since the PR description explicitly states that untrusted remote YAML content is sanitized to prevent terminal escape injection, this is a gap in the defence. A malicious agent YAML could embed \x9b (CSI) followed by ANSI sequence bytes and bypass the current filter entirely.
Suggested fix:
func stripControl(s string) string {
return strings.Map(func(r rune) rune {
if r == '\n' {
return r
}
if r < 0x20 || (r >= 0x7f && r <= 0x9f) {
return -1
}
return r
}, s)
}This removes DEL (0x7f) and the entire C1 range (0x80–0x9f) in one range check, which also correctly handles DEL without a separate condition.
When running
docker agent runwith multiple agents available, users currently have to know the agent name or use trial-and-error to pick the right one. This change adds a--agent-pickerflag that opens a full-screen pre-TUI dialog for browsing and selecting an agent interactively before launching the main agent TUI.The new
--agent-pickerflag accepts an optional comma-separated list of agent references (defaulting todefault,coder) and displays them in a scrollable dialog with the selected agent's raw YAML configuration visible in a collapsible panel. Keyboard shortcuts let users view or hide the YAML details (?to toggle), navigate with arrow keys, and confirm with Enter. The agent is resolved before sandbox or alias processing, so the chosen agent's defaults are honored. The feature is rejected cleanly in--execor non-TTY modes where interactive selection doesn't make sense.The implementation includes comprehensive test coverage, proper sanitization of untrusted YAML content (stripping terminal escape sequences), soft-wrap support for long lines, and syntax highlighting using the active TUI theme.