diff --git a/packages/cli/src/commands/handlers/default.ts b/packages/cli/src/commands/handlers/default.ts
index b016b863f90..b3234575895 100644
--- a/packages/cli/src/commands/handlers/default.ts
+++ b/packages/cli/src/commands/handlers/default.ts
@@ -22,6 +22,7 @@ export default Runtime.handler(Commands, (input) =>
const server = yield* ServerConnection.resolve({
server: Option.getOrUndefined(input.server),
standalone: input.standalone,
+ mismatch: "replace",
onStart: (reason, previousVersion) => {
if (reason === "version-mismatch" && preflight.begin(previousVersion)) return
process.stderr.write(
diff --git a/packages/cli/src/commands/handlers/mini.ts b/packages/cli/src/commands/handlers/mini.ts
index 972c3bf962a..541d3409ed4 100644
--- a/packages/cli/src/commands/handlers/mini.ts
+++ b/packages/cli/src/commands/handlers/mini.ts
@@ -10,7 +10,11 @@ export default Runtime.handler(Commands.commands.mini, (input) =>
const { runMini, validateMiniTerminal } = yield* Effect.promise(() => import("../../mini"))
yield* Effect.promise(async () => validateMiniTerminal())
const serverURL = Option.getOrUndefined(input.server)
- const server = yield* ServerConnection.resolve({ server: serverURL, standalone: input.standalone })
+ const server = yield* ServerConnection.resolve({
+ server: serverURL,
+ standalone: input.standalone,
+ mismatch: "replace",
+ })
const config = yield* Config.Service
const resolved = resolve(yield* config.get(), { terminalSuspend: process.platform !== "win32" })
const fileSystem = yield* FileSystem.FileSystem
diff --git a/packages/cli/src/services/server-connection.ts b/packages/cli/src/services/server-connection.ts
index 6f854eefb2f..0ca5649f6e1 100644
--- a/packages/cli/src/services/server-connection.ts
+++ b/packages/cli/src/services/server-connection.ts
@@ -42,9 +42,10 @@ export const resolve = Effect.fn("cli.server-connection.resolve")(function* (arg
return { endpoint: yield* Standalone.start() } satisfies Resolved
}
- const options = yield* ServiceConfig.options()
+ const mismatch = args.mismatch ?? "ignore"
+ const options = yield* ServiceConfig.options({ checkVersion: mismatch !== "ignore" })
return {
- endpoint: yield* resolveManaged({ ...options, onStart: args.onStart }, args.mismatch ?? "replace"),
+ endpoint: yield* resolveManaged({ ...options, onStart: args.onStart }, mismatch),
service: managedService(options),
} satisfies Resolved
})
diff --git a/packages/cli/src/services/service-config.ts b/packages/cli/src/services/service-config.ts
index 57c31029932..d348f390c2d 100644
--- a/packages/cli/src/services/service-config.ts
+++ b/packages/cli/src/services/service-config.ts
@@ -98,12 +98,12 @@ const paths = Effect.gen(function* () {
}
})
-export const options = Effect.fnUntraced(function* () {
+export const options = Effect.fnUntraced(function* (input: { readonly checkVersion?: boolean } = {}) {
const { file, legacyRegistrationFiles } = yield* paths
yield* Effect.forEach(legacyRegistrationFiles, (legacy) => migrateRegistration(legacy, file))
return {
file,
- version: OPENCODE_VERSION,
+ version: input.checkVersion ? OPENCODE_VERSION : undefined,
command: [...selfCommand(), "serve", "--service"],
}
})
diff --git a/packages/cli/test/server-connection.test.ts b/packages/cli/test/server-connection.test.ts
index f87854a7a10..f5ec0dc6e8f 100644
--- a/packages/cli/test/server-connection.test.ts
+++ b/packages/cli/test/server-connection.test.ts
@@ -55,3 +55,17 @@ test("resolution groups Effect-native lifecycle operations only for the managed
await fs.rm(root, { recursive: true, force: true })
}
})
+
+test("service options only require a matching version when requested", async () => {
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-service-options-"))
+ const layer = Global.layerWith({ config: path.join(root, "config"), state: path.join(root, "state") })
+ const runPromise = (effect: Effect.Effect) =>
+ Effect.runPromise(effect.pipe(Effect.provide(layer), Effect.provide(NodeFileSystem.layer), Effect.scoped))
+
+ try {
+ expect((await runPromise(ServiceConfig.options())).version).toBeUndefined()
+ expect((await runPromise(ServiceConfig.options({ checkVersion: true }))).version).toBe(OPENCODE_VERSION)
+ } finally {
+ await fs.rm(root, { recursive: true, force: true })
+ }
+})