From b96436600302a57f2e66364f763326554b510b0c Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 1 May 2026 22:30:47 -0400 Subject: [PATCH] refactor: extract InstanceStore.provide helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds InstanceStore.provide(input, effect) — loads the cached instance context and provides InstanceRef to the wrapped effect. Replaces the inline makeInstanceContext + provideService(InstanceRef) dance in the HttpApi middleware, and gives non-middleware callers (CLI bridges, background jobs) a single primitive for entering an instance scope from Effect-native code. --- packages/opencode/src/project/instance-store.ts | 6 ++++++ .../httpapi/middleware/instance-context.ts | 17 ++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/project/instance-store.ts b/packages/opencode/src/project/instance-store.ts index 327835ea074..7abb0bb7e33 100644 --- a/packages/opencode/src/project/instance-store.ts +++ b/packages/opencode/src/project/instance-store.ts @@ -1,5 +1,6 @@ import { GlobalBus } from "@/bus/global" import { WorkspaceContext } from "@/control-plane/workspace-context" +import { InstanceRef } from "@/effect/instance-ref" import { disposeInstance } from "@/effect/instance-registry" import { makeRuntime } from "@/effect/run-service" import { AppFileSystem } from "@opencode-ai/core/filesystem" @@ -19,6 +20,7 @@ export interface Interface { readonly reload: (input: LoadInput) => Effect.Effect readonly dispose: (ctx: InstanceContext) => Effect.Effect readonly disposeAll: () => Effect.Effect + readonly provide: (input: LoadInput, effect: Effect.Effect) => Effect.Effect } export class Service extends Context.Service()("@opencode/InstanceStore") {} @@ -168,6 +170,9 @@ export const layer: Layer.Layer = Layer.effect( return yield* cachedDisposeAll }) + const provide = (input: LoadInput, effect: Effect.Effect): Effect.Effect => + load(input).pipe(Effect.flatMap((ctx) => effect.pipe(Effect.provideService(InstanceRef, ctx)))) + yield* Effect.addFinalizer(() => disposeAll().pipe(Effect.ignore)) return Service.of({ @@ -175,6 +180,7 @@ export const layer: Layer.Layer = Layer.effect( reload, dispose, disposeAll, + provide, }) }), ) diff --git a/packages/opencode/src/server/routes/instance/httpapi/middleware/instance-context.ts b/packages/opencode/src/server/routes/instance/httpapi/middleware/instance-context.ts index 4bb15cd3cdc..bf0093bd2ba 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/middleware/instance-context.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/middleware/instance-context.ts @@ -1,7 +1,6 @@ -import { InstanceRef, WorkspaceRef } from "@/effect/instance-ref" +import { WorkspaceRef } from "@/effect/instance-ref" import { AppRuntime } from "@/effect/app-runtime" import { InstanceBootstrap } from "@/project/bootstrap" -import type { InstanceContext } from "@/project/instance" import { InstanceStore } from "@/project/instance-store" import { Effect, Layer } from "effect" import { HttpRouter, HttpServerResponse } from "effect/unstable/http" @@ -23,23 +22,15 @@ function decode(input: string): string { } } -function makeInstanceContext(store: InstanceStore.Interface, directory: string): Effect.Effect { - return store.load({ - directory: decode(directory), - init: () => AppRuntime.runPromise(InstanceBootstrap), - }) -} - function provideInstanceContext( effect: Effect.Effect, store: InstanceStore.Interface, ): Effect.Effect { return Effect.gen(function* () { const route = yield* WorkspaceRouteContext - const ctx = yield* makeInstanceContext(store, route.directory) - return yield* effect.pipe( - Effect.provideService(InstanceRef, ctx), - Effect.provideService(WorkspaceRef, route.workspaceID), + return yield* store.provide( + { directory: decode(route.directory), init: () => AppRuntime.runPromise(InstanceBootstrap) }, + effect.pipe(Effect.provideService(WorkspaceRef, route.workspaceID)), ) }) }