refactor(core): resolve database and websearch config through Effect Config
This commit is contained in:
parent
4045041554
commit
0552458fba
10 changed files with 222 additions and 46 deletions
37
packages/core/test/database-path.test.ts
Normal file
37
packages/core/test/database-path.test.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import path from "path"
|
||||
import { ConfigProvider, Effect, Layer } from "effect"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { tmpdir } from "./fixture/tmpdir"
|
||||
|
||||
const resolve = (env: Record<string, string>) =>
|
||||
Effect.runPromise(Effect.provide(Database.configuredPath, ConfigProvider.layer(ConfigProvider.fromUnknown(env))))
|
||||
|
||||
describe("Database placement", () => {
|
||||
test("resolves explicit files, relative names, and the channel default", async () => {
|
||||
expect(await resolve({ OPENCODE_DB: ":memory:" })).toBe(":memory:")
|
||||
expect(await resolve({ OPENCODE_DB: "/tmp/explicit.db" })).toBe("/tmp/explicit.db")
|
||||
expect(await resolve({ OPENCODE_DB: "relative.db" })).toBe(path.join(Global.Path.data, "relative.db"))
|
||||
expect(await resolve({ OPENCODE_DISABLE_CHANNEL_DB: "true" })).toBe(path.join(Global.Path.data, "opencode.db"))
|
||||
})
|
||||
|
||||
test("reads placement from the active ConfigProvider when the layer is built", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
const file = path.join(tmp.path, "config-seam.sqlite")
|
||||
|
||||
// The preload sets OPENCODE_DB=":memory:" in the process environment, so a
|
||||
// database appearing at this path proves the layer reads through the
|
||||
// replaced ConfigProvider rather than the environment snapshot.
|
||||
await Effect.runPromise(
|
||||
Layer.build(
|
||||
LayerNode.compile(LayerNode.group([Database.node])).pipe(
|
||||
Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown({ OPENCODE_DB: file }))),
|
||||
),
|
||||
).pipe(Effect.scoped, Effect.asVoid),
|
||||
)
|
||||
|
||||
expect(await Bun.file(file).exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { beforeEach, describe, expect, test } from "bun:test"
|
||||
import { Effect, Layer, Schema } from "effect"
|
||||
import { ConfigProvider, Effect, Layer, Schema } from "effect"
|
||||
import { HttpClient, HttpClientResponse } from "effect/unstable/http"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
|
|
@ -47,6 +47,57 @@ describe("WebSearchTool provider selection", () => {
|
|||
})
|
||||
})
|
||||
|
||||
const readDefaultConfig = (env: Record<string, string>) =>
|
||||
Effect.provide(
|
||||
WebSearchTool.ConfigService,
|
||||
WebSearchTool.defaultConfigLayer.pipe(Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown(env)))),
|
||||
)
|
||||
|
||||
describe("WebSearchTool default config", () => {
|
||||
test("decodes an empty environment to defaults", async () => {
|
||||
expect(await Effect.runPromise(readDefaultConfig({}))).toEqual({
|
||||
provider: undefined,
|
||||
enableExa: false,
|
||||
enableParallel: false,
|
||||
exaApiKey: undefined,
|
||||
parallelApiKey: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
test("decodes provider, truthy flags, and credentials from the active ConfigProvider", async () => {
|
||||
expect(
|
||||
await Effect.runPromise(
|
||||
readDefaultConfig({
|
||||
OPENCODE_WEBSEARCH_PROVIDER: "parallel",
|
||||
OPENCODE_ENABLE_EXA: "1",
|
||||
OPENCODE_EXPERIMENTAL_PARALLEL: "true",
|
||||
EXA_API_KEY: "exa-key",
|
||||
PARALLEL_API_KEY: "parallel-key",
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
provider: "parallel",
|
||||
enableExa: true,
|
||||
enableParallel: true,
|
||||
exaApiKey: "exa-key",
|
||||
parallelApiKey: "parallel-key",
|
||||
})
|
||||
})
|
||||
|
||||
test("keeps the legacy lenient truthiness grammar", async () => {
|
||||
const decoded = await Effect.runPromise(
|
||||
readDefaultConfig({ OPENCODE_ENABLE_EXA: "TRUE", OPENCODE_ENABLE_PARALLEL: "banana" }),
|
||||
)
|
||||
expect(decoded.enableExa).toBe(true)
|
||||
expect(decoded.enableParallel).toBe(false)
|
||||
})
|
||||
|
||||
test("ignores an invalid provider instead of failing the Location layer", async () => {
|
||||
const decoded = await Effect.runPromise(readDefaultConfig({ OPENCODE_WEBSEARCH_PROVIDER: "bing" }))
|
||||
expect(decoded.provider).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe("WebSearchTool MCP response parser", () => {
|
||||
test("parses plain JSON-RPC responses", async () => {
|
||||
expect(await Effect.runPromise(WebSearchTool.parseResponse(payload("search results")))).toBe("search results")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue