feat(web): add optional Session Name field to the Spawn Agent dialog#279
feat(web): add optional Session Name field to the Spawn Agent dialog#279vprudnikoff wants to merge 3 commits into
Conversation
The Spawn Agent dialog had no way to set a session name, so every web-UI session got an auto-generated cao-<hash> name. That hash is the only label the session list shows and searches by, and there is no rename — so the spawn dialog is the one place a user can give a session a readable identity. The backend POST /sessions and the CLI --session-name already accept a custom name; this just exposes it in the UI. - AgentPanel: add an optional "Session Name" input, pass it to createSession - store: thread sessionName through createSession (it was hardcoded undefined) - api: url-encode session_name in the query string (mirrors working_directory) - test: createSession includes the url-encoded session_name
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #279 +/- ##
=======================================
Coverage ? 92.14%
=======================================
Files ? 70
Lines ? 7106
Branches ? 0
=======================================
Hits ? 6548
Misses ? 558
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR adds an optional “Session Name” field to the web UI’s Spawn Agent dialog so users can create readable session identities instead of relying solely on auto-generated cao-<hash> names, bringing the web experience closer to existing CLI/API capabilities.
Changes:
- Adds an optional Session Name input to the Spawn Agent modal and passes it through the store to session creation.
- Threads
sessionNamethrough the Zustand store’screateSessioncall (previously alwaysundefined). - URL-encodes
session_namein thePOST /sessionsrequest and adds a unit test asserting the encoding.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| web/src/components/AgentPanel.tsx | Adds Session Name input and passes it into session creation from the spawn dialog. |
| web/src/store.ts | Extends the store createSession API to accept and forward sessionName. |
| web/src/api.ts | Encodes session_name in the create-session query string. |
| web/src/test/api.test.ts | Adds a test ensuring session_name is URL-encoded in requests. |
Comments suppressed due to low confidence (1)
web/src/store.ts:82
createSessionswallows errors and always resolves, which prevents the caller from keeping the Spawn dialog open on validation/duplicate-name failures (now more likely with the new Session Name field). Consider returning a success boolean or rethrowing after showing the snackbar so the UI can avoid closing/resetting on failure.
createSession: async (provider, agentProfile, workingDirectory, sessionName) => {
try {
await api.createSession(provider, agentProfile, sessionName, workingDirectory)
get().showSnackbar({ type: 'success', message: 'Session created' })
await get().fetchSessions()
} catch (e: any) {
get().showSnackbar({ type: 'error', message: e.message || 'Failed to create session' })
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| createSession: (provider: string, agentProfile: string, sessionName?: string, workingDirectory?: string) => | ||
| fetchJSON<Terminal>(`/sessions?provider=${provider}&agent_profile=${agentProfile}${sessionName ? `&session_name=${sessionName}` : ''}${workingDirectory ? `&working_directory=${encodeURIComponent(workingDirectory)}` : ''}`, { method: 'POST', timeoutMs: 90000 }), | ||
| fetchJSON<Terminal>(`/sessions?provider=${provider}&agent_profile=${agentProfile}${sessionName ? `&session_name=${encodeURIComponent(sessionName)}` : ''}${workingDirectory ? `&working_directory=${encodeURIComponent(workingDirectory)}` : ''}`, { method: 'POST', timeoutMs: 90000 }), |
There was a problem hiding this comment.
Good catch, and it's right on the line this PR touches. agent_profile can be free-text when no profiles are loaded, so a space or reserved character would corrupt the query. Fixed: encodeURIComponent is now applied to both provider and agent_profile (and to the sibling addTerminalToSession, which shared the same raw interpolation).
agent_profile can be free-text when no profiles are loaded, so a space or reserved character would corrupt the query string. encodeURIComponent both provider and agent_profile, matching the existing session_name and working_directory encoding. Applied to createSession and the sibling addTerminalToSession, which shared the same raw interpolation.
2c90ddb to
ee900b2
Compare
|
Re: the suppressed low-confidence note about |
| const handleCreate = async () => { | ||
| if (!profile.trim()) return | ||
| setCreating(true) | ||
| await createSession(provider, profile.trim(), workingDirectory.trim() || undefined) | ||
| await createSession(provider, profile.trim(), workingDirectory.trim() || undefined, sessionName.trim() || undefined) | ||
| setCreating(false) |
There was a problem hiding this comment.
Fixed in d90c783. Added a synchronous useRef in-flight lock so a second submit (rapid double-click, or Enter in the modal inputs — which bypass the button's disabled state) early-returns instead of firing a duplicate createSession. The success-side resets now run in a try, with setCreating(false) (and the lock release) in finally, so the form can't get stuck in "Spawning…" if the call throws, and the dialog stays open with its fields preserved on failure.
handleCreate is reachable via the Spawn button and via Enter in the modal inputs; the inputs bypass the button's disabled state, so a rapid double-press could fire a second createSession before the `creating` state re-renders. Add a synchronous useRef in-flight lock, and move the success-side resets into a try/finally so `creating` is always cleared (even if createSession throws) and the dialog stays open with its fields preserved on failure.
Summary
The Spawn Agent dialog in the web UI had no way to set a session name, so every web-created session got an auto-generated
cao-<hash>name (8 hex chars from a UUID). That generated id is the only label the session list shows and searches by, and there is no rename — so the spawn dialog is the one place to give a session a readable identity. The backendPOST /sessionsand the CLI--session-namealready accept a custom name; this just exposes it in the UI.What changed
createSession.sessionNamethroughcreateSession(it was hardcoded toundefined).session_namein the query string (matchingworking_directory).createSessionincludes the URL-encodedsession_name.Behavior
cao-<hash>exactly as before.validate_tmux_name) and prefixescao-if missing, identical tocao launch --session-nameand the API. A duplicate name surfaces the backend error in the existing snackbar.This brings the web UI to parity with the CLI's
--session-name.Testing
npm test(vitest) — green.npm run build(tsc + vite) — clean.