diff --git a/.agents/specs/REMOTE-1063-docs-setup-command-openapi.md b/.agents/specs/REMOTE-1063-docs-setup-command-openapi.md new file mode 100644 index 000000000..be8f7c0d9 --- /dev/null +++ b/.agents/specs/REMOTE-1063-docs-setup-command-openapi.md @@ -0,0 +1,217 @@ +*Spec: Docs OpenAPI — expose precise setup-command operations (REMOTE-1063, docs repo)* + +== PRODUCT == +*Summary:* After the warp-server canonical public API adds precise setup-command +update operations for cloud environments, the generated docs OpenAPI at +`developers/agent-api-openapi.yaml` must mirror those operations — paths, +parameters, request/response shapes, and index semantics — so the Scalar API +reference at `docs.warp.dev/api` and the raw `docs.warp.dev/openapi.json` +document them. This spec covers *only* the docs repo's generated OpenAPI file +and the sync mechanics that keep it aligned to the warp-server canonical +contract; the warp-server spec owns the canonical contract shape and is the +source of truth. + +*Key design choices:* +1. **Mirror, don't hand-author.** `developers/agent-api-openapi.yaml` is a + generated curated subset of `warp-server/public_api/openapi.yaml` + (`sync-openapi-spec` skill → `scripts/sync_openapi.py`). The docs change is + produced by running the existing sync tool against an updated canonical + source, not by editing the docs YAML by hand. This keeps the two specs + structurally identical for the included surface. +2. **REST-only public contract.** The existing public environment surface is + REST (`GET /agent/environments`); the OpenAPI spec and the Scalar reference + are REST. The new precise setup-command operations are REST endpoints + committed to `warp-server/public_api/openapi.yaml` and flow through the sync + to docs. GraphQL remains internal and is not part of the documented public + contract (see Design alternatives). +3. **Index semantics live in the contract, not just the CLI.** The documented + operations carry zero-based index parameters with explicit append-at-length + and out-of-range rules, so the CLI, server, and docs all agree on the same + shape (the cross-repo alignment requirement). + +*Behavior* (numbered, testable invariants from the docs consumer's view): +1. The Scalar reference at `docs.warp.dev/api` lists the new precise + setup-command operation(s) for cloud environments alongside the existing + `GET /agent/environments` operation, with HTTP method, path, parameters, + request body, and response codes rendered. +2. The documented surface exposes the setup-commands sub-resource as +multiple verbs under `/agent/environments/{uid}/setup-commands`: `GET` (list), +`PUT` (replace / clear-and-rebuild the whole list), `POST` (add — append when +index omitted, insert at `0..=len`), `PATCH /{index}` (edit one command by +index without resending the rest), `DELETE /{index}` (remove one by index), +and `DELETE` (clear all). The index-based ops (`POST` insert, +`PATCH /{index}`, `DELETE /{index}`) address a single command by index +without the caller resending the unchanged full list. +3. Index parameters are documented as **zero-based**; a `POST` insert at +`index == length` appends (preserves order); an edit (`PATCH /{index}`) or +remove (`DELETE /{index}`) whose index is out of range (`[0, length)`) is +documented as a `404`; a malformed/bad index (e.g. non-integer, negative) is +documented as a `400`. +4. Duplicate setup commands (same text, different positions) are addressable by + index in the documented operations; the docs do not require command text to + be unique. +5. The existing `GET /agent/environments` operation and the + `CloudEnvironmentConfig` schema (including its `setup_commands` array field) + remain present and unchanged in the regenerated docs file — the change is + purely additive for the public surface. +6. `docs.warp.dev/openapi.json` (served from the same source via + `src/pages/api.astro`) reflects the new operations after deploy. + +== TECH == +*Context:* how the docs OpenAPI surface works today (commit-pinned): +- `developers/agent-api-openapi.yaml:1155` (@ `aca5ecce`) — the only environment + path today: `GET /agent/environments` (`operationId: listEnvironments`, tag + `agent`, `bearerAuth`, `sort_by` query param). Mirrors the canonical. +- `developers/agent-api-openapi.yaml:2908` — `CloudEnvironmentConfig` schema; + `setup_commands` at `:2927` is `array of string` ("Shell commands to run + during environment setup"). No setup-command CRUD operations exist. +- `src/pages/api.astro:16` reads `developers/agent-api-openapi.yaml` and feeds + Scalar; `:213` links the raw `openapi.json`. So one YAML file powers both the + rendered reference and the JSON download. +- Canonical source of truth: `warp-server/public_api/openapi.yaml:3980` + (`GET /agent/environments`) and `:7774` (`CloudEnvironmentConfig`, + `setup_commands` at `:7793`) @ `21fbda3f`. The server REST handler + `warp-server/router/handlers/public_api/agent_environments.go:48` + (`RegisterAgentEnvironmentRoutes`) registers only the GET route today — no + update/create/delete/setup-command handlers exist yet. GraphQL + `warp-server/graphql/v2/cloud_environment.graphqls:49` exposes + `setupCommands: [String!]` but is internal, not the documented public + contract. +- Sync tool: `docs/.agents/skills/sync-openapi-spec/scripts/sync_openapi.py` + (`EXCLUDED_TAGS` at `:44` = `{memory_stores, harness-support}`; + `EXCLUDED_PATHS` at `:48`; `KNOWN_TAGS` at `:343` = `{agent, schedules}` ∪ + excluded). Policy doc: `references/sync-policy.md`. Direction is + warp-server → docs; apply mode validates every `$ref` resolves before + writing (exit 3 on failure). + +*Design alternatives* (per decision point with more than one reasonable +approach): +- **REST vs GraphQL vs both for the public contract** — options: + (a) *REST only* (chosen): matches the existing `GET /agent/environments` + public surface, the OpenAPI/Scalar reference, and `docs.warp.dev/api`. The + server already wraps a GraphQL resolver for listing but exposes REST + publicly; adding REST precise-update ops keeps the documented contract + consistent and reviewable in one spec. (b) *GraphQL only*: would require a + new public GraphQL surface and a different docs rendering path; Scalar + renders OpenAPI/REST, so this would not flow through the existing sync. (c) + *Both*: doubles the documented surface and the cross-repo alignment cost for + no user-facing benefit today. → REST only. +- **Where index semantics live** — options: + (a) *In the contract* (chosen): the documented operations carry index + parameters and explicit bounds, so CLI/server/docs agree on one shape (the + brief's cross-repo requirement). (b) *Contract is full-replacement only + (`PUT` the whole `setup_commands` list), CLI computes the final list*: simpler + contract but moves index semantics out of the shared contract, so the three + specs cannot "agree on the same index semantics" — rejected for this + multi-repo task. → contract carries index semantics. +- **Endpoint shape** — **binding per warp-server's committed REST contract** + (the docs file mirrors it verbatim via the sync): a multi-verb sub-resource + under `/agent/environments/{uid}/setup-commands` (mounted at + `/api/v1/agent/environments/{uid}/setup-commands`): `GET` (list), `PUT` + (replace / clear-and-rebuild), `POST` (add — append when index omitted, + insert at `0..=len`), `PATCH /{index}` (edit by index), `DELETE /{index}` + (remove by index), `DELETE` (clear all). Alternatives weighed before + warp-server committed: (a) a single `PATCH` with an ordered `operations` + array body (insert/edit/remove/append/clear/replace) — fewer endpoints but a + less standard REST shape and a compound request body; (b) a whole-config + `PATCH /agent/environments/{uid}` with a setup-commands patch nested under + config — broader blast radius implying a general environment update + contract. warp-server chose the multi-verb sub-resource; the docs file + mirrors that exact surface, so the validation criteria below check for those + verbs and the `{uid}` path parameter. +- **New tag or reuse `agent`** — options: + (a) *Reuse the `agent` tag* (proposed): the new operations flow through the + sync automatically (`agent` ∈ `KNOWN_TAGS`, path not in `EXCLUDED_PATHS`) — + no policy change needed. (b) *Introduce an `environments` tag*: would require + extending `KNOWN_TAGS`/`EXCLUDED_TAGS` and `references/sync-policy.md` or the + diff flags it with `!` for triage. → reuse `agent` unless the warp-server + spec introduces a new tag, in which case the sync policy MUST be updated + (criterion 2). + +*Proposed changes* (docs repo): +1. **Regenerate** `developers/agent-api-openapi.yaml` by running + `scripts/sync_openapi.py --mode apply --source --target developers/agent-api-openapi.yaml` once + the warp-server canonical lands the setup-commands sub-resource. The + regenerated file adds the new paths — `/agent/environments/{uid}/setup-commands` + and `/agent/environments/{uid}/setup-commands/{index}` — the per-verb + operations (`GET`/`PUT`/`POST`/`PATCH`/`DELETE`), their request/response + schemas (e.g. add/replace/edit request bodies and the list response), and + the `Error`-referenced error responses — mirroring the canonical verbatim + for the included surface. +2. **Sync policy** (only if needed): if the warp-server spec introduces a new + tag (not `agent`/`schedules`) or a path that should stay hidden, update + `EXCLUDED_TAGS`/`EXCLUDED_PATHS` in `scripts/sync_openapi.py` and record the + rationale in `references/sync-policy.md`. If the new ops reuse the `agent` + tag and are public, no policy change is required. +3. **No hand-edits** to the generated YAML outside the sync tool's output; the + file remains a generated artifact so future syncs are clean. +4. **Sequencing note (for the foreman/implementation):** the docs sync + `--mode apply` step requires a `warp-server/public_api/openapi.yaml` that + already contains the new operations. The docs implementation child therefore + runs the sync against the warp-server branch/commit that lands the contract + (or waits until that contract is merged). The docs PR may land in two phases: + (i) this spec file (+ any sync-policy update), (ii) the regenerated YAML + once the canonical source is available. Both phases land on this same PR + branch. + +*Open questions resolved* (each ambiguity and how it was settled; the +warp-server spec is the source of truth for the exact contract, these are the +docs-side assumptions that keep all three specs aligned — surfaced in the +approval request for ben to confirm): +- **Index base: zero-based.** Settled from the JSON array model + (`setup_commands: array of string`) and OpenAPI/JSON conventions; avoids + off-by-one translation between the API and the underlying model. The CLI may + display one-based indexes in help text, but the *contract* is zero-based and + all three specs agree on zero-based. *Assumption to confirm:* ben may prefer + one-based for CLI ergonomics — if so, the CLI maps one-based→zero-based at the + edge and the contract stays zero-based. +- **Insert permits append-at-length: yes.** `POST` insert at `index == length` + appends and preserves order; an insert `index > length` is out of range. + Per warp-server's binding contract: edit/remove out of range → `404`; a bad + (malformed/negative) index → `400`. Settled as standard list-insert + semantics; supports `--insert-setup-command ` as an append. +- **Duplicate-command addressing: by index.** Setup commands may legitimately + repeat, so the precise ops address by index, not by text. The existing + text-based `--remove-setup-command` CLI flag is preserved for compatibility + and is translated client-side (find first text match → its index → + `DELETE /{index}`); the public contract is index-based only. Settled from the + ticket's "edit one setup command by index without resending" requirement. +- **Public contract: REST.** Settled from the existing REST public surface and + the Scalar/OpenAPI docs pipeline; GraphQL stays internal. See Design + alternatives. +- **Exact endpoint path/shape: binding per warp-server.** Multi-verb + sub-resource under `/agent/environments/{uid}/setup-commands` (mounted at + `/api/v1/...`): `GET` list, `PUT` replace/clear-and-rebuild, `POST` add + (append when index omitted, insert at `0..=len`), `PATCH /{index}` edit, + `DELETE /{index}` remove, `DELETE` clear. The docs file mirrors this exact + surface verbatim via the sync; the validation criteria check for these verbs + and the `{uid}` path parameter. + +*Risks / blast radius:* +- The docs file is generated; a hand-edit would be overwritten on the next + sync. Mitigation: only change it via `sync_openapi.py --mode apply`. +- If the warp-server contract introduces a new tag/path, the sync diff flags it + `!` and the docs PR must update the sync policy or the build/sync is blocked. + Mitigation: criterion 2 enforces zero `!` flags before merge. +- Cross-repo drift: if the docs file diverges from the canonical (e.g. stale + schema names or index semantics), the Scalar reference would document a + contract the server doesn't implement. Mitigation: criterion 10 enforces + `--mode diff` shows the docs file equals the curated canonical subset. +- The docs sync depends on the warp-server contract landing first; the docs PR + cannot be merged with a regenerated YAML until that source exists + (criterion 1 runs against the updated canonical). + +*Validation & verification criteria* (must ALL pass before merge of the docs +PR; criteria 1–4 run against a `warp-server/public_api/openapi.yaml` that +already contains the new setup-command operations): +1. `python3 .agents/skills/sync-openapi-spec/scripts/sync_openapi.py --mode apply --source ../warp-server/public_api/openapi.yaml --target developers/agent-api-openapi.yaml` regenerates the docs file containing the new setup-command operation(s) and exits 0 with "All $refs resolve in the regenerated spec." (every `$ref` resolves). - verifies behavior #1, #2. +2. `python3 .agents/skills/sync-openapi-spec/scripts/sync_openapi.py --mode diff --source ../warp-server/public_api/openapi.yaml --target developers/agent-api-openapi.yaml` reports **no `!` unclassified items**: the new operations either reuse the `agent` tag (no policy change) OR `EXCLUDED_TAGS`/`KNOWN_TAGS` in `scripts/sync_openapi.py` and `references/sync-policy.md` have been updated with a rationale for any new tag/path. - verifies the sync policy stays consistent. +3. The regenerated `developers/agent-api-openapi.yaml` contains the setup-commands sub-resource the warp-server canonical commits: paths `/agent/environments/{uid}/setup-commands` and `/agent/environments/{uid}/setup-commands/{index}`, with `GET` (list), `PUT` (replace/clear-and-rebuild), `POST` (add; append when index omitted, insert at `0..=len`), `PATCH /{index}` (edit by index), `DELETE /{index}` (remove by index), and `DELETE` (clear all) operations — each with `bearerAuth` security, the appropriate request body schema, and `200`/`201`/`204`/`400`/`401`/`403`/`404`/`500` responses (error responses `$ref` `#/components/schemas/Error`). - verifies behavior #1, #2; checked by grepping the regenerated YAML for the committed operationIds/paths and schema names. +4. The regenerated docs file documents the **zero-based** index semantics in the operation/schema `description` fields, matching the warp-server canonical verbatim: `POST` insert at `index == length` appends; edit (`PATCH /{index}`) / remove (`DELETE /{index}`) out of range → `404`; a bad (malformed/negative) index → `400`; duplicate command text allowed and addressed by index. - verifies behavior #3, #4; checked by reading the regenerated schema descriptions and confirming they equal the canonical's. +5. `npm run build` succeeds (Astro picks up the regenerated YAML and Scalar parses it at build time). - verifies behavior #1, #6; the docs repo's documented build check. +6. (Recommended when schemas changed) `npx @redocly/cli lint developers/agent-api-openapi.yaml` passes with no errors. - belt-and-braces OpenAPI lint. +7. No regressions to the existing public surface: the regenerated docs file still contains `GET /agent/environments` (`operationId: listEnvironments`) and the `CloudEnvironmentConfig` schema with its `setup_commands` array field, unchanged; `--mode diff` shows the new operations as **additions** only (no removals of existing public paths/schemas). - verifies behavior #5. +8. The docs PR records the warp-server source commit SHA used for the sync and the count of paths/schemas added/modified (per the sync-openapi-spec skill's reporting step). - traceability of the generated artifact to its source. +9. Cross-repo alignment: the docs sub-resource paths (`/agent/environments/{uid}/setup-commands` and `.../{index}`), the `{uid}` path parameter name, the per-verb operationIds, request/response schema `$ref` names, HTTP status codes (`404` out-of-range edit/remove, `400` bad index), and zero-based index semantics exactly match `warp-server/public_api/openapi.yaml`. - verifies the three specs agree on one contract; checked by `--mode diff` reporting the docs file equals the curated subset of the canonical (no docs-only divergence). +10. After deploy, `docs.warp.dev/api` (Scalar) and `docs.warp.dev/openapi.json` expose the new operations. For the PR itself, verify via the `npm run build` output that the new path is present in the built spec; live deploy verification is post-merge. - verifies behavior #1, #6. diff --git a/developers/agent-api-openapi.yaml b/developers/agent-api-openapi.yaml index 870bee047..e49cbe321 100644 --- a/developers/agent-api-openapi.yaml +++ b/developers/agent-api-openapi.yaml @@ -1197,6 +1197,325 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + '/agent/environments/{uid}/setup-commands': + get: + summary: List environment setup commands + description: | + Return the environment's current ordered `setup_commands` as a JSON array, + 0-indexed in array order. An environment with no setup commands returns + an empty array. Duplicate command text is permitted: each entry is a + distinct element addressed by its zero-based index. Requires update + permission on the environment. + operationId: listEnvironmentSetupCommands + tags: + - agent + security: + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/EnvironmentUID' + responses: + '200': + description: The environment's ordered setup commands + content: + application/json: + schema: + $ref: '#/components/schemas/SetupCommandsResponse' + '401': + description: Authentication required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: No permission to update the environment + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Environment not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + put: + summary: Replace environment setup commands + description: | + Replace the environment's entire `setup_commands` list with the provided + array (the "clear and rebuild" operation). An empty array or an omitted + field clears the list. The resulting list equals the request array in + order. Duplicate command text is permitted and preserved in order; + entries are addressed by their zero-based index. Requires update + permission on the environment. + operationId: replaceEnvironmentSetupCommands + tags: + - agent + security: + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/EnvironmentUID' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ReplaceSetupCommandsRequest' + responses: + '200': + description: The replaced setup commands + content: + application/json: + schema: + $ref: '#/components/schemas/SetupCommandsResponse' + '400': + description: Invalid setup command(s) or list size + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Authentication required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: No permission to update the environment + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Environment not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + summary: Add or insert an environment setup command + description: | + Append a command to the end of `setup_commands` when `index` is omitted. + When `index` is provided and `0 <= index <= len`, insert the command at + that position, shifting the element previously at `index` and all later + elements right by one; `index == len` appends. `index < 0` or + `index > len` is a 400. Duplicate command text is allowed: the new + command may equal an existing entry, since list entries are addressed by + their zero-based index, not by text. Requires update permission on the + environment. + operationId: addEnvironmentSetupCommand + tags: + - agent + security: + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/EnvironmentUID' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AddSetupCommandRequest' + responses: + '200': + description: The updated setup commands + content: + application/json: + schema: + $ref: '#/components/schemas/SetupCommandsResponse' + '400': + description: Invalid index or setup command + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Authentication required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: No permission to update the environment + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Environment not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + summary: Clear all environment setup commands + description: | + Remove every setup command from the environment; the resulting list is + empty. Requires update permission on the environment. + operationId: clearEnvironmentSetupCommands + tags: + - agent + security: + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/EnvironmentUID' + responses: + '204': + description: Setup commands cleared + '401': + description: Authentication required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: No permission to update the environment + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Environment not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '/agent/environments/{uid}/setup-commands/{index}': + patch: + summary: Edit an environment setup command by index + description: | + Replace only the command at `index` with the provided `command`, leaving + all other entries and the list length unchanged. `index` is 0-based and + must reference an existing entry (`0 <= index < len`); an out-of-range + index returns 404 and a non-integer/negative index returns 400. + Duplicate command text is allowed: editing index `i` changes only that + slot, so any other entry with the same text is left untouched. + Requires update permission on the environment. + operationId: updateEnvironmentSetupCommand + tags: + - agent + security: + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/EnvironmentUID' + - $ref: '#/components/parameters/SetupCommandIndex' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateSetupCommandRequest' + responses: + '200': + description: The updated setup commands + content: + application/json: + schema: + $ref: '#/components/schemas/SetupCommandsResponse' + '400': + description: Invalid index or setup command + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Authentication required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: No permission to update the environment + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Environment or setup command index not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + summary: Remove an environment setup command by index + description: | + Remove the command at `index`, shifting later elements left by one; the + list length decreases by one. `index` is 0-based and must reference an + existing entry (`0 <= index < len`); an out-of-range index returns 404 + and a non-integer/negative index returns 400. Duplicate command text is + allowed: removing index `i` affects only that slot, so any other entry + with the same text is left untouched. Requires update permission on the + environment. + operationId: removeEnvironmentSetupCommand + tags: + - agent + security: + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/EnvironmentUID' + - $ref: '#/components/parameters/SetupCommandIndex' + responses: + '204': + description: Setup command removed + '400': + description: Invalid index + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Authentication required + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: No permission to update the environment + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Environment or setup command index not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' /agent/models: get: summary: List available models @@ -1577,6 +1896,26 @@ components: scheme: bearer description: | Authentication via a Warp API key. + parameters: + EnvironmentUID: + name: uid + in: path + description: The unique identifier of the cloud environment. + required: true + schema: + type: string + SetupCommandIndex: + name: index + in: path + description: | + Zero-based index of a setup command within the environment's + `setup_commands` array. Must be a non-negative integer; an + out-of-range integer returns 404 and a non-integer or negative + value returns 400. + required: true + schema: + type: integer + minimum: 0 schemas: RunAgentRequest: type: object @@ -2931,6 +3270,85 @@ components: description: Shell commands to run during environment setup providers: $ref: '#/components/schemas/ProvidersConfig' + SetupCommandsResponse: + type: object + description: | + The environment's ordered setup commands. `setup_commands` is the + current list in array order (0-indexed); an environment with no setup + commands returns an empty array. Duplicate command text is permitted: + each list entry is a distinct element addressed by its zero-based + index, so editing or removing index `i` changes only that slot. + required: + - setup_commands + properties: + setup_commands: + type: array + maxItems: 100 + items: + type: string + minLength: 1 + maxLength: 4096 + description: The environment's ordered setup commands + ReplaceSetupCommandsRequest: + type: object + description: | + Request body for replacing an environment's entire setup_commands list + (the "clear and rebuild" operation). An empty array or an omitted + field clears the list. The resulting list equals the request array in + order. Duplicate command text is permitted and preserved in order; + entries are addressed by their zero-based index. + properties: + setup_commands: + type: array + maxItems: 100 + items: + type: string + minLength: 1 + maxLength: 4096 + description: The full replacement list of setup commands + AddSetupCommandRequest: + type: object + description: | + Request body for adding or inserting a single setup command. When + `index` is omitted the command is appended; when `index` is provided + and `0 <= index <= len` the command is inserted at that position + (`index == len` appends). `index < 0` or `index > len` is a 400. + Duplicate command text is permitted: the new command may equal an + existing entry, since each entry is addressed by its zero-based index. + required: + - command + properties: + command: + type: string + minLength: 1 + maxLength: 4096 + x-oapi-codegen-extra-tags: + binding: required + description: The setup command to add or insert. + index: + type: integer + minimum: 0 + x-go-type-skip-optional-pointer: false + description: | + Optional 0-based position to insert at. Omit to append. Must + satisfy `0 <= index <= len`; `index == len` appends. + UpdateSetupCommandRequest: + type: object + description: | + Request body for editing a single setup command by index. Replaces only + the command at the path `index` with the provided `command`. Duplicate + command text is permitted: editing index `i` changes only that slot and + leaves any other entry with the same text untouched. + required: + - command + properties: + command: + type: string + minLength: 1 + maxLength: 4096 + x-oapi-codegen-extra-tags: + binding: required + description: The replacement setup command. ProvidersConfig: type: object description: Optional cloud provider configurations for automatic auth