Feat: Sync SDK with v2 Platform API + route-drift guard#1
Merged
Conversation
Brings the SDK back in line with compute/pkg/platform/v2/routes.go (26 routes): - Fix sandbox resource path /v2/sandboxes -> /v2/sandcastles (the backend renamed it with no alias; every sandbox call was 404ing). Verified live against staging. - Sandbox: add list/executions (cursor-paginated), optional sandbox_id on start, and tql_path/params/max_rows on query (exactly-one-of guard). - Connectors: add types/create/test/update/delete (config passed through as proto-JSON; types() is self-describing). - Bump 2.0.0 -> 2.1.0; CHANGELOG entry + backfilled 2.0.0 entry. Drift prevention (SDK half of Tier 1): - # v2:covers comment on all 26 methods + tests/test_route_coverage.py asserting SDK coverage == vendored tests/routes.manifest.json (byte-identical to the canonical manifest generated by the backend's TestRouteManifest golden test). - Scheduled route-sync workflow opens a PR when the backend manifest drifts. - respx unit tests for sandbox + connectors; live-staging coverage for the new read endpoints. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
raw.githubusercontent.com + a PAT bearer header is unreliable for private repos. Use `gh api .../contents/...` with Accept: application/vnd.github.raw, which authenticates with BACKEND_REPO_TOKEN. Repo/path/ref are overridable via repo vars (default TextQLLabs/demo2). Copy the canonical file verbatim instead of re-serializing, so the vendored copy stays byte-identical. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A single App credential covers both halves: read the private backend manifest and open a PR here that actually triggers CI (default GITHUB_TOKEN PRs don't run checks, so the drift guard would never go red). Mint the installation token in-workflow via actions/create-github-app-token scoped to both repos; job no-ops until SYNC_APP_ID + SYNC_APP_PRIVATE_KEY are set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cross-repo credentials must be minted in the UI (gh can't create an App or a PAT), so support the lighter option too: resolve the token from a GitHub App (SYNC_APP_ID) when present, else fall back to a fine-grained PAT secret (BACKEND_REPO_TOKEN). Either triggers CI on the auto-PR; job no-ops with neither. Token is masked before use. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
demo2 main builds to staging; prod is the `release` branch. The SDK defaults to app.textql.com (prod), so syncing against main would advertise routes before prod serves them — the lead/lag break this guard exists to prevent. Default MANIFEST_REF to `release` and soft-skip when the manifest isn't on that ref yet (bootstrap), failing loudly only on real fetch errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jlsajfj
added a commit
that referenced
this pull request
Jun 22, 2026
…#2) * Feat: Add models + sandbox file/exec/library routes (33/33 with prod) Bundle the 7 routes prod gained after PR #1 so 2.1.0 ships in full sync: - Models resource: list (GET /v2/models) - Sandbox: exec (bash/python), list_files, download_file (raw bytes), delete_file, library_diff, create_library_patch - _client.request gains raw= for binary downloads - Vendored manifest bumped to 33; respx + live-staging coverage added Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix: ruff format (newer version) + pin ruff to 0.15.18 CI's ruff collapsed download_file's call to one line; pin ruff exactly so local and CI formatting never diverge (even patch releases change formatting). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The SDK had drifted from the backend
/v2surface (compute/pkg/platform/v2/routes.go, 26 routes). Most urgently, the backend renamed the sandbox path/v2/sandboxes → /v2/sandcastleswith no alias, so everysandbox.*call was 404ing. This PR restores 26/26 coverage and adds a guard so this can't silently recur.Grounded against the live backend handlers (
routes.go,connector.go,sandbox.go), not guessed.Changes
P0 — sandbox path fix (was actively broken)
/v2/sandcastles. Verified live againststaging.textql.com(fullstart→status→execute→query→stoplifecycle passes).P1 — sandbox additions
list(status, limit, cursor),executions(sandbox_id, limit, cursor)(cursor-paginated).sandbox_idonstart(restart a specific sandbox).querygainstql_path(run a saved library.tql),params,max_rows; enforces exactly-one-ofquery/tql_pathclient-side.P1 — connector write APIs
types,create,test,update,delete.configis passed through as proto-JSON (the backend body is a polymorphic, strict-unmarshaled proto;connectors.types()is self-describing for per-type fields).connectors.testreturning200 {success:false}is not raised as an error.P2 — release hygiene
2.0.0 → 2.1.0; CHANGELOG entry plus a backfilled2.0.0entry (the changelog had skipped it).Drift prevention (SDK half of Tier 1)
# v2:covers METHOD /pathcomment on all 26 methods (mirrors the backend's own// v2:coversidiom).tests/test_route_coverage.pyasserts SDK coverage == vendoredtests/routes.manifest.json, which is byte-identical to the canonical manifest produced by the backend'sTestRouteManifestgolden test..github/workflows/route-sync.yml(scheduled) opens a PR when the backend manifest drifts → that PR fails coverage until the new method +# v2:coversis added.Companion backend PR
The canonical
routes.manifest.json+ itsTestRouteManifestgolden test land in demo2 (compute/pkg/platform/v2/). Together they close the loop: backend route change → manifest diff → SDK sync PR.Follow-up (not blocking)
After the backend PR merges, set repo var
BACKEND_MANIFEST_URL(raw URL of the canonical manifest) + secretBACKEND_REPO_TOKENif private. Until thenroute-syncno-ops safely.Verification
ruff check/ruff format --check: cleanpyright(strict): 0 errorspytest(incl. live staging): 35 passed🤖 Generated with Claude Code