diff --git a/.github/workflows/receive-endpoint-event.yml b/.github/workflows/receive-endpoint-event.yml new file mode 100644 index 00000000..6ddaa13b --- /dev/null +++ b/.github/workflows/receive-endpoint-event.yml @@ -0,0 +1,219 @@ +name: Receive endpoint change and generate CLI PR + +on: + workflow_dispatch: + inputs: + client_payload: + description: "Full client_payload JSON (the object under client_payload from the dispatch body)" + required: true + default: '{"relevant": true, "source_pr_url": "", "commit": "", "summary": "1 supported endpoint(s) affected: GET /api/v1/analytics/team", "changed_files": ["src/api/analytics/router.ts"], "changed_endpoints": [{"method": "GET", "path": "/api/v1/analytics/team", "change_type": "modified", "auth": ["userApiToken"], "summary": "team analytics", "source": "typescript", "api_server_files": ["src/api/analytics/router.ts"], "id": "analytics-team", "cli_command": "cloudos analytics team", "cli_source_file": "cloudos_cli/analytics/analytics.py", "query_params": ["teamId"]}]}' + +permissions: + contents: read + +jobs: + generate-pr: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.AGENT_PR_PAT }} + fetch-depth: 0 + + - name: Resolve payload + id: payload + env: + # Use env vars to safely pass user inputs — avoids single-quote injection + # when the JSON payload contains quotes. + CLIENT_PAYLOAD: ${{ inputs.client_payload }} + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + # workflow_dispatch receives the client_payload object as a JSON string + # input — write it via env var (safe against single-quote injection). + printf '%s' "$CLIENT_PAYLOAD" > /tmp/payload.json + else + # repository_dispatch: client_payload is already JSON — write via tojson filter + cat <<'EOJSON' > /tmp/payload.json + ${{ toJson(github.event.client_payload) }} + EOJSON + fi + + - name: Build Copilot PR body + run: | + python3 - <<'EOF' + import json + import sys + + payload = json.load(open("/tmp/payload.json")) + + if not payload.get("relevant", True): + print("Payload marked as not relevant — skipping.") + sys.exit(0) + + endpoints = payload.get("changed_endpoints", []) + if not endpoints: + print("No changed endpoints in payload — skipping.") + sys.exit(0) + + source_pr = payload.get("source_pr_url") or "manual trigger" + commit = payload.get("commit", "") + overall = payload.get("summary", "") + changed_files = payload.get("changed_files", []) + version = open("cloudos_cli/_version.py").read().strip() + + fence = "```" + + def fmt_list(items): + return ", ".join(items) if items else "—" + + # Group endpoints by the CLI source file they map to, so the agent can + # tackle one module at a time. + by_file = {} + for ep in endpoints: + by_file.setdefault(ep.get("cli_source_file") or "(unknown)", []).append(ep) + + lines = [] + lines.append("## Sync cloudos-cli with a CloudOS API endpoint change\n") + lines.append(f"**Source PR:** {source_pr} ") + if commit: + lines.append(f"**api-server commit:** `{commit}` ") + lines.append(f"**Summary:** {overall}\n") + + lines.append("### What changed (and where to act)\n") + lines.append( + "Each endpoint below was detected as changed in the api-server. " + "`source` tells you whether the change was found in the OpenAPI " + "`specification.yaml` (`specification`), in the TypeScript route/handler " + "code (`typescript`), or both. A `typescript`-only change means the " + "public contract may have shifted WITHOUT a spec update — read the " + "linked api-server files carefully before assuming the request/response " + "shape.\n" + ) + + for ep in endpoints: + method = ep.get("method") or "" + path = ep.get("path") or "" + change = ep.get("change_type") or "modified" + header = f"#### `{change}` — {method} {path}".strip() + lines.append(header) + if ep.get("new_path"): + lines.append(f"- **Renamed/new path:** `{ep['new_path']}`") + if ep.get("id"): + lines.append(f"- **Endpoint id:** `{ep['id']}` (key in `supported-endpoints.json`)") + if ep.get("cli_command"): + lines.append(f"- **CLI command to update:** `{ep['cli_command']}`") + if ep.get("cli_source_file"): + lines.append(f"- **CLI source file:** `{ep['cli_source_file']}`") + if ep.get("query_params"): + lines.append(f"- **Query params:** {fmt_list(ep['query_params'])}") + if ep.get("auth"): + lines.append(f"- **Auth strategies:** {fmt_list(ep['auth'])}") + lines.append(f"- **Detection source:** {ep.get('source', 'specification')}") + if ep.get("api_server_files"): + lines.append( + "- **api-server files that changed:** " + + fmt_list([f"`{f}`" for f in ep["api_server_files"]]) + ) + if ep.get("summary"): + lines.append(f"- **Notes:** {ep['summary']}") + lines.append("") + + if changed_files: + lines.append("
All changed api-server files\n") + for f in changed_files: + lines.append(f"- `{f}`") + lines.append("\n
\n") + + lines.append("### Full machine-readable payload\n") + lines.append(f"{fence}json\n{json.dumps(endpoints, indent=2)}\n{fence}\n") + + lines.append("### How cloudos-cli is structured\n") + lines.append( + "- CLI command groups register in `cloudos_cli/__main__.py`.\n" + "- Each module under `cloudos_cli//` has a `cli.py` (Click " + "commands / options) plus a logic class (e.g. `.py`) that " + "usually extends `Cloudos` in `cloudos_cli/clos.py`.\n" + "- All HTTP calls go through the wrappers in " + "`cloudos_cli/utils/requests.py` and send the `apikey` header.\n" + "- `supported-endpoints.json` is the source of truth mapping each " + "endpoint to its `cli_command` and `source_file`.\n" + ) + + lines.append("### Required steps\n") + lines.append( + "1. For every endpoint above, open its `cli_source_file` (fall back to " + "looking it up by `id` in `supported-endpoints.json` if missing) and " + "the api-server files listed, to understand the exact contract change.\n" + "2. Apply the change according to `change_type`:\n" + " - `added`: add the new command/option and wrapper call.\n" + " - `modified`: update params, request body, response parsing, and " + "any affected Click options to match the new contract.\n" + " - `removed`: deprecate/remove the wrapping command and its tests.\n" + " - renamed (`new_path` present): update the request path/URL builder.\n" + "3. Route all HTTP changes through `cloudos_cli/utils/requests.py`, keep " + "the `apikey` header, and match the style of neighbouring commands.\n" + "4. Add or update at least 2 tests under `tests//` using pytest " + "and `responses` (`@responses.activate`), covering happy path and one " + "failure/edge case.\n" + f"5. Bump the patch version in `cloudos_cli/_version.py` (currently " + f"`{version}`) and add a top `CHANGELOG.md` entry in the existing format.\n" + "6. Update `supported-endpoints.json` so the mapping reflects the new " + "path/params/method (and bump its `cli_version` if you change behaviour).\n" + ) + + body = "\n".join(lines) + open("/tmp/pr-body.md", "w").write(body) + + # NOTE: PR title generation removed because it is not used by any subsequent step. + EOF + + - name: Start Copilot cloud agent task (create session) + env: + # Agent tasks API requires a USER-to-server token (classic PAT / OAuth / + # GitHub App user token). Server-to-server (GITHUB_TOKEN / App installation + # tokens) are NOT supported. + GH_TOKEN: ${{ secrets.AGENT_PR_PAT }} + REPO: ${{ github.repository }} + AGENT_MODEL: claude-sonnet-4.6 + run: | + set -euo pipefail + gh auth status + + # Native cloud-agent session: POST /agents/repos/{owner}/{repo}/tasks. + # This starts the agent directly instead of assigning an issue, so it + # doesn't depend on the issue-assignment session bootstrap that was failing. + # Include "model" only when AGENT_MODEL is set (empty => auto selection). + jq -n \ + --rawfile prompt /tmp/pr-body.md \ + --arg base "main" \ + --arg model "${AGENT_MODEL:-}" \ + '{prompt: $prompt, base_ref: $base, create_pull_request: true} + + (if $model == "" then {} else {model: $model} end)' \ + | gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/agents/repos/$REPO/tasks" \ + --input - + + echo "Cloud agent task created for $REPO (model: ${AGENT_MODEL:-auto})" + + - name: Open fallback issue on failure + if: failure() + env: + GH_TOKEN: ${{ secrets.AGENT_PR_PAT }} + run: | + { + echo "The agent workflow failed." + echo + echo "Trigger payload:" + echo '```json' + cat /tmp/payload.json + echo + echo '```' + } > /tmp/failure-body.md + + gh issue create \ + --title "Agent workflow failed: could not create Copilot task PR" \ + --body-file /tmp/failure-body.md \ + --label "agent-failed" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 07f2df07..6c96664f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ ## lifebit-ai/cloudos-cli: changelog +## v2.94.0 (2026-06-19) + +### Feat: + +- Adds GitHub workflow to receive api-server endpoint events and open Copilot agent PRs +- Adds `supported-endpoints.json` mapping wrapped API endpoints to CLI commands + ## v2.91.0 (2026-05-28) ### Feat: diff --git a/cloudos_cli/_version.py b/cloudos_cli/_version.py index 1271f796..51e998d4 100644 --- a/cloudos_cli/_version.py +++ b/cloudos_cli/_version.py @@ -1 +1 @@ -__version__ = '2.91.0' +__version__ = '2.94.0' diff --git a/supported-endpoints.json b/supported-endpoints.json new file mode 100644 index 00000000..f7a586c3 --- /dev/null +++ b/supported-endpoints.json @@ -0,0 +1,643 @@ +{ + "version": "1.0", + "cli_version": "2.94.0", + "description": "Single source of truth mapping every API endpoint wrapped by cloudos-cli to the CLI command that wraps it. Used by the AI agent PR workflow to detect breaking changes in the api-server repo.", + "notes": [ + "Path parameters are expressed as {param_name}.", + "Query parameters (teamId, page, limit, etc.) are omitted from 'path'; they appear in 'query_params'.", + "Entries with cli_command starting with '_internal/' are not directly user-facing but are called as helpers during a user command.", + "added_in_version reflects the CLI release when this mapping entry was first formally tracked. Historical endpoint additions were not back-filled." + ], + "endpoints": [ + { + "id": "jobs-run", + "method": "POST", + "path": "/api/v2/jobs", + "query_params": ["teamId"], + "cli_command": "cloudos job run", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Also called by 'cloudos bash job' and 'cloudos bash array-job'" + }, + { + "id": "jobs-array-metadata", + "method": "GET", + "path": "/api/v1/jobs/array-file/metadata", + "query_params": [], + "cli_command": "cloudos job run", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Called when submitting array jobs. Also called by 'cloudos bash array-job'" + }, + { + "id": "jobs-status", + "method": "GET", + "path": "/api/v1/jobs/{job_id}", + "query_params": ["teamId"], + "cli_command": "cloudos job status", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Also used internally by 'cloudos job logs', 'cloudos job results', 'cloudos job workdir', 'cloudos job related'" + }, + { + "id": "jobs-details", + "method": "GET", + "path": "/api/v1/jobs/{job_id}", + "query_params": ["teamId"], + "cli_command": "cloudos job details", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Same endpoint as status but surfaced separately by the 'details' sub-command" + }, + { + "id": "jobs-list", + "method": "GET", + "path": "/api/v2/jobs", + "query_params": ["teamId", "page", "limit"], + "cli_command": "cloudos job list", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "jobs-list-related-by-workdir", + "method": "GET", + "path": "/api/v2/jobs", + "query_params": ["workDirectory.folderId", "teamId"], + "cli_command": "cloudos job related", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Filters jobs by shared work-directory folder to find related analyses" + }, + { + "id": "jobs-abort", + "method": "PUT", + "path": "/api/v2/jobs/{job_id}/abort", + "query_params": ["forceAbort", "teamId"], + "cli_command": "cloudos job abort", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "jobs-archive", + "method": "PUT", + "path": "/api/v1/jobs", + "query_params": ["teamId"], + "cli_command": "cloudos job archive", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Also called by 'cloudos job unarchive'. Body payload differentiates the action." + }, + { + "id": "jobs-delete-results", + "method": "DELETE", + "path": "/api/v1/jobs/{job_id}/data", + "query_params": ["properties[]", "teamId"], + "cli_command": "cloudos job workdir", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Called when --delete flag is passed to 'cloudos job workdir'" + }, + { + "id": "jobs-clone-resume-payload", + "method": "GET", + "path": "/api/v1/jobs/{job_id}/request-payload", + "query_params": ["teamId"], + "cli_command": "cloudos job clone", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Also called by 'cloudos job resume'" + }, + { + "id": "jobs-clone-resume-submit", + "method": "POST", + "path": "/api/v2/jobs", + "query_params": ["teamId"], + "cli_command": "cloudos job resume", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "POST after fetching the request-payload; also used by 'cloudos job clone'" + }, + { + "id": "jobs-git-branches", + "method": "GET", + "path": "/api/v1/git/{strategy}/getBranches", + "query_params": [], + "cli_command": "cloudos job clone", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Used when resolving workflow branches for clone/resume. Also called by 'cloudos job resume'" + }, + { + "id": "jobs-cost", + "method": "GET", + "path": "/api/v1/jobs/{job_id}/costs/compute", + "query_params": [], + "cli_command": "cloudos job cost", + "source_file": "cloudos_cli/cost/cost.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "jobs-workdir-folder-lookup", + "method": "GET", + "path": "/api/v1/folders/", + "query_params": ["id", "teamId"], + "cli_command": "cloudos job workdir", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Also used internally to resolve folder status for 'cloudos job related'" + }, + { + "id": "bash-job", + "method": "POST", + "path": "/api/v2/jobs", + "query_params": ["teamId"], + "cli_command": "cloudos bash job", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": "Bash job submission" + }, + { + "id": "bash-array-job-metadata", + "method": "GET", + "path": "/api/v1/jobs/array-file/metadata", + "query_params": [], + "cli_command": "cloudos bash array-job", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "bash-array-job-submit", + "method": "POST", + "path": "/api/v2/jobs", + "query_params": ["teamId"], + "cli_command": "cloudos bash array-job", + "source_file": "cloudos_cli/jobs/job.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "queue-list-user", + "method": "GET", + "path": "/api/v1/teams/aws/v2/job-queues", + "query_params": ["teamId"], + "cli_command": "cloudos queue list", + "source_file": "cloudos_cli/queue/queue.py", + "added_in_version": "2.91.0", + "notes": "Returns user-visible / team job queues" + }, + { + "id": "queue-list-system", + "method": "GET", + "path": "/api/v1/teams/aws/v2/system-job-queues", + "query_params": ["teamId"], + "cli_command": "cloudos queue list", + "source_file": "cloudos_cli/queue/queue.py", + "added_in_version": "2.91.0", + "notes": "Returns system-level job queues; results merged with user queues in the CLI output" + }, + { + "id": "projects-list", + "method": "GET", + "path": "/api/v2/projects", + "query_params": ["teamId", "pageSize", "page"], + "cli_command": "cloudos project list", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Also accepts 'search' query param when filtering by name" + }, + { + "id": "projects-create", + "method": "POST", + "path": "/api/v1/projects", + "query_params": ["teamId"], + "cli_command": "cloudos project create", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "workflows-list", + "method": "GET", + "path": "/api/v3/workflows", + "query_params": ["teamId", "pageSize", "page", "archived.status"], + "cli_command": "cloudos workflow list", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Also accepts 'search' query param" + }, + { + "id": "workflows-import", + "method": "POST", + "path": "/api/v2/workflows", + "query_params": ["teamId"], + "cli_command": "cloudos workflow import", + "source_file": "cloudos_cli/import_wf/import_wf.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "workflows-import-legacy", + "method": "POST", + "path": "/api/v1/workflows", + "query_params": ["teamId"], + "cli_command": "cloudos workflow import", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Legacy v1 fallback path for workflow import" + }, + { + "id": "workflows-import-get-public-repo", + "method": "GET", + "path": "/api/v1/git/{platform}/getPublicRepo", + "query_params": [], + "cli_command": "cloudos workflow import", + "source_file": "cloudos_cli/import_wf/import_wf.py", + "added_in_version": "2.91.0", + "notes": "Fetches metadata for a public git repository before import" + }, + { + "id": "workflows-import-get-config", + "method": "GET", + "path": "/api/v1/git/{platform}/getWorkflowConfig/{repo_name}/{repo_owner}", + "query_params": [], + "cli_command": "cloudos workflow import", + "source_file": "cloudos_cli/import_wf/import_wf.py", + "added_in_version": "2.91.0", + "notes": "Fetches the workflow main-file config for the repository" + }, + { + "id": "cromwell-status", + "method": "GET", + "path": "/api/v1/cromwell", + "query_params": ["teamId"], + "cli_command": "cloudos cromwell status", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "cromwell-start", + "method": "PUT", + "path": "/api/v1/cromwell/restart", + "query_params": ["teamId"], + "cli_command": "cloudos cromwell start", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "cromwell-stop", + "method": "PUT", + "path": "/api/v1/cromwell/stop", + "query_params": ["teamId"], + "cli_command": "cloudos cromwell stop", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "datasets-ls-project", + "method": "GET", + "path": "/api/v2/datasets", + "query_params": ["projectId", "teamId"], + "cli_command": "cloudos datasets ls", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Lists top-level dataset folders within a project" + }, + { + "id": "datasets-ls-folder-items", + "method": "GET", + "path": "/api/v1/datasets/{folder_id}/items", + "query_params": ["teamId"], + "cli_command": "cloudos datasets ls", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Lists items inside a dataset folder" + }, + { + "id": "datasets-ls-s3", + "method": "GET", + "path": "/api/v1/data-access/s3/bucket-contents", + "query_params": ["bucket", "path", "teamId"], + "cli_command": "cloudos datasets ls", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Lists S3 bucket contents for a given path" + }, + { + "id": "datasets-ls-azure", + "method": "GET", + "path": "/api/v1/data-access/azure/container-contents", + "query_params": ["containerName", "path", "teamId"], + "cli_command": "cloudos datasets ls", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Lists Azure Blob Storage container contents" + }, + { + "id": "datasets-ls-virtual-folder", + "method": "GET", + "path": "/api/v1/folders/virtual/{folder_id}/items", + "query_params": ["teamId"], + "cli_command": "cloudos datasets ls", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Lists items inside a virtual folder" + }, + { + "id": "datasets-mv", + "method": "PUT", + "path": "/api/v1/dataItems/move", + "query_params": ["teamId"], + "cli_command": "cloudos datasets mv", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Moves files or folders to a different location" + }, + { + "id": "datasets-rename-file", + "method": "PUT", + "path": "/api/v1/files/{item_id}", + "query_params": ["teamId"], + "cli_command": "cloudos datasets rename", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Renames a file item" + }, + { + "id": "datasets-rename-folder", + "method": "PUT", + "path": "/api/v1/folders/{item_id}", + "query_params": ["teamId"], + "cli_command": "cloudos datasets rename", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Renames a folder item" + }, + { + "id": "datasets-cp-virtual-folder", + "method": "POST", + "path": "/api/v1/folders/virtual", + "query_params": ["teamId"], + "cli_command": "cloudos datasets cp", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Creates a virtual folder copy. Also called by 'cloudos datasets mkdir'" + }, + { + "id": "datasets-cp-s3-folder", + "method": "POST", + "path": "/api/v1/folders/s3", + "query_params": ["teamId"], + "cli_command": "cloudos datasets cp", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Copies an S3 folder into a dataset" + }, + { + "id": "datasets-cp-s3-file", + "method": "POST", + "path": "/api/v1/files/s3", + "query_params": ["teamId"], + "cli_command": "cloudos datasets cp", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Copies an S3 file into a dataset" + }, + { + "id": "datasets-cp-azure-folder", + "method": "POST", + "path": "/api/v1/folders/azure-blob", + "query_params": ["teamId"], + "cli_command": "cloudos datasets cp", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Copies an Azure Blob folder into a dataset" + }, + { + "id": "datasets-cp-azure-file", + "method": "POST", + "path": "/api/v1/files/azure-blob", + "query_params": ["teamId"], + "cli_command": "cloudos datasets cp", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Copies an Azure Blob file into a dataset" + }, + { + "id": "datasets-mkdir", + "method": "POST", + "path": "/api/v1/folders/virtual", + "query_params": ["teamId"], + "cli_command": "cloudos datasets mkdir", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Creates a new virtual folder" + }, + { + "id": "datasets-rm-file", + "method": "DELETE", + "path": "/api/v1/files/{item_id}", + "query_params": ["teamId"], + "cli_command": "cloudos datasets rm", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Deletes a file from a dataset" + }, + { + "id": "datasets-rm-folder", + "method": "DELETE", + "path": "/api/v1/folders/{item_id}", + "query_params": ["teamId"], + "cli_command": "cloudos datasets rm", + "source_file": "cloudos_cli/datasets/datasets.py", + "added_in_version": "2.91.0", + "notes": "Deletes a folder from a dataset" + }, + { + "id": "datasets-link-mount-v2", + "method": "POST", + "path": "/api/v2/interactive-sessions/{session_id}/fuse-filesystem/mount", + "query_params": ["teamId"], + "cli_command": "cloudos datasets link", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Also called by 'cloudos link'. Falls back to v1 on error." + }, + { + "id": "datasets-link-mount-v1-fallback", + "method": "POST", + "path": "/api/v1/interactive-sessions/{session_id}/fuse-filesystem/mount", + "query_params": ["teamId"], + "cli_command": "cloudos datasets link", + "source_file": "cloudos_cli/link/link.py", + "added_in_version": "2.91.0", + "notes": "Legacy v1 fallback. Also used by 'cloudos link'." + }, + { + "id": "datasets-link-verify", + "method": "GET", + "path": "/api/v1/interactive-sessions/{session_id}/fuse-filesystems", + "query_params": ["teamId"], + "cli_command": "cloudos datasets link", + "source_file": "cloudos_cli/link/link.py", + "added_in_version": "2.91.0", + "notes": "Polls mount status after requesting a link. Also used by 'cloudos link'." + }, + { + "id": "interactive-session-list", + "method": "GET", + "path": "/api/v3/interactive-sessions", + "query_params": ["teamId", "page", "limit"], + "cli_command": "cloudos interactive-session list", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "interactive-session-create", + "method": "POST", + "path": "/api/v1/interactive-sessions", + "query_params": ["teamId"], + "cli_command": "cloudos interactive-session create", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "interactive-session-status", + "method": "GET", + "path": "/api/v2/interactive-sessions/{session_id}", + "query_params": ["teamId"], + "cli_command": "cloudos interactive-session status", + "source_file": "cloudos_cli/interactive_session/interactive_session.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "interactive-session-resume", + "method": "PUT", + "path": "/api/v1/interactive-sessions/{session_id}/resume", + "query_params": ["teamId"], + "cli_command": "cloudos interactive-session resume", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "interactive-session-pause", + "method": "PUT", + "path": "/api/v1/interactive-sessions/{session_id}/abort", + "query_params": ["teamId"], + "cli_command": "cloudos interactive-session pause", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "link-mount-v2", + "method": "POST", + "path": "/api/v2/interactive-sessions/{session_id}/fuse-filesystem/mount", + "query_params": ["teamId"], + "cli_command": "cloudos link", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Primary mount call; falls back to v1 on failure" + }, + { + "id": "link-mount-v1-fallback", + "method": "POST", + "path": "/api/v1/interactive-sessions/{session_id}/fuse-filesystem/mount", + "query_params": ["teamId"], + "cli_command": "cloudos link", + "source_file": "cloudos_cli/link/link.py", + "added_in_version": "2.91.0", + "notes": "Legacy v1 fallback path" + }, + { + "id": "link-verify", + "method": "GET", + "path": "/api/v1/interactive-sessions/{session_id}/fuse-filesystems", + "query_params": ["teamId"], + "cli_command": "cloudos link", + "source_file": "cloudos_cli/link/link.py", + "added_in_version": "2.91.0", + "notes": "Polls mount status after requesting a link" + }, + { + "id": "procurement-images-list", + "method": "GET", + "path": "/api/v1/procurements/{procurement_id}/images", + "query_params": ["page", "limit"], + "cli_command": "cloudos procurement images list", + "source_file": "cloudos_cli/procurement/images.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "procurement-images-set", + "method": "PUT", + "path": "/api/v1/procurements/{procurement_id}/images", + "query_params": [], + "cli_command": "cloudos procurement images set", + "source_file": "cloudos_cli/procurement/images.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "procurement-images-reset", + "method": "PUT", + "path": "/api/v1/procurements/{procurement_id}/images/reset", + "query_params": [], + "cli_command": "cloudos procurement images reset", + "source_file": "cloudos_cli/procurement/images.py", + "added_in_version": "2.91.0", + "notes": null + }, + { + "id": "_internal-cloud-azure-detect", + "method": "GET", + "path": "/api/v1/cloud/azure", + "query_params": ["teamId"], + "cli_command": "_internal/cloud-provider-detection", + "source_file": "cloudos_cli/utils/cloud.py", + "added_in_version": "2.91.0", + "notes": "Called internally to detect whether the workspace is running on Azure; affects which dataset copy endpoints are used" + }, + { + "id": "_internal-users-me", + "method": "GET", + "path": "/api/v1/users/me", + "query_params": [], + "cli_command": "_internal/current-user", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Called internally to resolve the current authenticated user" + }, + { + "id": "_internal-users-search-assist", + "method": "GET", + "path": "/api/v1/users/search-assist", + "query_params": ["q", "teamId"], + "cli_command": "_internal/user-search", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Called internally to resolve a username/email to a user ID" + }, + { + "id": "_internal-folders-status", + "method": "GET", + "path": "/api/v1/folders/", + "query_params": ["id", "status[]", "teamId"], + "cli_command": "_internal/folder-deletion-status", + "source_file": "cloudos_cli/clos.py", + "added_in_version": "2.91.0", + "notes": "Called internally to poll folder deletion status during 'cloudos job workdir' and dataset operations" + } + ] +}