feat(agents): "save as persona template" on agent card + sidebar#1301
feat(agents): "save as persona template" on agent card + sidebar#1301tellaho wants to merge 1 commit into
Conversation
Opt-in promote of an existing managed agent into a reusable persona template. Lands on two surfaces — the agent card overflow menu (standalone agents only) and the sidebar agent profile's overflow menu — sharing one `saveAsPersonaTemplateDialogState` + the existing PersonaDialog and create-persona mutation. No new backend or IPC. The promote is near-lossless: name, system prompt, model, provider, and env vars copy across; the resolved harness command reverse-maps to a runtime id; namePool starts empty for the user to fill in the dialog. UI says "persona template" while the backend stays `persona` (kind:30175, builtin:*, .persona.md) — a boundary comment in personaLibraryCopy.ts records the mapping so the names are not conflated. Pure refactors to stay under the 1000-line file limit: extract AgentActionItems (+ AgentMenuProps) and the profile quick-action buttons into sibling files. Adds regression tests for the dialog-state mapping and a guard that default agent create stays persona-less. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
Reviewer note — runtime reverse-map on first open. The sidebar "Save as persona template" lazily loads ACP runtimes only when the dialog opens ( This is intentional and degrades gracefully — the user just picks the runtime themselves, same as a fresh persona create. A naive "re-seed once runtimes load" fix was prototyped and rejected: |
What & why
Adds an opt-in "Save as persona template" action so a configured managed agent can be saved as a reusable persona template — wired consistently across the surfaces where a user manages an agent. Part of the #1201 line of UX work.
Based on
kennylopez-agents-page-cards(#1199), notmain— the action lives on exactly the surface #1199 rewrites (agent action menus → card⋮). Basing here lands it on the UI that actually ships and avoids a double-merge into dead UI. Targets that branch as a draft so it merges into Kenny's work.Surfaces
⋮menu (AgentActionItems) — item gated!agent.personaId, so it only appears on agents that aren't already persona-backed.UserProfilePanel→ProfileQuickActionsoverflow⋮) — gatedcanEditAgent(owner + managed agent). Tucked in an overflow⋮to keep the quick-action row lean.How
duplicatePersonaDialogStateprefilled-dialog pattern:saveAsPersonaTemplateDialogState(agent)prefills the persona editor (name, system prompt, model, provider, env vars; reverse-mapsagentCommand→ runtime), leavesnamePoolempty for the user to fill, and opens the existingPersonaDialogso the user reviews before anything is created.CreatePersonaInputthrough the existing create mutation.useSaveAsPersonaTemplatefor surfaces outside the Agents page (the sidebar), with toast-based error handling.personaLibraryCopy.ts: UI says "persona template", backend stayspersona(kind:30175); symbols deliberately not renamed.ManagedAgent) — a databricks agent saves as a databricks template. (Reversed an earlier "leave provider unset" call once we confirmedprovideris on the row type.)Guardrails held
buildUnifiedGroupsor the card-grid structure — pure wiring.UnifiedAgentsSection.tsxchange tipped the 1000-line file-size gate; resolved by extracting the sharedAgentActionItemsinto its own file (the sanctioned "split, don't override" path) — a pure lift, no logic change. File now 869 lines.Part 1 (regression guard)
Verified
CreateAgentDialog.handleSubmitnever setspersonaId(persona-less by construction) and added 6 regression tests, incl. an explicit "default create stays persona-less" guard.Checks
pnpm typecheck✅ ·pnpm check✅ (biome + file-sizes + px-text) ·pnpm test✅ 1138/1138 · pre-push hooks green.Draft for review. Targets
kennylopez-agents-page-cards.