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:
@@ -20,6 +20,7 @@ export interface ToolType {
|
||||
dockerfile_template: string | null;
|
||||
build_context: Record<string, string> | null;
|
||||
readiness_probe: ReadinessProbe | null;
|
||||
startup_command: string | null;
|
||||
required_variables: string[];
|
||||
created_by_id: string | null;
|
||||
created_at: string;
|
||||
@@ -39,6 +40,7 @@ export interface CreateToolTypeRequest {
|
||||
dockerfile_template?: string;
|
||||
build_context?: Record<string, string>;
|
||||
readiness_probe?: ReadinessProbe;
|
||||
startup_command?: string;
|
||||
required_variables: string[];
|
||||
}
|
||||
|
||||
@@ -54,6 +56,7 @@ export interface UpdateToolTypeRequest {
|
||||
dockerfile_template?: string;
|
||||
build_context?: Record<string, string>;
|
||||
readiness_probe?: ReadinessProbe;
|
||||
startup_command?: string;
|
||||
required_variables?: string[];
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ export const ToolWorkshopPage = () => {
|
||||
readiness_timeout: "30",
|
||||
readiness_interval: "2",
|
||||
required_variables: "",
|
||||
startup_command: "",
|
||||
});
|
||||
const [toolTypeError, setToolTypeError] = useState<string | null>(null);
|
||||
const [toolTypeDirty, setToolTypeDirty] = useState(false);
|
||||
@@ -131,6 +132,7 @@ export const ToolWorkshopPage = () => {
|
||||
readiness_timeout: "30",
|
||||
readiness_interval: "2",
|
||||
required_variables: "",
|
||||
startup_command: "",
|
||||
});
|
||||
setToolTypeError(null);
|
||||
setToolTypeDirty(false);
|
||||
@@ -152,6 +154,7 @@ export const ToolWorkshopPage = () => {
|
||||
readiness_timeout: toolType.readiness_probe?.timeout?.toString() || "30",
|
||||
readiness_interval: toolType.readiness_probe?.interval?.toString() || "2",
|
||||
required_variables: toolType.required_variables?.join(", ") || "",
|
||||
startup_command: toolType.startup_command || "",
|
||||
});
|
||||
setToolTypeError(null);
|
||||
setToolTypeDirty(false);
|
||||
@@ -250,6 +253,7 @@ export const ToolWorkshopPage = () => {
|
||||
dockerfile_template: toolTypeForm.definition_type === "dockerfile" ? template : undefined,
|
||||
readiness_probe: readinessProbe,
|
||||
required_variables: variables,
|
||||
startup_command: toolTypeForm.startup_command.trim() || undefined,
|
||||
};
|
||||
const newTool = await createToolType(input);
|
||||
setIsCreating(false);
|
||||
@@ -268,6 +272,7 @@ export const ToolWorkshopPage = () => {
|
||||
dockerfile_template: toolTypeForm.definition_type === "dockerfile" ? template : undefined,
|
||||
readiness_probe: readinessProbe,
|
||||
required_variables: variables,
|
||||
startup_command: toolTypeForm.startup_command.trim() || undefined,
|
||||
};
|
||||
await updateToolType(selectedToolType.id, input);
|
||||
setToolTypeDirty(false);
|
||||
@@ -772,6 +777,24 @@ export const ToolWorkshopPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{toolTypeForm.interface_type === "terminal" && (
|
||||
<div className="form-group">
|
||||
<label htmlFor="tool-type-startup-command">Startup Command</label>
|
||||
<input
|
||||
id="tool-type-startup-command"
|
||||
type="text"
|
||||
value={toolTypeForm.startup_command}
|
||||
onChange={(e) => {
|
||||
setToolTypeForm({ ...toolTypeForm, startup_command: e.target.value });
|
||||
setToolTypeDirty(true);
|
||||
}}
|
||||
placeholder="e.g., cd /workspace && ls"
|
||||
className="form-input"
|
||||
/>
|
||||
<small className="form-help">Command to run before the interactive shell for each new terminal session.</small>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{toolTypeForm.requires_port && (
|
||||
<div className="form-group">
|
||||
<label htmlFor="tool-type-default-port">Default Port *</label>
|
||||
|
||||
Reference in New Issue
Block a user