Startup agent picker — fetch GET /agents when --new without --agent (TUI) #8
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Today,
ratatoskr --new --agent <id>requires the--agentflag. If theoperator omits it,
_parse_argsraisesUsageError("--agent is required when --new is passed"). That's the right behavior for--sendmode(non-interactive, can't prompt). It's the wrong behavior for the TUI: the
operator might not know which agents are available, doesn't want to look
them up out-of-band, and would prefer to pick from a list at startup.
The Worldtree spec exposes
GET /agents(spec line 832; vendored atdocs/conversation-api-spec.mdat SHA55101e9...). It returns a JSONarray with at minimum
agent_id,name,descriptionper agent; somecarry
version,capabilities,supported_models,persona_traits,and
ui_hints(icon + color_hint). Ratatoskr could fetch this list andlet the operator pick.
Solution
Minimal startup agent picker for the TUI when
--newis passed without--agent. Three pieces:ratatoskr.sessions(issue #2 amendment): newlist_agents()function.AgentInfois a new frozen dataclass with all fields the spec lists; thenon-required fields default to
None/[]/{}when omitted from theserver response (mirrors the
SessionInfoorigin-conditional-defaultspattern from INV-001/INV-002 of issue #2).
ratatoskr.cli(issue #3 amendment):--agentbecomes conditionallyoptional.
--agentrequirement now depends on mode:--send --new(non-interactive create):--agentSTILL required;no way to prompt.
UsageErrorpreserved.--new(TUI create):--agentOPTIONAL. When omitted, the TUIlaunches an agent-picker screen before the chat pane.
--session <id>(any mode):--agentSTILL forbidden (existingINV-004 behavior; preserved).
_parse_argsSTEP 3 validates the mode-conditional requirement.ratatoskr.tui(issue #4 amendment): newAgentPickerScreen.Pushed onto the App's screen stack BEFORE
on_mount's session-createwhen
args.newANDargs.agent_id is None. Layout:On Enter, the picker pops itself off the screen stack and stores the
selection in
self.agent_id; control returns to the chat-pane screenwhich proceeds with
create_session(client, agent_id=self.agent_id, end_user_id=self.args.end_user_id). (Theend_user_idthreading isissue #5's amendment; this issue and #5 compose naturally.)
On Esc (or Ctrl-D / Ctrl-C from the picker): exit cleanly with code 0.
No session was created.
Out of scope (this issue)
installed-agent count grows large enough to need search, file a
follow-up.
ui_hintsrendering.iconandcolor_hintfrom the spec aredeclared in
AgentInfofor future use but the picker just showsagent_id · name — descriptionin v1. Pretty-print is a follow-up.show up in
GET /agentsif the server has them; the picker showsthem like any other; ratatoskr doesn't distinguish.
persona_traits/capabilitiespreview pane. Side detail whenthe operator highlights an agent. Future polish.
--sendmode.--sendis non-interactiveby design (design-brief §8b). Operators using
--sendmust knowthe agent_id; they can shell out to
curl GET /agents | jqif theyforget.
ratatoskrlaunchfetches fresh. v1 over-fetches by design — agent list is small,
cheap, and rarely stale; cache-coherence is a real cost.
Benefits
ratatoskr --newJust Works for interactive use.
naturally on next launch.
--end-user-id): if both are needed, operatorpasses
--end-user-idon the CLI and picks the agent in the TUI.screen, one CLI conditional. Doesn't reshape the existing
modules' invariants.
Acceptance
list_agentscoverage + new TUIpicker coverage).
uv run ruff check src/ tests/clean.ratatoskr --new(no--agent) → picker appears with all agentsfrom personal Worldtree; pick mimir → proceeds to chat pane;
type a message → response streams cleanly.
ratatoskr --new --agent mimir(with--agent) → picker skipped;behavior unchanged from today.
ratatoskr --send "hello" --new(no--agent) → UsageError; noTUI launch. (Regression check.)
ratatoskr --session s-1→ no picker; no agent fetch; attachesto the existing session. (Regression check.)
Dependencies
ratatoskr.sessions) — landed on main; this issue addslist_agents()+AgentInfodataclass.ratatoskr.cli) — landed on main; this issue amends_parse_argsfor conditional--agentrequirement.ratatoskr.tui) — landed on main; this issue addsAgentPickerScreenand a startup branch.--end-user-id) — independent; composes naturally if bothland but neither blocks the other.
Shipped at
d30be12(v0.3.0).ratatoskr.sessions:list_agents()+AgentInfofrozen dataclass.ratatoskr.cli:--agentmode-conditional (required for--send --new; optional for bare--new; forbidden with--session).ratatoskr.tui: newAgentPickerApp(separate Textual App, opens beforeRatatoskrAppsolist_agentserrors land on real stderr — preserves issue #6 INV-001)._resolve_then_rungains the pre-create picker branch.Contract:
docs/contracts/issues/8.contract.md(drift-check clean).+18 tests; 227 total GREEN; ruff clean. Live smoke against personal Worldtree returned 12 agents; programmatic picker drive auto-picked
lofnand created a real session withend_user_id="ratatoskr-tui". Interactive eyeball still pending — auto-pick covered the wiring.