export * as Status from "./service-status" import { ServiceStatus } from "@opencode-ai/protocol/groups/health" import { Effect, Ref } from "effect" export type State = | { readonly type: "starting" } | { readonly type: "ready" } | { readonly type: "stopping" } | { readonly type: "failed" } export interface Interface { readonly current: Effect.Effect readonly ready: Effect.Effect readonly fail: Effect.Effect readonly beginStopping: Effect.Effect readonly requestStop: (request: ServiceStatus.StopRequest) => Effect.Effect } export const make = Effect.fnUntraced(function* (options: { readonly instanceID: string readonly managed: boolean readonly initial?: State }) { const current = yield* Ref.make(options.initial ?? ({ type: "starting" } satisfies State)) const beginStopping = Ref.update(current, (status) => status.type === "stopping" ? status : ({ type: "stopping" } satisfies State), ) return { current: Ref.get(current), ready: Ref.update(current, (status) => status.type === "starting" ? ({ type: "ready" } satisfies State) : status, ), fail: Ref.update(current, (status) => status.type === "starting" ? ({ type: "failed" } satisfies State) : status, ), beginStopping, requestStop: (request) => { if (!options.managed || request.instanceID !== options.instanceID) return Effect.succeed(false) return beginStopping.pipe(Effect.as(true)) }, } satisfies Interface })