Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/restore-kilo-upgrade-version-lookup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---

Keep `kilo upgrade` on the Kilo CLI release channel when GitHub's latest release is a JetBrains release.
16 changes: 2 additions & 14 deletions packages/opencode/src/installation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
Release as KiloRelease,
Scoop as KiloScoop,
} from "@/kilocode/installation"
import { latest as kiloLatest } from "@/kilocode/installation/latest"
// kilocode_change end
import { InstallationEvent } from "@opencode-ai/schema/installation-event"

Expand Down Expand Up @@ -70,7 +71,6 @@ export class UpgradeFailedError extends Schema.TaggedErrorClass<UpgradeFailedErr
}

// Response schemas for external version APIs
const GitHubRelease = Schema.Struct({ tag_name: Schema.String })
const NpmPackage = Schema.Struct({ version: Schema.String })
const BrewFormula = Schema.Struct({
versions: Schema.Struct({ stable: Schema.String }),
Expand Down Expand Up @@ -302,19 +302,7 @@ const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProcess.Serv
return data.version
}

// kilocode_change start - curl/unknown fallback: resolve from the public npm
// dist-tag instead of GitHub /releases/latest, which is polluted by non-CLI
// (e.g. JetBrains) releases and returns a tag like "jetbrains/v7.0.4" that
// breaks version resolution. Use the public registry directly: a curl-
// installed binary is not tied to any project's npm config.
const response = yield* httpOk.execute(
HttpClientRequest.get(`https://registry.npmjs.org/${KiloNpm.path}/${InstallationChannel}`).pipe(
HttpClientRequest.acceptJson,
),
)
const data = yield* HttpClientResponse.schemaBodyJson(NpmPackage)(response)
return data.version
// kilocode_change end
return yield* kiloLatest(httpOk, KiloNpm.path, InstallationChannel) // kilocode_change
}, Effect.orDie),
upgrade: Effect.fn("Installation.upgrade")(function* (m: Method, target: string) {
let upgradeResult: { code: number; stdout: string; stderr: string } | undefined
Expand Down
16 changes: 16 additions & 0 deletions packages/opencode/src/kilocode/installation/latest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Effect, Schema } from "effect"
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"

const Package = Schema.Struct({ version: Schema.String })

// GitHub's latest Kilo release can be a JetBrains release, not a CLI release.
// Use the public npm channel so curl installs resolve only Kilo CLI versions.
export function latest(http: HttpClient.HttpClient, path: string, channel: string) {
Comment thread
marius-kilocode marked this conversation as resolved.
return Effect.gen(function* () {
const response = yield* http.execute(
HttpClientRequest.get(`https://registry.npmjs.org/${path}/${channel}`).pipe(HttpClientRequest.acceptJson),
)
const data = yield* HttpClientResponse.schemaBodyJson(Package)(response)
return data.version
})
}
6 changes: 5 additions & 1 deletion packages/opencode/test/kilocode/installation/upgrade.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,18 @@ describe("Kilo installation upgrade", () => {
() => "",
(request) => {
release.push(request.url)
if (request.url === "https://api.github.com/repos/Kilo-Org/kilocode/releases/latest") {
return json({ tag_name: "jetbrains/v7.0.16" })
}
return json({ version: "8.8.8" })
},
),
).effect("reads fallback versions from the Kilo npm registry", () =>
).effect("does not use polluted GitHub release tags for fallback versions", () =>
Effect.gen(function* () {
const result = yield* Installation.Service.use((svc) => svc.latest("unknown"))
expect(result).toBe("8.8.8")
expect(release).toContain(`https://registry.npmjs.org/@kilocode%2fcli/${InstallationChannel}`)
expect(release).not.toContain("https://api.github.com/repos/Kilo-Org/kilocode/releases/latest")
}),
)

Expand Down
Loading