From 3fc01e441a0efbd93c8a1ecb96130dbdd7efdce8 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Mon, 1 Dec 2025 22:47:27 +0000 Subject: [PATCH 1/3] Fixed hardcoded npm registry with fallback support Co-authored-by: rekram1-node --- packages/opencode/src/installation/index.ts | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index 7ac2980c46a5..38cec40ca157 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -162,14 +162,34 @@ export namespace Installation { export const CHANNEL = typeof OPENCODE_CHANNEL === "string" ? OPENCODE_CHANNEL : "local" export const USER_AGENT = `opencode/${CHANNEL}/${VERSION}` + async function getRegistryUrl() { + const result = await $`npm config get registry`.throws(false).text() + const registry = result.trim() + return registry || "https://registry.npmjs.org" + } + export async function latest() { const [major] = VERSION.split(".").map((x) => Number(x)) const channel = CHANNEL === "latest" ? `latest-${major}` : CHANNEL - return fetch(`https://registry.npmjs.org/opencode-ai/${channel}`) + const registry = await getRegistryUrl() + const registryUrl = registry.endsWith("/") ? registry.slice(0, -1) : registry + return fetch(`${registryUrl}/opencode-ai/${channel}`) .then((res) => { if (!res.ok) throw new Error(res.statusText) return res.json() }) .then((data: any) => data.version) + .catch(() => { + // Fallback to default registry if configured registry fails + if (registry !== "https://registry.npmjs.org") { + return fetch(`https://registry.npmjs.org/opencode-ai/${channel}`) + .then((res) => { + if (!res.ok) throw new Error(res.statusText) + return res.json() + }) + .then((data: any) => data.version) + } + throw new Error("Failed to fetch latest version") + }) } } From 04aaa21e4f9c8d75a81ec9e6a186fea07293bf81 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Mon, 1 Dec 2025 22:52:01 +0000 Subject: [PATCH 2/3] Simplified `latest()` function, removed fallback Co-authored-by: rekram1-node --- packages/opencode/src/installation/index.ts | 22 ++++----------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index 38cec40ca157..e0d2c52a2a65 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -173,23 +173,9 @@ export namespace Installation { const channel = CHANNEL === "latest" ? `latest-${major}` : CHANNEL const registry = await getRegistryUrl() const registryUrl = registry.endsWith("/") ? registry.slice(0, -1) : registry - return fetch(`${registryUrl}/opencode-ai/${channel}`) - .then((res) => { - if (!res.ok) throw new Error(res.statusText) - return res.json() - }) - .then((data: any) => data.version) - .catch(() => { - // Fallback to default registry if configured registry fails - if (registry !== "https://registry.npmjs.org") { - return fetch(`https://registry.npmjs.org/opencode-ai/${channel}`) - .then((res) => { - if (!res.ok) throw new Error(res.statusText) - return res.json() - }) - .then((data: any) => data.version) - } - throw new Error("Failed to fetch latest version") - }) + const res = await fetch(`${registryUrl}/opencode-ai/${channel}`) + if (!res.ok) throw new Error(res.statusText) + const data = await res.json() + return data.version } } From 169ce9f16db9f5142a3dbd729d13e55c570c9c12 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 1 Dec 2025 16:56:53 -0600 Subject: [PATCH 3/3] cleanup --- packages/opencode/src/installation/index.ts | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index e0d2c52a2a65..7552365517b3 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -4,6 +4,7 @@ import z from "zod" import { NamedError } from "@opencode-ai/util/error" import { Bus } from "../bus" import { Log } from "../util/log" +import { iife } from "@/util/iife" declare global { const OPENCODE_VERSION: string @@ -162,20 +163,19 @@ export namespace Installation { export const CHANNEL = typeof OPENCODE_CHANNEL === "string" ? OPENCODE_CHANNEL : "local" export const USER_AGENT = `opencode/${CHANNEL}/${VERSION}` - async function getRegistryUrl() { - const result = await $`npm config get registry`.throws(false).text() - const registry = result.trim() - return registry || "https://registry.npmjs.org" - } - export async function latest() { + const registry = await iife(async () => { + const r = (await $`npm config get registry`.throws(false).text()).trim() + const reg = r || "https://registry.npmjs.org" + return reg.endsWith("/") ? reg.slice(0, -1) : reg + }) const [major] = VERSION.split(".").map((x) => Number(x)) const channel = CHANNEL === "latest" ? `latest-${major}` : CHANNEL - const registry = await getRegistryUrl() - const registryUrl = registry.endsWith("/") ? registry.slice(0, -1) : registry - const res = await fetch(`${registryUrl}/opencode-ai/${channel}`) - if (!res.ok) throw new Error(res.statusText) - const data = await res.json() - return data.version + return fetch(`${registry}/opencode-ai/${channel}`) + .then((res) => { + if (!res.ok) throw new Error(res.statusText) + return res.json() + }) + .then((data: any) => data.version) } }