fix(tui): stabilize reload connection state

This commit is contained in:
Dax Raad 2026-06-30 22:31:51 -04:00
commit 8dd993d25a
16 changed files with 224 additions and 19 deletions

View file

@ -0,0 +1,13 @@
import { define } from "@opencode-ai/plugin/v2/promise"
export default define({
id: "folder-plugin",
setup: async (ctx) => {
await ctx.agent.transform((agents) => {
agents.update("folder", (agent) => {
agent.description = "Loaded from plugin folder"
agent.mode = "subagent"
})
})
},
})

View file

@ -234,6 +234,10 @@ describe("ConfigExternalPlugin", () => {
description: "Loaded from plugin directory",
mode: "subagent",
})
expect(yield* waitForAgent(agents, "folder")).toMatchObject({
description: "Loaded from plugin folder",
mode: "subagent",
})
}),
)
})

View file

@ -0,0 +1,14 @@
import { describe, expect, test } from "bun:test"
import path from "path"
import { Global } from "@opencode-ai/core/global"
import { Logging } from "@opencode-ai/core/observability/logging"
describe("Logging", () => {
test("uses a local-specific log file for local installs", () => {
expect(Logging.file(true, "local")).toBe(path.join(Global.Path.log, "opencode-local.log"))
})
test("keeps non-local installs on the default log file", () => {
expect(Logging.file(false, "next")).toBe(path.join(Global.Path.log, "opencode.log"))
})
})

View file

@ -9,6 +9,27 @@
"id": "local",
"name": "Local",
"env": [],
"models": {}
"models": {
"model": {
"id": "model",
"name": "Local Model",
"release_date": "2026-01-01",
"attachment": false,
"reasoning": true,
"temperature": true,
"tool_call": true,
"limit": { "context": 1000, "output": 100 },
"experimental": {
"modes": {
"high": {
"provider": { "body": { "reasoning_effort": "high" } }
},
"max": {
"provider": { "headers": { "x-variant": "max" }, "body": { "reasoning_effort": "max" } }
}
}
}
}
}
}
}

View file

@ -7,9 +7,11 @@ import { Credential } from "@opencode-ai/core/credential"
import { EventV2 } from "@opencode-ai/core/event"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Location } from "@opencode-ai/core/location"
import { ModelV2 } from "@opencode-ai/core/model"
import { ModelsDev } from "@opencode-ai/core/models-dev"
import { ModelsDevPlugin } from "@opencode-ai/core/plugin/models-dev"
import { Policy } from "@opencode-ai/core/policy"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { location } from "../fixture/location"
import { testEffect } from "../lib/effect"
@ -73,4 +75,48 @@ describe("ModelsDevPlugin", () => {
}),
),
)
it.effect("loads models.dev variants without replacing existing variants", () =>
Effect.acquireUseRelease(
Effect.sync(() => {
const previous = {
path: Flag.OPENCODE_MODELS_PATH,
disabled: Flag.OPENCODE_DISABLE_MODELS_FETCH,
}
Flag.OPENCODE_MODELS_PATH = path.join(import.meta.dir, "fixtures", "models-dev.json")
Flag.OPENCODE_DISABLE_MODELS_FETCH = true
return previous
}),
() =>
Effect.gen(function* () {
const service = yield* Catalog.Service
const integrations = yield* Integration.Service
yield* service.transform((catalog) => {
catalog.model.update(ProviderV2.ID.make("local"), ModelV2.ID.make("model"), (model) => {
model.variants = [
{ id: ModelV2.VariantID.make("high"), headers: { custom: "true" }, body: {} },
{ id: ModelV2.VariantID.make("custom"), headers: {}, body: { custom: true } },
]
})
})
yield* ModelsDevPlugin.effect(
host({
catalog: catalogHost(service),
integration: integrationHost(integrations),
}),
)
expect((yield* service.model.get(ProviderV2.ID.make("local"), ModelV2.ID.make("model")))?.variants).toEqual([
expect.objectContaining({ id: "high", headers: { custom: "true" } }),
expect.objectContaining({ id: "max", headers: { "x-variant": "max" }, body: { reasoning_effort: "max" } }),
expect.objectContaining({ id: "custom", body: { custom: true } }),
])
}).pipe(Effect.provide(ModelsDev.defaultLayer)),
(previous) =>
Effect.sync(() => {
Flag.OPENCODE_MODELS_PATH = previous.path
Flag.OPENCODE_DISABLE_MODELS_FETCH = previous.disabled
}),
),
)
})

View file

@ -133,6 +133,15 @@ describe("OpencodePlugin", () => {
const catalog = yield* Catalog.Service
yield* catalog.transform((draft) => {
draft.provider.update(ProviderV2.ID.make("remote"), () => {})
draft.model.update(ProviderV2.ID.make("remote"), ModelV2.ID.make("model"), (model) => {
model.variants = [
{
id: ModelV2.VariantID.make("custom"),
headers: { "x-custom": "true" },
body: { custom: true },
},
]
})
draft.model.update(ProviderV2.ID.make("remote"), ModelV2.ID.make("stale"), () => {})
})
yield* credentials.create({
@ -176,6 +185,11 @@ describe("OpencodePlugin", () => {
})
expect(model.request.body).toEqual({ custom: "value", temperature: 0.5 })
expect(model.variants).toEqual([
{
id: ModelV2.VariantID.make("custom"),
headers: { "x-custom": "true" },
body: { custom: true },
},
{
id: ModelV2.VariantID.make("high"),
headers: {},