diff --git a/openapi-git-spec.json b/openapi-git-spec.json deleted file mode 100644 index 3a8d660..0000000 --- a/openapi-git-spec.json +++ /dev/null @@ -1,1348 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Git API", - "description": "API for interacting with Git version control in sandboxes", - "version": "1.0.0" - }, - "paths": { - "/git/status": { - "post": { - "summary": "Get git status", - "description": "Retrieve the current git status of the repository", - "operationId": "gitStatus", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitStatus" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving git status", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/remotes": { - "post": { - "summary": "Get git remotes", - "description": "Retrieve the remote repositories configured for the git repository", - "operationId": "gitRemotes", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitRemotes" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving git remotes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/targetDiff": { - "post": { - "summary": "Get target diff", - "description": "Retrieve the difference between the current branch and a target branch", - "operationId": "gitTargetDiff", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "branch": { - "type": "string", - "description": "Target branch name" - } - }, - "required": ["branch"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitTargetDiff" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving target diff", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/pull": { - "post": { - "summary": "Pull changes", - "description": "Pull changes from the remote repository", - "operationId": "gitPull", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "branch": { - "type": "string", - "description": "Branch to pull from" - }, - "force": { - "type": "boolean", - "description": "Force pull" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error pulling changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/discard": { - "post": { - "summary": "Discard changes", - "description": "Discard changes to specified paths or all changes", - "operationId": "gitDiscard", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths to discard changes for" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths that were discarded" - } - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error discarding changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/commit": { - "post": { - "summary": "Commit changes", - "description": "Commit changes to the local repository", - "operationId": "gitCommit", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths to commit" - }, - "message": { - "type": "string", - "description": "Commit message" - }, - "push": { - "type": "boolean", - "description": "Whether to push after committing" - } - }, - "required": ["message"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "shellId": { - "type": "string", - "description": "ID of the shell process" - } - }, - "required": ["shellId"] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error committing changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/push": { - "post": { - "summary": "Push changes", - "description": "Push changes to the remote repository", - "operationId": "gitPush", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error pushing changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/pushToRemote": { - "post": { - "summary": "Push to remote", - "description": "Push changes to a specific remote repository and branch", - "operationId": "gitPushToRemote", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "URL of the remote repository" - }, - "branch": { - "type": "string", - "description": "Branch to push to" - }, - "squashAllCommits": { - "type": "boolean", - "description": "Whether to squash all commits before pushing" - } - }, - "required": ["url", "branch"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error pushing to remote", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/renameBranch": { - "post": { - "summary": "Rename branch", - "description": "Rename a branch in the local repository", - "operationId": "gitRenameBranch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "oldBranch": { - "type": "string", - "description": "Name of the branch to rename" - }, - "newBranch": { - "type": "string", - "description": "New name for the branch" - } - }, - "required": ["oldBranch", "newBranch"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error renaming branch", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/remoteContent": { - "post": { - "summary": "Get remote content", - "description": "Retrieve the content of a file from a remote branch or commit", - "operationId": "gitRemoteContent", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GitRemoteParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Content of the file" - } - }, - "required": ["content"] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving remote content", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/diffStatus": { - "post": { - "summary": "Get diff status", - "description": "Retrieve the status of changes between two references", - "operationId": "gitDiffStatus", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GitDiffStatusParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitDiffStatusResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving diff status", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/resetLocalWithRemote": { - "post": { - "summary": "Reset local with remote", - "description": "Reset the local repository to match the remote", - "operationId": "gitResetLocalWithRemote", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error resetting local with remote", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/checkoutInitialBranch": { - "post": { - "summary": "Checkout initial branch", - "description": "Checkout the initial branch of the repository", - "operationId": "gitCheckoutInitialBranch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error checking out initial branch", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/transposeLines": { - "post": { - "summary": "Transpose lines", - "description": "Map line numbers between different git commits", - "operationId": "gitTransposeLines", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "sha": { - "type": "string", - "description": "Commit SHA" - }, - "path": { - "type": "string", - "description": "File path" - }, - "line": { - "type": "number", - "description": "Line number" - } - }, - "required": ["sha", "path", "line"] - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path" - }, - "line": { - "type": "number", - "description": "Line number" - } - }, - "required": ["path", "line"], - "nullable": true - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error transposing lines", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "CommonError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data", - "nullable": true - } - }, - "required": ["code", "message"] - }, - "GitStatusShortFormat": { - "type": "string", - "enum": ["", "M", "A", "D", "R", "C", "U", "?"], - "description": "Git status short format codes" - }, - "GitItem": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path" - }, - "index": { - "$ref": "#/components/schemas/GitStatusShortFormat" - }, - "workingTree": { - "$ref": "#/components/schemas/GitStatusShortFormat" - }, - "isStaged": { - "type": "boolean", - "description": "Whether the file is staged" - }, - "isConflicted": { - "type": "boolean", - "description": "Whether the file has conflicts" - }, - "fileId": { - "type": "string", - "description": "File ID" - } - }, - "required": ["path", "index", "workingTree", "isStaged", "isConflicted"] - }, - "GitChangedFiles": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/GitItem" - }, - "description": "Map of file IDs to GitItems" - }, - "GitBranchProperties": { - "type": "object", - "properties": { - "head": { - "type": "string", - "nullable": true, - "description": "Head commit" - }, - "branch": { - "type": "string", - "nullable": true, - "description": "Branch name" - }, - "ahead": { - "type": "number", - "description": "Number of commits ahead" - }, - "behind": { - "type": "number", - "description": "Number of commits behind" - }, - "safe": { - "type": "boolean", - "description": "Whether the branch is safe to use" - } - }, - "required": ["ahead", "behind", "safe"] - }, - "GitCommit": { - "type": "object", - "properties": { - "hash": { - "type": "string", - "description": "Commit hash" - }, - "date": { - "type": "string", - "description": "Commit date" - }, - "message": { - "type": "string", - "description": "Commit message" - }, - "author": { - "type": "string", - "description": "Commit author" - } - }, - "required": ["hash", "date", "message", "author"] - }, - "GitStatus": { - "type": "object", - "properties": { - "changedFiles": { - "$ref": "#/components/schemas/GitChangedFiles" - }, - "deletedFiles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitItem" - } - }, - "conflicts": { - "type": "boolean", - "description": "Whether there are remote conflicts" - }, - "localChanges": { - "type": "boolean", - "description": "Whether there are local changes" - }, - "remote": { - "$ref": "#/components/schemas/GitBranchProperties" - }, - "target": { - "$ref": "#/components/schemas/GitBranchProperties" - }, - "head": { - "type": "string", - "description": "Current HEAD commit" - }, - "commits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitCommit" - } - }, - "branch": { - "type": "string", - "nullable": true, - "description": "Current branch name" - }, - "isMerging": { - "type": "boolean", - "description": "Whether a merge is in progress" - } - }, - "required": [ - "changedFiles", - "deletedFiles", - "conflicts", - "localChanges", - "remote", - "target", - "commits", - "branch", - "isMerging" - ] - }, - "GitTargetDiff": { - "type": "object", - "properties": { - "ahead": { - "type": "number", - "description": "Number of commits ahead of target" - }, - "behind": { - "type": "number", - "description": "Number of commits behind target" - }, - "commits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitCommit" - } - } - }, - "required": ["ahead", "behind", "commits"] - }, - "GitRemotes": { - "type": "object", - "properties": { - "origin": { - "type": "string", - "description": "Origin remote URL" - }, - "upstream": { - "type": "string", - "description": "Upstream remote URL" - } - }, - "required": ["origin", "upstream"] - }, - "GitRemoteParams": { - "type": "object", - "properties": { - "reference": { - "type": "string", - "description": "Branch or commit hash" - }, - "path": { - "type": "string", - "description": "File path" - } - }, - "required": ["reference", "path"] - }, - "GitDiffStatusParams": { - "type": "object", - "properties": { - "base": { - "type": "string", - "description": "Base reference for diffing" - }, - "head": { - "type": "string", - "description": "Head reference for diffing" - } - }, - "required": ["base", "head"] - }, - "GitDiffStatusItem": { - "type": "object", - "properties": { - "status": { - "$ref": "#/components/schemas/GitStatusShortFormat" - }, - "path": { - "type": "string", - "description": "File path" - }, - "oldPath": { - "type": "string", - "description": "Original file path (for renames)" - }, - "hunks": { - "type": "array", - "items": { - "type": "object", - "properties": { - "original": { - "type": "object", - "properties": { - "start": { - "type": "number" - }, - "end": { - "type": "number" - } - }, - "required": ["start", "end"] - }, - "modified": { - "type": "object", - "properties": { - "start": { - "type": "number" - }, - "end": { - "type": "number" - } - }, - "required": ["start", "end"] - } - }, - "required": ["original", "modified"] - } - } - }, - "required": ["status", "path", "hunks"] - }, - "GitDiffStatusResult": { - "type": "object", - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitDiffStatusItem" - } - } - }, - "required": ["files"] - } - } - } -} diff --git a/openapi-git.json b/openapi-git.json deleted file mode 100644 index e69de29..0000000 diff --git a/openapi-pint.json b/openapi-pint.json new file mode 100644 index 0000000..d67d824 --- /dev/null +++ b/openapi-pint.json @@ -0,0 +1,1255 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Pint API", + "description": "Pint (formerly Sandbox Agent) is a Go CLI tool that exposes REST API endpoints for file operations, terminal management, and task execution, designed to enable building code editor applications similar to VSCode.\n\nThe application uses file-based authentication with admin and readonly tokens, supporting CodeSandbox-compatible task management with robust workspace isolation.\n\nSupports Server-Sent Events (SSE) for real-time updates by passing `Accept: text/event-stream` header.", + "version": "1.0.0", + "contact": { + "name": "CodeSandbox", + "url": "https://codesandbox.io" + }, + "license": { + "name": "MIT" + } + }, + "servers": [ + { + "url": "http://localhost:57468", + "description": "Default development server" + }, + { + "url": "http://localhost:{port}", + "description": "Custom port server", + "variables": { + "port": { + "default": "57468", + "description": "Custom port number" + } + } + } + ], + "security": [ + { + "bearerAuth": [] + }, + { + "tokenAuth": [] + }, + { + "queryToken": [] + } + ], + "paths": { + "/health": { + "get": { + "summary": "Health check endpoint", + "description": "Returns the health status of the server", + "security": [], + "responses": { + "200": { + "description": "Server is healthy", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "ok" + } + } + } + } + } + } + } + } + }, + "/api/fs/events": { + "get": { + "summary": "Watch filesystem events", + "description": "Watch filesystem changes matching a glob pattern. Use SSE for real-time events.", + "parameters": [ + { + "name": "glob", + "in": "header", + "required": true, + "description": "Glob pattern for files to watch", + "schema": { + "type": "string" + }, + "example": "**/*.js" + } + ], + "responses": { + "200": { + "description": "File system events", + "content": { + "text/event-stream": { + "schema": { + "type": "string", + "description": "Server-sent events containing filesystem changes", + "example": "data: {\"type\":\"create\",\"path\":\"/workspace/file.js\",\"timestamp\":\"2024-01-15T10:30:45Z\"}\n\n" + } + }, + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "example": "Filesystem watcher started" + } + } + } + } + } + } + } + } + }, + "/api/fs/stats/{path}": { + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "description": "File or directory path", + "schema": { + "type": "string" + }, + "example": "/workspace/src/main.go" + } + ], + "get": { + "summary": "Get file or directory stats", + "description": "Get filesystem statistics for a file or directory", + "responses": { + "200": { + "description": "File stats retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FileStats" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/fs/files/{path}": { + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "description": "File path", + "schema": { + "type": "string" + }, + "example": "/workspace/src/main.go" + } + ], + "get": { + "summary": "Read file contents", + "description": "Read file contents. Use SSE for chunked reading of large files.", + "responses": { + "200": { + "description": "File contents", + "content": { + "text/plain": { + "schema": { + "type": "string", + "example": "package main\n\nfunc main() {\n\tfmt.Println(\"Hello World\")\n}" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "File content streamed in chunks", + "example": "data: {\"chunk\":\"package main\\n\",\"offset\":0,\"total\":1024}\n\n" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "put": { + "summary": "Write to file", + "description": "Write content to file or perform file operations", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["operation"], + "properties": { + "operation": { + "type": "string", + "enum": ["write", "moveFrom", "copyFrom"], + "description": "File operation to perform" + }, + "content": { + "type": "string", + "description": "File content (for write operation)", + "example": "package main\n\nfunc main() {\n\tfmt.Println(\"Hello World\")\n}" + }, + "source": { + "type": "string", + "description": "Source path (for moveFrom/copyFrom operations)", + "example": "/workspace/src/old_file.go" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "File operation completed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FileOperationResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + } + } + }, + "delete": { + "summary": "Delete file", + "description": "Delete a file", + "responses": { + "200": { + "description": "File deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FileDeleteResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/directories/{path}": { + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "description": "Directory path", + "schema": { + "type": "string" + }, + "example": "/workspace/src" + } + ], + "post": { + "summary": "Create directory", + "description": "Create a new directory", + "responses": { + "201": { + "description": "Directory created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DirectoryCreateResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + } + } + }, + "get": { + "summary": "List directory contents", + "description": "List files and subdirectories in a directory", + "responses": { + "200": { + "description": "Directory contents", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DirectoryListResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "summary": "Delete directory", + "description": "Delete a directory and all its contents", + "responses": { + "200": { + "description": "Directory deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DirectoryDeleteResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/terminals": { + "get": { + "summary": "List terminals", + "description": "Get list of all terminals. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Terminal list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TerminalListResponse" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time terminal list updates", + "example": "data: {\"terminals\":[{\"id\":\"term_123\",\"status\":\"running\",\"pid\":1234}]}\n\n" + } + } + } + } + } + }, + "post": { + "summary": "Create new terminal", + "description": "Create a new terminal instance", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["command"], + "properties": { + "command": { + "type": "string", + "description": "Command to execute", + "example": "bash" + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Command arguments", + "example": ["-l"] + }, + "workingDir": { + "type": "string", + "description": "Working directory", + "example": "/workspace" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Terminal created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TerminalCreateResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + } + } + } + }, + "/api/terminals/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Terminal ID", + "schema": { + "type": "string" + }, + "example": "term_123" + } + ], + "get": { + "summary": "Get terminal state", + "description": "Get terminal information and state. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Terminal state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TerminalResponse" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time terminal state updates", + "example": "data: {\"id\":\"term_123\",\"status\":\"running\",\"pid\":1234}\n\n" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "summary": "Delete terminal", + "description": "Delete a terminal and kill its process", + "responses": { + "200": { + "description": "Terminal deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TerminalDeleteResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/terminals/{id}/stdout": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Terminal ID", + "schema": { + "type": "string" + }, + "example": "term_123" + } + ], + "get": { + "summary": "Get terminal stdout", + "description": "Get terminal stdout output. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Terminal stdout", + "content": { + "text/plain": { + "schema": { + "type": "string", + "example": "$ echo hello\nhello\n" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time stdout updates", + "example": "data: {\"output\":\"hello\\n\",\"timestamp\":\"2024-01-15T10:30:45Z\"}\n\n" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/terminals/{id}/stderr": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Terminal ID", + "schema": { + "type": "string" + }, + "example": "term_123" + } + ], + "get": { + "summary": "Get terminal stderr", + "description": "Get terminal stderr output. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Terminal stderr", + "content": { + "text/plain": { + "schema": { + "type": "string", + "example": "Error: command not found\n" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time stderr updates", + "example": "data: {\"output\":\"Error: command not found\\n\",\"timestamp\":\"2024-01-15T10:30:45Z\"}\n\n" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/terminals/{id}/stdin": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Terminal ID", + "schema": { + "type": "string" + }, + "example": "term_123" + } + ], + "post": { + "summary": "Send input to terminal", + "description": "Send input to terminal stdin", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["input"], + "properties": { + "input": { + "type": "string", + "description": "Input to send to terminal", + "example": "echo hello\n" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string", + "example": "echo hello\n" + } + } + } + }, + "responses": { + "200": { + "description": "Input sent successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "example": "Input sent to terminal" + } + } + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/tasks": { + "get": { + "summary": "List tasks", + "description": "Get list of all tasks. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Task list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskListResponse" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time task list updates", + "example": "data: {\"tasks\":[{\"id\":\"build\",\"status\":\"running\",\"name\":\"Build App\"}]}\n\n" + } + } + } + } + } + } + }, + "/api/tasks/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Task ID", + "schema": { + "type": "string" + }, + "example": "build" + } + ], + "get": { + "summary": "Get task state", + "description": "Get task information and state. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Task state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskResponse" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time task state updates", + "example": "data: {\"id\":\"build\",\"status\":\"running\",\"progress\":75}\n\n" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/tasks/{id}/run": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Task ID", + "schema": { + "type": "string" + }, + "example": "build" + } + ], + "post": { + "summary": "Run task", + "description": "Start executing a task", + "responses": { + "200": { + "description": "Task started successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskActionResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "description": "Task already running", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/tasks/{id}/stop": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Task ID", + "schema": { + "type": "string" + }, + "example": "build" + } + ], + "post": { + "summary": "Stop task", + "description": "Stop a running task", + "responses": { + "200": { + "description": "Task stopped successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskActionResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "description": "Task not running", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/tasks/{id}/restart": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Task ID", + "schema": { + "type": "string" + }, + "example": "build" + } + ], + "post": { + "summary": "Restart task", + "description": "Restart a task (stop if running, then start)", + "responses": { + "200": { + "description": "Task restarted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskActionResponse" + } + } + } + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/api/state": { + "get": { + "summary": "Get sandbox state", + "description": "Get the current state of the sandbox including version and setup status", + "responses": { + "200": { + "description": "Sandbox state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxState" + } + } + } + } + } + } + }, + "/api/ports": { + "get": { + "summary": "List open ports", + "description": "Get list of open ports. Use SSE for real-time updates.", + "responses": { + "200": { + "description": "Port list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortListResponse" + } + }, + "text/event-stream": { + "schema": { + "type": "string", + "description": "Real-time port updates", + "example": "data: {\"ports\":[{\"port\":3000,\"status\":\"open\",\"process\":\"node\"}]}\n\n" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "description": "Use 'Bearer ' format with admin or readonly token" + }, + "tokenAuth": { + "type": "apiKey", + "in": "header", + "name": "Authorization", + "description": "Use token directly in Authorization header (without 'Bearer' prefix)" + }, + "queryToken": { + "type": "apiKey", + "in": "query", + "name": "token", + "description": "Use token as query parameter (mainly for WebSocket connections)" + } + }, + "responses": { + "BadRequest": { + "description": "Bad request - invalid parameters or request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "NotFound": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "Unauthorized": { + "description": "Unauthorized - authentication required", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "schemas": { + "ErrorResponse": { + "type": "object", + "required": ["error"], + "properties": { + "error": { + "type": "string", + "description": "Error message", + "example": "Resource not found" + } + } + }, + "FileStats": { + "type": "object", + "required": ["name", "path", "isDir", "size", "modTime"], + "properties": { + "name": { + "type": "string", + "description": "File or directory name", + "example": "main.go" + }, + "path": { + "type": "string", + "description": "Full path", + "example": "/workspace/src/main.go" + }, + "isDir": { + "type": "boolean", + "description": "Whether this is a directory", + "example": false + }, + "size": { + "type": "integer", + "format": "int64", + "description": "File size in bytes", + "example": 1024 + }, + "modTime": { + "type": "string", + "format": "date-time", + "description": "Last modification time", + "example": "2024-01-15T10:30:45Z" + }, + "permissions": { + "type": "string", + "description": "File permissions", + "example": "rw-r--r--" + } + } + }, + "FileOperationResponse": { + "type": "object", + "required": ["message", "path", "operation"], + "properties": { + "message": { + "type": "string", + "example": "File operation completed successfully" + }, + "path": { + "type": "string", + "example": "/workspace/src/main.go" + }, + "operation": { + "type": "string", + "enum": ["write", "moveFrom", "copyFrom"], + "example": "write" + }, + "bytesWritten": { + "type": "integer", + "description": "Number of bytes written (for write operation)", + "example": 1024 + } + } + }, + "FileDeleteResponse": { + "type": "object", + "required": ["message", "path"], + "properties": { + "message": { + "type": "string", + "example": "File deleted successfully" + }, + "path": { + "type": "string", + "example": "/workspace/src/main.go" + } + } + }, + "DirectoryCreateResponse": { + "type": "object", + "required": ["message", "path"], + "properties": { + "message": { + "type": "string", + "example": "Directory created successfully" + }, + "path": { + "type": "string", + "example": "/workspace/src" + } + } + }, + "DirectoryListResponse": { + "type": "object", + "required": ["path", "entries"], + "properties": { + "path": { + "type": "string", + "example": "/workspace/src" + }, + "entries": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FileStats" + } + } + } + }, + "DirectoryDeleteResponse": { + "type": "object", + "required": ["message", "path"], + "properties": { + "message": { + "type": "string", + "example": "Directory deleted successfully" + }, + "path": { + "type": "string", + "example": "/workspace/src" + } + } + }, + "TerminalListResponse": { + "type": "object", + "required": ["terminals"], + "properties": { + "terminals": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Terminal" + } + } + } + }, + "TerminalCreateResponse": { + "type": "object", + "required": ["terminal"], + "properties": { + "terminal": { + "$ref": "#/components/schemas/Terminal" + } + } + }, + "TerminalResponse": { + "type": "object", + "required": ["terminal"], + "properties": { + "terminal": { + "$ref": "#/components/schemas/Terminal" + } + } + }, + "TerminalDeleteResponse": { + "type": "object", + "required": ["message"], + "properties": { + "message": { + "type": "string", + "example": "Terminal deleted successfully" + } + } + }, + "Terminal": { + "type": "object", + "required": ["id", "command", "status", "pid"], + "properties": { + "id": { + "type": "string", + "description": "Terminal ID", + "example": "term_123" + }, + "command": { + "type": "string", + "description": "Command being executed", + "example": "bash" + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Command arguments", + "example": ["-l"] + }, + "status": { + "type": "string", + "enum": ["created", "running", "finished", "error"], + "description": "Terminal status", + "example": "running" + }, + "pid": { + "type": "integer", + "description": "Process ID", + "example": 1234 + }, + "workingDir": { + "type": "string", + "description": "Working directory", + "example": "/workspace" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Creation timestamp", + "example": "2024-01-15T10:30:45Z" + } + } + }, + "TaskListResponse": { + "type": "object", + "required": ["tasks"], + "properties": { + "tasks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Task" + } + } + } + }, + "TaskResponse": { + "type": "object", + "required": ["task"], + "properties": { + "task": { + "$ref": "#/components/schemas/Task" + } + } + }, + "TaskActionResponse": { + "type": "object", + "required": ["message", "task"], + "properties": { + "message": { + "type": "string", + "example": "Task started successfully" + }, + "task": { + "$ref": "#/components/schemas/Task" + } + } + }, + "Task": { + "type": "object", + "required": ["id", "name", "command", "status"], + "properties": { + "id": { + "type": "string", + "description": "Task ID", + "example": "build" + }, + "name": { + "type": "string", + "description": "Task name", + "example": "Build Application" + }, + "command": { + "type": "string", + "description": "Command to execute", + "example": "npm run build" + }, + "status": { + "type": "string", + "enum": ["idle", "running", "finished", "error", "killed"], + "description": "Task status", + "example": "idle" + }, + "terminalId": { + "type": "string", + "description": "Associated terminal ID", + "example": "term_123" + }, + "startTime": { + "type": "string", + "format": "date-time", + "description": "Start time", + "example": "2024-01-15T10:30:45Z" + }, + "endTime": { + "type": "string", + "format": "date-time", + "description": "End time", + "example": "2024-01-15T10:35:45Z" + }, + "exitCode": { + "type": "integer", + "description": "Exit code (if finished)", + "example": 0 + } + } + }, + "SandboxState": { + "type": "object", + "required": ["version", "setupCompleted"], + "properties": { + "version": { + "type": "string", + "description": "Pint version", + "example": "1.0.0" + }, + "setupCompleted": { + "type": "boolean", + "description": "Whether initial setup is completed", + "example": true + }, + "workspace": { + "type": "string", + "description": "Workspace path", + "example": "/workspace" + }, + "uptime": { + "type": "integer", + "description": "Server uptime in seconds", + "example": 3600 + } + } + }, + "PortListResponse": { + "type": "object", + "required": ["ports"], + "properties": { + "ports": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Port" + } + } + } + }, + "Port": { + "type": "object", + "required": ["port", "status"], + "properties": { + "port": { + "type": "integer", + "format": "int32", + "description": "Port number", + "example": 3000 + }, + "status": { + "type": "string", + "enum": ["open", "closed", "listening"], + "description": "Port status", + "example": "open" + }, + "process": { + "type": "string", + "description": "Process name using the port", + "example": "node" + }, + "pid": { + "type": "integer", + "description": "Process ID", + "example": 1234 + }, + "address": { + "type": "string", + "description": "Bind address", + "example": "0.0.0.0" + } + } + } + } + } +} \ No newline at end of file diff --git a/openapi-port.json b/openapi-port.json deleted file mode 100644 index 176f301..0000000 --- a/openapi-port.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Port API", - "description": "API for managing sandbox port operations", - "version": "1.0.0" - }, - "paths": { - "/port/list": { - "post": { - "summary": "List ports", - "description": "Retrieve a list of available ports and their URLs", - "operationId": "portList", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Port" - }, - "description": "List of available ports" - } - }, - "required": ["list"] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error listing ports", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "CommonError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data", - "nullable": true - } - }, - "required": ["code", "message"] - }, - "Port": { - "type": "object", - "properties": { - "port": { - "type": "number", - "description": "Port number" - }, - "url": { - "type": "string", - "description": "URL to access the service on this port" - } - }, - "required": ["port", "url"] - } - } - } -} diff --git a/openapi-sandbox-container.json b/openapi-sandbox-container.json deleted file mode 100644 index f272b37..0000000 --- a/openapi-sandbox-container.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox Container API", - "description": "API for managing sandbox container operations", - "version": "1.0.0" - }, - "paths": { - "/container/setup": { - "post": { - "summary": "Setup container", - "description": "Set up a new container based on a template", - "operationId": "containerSetup", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "templateId": { - "type": "string", - "description": "Identifier of the template to use" - }, - "templateArgs": { - "type": "object", - "description": "Arguments for the template", - "additionalProperties": { - "type": "string" - } - }, - "features": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Feature identifier" - }, - "options": { - "type": "object", - "description": "Options for the feature", - "additionalProperties": { - "type": "string" - } - } - }, - "required": ["id", "options"] - }, - "nullable": true - } - }, - "required": ["templateId", "templateArgs"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error setting up container", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "ProtocolError": { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data", - "nullable": true - } - }, - "required": ["code", "message"] - }, - "TaskDTO": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Task identifier" - }, - "status": { - "type": "string", - "description": "Task status" - }, - "progress": { - "type": "number", - "description": "Task progress (0-100)" - } - }, - "required": ["id", "status", "progress"] - } - } - } -} diff --git a/openapi-sandbox-fs.json b/openapi-sandbox-fs.json deleted file mode 100644 index 57c3c6c..0000000 --- a/openapi-sandbox-fs.json +++ /dev/null @@ -1,2005 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox Rest FS API", - "description": "FS API for interacting with sandbox", - "version": "1.0.0" - }, - "paths": { - "/fs/writeFile": { - "post": { - "summary": "Write to a file", - "description": "Write content to a file at the specified path", - "operationId": "writeFile", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WriteFileRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error writing file", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/read": { - "post": { - "summary": "Read file system", - "description": "Retrieve the latest snapshot of the server's MemoryFS file and children list", - "operationId": "fsRead", - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/FSReadResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error reading file system", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/operation": { - "post": { - "summary": "Perform file system operation", - "description": "Send a tree operation reflecting filesystem operations", - "operationId": "fsOperation", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSOperationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/FSOperationResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error performing operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/search": { - "post": { - "summary": "Search files", - "description": "Search for content in files", - "operationId": "fsSearch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSSearchParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SearchResult" - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error searching files", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/streamingSearch": { - "post": { - "summary": "Start streaming search", - "description": "Start a streaming search for content in files", - "operationId": "fsStreamingSearch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSStreamingSearchParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "searchId": { - "type": "string", - "description": "ID of the search operation" - } - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error starting streaming search", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/cancelStreamingSearch": { - "post": { - "summary": "Cancel streaming search", - "description": "Cancel an ongoing streaming search", - "operationId": "fsCancelStreamingSearch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "searchId": { - "type": "string", - "description": "ID of the search to cancel" - } - }, - "required": ["searchId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "searchId": { - "type": "string", - "description": "ID of the cancelled search" - } - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error cancelling search", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/pathSearch": { - "post": { - "summary": "Search file paths", - "description": "Search for file paths matching a pattern", - "operationId": "fsPathSearch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PathSearchParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/PathSearchResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error searching paths", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/upload": { - "post": { - "summary": "Upload file", - "description": "Upload a file to the specified parent directory", - "operationId": "fsUpload", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "parentId": { - "type": "string", - "description": "ID of the parent directory" - }, - "filename": { - "type": "string", - "description": "Name of the file to create" - }, - "content": { - "type": "string", - "format": "binary", - "description": "File content as binary data" - } - }, - "required": ["parentId", "filename", "content"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "fileId": { - "type": "string", - "description": "ID of the created file" - } - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error uploading file", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/InvalidIdError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/download": { - "post": { - "summary": "Download files", - "description": "Download files at a specified path as a zip", - "operationId": "fsDownload", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to download" - }, - "excludes": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Glob patterns of files/folders to exclude from the download" - } - }, - "required": ["path"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "downloadUrl": { - "type": "string", - "description": "URL to download the files from" - } - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error creating download", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultError" - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/readFile": { - "post": { - "summary": "Read file content", - "description": "Read the content of a file at the specified path", - "operationId": "fsReadFile", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSReadFileParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/FSReadFileResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error reading file", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/readdir": { - "post": { - "summary": "Read directory contents", - "description": "List the contents of a directory at the specified path", - "operationId": "fsReadDir", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSReadDirParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/FSReadDirResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error reading directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/stat": { - "post": { - "summary": "Get file/directory stats", - "description": "Get stats for a file or directory at the specified path", - "operationId": "fsStat", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSStatParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/FSStatResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error getting stats", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/copy": { - "post": { - "summary": "Copy file/directory", - "description": "Copy a file or directory from one location to another", - "operationId": "fsCopy", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSCopyParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error copying file/directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/rename": { - "post": { - "summary": "Rename file/directory", - "description": "Rename a file or directory (move from one location to another)", - "operationId": "fsRename", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSRenameParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error renaming file/directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/remove": { - "post": { - "summary": "Remove file/directory", - "description": "Delete a file or directory at the specified path", - "operationId": "fsRemove", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSRemoveParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error removing file/directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/mkdir": { - "post": { - "summary": "Create directory", - "description": "Create a new directory at the specified path", - "operationId": "fsMkdir", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSMkdirParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error creating directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/watch": { - "post": { - "summary": "Watch file/directory", - "description": "Watch a file or directory for changes", - "operationId": "fsWatch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSWatchParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/FSWatchResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error watching file/directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - }, - "/fs/unwatch": { - "post": { - "summary": "Stop watching file/directory", - "description": "Stop watching a file or directory for changes", - "operationId": "fsUnwatch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FSUnwatchParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error unwatching file/directory", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/DefaultError" - }, - { - "$ref": "#/components/schemas/RawFsError" - } - ], - "discriminator": { - "propertyName": "code" - } - } - }, - "required": ["status", "error"] - }, - "DefaultError": { - "type": "object", - "properties": { - "code": { - "$ref": "#/components/schemas/PitcherErrorCode", - "description": "Error code identifying the type of error" - }, - "data": { - "type": "object", - "description": "Additional error details", - "nullable": true - }, - "publicMessage": { - "type": "string", - "description": "Human-readable error message that can be displayed to users", - "nullable": true - } - }, - "required": ["code"] - }, - "RawFsError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [102], - "description": "RAWFS_ERROR code" - }, - "data": { - "type": "object", - "properties": { - "errno": { - "type": ["number", "null"], - "description": "File system error number, or null if not available" - } - }, - "required": ["errno"] - }, - "publicMessage": { - "type": "string", - "description": "Human-readable error message that can be displayed to users", - "nullable": true - } - }, - "required": ["code", "data"] - }, - "PitcherErrorCode": { - "type": "integer", - "description": "Enumeration of error codes", - "enum": [ - 0, 1, 2, 3, 100, 101, 102, 200, 201, 204, 300, 400, 404, 410, 420, - 430, 440, 450, 460, 470, 500, 600, 601, 602, 704, 800, 801, 802, 803, - 814 - ], - "x-enum-descriptions": [ - "CRITICAL_ERROR", - "FEATURE_UNAVAILABLE", - "NO_ACCESS", - "RATE_LIMIT", - "INVALID_ID", - "INVALID_PATH", - "RAWFS_ERROR", - "SHELL_NOT_ACCESSIBLE", - "SHELL_CLOSED", - "SHELL_NOT_FOUND", - "MODEL_NOT_FOUND", - "GIT_OPERATION_IN_PROGRESS", - "GIT_REMOTE_FILE_NOT_FOUND", - "GIT_FETCH_FAIL", - "GIT_PULL_CONFLICT", - "GIT_RESET_LOCAL_REMOTE_ERROR", - "GIT_PUSH_FAIL", - "GIT_RESET_CHECKOUT_INITIAL_BRANCH_FAIL", - "GIT_PULL_FAIL", - "GIT_TRANSPOSE_LINES_FAIL", - "CHANNEL_NOT_FOUND", - "CONFIG_FILE_ALREADY_EXISTS", - "TASK_NOT_FOUND", - "COMMAND_ALREADY_CONFIGURED", - "COMMAND_NOT_FOUND", - "AI_NOT_AVAILABLE", - "PROMPT_TOO_BIG", - "FAILED_TO_RESPOND", - "AI_TOO_FREQUENT_REQUESTS", - "AI_CHAT_NOT_FOUND" - ] - }, - "WriteFileRequest": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path to write to" - }, - "content": { - "type": "string", - "format": "binary", - "description": "File content as binary data (Uint8Array)" - }, - "create": { - "type": "boolean", - "description": "Whether to create the file if it doesn't exist", - "default": false - }, - "overwrite": { - "type": "boolean", - "description": "Whether to overwrite the file if it exists", - "default": false - } - }, - "required": ["path", "content"] - }, - "FSReadResult": { - "type": "object", - "properties": { - "treeNodes": { - "type": "array", - "items": { - "type": "object", - "description": "JSON representation of a node in the file system" - } - }, - "clock": { - "type": "number", - "description": "Current clock value for the file system" - } - }, - "required": ["treeNodes", "clock"] - }, - "FSOperationRequest": { - "type": "object", - "properties": { - "operation": { - "$ref": "#/components/schemas/FSOperation" - } - }, - "required": ["operation"] - }, - "FSOperation": { - "oneOf": [ - { - "$ref": "#/components/schemas/FSCreateOperation" - }, - { - "$ref": "#/components/schemas/FSDeleteOperation" - }, - { - "$ref": "#/components/schemas/FSMoveOperation" - } - ], - "discriminator": { - "propertyName": "type" - } - }, - "FSCreateOperation": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["create"] - }, - "parentId": { - "type": "string", - "description": "ID of the parent directory" - }, - "newEntry": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "ID of the new entry" - }, - "type": { - "type": "string", - "enum": ["directory", "file"], - "description": "Type of the node" - }, - "name": { - "type": "string", - "description": "Name of the new entry" - } - }, - "required": ["id", "type", "name"] - } - }, - "required": ["type", "parentId", "newEntry"] - }, - "FSDeleteOperation": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["delete"] - }, - "id": { - "type": "string", - "description": "ID of the entry to delete" - } - }, - "required": ["type", "id"] - }, - "FSMoveOperation": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["move"] - }, - "id": { - "type": "string", - "description": "ID of the entry to move" - }, - "parentId": { - "type": "string", - "description": "ID of the new parent directory", - "nullable": true - }, - "name": { - "type": "string", - "description": "New name for the entry", - "nullable": true - } - }, - "required": ["type", "id"] - }, - "FSOperationResult": { - "oneOf": [ - { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [0], - "description": "Success code" - }, - "clock": { - "type": "number", - "description": "Current clock value" - } - }, - "required": ["code", "clock"] - }, - { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [1], - "description": "Ignored code" - } - }, - "required": ["code"] - } - ], - "discriminator": { - "propertyName": "code" - } - }, - "FSSearchParams": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "Text to search for" - }, - "glob": { - "type": "string", - "description": "Glob pattern to filter files", - "nullable": true - }, - "isRegex": { - "type": "boolean", - "description": "Whether to treat the search text as a regular expression", - "nullable": true - }, - "caseSensitivity": { - "type": "string", - "enum": ["smart", "enabled", "disabled"], - "description": "Case sensitivity setting for the search", - "nullable": true - } - }, - "required": ["text"] - }, - "SearchResult": { - "type": "object", - "properties": { - "fileId": { - "type": "string", - "description": "ID of the file containing the match" - }, - "lines": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "Text of the line containing the match" - } - }, - "required": ["text"] - }, - "lineNumber": { - "type": "integer", - "description": "Line number of the match" - }, - "absoluteOffset": { - "type": "integer", - "description": "Absolute offset of the match in the file" - }, - "submatches": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SearchSubMatch" - } - } - }, - "required": [ - "fileId", - "lines", - "lineNumber", - "absoluteOffset", - "submatches" - ] - }, - "SearchSubMatch": { - "type": "object", - "properties": { - "match": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "Matched text" - } - }, - "required": ["text"] - }, - "start": { - "type": "integer", - "description": "Start position of the match" - }, - "end": { - "type": "integer", - "description": "End position of the match" - } - }, - "required": ["match", "start", "end"] - }, - "FSStreamingSearchParams": { - "type": "object", - "properties": { - "searchId": { - "type": "string", - "description": "ID for the search operation" - }, - "text": { - "type": "string", - "description": "Text to search for" - }, - "glob": { - "type": "string", - "description": "Glob pattern to filter files", - "nullable": true - }, - "isRegex": { - "type": "boolean", - "description": "Whether to treat the search text as a regular expression", - "nullable": true - }, - "caseSensitivity": { - "type": "string", - "enum": ["smart", "enabled", "disabled"], - "description": "Case sensitivity setting for the search", - "nullable": true - }, - "maxResults": { - "type": "integer", - "description": "Maximum number of results to return (default: 10,000)", - "nullable": true - } - }, - "required": ["searchId", "text"] - }, - "PathSearchParams": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "Text to search for in file paths" - } - }, - "required": ["text"] - }, - "PathSearchResult": { - "type": "object", - "properties": { - "matches": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PathSearchMatch" - } - } - }, - "required": ["matches"] - }, - "PathSearchMatch": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path that matched the search" - }, - "submatches": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SearchSubMatch" - } - } - }, - "required": ["path", "submatches"] - }, - "InvalidIdError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [100], - "description": "INVALID_ID error code" - } - }, - "required": ["code"] - }, - "FSReadFileParams": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to the file to read" - } - }, - "required": ["path"] - }, - "FSReadFileResult": { - "type": "object", - "properties": { - "content": { - "type": "string", - "format": "binary", - "description": "File content as binary data" - } - }, - "required": ["content"] - }, - "FSReadDirParams": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to the directory to read" - } - }, - "required": ["path"] - }, - "FSReadDirResult": { - "type": "object", - "properties": { - "entries": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the entry" - }, - "type": { - "type": "string", - "enum": ["directory", "file"], - "description": "Type of the entry" - }, - "isSymlink": { - "type": "boolean", - "description": "Whether the entry is a symlink" - } - }, - "required": ["name", "type", "isSymlink"] - } - } - }, - "required": ["entries"] - }, - "FSStatParams": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to the file or directory to stat" - } - }, - "required": ["path"] - }, - "FSStatResult": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["directory", "file"], - "description": "Type of the entry" - }, - "isSymlink": { - "type": "boolean", - "description": "Whether the entry is a symlink" - }, - "size": { - "type": "integer", - "description": "Size of the file in bytes" - }, - "mtime": { - "type": "integer", - "description": "Last modified time" - }, - "ctime": { - "type": "integer", - "description": "Creation time" - }, - "atime": { - "type": "integer", - "description": "Last accessed time" - } - }, - "required": ["type", "isSymlink", "size", "mtime", "ctime", "atime"] - }, - "FSCopyParams": { - "type": "object", - "properties": { - "from": { - "type": "string", - "description": "Path to copy from" - }, - "to": { - "type": "string", - "description": "Path to copy to" - }, - "recursive": { - "type": "boolean", - "description": "Whether to copy directories recursively", - "nullable": true - }, - "overwrite": { - "type": "boolean", - "description": "Whether to overwrite existing files", - "nullable": true - } - }, - "required": ["from", "to"] - }, - "FSRenameParams": { - "type": "object", - "properties": { - "from": { - "type": "string", - "description": "Path to rename from" - }, - "to": { - "type": "string", - "description": "Path to rename to" - }, - "overwrite": { - "type": "boolean", - "description": "Whether to overwrite existing files", - "nullable": true - } - }, - "required": ["from", "to"] - }, - "FSRemoveParams": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to remove" - }, - "recursive": { - "type": "boolean", - "description": "Whether to remove directories recursively", - "nullable": true - } - }, - "required": ["path"] - }, - "FSMkdirParams": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to create directory at" - }, - "recursive": { - "type": "boolean", - "description": "Whether to create parent directories if they don't exist", - "nullable": true - } - }, - "required": ["path"] - }, - "FSWatchParams": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "Path to watch" - }, - "recursive": { - "type": "boolean", - "description": "Whether to watch directories recursively", - "nullable": true - }, - "excludes": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Glob patterns to exclude from watching", - "nullable": true - } - }, - "required": ["path"] - }, - "FSWatchResult": { - "type": "object", - "properties": { - "watchId": { - "type": "string", - "description": "ID of the watch" - } - }, - "required": ["watchId"] - }, - "FSUnwatchParams": { - "type": "object", - "properties": { - "watchId": { - "type": "string", - "description": "ID of the watch to stop" - } - }, - "required": ["watchId"] - } - } - } -} diff --git a/openapi-sandbox-git.json b/openapi-sandbox-git.json deleted file mode 100644 index 827a6e9..0000000 --- a/openapi-sandbox-git.json +++ /dev/null @@ -1,1369 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox Git API", - "description": "API for managing git operations in CodeSandbox", - "version": "1.0.0" - }, - "paths": { - "/git/status": { - "post": { - "summary": "Get git status", - "description": "Retrieve current git status including changed files, branch information, and commits", - "operationId": "gitStatus", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitStatus" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving git status", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/remotes": { - "post": { - "summary": "Get git remotes", - "description": "Retrieve git remote information", - "operationId": "gitRemotes", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitRemotes" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving git remotes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/targetDiff": { - "post": { - "summary": "Get git target diff", - "description": "Retrieve diff between current branch and target branch", - "operationId": "gitTargetDiff", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "branch": { - "type": "string", - "description": "Branch to compare against" - } - }, - "required": ["branch"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitTargetDiff" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving git target diff", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/pull": { - "post": { - "summary": "Pull from remote", - "description": "Pull changes from remote repository", - "operationId": "gitPull", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "branch": { - "type": "string", - "description": "Branch to pull from" - }, - "force": { - "type": "boolean", - "description": "Force pull even if there are conflicts" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error pulling from remote", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/discard": { - "post": { - "summary": "Discard changes", - "description": "Discard local changes for specified paths", - "operationId": "gitDiscard", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths of files to discard changes" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error discarding changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/commit": { - "post": { - "summary": "Commit changes", - "description": "Commit changes to the repository", - "operationId": "gitCommit", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "paths": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths of files to commit" - }, - "message": { - "type": "string", - "description": "Commit message" - }, - "push": { - "type": "boolean", - "description": "Whether to push the commit immediately" - } - }, - "required": ["message"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "shellId": { - "type": "string", - "description": "ID of the shell process" - } - }, - "required": ["shellId"] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error committing changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/push": { - "post": { - "summary": "Push changes", - "description": "Push local commits to remote repository", - "operationId": "gitPush", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error pushing changes", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/pushToRemote": { - "post": { - "summary": "Push to remote", - "description": "Push to a specific remote repository", - "operationId": "gitPushToRemote", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "URL of the remote repository" - }, - "branch": { - "type": "string", - "description": "Branch to push to" - }, - "squashAllCommits": { - "type": "boolean", - "description": "Whether to squash all commits into one" - } - }, - "required": ["url", "branch"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error pushing to remote", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/renameBranch": { - "post": { - "summary": "Rename branch", - "description": "Rename a git branch", - "operationId": "gitRenameBranch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "oldBranch": { - "type": "string", - "description": "Current branch name" - }, - "newBranch": { - "type": "string", - "description": "New branch name" - } - }, - "required": ["oldBranch", "newBranch"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error renaming branch", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/remoteContent": { - "post": { - "summary": "Get remote content", - "description": "Retrieve content from a remote repository", - "operationId": "gitRemoteContent", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GitRemoteParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Content of the file" - } - }, - "required": ["content"] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving remote content", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/diffStatus": { - "post": { - "summary": "Get diff status", - "description": "Retrieve diff status between two git references", - "operationId": "gitDiffStatus", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GitDiffStatusParams" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/GitDiffStatusResult" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving diff status", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/resetLocalWithRemote": { - "post": { - "summary": "Reset local with remote", - "description": "Reset local repository to match the remote state", - "operationId": "gitResetLocalWithRemote", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error resetting local with remote", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/checkoutInitialBranch": { - "post": { - "summary": "Checkout initial branch", - "description": "Checkout the initial branch of the repository", - "operationId": "gitCheckoutInitialBranch", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error checking out initial branch", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/git/transposeLines": { - "post": { - "summary": "Transpose lines", - "description": "Transpose line numbers from one git reference to another", - "operationId": "gitTransposeLines", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "sha": { - "type": "string", - "description": "Git commit SHA" - }, - "path": { - "type": "string", - "description": "Path to the file" - }, - "line": { - "type": "number", - "description": "Line number to transpose" - } - }, - "required": ["sha", "path", "line"] - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "oneOf": [ - { - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "line": { - "type": "number" - } - }, - "required": ["path", "line"] - }, - { - "type": "null" - } - ] - } - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error transposing lines", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "CommonError": { - "oneOf": [ - { - "type": "object", - "properties": { - "code": { - "type": "string", - "enum": [ - "GIT_OPERATION_IN_PROGRESS", - "GIT_REMOTE_FILE_NOT_FOUND" - ], - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "required": ["code", "message"] - }, - { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Protocol error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data" - } - }, - "required": ["code", "message"] - } - ] - }, - "GitStatusShortFormat": { - "type": "string", - "enum": ["", "M", "A", "D", "R", "C", "U", "?"], - "description": "Git status short format codes" - }, - "GitItem": { - "type": "object", - "properties": { - "path": { - "type": "string", - "description": "File path" - }, - "index": { - "$ref": "#/components/schemas/GitStatusShortFormat" - }, - "workingTree": { - "$ref": "#/components/schemas/GitStatusShortFormat" - }, - "isStaged": { - "type": "boolean", - "description": "Whether the file is staged" - }, - "isConflicted": { - "type": "boolean", - "description": "Whether the file has conflicts" - }, - "fileId": { - "type": "string", - "description": "Unique identifier for the file" - } - }, - "required": ["path", "index", "workingTree", "isStaged", "isConflicted"] - }, - "GitChangedFiles": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/GitItem" - }, - "description": "Map of file IDs to Git items" - }, - "GitBranchProperties": { - "type": "object", - "properties": { - "head": { - "type": ["string", "null"], - "description": "Current HEAD reference" - }, - "branch": { - "type": ["string", "null"], - "description": "Current branch name" - }, - "ahead": { - "type": "number", - "description": "Number of commits ahead of the remote" - }, - "behind": { - "type": "number", - "description": "Number of commits behind the remote" - }, - "safe": { - "type": "boolean", - "description": "Whether the branch is safe to operate on" - } - }, - "required": ["ahead", "behind", "safe"] - }, - "GitCommit": { - "type": "object", - "properties": { - "hash": { - "type": "string", - "description": "Commit hash" - }, - "date": { - "type": "string", - "description": "Commit date" - }, - "message": { - "type": "string", - "description": "Commit message" - }, - "author": { - "type": "string", - "description": "Commit author" - } - }, - "required": ["hash", "date", "message", "author"] - }, - "GitStatus": { - "type": "object", - "properties": { - "changedFiles": { - "$ref": "#/components/schemas/GitChangedFiles" - }, - "deletedFiles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitItem" - } - }, - "conflicts": { - "type": "boolean", - "description": "Whether there are remote conflicts" - }, - "localChanges": { - "type": "boolean", - "description": "Whether there are local changes" - }, - "remote": { - "$ref": "#/components/schemas/GitBranchProperties" - }, - "target": { - "$ref": "#/components/schemas/GitBranchProperties" - }, - "head": { - "type": "string", - "description": "Current HEAD reference" - }, - "commits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitCommit" - } - }, - "branch": { - "type": ["string", "null"], - "description": "Current branch name" - }, - "isMerging": { - "type": "boolean", - "description": "Whether a merge is in progress" - } - }, - "required": [ - "changedFiles", - "deletedFiles", - "conflicts", - "localChanges", - "remote", - "target", - "commits", - "branch", - "isMerging" - ] - }, - "GitTargetDiff": { - "type": "object", - "properties": { - "ahead": { - "type": "number", - "description": "Number of commits ahead of the target" - }, - "behind": { - "type": "number", - "description": "Number of commits behind the target" - }, - "commits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitCommit" - } - } - }, - "required": ["ahead", "behind", "commits"] - }, - "GitRemotes": { - "type": "object", - "properties": { - "origin": { - "type": "string", - "description": "Origin remote URL" - }, - "upstream": { - "type": "string", - "description": "Upstream remote URL" - } - }, - "required": ["origin", "upstream"] - }, - "GitRemoteParams": { - "type": "object", - "properties": { - "reference": { - "type": "string", - "description": "Branch or commit hash" - }, - "path": { - "type": "string", - "description": "Path to the file" - } - }, - "required": ["reference", "path"] - }, - "GitDiffStatusParams": { - "type": "object", - "properties": { - "base": { - "type": "string", - "description": "Base reference used for diffing" - }, - "head": { - "type": "string", - "description": "Head reference used for diffing" - } - }, - "required": ["base", "head"] - }, - "GitDiffStatusItem": { - "type": "object", - "properties": { - "status": { - "$ref": "#/components/schemas/GitStatusShortFormat" - }, - "path": { - "type": "string", - "description": "Path to the file" - }, - "oldPath": { - "type": "string", - "description": "Original path for renamed files" - }, - "hunks": { - "type": "array", - "items": { - "type": "object", - "properties": { - "original": { - "type": "object", - "properties": { - "start": { - "type": "number" - }, - "end": { - "type": "number" - } - }, - "required": ["start", "end"] - }, - "modified": { - "type": "object", - "properties": { - "start": { - "type": "number" - }, - "end": { - "type": "number" - } - }, - "required": ["start", "end"] - } - }, - "required": ["original", "modified"] - } - } - }, - "required": ["status", "path", "hunks"] - }, - "GitDiffStatusResult": { - "type": "object", - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitDiffStatusItem" - } - } - }, - "required": ["files"] - } - } - } -} diff --git a/openapi-sandbox-setup.json b/openapi-sandbox-setup.json deleted file mode 100644 index bc8b5c4..0000000 --- a/openapi-sandbox-setup.json +++ /dev/null @@ -1,570 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox Setup API", - "description": "API for managing sandbox setup operations", - "version": "1.0.0" - }, - "paths": { - "/setup/get": { - "post": { - "summary": "Get setup progress", - "description": "Retrieve the current setup progress status", - "operationId": "setupGet", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving setup progress", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - }, - "/setup/skip": { - "post": { - "summary": "Skip setup step", - "description": "Skip a specific step in the setup process", - "operationId": "setupSkipStep", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "stepIndexToSkip": { - "type": "number", - "description": "Index of the step to skip" - } - }, - "required": ["stepIndexToSkip"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error skipping step", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - }, - "/setup/skipAll": { - "post": { - "summary": "Skip all setup steps", - "description": "Skip all remaining steps in the setup process", - "operationId": "setupSkipAll", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "null" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error skipping all steps", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - }, - "/setup/disable": { - "post": { - "summary": "Disable setup", - "description": "Disable the setup process", - "operationId": "setupDisable", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "null" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error disabling setup", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - }, - "/setup/enable": { - "post": { - "summary": "Enable setup", - "description": "Enable the setup process", - "operationId": "setupEnable", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "null" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error enabling setup", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - }, - "/setup/init": { - "post": { - "summary": "Initialize setup", - "description": "Initialize the setup process", - "operationId": "setupInit", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "null" - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error initializing setup", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - }, - "/setup/setStep": { - "post": { - "summary": "Set current setup step", - "description": "Set the current step in the setup process (used for restarting)", - "operationId": "setupSetStep", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "stepIndex": { - "type": "number", - "description": "Index of the step to set as current" - } - }, - "required": ["stepIndex"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SetupProgress" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error setting current step", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/ProtocolError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "ProtocolError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data", - "nullable": true - } - }, - "required": ["code", "message"] - }, - "SetupShellStatus": { - "type": "string", - "enum": ["SUCCEEDED", "FAILED", "SKIPPED"], - "description": "Status of a setup shell step" - }, - "Step": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the setup step" - }, - "command": { - "type": "string", - "description": "Command to execute for this step" - }, - "shellId": { - "type": "string", - "description": "ID of the shell executing the command", - "nullable": true - }, - "finishStatus": { - "$ref": "#/components/schemas/SetupShellStatus", - "nullable": true, - "description": "Status of the step after completion" - } - }, - "required": ["name", "command", "shellId", "finishStatus"] - }, - "SetupProgress": { - "type": "object", - "properties": { - "state": { - "type": "string", - "enum": ["IDLE", "IN_PROGRESS", "FINISHED", "STOPPED"], - "description": "Current state of the setup process" - }, - "steps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Step" - }, - "description": "List of setup steps" - }, - "currentStepIndex": { - "type": "number", - "description": "Index of the current step being executed" - } - }, - "required": ["state", "steps", "currentStepIndex"] - } - } - } -} diff --git a/openapi-sandbox-shell.json b/openapi-sandbox-shell.json deleted file mode 100644 index e362489..0000000 --- a/openapi-sandbox-shell.json +++ /dev/null @@ -1,916 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox Shell API", - "description": "API for managing terminal and command shells in the sandbox", - "version": "1.0.0" - }, - "paths": { - "/shell/create": { - "post": { - "summary": "Create a new shell", - "description": "Creates a new terminal or command shell", - "operationId": "shellCreate", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "command": { - "type": "string", - "description": "Command to execute in the shell" - }, - "cwd": { - "type": "string", - "description": "Working directory for the shell" - }, - "size": { - "$ref": "#/components/schemas/ShellSize", - "description": "Terminal size dimensions" - }, - "type": { - "$ref": "#/components/schemas/ShellProcessType", - "description": "Type of shell to create" - }, - "isSystemShell": { - "type": "boolean", - "description": "Whether this shell is started by the editor itself to run a specific process" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/OpenShellDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error creating shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/in": { - "post": { - "summary": "Send input to shell", - "description": "Sends user input to an active shell", - "operationId": "shellIn", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the target shell" - }, - "input": { - "type": "string", - "description": "Input to send to the shell" - }, - "size": { - "$ref": "#/components/schemas/ShellSize", - "description": "Current terminal dimensions" - } - }, - "required": ["shellId", "input", "size"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error sending input to shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/list": { - "post": { - "summary": "List all shells", - "description": "Retrieves a list of all available shells", - "operationId": "shellList", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "shells": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ShellDTO" - } - } - }, - "required": ["shells"] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error listing shells", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/open": { - "post": { - "summary": "Open an existing shell", - "description": "Opens an existing shell and retrieves its buffer", - "operationId": "shellOpen", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the shell to open" - }, - "size": { - "$ref": "#/components/schemas/ShellSize", - "description": "Terminal dimensions" - } - }, - "required": ["shellId", "size"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/OpenShellDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error opening shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/close": { - "post": { - "summary": "Close a shell", - "description": "Closes a shell without terminating the underlying process", - "operationId": "shellClose", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the shell to close" - } - }, - "required": ["shellId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error closing shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/restart": { - "post": { - "summary": "Restart a shell", - "description": "Restarts an existing shell process", - "operationId": "shellRestart", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the shell to restart" - } - }, - "required": ["shellId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error restarting shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/terminate": { - "post": { - "summary": "Terminate a shell", - "description": "Terminates a shell and its underlying process", - "operationId": "shellTerminate", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the shell to terminate" - } - }, - "required": ["shellId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/ShellDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error terminating shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/resize": { - "post": { - "summary": "Resize a shell", - "description": "Updates the dimensions of a shell", - "operationId": "shellResize", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the shell to resize" - }, - "size": { - "$ref": "#/components/schemas/ShellSize", - "description": "New terminal dimensions" - } - }, - "required": ["shellId", "size"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error resizing shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/shell/rename": { - "post": { - "summary": "Rename a shell", - "description": "Updates the name of a shell", - "operationId": "shellRename", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId", - "description": "ID of the shell to rename" - }, - "name": { - "type": "string", - "description": "New name for the shell" - } - }, - "required": ["shellId", "name"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error renaming shell", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "ShellId": { - "type": "string", - "description": "Unique identifier for a shell" - }, - "ShellSize": { - "type": "object", - "properties": { - "cols": { - "type": "number", - "description": "Number of columns in the terminal" - }, - "rows": { - "type": "number", - "description": "Number of rows in the terminal" - } - }, - "required": ["cols", "rows"] - }, - "ShellProcessType": { - "type": "string", - "enum": ["TERMINAL", "COMMAND"], - "description": "Type of shell process" - }, - "ShellProcessStatus": { - "type": "string", - "enum": ["RUNNING", "FINISHED", "ERROR", "KILLED", "RESTARTING"], - "description": "Current status of the shell process" - }, - "BaseShellDTO": { - "type": "object", - "properties": { - "shellId": { - "$ref": "#/components/schemas/ShellId" - }, - "name": { - "type": "string", - "description": "Display name of the shell" - }, - "status": { - "$ref": "#/components/schemas/ShellProcessStatus" - }, - "exitCode": { - "type": "number", - "description": "Exit code of the process if it has finished", - "nullable": true - } - }, - "required": ["shellId", "name", "status"] - }, - "CommandShellDTO": { - "allOf": [ - { - "$ref": "#/components/schemas/BaseShellDTO" - }, - { - "type": "object", - "properties": { - "shellType": { - "type": "string", - "enum": ["COMMAND"], - "description": "Indicates this is a command shell" - }, - "startCommand": { - "type": "string", - "description": "The command that was executed to start this shell" - } - }, - "required": ["shellType", "startCommand"] - } - ] - }, - "TerminalShellDTO": { - "allOf": [ - { - "$ref": "#/components/schemas/BaseShellDTO" - }, - { - "type": "object", - "properties": { - "shellType": { - "type": "string", - "enum": ["TERMINAL"], - "description": "Indicates this is a terminal shell" - }, - "ownerUsername": { - "type": "string", - "description": "Username of the shell owner" - }, - "isSystemShell": { - "type": "boolean", - "description": "Whether this is a system shell" - } - }, - "required": ["shellType", "ownerUsername", "isSystemShell"] - } - ] - }, - "ShellDTO": { - "oneOf": [ - { - "$ref": "#/components/schemas/CommandShellDTO" - }, - { - "$ref": "#/components/schemas/TerminalShellDTO" - } - ], - "discriminator": { - "propertyName": "shellType", - "mapping": { - "COMMAND": "#/components/schemas/CommandShellDTO", - "TERMINAL": "#/components/schemas/TerminalShellDTO" - } - } - }, - "OpenCommandShellDTO": { - "allOf": [ - { - "$ref": "#/components/schemas/CommandShellDTO" - }, - { - "type": "object", - "properties": { - "buffer": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Content buffer of the shell" - } - }, - "required": ["buffer"] - } - ] - }, - "OpenTerminalShellDTO": { - "allOf": [ - { - "$ref": "#/components/schemas/TerminalShellDTO" - }, - { - "type": "object", - "properties": { - "buffer": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Content buffer of the shell" - } - }, - "required": ["buffer"] - } - ] - }, - "OpenShellDTO": { - "oneOf": [ - { - "$ref": "#/components/schemas/OpenCommandShellDTO" - }, - { - "$ref": "#/components/schemas/OpenTerminalShellDTO" - } - ], - "discriminator": { - "propertyName": "shellType", - "mapping": { - "COMMAND": "#/components/schemas/OpenCommandShellDTO", - "TERMINAL": "#/components/schemas/OpenTerminalShellDTO" - } - } - }, - "CommonError": { - "oneOf": [ - { - "type": "object", - "properties": { - "code": { - "type": "string", - "enum": ["SHELL_NOT_ACCESSIBLE"], - "description": "Error code indicating the shell is not accessible" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "required": ["code", "message"] - }, - { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Protocol error code" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "required": ["code", "message"] - } - ] - } - } - } -} diff --git a/openapi-sandbox-system.json b/openapi-sandbox-system.json deleted file mode 100644 index 501f2f5..0000000 --- a/openapi-sandbox-system.json +++ /dev/null @@ -1,348 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox System API", - "description": "API for managing sandbox system operations", - "version": "1.0.0" - }, - "paths": { - "/system/update": { - "post": { - "summary": "Update system", - "description": "Update the sandbox system", - "operationId": "systemUpdate", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error updating system", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/SystemError" - } - } - } - ] - } - } - } - } - } - } - }, - "/system/hibernate": { - "post": { - "summary": "Hibernate system", - "description": "Put the sandbox system into hibernation mode", - "operationId": "systemHibernate", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error hibernating system", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/SystemError" - } - } - } - ] - } - } - } - } - } - } - }, - "/system/metrics": { - "post": { - "summary": "Get system metrics", - "description": "Retrieve current system metrics including CPU, memory and storage usage", - "operationId": "systemMetrics", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/SystemMetricsStatus" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving system metrics", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/SystemError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "SystemError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data", - "nullable": true - } - }, - "required": ["code", "message"] - }, - "SystemMetricsStatus": { - "type": "object", - "properties": { - "cpu": { - "type": "object", - "properties": { - "cores": { - "type": "number", - "description": "Number of CPU cores" - }, - "used": { - "type": "number", - "description": "Used CPU resources" - }, - "configured": { - "type": "number", - "description": "Configured CPU resources" - } - }, - "required": ["cores", "used", "configured"] - }, - "memory": { - "type": "object", - "properties": { - "used": { - "type": "number", - "description": "Used memory in bytes" - }, - "total": { - "type": "number", - "description": "Total available memory in bytes" - }, - "configured": { - "type": "number", - "description": "Configured memory limit in bytes" - } - }, - "required": ["used", "total", "configured"] - }, - "storage": { - "type": "object", - "properties": { - "used": { - "type": "number", - "description": "Used storage in bytes" - }, - "total": { - "type": "number", - "description": "Total available storage in bytes" - }, - "configured": { - "type": "number", - "description": "Configured storage limit in bytes" - } - }, - "required": ["used", "total", "configured"] - } - }, - "required": ["cpu", "memory", "storage"] - }, - "InitStatus": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Status message" - }, - "isError": { - "type": "boolean", - "description": "Whether the status represents an error", - "nullable": true - }, - "progress": { - "type": "number", - "description": "Current progress (0-100)", - "minimum": 0, - "maximum": 100 - }, - "nextProgress": { - "type": "number", - "description": "Next progress target (0-100)", - "minimum": 0, - "maximum": 100 - }, - "stdout": { - "type": "string", - "description": "Standard output from the initialization process", - "nullable": true - } - }, - "required": ["message", "progress", "nextProgress"] - } - } - } -} diff --git a/openapi-sandbox-task.json b/openapi-sandbox-task.json deleted file mode 100644 index 6b5e320..0000000 --- a/openapi-sandbox-task.json +++ /dev/null @@ -1,947 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Sandbox Task API", - "description": "API for managing tasks in sandbox", - "version": "1.0.0" - }, - "paths": { - "/task/list": { - "post": { - "summary": "List tasks", - "description": "Retrieve a list of all configured tasks", - "operationId": "taskList", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskListDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error retrieving task list", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/CommonError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/run": { - "post": { - "summary": "Run task", - "description": "Start execution of a task by ID", - "operationId": "taskRun", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "taskId": { - "type": "string", - "description": "ID of the task to run" - } - }, - "required": ["taskId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error running task", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/runCommand": { - "post": { - "summary": "Run command", - "description": "Run a shell command directly, optionally saving it as a task", - "operationId": "taskRunCommand", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "command": { - "type": "string", - "description": "Command to run" - }, - "name": { - "type": "string", - "description": "Optional name for the task", - "nullable": true - }, - "saveToConfig": { - "type": "boolean", - "description": "Whether to save this command as a task in the config", - "nullable": true - } - }, - "required": ["command"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error running command", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/stop": { - "post": { - "summary": "Stop task", - "description": "Stop execution of a running task", - "operationId": "taskStop", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "taskId": { - "type": "string", - "description": "ID of the task to stop" - } - }, - "required": ["taskId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "oneOf": [ - { - "$ref": "#/components/schemas/TaskDTO" - }, - { - "type": "null", - "description": "Null when stopping an unconfigured task" - } - ] - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error stopping task", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/create": { - "post": { - "summary": "Create task", - "description": "Create a new task configuration", - "operationId": "taskCreate", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "taskFields": { - "$ref": "#/components/schemas/TaskDefinitionDTO" - }, - "startTask": { - "type": "boolean", - "description": "Whether to start the task immediately after creation", - "nullable": true - } - }, - "required": ["taskFields"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskListDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error creating task", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/update": { - "post": { - "summary": "Update task", - "description": "Update an existing task configuration", - "operationId": "taskUpdate", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "taskId": { - "type": "string", - "description": "ID of the task to update" - }, - "taskFields": { - "type": "object", - "description": "Fields to update in the task", - "properties": { - "name": { - "type": "string", - "description": "Name of the task", - "nullable": true - }, - "command": { - "type": "string", - "description": "Command to run", - "nullable": true - }, - "runAtStart": { - "type": "boolean", - "description": "Whether to run the task at sandbox start", - "nullable": true - }, - "preview": { - "type": "object", - "properties": { - "port": { - "type": "number", - "description": "Port to use for previewing the task", - "nullable": true - }, - "pr-link": { - "type": "string", - "enum": ["direct", "redirect", "devtool"], - "description": "Type of PR link to use", - "nullable": true - } - }, - "nullable": true - } - } - } - }, - "required": ["taskId", "taskFields"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error updating task", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/saveToConfig": { - "post": { - "summary": "Save task to config", - "description": "Save a runtime task to the configuration file", - "operationId": "taskSaveToConfig", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "taskId": { - "type": "string", - "description": "ID of the task to save to config" - } - }, - "required": ["taskId"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "$ref": "#/components/schemas/TaskDTO" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error saving task to config", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/generateConfig": { - "post": { - "summary": "Generate task config", - "description": "Generate a configuration file from current tasks", - "operationId": "taskGenerateConfig", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {} - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error generating config", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - }, - "/task/createSetupTasks": { - "post": { - "summary": "Create setup tasks", - "description": "Create tasks that run during sandbox setup", - "operationId": "taskCreateSetupTasks", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tasks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaskDefinitionDTO" - }, - "description": "Setup tasks to create" - } - }, - "required": ["tasks"] - } - } - } - }, - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessResponse" - }, - { - "type": "object", - "properties": { - "result": { - "type": "null" - } - } - } - ] - } - } - } - }, - "400": { - "description": "Error creating setup tasks", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorResponse" - }, - { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/TaskError" - } - } - } - ] - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "SuccessResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [0], - "description": "Status code for successful operations" - }, - "result": { - "type": "object", - "description": "Result payload for the operation" - } - }, - "required": ["status", "result"] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "status": { - "type": "number", - "enum": [1], - "description": "Status code for error operations" - }, - "error": { - "type": "object", - "description": "Error details" - } - }, - "required": ["status", "error"] - }, - "CommonError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "description": "Error code" - }, - "message": { - "type": "string", - "description": "Error message" - }, - "data": { - "type": "object", - "description": "Additional error data", - "nullable": true - } - }, - "required": ["code"] - }, - "TaskError": { - "oneOf": [ - { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [600], - "description": "CONFIG_FILE_ALREADY_EXISTS error code" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "required": ["code", "message"] - }, - { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [601], - "description": "TASK_NOT_FOUND error code" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "required": ["code", "message"] - }, - { - "type": "object", - "properties": { - "code": { - "type": "number", - "enum": [602], - "description": "COMMAND_ALREADY_CONFIGURED error code" - }, - "message": { - "type": "string", - "description": "Error message" - } - }, - "required": ["code", "message"] - }, - { - "$ref": "#/components/schemas/CommonError" - } - ], - "discriminator": { - "propertyName": "code" - } - }, - "TaskDefinitionDTO": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the task" - }, - "command": { - "type": "string", - "description": "Command to run for the task" - }, - "runAtStart": { - "type": "boolean", - "description": "Whether the task should run when the sandbox starts", - "nullable": true - }, - "preview": { - "type": "object", - "properties": { - "port": { - "type": "number", - "description": "Port to preview from this task", - "nullable": true - }, - "pr-link": { - "type": "string", - "enum": ["direct", "redirect", "devtool"], - "description": "Type of PR link to use", - "nullable": true - } - }, - "nullable": true - } - }, - "required": ["name", "command"] - }, - "CommandShellDTO": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "ID of the shell command" - }, - "command": { - "type": "string", - "description": "Command being executed" - }, - "status": { - "type": "string", - "enum": ["initializing", "running", "stopped", "error"], - "description": "Current status of the shell command" - }, - "output": { - "type": "string", - "description": "Current output of the command" - } - }, - "required": ["id", "command", "status", "output"] - }, - "Port": { - "type": "object", - "properties": { - "port": { - "type": "number", - "description": "Port number" - }, - "hostname": { - "type": "string", - "description": "Hostname the port is bound to" - }, - "status": { - "type": "string", - "enum": ["open", "closed"], - "description": "Current status of the port" - }, - "taskId": { - "type": "string", - "description": "ID of the task that opened this port", - "nullable": true - } - }, - "required": ["port", "hostname", "status"] - }, - "TaskDTO": { - "allOf": [ - { - "$ref": "#/components/schemas/TaskDefinitionDTO" - }, - { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Unique ID of the task" - }, - "unconfigured": { - "type": "boolean", - "description": "Whether this task is unconfigured (not saved in config)", - "nullable": true - }, - "shell": { - "type": "object", - "nullable": true, - "allOf": [ - { - "$ref": "#/components/schemas/CommandShellDTO" - } - ] - }, - "ports": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Port" - }, - "description": "Ports opened by this task" - } - }, - "required": ["id", "shell", "ports"] - } - ] - }, - "TaskListDTO": { - "type": "object", - "properties": { - "tasks": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/TaskDTO" - }, - "description": "Map of task IDs to task objects" - }, - "setupTasks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaskDefinitionDTO" - }, - "description": "Tasks that run during sandbox setup" - }, - "validationErrors": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Validation errors in the task configuration" - } - }, - "required": ["tasks", "setupTasks", "validationErrors"] - } - } - } -} diff --git a/package.json b/package.json index 7028620..5c44d88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codesandbox/sdk", - "version": "2.0.7", + "version": "2.1.0-rc.2", "description": "The CodeSandbox SDK", "author": "CodeSandbox", "license": "MIT", @@ -44,14 +44,7 @@ "build:esm:types": "tsc -p ./tsconfig.build-esm.json --emitDeclarationOnly", "build-openapi": "rimraf src/api-clients && curl -o openapi.json https://api.codesandbox.io/meta/openapi && npx prettier --write ./openapi.json && node_modules/.bin/openapi-ts -i ./openapi.json -o src/api-clients/client -c @hey-api/client-fetch && npm run build-openapi-rest", "build-openapi:staging": "rimraf src/api-clients && curl -o openapi.json https://api.codesandbox.stream/meta/openapi && npx prettier --write ./openapi.json && node_modules/.bin/openapi-ts -i ./openapi.json -o src/api-clients/client -c @hey-api/client-fetch && npm run build-openapi-rest", - "build-openapi-rest": "npm run build-openapi-rest-fs && npm run build-openapi-rest-task && npm run build-openapi-rest-container && npm run build-openapi-rest-git && npm run build-openapi-rest-setup && npm run build-openapi-rest-shell && npm run build-openapi-rest-system", - "build-openapi-rest-container": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-container.json -o src/api-clients/client-rest-container -c @hey-api/client-fetch", - "build-openapi-rest-fs": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-fs.json -o src/api-clients/client-rest-fs -c @hey-api/client-fetch", - "build-openapi-rest-git": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-git.json -o src/api-clients/client-rest-git -c @hey-api/client-fetch", - "build-openapi-rest-setup": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-setup.json -o src/api-clients/client-rest-setup -c @hey-api/client-fetch", - "build-openapi-rest-shell": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-shell.json -o src/api-clients/client-rest-shell -c @hey-api/client-fetch", - "build-openapi-rest-system": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-system.json -o src/api-clients/client-rest-system -c @hey-api/client-fetch", - "build-openapi-rest-task": "node_modules/.bin/openapi-ts -i ./openapi-sandbox-task.json -o src/api-clients/client-rest-task -c @hey-api/client-fetch", + "build-openapi-pint": "node_modules/.bin/openapi-ts -i ./openapi-pint.json -o src/api-clients/client-pint -c @hey-api/client-fetch", "clean": "rimraf ./dist", "typecheck": "tsc --noEmit", "format": "prettier '**/*.{md,js,jsx,json,ts,tsx}' --write", diff --git a/src/AgentClient/AgentConnection.ts b/src/AgentClient/AgentConnection.ts index 9541ffa..16ec80b 100644 --- a/src/AgentClient/AgentConnection.ts +++ b/src/AgentClient/AgentConnection.ts @@ -14,7 +14,7 @@ import type { import { PendingPitcherMessage } from "./PendingPitcherMessage"; import { createWebSocketClient, WebSocketClient } from "./WebSocketClient"; -import { IAgentClientState } from "./agent-client-interface"; +import { IAgentClientState } from "../agent-client-interface"; import { DEFAULT_SUBSCRIPTIONS } from "../types"; import { Emitter } from "../utils/event"; import { SliceList } from "../utils/sliceList"; diff --git a/src/AgentClient/index.ts b/src/AgentClient/index.ts index e195fb5..de4b23a 100644 --- a/src/AgentClient/index.ts +++ b/src/AgentClient/index.ts @@ -17,7 +17,7 @@ import { IAgentClientSystem, IAgentClientTasks, PickRawFsResult, -} from "./agent-client-interface"; +} from "../agent-client-interface"; import { AgentConnection } from "./AgentConnection"; import { Emitter, Event } from "../utils/event"; import { DEFAULT_SUBSCRIPTIONS, SandboxSession } from "../types"; diff --git a/src/PintAgentClient/index.ts b/src/PintAgentClient/index.ts new file mode 100644 index 0000000..53c8d96 --- /dev/null +++ b/src/PintAgentClient/index.ts @@ -0,0 +1,816 @@ +import { createClient } from '@hey-api/client-fetch'; +import * as PintAPI from '../api-clients/client-pint'; +import { + IAgentClient, + IAgentClientFS, + IAgentClientPorts, + IAgentClientSetup, + IAgentClientShells, + IAgentClientState, + IAgentClientSystem, + IAgentClientTasks, + PickRawFsResult, + RawFsResult, +} from '../agent-client-interface'; +import { Event, Emitter } from '../utils/event'; +import { Disposable } from '../utils/disposable'; +import { + fs, + port, + shell, + setup, + system, + task, +} from '../pitcher-protocol'; + +export class PintAgentClient implements IAgentClient { + private client = createClient({ + baseUrl: `http://localhost:${this.port}`, + headers: { + Authorization: `Bearer ${this.authToken}`, + }, + }); + + private _state: IAgentClientState = 'CONNECTING'; + private _onStateChange = new Emitter(); + + private _shells: PintAgentClientShells; + private _fs: PintAgentClientFS; + private _ports: PintAgentClientPorts; + private _setup: PintAgentClientSetup; + private _tasks: PintAgentClientTasks; + private _system: PintAgentClientSystem; + + constructor( + public sandboxId: string, + public workspacePath: string, + private port: number, + private authToken: string + ) { + this._shells = new PintAgentClientShells(this.client); + this._fs = new PintAgentClientFS(this.client); + this._ports = new PintAgentClientPorts(this.client); + this._setup = new PintAgentClientSetup(this.client); + this._tasks = new PintAgentClientTasks(this.client); + this._system = new PintAgentClientSystem(this.client); + + this.initialize(); + } + + get isUpToDate(): boolean { + return true; // TODO: Implement version checking + } + + get state(): IAgentClientState { + return this._state; + } + + get onStateChange(): Event { + return this._onStateChange.event; + } + + get shells(): IAgentClientShells { + return this._shells; + } + + get fs(): IAgentClientFS { + return this._fs; + } + + get ports(): IAgentClientPorts { + return this._ports; + } + + get setup(): IAgentClientSetup { + return this._setup; + } + + get tasks(): IAgentClientTasks { + return this._tasks; + } + + get system(): IAgentClientSystem { + return this._system; + } + + private async initialize() { + try { + await this.ping(); + this.setState('CONNECTED'); + } catch (error) { + this.setState('DISCONNECTED'); + } + } + + private setState(state: IAgentClientState) { + if (this._state !== state) { + this._state = state; + this._onStateChange.fire(state); + } + } + + async ping(): Promise { + try { + await PintAPI.getHealth({ client: this.client }); + } catch (error) { + throw new Error(`Ping failed: ${error}`); + } + } + + async disconnect(): Promise { + this.setState('DISCONNECTED'); + } + + async reconnect(): Promise { + this.setState('RECONNECTING'); + try { + await this.ping(); + this.setState('CONNECTED'); + } catch (error) { + this.setState('DISCONNECTED'); + throw error; + } + } + + dispose(): void { + this._onStateChange.dispose(); + this._shells.dispose(); + this._fs.dispose(); + this._ports.dispose(); + this._setup.dispose(); + this._tasks.dispose(); + this._system.dispose(); + } +} + +class PintAgentClientShells implements IAgentClientShells { + private _onShellExited = new Emitter<{ shellId: string; exitCode: number }>(); + private _onShellTerminated = new Emitter(); + private _onShellOut = new Emitter(); + + constructor(private client: any) {} + + get onShellExited(): Event<{ shellId: string; exitCode: number }> { + return this._onShellExited.event; + } + + get onShellTerminated(): Event { + return this._onShellTerminated.event; + } + + get onShellOut(): Event { + return this._onShellOut.event; + } + + async create( + projectPath: string, + size: shell.ShellSize, + command?: string, + type?: shell.ShellProcessType, + isSystemShell?: boolean + ): Promise { + const response = await PintAPI.postApiTerminals({ + client: this.client, + body: { + command: command || 'bash', + args: [], + workingDir: projectPath, + }, + }); + + if (!response.data?.terminal) { + throw new Error('Failed to create terminal'); + } + + // Convert Pint API response to shell.OpenShellDTO format + const terminal = response.data.terminal; + return { + shellId: terminal.id, + name: `Terminal ${terminal.id}`, + status: this.mapTerminalStatus(terminal.status), + exitCode: undefined, + shellType: type === 'COMMAND' ? 'COMMAND' : 'TERMINAL', + ...(type === 'COMMAND' + ? { startCommand: command || 'bash' } + : { + ownerUsername: 'user', + isSystemShell: isSystemShell || false, + }), + buffer: [], // Will be populated by stdout calls + } as shell.OpenShellDTO; + } + + async rename(shellId: shell.ShellId, name: string): Promise { + // Pint API doesn't have rename endpoint, so we'll just return null + return null; + } + + async getShells(): Promise { + const response = await PintAPI.getApiTerminals({ client: this.client }); + + if (!response.data?.terminals) { + return []; + } + + return response.data.terminals.map((terminal) => ({ + shellId: terminal.id, + name: `Terminal ${terminal.id}`, + status: this.mapTerminalStatus(terminal.status), + exitCode: undefined, + shellType: 'TERMINAL' as const, + ownerUsername: 'user', + isSystemShell: false, + })); + } + + async open( + shellId: shell.ShellId, + size: shell.ShellSize + ): Promise { + const response = await PintAPI.getApiTerminalsById({ + client: this.client, + path: { id: shellId }, + }); + + if (!response.data?.terminal) { + throw new Error(`Terminal ${shellId} not found`); + } + + const terminal = response.data.terminal; + + // Get terminal output for buffer + const outputResponse = await PintAPI.getApiTerminalsByIdStdout({ + client: this.client, + path: { id: shellId }, + }); + + const buffer = typeof outputResponse.data === 'string' + ? outputResponse.data.split('\n') + : []; + + return { + shellId: terminal.id, + name: `Terminal ${terminal.id}`, + status: this.mapTerminalStatus(terminal.status), + exitCode: undefined, + shellType: 'TERMINAL', + ownerUsername: 'user', + isSystemShell: false, + buffer, + }; + } + + async delete( + shellId: shell.ShellId + ): Promise { + const terminalResponse = await PintAPI.getApiTerminalsById({ + client: this.client, + path: { id: shellId }, + }); + + if (!terminalResponse.data?.terminal) { + return null; + } + + const terminal = terminalResponse.data.terminal; + + await PintAPI.deleteApiTerminalsById({ + client: this.client, + path: { id: shellId }, + }); + + return { + shellId: terminal.id, + name: `Terminal ${terminal.id}`, + status: this.mapTerminalStatus(terminal.status), + exitCode: undefined, + shellType: 'TERMINAL', + ownerUsername: 'user', + isSystemShell: false, + }; + } + + async restart(shellId: shell.ShellId): Promise { + // Pint API doesn't have restart endpoint for terminals + // We could delete and recreate, but for now just return null + return null; + } + + async send( + shellId: shell.ShellId, + input: string, + size: shell.ShellSize + ): Promise { + await PintAPI.postApiTerminalsByIdStdin({ + client: this.client, + path: { id: shellId }, + body: { input }, + }); + return null; + } + + private mapTerminalStatus(status: string): shell.ShellProcessStatus { + switch (status) { + case 'created': + return 'RUNNING'; + case 'running': + return 'RUNNING'; + case 'finished': + return 'FINISHED'; + case 'error': + return 'ERROR'; + default: + return 'RUNNING'; + } + } + + dispose(): void { + this._onShellExited.dispose(); + this._onShellTerminated.dispose(); + this._onShellOut.dispose(); + } +} + +class PintAgentClientFS implements IAgentClientFS { + constructor(private client: any) {} + + async readFile(path: string): Promise> { + try { + const response = await PintAPI.getApiFsFilesByPath({ + client: this.client, + path: { path }, + }); + + if (typeof response.data === 'string') { + return { + type: 'ok', + result: { + content: new TextEncoder().encode(response.data), + }, + }; + } + + return { + type: 'error', + error: 'Invalid response format', + errno: null, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async readdir(path: string): Promise> { + try { + const response = await PintAPI.getApiDirectoriesByPath({ + client: this.client, + path: { path }, + }); + + if (!response.data?.entries) { + return { + type: 'error', + error: 'Invalid response format', + errno: null, + }; + } + + return { + type: 'ok', + result: { + entries: response.data.entries.map((entry) => ({ + name: entry.name, + type: entry.isDir ? 'directory' : 'file', + })), + }, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async writeFile( + path: string, + content: Uint8Array, + create?: boolean, + overwrite?: boolean + ): Promise> { + try { + await PintAPI.putApiFsFilesByPath({ + client: this.client, + path: { path }, + body: { + operation: 'write', + content: new TextDecoder().decode(content), + }, + }); + + return { + type: 'ok', + result: {}, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async stat(path: string): Promise> { + try { + const response = await PintAPI.getApiFsStatsByPath({ + client: this.client, + path: { path }, + }); + + if (!response.data) { + return { + type: 'error', + error: 'File not found', + errno: null, + }; + } + + return { + type: 'ok', + result: { + type: response.data.isDir ? 'directory' : 'file', + size: response.data.size, + mtime: new Date(response.data.modTime).getTime(), + ctime: new Date(response.data.modTime).getTime(), // Use modTime as ctime + }, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async copy( + from: string, + to: string, + recursive?: boolean, + overwrite?: boolean + ): Promise> { + try { + await PintAPI.putApiFsFilesByPath({ + client: this.client, + path: { path: to }, + body: { + operation: 'copyFrom', + source: from, + }, + }); + + return { + type: 'ok', + result: {}, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async rename( + from: string, + to: string, + overwrite?: boolean + ): Promise> { + try { + await PintAPI.putApiFsFilesByPath({ + client: this.client, + path: { path: to }, + body: { + operation: 'moveFrom', + source: from, + }, + }); + + return { + type: 'ok', + result: {}, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async remove( + path: string, + recursive?: boolean + ): Promise> { + try { + // Try to stat first to see if it's a file or directory + const statResponse = await PintAPI.getApiFsStatsByPath({ + client: this.client, + path: { path }, + }); + + if (statResponse.data?.isDir) { + await PintAPI.deleteApiDirectoriesByPath({ + client: this.client, + path: { path }, + }); + } else { + await PintAPI.deleteApiFsFilesByPath({ + client: this.client, + path: { path }, + }); + } + + return { + type: 'ok', + result: {}, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async mkdir( + path: string, + recursive?: boolean + ): Promise> { + try { + await PintAPI.postApiDirectoriesByPath({ + client: this.client, + path: { path }, + }); + + return { + type: 'ok', + result: {}, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async watch( + path: string, + options: { + readonly recursive?: boolean; + readonly excludes?: readonly string[]; + }, + onEvent: (watchEvent: fs.FSWatchEvent) => void + ): Promise< + | (PickRawFsResult<'fs/watch'> & { type: 'error' }) + | { type: 'success'; dispose(): void } + > { + try { + // Create a glob pattern from path and options + let globPattern = path; + if (options.recursive) { + globPattern = `${path}/**/*`; + } + + // Note: Real implementation would need to handle SSE for watch events + // For now, we'll return a mock success response + return { + type: 'success', + dispose() { + // Cleanup watch subscription + }, + }; + } catch (error) { + return { + type: 'error', + error: error instanceof Error ? error.message : 'Unknown error', + errno: null, + }; + } + } + + async download(path?: string): Promise<{ downloadUrl: string }> { + // Pint API doesn't have download endpoint, return placeholder + return { + downloadUrl: `http://localhost/download${path ? `?path=${encodeURIComponent(path)}` : ''}`, + }; + } + + dispose(): void { + // Cleanup any subscriptions + } +} + +class PintAgentClientPorts implements IAgentClientPorts { + private _onPortsUpdated = new Emitter(); + + constructor(private client: any) {} + + get onPortsUpdated(): Event { + return this._onPortsUpdated.event; + } + + async getPorts(): Promise { + const response = await PintAPI.getApiPorts({ client: this.client }); + + if (!response.data?.ports) { + return []; + } + + return response.data.ports.map((p) => ({ + port: p.port, + state: p.status === 'open' ? 'OPEN' : 'CLOSED', + hostname: p.address || 'localhost', + preview: undefined, // TODO: Determine preview URL + process: p.process, + })); + } + + dispose(): void { + this._onPortsUpdated.dispose(); + } +} + +class PintAgentClientSetup implements IAgentClientSetup { + private _onSetupProgressUpdate = new Emitter(); + + constructor(private client: any) {} + + get onSetupProgressUpdate(): Event { + return this._onSetupProgressUpdate.event; + } + + async getProgress(): Promise { + const response = await PintAPI.getApiState({ client: this.client }); + + return { + hasRunSetup: response.data?.setupCompleted || false, + steps: [], + }; + } + + async init(): Promise { + return this.getProgress(); + } + + dispose(): void { + this._onSetupProgressUpdate.dispose(); + } +} + +class PintAgentClientTasks implements IAgentClientTasks { + private _onTaskUpdate = new Emitter(); + + constructor(private client: any) {} + + get onTaskUpdate(): Event { + return this._onTaskUpdate.event; + } + + async getTasks(): Promise { + const response = await PintAPI.getApiTasks({ client: this.client }); + + if (!response.data?.tasks) { + return { tasks: [] }; + } + + return { + tasks: response.data.tasks.map((t) => ({ + id: t.id, + name: t.name, + status: this.mapTaskStatus(t.status), + command: t.command, + terminalId: t.terminalId, + })), + }; + } + + async getTask(taskId: string): Promise { + try { + const response = await PintAPI.getApiTasksById({ + client: this.client, + path: { id: taskId }, + }); + + if (!response.data?.task) { + return undefined; + } + + const t = response.data.task; + return { + id: t.id, + name: t.name, + status: this.mapTaskStatus(t.status), + command: t.command, + terminalId: t.terminalId, + }; + } catch (error) { + return undefined; + } + } + + async runTask(taskId: string): Promise { + const response = await PintAPI.postApiTasksByIdRun({ + client: this.client, + path: { id: taskId }, + }); + + if (!response.data?.task) { + throw new Error(`Failed to run task ${taskId}`); + } + + const t = response.data.task; + return { + id: t.id, + name: t.name, + status: this.mapTaskStatus(t.status), + command: t.command, + terminalId: t.terminalId, + }; + } + + async stopTask(taskId: string): Promise { + try { + const response = await PintAPI.postApiTasksByIdStop({ + client: this.client, + path: { id: taskId }, + }); + + if (!response.data?.task) { + return null; + } + + const t = response.data.task; + return { + id: t.id, + name: t.name, + status: this.mapTaskStatus(t.status), + command: t.command, + terminalId: t.terminalId, + }; + } catch (error) { + return null; + } + } + + private mapTaskStatus(status: string): task.TaskStatus { + switch (status) { + case 'idle': + return 'IDLE'; + case 'running': + return 'RUNNING'; + case 'finished': + return 'FINISHED'; + case 'error': + return 'ERROR'; + case 'killed': + return 'KILLED'; + default: + return 'IDLE'; + } + } + + dispose(): void { + this._onTaskUpdate.dispose(); + } +} + +class PintAgentClientSystem implements IAgentClientSystem { + private _onInitStatusUpdate = new Emitter(); + + constructor(private client: any) {} + + get onInitStatusUpdate(): Event { + return this._onInitStatusUpdate.event; + } + + async update(): Promise> { + // Pint API doesn't have system update endpoint + return {}; + } + + dispose(): void { + this._onInitStatusUpdate.dispose(); + } +} \ No newline at end of file diff --git a/src/SandboxClient/commands.ts b/src/SandboxClient/commands.ts index 110849a..c625748 100644 --- a/src/SandboxClient/commands.ts +++ b/src/SandboxClient/commands.ts @@ -1,6 +1,6 @@ import { Disposable, DisposableStore } from "../utils/disposable"; import { Emitter } from "../utils/event"; -import { IAgentClient } from "../AgentClient/agent-client-interface"; +import { IAgentClient } from "../agent-client-interface"; import * as protocol from "../pitcher-protocol"; import { Barrier } from "../utils/barrier"; import { Tracer, SpanStatusCode } from "@opentelemetry/api"; @@ -88,7 +88,7 @@ export class SandboxCommands { "command.text": cmdString, "command.cwd": opts?.cwd || "/project", "command.asGlobalSession": opts?.asGlobalSession || false, - "command.name": opts?.name || "" + "command.name": opts?.name || "", }, async () => { const disposableStore = new DisposableStore(); @@ -168,7 +168,7 @@ export class SandboxCommands { { "command.text": cmdString, "command.cwd": opts?.cwd || "/project", - "command.asGlobalSession": opts?.asGlobalSession || false + "command.asGlobalSession": opts?.asGlobalSession || false, }, async () => { const cmd = await this.runBackground(command, opts); @@ -181,21 +181,23 @@ export class SandboxCommands { * Get all running commands. */ async getAll(): Promise { - return this.withSpan( - "commands.getAll", - {}, - async () => { - const shells = await this.agentClient.shells.getShells(); - - return shells - .filter( - (shell) => shell.shellType === "TERMINAL" && isCommandShell(shell) - ) - .map( - (shell) => new Command(this.agentClient, shell, JSON.parse(shell.name), this.tracer) - ); - } - ); + return this.withSpan("commands.getAll", {}, async () => { + const shells = await this.agentClient.shells.getShells(); + + return shells + .filter( + (shell) => shell.shellType === "TERMINAL" && isCommandShell(shell) + ) + .map( + (shell) => + new Command( + this.agentClient, + shell, + JSON.parse(shell.name), + this.tracer + ) + ); + }); } } @@ -348,7 +350,7 @@ export class Command { "command.shellId": this.shell.shellId, "command.text": this.command, "command.dimensions.cols": dimensions.cols, - "command.dimensions.rows": dimensions.rows + "command.dimensions.rows": dimensions.rows, }, async () => { const shell = await this.agentClient.shells.open( @@ -372,7 +374,7 @@ export class Command { { "command.shellId": this.shell.shellId, "command.text": this.command, - "command.status": this.status + "command.status": this.status, }, async () => { await this.barrier.wait(); @@ -403,7 +405,7 @@ export class Command { { "command.shellId": this.shell.shellId, "command.text": this.command, - "command.status": this.status + "command.status": this.status, }, async () => { this.disposable.dispose(); @@ -421,7 +423,7 @@ export class Command { { "command.shellId": this.shell.shellId, "command.text": this.command, - "command.status": this.status + "command.status": this.status, }, async () => { if (this.status !== "RUNNING") { diff --git a/src/SandboxClient/filesystem.ts b/src/SandboxClient/filesystem.ts index b94df85..3a48889 100644 --- a/src/SandboxClient/filesystem.ts +++ b/src/SandboxClient/filesystem.ts @@ -1,4 +1,4 @@ -import { type IAgentClient } from "../AgentClient/agent-client-interface"; +import { type IAgentClient } from "../agent-client-interface"; import { Disposable } from "../utils/disposable"; import { Emitter, type Event } from "../utils/event"; @@ -102,7 +102,7 @@ export class FileSystem { "fs.path": path, "fs.size": content.length, "fs.create": opts.create ?? true, - "fs.overwrite": opts.overwrite ?? true + "fs.overwrite": opts.overwrite ?? true, }, async () => { const result = await this.agentClient.fs.writeFile( @@ -129,7 +129,7 @@ export class FileSystem { "fs.path": path, "fs.contentLength": content.length, "fs.create": opts.create ?? true, - "fs.overwrite": opts.overwrite ?? true + "fs.overwrite": opts.overwrite ?? true, }, async () => { return this.writeFile(path, new TextEncoder().encode(content), opts); @@ -145,7 +145,7 @@ export class FileSystem { "fs.mkdir", { "fs.path": path, - "fs.recursive": recursive + "fs.recursive": recursive, }, async () => { const result = await this.agentClient.fs.mkdir(path, recursive); @@ -161,78 +161,62 @@ export class FileSystem { * Read a directory. */ async readdir(path: string): Promise { - return this.withSpan( - "fs.readdir", - { "fs.path": path }, - async () => { - const result = await this.agentClient.fs.readdir(path); + return this.withSpan("fs.readdir", { "fs.path": path }, async () => { + const result = await this.agentClient.fs.readdir(path); - if (result.type === "error") { - throw new Error(`${result.errno}: ${result.error}`); - } - - return result.result.entries.map((entry) => ({ - ...entry, - type: entry.type === 0 ? "file" : "directory", - })); + if (result.type === "error") { + throw new Error(`${result.errno}: ${result.error}`); } - ); + + return result.result.entries.map((entry) => ({ + ...entry, + type: entry.type === 0 ? "file" : "directory", + })); + }); } /** * Read a file */ async readFile(path: string): Promise { - return this.withSpan( - "fs.readFile", - { "fs.path": path }, - async () => { - const result = await this.agentClient.fs.readFile(path); - - if (result.type === "error") { - throw new Error(`${result.errno}: ${result.error}`); - } + return this.withSpan("fs.readFile", { "fs.path": path }, async () => { + const result = await this.agentClient.fs.readFile(path); - return result.result.content; + if (result.type === "error") { + throw new Error(`${result.errno}: ${result.error}`); } - ); + + return result.result.content; + }); } /** * Read a file as a string. */ async readTextFile(path: string): Promise { - return this.withSpan( - "fs.readTextFile", - { "fs.path": path }, - async () => { - const content = await this.readFile(path); - return new TextDecoder("utf-8").decode(content); - } - ); + return this.withSpan("fs.readTextFile", { "fs.path": path }, async () => { + const content = await this.readFile(path); + return new TextDecoder("utf-8").decode(content); + }); } /** * Get the stat of a file or directory. */ async stat(path: string): Promise { - return this.withSpan( - "fs.stat", - { "fs.path": path }, - async () => { - const result = await this.agentClient.fs.stat(path); + return this.withSpan("fs.stat", { "fs.path": path }, async () => { + const result = await this.agentClient.fs.stat(path); - if (result.type === "error") { - throw new Error(`${result.errno}: ${result.error}`); - } - - return { - ...result.result, - type: - result.result.type === 0 ? ("file" as const) : ("directory" as const), - }; + if (result.type === "error") { + throw new Error(`${result.errno}: ${result.error}`); } - ); + + return { + ...result.result, + type: + result.result.type === 0 ? ("file" as const) : ("directory" as const), + }; + }); } /** @@ -250,7 +234,7 @@ export class FileSystem { "fs.from": from, "fs.to": to, "fs.recursive": recursive, - "fs.overwrite": overwrite + "fs.overwrite": overwrite, }, async () => { const result = await this.agentClient.fs.copy( @@ -276,7 +260,7 @@ export class FileSystem { { "fs.from": from, "fs.to": to, - "fs.overwrite": overwrite + "fs.overwrite": overwrite, }, async () => { const result = await this.agentClient.fs.rename(from, to, overwrite); @@ -296,7 +280,7 @@ export class FileSystem { "fs.remove", { "fs.path": path, - "fs.recursive": recursive + "fs.recursive": recursive, }, async () => { const result = await this.agentClient.fs.remove(path, recursive); @@ -331,23 +315,27 @@ export class FileSystem { { "fs.path": path, "fs.recursive": options.recursive ?? false, - "fs.excludeCount": options.excludes?.length ?? 0 + "fs.excludeCount": options.excludes?.length ?? 0, }, async () => { const emitter = new Emitter(); - const result = await this.agentClient.fs.watch(path, options, (event) => { - if (this.username) { - emitter.fire({ - ...event, - paths: event.paths.map((path) => - path.replace(`home/${this.username}/workspace/`, "sandbox/") - ), - }); - } else { - emitter.fire(event); + const result = await this.agentClient.fs.watch( + path, + options, + (event) => { + if (this.username) { + emitter.fire({ + ...event, + paths: event.paths.map((path) => + path.replace(`home/${this.username}/workspace/`, "sandbox/") + ), + }); + } else { + emitter.fire(event); + } } - }); + ); if (result.type === "error") { throw new Error(`${result.errno}: ${result.error}`); @@ -372,14 +360,10 @@ export class FileSystem { * from within the workspace directory. A download URL that's valid for 5 minutes. */ async download(path: string): Promise<{ downloadUrl: string }> { - return this.withSpan( - "fs.download", - { "fs.path": path }, - async () => { - const result = await this.agentClient.fs.download(path); + return this.withSpan("fs.download", { "fs.path": path }, async () => { + const result = await this.agentClient.fs.download(path); - return result; - } - ); + return result; + }); } } diff --git a/src/SandboxClient/index.ts b/src/SandboxClient/index.ts index fb54b5e..ce8b624 100644 --- a/src/SandboxClient/index.ts +++ b/src/SandboxClient/index.ts @@ -10,7 +10,7 @@ import { Terminals } from "./terminals"; import { SandboxCommands } from "./commands"; import { HostToken } from "../HostTokens"; import { Hosts } from "./hosts"; -import { IAgentClient } from "../AgentClient/agent-client-interface"; +import { IAgentClient } from "../agent-client-interface"; import { setup, system } from "../pitcher-protocol"; import { Barrier } from "../utils/barrier"; import { AgentClient } from "../AgentClient"; @@ -119,7 +119,11 @@ export class SandboxClient { /** * Namespace for managing ports on this Sandbox */ - public readonly ports = new Ports(this.disposable, this.agentClient, this.tracer); + public readonly ports = new Ports( + this.disposable, + this.agentClient, + this.tracer + ); /** * Namespace for the setup that runs when the Sandbox starts from scratch. @@ -150,13 +154,26 @@ export class SandboxClient { initialSetupProgress, tracer ); - this.fs = new FileSystem(this.disposable, this.agentClient, username, tracer); + this.fs = new FileSystem( + this.disposable, + this.agentClient, + username, + tracer + ); this.terminals = new Terminals(this.disposable, this.agentClient, tracer); this.tasks = new Tasks(this.disposable, this.agentClient, tracer); - this.commands = new SandboxCommands(this.disposable, this.agentClient, tracer); + this.commands = new SandboxCommands( + this.disposable, + this.agentClient, + tracer + ); this.hosts = new Hosts(this.agentClient.sandboxId, hostToken, tracer); - this.interpreters = new Interpreters(this.disposable, this.commands, tracer); + this.interpreters = new Interpreters( + this.disposable, + this.commands, + tracer + ); this.disposable.onWillDispose(() => this.agentClient.dispose()); this.disposable.onWillDispose(() => { @@ -329,7 +346,7 @@ export class SandboxClient { */ public reconnect() { return this.withSpan( - "sandboxClient.reconnect", + "sandboxClient.reconnect", { "sandbox.id": this.id }, async () => { this.isExplicitlyDisconnected = false; @@ -350,7 +367,9 @@ export class SandboxClient { await retryWithDelay( async () => { if (this.isExplicitlyDisconnected) { - throw new Error("Explicit disconnect - stopping auto-reconnect"); + throw new Error( + "Explicit disconnect - stopping auto-reconnect" + ); } await this.agentClient.reconnect(); }, diff --git a/src/SandboxClient/ports.ts b/src/SandboxClient/ports.ts index fe2cbbc..f0ccf1d 100644 --- a/src/SandboxClient/ports.ts +++ b/src/SandboxClient/ports.ts @@ -1,6 +1,6 @@ import { Disposable } from "../utils/disposable"; import { Emitter } from "../utils/event"; -import { IAgentClient } from "../AgentClient/agent-client-interface"; +import { IAgentClient } from "../agent-client-interface"; import { Tracer, SpanStatusCode } from "@opentelemetry/api"; export type Port = { @@ -78,52 +78,50 @@ export class Ports { if (!this.tracer) { return fn(); } - return this.tracer.startActiveSpan(operationName, { attributes }, async (span) => { - try { - const result = await fn(); - span.setStatus({ code: SpanStatusCode.OK }); - return result; - } catch (error) { - span.setStatus({ - code: SpanStatusCode.ERROR, - message: error instanceof Error ? error.message : String(error), - }); - span.recordException(error instanceof Error ? error : new Error(String(error))); - throw error; - } finally { - span.end(); + return this.tracer.startActiveSpan( + operationName, + { attributes }, + async (span) => { + try { + const result = await fn(); + span.setStatus({ code: SpanStatusCode.OK }); + return result; + } catch (error) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error instanceof Error ? error.message : String(error), + }); + span.recordException( + error instanceof Error ? error : new Error(String(error)) + ); + throw error; + } finally { + span.end(); + } } - }); + ); } /** * Get a port by number. */ async get(port: number) { - return this.withSpan( - "ports.get", - { "port.number": port }, - async () => { - const ports = await this.getAll(); + return this.withSpan("ports.get", { "port.number": port }, async () => { + const ports = await this.getAll(); - return ports.find((p) => p.port === port); - } - ); + return ports.find((p) => p.port === port); + }); } /** * Get all ports. */ async getAll(): Promise { - return this.withSpan( - "ports.getAll", - {}, - async () => { - const ports = await this.agentClient.ports.getPorts(); + return this.withSpan("ports.getAll", {}, async () => { + const ports = await this.agentClient.ports.getPorts(); - return ports.map(({ port, url }) => ({ port, host: url })); - } - ); + return ports.map(({ port, url }) => ({ port, host: url })); + }); } /** @@ -141,9 +139,9 @@ export class Ports { ): Promise { return this.withSpan( "ports.waitForPort", - { + { "port.number": port, - "port.timeout.ms": options?.timeoutMs + "port.timeout.ms": options?.timeoutMs, }, async () => { return new Promise(async (resolve, reject) => { diff --git a/src/SandboxClient/setup.ts b/src/SandboxClient/setup.ts index 8bc70bf..e322cd2 100644 --- a/src/SandboxClient/setup.ts +++ b/src/SandboxClient/setup.ts @@ -2,7 +2,7 @@ import * as protocol from "../pitcher-protocol"; import { Disposable } from "../utils/disposable"; import { Emitter } from "../utils/event"; import { DEFAULT_SHELL_SIZE } from "./terminals"; -import { IAgentClient } from "../AgentClient/agent-client-interface"; +import { IAgentClient } from "../agent-client-interface"; import { Tracer, SpanStatusCode } from "@opentelemetry/api"; export class Setup { @@ -41,22 +41,28 @@ export class Setup { if (!this.tracer) { return fn(); } - return this.tracer.startActiveSpan(operationName, { attributes }, async (span) => { - try { - const result = await fn(); - span.setStatus({ code: SpanStatusCode.OK }); - return result; - } catch (error) { - span.setStatus({ - code: SpanStatusCode.ERROR, - message: error instanceof Error ? error.message : String(error), - }); - span.recordException(error instanceof Error ? error : new Error(String(error))); - throw error; - } finally { - span.end(); + return this.tracer.startActiveSpan( + operationName, + { attributes }, + async (span) => { + try { + const result = await fn(); + span.setStatus({ code: SpanStatusCode.OK }); + return result; + } catch (error) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error instanceof Error ? error.message : String(error), + }); + span.recordException( + error instanceof Error ? error : new Error(String(error)) + ); + throw error; + } finally { + span.end(); + } } - }); + ); } getSteps() { @@ -180,22 +186,28 @@ export class Step { if (!this.tracer) { return fn(); } - return this.tracer.startActiveSpan(operationName, { attributes }, async (span) => { - try { - const result = await fn(); - span.setStatus({ code: SpanStatusCode.OK }); - return result; - } catch (error) { - span.setStatus({ - code: SpanStatusCode.ERROR, - message: error instanceof Error ? error.message : String(error), - }); - span.recordException(error instanceof Error ? error : new Error(String(error))); - throw error; - } finally { - span.end(); + return this.tracer.startActiveSpan( + operationName, + { attributes }, + async (span) => { + try { + const result = await fn(); + span.setStatus({ code: SpanStatusCode.OK }); + return result; + } catch (error) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error instanceof Error ? error.message : String(error), + }); + span.recordException( + error instanceof Error ? error : new Error(String(error)) + ); + throw error; + } finally { + span.end(); + } } - }); + ); } async open(dimensions = DEFAULT_SHELL_SIZE): Promise { @@ -271,4 +283,4 @@ export class Step { } ); } -} \ No newline at end of file +} diff --git a/src/SandboxClient/tasks.ts b/src/SandboxClient/tasks.ts index 9409caf..e8fce74 100644 --- a/src/SandboxClient/tasks.ts +++ b/src/SandboxClient/tasks.ts @@ -1,7 +1,7 @@ import * as protocol from "../pitcher-protocol"; import { Disposable, IDisposable } from "../utils/disposable"; import { DEFAULT_SHELL_SIZE } from "./terminals"; -import { IAgentClient } from "../AgentClient/agent-client-interface"; +import { IAgentClient } from "../agent-client-interface"; import { Emitter } from "../utils/event"; import { Tracer, SpanStatusCode } from "@opentelemetry/api"; @@ -88,15 +88,11 @@ export class Tasks { * Gets a task by its ID. */ async get(taskId: string): Promise { - return this.withSpan( - "tasks.get", - { taskId }, - async () => { - const tasks = await this.getAll(); + return this.withSpan("tasks.get", { taskId }, async () => { + const tasks = await this.getAll(); - return tasks.find((task) => task.id === taskId); - } - ); + return tasks.find((task) => task.id === taskId); + }); } } @@ -248,12 +244,12 @@ export class Task { async open(dimensions = DEFAULT_SHELL_SIZE) { return this.withSpan( "task.open", - { + { taskId: this.id, taskName: this.name, cols: dimensions.cols, rows: dimensions.rows, - hasShell: !!this.shell + hasShell: !!this.shell, }, async () => { if (!this.shell) { @@ -278,11 +274,11 @@ export class Task { async waitForPort(timeout: number = 30_000) { return this.withSpan( "task.waitForPort", - { + { taskId: this.id, taskName: this.name, timeout, - existingPortsCount: this.ports.length + existingPortsCount: this.ports.length, }, async () => { if (this.ports.length) { @@ -320,11 +316,11 @@ export class Task { async run() { return this.withSpan( "task.run", - { + { taskId: this.id, taskName: this.name, command: this.command, - runAtStart: this.runAtStart + runAtStart: this.runAtStart, }, async () => { await this.agentClient.tasks.runTask(this.id); @@ -334,10 +330,10 @@ export class Task { async restart() { return this.withSpan( "task.restart", - { + { taskId: this.id, taskName: this.name, - command: this.command + command: this.command, }, async () => { await this.run(); @@ -347,10 +343,10 @@ export class Task { async stop() { return this.withSpan( "task.stop", - { + { taskId: this.id, taskName: this.name, - hasShell: !!this.shell + hasShell: !!this.shell, }, async () => { if (this.shell) { @@ -362,4 +358,4 @@ export class Task { dispose() { this.disposable.dispose(); } -} \ No newline at end of file +} diff --git a/src/SandboxClient/terminals.ts b/src/SandboxClient/terminals.ts index c9c0391..408e5b6 100644 --- a/src/SandboxClient/terminals.ts +++ b/src/SandboxClient/terminals.ts @@ -2,7 +2,7 @@ import * as protocol from "../pitcher-protocol"; import { Disposable } from "../utils/disposable"; import { Emitter } from "../utils/event"; import { isCommandShell, ShellRunOpts } from "./commands"; -import { IAgentClient } from "../AgentClient/agent-client-interface"; +import { IAgentClient } from "../agent-client-interface"; import { Tracer, SpanStatusCode } from "@opentelemetry/api"; export type ShellSize = { cols: number; rows: number }; @@ -104,40 +104,32 @@ export class Terminals { } async get(shellId: string) { - return this.withSpan( - "terminals.get", - { shellId }, - async () => { - const shells = await this.agentClient.shells.getShells(); + return this.withSpan("terminals.get", { shellId }, async () => { + const shells = await this.agentClient.shells.getShells(); - const shell = shells.find((shell) => shell.shellId === shellId); - - if (!shell) { - return; - } + const shell = shells.find((shell) => shell.shellId === shellId); - return new Terminal(shell, this.agentClient, this.tracer); + if (!shell) { + return; } - ); + + return new Terminal(shell, this.agentClient, this.tracer); + }); } /** * Gets all terminals running in the current sandbox */ async getAll() { - return this.withSpan( - "terminals.getAll", - {}, - async () => { - const shells = await this.agentClient.shells.getShells(); + return this.withSpan("terminals.getAll", {}, async () => { + const shells = await this.agentClient.shells.getShells(); - return shells - .filter( - (shell) => shell.shellType === "TERMINAL" && !isCommandShell(shell) - ) - .map((shell) => new Terminal(shell, this.agentClient, this.tracer)); - } - ); + return shells + .filter( + (shell) => shell.shellType === "TERMINAL" && !isCommandShell(shell) + ) + .map((shell) => new Terminal(shell, this.agentClient, this.tracer)); + }); } } @@ -253,7 +245,11 @@ export class Terminal { rows: dimensions.rows, }, async () => { - await this.agentClient.shells.send(this.shell.shellId, input, dimensions); + await this.agentClient.shells.send( + this.shell.shellId, + input, + dimensions + ); } ); } diff --git a/src/AgentClient/agent-client-interface.ts b/src/agent-client-interface.ts similarity index 98% rename from src/AgentClient/agent-client-interface.ts rename to src/agent-client-interface.ts index c84dca5..a5f9a55 100644 --- a/src/AgentClient/agent-client-interface.ts +++ b/src/agent-client-interface.ts @@ -8,8 +8,8 @@ import { setup, task, system, -} from "../pitcher-protocol"; -import { Event } from "../utils/event"; +} from "./pitcher-protocol"; +import { Event } from "./utils/event"; export interface IAgentClientShells { onShellExited: Event<{ diff --git a/src/api-clients/client-pint/client.gen.ts b/src/api-clients/client-pint/client.gen.ts new file mode 100644 index 0000000..1822a95 --- /dev/null +++ b/src/api-clients/client-pint/client.gen.ts @@ -0,0 +1,5 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createClient, createConfig } from '@hey-api/client-fetch'; + +export const client = createClient(createConfig()); \ No newline at end of file diff --git a/src/api-clients/client-pint/index.ts b/src/api-clients/client-pint/index.ts new file mode 100644 index 0000000..e64537d --- /dev/null +++ b/src/api-clients/client-pint/index.ts @@ -0,0 +1,3 @@ +// This file is auto-generated by @hey-api/openapi-ts +export * from './types.gen'; +export * from './sdk.gen'; \ No newline at end of file diff --git a/src/api-clients/client-pint/sdk.gen.ts b/src/api-clients/client-pint/sdk.gen.ts new file mode 100644 index 0000000..486bac0 --- /dev/null +++ b/src/api-clients/client-pint/sdk.gen.ts @@ -0,0 +1,609 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch'; +import type { GetHealthData, GetHealthResponse, GetApiFsEventsData, GetApiFsEventsResponse, GetApiFsStatsByPathData, GetApiFsStatsByPathResponse, GetApiFsStatsByPathError, DeleteApiFsFilesByPathData, DeleteApiFsFilesByPathResponse, DeleteApiFsFilesByPathError, GetApiFsFilesByPathData, GetApiFsFilesByPathResponse, GetApiFsFilesByPathError, PutApiFsFilesByPathData, PutApiFsFilesByPathResponse, PutApiFsFilesByPathError, DeleteApiDirectoriesByPathData, DeleteApiDirectoriesByPathResponse, DeleteApiDirectoriesByPathError, GetApiDirectoriesByPathData, GetApiDirectoriesByPathResponse, GetApiDirectoriesByPathError, PostApiDirectoriesByPathData, PostApiDirectoriesByPathResponse, PostApiDirectoriesByPathError, GetApiTerminalsData, GetApiTerminalsResponse, PostApiTerminalsData, PostApiTerminalsResponse, PostApiTerminalsError, DeleteApiTerminalsByIdData, DeleteApiTerminalsByIdResponse, DeleteApiTerminalsByIdError, GetApiTerminalsByIdData, GetApiTerminalsByIdResponse, GetApiTerminalsByIdError, GetApiTerminalsByIdStdoutData, GetApiTerminalsByIdStdoutResponse, GetApiTerminalsByIdStdoutError, GetApiTerminalsByIdStderrData, GetApiTerminalsByIdStderrResponse, GetApiTerminalsByIdStderrError, PostApiTerminalsByIdStdinData, PostApiTerminalsByIdStdinResponse, PostApiTerminalsByIdStdinError, GetApiTasksData, GetApiTasksResponse, GetApiTasksByIdData, GetApiTasksByIdResponse, GetApiTasksByIdError, PostApiTasksByIdRunData, PostApiTasksByIdRunResponse, PostApiTasksByIdRunError, PostApiTasksByIdStopData, PostApiTasksByIdStopResponse, PostApiTasksByIdStopError, PostApiTasksByIdRestartData, PostApiTasksByIdRestartResponse, PostApiTasksByIdRestartError, GetApiStateData, GetApiStateResponse, GetApiPortsData, GetApiPortsResponse } from './types.gen'; +import { client as _heyApiClient } from './client.gen'; + +export type Options = ClientOptions & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; +}; + +/** + * Health check endpoint + * Returns the health status of the server + */ +export const getHealth = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + url: '/health', + ...options + }); +}; + +/** + * Watch filesystem events + * Watch filesystem changes matching a glob pattern. Use SSE for real-time events. + */ +export const getApiFsEvents = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/fs/events', + ...options + }); +}; + +/** + * Get file or directory stats + * Get filesystem statistics for a file or directory + */ +export const getApiFsStatsByPath = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/fs/stats/{path}', + ...options + }); +}; + +/** + * Delete file + * Delete a file + */ +export const deleteApiFsFilesByPath = (options: Options) => { + return (options.client ?? _heyApiClient).delete({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/fs/files/{path}', + ...options + }); +}; + +/** + * Read file contents + * Read file contents. Use SSE for chunked reading of large files. + */ +export const getApiFsFilesByPath = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/fs/files/{path}', + ...options + }); +}; + +/** + * Write to file + * Write content to file or perform file operations + */ +export const putApiFsFilesByPath = (options: Options) => { + return (options.client ?? _heyApiClient).put({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/fs/files/{path}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); +}; + +/** + * Delete directory + * Delete a directory and all its contents + */ +export const deleteApiDirectoriesByPath = (options: Options) => { + return (options.client ?? _heyApiClient).delete({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/directories/{path}', + ...options + }); +}; + +/** + * List directory contents + * List files and subdirectories in a directory + */ +export const getApiDirectoriesByPath = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/directories/{path}', + ...options + }); +}; + +/** + * Create directory + * Create a new directory + */ +export const postApiDirectoriesByPath = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/directories/{path}', + ...options + }); +}; + +/** + * List terminals + * Get list of all terminals. Use SSE for real-time updates. + */ +export const getApiTerminals = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals', + ...options + }); +}; + +/** + * Create new terminal + * Create a new terminal instance + */ +export const postApiTerminals = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); +}; + +/** + * Delete terminal + * Delete a terminal and kill its process + */ +export const deleteApiTerminalsById = (options: Options) => { + return (options.client ?? _heyApiClient).delete({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals/{id}', + ...options + }); +}; + +/** + * Get terminal state + * Get terminal information and state. Use SSE for real-time updates. + */ +export const getApiTerminalsById = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals/{id}', + ...options + }); +}; + +/** + * Get terminal stdout + * Get terminal stdout output. Use SSE for real-time updates. + */ +export const getApiTerminalsByIdStdout = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals/{id}/stdout', + ...options + }); +}; + +/** + * Get terminal stderr + * Get terminal stderr output. Use SSE for real-time updates. + */ +export const getApiTerminalsByIdStderr = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals/{id}/stderr', + ...options + }); +}; + +/** + * Send input to terminal + * Send input to terminal stdin + */ +export const postApiTerminalsByIdStdin = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/terminals/{id}/stdin', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); +}; + +/** + * List tasks + * Get list of all tasks. Use SSE for real-time updates. + */ +export const getApiTasks = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/tasks', + ...options + }); +}; + +/** + * Get task state + * Get task information and state. Use SSE for real-time updates. + */ +export const getApiTasksById = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/tasks/{id}', + ...options + }); +}; + +/** + * Run task + * Start executing a task + */ +export const postApiTasksByIdRun = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/tasks/{id}/run', + ...options + }); +}; + +/** + * Stop task + * Stop a running task + */ +export const postApiTasksByIdStop = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/tasks/{id}/stop', + ...options + }); +}; + +/** + * Restart task + * Restart a task (stop if running, then start) + */ +export const postApiTasksByIdRestart = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/tasks/{id}/restart', + ...options + }); +}; + +/** + * Get sandbox state + * Get the current state of the sandbox including version and setup status + */ +export const getApiState = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/state', + ...options + }); +}; + +/** + * List open ports + * Get list of open ports. Use SSE for real-time updates. + */ +export const getApiPorts = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + security: [ + { + scheme: 'bearer', + type: 'http' + }, + { + name: 'Authorization', + type: 'apiKey' + }, + { + in: 'query', + name: 'token', + type: 'apiKey' + } + ], + url: '/api/ports', + ...options + }); +}; \ No newline at end of file diff --git a/src/api-clients/client-pint/types.gen.ts b/src/api-clients/client-pint/types.gen.ts new file mode 100644 index 0000000..feab99a --- /dev/null +++ b/src/api-clients/client-pint/types.gen.ts @@ -0,0 +1,856 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ErrorResponse = { + /** + * Error message + */ + error: string; +}; + +export type FileStats = { + /** + * File or directory name + */ + name: string; + /** + * Full path + */ + path: string; + /** + * Whether this is a directory + */ + isDir: boolean; + /** + * File size in bytes + */ + size: number; + /** + * Last modification time + */ + modTime: string; + /** + * File permissions + */ + permissions?: string; +}; + +export type FileOperationResponse = { + message: string; + path: string; + operation: 'write' | 'moveFrom' | 'copyFrom'; + /** + * Number of bytes written (for write operation) + */ + bytesWritten?: number; +}; + +export type FileDeleteResponse = { + message: string; + path: string; +}; + +export type DirectoryCreateResponse = { + message: string; + path: string; +}; + +export type DirectoryListResponse = { + path: string; + entries: Array; +}; + +export type DirectoryDeleteResponse = { + message: string; + path: string; +}; + +export type TerminalListResponse = { + terminals: Array; +}; + +export type TerminalCreateResponse = { + terminal: Terminal; +}; + +export type TerminalResponse = { + terminal: Terminal; +}; + +export type TerminalDeleteResponse = { + message: string; +}; + +export type Terminal = { + /** + * Terminal ID + */ + id: string; + /** + * Command being executed + */ + command: string; + /** + * Command arguments + */ + args?: Array; + /** + * Terminal status + */ + status: 'created' | 'running' | 'finished' | 'error'; + /** + * Process ID + */ + pid: number; + /** + * Working directory + */ + workingDir?: string; + /** + * Creation timestamp + */ + createdAt?: string; +}; + +export type TaskListResponse = { + tasks: Array; +}; + +export type TaskResponse = { + task: Task; +}; + +export type TaskActionResponse = { + message: string; + task: Task; +}; + +export type Task = { + /** + * Task ID + */ + id: string; + /** + * Task name + */ + name: string; + /** + * Command to execute + */ + command: string; + /** + * Task status + */ + status: 'idle' | 'running' | 'finished' | 'error' | 'killed'; + /** + * Associated terminal ID + */ + terminalId?: string; + /** + * Start time + */ + startTime?: string; + /** + * End time + */ + endTime?: string; + /** + * Exit code (if finished) + */ + exitCode?: number; +}; + +export type SandboxState = { + /** + * Pint version + */ + version: string; + /** + * Whether initial setup is completed + */ + setupCompleted: boolean; + /** + * Workspace path + */ + workspace?: string; + /** + * Server uptime in seconds + */ + uptime?: number; +}; + +export type PortListResponse = { + ports: Array; +}; + +export type Port = { + /** + * Port number + */ + port: number; + /** + * Port status + */ + status: 'open' | 'closed' | 'listening'; + /** + * Process name using the port + */ + process?: string; + /** + * Process ID + */ + pid?: number; + /** + * Bind address + */ + address?: string; +}; + +export type GetHealthData = { + body?: never; + path?: never; + query?: never; + url: '/health'; +}; + +export type GetHealthResponses = { + /** + * Server is healthy + */ + 200: { + status?: string; + }; +}; + +export type GetHealthResponse = GetHealthResponses[keyof GetHealthResponses]; + +export type GetApiFsEventsData = { + body?: never; + headers: { + /** + * Glob pattern for files to watch + */ + glob: string; + }; + path?: never; + query?: never; + url: '/api/fs/events'; +}; + +export type GetApiFsEventsResponses = { + /** + * Server-sent events containing filesystem changes + */ + 200: string; +}; + +export type GetApiFsEventsResponse = GetApiFsEventsResponses[keyof GetApiFsEventsResponses]; + +export type GetApiFsStatsByPathData = { + body?: never; + path: { + /** + * File or directory path + */ + path: string; + }; + query?: never; + url: '/api/fs/stats/{path}'; +}; + +export type GetApiFsStatsByPathErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiFsStatsByPathError = GetApiFsStatsByPathErrors[keyof GetApiFsStatsByPathErrors]; + +export type GetApiFsStatsByPathResponses = { + /** + * File stats retrieved successfully + */ + 200: FileStats; +}; + +export type GetApiFsStatsByPathResponse = GetApiFsStatsByPathResponses[keyof GetApiFsStatsByPathResponses]; + +export type DeleteApiFsFilesByPathData = { + body?: never; + path: { + /** + * File path + */ + path: string; + }; + query?: never; + url: '/api/fs/files/{path}'; +}; + +export type DeleteApiFsFilesByPathErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type DeleteApiFsFilesByPathError = DeleteApiFsFilesByPathErrors[keyof DeleteApiFsFilesByPathErrors]; + +export type DeleteApiFsFilesByPathResponses = { + /** + * File deleted successfully + */ + 200: FileDeleteResponse; +}; + +export type DeleteApiFsFilesByPathResponse = DeleteApiFsFilesByPathResponses[keyof DeleteApiFsFilesByPathResponses]; + +export type GetApiFsFilesByPathData = { + body?: never; + path: { + /** + * File path + */ + path: string; + }; + query?: never; + url: '/api/fs/files/{path}'; +}; + +export type GetApiFsFilesByPathErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiFsFilesByPathError = GetApiFsFilesByPathErrors[keyof GetApiFsFilesByPathErrors]; + +export type GetApiFsFilesByPathResponses = { + /** + * File contents + */ + 200: string; +}; + +export type GetApiFsFilesByPathResponse = GetApiFsFilesByPathResponses[keyof GetApiFsFilesByPathResponses]; + +export type PutApiFsFilesByPathData = { + body: { + /** + * File operation to perform + */ + operation: 'write' | 'moveFrom' | 'copyFrom'; + /** + * File content (for write operation) + */ + content?: string; + /** + * Source path (for moveFrom/copyFrom operations) + */ + source?: string; + }; + path: { + /** + * File path + */ + path: string; + }; + query?: never; + url: '/api/fs/files/{path}'; +}; + +export type PutApiFsFilesByPathErrors = { + /** + * Bad request - invalid parameters or request body + */ + 400: ErrorResponse; +}; + +export type PutApiFsFilesByPathError = PutApiFsFilesByPathErrors[keyof PutApiFsFilesByPathErrors]; + +export type PutApiFsFilesByPathResponses = { + /** + * File operation completed successfully + */ + 200: FileOperationResponse; +}; + +export type PutApiFsFilesByPathResponse = PutApiFsFilesByPathResponses[keyof PutApiFsFilesByPathResponses]; + +export type DeleteApiDirectoriesByPathData = { + body?: never; + path: { + /** + * Directory path + */ + path: string; + }; + query?: never; + url: '/api/directories/{path}'; +}; + +export type DeleteApiDirectoriesByPathErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type DeleteApiDirectoriesByPathError = DeleteApiDirectoriesByPathErrors[keyof DeleteApiDirectoriesByPathErrors]; + +export type DeleteApiDirectoriesByPathResponses = { + /** + * Directory deleted successfully + */ + 200: DirectoryDeleteResponse; +}; + +export type DeleteApiDirectoriesByPathResponse = DeleteApiDirectoriesByPathResponses[keyof DeleteApiDirectoriesByPathResponses]; + +export type GetApiDirectoriesByPathData = { + body?: never; + path: { + /** + * Directory path + */ + path: string; + }; + query?: never; + url: '/api/directories/{path}'; +}; + +export type GetApiDirectoriesByPathErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiDirectoriesByPathError = GetApiDirectoriesByPathErrors[keyof GetApiDirectoriesByPathErrors]; + +export type GetApiDirectoriesByPathResponses = { + /** + * Directory contents + */ + 200: DirectoryListResponse; +}; + +export type GetApiDirectoriesByPathResponse = GetApiDirectoriesByPathResponses[keyof GetApiDirectoriesByPathResponses]; + +export type PostApiDirectoriesByPathData = { + body?: never; + path: { + /** + * Directory path + */ + path: string; + }; + query?: never; + url: '/api/directories/{path}'; +}; + +export type PostApiDirectoriesByPathErrors = { + /** + * Bad request - invalid parameters or request body + */ + 400: ErrorResponse; +}; + +export type PostApiDirectoriesByPathError = PostApiDirectoriesByPathErrors[keyof PostApiDirectoriesByPathErrors]; + +export type PostApiDirectoriesByPathResponses = { + /** + * Directory created successfully + */ + 201: DirectoryCreateResponse; +}; + +export type PostApiDirectoriesByPathResponse = PostApiDirectoriesByPathResponses[keyof PostApiDirectoriesByPathResponses]; + +export type GetApiTerminalsData = { + body?: never; + path?: never; + query?: never; + url: '/api/terminals'; +}; + +export type GetApiTerminalsResponses = { + /** + * Terminal list + */ + 200: TerminalListResponse; +}; + +export type GetApiTerminalsResponse = GetApiTerminalsResponses[keyof GetApiTerminalsResponses]; + +export type PostApiTerminalsData = { + body: { + /** + * Command to execute + */ + command: string; + /** + * Command arguments + */ + args?: Array; + /** + * Working directory + */ + workingDir?: string; + }; + path?: never; + query?: never; + url: '/api/terminals'; +}; + +export type PostApiTerminalsErrors = { + /** + * Bad request - invalid parameters or request body + */ + 400: ErrorResponse; +}; + +export type PostApiTerminalsError = PostApiTerminalsErrors[keyof PostApiTerminalsErrors]; + +export type PostApiTerminalsResponses = { + /** + * Terminal created successfully + */ + 201: TerminalCreateResponse; +}; + +export type PostApiTerminalsResponse = PostApiTerminalsResponses[keyof PostApiTerminalsResponses]; + +export type DeleteApiTerminalsByIdData = { + body?: never; + path: { + /** + * Terminal ID + */ + id: string; + }; + query?: never; + url: '/api/terminals/{id}'; +}; + +export type DeleteApiTerminalsByIdErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type DeleteApiTerminalsByIdError = DeleteApiTerminalsByIdErrors[keyof DeleteApiTerminalsByIdErrors]; + +export type DeleteApiTerminalsByIdResponses = { + /** + * Terminal deleted successfully + */ + 200: TerminalDeleteResponse; +}; + +export type DeleteApiTerminalsByIdResponse = DeleteApiTerminalsByIdResponses[keyof DeleteApiTerminalsByIdResponses]; + +export type GetApiTerminalsByIdData = { + body?: never; + path: { + /** + * Terminal ID + */ + id: string; + }; + query?: never; + url: '/api/terminals/{id}'; +}; + +export type GetApiTerminalsByIdErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiTerminalsByIdError = GetApiTerminalsByIdErrors[keyof GetApiTerminalsByIdErrors]; + +export type GetApiTerminalsByIdResponses = { + /** + * Terminal state + */ + 200: TerminalResponse; +}; + +export type GetApiTerminalsByIdResponse = GetApiTerminalsByIdResponses[keyof GetApiTerminalsByIdResponses]; + +export type GetApiTerminalsByIdStdoutData = { + body?: never; + path: { + /** + * Terminal ID + */ + id: string; + }; + query?: never; + url: '/api/terminals/{id}/stdout'; +}; + +export type GetApiTerminalsByIdStdoutErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiTerminalsByIdStdoutError = GetApiTerminalsByIdStdoutErrors[keyof GetApiTerminalsByIdStdoutErrors]; + +export type GetApiTerminalsByIdStdoutResponses = { + /** + * Terminal stdout + */ + 200: string; +}; + +export type GetApiTerminalsByIdStdoutResponse = GetApiTerminalsByIdStdoutResponses[keyof GetApiTerminalsByIdStdoutResponses]; + +export type GetApiTerminalsByIdStderrData = { + body?: never; + path: { + /** + * Terminal ID + */ + id: string; + }; + query?: never; + url: '/api/terminals/{id}/stderr'; +}; + +export type GetApiTerminalsByIdStderrErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiTerminalsByIdStderrError = GetApiTerminalsByIdStderrErrors[keyof GetApiTerminalsByIdStderrErrors]; + +export type GetApiTerminalsByIdStderrResponses = { + /** + * Terminal stderr + */ + 200: string; +}; + +export type GetApiTerminalsByIdStderrResponse = GetApiTerminalsByIdStderrResponses[keyof GetApiTerminalsByIdStderrResponses]; + +export type PostApiTerminalsByIdStdinData = { + body: { + /** + * Input to send to terminal + */ + input: string; + }; + path: { + /** + * Terminal ID + */ + id: string; + }; + query?: never; + url: '/api/terminals/{id}/stdin'; +}; + +export type PostApiTerminalsByIdStdinErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type PostApiTerminalsByIdStdinError = PostApiTerminalsByIdStdinErrors[keyof PostApiTerminalsByIdStdinErrors]; + +export type PostApiTerminalsByIdStdinResponses = { + /** + * Input sent successfully + */ + 200: { + message?: string; + }; +}; + +export type PostApiTerminalsByIdStdinResponse = PostApiTerminalsByIdStdinResponses[keyof PostApiTerminalsByIdStdinResponses]; + +export type GetApiTasksData = { + body?: never; + path?: never; + query?: never; + url: '/api/tasks'; +}; + +export type GetApiTasksResponses = { + /** + * Task list + */ + 200: TaskListResponse; +}; + +export type GetApiTasksResponse = GetApiTasksResponses[keyof GetApiTasksResponses]; + +export type GetApiTasksByIdData = { + body?: never; + path: { + /** + * Task ID + */ + id: string; + }; + query?: never; + url: '/api/tasks/{id}'; +}; + +export type GetApiTasksByIdErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type GetApiTasksByIdError = GetApiTasksByIdErrors[keyof GetApiTasksByIdErrors]; + +export type GetApiTasksByIdResponses = { + /** + * Task state + */ + 200: TaskResponse; +}; + +export type GetApiTasksByIdResponse = GetApiTasksByIdResponses[keyof GetApiTasksByIdResponses]; + +export type PostApiTasksByIdRunData = { + body?: never; + path: { + /** + * Task ID + */ + id: string; + }; + query?: never; + url: '/api/tasks/{id}/run'; +}; + +export type PostApiTasksByIdRunErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; + /** + * Task already running + */ + 409: ErrorResponse; +}; + +export type PostApiTasksByIdRunError = PostApiTasksByIdRunErrors[keyof PostApiTasksByIdRunErrors]; + +export type PostApiTasksByIdRunResponses = { + /** + * Task started successfully + */ + 200: TaskActionResponse; +}; + +export type PostApiTasksByIdRunResponse = PostApiTasksByIdRunResponses[keyof PostApiTasksByIdRunResponses]; + +export type PostApiTasksByIdStopData = { + body?: never; + path: { + /** + * Task ID + */ + id: string; + }; + query?: never; + url: '/api/tasks/{id}/stop'; +}; + +export type PostApiTasksByIdStopErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; + /** + * Task not running + */ + 409: ErrorResponse; +}; + +export type PostApiTasksByIdStopError = PostApiTasksByIdStopErrors[keyof PostApiTasksByIdStopErrors]; + +export type PostApiTasksByIdStopResponses = { + /** + * Task stopped successfully + */ + 200: TaskActionResponse; +}; + +export type PostApiTasksByIdStopResponse = PostApiTasksByIdStopResponses[keyof PostApiTasksByIdStopResponses]; + +export type PostApiTasksByIdRestartData = { + body?: never; + path: { + /** + * Task ID + */ + id: string; + }; + query?: never; + url: '/api/tasks/{id}/restart'; +}; + +export type PostApiTasksByIdRestartErrors = { + /** + * Resource not found + */ + 404: ErrorResponse; +}; + +export type PostApiTasksByIdRestartError = PostApiTasksByIdRestartErrors[keyof PostApiTasksByIdRestartErrors]; + +export type PostApiTasksByIdRestartResponses = { + /** + * Task restarted successfully + */ + 200: TaskActionResponse; +}; + +export type PostApiTasksByIdRestartResponse = PostApiTasksByIdRestartResponses[keyof PostApiTasksByIdRestartResponses]; + +export type GetApiStateData = { + body?: never; + path?: never; + query?: never; + url: '/api/state'; +}; + +export type GetApiStateResponses = { + /** + * Sandbox state + */ + 200: SandboxState; +}; + +export type GetApiStateResponse = GetApiStateResponses[keyof GetApiStateResponses]; + +export type GetApiPortsData = { + body?: never; + path?: never; + query?: never; + url: '/api/ports'; +}; + +export type GetApiPortsResponses = { + /** + * Port list + */ + 200: PortListResponse; +}; + +export type GetApiPortsResponse = GetApiPortsResponses[keyof GetApiPortsResponses]; \ No newline at end of file