openapi: "3.0.3" info: title: Pipeline Runner API version: "0.1.0" description: >- REST API for managing and executing AI pipelines. Each pipeline consists of ordered prompts that are executed sequentially via opencode. servers: - url: http://localhost:8080 description: Local development server tags: - name: Pipelines description: Pipeline CRUD operations - name: Runs description: Pipeline execution and monitoring paths: /api/pipelines: get: tags: - Pipelines summary: List all pipelines description: Returns all stored pipelines as a JSON array. operationId: listPipelines responses: "200": description: A JSON array of all pipelines headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: application/json: schema: type: array items: $ref: '#/components/schemas/Pipeline' example: - id: "my-pipeline" name: "My Pipeline" working_dir: "/workspace" created_at: "2025-01-15T10:30:00Z" updated_at: "2025-01-15T10:30:00Z" prompts: - id: "p1" text: "Summarize the document" title: "Summarization" order: 0 - id: "p2" text: "Translate to French" title: "Translation" order: 1 "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Internal server error" post: tags: - Pipelines summary: Create a new pipeline description: >- Creates a new pipeline and persists it as a JSON file. Returns the created pipeline with generated timestamps. operationId: createPipeline requestBody: required: true description: Pipeline data to create content: application/json: schema: $ref: '#/components/schemas/CreatePipelineRequest' example: id: "my-pipeline" name: "My Pipeline" working_dir: "/workspace" prompts: - id: "p1" text: "Summarize the document" title: "Summarization" order: 0 - id: "p2" text: "Translate to French" title: "Translation" order: 1 responses: "200": description: Pipeline created successfully headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: application/json: schema: $ref: '#/components/schemas/Pipeline' example: id: "my-pipeline" name: "My Pipeline" working_dir: "/workspace" created_at: "2025-01-15T10:30:00Z" updated_at: "2025-01-15T10:30:00Z" prompts: - id: "p1" text: "Summarize the document" title: "Summarization" order: 0 "400": description: Invalid request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: invalidJson: summary: Malformed JSON body value: error: "Invalid JSON" missingFields: summary: Missing required fields value: error: "id and name are required" "409": description: Pipeline with this ID already exists content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Pipeline already exists" "500": description: Failed to save pipeline content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Failed to save pipeline" /api/pipelines/{id}: get: tags: - Pipelines summary: Get a single pipeline by ID description: Returns a specific pipeline by its ID. operationId: getPipeline parameters: - name: id in: path required: true description: The pipeline ID schema: type: string responses: "200": description: Pipeline found headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: application/json: schema: $ref: '#/components/schemas/Pipeline' "404": description: Pipeline not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Pipeline not found" delete: tags: - Pipelines summary: Delete a pipeline description: Deletes a pipeline by its ID. Removes the corresponding JSON file. operationId: deletePipeline parameters: - name: id in: path required: true description: The pipeline ID schema: type: string responses: "200": description: Pipeline deleted successfully headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: application/json: schema: $ref: '#/components/schemas/DeletePipelineResponse' example: deleted: "my-pipeline" "404": description: Pipeline not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Pipeline not found" "500": description: Failed to delete pipeline content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Failed to delete pipeline" /api/runs: post: tags: - Runs summary: Start a pipeline execution description: >- Starts asynchronous execution of a pipeline. Each step runs `opencode run --title ` with a 300-second timeout. Execution stops on the first step error. operationId: startRun requestBody: required: true description: Pipeline ID to execute content: application/json: schema: $ref: '#/components/schemas/StartRunRequest' example: pipeline_id: "my-pipeline" responses: "200": description: Run started successfully headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: application/json: schema: $ref: '#/components/schemas/StartRunResponse' example: run_id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" pipeline_id: "my-pipeline" status: "running" "400": description: Invalid request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: invalidJson: summary: Malformed JSON body value: error: "Invalid JSON" missingPipelineId: summary: Missing pipeline_id value: error: "pipeline_id is required" "404": description: Pipeline not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Pipeline not found" "500": description: Failed to start run content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Failed to start run" /api/runs/{run_id}/status: get: tags: - Runs summary: Get run status and step results description: >- Returns the current execution state of a run, including the status of each step. Poll this endpoint to track progress. operationId: getRunStatus parameters: - name: run_id in: path required: true description: The run ID returned by POST /api/runs schema: type: string responses: "200": description: Run state headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: application/json: schema: $ref: '#/components/schemas/RunState' example: run_id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" pipeline_id: "my-pipeline" status: "running" current_step: 1 steps: - step_index: 0 title: "Summarization" status: "completed" returncode: 0 output: "Document summary generated." error: "" "404": description: Run not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: "Run not found" /api/runs/{run_id}/log: get: tags: - Runs summary: Get run log file contents description: Returns the raw log file for a given run as plain text. operationId: getRunLog parameters: - name: run_id in: path required: true description: The run ID returned by POST /api/runs schema: type: string responses: "200": description: Log file contents headers: Access-Control-Allow-Origin: schema: type: string description: CORS wildcard origin content: text/plain: schema: type: string description: Raw log contents example: | [2025-01-15T10:30:01Z] Starting pipeline: my-pipeline [2025-01-15T10:30:01Z] Step 0: Summarization - running [2025-01-15T10:30:05Z] Step 0: Summarization - completed (rc=0) [2025-01-15T10:30:05Z] Step 1: Translation - running components: schemas: Pipeline: type: object required: - id - name - prompts properties: id: type: string description: Unique pipeline identifier example: "my-pipeline" name: type: string description: Human-readable pipeline name example: "My Pipeline" working_dir: type: string description: Working directory for pipeline execution example: "/workspace" created_at: type: string format: date-time description: ISO 8601 timestamp of pipeline creation example: "2025-01-15T10:30:00Z" updated_at: type: string format: date-time description: ISO 8601 timestamp of last update example: "2025-01-15T10:30:00Z" prompts: type: array description: Ordered list of prompts to execute items: $ref: '#/components/schemas/Prompt' Prompt: type: object required: - id - text properties: id: type: string description: Unique prompt identifier within the pipeline example: "p1" text: type: string description: Prompt text passed to `opencode run` example: "Summarize the document" title: type: string description: Display title for the step example: "Summarization" order: type: integer description: Execution order (lower values run first) default: 0 example: 0 CreatePipelineRequest: type: object required: - id - name properties: id: type: string description: Unique pipeline identifier example: "my-pipeline" name: type: string description: Human-readable pipeline name example: "My Pipeline" working_dir: type: string description: Working directory for pipeline execution example: "/workspace" prompts: type: array description: Ordered list of prompts to execute items: $ref: '#/components/schemas/Prompt' DeletePipelineResponse: type: object properties: deleted: type: string description: ID of the deleted pipeline example: "my-pipeline" StartRunRequest: type: object required: - pipeline_id properties: pipeline_id: type: string description: ID of the pipeline to execute example: "my-pipeline" StartRunResponse: type: object properties: run_id: type: string description: Unique identifier for this execution run example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" pipeline_id: type: string description: ID of the executed pipeline example: "my-pipeline" status: type: string enum: - running description: Initial status is always "running" example: "running" RunState: type: object properties: run_id: type: string description: Unique identifier for this execution run example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" pipeline_id: type: string description: ID of the executed pipeline example: "my-pipeline" status: type: string enum: - pending - running - completed - error description: >- Current status of the run. "pending" before execution begins, "running" during execution, "completed" on success, "error" if any step failed. example: "running" current_step: type: integer description: >- Index of the step currently being executed, or -1 if not yet started. example: 1 steps: type: array description: Results of each executed step in order items: $ref: '#/components/schemas/StepResult' StepResult: type: object properties: step_index: type: integer description: Zero-based index of the step in the pipeline example: 0 title: type: string description: Display title of the step example: "Summarization" status: type: string enum: - pending - running - completed - error description: Status of this individual step example: "completed" returncode: type: integer description: Process exit code (0 for success) example: 0 output: type: string description: Standard output from the step execution example: "Document summary generated." error: type: string description: Standard error or error message from the step example: "" ErrorResponse: type: object properties: error: type: string description: Human-readable error message example: "Pipeline not found"