diff --git a/services/update/README.md b/services/update/README.md index fe3024dfccb..b81affab8cc 100644 --- a/services/update/README.md +++ b/services/update/README.md @@ -34,7 +34,8 @@ available to roughly half of IPs after three hours and all IPs after six hours. Eligibility uses the original publication time (`time_created`) and a SHA-256 hash of the channel and Cloudflare's `CF-Connecting-IP`. Each IP keeps the same rollout position across releases in that channel. Requests without this header wait for -the full duration. The retired `next` channel is not available or configurable. +the full duration. The retired `next` channel is not configurable; `/api/next` +remains a compatibility alias for `/api/beta`, including its rollout settings. Until the active release is eligible, callers receive the newest eligible artifact published before it, for the same name and distribution. This also handles overlapping @@ -71,7 +72,7 @@ no-store` because responses can depend on the User-Agent. Version comparison uses semver, normalizing preview run numbers to numeric prerelease identifiers and historical `next` versions to `beta`. The retired `/api/next` -channel returns 404; use `/api/beta` instead. +channel transparently resolves to `beta` for older clients. Choose a minimum that older clients can install and that can itself consume the active release. For the CLI package migration, retain a package-aware release published as diff --git a/services/update/src/index.ts b/services/update/src/index.ts index bd0c711d180..c0a5fda2af4 100644 --- a/services/update/src/index.ts +++ b/services/update/src/index.ts @@ -77,8 +77,7 @@ export default { return new Response("Not found", { status: 404 }) } - if (path[0] === "next") return json({ error: "Channel not found" }, 404) - const resolved = path[0] + const resolved = resolveChannel(path[0]) const agent = request.headers.get("User-Agent")?.match(/^opencode\/(?:([^/]+)\/([^/]+)\/cli|(.*))$/) const current = url.searchParams.get("current") ?? agent?.[2] ?? agent?.[3] const source = agent?.[1] ?? current?.match(/^v?0\.0\.0-(.+)-\d+(?:\.\d+)?(?:\+.*)?$/)?.[1]