Add multiple terminals per task and saved commands that start one

This commit is contained in:
Ian Gulliver
2026-10-21 08:59:03 -07:00
parent fe2a2022c3
commit d062d7ccae
15 changed files with 1418 additions and 450 deletions
+132 -5
View File
@@ -150,6 +150,60 @@ paths:
description: Deleted.
"404": { $ref: "#/components/responses/Error" }
/api/me/commands:
get:
operationId: listSavedCommands
description: >
The calling user's saved commands on this server, by name. Each starts a terminal in a task that runs it.
command.saved and command.deleted events tell the user's clients of changes.
responses:
"200":
description: The saved commands.
content:
application/json:
schema:
type: array
items: { $ref: "#/components/schemas/SavedCommand" }
post:
operationId: createSavedCommand
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/SavedCommandSave" }
responses:
"201":
description: The saved command.
content:
application/json:
schema: { $ref: "#/components/schemas/SavedCommand" }
"400": { $ref: "#/components/responses/Error" }
/api/me/commands/{commandId}:
parameters:
- { name: commandId, in: path, required: true, schema: { type: string } }
put:
operationId: updateSavedCommand
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/SavedCommandSave" }
responses:
"200":
description: The saved command.
content:
application/json:
schema: { $ref: "#/components/schemas/SavedCommand" }
"400": { $ref: "#/components/responses/Error" }
"404": { $ref: "#/components/responses/Error" }
delete:
operationId: deleteSavedCommand
responses:
"204":
description: Deleted.
"404": { $ref: "#/components/responses/Error" }
/api/me/focus:
get:
operationId: getFocus
@@ -717,16 +771,54 @@ paths:
"404": { $ref: "#/components/responses/Error" }
"409": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/terminal:
/api/tasks/{taskId}/terminals:
parameters:
- { name: taskId, in: path, required: true, schema: { type: string } }
get:
operationId: listTaskTerminals
description: >
The task's running terminals, login shells in its worktree, oldest first. A terminals.changed event with the
task's id is broadcast whenever one starts or ends.
responses:
"200":
description: The terminals.
content:
application/json:
schema:
type: array
items: { $ref: "#/components/schemas/TaskTerminal" }
"404": { $ref: "#/components/responses/Error" }
"409": { $ref: "#/components/responses/Error" }
post:
operationId: startTaskTerminal
description: >
Starts a terminal in the task's worktree. With command_id, the calling user's saved command is typed into it
once the shell is ready, and the terminal takes the command's name; otherwise it is named Shell.
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/TerminalStart" }
responses:
"201":
description: The terminal started.
content:
application/json:
schema: { $ref: "#/components/schemas/TaskTerminal" }
"404": { $ref: "#/components/responses/Error" }
"409": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/terminals/{terminalId}:
parameters:
- { name: taskId, in: path, required: true, schema: { type: string } }
- { name: terminalId, in: path, required: true, schema: { type: string } }
get:
operationId: getTaskTerminal
description: >
A WebSocket attached to the task's terminal, a login shell in its worktree, started at cols by rows if none is
running. The server first sends what the terminal has recently printed, then its output as it comes, all as
binary messages. The client sends input as binary messages and resizes as text messages holding a
TerminalSize. When the shell exits the server closes with code 4000 and the exit status as the reason.
A WebSocket attached to one of the task's terminals, resized to cols by rows. The server first sends what the
terminal has recently printed, then its output as it comes, all as binary messages. The client sends input as
binary messages and resizes as text messages holding a TerminalSize. When the shell exits the server closes
with code 4000 and the exit status as the reason.
parameters:
- { name: cols, in: query, required: true, schema: { type: integer, minimum: 1 } }
- { name: rows, in: query, required: true, schema: { type: integer, minimum: 1 } }
@@ -736,6 +828,13 @@ paths:
"400": { $ref: "#/components/responses/Error" }
"404": { $ref: "#/components/responses/Error" }
"409": { $ref: "#/components/responses/Error" }
delete:
operationId: closeTaskTerminal
description: Hangs up the terminal's shell.
responses:
"204":
description: Closed.
"404": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/previews:
parameters:
@@ -1980,6 +2079,34 @@ components:
cols: { type: integer, minimum: 1 }
rows: { type: integer, minimum: 1 }
TaskTerminal:
type: object
required: [id, name, started_at]
properties:
id: { type: string }
name: { type: string, description: "Shell, or the name of the saved command it was started with." }
started_at: { type: string, format: date-time }
TerminalStart:
type: object
properties:
command_id: { type: string, description: "A saved command of the calling user's to run in it." }
SavedCommand:
type: object
required: [id, name, command]
properties:
id: { type: string }
name: { type: string }
command: { type: string, description: "The line typed into the new terminal's shell." }
SavedCommandSave:
type: object
required: [name, command]
properties:
name: { type: string, minLength: 1 }
command: { type: string, minLength: 1 }
Permission:
type: object
required: [name, status, detail, settings]