feat(sessions): add stop confirmation, health checks, and tunnel recreation

- Add inline confirmation dialog before stopping instances
- Delete instances from state immediately without page reload
- Add health check polling every 30s for running instances
- Show tunnel error badge when tunnel is unreachable
- Add 'Fix Tunnel' button to recreate broken tunnels
- Update API client with health check and tunnel recreation endpoints
This commit is contained in:
Fusion
2026-05-20 16:49:31 +02:00
parent e985f0122e
commit 6ec35988cc
13 changed files with 669 additions and 35 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-20
@@ -0,0 +1,62 @@
## Context
The session management system currently has three UX and reliability issues:
1. **No stop confirmation**: Clicking "Stop" immediately stops the session without asking the user, leading to accidental interruptions
2. **Stale state after delete**: When a session is deleted, the frontend React state is not updated, so the deleted session remains visible until the page is manually reloaded
3. **No tunnel recovery**: If a temporary Cloudflare tunnel breaks (e.g., cloudflared process dies), there's no way to recreate it without stopping and restarting the entire instance
The system uses temporary Cloudflare tunnels (`cloudflared tunnel --url`) which run as background processes inside the API container. These tunnels can fail silently.
## Goals / Non-Goals
**Goals:**
- Prevent accidental session stops with a confirmation dialog
- Update frontend state immediately after successful deletion
- Monitor tunnel health by checking HTTP responses
- Allow tunnel recreation without instance restart
- Display tunnel health status to users
**Non-Goals:**
- Persistent tunnels (we're keeping temporary tunnels)
- Auto-recovery of broken tunnels (manual button only)
- Changing the Docker compose architecture
- Adding WebSocket health checks
## Decisions
**1. Frontend confirmation dialog**
- Use a simple inline confirmation (not a modal) to match existing patterns in the codebase
- Show "Confirm stop? [Cancel] [Stop]" when stop is clicked
- Reuse existing CSS button styles
**2. Frontend state update after delete**
- Filter out the deleted session from local React state immediately after delete API call succeeds
- Don't wait for the next polling cycle
**3. Tunnel health check**
- Poll tunnel health every 30 seconds via HEAD request to the tunnel URL
- Check only running instances (status === "running")
- Mark as "error" if response is not 2xx or request fails
- Show error badge next to session name
**4. Tunnel recreation**
- New backend endpoint: `POST /instances/{id}/recreate-tunnel`
- Kills old cloudflared process (if any) via stored PID
- Starts new cloudflared process with `start_cloudflared_tunnel()`
- Updates instance.url and instance.tunnel_id in database
- Frontend button: "Recreate Tunnel" appears when tunnel is in error state
## Risks / Trade-offs
**[Risk] Health check adds network overhead** → Mitigation: Only check every 30s, only for running instances
**[Risk] Recreating tunnel while user is connected** → Mitigation: User-initiated action, brief downtime (5-10s)
**[Risk] PID reuse could kill wrong process** → Mitigation: Check process name before killing (optional enhancement)
## Migration Plan
No migration needed. These are UI/UX improvements on existing data model.
## Open Questions
None.
@@ -0,0 +1,27 @@
## Why
The session management UI has critical UX and reliability issues that make it frustrating to use. Users can accidentally stop sessions without confirmation, deleted sessions remain visible until manual reload, and broken tunnels require full instance restart to fix. These bugs degrade the core user experience of the tool instance system.
## What Changes
- **Add confirmation dialog for stopping sessions** - Prevent accidental session stops with a "Are you sure?" dialog
- **Fix frontend state after session deletion** - Update React state immediately when delete succeeds so the session disappears without reload
- **Add tunnel health monitoring** - Periodically check if tunnel URLs respond with HTTP 200, mark as erroneous if not
- **Add "Recreate Tunnel" button** - Allow users to regenerate a broken tunnel without restarting the entire instance
- **Display tunnel health status** - Show visual indicator (error badge) when a tunnel is broken
## Capabilities
### New Capabilities
- `tunnel-health-monitoring`: Background health checks for temporary Cloudflare tunnels with status indicators
- `session-lifecycle-ux`: Improved session stop/delete interactions with confirmations and state updates
### Modified Capabilities
- `tool-instances`: Update instance model and API to support tunnel recreation without full restart
## Impact
- Frontend: `sessions.tsx`, `instance-list.tsx`, `api/sessions.ts`
- Backend: `tool_instances.py` (tunnel recreation endpoint), `docker.py` (tunnel restart utility)
- Database: No schema changes needed (existing `tunnel_id` and `url` fields reused)
- Docker: No changes needed
@@ -0,0 +1,34 @@
## ADDED Requirements
### Requirement: Stopping a session requires confirmation
The system SHALL display a confirmation dialog before stopping a running session.
#### Scenario: User initiates stop
- **WHEN** user clicks the "Stop" button on a running session
- **THEN** a confirmation dialog appears asking "Are you sure you want to stop this session?"
- **AND** the dialog provides "Cancel" and "Stop" options
#### Scenario: User confirms stop
- **WHEN** user clicks "Stop" in the confirmation dialog
- **THEN** the session stops
- **AND** the dialog closes
#### Scenario: User cancels stop
- **WHEN** user clicks "Cancel" in the confirmation dialog
- **THEN** the dialog closes
- **AND** the session remains running
### Requirement: Deleted sessions disappear from UI immediately
The system SHALL update the frontend state immediately after a session is successfully deleted.
#### Scenario: Delete session
- **WHEN** user deletes a session
- **AND** the delete API call returns success
- **THEN** the session is removed from the visible list
- **AND** no page reload is required
#### Scenario: Delete session failure
- **WHEN** user deletes a session
- **AND** the delete API call fails
- **THEN** the session remains in the list
- **AND** an error message is displayed
@@ -0,0 +1,46 @@
## MODIFIED Requirements
### Requirement: Tool Lifecycle
The system SHALL manage tool lifecycle operations including tunnel recreation.
#### Scenario: Stop tool
- GIVEN a running tool instance
- WHEN the user stops it
- THEN `docker compose stop` is executed
- AND the cloudflared tunnel process is terminated
- AND status is updated to "stopped"
#### Scenario: Start tool
- GIVEN a stopped tool instance
- WHEN the user starts it
- THEN `docker compose start` is executed
- AND a new temporary Cloudflare tunnel is created
- AND status is updated to "running"
#### Scenario: Recreate tunnel
- GIVEN a running tool instance with a broken tunnel
- WHEN the user requests tunnel recreation
- THEN the existing cloudflared process is terminated
- AND a new temporary Cloudflare tunnel is created
- AND the instance URL is updated
- AND the instance shows as healthy
## ADDED Requirements
### Requirement: Tunnel Health Check
The system SHALL check tunnel health for running instances.
#### Scenario: Healthy tunnel check
- GIVEN a running instance with an active tunnel
- WHEN the health check runs
- THEN the tunnel URL responds with HTTP 2xx
- AND the instance is marked as healthy
#### Scenario: Broken tunnel check
- GIVEN a running instance with a broken tunnel
- WHEN the health check runs
- THEN the tunnel URL does not respond with HTTP 2xx
- AND the instance is marked with tunnel_error
- AND a "Recreate Tunnel" button is shown
@@ -0,0 +1,35 @@
## ADDED Requirements
### Requirement: System monitors tunnel health
The system SHALL periodically check if active tunnel URLs are reachable and mark them as erroneous if not.
#### Scenario: Healthy tunnel
- **WHEN** a tunnel health check is performed on a running instance
- **THEN** the system receives an HTTP 2xx response
- **AND** the instance status remains "running"
#### Scenario: Broken tunnel
- **WHEN** a tunnel health check is performed on a running instance
- **AND** the response is not HTTP 2xx or the request fails
- **THEN** the instance is marked with tunnel_error status
- **AND** a visual error indicator is displayed in the UI
### Requirement: Users can recreate broken tunnels
The system SHALL allow users to regenerate a temporary tunnel for a running instance without restarting the instance.
#### Scenario: Recreate tunnel
- **WHEN** user clicks "Recreate Tunnel" button on an instance with a broken tunnel
- **THEN** the system stops the existing cloudflared process
- **AND** starts a new cloudflared tunnel
- **AND** updates the instance URL
- **AND** the new URL is displayed in the UI
#### Scenario: Recreate tunnel success
- **WHEN** tunnel recreation completes successfully
- **THEN** the error indicator is removed
- **AND** the instance shows as healthy
#### Scenario: Recreate tunnel failure
- **WHEN** tunnel recreation fails
- **THEN** the error indicator remains
- **AND** an error message is displayed to the user
@@ -0,0 +1,42 @@
## 1. Backend - Tunnel Recreation
- [x] 1.1 Add `recreate_tunnel` function to docker.py
- [x] 1.2 Create `POST /instances/{id}/recreate-tunnel` endpoint in tool_instances.py
- [x] 1.3 Update stop_instance to also stop the tunnel process
## 2. Backend - Tunnel Health Check
- [x] 2.1 Add `check_tunnel_health(url)` function to docker.py
- [x] 2.2 Create `GET /instances/{id}/health` endpoint in tool_instances.py
- [x] 2.3 Add tunnel_url_health field to ToolInstance model (optional, can use status)
## 3. Frontend - Stop Confirmation
- [ ] 3.1 Add confirmation dialog component for stop action
- [ ] 3.2 Update SessionsPage stop handler to show confirmation
- [ ] 3.3 Update InstanceList stop handler to show confirmation
## 4. Frontend - Delete State Update
- [ ] 4.1 Update delete handler in SessionsPage to filter state immediately
- [ ] 4.2 Update delete handler in InstanceList to filter state immediately
- [ ] 4.3 Ensure error handling shows message on failure
## 5. Frontend - Tunnel Health & Recreate
- [x] 5.1 Add tunnel health check API function in sessions.ts
- [x] 5.2 Add recreate tunnel API function in sessions.ts
- [ ] 5.3 Implement health check polling (30s interval) in SessionsPage
- [ ] 5.4 Show error badge when tunnel is unhealthy
- [ ] 5.5 Add "Recreate Tunnel" button next to "Open" button
- [ ] 5.6 Update InstanceList to show health status and recreate button
## 6. Quality Gates
- [ ] 6.1 Run Python syntax check
- [ ] 6.2 Run frontend typecheck
- [ ] 6.3 Run frontend lint
- [ ] 6.4 Test stop confirmation dialog
- [ ] 6.5 Test delete state update
- [ ] 6.6 Test tunnel recreation
- [ ] 6.7 Commit and push changes