+21

![opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)



![opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)



James Long
Brendan Allan
Kit Langton
opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Affan Ali
affanali2k3
Frank
opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴
Aiden Cline
Jay V
Dax Raad
Aarav Sareen
OpeOginni
Luke Parker
Ben Guthrie
Dax
Filip
Max Anderson
Brendan Allan
Jack
Shoubhit Dash
Dustin Deus
starptech
Aiden Cline
usrnk1
Jay
runvip
opencode
Julian Coy
Vladimir Glafirov
8c94e9005f
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Kit Langton <kit.langton@gmail.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Affan Ali <93028901+affanali2k3@users.noreply.github.com> Co-authored-by: affanali2k3 <affanalikhanxx@gmail.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: 𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 <little-frank@opencord.local> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Jay V <air@live.ca> Co-authored-by: Dax Raad <d@ironbay.co> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: Ben Guthrie <benjee.012@gmail.com> Co-authored-by: Dax <mail@thdxr.com> Co-authored-by: Filip <34747899+neriousy@users.noreply.github.com> Co-authored-by: Max Anderson <max.a.anderson95@gmail.com> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: starptech <starptech@starptechs-MBP.fritz.box> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: runvip <164729189+runvip@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Julian Coy <julian@ex-machina.co> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
375 lines
13 KiB
TypeScript
375 lines
13 KiB
TypeScript
import { describe, expect } from "bun:test"
|
|
import { ConfigProvider, Effect, Layer } from "effect"
|
|
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
|
import { RuntimeFlags } from "../../src/effect/runtime-flags"
|
|
import { it } from "../lib/effect"
|
|
|
|
const fromConfig = (input: Record<string, unknown>) =>
|
|
AppNodeBuilder.build(RuntimeFlags.node).pipe(Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown(input))))
|
|
|
|
const readFlags = RuntimeFlags.Service.useSync((flags) => flags)
|
|
|
|
describe("RuntimeFlags", () => {
|
|
it.effect("layer defaults autoShare to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.autoShare).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("layer parses plugin flags from the active ConfigProvider", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(
|
|
fromConfig({
|
|
OPENCODE_PURE: "true",
|
|
OPENCODE_DISABLE_DEFAULT_PLUGINS: "true",
|
|
OPENCODE_AUTO_SHARE: "true",
|
|
OPENCODE_DISABLE_EMBEDDED_WEB_UI: "true",
|
|
OPENCODE_DISABLE_EXTERNAL_SKILLS: "true",
|
|
OPENCODE_DISABLE_LSP_DOWNLOAD: "true",
|
|
OPENCODE_EXPERIMENTAL: "true",
|
|
OPENCODE_ENABLE_EXA: "true",
|
|
OPENCODE_ENABLE_PARALLEL: "true",
|
|
OPENCODE_ENABLE_EXPERIMENTAL_MODELS: "true",
|
|
OPENCODE_ENABLE_QUESTION_TOOL: "true",
|
|
OPENCODE_CLIENT: "desktop",
|
|
}),
|
|
),
|
|
)
|
|
|
|
expect(flags.pure).toBe(true)
|
|
expect(flags.autoShare).toBe(true)
|
|
expect(flags.disableDefaultPlugins).toBe(true)
|
|
expect(flags.disableEmbeddedWebUi).toBe(true)
|
|
expect(flags.disableExternalSkills).toBe(true)
|
|
expect(flags.disableLspDownload).toBe(true)
|
|
expect(flags.disableClaudeCodePrompt).toBe(false)
|
|
expect(flags.enableExa).toBe(true)
|
|
expect(flags.enableParallel).toBe(true)
|
|
expect(flags.enableExperimentalModels).toBe(true)
|
|
expect(flags.enableQuestionTool).toBe(true)
|
|
expect(flags.experimentalReferences).toBe(true)
|
|
expect(flags.experimentalBackgroundSubagents).toBe(true)
|
|
expect(flags.experimentalLspTy).toBe(false)
|
|
expect(flags.experimentalLspTool).toBe(true)
|
|
expect(flags.experimentalOxfmt).toBe(true)
|
|
expect(flags.experimentalPlanMode).toBe(true)
|
|
expect(flags.experimentalEventSystem).toBe(true)
|
|
expect(flags.experimentalWorkspaces).toBe(true)
|
|
expect(flags.experimentalIconDiscovery).toBe(true)
|
|
expect(flags.experimentalNativeLlm).toBe(false)
|
|
expect(flags.experimentalWebSockets).toBe(false)
|
|
expect(flags.client).toBe("desktop")
|
|
}),
|
|
)
|
|
|
|
it.effect("layer parses OPENCODE_EXPERIMENTAL_LSP_TY", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(
|
|
fromConfig({
|
|
OPENCODE_EXPERIMENTAL_LSP_TY: "true",
|
|
}),
|
|
),
|
|
)
|
|
|
|
expect(flags.experimentalLspTy).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("enables native LLM via dedicated flag only", () =>
|
|
Effect.gen(function* () {
|
|
const explicit = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL_NATIVE_LLM: "true" })))
|
|
const umbrella = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL: "true" })))
|
|
|
|
expect(explicit.experimentalNativeLlm).toBe(true)
|
|
expect(umbrella.experimentalNativeLlm).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("enables WebSockets via dedicated flag only", () =>
|
|
Effect.gen(function* () {
|
|
const explicit = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL_WEBSOCKETS: "true" })))
|
|
const umbrella = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL: "true" })))
|
|
|
|
expect(explicit.experimentalWebSockets).toBe(true)
|
|
expect(umbrella.experimentalWebSockets).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("layer accepts partial test overrides and fills defaults from Config definitions", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(RuntimeFlags.layer({ disableDefaultPlugins: true, bashDefaultTimeoutMs: 1_000 })),
|
|
)
|
|
|
|
expect(flags.pure).toBe(false)
|
|
expect(flags.autoShare).toBe(false)
|
|
expect(flags.disableDefaultPlugins).toBe(true)
|
|
expect(flags.disableEmbeddedWebUi).toBe(false)
|
|
expect(flags.disableExternalSkills).toBe(false)
|
|
expect(flags.disableLspDownload).toBe(false)
|
|
expect(flags.disableClaudeCodePrompt).toBe(false)
|
|
expect(flags.disableClaudeCodeSkills).toBe(false)
|
|
expect(flags.enableExa).toBe(false)
|
|
expect(flags.experimentalIconDiscovery).toBe(false)
|
|
expect(flags.experimentalOxfmt).toBe(false)
|
|
expect(flags.outputTokenMax).toBeUndefined()
|
|
expect(flags.bashDefaultTimeoutMs).toBe(1_000)
|
|
expect(flags.enableExperimentalModels).toBe(false)
|
|
expect(flags.client).toBe("cli")
|
|
}),
|
|
)
|
|
|
|
it.effect("experimentalIconDiscovery defaults to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.experimentalIconDiscovery).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableExternalSkills defaults to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.disableExternalSkills).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableExternalSkills reads OPENCODE_DISABLE_EXTERNAL_SKILLS", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_EXTERNAL_SKILLS: "true" })))
|
|
|
|
expect(flags.disableExternalSkills).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableLspDownload defaults to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.disableLspDownload).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableLspDownload reads OPENCODE_DISABLE_LSP_DOWNLOAD", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_LSP_DOWNLOAD: "true" })))
|
|
|
|
expect(flags.disableLspDownload).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableClaudeCodePrompt defaults to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.disableClaudeCodePrompt).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableClaudeCodePrompt reads OPENCODE_DISABLE_CLAUDE_CODE_PROMPT", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_CLAUDE_CODE_PROMPT: "true" })))
|
|
|
|
expect(flags.disableClaudeCodePrompt).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableClaudeCodePrompt inherits OPENCODE_DISABLE_CLAUDE_CODE", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_CLAUDE_CODE: "true" })))
|
|
|
|
expect(flags.disableClaudeCodePrompt).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("experimentalIconDiscovery reads OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL_ICON_DISCOVERY: "true" })))
|
|
|
|
expect(flags.experimentalIconDiscovery).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("experimentalIconDiscovery inherits OPENCODE_EXPERIMENTAL", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL: "true" })))
|
|
|
|
expect(flags.experimentalIconDiscovery).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("specific experimental flags override OPENCODE_EXPERIMENTAL", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(
|
|
fromConfig({
|
|
OPENCODE_EXPERIMENTAL: "true",
|
|
OPENCODE_EXPERIMENTAL_ICON_DISCOVERY: "false",
|
|
}),
|
|
),
|
|
)
|
|
|
|
expect(flags.experimentalIconDiscovery).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("experimentalOxfmt defaults to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.experimentalOxfmt).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("experimentalOxfmt is enabled by OPENCODE_EXPERIMENTAL_OXFMT", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(
|
|
fromConfig({
|
|
OPENCODE_EXPERIMENTAL_OXFMT: "true",
|
|
}),
|
|
),
|
|
)
|
|
|
|
expect(flags.experimentalOxfmt).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("experimentalOxfmt inherits OPENCODE_EXPERIMENTAL", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(
|
|
fromConfig({
|
|
OPENCODE_EXPERIMENTAL: "true",
|
|
}),
|
|
),
|
|
)
|
|
|
|
expect(flags.experimentalOxfmt).toBe(true)
|
|
}),
|
|
)
|
|
|
|
for (const input of [
|
|
{ name: "absent", config: {}, expected: undefined },
|
|
{
|
|
name: "valid positive integer",
|
|
config: { OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "1234" },
|
|
expected: 1234,
|
|
},
|
|
{
|
|
name: "invalid string",
|
|
config: { OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "nope" },
|
|
expected: undefined,
|
|
},
|
|
{ name: "zero", config: { OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "0" }, expected: undefined },
|
|
{ name: "negative", config: { OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "-1" }, expected: undefined },
|
|
{
|
|
name: "non-integer",
|
|
config: { OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "1.5" },
|
|
expected: undefined,
|
|
},
|
|
]) {
|
|
it.effect(`parses bashDefaultTimeoutMs from config: ${input.name}`, () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig(input.config)))
|
|
|
|
expect(flags.bashDefaultTimeoutMs).toBe(input.expected)
|
|
}),
|
|
)
|
|
}
|
|
|
|
for (const input of [
|
|
{ name: "absent", config: {}, expected: undefined },
|
|
{
|
|
name: "valid positive integer",
|
|
config: { OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX: "1234" },
|
|
expected: 1234,
|
|
},
|
|
{
|
|
name: "invalid string",
|
|
config: { OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX: "nope" },
|
|
expected: undefined,
|
|
},
|
|
{ name: "zero", config: { OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX: "0" }, expected: undefined },
|
|
{ name: "negative", config: { OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX: "-1" }, expected: undefined },
|
|
{
|
|
name: "non-integer",
|
|
config: { OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX: "1.5" },
|
|
expected: undefined,
|
|
},
|
|
]) {
|
|
it.effect(`parses outputTokenMax from config: ${input.name}`, () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig(input.config)))
|
|
|
|
expect(flags.outputTokenMax).toBe(input.expected)
|
|
}),
|
|
)
|
|
}
|
|
|
|
it.effect("layer ignores the active ConfigProvider for omitted test overrides", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(
|
|
Effect.provide(RuntimeFlags.layer()),
|
|
Effect.provide(
|
|
ConfigProvider.layer(
|
|
ConfigProvider.fromUnknown({
|
|
OPENCODE_PURE: "true",
|
|
OPENCODE_DISABLE_DEFAULT_PLUGINS: "true",
|
|
OPENCODE_DISABLE_EXTERNAL_SKILLS: "true",
|
|
OPENCODE_DISABLE_LSP_DOWNLOAD: "true",
|
|
OPENCODE_EXPERIMENTAL: "true",
|
|
OPENCODE_ENABLE_EXA: "true",
|
|
OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "1234",
|
|
OPENCODE_CLIENT: "desktop",
|
|
}),
|
|
),
|
|
),
|
|
)
|
|
|
|
expect(flags.pure).toBe(false)
|
|
expect(flags.disableDefaultPlugins).toBe(false)
|
|
expect(flags.disableEmbeddedWebUi).toBe(false)
|
|
expect(flags.disableExternalSkills).toBe(false)
|
|
expect(flags.disableLspDownload).toBe(false)
|
|
expect(flags.disableClaudeCodePrompt).toBe(false)
|
|
expect(flags.disableClaudeCodeSkills).toBe(false)
|
|
expect(flags.enableExa).toBe(false)
|
|
expect(flags.experimentalIconDiscovery).toBe(false)
|
|
expect(flags.experimentalOxfmt).toBe(false)
|
|
expect(flags.outputTokenMax).toBeUndefined()
|
|
expect(flags.bashDefaultTimeoutMs).toBeUndefined()
|
|
expect(flags.client).toBe("cli")
|
|
}),
|
|
)
|
|
|
|
it.effect("disableClaudeCodeSkills defaults to false", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
|
|
|
|
expect(flags.disableClaudeCodeSkills).toBe(false)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableClaudeCodeSkills reads OPENCODE_DISABLE_CLAUDE_CODE_SKILLS", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_CLAUDE_CODE_SKILLS: "true" })))
|
|
|
|
expect(flags.disableClaudeCodeSkills).toBe(true)
|
|
}),
|
|
)
|
|
|
|
it.effect("disableClaudeCodeSkills inherits OPENCODE_DISABLE_CLAUDE_CODE", () =>
|
|
Effect.gen(function* () {
|
|
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DISABLE_CLAUDE_CODE: "true" })))
|
|
|
|
expect(flags.disableClaudeCodeSkills).toBe(true)
|
|
}),
|
|
)
|
|
})
|