fix(opencode): enumerate models after cache refresh

This commit is contained in:
Dotta 2026-09-04 02:56:20 -05:00
parent fca39344b1
commit bc85c44b10
2 changed files with 41 additions and 6 deletions

View File

@ -148,12 +148,21 @@ describe("openCode models", () => {
pid: 1,
startedAt: new Date().toISOString(),
})
.mockResolvedValueOnce({
exitCode: 0,
signal: null,
timedOut: false,
stdout: "Models cache refreshed\n",
stderr: "",
pid: 1,
startedAt: new Date().toISOString(),
})
.mockResolvedValueOnce({
exitCode: 0,
signal: null,
timedOut: false,
stdout:
"openrouter/example/stale-model\nopenrouter/deepseek/deepseek-v4-flash-0731\n",
"openrouter/example/current-model\nopenrouter/deepseek/deepseek-v4-flash-0731\n",
stderr: "",
pid: 1,
startedAt: new Date().toISOString(),
@ -167,9 +176,10 @@ describe("openCode models", () => {
id: "openrouter/deepseek/deepseek-v4-flash-0731",
label: "openrouter/deepseek/deepseek-v4-flash-0731",
});
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledTimes(3);
expect(spy.mock.calls[0]?.[2]).toEqual(["models"]);
expect(spy.mock.calls[1]?.[2]).toEqual(["models", "--refresh"]);
expect(spy.mock.calls[2]?.[2]).toEqual(["models"]);
});
it("still rejects when a refreshed non-empty catalog omits the configured model", async () => {
@ -184,6 +194,15 @@ describe("openCode models", () => {
pid: 1,
startedAt: new Date().toISOString(),
})
.mockResolvedValueOnce({
exitCode: 0,
signal: null,
timedOut: false,
stdout: "Models cache refreshed\n",
stderr: "",
pid: 1,
startedAt: new Date().toISOString(),
})
.mockResolvedValueOnce({
exitCode: 0,
signal: null,
@ -201,11 +220,12 @@ describe("openCode models", () => {
).rejects.toThrow(
"Configured OpenCode model is unavailable: openrouter/deepseek/deepseek-v4-flash-0731",
);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledTimes(3);
expect(spy.mock.calls[1]?.[2]).toEqual(["models", "--refresh"]);
expect(spy.mock.calls[2]?.[2]).toEqual(["models"]);
});
it("still rejects from the original catalog when refresh returns no models", async () => {
it("still rejects from the original catalog when post-refresh enumeration returns no models", async () => {
const spy = vi
.spyOn(serverUtils, "runChildProcess")
.mockResolvedValueOnce({
@ -217,6 +237,15 @@ describe("openCode models", () => {
pid: 1,
startedAt: new Date().toISOString(),
})
.mockResolvedValueOnce({
exitCode: 0,
signal: null,
timedOut: false,
stdout: "Models cache refreshed\n",
stderr: "",
pid: 1,
startedAt: new Date().toISOString(),
})
.mockResolvedValueOnce({
exitCode: 0,
signal: null,
@ -232,8 +261,9 @@ describe("openCode models", () => {
model: "openrouter/deepseek/deepseek-v4-flash-0731",
}),
).rejects.toThrow("Available models: openrouter/example/stale-model");
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledTimes(3);
expect(spy.mock.calls[1]?.[2]).toEqual(["models", "--refresh"]);
expect(spy.mock.calls[2]?.[2]).toEqual(["models"]);
});
it("still rejects from the original catalog when refresh fails", async () => {

View File

@ -238,12 +238,17 @@ async function refreshOpenCodeModelsCached(input: {
const command = resolveOpenCodeCommand(input.command);
const cwd = asString(input.cwd, process.cwd());
const env = normalizeEnv(input.env);
const models = await discoverOpenCodeModels({
// OpenCode 1.18.17 uses `models --refresh` only to update its on-disk
// models.dev cache. Its stdout is a confirmation message, not the refreshed
// catalog, so enumerate once more after the refresh under the exact same
// command/cwd/env before deciding whether the configured model exists.
await discoverOpenCodeModels({
command,
cwd,
env,
refresh: true,
});
const models = await discoverOpenCodeModels({ command, cwd, env });
if (models.length > 0) {
discoveryCache.set(discoveryCacheKey(command, cwd, env), {
expiresAt: Date.now() + MODELS_CACHE_TTL_MS,