diff --git a/packages/core/src/flag/flag.ts b/packages/core/src/flag/flag.ts index 97d9cd5dab..ee5274461a 100644 --- a/packages/core/src/flag/flag.ts +++ b/packages/core/src/flag/flag.ts @@ -51,7 +51,6 @@ export const Flag = { OPENCODE_MODELS_URL: process.env["OPENCODE_MODELS_URL"], OPENCODE_MODELS_PATH: process.env["OPENCODE_MODELS_PATH"], OPENCODE_DB: process.env["OPENCODE_DB"], - OPENCODE_SKIP_MIGRATIONS: truthy("OPENCODE_SKIP_MIGRATIONS"), OPENCODE_STRICT_CONFIG_DEPS: truthy("OPENCODE_STRICT_CONFIG_DEPS"), OPENCODE_WORKSPACE_ID: process.env["OPENCODE_WORKSPACE_ID"], diff --git a/packages/opencode/src/effect/runtime-flags.ts b/packages/opencode/src/effect/runtime-flags.ts index 20e7d24963..0b5939cd7d 100644 --- a/packages/opencode/src/effect/runtime-flags.ts +++ b/packages/opencode/src/effect/runtime-flags.ts @@ -19,6 +19,7 @@ export class Service extends ConfigService.Service()("@opencode/Runtime disableEmbeddedWebUi: bool("OPENCODE_DISABLE_EMBEDDED_WEB_UI"), disableExternalSkills: bool("OPENCODE_DISABLE_EXTERNAL_SKILLS"), disableLspDownload: bool("OPENCODE_DISABLE_LSP_DOWNLOAD"), + skipMigrations: bool("OPENCODE_SKIP_MIGRATIONS"), disableClaudeCodePrompt: Config.all({ broad: bool("OPENCODE_DISABLE_CLAUDE_CODE"), direct: bool("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"), diff --git a/packages/opencode/src/storage/db.ts b/packages/opencode/src/storage/db.ts index 3c93639136..6cb819a6fd 100644 --- a/packages/opencode/src/storage/db.ts +++ b/packages/opencode/src/storage/db.ts @@ -23,19 +23,19 @@ export const NotFoundError = NamedError.create("NotFoundError", { const log = Log.create({ service: "db" }) -type ChannelDbFlags = Pick +type DatabaseFlags = Pick const readRuntimeFlags = () => Effect.runSync(RuntimeFlags.Service.useSync((flags) => flags).pipe(Effect.provide(RuntimeFlags.defaultLayer))) -export function getChannelPath(flags: ChannelDbFlags = readRuntimeFlags()) { +export function getChannelPath(flags: Pick = readRuntimeFlags()) { if (["latest", "beta", "prod"].includes(InstallationChannel) || flags.disableChannelDb) return path.join(Global.Path.data, "opencode.db") const safe = InstallationChannel.replace(/[^a-zA-Z0-9._-]/g, "-") return path.join(Global.Path.data, `opencode-${safe}.db`) } -export const getPath = (flags?: ChannelDbFlags) => { +export const getPath = (flags?: Pick) => { if (Flag.OPENCODE_DB) { if (Flag.OPENCODE_DB === ":memory:" || path.isAbsolute(Flag.OPENCODE_DB)) return Flag.OPENCODE_DB return path.join(Global.Path.data, Flag.OPENCODE_DB) @@ -93,7 +93,7 @@ let client: Client | undefined let loaded = false export const Client = Object.assign( - (flags?: ChannelDbFlags): Client => { + (flags: DatabaseFlags = readRuntimeFlags()): Client => { if (loaded) return client as Client const dbPath = getPath(flags) @@ -118,7 +118,7 @@ export const Client = Object.assign( count: entries.length, mode: typeof OPENCODE_MIGRATIONS !== "undefined" ? "bundled" : "dev", }) - if (Flag.OPENCODE_SKIP_MIGRATIONS) { + if (flags.skipMigrations) { for (const item of entries) { item.sql = "select 1;" } diff --git a/packages/opencode/test/effect/runtime-flags.test.ts b/packages/opencode/test/effect/runtime-flags.test.ts index 2ac53a3d54..665b546f3d 100644 --- a/packages/opencode/test/effect/runtime-flags.test.ts +++ b/packages/opencode/test/effect/runtime-flags.test.ts @@ -29,6 +29,7 @@ describe("RuntimeFlags", () => { OPENCODE_DISABLE_EMBEDDED_WEB_UI: "true", OPENCODE_DISABLE_EXTERNAL_SKILLS: "true", OPENCODE_DISABLE_LSP_DOWNLOAD: "true", + OPENCODE_SKIP_MIGRATIONS: "true", OPENCODE_EXPERIMENTAL: "true", OPENCODE_ENABLE_EXA: "true", OPENCODE_ENABLE_PARALLEL: "true", @@ -46,6 +47,7 @@ describe("RuntimeFlags", () => { expect(flags.disableEmbeddedWebUi).toBe(true) expect(flags.disableExternalSkills).toBe(true) expect(flags.disableLspDownload).toBe(true) + expect(flags.skipMigrations).toBe(true) expect(flags.disableClaudeCodePrompt).toBe(false) expect(flags.enableExa).toBe(true) expect(flags.enableParallel).toBe(true) @@ -91,6 +93,7 @@ describe("RuntimeFlags", () => { expect(flags.disableEmbeddedWebUi).toBe(false) expect(flags.disableExternalSkills).toBe(false) expect(flags.disableLspDownload).toBe(false) + expect(flags.skipMigrations).toBe(false) expect(flags.disableClaudeCodePrompt).toBe(false) expect(flags.disableClaudeCodeSkills).toBe(false) expect(flags.enableExa).toBe(false) @@ -143,6 +146,22 @@ describe("RuntimeFlags", () => { }), ) + it.effect("skipMigrations defaults to false", () => + Effect.gen(function* () { + const flags = yield* readFlags.pipe(Effect.provide(fromConfig({}))) + + expect(flags.skipMigrations).toBe(false) + }), + ) + + it.effect("skipMigrations reads OPENCODE_SKIP_MIGRATIONS", () => + Effect.gen(function* () { + const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_SKIP_MIGRATIONS: "true" }))) + + expect(flags.skipMigrations).toBe(true) + }), + ) + it.effect("disableClaudeCodePrompt defaults to false", () => Effect.gen(function* () { const flags = yield* readFlags.pipe(Effect.provide(fromConfig({}))) @@ -288,6 +307,7 @@ describe("RuntimeFlags", () => { OPENCODE_DISABLE_DEFAULT_PLUGINS: "true", OPENCODE_DISABLE_EXTERNAL_SKILLS: "true", OPENCODE_DISABLE_LSP_DOWNLOAD: "true", + OPENCODE_SKIP_MIGRATIONS: "true", OPENCODE_EXPERIMENTAL: "true", OPENCODE_ENABLE_EXA: "true", OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: "1234", @@ -303,6 +323,7 @@ describe("RuntimeFlags", () => { expect(flags.disableEmbeddedWebUi).toBe(false) expect(flags.disableExternalSkills).toBe(false) expect(flags.disableLspDownload).toBe(false) + expect(flags.skipMigrations).toBe(false) expect(flags.disableClaudeCodePrompt).toBe(false) expect(flags.disableClaudeCodeSkills).toBe(false) expect(flags.enableExa).toBe(false) diff --git a/packages/opencode/test/storage/db.test.ts b/packages/opencode/test/storage/db.test.ts index ec351fdd76..ba7f0912aa 100644 --- a/packages/opencode/test/storage/db.test.ts +++ b/packages/opencode/test/storage/db.test.ts @@ -26,4 +26,13 @@ describe("Database.getChannelPath", () => { expect(Database.getChannelPath(flags)).toBe(path.join(Global.Path.data, "opencode.db")) }).pipe(Effect.provide(RuntimeFlags.layer({ disableChannelDb: true }))), ) + + it.effect("accepts RuntimeFlags with skipMigrations for database callers", () => + Effect.gen(function* () { + const flags = yield* RuntimeFlags.Service + + expect(flags.skipMigrations).toBe(true) + expect(Database.getChannelPath(flags)).toBe(Database.getChannelPath({ disableChannelDb: flags.disableChannelDb })) + }).pipe(Effect.provide(RuntimeFlags.layer({ skipMigrations: true }))), + ) })