feat: terminal startup command and container tools
- Add startup_command field to ToolType model and API - Execute startup command before interactive shell in terminal sessions - Add tmux and ranger to OpenCode container spec - Update Tool Workshop UI with startup_command input for terminal types - Add backend tests for startup_command CRUD operations - Sync specs: tool-terminal, tool-types-definition, opencode-web-server - New spec: tool-terminal-startup-command Quality gates: Frontend typecheck/lint passed. Backend tests blocked by environment (Python/Docker not available). OpenSpec: terminal-startup-and-container-tools
This commit is contained in:
@@ -9,6 +9,8 @@ The system SHALL configure OpenCode containers to run a web server accessible on
|
||||
- **WHEN** the container starts
|
||||
- **THEN** a web server is running on port 3000 inside the container
|
||||
- **AND** the server serves a web terminal interface
|
||||
- **AND** the container has `tmux` installed
|
||||
- **AND** the container has `ranger` installed
|
||||
|
||||
### Requirement: OpenCode exposes web interface
|
||||
|
||||
@@ -37,3 +39,4 @@ The system SHALL serve a functional web terminal interface for OpenCode.
|
||||
- **WHEN** the user clicks the "Open" button
|
||||
- **THEN** a new tab opens with the OpenCode web interface
|
||||
- **AND** the interface shows a terminal connected to the OpenCode process
|
||||
- **AND** the user can run `tmux` and `ranger` commands
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Terminal Startup Command Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Allow tool type authors to define a startup command that executes for each new terminal session.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Terminal tool types can define a startup command
|
||||
|
||||
The system SHALL allow tool types to specify a `startup_command` that runs before the interactive shell for each new terminal session.
|
||||
|
||||
#### Scenario: Tool type with startup command
|
||||
- **GIVEN** a tool type with `interface_type` = "terminal" and `startup_command` = "cd /workspace && ls"
|
||||
- **WHEN** a user opens a terminal session to an instance of this tool type
|
||||
- **THEN** the startup command executes before the interactive shell starts
|
||||
- **AND** the user sees the output of the startup command in the terminal
|
||||
|
||||
#### Scenario: Tool type without startup command
|
||||
- **GIVEN** a tool type with `interface_type` = "terminal" and no `startup_command`
|
||||
- **WHEN** a user opens a terminal session
|
||||
- **THEN** the interactive shell starts immediately without any startup execution
|
||||
|
||||
#### Scenario: Startup command failure does not block shell
|
||||
- **GIVEN** a tool type with `startup_command` = "exit 1"
|
||||
- **WHEN** a user opens a terminal session
|
||||
- **THEN** the startup command runs and fails
|
||||
- **AND** the interactive shell still starts afterward
|
||||
|
||||
### Requirement: Startup command is stored on the tool type
|
||||
|
||||
The system SHALL persist `startup_command` as a field on the `tool_types` table.
|
||||
|
||||
#### Scenario: Create tool type with startup command
|
||||
- **GIVEN** a user creating a tool type
|
||||
- **WHEN** they provide `startup_command` = "source /etc/profile"
|
||||
- **THEN** the tool type is created with the startup command stored
|
||||
|
||||
#### Scenario: Update tool type startup command
|
||||
- **GIVEN** an existing tool type with a startup command
|
||||
- **WHEN** an admin updates `startup_command` to a new value
|
||||
- **THEN** the tool type is updated
|
||||
- **AND** new terminal sessions use the updated startup command
|
||||
|
||||
### Requirement: Startup command is optional
|
||||
|
||||
The system SHALL treat `startup_command` as an optional field on tool types.
|
||||
|
||||
#### Scenario: Create tool type without startup command
|
||||
- **GIVEN** a user creating a terminal tool type
|
||||
- **WHEN** they omit `startup_command`
|
||||
- **THEN** the tool type is created successfully
|
||||
- **AND** terminal sessions start normally without a startup command
|
||||
|
||||
## Dependencies
|
||||
|
||||
- tool-types-definition (model and API)
|
||||
- tool-terminal (session execution)
|
||||
|
||||
## Quality Gates
|
||||
|
||||
- `pytest` must pass
|
||||
- `mypy .` must pass
|
||||
- `ruff check .` must pass
|
||||
- `npm run typecheck` must pass
|
||||
- `npm run lint` must pass
|
||||
@@ -16,6 +16,19 @@ The system SHALL provide terminal sessions via WebSocket.
|
||||
- THEN a WebSocket connection is established
|
||||
- AND a shell is spawned in the container via `docker exec`
|
||||
|
||||
#### Scenario: Open terminal with startup command
|
||||
- GIVEN a running tool instance with a tool type that has `startup_command` set
|
||||
- WHEN the user opens the terminal
|
||||
- THEN a WebSocket connection is established
|
||||
- AND the startup command is executed before the interactive shell
|
||||
- AND the shell is spawned in the container via `docker exec`
|
||||
|
||||
#### Scenario: Open terminal without startup command
|
||||
- GIVEN a running tool instance with a tool type that has no `startup_command`
|
||||
- WHEN the user opens the terminal
|
||||
- THEN a WebSocket connection is established
|
||||
- AND the shell spawns directly without any startup execution
|
||||
|
||||
### Requirement: Terminal I/O
|
||||
|
||||
The system SHALL stream terminal I/O via WebSocket.
|
||||
@@ -51,6 +64,12 @@ The system SHALL manage terminal sessions.
|
||||
- THEN the session is cleaned up
|
||||
- AND the shell process is terminated
|
||||
|
||||
#### Scenario: Reset terminal session runs startup command
|
||||
- GIVEN an active terminal session
|
||||
- WHEN the user resets the session
|
||||
- THEN a new shell is spawned
|
||||
- AND the startup command executes before the new interactive shell
|
||||
|
||||
### Requirement: Access Control
|
||||
|
||||
The system SHALL restrict terminal access.
|
||||
|
||||
@@ -18,6 +18,7 @@ The system SHALL provide a `ToolType` model to store tool definitions.
|
||||
- `dockerfile_template`: Dockerfile string
|
||||
- `definition_type`: string — "compose" or "dockerfile"
|
||||
- `required_variables`: list of required template variables
|
||||
- `startup_command`: optional text — command to run before interactive shell for terminal sessions
|
||||
- `is_builtin`: boolean flag for system-defined types
|
||||
- `created_at`/`updated_at`: timestamps
|
||||
|
||||
@@ -39,6 +40,7 @@ The system SHALL provide REST API endpoints for tool type management.
|
||||
- AND validates `requires_port` is boolean
|
||||
- AND validates the compose template YAML (if definition_type is "compose")
|
||||
- AND validates all required variables are present in template
|
||||
- AND accepts optional `startup_command` field
|
||||
- AND returns 201 Created with the new tool type
|
||||
|
||||
#### Scenario: Get tool type
|
||||
@@ -51,10 +53,14 @@ The system SHALL provide REST API endpoints for tool type management.
|
||||
- GIVEN an admin user
|
||||
- WHEN they PUT /api/tool-types/{id} with valid data
|
||||
- THEN the system updates the tool type
|
||||
- AND validates `interface_type` is "web" or "terminal" if provided
|
||||
- AND re-validates the compose template
|
||||
- AND accepts optional `startup_command` field
|
||||
- AND returns 200 OK with updated tool type
|
||||
|
||||
#### Scenario: Get tool type includes startup command
|
||||
- GIVEN an authenticated user
|
||||
- WHEN they GET /api/tool-types/{id}
|
||||
- THEN the response includes `startup_command` if set
|
||||
|
||||
#### Scenario: Delete tool type
|
||||
- GIVEN an admin user
|
||||
- WHEN they DELETE /api/tool-types/{id}
|
||||
|
||||
Reference in New Issue
Block a user