sdk: name the v0 modules for the surface they serve - #1122
Merged
Conversation
kvinwang
force-pushed
the
feat/sdk-v0-naming
branch
from
August 25, 2026 02:44
95deb93 to
23badaf
Compare
kvinwang
force-pushed
the
feat/sdk-v0-naming
branch
from
August 25, 2026 03:06
23badaf to
84cd7aa
Compare
Every SDK ended 0.6.0 with the v1 code in `*_v1` files and the v0 code still in the unsuffixed ones it had before there was anything to distinguish it from. So "unsuffixed file" meant v0 while "unsuffixed class" meant v1, and a reader opening `dstack_client.rs` landed on the legacy surface. The v0 modules now say so: `dstack_client.rs` -> `dstack_client_v0.rs` and types `dstack.rs` -> `dstack_v0.rs` in Rust, `dstack_client.py` -> `dstack_client_v0.py` in Python, `client.go` -> `client_v0.go` in Go. The JS SDK had both clients and their shared helpers in one `index.ts`; it is split into `client-v0.ts`, `client-v1.ts` and `shared.ts`, with `index.ts` kept as a barrel exporting exactly what it exported before. No compatibility aliases for the old module paths. 0.6.0 is already the release where the unsuffixed client name changed meaning, and the whole point of that decision was that an unmigrated caller fails at build time rather than silently binding the frozen surface; a module alias would reopen the hole the rename closes. Deprecation is now visible to each language's tooling rather than only to a reader. Go and JS already carried `// Deprecated:` and `@deprecated`; Rust had no attribute at all and Python only a docstring note. `DstackClientV0` and `TappdClient` now carry `#[deprecated]`, with `#[allow(deprecated)]` at the internal use sites so the attribute reaches downstream callers instead of being blanket-suppressed, and the Python v0 clients warn at construction through the helper the file already had for `TappdClient`. Two tests pin that warning, which nothing did before. `.claude/agents/sdk-sync-checker.md` listed the old paths and now lists both surfaces' files, since a rename that leaves the agent looking at the wrong file makes it quietly useless.
Three of them did not, and the CHANGELOG claimed things the diff does not do. Python read the public `use_sync_http` flag as "this instance is an internal transport, stay quiet". It is a documented option on `AsyncDstackClientV0`, so a caller who set it themselves was silently opted out of the one signal that says the surface is frozen. The sync wrappers now pass a private `_warn=False` instead, which is what they actually mean. Go's `ToEthereumAccount` and `ToSolanaKeypair` still carried their `// Deprecated:` inside the first comment paragraph, where neither gopls nor pkg.go.dev recognises it -- the same shape this branch repairs five times over in `client_v0.go`, left on the two functions whose own doc comments say they have security concerns. The JSDoc on the `DstackClient` alias told readers to import `DstackClientV0` from `./client-v0`. That text ships in `dist/index.d.ts` and the path does not resolve for a package consumer: `client-v0` is not a `tsup` entry and not in the `exports` map. Point at the package root. CHANGELOG corrections: Rust warns at every *mention of the type*, not at every call -- `#[deprecated]` on a struct does not propagate to its inherent methods, and a client received from a factory function warns nowhere. `TappdClient`'s `@deprecated` JSDoc is added here, not pre-existing. And "no behaviour changes" was wrong for Python: the warning fires at construction, so a downstream suite with `filterwarnings = error` goes red on upgrade. Say so where they will read it.
kvinwang
force-pushed
the
feat/sdk-v0-naming
branch
from
August 25, 2026 03:16
84cd7aa to
6898486
Compare
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.
Stacked on #1120 — review that first; this diff is only the commit on top.
Why
Every SDK came out of #1116 with the v1 code in
*_v1files and the v0 code still in the unsuffixed files it occupied before there was anything to distinguish it from. The result reads backwards: the unsuffixed file means v0, while the unsuffixed class (DstackClient) now means v1. A reader who opensdstack_client.rslands on the legacy surface.The renames
src/dstack_client.rssrc/dstack_client_v0.rstypes/src/dstack.rstypes/src/dstack_v0.rsdstack_client.pydstack_client_v0.pyclient.go,client_test.goclient_v0.go,client_v0_test.goThe JS SDK kept both clients and their shared helpers in a single
index.ts, so there was no v0 module to rename. It is split intoclient-v0.ts,client-v1.tsandshared.ts, withindex.tskept as a barrel that exports exactly what it exported before — no additions, no removals, no renamed exports.No compatibility aliases for the old module paths. 0.6.0 is already the release where the unsuffixed client name changed meaning, and the point of that decision was that an unmigrated caller fails at build time rather than silently binding the frozen surface. A deprecated module alias would reopen the hole the rename closes.
Deprecation, visible to tooling
Go and JS already carried
// Deprecated:and@deprecated, which their tooling understands. Rust had no#[deprecated]attribute at all, and Python had only a docstring note — so in two of four SDKs the legacy client was marked only for a human who went looking.#[deprecated]onDstackClientV0andTappdClient. The internal use sites get narrowly-scoped#[allow(deprecated)]rather than a crate-level allow, so the attribute still reaches downstream callers.cargo clippy --all-targets -- -D warningsis clean.TappdClient. Two tests pin that warning —TappdClient's was pinned and the new one was not, which is how a deprecation quietly stops firing..claude/agents/sdk-sync-checker.mdlisted the old paths; it now lists both surfaces' files, since a rename that leaves that agent reading the wrong file makes it silently useless.Verification
./sdk/run-tests.shgreen end to end: Rust (clippy-D warningsclean), Go (vet/gofmtclean), Python 160 passed, JS 141 passed withtsc --noEmitclean. Every rename is recorded as a rename, not a delete-plus-add, sogit log --followstill works.