fix: call models.dev once instead of twice on start (#20765)
This commit is contained in:
parent
8e9e79d276
commit
eb6f1dada8
3 changed files with 45 additions and 15 deletions
|
|
@ -28,7 +28,7 @@ export const ModelsCommand = cmd({
|
||||||
},
|
},
|
||||||
handler: async (args) => {
|
handler: async (args) => {
|
||||||
if (args.refresh) {
|
if (args.refresh) {
|
||||||
await ModelsDev.refresh()
|
await ModelsDev.refresh(true)
|
||||||
UI.println(UI.Style.TEXT_SUCCESS_BOLD + "Models cache refreshed" + UI.Style.TEXT_NORMAL)
|
UI.println(UI.Style.TEXT_SUCCESS_BOLD + "Models cache refreshed" + UI.Style.TEXT_NORMAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ export const ProvidersLoginCommand = cmd({
|
||||||
prompts.outro("Done")
|
prompts.outro("Done")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await ModelsDev.refresh().catch(() => {})
|
await ModelsDev.refresh(true).catch(() => {})
|
||||||
|
|
||||||
const config = await Config.get()
|
const config = await Config.get()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import { Installation } from "../installation"
|
||||||
import { Flag } from "../flag/flag"
|
import { Flag } from "../flag/flag"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { Filesystem } from "../util/filesystem"
|
import { Filesystem } from "../util/filesystem"
|
||||||
|
import { Flock } from "@/util/flock"
|
||||||
|
import { Hash } from "@/util/hash"
|
||||||
|
|
||||||
// Try to import bundled snapshot (generated at build time)
|
// Try to import bundled snapshot (generated at build time)
|
||||||
// Falls back to undefined in dev mode when snapshot doesn't exist
|
// Falls back to undefined in dev mode when snapshot doesn't exist
|
||||||
|
|
@ -13,7 +15,12 @@ import { Filesystem } from "../util/filesystem"
|
||||||
|
|
||||||
export namespace ModelsDev {
|
export namespace ModelsDev {
|
||||||
const log = Log.create({ service: "models.dev" })
|
const log = Log.create({ service: "models.dev" })
|
||||||
const filepath = path.join(Global.Path.cache, "models.json")
|
const source = url()
|
||||||
|
const filepath = path.join(
|
||||||
|
Global.Path.cache,
|
||||||
|
source === "https://models.dev" ? "models.json" : `models-${Hash.fast(source)}.json`,
|
||||||
|
)
|
||||||
|
const ttl = 5 * 60 * 1000
|
||||||
|
|
||||||
export const Model = z.object({
|
export const Model = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
|
|
@ -85,6 +92,22 @@ export namespace ModelsDev {
|
||||||
return Flag.OPENCODE_MODELS_URL || "https://models.dev"
|
return Flag.OPENCODE_MODELS_URL || "https://models.dev"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fresh() {
|
||||||
|
return Date.now() - Number(Filesystem.stat(filepath)?.mtimeMs ?? 0) < ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
function skip(force: boolean) {
|
||||||
|
return !force && fresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchApi = async () => {
|
||||||
|
const result = await fetch(`${url()}/api.json`, {
|
||||||
|
headers: { "User-Agent": Installation.USER_AGENT },
|
||||||
|
signal: AbortSignal.timeout(10000),
|
||||||
|
})
|
||||||
|
return { ok: result.ok, text: await result.text() }
|
||||||
|
}
|
||||||
|
|
||||||
export const Data = lazy(async () => {
|
export const Data = lazy(async () => {
|
||||||
const result = await Filesystem.readJson(Flag.OPENCODE_MODELS_PATH ?? filepath).catch(() => {})
|
const result = await Filesystem.readJson(Flag.OPENCODE_MODELS_PATH ?? filepath).catch(() => {})
|
||||||
if (result) return result
|
if (result) return result
|
||||||
|
|
@ -94,8 +117,17 @@ export namespace ModelsDev {
|
||||||
.catch(() => undefined)
|
.catch(() => undefined)
|
||||||
if (snapshot) return snapshot
|
if (snapshot) return snapshot
|
||||||
if (Flag.OPENCODE_DISABLE_MODELS_FETCH) return {}
|
if (Flag.OPENCODE_DISABLE_MODELS_FETCH) return {}
|
||||||
const json = await fetch(`${url()}/api.json`).then((x) => x.text())
|
return Flock.withLock(`models-dev:${filepath}`, async () => {
|
||||||
return JSON.parse(json)
|
const result = await Filesystem.readJson(Flag.OPENCODE_MODELS_PATH ?? filepath).catch(() => {})
|
||||||
|
if (result) return result
|
||||||
|
const result2 = await fetchApi()
|
||||||
|
if (result2.ok) {
|
||||||
|
await Filesystem.write(filepath, result2.text).catch((e) => {
|
||||||
|
log.error("Failed to write models cache", { error: e })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return JSON.parse(result2.text)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
export async function get() {
|
export async function get() {
|
||||||
|
|
@ -103,21 +135,19 @@ export namespace ModelsDev {
|
||||||
return result as Record<string, Provider>
|
return result as Record<string, Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function refresh() {
|
export async function refresh(force = false) {
|
||||||
const result = await fetch(`${url()}/api.json`, {
|
if (skip(force)) return ModelsDev.Data.reset()
|
||||||
headers: {
|
await Flock.withLock(`models-dev:${filepath}`, async () => {
|
||||||
"User-Agent": Installation.USER_AGENT,
|
if (skip(force)) return ModelsDev.Data.reset()
|
||||||
},
|
const result = await fetchApi()
|
||||||
signal: AbortSignal.timeout(10 * 1000),
|
if (!result.ok) return
|
||||||
|
await Filesystem.write(filepath, result.text)
|
||||||
|
ModelsDev.Data.reset()
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
log.error("Failed to fetch models.dev", {
|
log.error("Failed to fetch models.dev", {
|
||||||
error: e,
|
error: e,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (result && result.ok) {
|
|
||||||
await Filesystem.write(filepath, await result.text())
|
|
||||||
ModelsDev.Data.reset()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue