Sending SIGWINCH to the docker exec process was crashing/killing it,
which closed the PTY and caused WebSocket 1006 abnormal closure loops.
Reverting to the original TIOCSWINSZ-only approach.
When resizing the PTY, docker exec needs to be notified so it can
re-read the terminal size and propagate it to the container's PTY.
Without this, the container shell stays at 80x24 regardless of what
the frontend sends.
TerminalManager was trying to create an asyncio task at module import time,
but no event loop exists yet during import. This caused RuntimeError on startup.
Changes:
- _start_idle_check() now checks if event loop is running before creating task
- If no loop exists, silently skips (will be started lazily)
- Added lazy start call in get_or_create_session() when websocket connects
- Backend: Send ping every 30s from WebSocket endpoint
- Frontend: Respond to pings with pongs, detect missed pings (60s timeout)
- Update type definitions to include 'resetting' status
Refs: persistent-terminal-sessions task 6.4
- Terminal sessions now persist across WebSocket disconnections
- Added circular output buffer (10KB) for replay on reconnect
- Added idle timeout cleanup (30 minutes)
- Added reset functionality via WebSocket message and HTTP endpoint
- Concurrent connections close old WebSocket when new one connects
- Frontend: Added reset button with confirmation dialog
- Frontend: Handle resetting status and reconnection
Refs: persistent-terminal-sessions
- Add safety check after rendering compose template to ensure REPO_PATH is mounted
- If compose template lacks volume mount, auto-add default mount to /workspace
- Add cloned repo verification to catch empty clone directories
Refs: clone mode repo not appearing in container workspace
Backend:
- Add created_at to get_user_sessions response
Frontend:
- Hide tunnel error badges, probe output, and 'Recreate Tunnel' button for terminal-only sessions
- Show session start time (created_at) in active sessions list
- Show repository configuration (clone_mode, branch) for each session
- Skip health check polling for terminal-only sessions
- Update Session type to include created_at field
- Create merge migration f3d2dc90ba3a to merge single_interface and clone_mode heads
- Make remove_is_builtin migration idempotent with IF EXISTS clause
Refs: alembic migration fix for dev branch
Git branch -a --format=%(refname:short) returns remote branches as
'origin/branch-name', not 'remotes/origin/branch-name'. The code was
only filtering 'remotes/' prefix, causing clone to fail with branch
names like 'origin/feat/foo'.
Now properly detects remote names using 'git remote' and strips the
remote prefix (e.g., 'origin/') from branch names.
Resolved conflicts:
- Moved branch selection UI from inline sessions.tsx to CreateSessionForm component
- Integrated branch dropdown and new branch creation into CreateSessionForm
- Removed duplicate branch state management from sessions.tsx
All branch selection tests pass (7/7).
- Add new_branch field to CreateInstanceRequest
- Run git checkout -b after cloning when new_branch is provided
- Store new branch name in ToolInstance record
- Drop is_builtin column from tool_types table
- Remove built-in tool seeding from startup
- Remove is_builtin from API schemas and frontend types
- Update tool-types spec to reflect removal of built-in concept
- Add Alembic migration for column removal
- Update tests to work without built-in distinction
Remove 500-character truncation on probe output so users can see
all attempts including the final successful one. Add probe status
indicator (passed/failed/pending) that's always visible when probe
data exists.
The backend was returning 'tool_type_interface_type' (string) but the
frontend expected 'tool_type_interfaces' (array). This caused
undefined.includes() crash when clicking Open on terminal sessions.
Changed both list_instances and get_user_sessions to return
tool_type_interfaces as an array. Also added clone_mode and branch
to get_user_sessions response.
For terminal-only tools like OpenCode, default_port is 0 which is falsy
in Python. The code incorrectly treated port 0 as 'not configured' and
marked the instance as error. Now we only check if tool_type exists,
and default to port 0. Terminal tools skip tunnel creation anyway.
For terminal-only tools (no URL), only check container status for
overall health instead of requiring tunnel health. Terminal tools
do not have tunnels, so tunnel_status stays as 'not_applicable'
which was failing the healthy check.
- POST /ssh-keys/{id}/sign - sign payload with Ed25519 private key
- POST /ssh-keys/{id}/verify - verify signature with public key
- Returns base64-encoded signatures
- Add clone_mode and branch fields to tool_instances
- Add ssh_key_id to git_repositories for per-repo SSH key assignment
- Implement host-side git cloning with branch selection (default: main)
- Mount SSH keys into containers for git operations in clone mode
- Add dirty state check on clone-mode instance deletion with confirmation
- Update SessionsPage with mount/clone selector, branch input, SSH key display
- Add SSH key selector to repository creation form
- Add dirty delete confirmation modal with changed files list
- Update API schemas and endpoints for new fields
- Sync delta specs to main specs (git-repo, tool-instances, repo-clone-mode)
- Archive completed OpenSpec change: repo-clone-mode-with-ssh
- Document git requirement for custom tool types
Quality gates: Frontend typecheck and build passed
OpenSpec: repo-clone-mode-with-ssh archived with all tasks complete
- Replace interfaces array with interface_type string and requires_port boolean
- Add database migration for schema change
- Update backend model, API schemas, and validation
- Update frontend types and tool workshop UI
- Add dropdown for interface type selection
- Conditionally show/hide port fields based on requires_port
- Update tests and mock data
- All frontend tests pass (37/37)
- Frontend typecheck and lint pass
Adds probe_result JSON column to tool_instances table.
This column stores readiness probe results and was added to the
model but the migration was missing.
- git-repo-working-clones: Complete remaining test task
- opencode-web-terminal: Add port validation tests, fix model validator
- session-management-fixes: Mark frontend tasks as complete (already implemented)
All in-progress changes now complete.
- Fall back to symbolic-ref when checkout --orphan fails on bare repos\n- Fall back to symbolic-ref when checkout fails on bare repos\n- Make get_current_branch handle bare repos with unborn branches\n- Add integration tests for bare repo branch operations\n\nQuality gates: pytest integration tests (12 passed)
- Add new status badges: starting, probing, unhealthy
- Show tunnel error only when tunnel_status is unreachable
- Show app error badge with status code for error_response
- Add collapsible probe output section for diagnostics
- Update health polling to check all active instances
- Only show Recreate Tunnel button for unreachable tunnels
- Add POST /tool-types/validate endpoint for pre-creation validation
- Add ToolConfigUpdate model with optional fields for PUT endpoint
- Fix tool_configs POST to return 201 status code
- Fix tool_configs list endpoint to return list instead of dict
- Fix tool_configs defaults endpoint to return 'suggested_configs'
- Fix tool_types create endpoint to include category and interfaces
- Add model_validator to enforce dockerfile/compose template requirements
- Update tests to match API response format