feat(stream-backend): server-side SDK migration skill - #55
Open
mogita wants to merge 7 commits into
Open
Conversation
New language-parameterized skill that migrates a backend Stream integration from a legacy hand-written SDK to the generated OpenAPI SDK. Go is the first supported path (github.com/GetStream/stream-chat-go -> github.com/GetStream/getstream-go). The migrate-go track is thin and docs-driven: it fetches the official migration guide and never migrates from memory, applies the documented transforms, then verifies with go build / go vet. Wires the skill into the router (peers.yaml, Server SDKs menu group, classifier row) and the README / AGENTS tables.
The legacy SDKs are Chat SDKs, so the migratable surface is Chat plus chat-era moderation. Video and Feeds are new capability in the generated SDK rather than migration targets, since no legacy code calls them. Name the real gaps, which are inside Chat.
Rewriting call sites by hand is the wrong tool for the mechanical part of an SDK migration: it is not repeatable and it silently misses call sites in files nobody opened. This adds stream-migrate, a type-aware Go codemod, and rewires the skill to drive it and handle only the residue. It rewrites call sites, legacy type references (a client held in a struct field has to change type too, or nothing compiles), and reads off a response, which now live under Data. Every call site is classified: applied and safe, applied but behavior changed, needs a decision, or not migrated. Anything the mapping table does not cover is reported rather than guessed at, and a builder that cannot match a call's shape degrades it to a decision instead of emitting a plausible wrong rewrite. testdata/chatmod is a representative Chat + Moderation integration used to exercise this: several files, responses consumed, a spread of operations. Running the tool over it rewrites 41 call sites safely, flags 4 behavior changes, and leaves 7 for a human. Every remaining compile error afterwards is one the report named.
…p fields Adds table-driven tests over the rewrite rules and the response pass. They run without network or the real SDK, since they exercise the builders on parsed snippets rather than a loaded package. Writing them found a real bug: CreateChannel silently dropped the members when they came from a variable instead of a literal, producing a channel with nobody in it that compiled fine. Rules now decline whenever a literal carries a field they do not map, so the call is reported for a human instead of being rewritten with data missing. A test locks that in. Also lowers the Go requirement from 1.25 to 1.23 by pinning older x/tools and x/sync, states the toolchain requirement in the skill, and reports what a surviving legacy type reference is doing so the request or response type can be chosen from how the value flows.
The skill was shaped around a per-language track backed by a Go codemod. That does not scale: five more rewriter kits is five more projects to build and keep current, and a human reviews the result either way. What actually made the Go migration trustworthy was not the rewriter. It was taking an inventory of every call site before editing, mapping data that says which operations change runtime behavior, and a report that separates safe from behavior-changed from needs-a-decision from not migrated. None of that is language-specific. So the skill is now one workflow every language runs, with the operation knowledge split into a language-independent reference plus a per-language symbol table. Human review is an explicit first step rather than an implication, and verification is honest about proving less on Ruby and Python, where there is no compiler to catch a wrong rewrite. The Go codemod stays in tools/ as an internal harness that proves the Go mappings compile. It is not shipped and the skill does not mention it, so it cannot raise the question of when the other five arrive. A test asserts the reference documents every mapping the tool implements, which caught a missing behavior warning on FlagUser.
Adds the Python symbol reference and a representative legacy Python integration to run the workflow against. Python is the language that tests whether the workflow stands on its own, because it has no compiler and no codemod behind it. Two things about it differ enough to be worth stating in the reference rather than discovering mid-migration: the generated SDK takes keyword arguments rather than a request object per call, with typed models only for nested payloads, and both SDKs ship separate sync and async clients that must not be quietly swapped for one another. Writing it also corrected something the Go reference got wrong. Listing operations as not covered conflated the reference not documenting them with the SDK not having them; unread counts and message translation, both listed as gaps, exist on both sides. Under a verify-first gate that framing is misleading, so both references now say unverified rather than missing. The Python fixture's calls were checked against the legacy SDK source since nothing else would catch them, which found a keyword argument passed to a method with no catch-all that would have failed only at runtime.
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.
Adds
stream-backend, a skill that migrates a customer's server-side Stream integration from a legacy hand-written SDK to the generated OpenAPI SDK.Shape
One skill and one workflow for all six server-side SDKs, rather than a track per language. The migration is a reading of how a codebase uses the SDK, and the parts that make that trustworthy are language-independent: take an inventory of every call site before editing, know which operations change runtime behavior, and report what is safe separately from what is not.
What differs per language is the symbol mapping, which lives in a reference file, and the commands used to verify.
It is an assisted migration, and says so
The skill states up front that a human reviews the result. Every call site lands in one of four buckets:
The second bucket is the one that earns its keep. The environment-variable rename is a one-token change that compiles perfectly and takes production auth down; deletes became asynchronous; flagging moved from the v1 store to v2 moderation, so migrating one call in isolation can leave a workflow writing to one store and reading from another.
Two rules hold it together: unclassified is never treated as safe, and a field with no home in the new request is a decision rather than something to quietly drop.
Scope
Covers Chat plus chat-era moderation, which is the entire surface the legacy SDKs have. Video and Feeds are new capability with no legacy code calling them, so they are not migration targets, and the skill says so instead of implying a gap.
Verification is honest about what it proves
Go, Java and .NET get a real compiler check. PHP has static analysis if configured. Ruby and Python have no equivalent, so the customer's test suite is the only meaningful backstop there, and the workflow says that rather than presenting equal confidence everywhere.
Files
skills/stream-backend/SKILL.md- classify server-side versus client, pick the language, hand offskills/stream-backend/migrate.md- the workflow: expectations, inventory, classify, agree, apply, verify, reportskills/stream-backend/references/operations.md- language-independent: what each operation becomes, which change behaviorskills/stream-backend/references/go.md- Go symbol mappingtools/stream-migrate/- internal, not shipped and not referenced by the skill. A Go codemod used to prove the Go mappings compile against the real SDK, with a representative Chat + Moderation integration undertestdata/to exercise them. Its tests also assert the reference has not drifted from what has been verified.Registered as a router peer with a classifier row, a Server SDKs menu group, and rows in
README.mdandAGENTS.md.