From ed95ba73f4e1b1c5b3d94db88d2e7fa3aa640be2 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Sat, 23 May 2026 19:39:03 -0400 Subject: [PATCH] test(opencode): restore config coverage parity --- bun.lock | 1 - packages/desktop/package.json | 1 - packages/opencode/test/config/config.test.ts | 96 +++++++++++++++----- 3 files changed, 74 insertions(+), 24 deletions(-) diff --git a/bun.lock b/bun.lock index 3ef06eda272..659d844823c 100644 --- a/bun.lock +++ b/bun.lock @@ -274,7 +274,6 @@ "@sentry/solid": "catalog:", "@sentry/vite-plugin": "catalog:", "@solid-primitives/i18n": "2.2.1", - "@solid-primitives/scheduled": "1.5.3", "@solid-primitives/storage": "catalog:", "@solidjs/meta": "catalog:", "@solidjs/router": "0.15.4", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index d78cd5e3063..ed9041e72b3 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -42,7 +42,6 @@ "@sentry/solid": "catalog:", "@sentry/vite-plugin": "catalog:", "@solid-primitives/i18n": "2.2.1", - "@solid-primitives/scheduled": "1.5.3", "@solid-primitives/storage": "catalog:", "@solidjs/meta": "catalog:", "@solidjs/router": "0.15.4", diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts index 49b7643d7bc..6ce0acdb2a7 100644 --- a/packages/opencode/test/config/config.test.ts +++ b/packages/opencode/test/config/config.test.ts @@ -128,6 +128,7 @@ const clear = (wait = false) => Effect.runPromise(clearEffect(wait)) // Get managed config directory from environment (set in preload.ts) const managedConfigDir = process.env.OPENCODE_TEST_MANAGED_CONFIG_DIR! const originalTestToken = process.env.TEST_TOKEN +const originalConsoleToken = process.env.OPENCODE_CONSOLE_TOKEN beforeEach(async () => { await clear(true) @@ -137,6 +138,8 @@ afterEach(async () => { await fs.rm(managedConfigDir, { force: true, recursive: true }).catch(() => {}) if (originalTestToken === undefined) delete process.env.TEST_TOKEN else process.env.TEST_TOKEN = originalTestToken + if (originalConsoleToken === undefined) delete process.env.OPENCODE_CONSOLE_TOKEN + else process.env.OPENCODE_CONSOLE_TOKEN = originalConsoleToken await clear(true) }) @@ -163,14 +166,14 @@ const withGlobalConfigDir = (dir: string, effect: Effect.Effect effect, (previous) => Effect.gen(function* () { ;(Global.Path as { config: string }).config = previous - yield* clearEffect() + yield* clearEffect(true) }), ) @@ -190,10 +193,11 @@ const withConfigTree = ( ) => Effect.gen(function* () { const root = yield* tmpdirScoped() + const global = yield* tmpdirScoped() const directory = path.join(root, "project") yield* Effect.all( [ - input.global ? writeConfigEffect(root, schemaConfig(input.global)) : undefined, + input.global ? writeConfigEffect(global, schemaConfig(input.global)) : undefined, input.project ? writeConfigEffect(directory, schemaConfig(input.project)) : undefined, input.local ? writeConfigEffect(path.join(directory, ".opencode"), schemaConfig(input.local)) : undefined, ].filter( @@ -201,7 +205,7 @@ const withConfigTree = ( ), { concurrency: "unbounded" }, ) - return yield* withInstanceDir(directory, effect) + return yield* withGlobalConfigDir(global, withInstanceDir(directory, effect)) }) const wellKnown = (input: { @@ -952,6 +956,25 @@ it.effect("merges plugin arrays from global and local configs", () => ), ) +it.effect("global config remains global when project config is disabled", () => + withConfigTree( + { + global: { model: "global/model", plugin: ["global-plugin"] }, + project: { model: "project/model" }, + local: { model: "local/model" }, + }, + withProcessEnv( + "OPENCODE_DISABLE_PROJECT_CONFIG", + "true", + Effect.gen(function* () { + const config = yield* Config.use.get() + expect(config.model).toBe("global/model") + expect(config.plugin_origins?.find((item) => item.spec === "global-plugin")?.scope).toBe("global") + }), + ), + ), +) + it.instance("does not error when only custom agent is a subagent", () => Effect.gen(function* () { const test = yield* TestInstance @@ -1130,6 +1153,16 @@ it.instance( { config: { autoupdate: true, disabled_providers: [] } }, ) +it.instance("managed jsonc settings override managed json settings", () => + Effect.gen(function* () { + yield* writeManagedSettingsEffect({ model: "managed/json" }) + yield* writeManagedSettingsEffect({ model: "managed/jsonc" }, "opencode.jsonc") + + const config = yield* Config.use.get() + expect(config.model).toBe("managed/jsonc") + }), +) + it.instance( "missing managed settings file is not an error", Effect.gen(function* () { @@ -1439,14 +1472,16 @@ test("remote well-known config can use FetchHttpClient layer", async () => { }) try { - await provideTmpdirInstance(() => - Config.Service.use((svc) => - Effect.gen(function* () { - const config = yield* svc.get() - expect(fetchedUrl).toBe(`${server.url.origin}/.well-known/opencode`) - expect(config.mcp?.jira?.enabled).toBe(true) - }), - ), + await provideTmpdirInstance( + () => + Config.Service.use((svc) => + Effect.gen(function* () { + const config = yield* svc.get() + expect(fetchedUrl).toBe(`${server.url.origin}/.well-known/opencode`) + expect(config.mcp?.jira?.enabled).toBe(true) + }), + ), + { git: true }, ).pipe( Effect.scoped, Effect.provide( @@ -1488,6 +1523,26 @@ templatedHeaderWellKnown.it.instance("wellknown remote_config supports templated }), ) +const remotePrecedenceWellKnown = wellKnown({ + config: { + mcp: { confluence: { type: "remote", url: "https://confluence.example.com/mcp", enabled: false } }, + }, + remoteConfig: { url: "https://config.example.com/{env:TEST_TOKEN}/opencode.json" }, + remote: { + config: { mcp: { confluence: { type: "remote", url: "https://confluence.example.com/mcp", enabled: true } } }, + }, +}) + +remotePrecedenceWellKnown.it.instance( + "wellknown remote_config url tokens and nested config override embedded config", + () => + Effect.gen(function* () { + const config = yield* Config.use.get() + expect(remotePrecedenceWellKnown.seen.remote).toBe("https://config.example.com/test-token/opencode.json") + expect(config.mcp?.confluence?.enabled).toBe(true) + }), +) + const envIsolationWellKnown = wellKnown({ remoteConfig: { url: "https://config.example.com/opencode.json", @@ -1501,16 +1556,13 @@ const envIsolationWellKnown = wellKnown({ envIsolationWellKnown.it.instance( "wellknown token env substitution does not mutate process env", () => - withProcessEnv( - "TEST_TOKEN", - "preexisting-token", - Effect.gen(function* () { - const config = yield* Config.use.get() - expect(envIsolationWellKnown.seen.authorization).toBe("Bearer test-token") - expect(config.username).toBe("test-token") - expect(process.env.TEST_TOKEN).toBe("preexisting-token") - }), - ), + Effect.gen(function* () { + process.env.TEST_TOKEN = "preexisting-token" + const config = yield* Config.use.get() + expect(envIsolationWellKnown.seen.authorization).toBe("Bearer test-token") + expect(config.username).toBe("test-token") + expect(process.env.TEST_TOKEN).toBe("preexisting-token") + }), { git: true, config: { username: "{env:TEST_TOKEN}" } }, )