feat: improve agent support in interactive rli#209
Conversation
fix list display fix list view refactor to consolidate shared rendering code remove dead agentStore code adjust labels remove multi selection for benchmark job agents. UX was too ugly so simplifying for now
|
Comparisons between this PR and several of my PRs
Summary: The agent picker in devbox create (#206) and agent detail/routing (#205) have the heaviest overlap. The benchmark job agent picker, agent create screen, standalone agent list screen, shared column extraction, and several ResourcePicker improvements are unique to #209. |
james-rl
left a comment
There was a problem hiding this comment.
a few issues:
I think the first one is the only big one; the rest are nice to haves.
-
The AgentCreateScreen leaves the success screen non-interactive.
On success, creating is never reset to false, but input handling is disabled whenever creating is true. That means the screen tells the user to press Enter/Esc, but those keys no longer work after a successful create. -
We only seem to let you pick one agent in interactive mode -- is that intentional? It looks like this was changed
-
CLI agent list can overflow and misalign on narrow terminals or long values.
getAgentColumns() forces a minimum flexible width even when the terminal is too narrow, and the CLI renderer pads but never truncates. So the computed table can exceed the terminal width, and long IDs/versions can push later columns out of alignment.
| type: "agent_mount", | ||
| agent_id: formData.agent_id, | ||
| agent_name: null, | ||
| } as any); |
There was a problem hiding this comment.
this as any looks a bit fishy to me
Also, why pass agent_name as null if you're using agent_id instead of undefined?
This could be a backend api schema issue
| }} | ||
| onSelect={handleAgentSelect} | ||
| onCancel={() => setShowAgentPicker(false)} | ||
| initialSelected={formData.agent_id ? [formData.agent_id] : []} |
There was a problem hiding this comment.
I think this will do incorrect things if you toggle between public and private tabs
| const publicResult = await listPublicAgents({ | ||
| limit: remainingSlots, | ||
| startingAfter: publicCursor, | ||
| search: params.search, | ||
| }); | ||
|
|
||
| const uniquePublic = publicResult.agents.filter( | ||
| (a) => !privateIds.has(a.id), | ||
| ); | ||
| publicAgentsConsumed = uniquePublic.slice( | ||
| 0, | ||
| remainingSlots, | ||
| ); | ||
| publicHasMore = | ||
| publicResult.hasMore || | ||
| uniquePublic.length > remainingSlots; |
There was a problem hiding this comment.
publicResult has a limit of remainingSlots so the second condition is never true
| const [activeTab, setActiveTab] = React.useState<Tab>("private"); | ||
| const [selectedIndex, setSelectedIndex] = React.useState(0); | ||
|
|
||
| useExitOnCtrlC(); |
There was a problem hiding this comment.
we should probably register a global hook for sig int
|
Thanks for the detailed review!!
Yes, good catch! This was working earlier, but I must have stomped on it at some point without realizing. Thanks for the fix!
Yes, that was intentional. Maintaining the state cleanly across different trips into/out of the agent picker was messy and I had some edge cases that I couldn't get to work properly. Rather than burn more time on it yesterday, I opted to simplify and go for the single-agent selection in the TUI. Since the CLI still allows multiple agents, users can still do the things they need that way. (And the CLI is probably the more useful path anyway...)
Good point. I think wrapping is inevitable if the information is too long to fit, but I changed the CLI version to make sure the columns line up in all cases. |
…ion (#205) ## Summary - Add agent list/detail TUI screens with private/public tabs, actions popup, delete confirmation, and full cursor pagination - Add axon list and axon detail TUI screens - Rewrite CLI `agent list` and `axon list` to `.tsx` with TUI components and standard pagination (`--limit`/`--starting-after`) - Add `includeTotalCount` parameter to agent service for accurate pagination totals - Add axon service enhancements: search, `getAxon()`, `totalCount` - Group Agents, Objects, and Axons under new "Agents & Objects" main menu submenu - Move Benchmarks menu item before Settings - Rename "Storage Objects" to "Objects" throughout TUI (breadcrumbs, labels, table titles) Note: Agent routing, navigation store types, and `getAgentColumns()`/`buildAgentTableColumns()` were introduced by #209 and are not part of this PR's diff. ## Test plan - [x] `pnpm build` passes - [x] Tests pass - [x] Command docs auto-generated 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
🤖 I have created a release *beep* *boop* --- ## [1.16.0](v1.15.0...v1.16.0) (2026-04-23) ### Features * add agent/axon TUI screens and align list commands with pagination ([#205](#205)) ([1481d7a](1481d7a)) * add secret config to bmj, toggle available to show public benchmarks for new jobs ([#156](#156)) ([86cda21](86cda21)) * better handling of RUNLOOP_BASE_URL ([#216](#216)) ([f4b59fd](f4b59fd)) * extract shared object detail fields and fix ResourcePicker height ([#204](#204)) ([b685b65](b685b65)) * improve agent support in interactive rli ([#209](#209)) ([4aa5ca6](4aa5ca6)) * update agents support in rli command line ([#200](#200)) ([512d41f](512d41f)) ### Bug Fixes * "Showing 1-0 of 0" in TUI, cache unfiltered total count through search reset ([#196](#196)) ([8170888](8170888)) * don't reset settings TUI menu cursor on back ([#198](#198)) ([7a0796d](7a0796d)) * harden dependency security posture ([#211](#211)) ([198ad1e](198ad1e)) * improve column width handling for rli agent list ([#199](#199)) ([d4aa73f](d4aa73f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR adapts and modifies the changes from Jason's jason/agents_tab branch. There are a number of additions to the interactive rli interface:
interactive agent pickers (agent list, devbox create, benchmark job create) for consistent column layout (NAME, SOURCE, VERSION, ID, CREATED) with terminal-width-adaptive sizing
rendering via ref to reduce flicker; fix cross-page multi-select by tracking item objects in a ref Map
Files changed
src/services/agentService.ts
Add AgentColumn, agentVersionText(), getAgentColumns(); fix totalCount to use response.total_count
src/components/agentColumns.ts
New — shared buildAgentTableColumns() UI-layer column builder
src/commands/agent/list.ts
Replace local column/width logic with shared getAgentColumns()
src/screens/AgentListScreen.tsx
New — agent list with private/public tabs
src/screens/AgentDetailScreen.tsx
New — agent detail with delete operation
src/screens/AgentCreateScreen.tsx
New — agent creation form (npm/pip/git/object sources)
src/components/MainMenu.tsx
Add Agents menu item with [a] shortcut
src/components/BenchmarkMenu.tsx
Rename menu labels for clarity
src/router/Router.tsx
Register 3 new agent screens
src/store/navigationStore.tsx
Add agent screen types
src/screens/MenuScreen.tsx
Route "agents" selection to agent-list
src/components/DevboxCreatePage.tsx
Add agent mount picker with merged private+public search
src/screens/BenchmarkJobCreateScreen.tsx
Switch agent picker to single-select, use shared columns, server-side search
src/components/ResourcePicker.tsx
Add extraDeps, extraOverhead, nextCursor; stabilize columns via ref; fix cross-page selection tracking
src/hooks/useCursorPagination.ts
Support opaque nextCursor in fetch results