diff options
| author | Kit Langton <[email protected]> | 2026-05-02 19:54:13 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-05-02 19:54:13 -0400 |
| commit | 85bb9007baab8e6c5cd28ea39e9eddb15022cb5d (patch) | |
| tree | d890af36bc865047eb656c3a4cfa8befb0342a25 /packages | |
| parent | 9bef88e3b072e426edfce2d7acb9a7f58ce53455 (diff) | |
| download | opencode-85bb9007baab8e6c5cd28ea39e9eddb15022cb5d.tar.gz opencode-85bb9007baab8e6c5cd28ea39e9eddb15022cb5d.zip | |
feat(cli): auto-dispose InstanceContext after effectCmd handlers (#25481)
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/opencode/src/cli/effect-cmd.ts | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/packages/opencode/src/cli/effect-cmd.ts b/packages/opencode/src/cli/effect-cmd.ts index 29f750d16..6785e0b61 100644 --- a/packages/opencode/src/cli/effect-cmd.ts +++ b/packages/opencode/src/cli/effect-cmd.ts @@ -2,6 +2,7 @@ import type { Argv } from "yargs" import { Effect, Schema } from "effect" import { AppRuntime, type AppServices } from "@/effect/app-runtime" import { InstanceStore } from "@/project/instance-store" +import { InstanceRef } from "@/effect/instance-ref" import { cmd } from "./cmd/cmd" /** @@ -21,6 +22,11 @@ export const fail = (message: string, exitCode = 1) => Effect.fail(new CliError( * Effect-native CLI command builder. Wraps yargs `cmd()` so the handler body is * an `Effect` with `InstanceRef` provided and any `AppServices` yieldable. * + * The handler is wrapped in `Effect.ensuring(store.dispose(ctx))` so the loaded + * InstanceContext is disposed (runDisposers + IPC `server.instance.disposed`) + * on every Exit — success, typed failure, defect, or interruption. Matches the + * legacy `bootstrap()` finally-disposal semantics without per-handler boilerplate. + * * Errors propagate to the existing top-level handler in `src/index.ts`; use * `fail("...")` for user-visible domain failures (clean exit, formatted message). * @@ -47,6 +53,17 @@ export const effectCmd = <Args, A>(opts: { // yargs typing wraps Args in ArgumentsCamelCase<WithDoubleDash<...>>; cast at the boundary. const args = rawArgs as unknown as Args const directory = opts.directory?.(args) ?? process.cwd() - await AppRuntime.runPromise(InstanceStore.Service.use((s) => s.provide({ directory }, opts.handler(args)))) + await AppRuntime.runPromise( + InstanceStore.Service.use((store) => + store.provide( + { directory }, + Effect.gen(function* () { + const ctx = yield* InstanceRef + const body = opts.handler(args) + return ctx ? yield* body.pipe(Effect.ensuring(store.dispose(ctx))) : yield* body + }), + ), + ), + ) }, }) |
