diff --git a/packages/opencode/specs/effect-migration.md b/packages/opencode/specs/effect-migration.md index 4f195917fde..86eb156d6e9 100644 --- a/packages/opencode/specs/effect-migration.md +++ b/packages/opencode/specs/effect-migration.md @@ -123,6 +123,7 @@ Done now: - [x] `Discovery` - [x] `File` - [x] `Snapshot` +- [x] `SessionStatus` Still open and likely worth migrating: diff --git a/packages/opencode/src/effect/instances.ts b/packages/opencode/src/effect/instances.ts index 6fcfddb24f5..408b55bedc9 100644 --- a/packages/opencode/src/effect/instances.ts +++ b/packages/opencode/src/effect/instances.ts @@ -8,6 +8,7 @@ import { Instance } from "@/project/instance" import { Vcs } from "@/project/vcs" import { ProviderAuth } from "@/provider/auth-service" import { Question } from "@/question/service" +import { SessionStatus } from "@/session/status" import { Skill } from "@/skill/service" import { Snapshot } from "@/snapshot/service" import { InstanceContext } from "./instance-context" @@ -24,6 +25,7 @@ export type InstanceServices = | FileTime.Service | Format.Service | File.Service + | SessionStatus.Service | Skill.Service | Snapshot.Service @@ -44,6 +46,7 @@ function lookup(_key: string) { FileTime.layer, Format.layer, File.layer, + SessionStatus.layer, Skill.defaultLayer, Snapshot.defaultLayer, ).pipe(Layer.provide(ctx)) diff --git a/packages/opencode/src/effect/runtime.ts b/packages/opencode/src/effect/runtime.ts index e6f1f326262..2cbc4b9e7e6 100644 --- a/packages/opencode/src/effect/runtime.ts +++ b/packages/opencode/src/effect/runtime.ts @@ -20,6 +20,10 @@ export function runPromiseInstance(effect: Effect.Effect(effect: Effect.Effect) { + return runtime.runSync(effect.pipe(Effect.provide(Instances.get(Instance.directory)))) +} + export function disposeRuntime() { return runtime.dispose() } diff --git a/packages/opencode/src/session/status.ts b/packages/opencode/src/session/status.ts index 57e7939853a..af0de15670a 100644 --- a/packages/opencode/src/session/status.ts +++ b/packages/opencode/src/session/status.ts @@ -1,7 +1,8 @@ import { BusEvent } from "@/bus/bus-event" import { Bus } from "@/bus" -import { Instance } from "@/project/instance" +import { runSyncInstance } from "@/effect/runtime" import { SessionID } from "./schema" +import { Effect, Layer, ServiceMap } from "effect" import z from "zod" export namespace SessionStatus { @@ -42,36 +43,51 @@ export namespace SessionStatus { ), } - const state = Instance.state(() => { - const data: Record = {} - return data - }) + export interface Interface { + readonly get: (sessionID: SessionID) => Effect.Effect + readonly list: () => Effect.Effect> + readonly set: (sessionID: SessionID, status: Info) => Effect.Effect + } + + export class Service extends ServiceMap.Service()("@opencode/SessionStatus") {} + + export const layer = Layer.effect( + Service, + Effect.gen(function* () { + const data = new Map() + + const get = Effect.fn("SessionStatus.get")(function* (sessionID: SessionID) { + return data.get(sessionID) ?? { type: "idle" as const } + }) + + const list = Effect.fn("SessionStatus.list")(function* () { + return Object.fromEntries(data) + }) + + const set = Effect.fn("SessionStatus.set")(function* (sessionID: SessionID, status: Info) { + Bus.publish(Event.Status, { sessionID, status }) + if (status.type === "idle") { + // deprecated + Bus.publish(Event.Idle, { sessionID }) + data.delete(sessionID) + return + } + data.set(sessionID, status) + }) - export function get(sessionID: SessionID) { - return ( - state()[sessionID] ?? { - type: "idle", - } - ) + return Service.of({ get, list, set }) + }), + ) + + export function get(sessionID: SessionID): Info { + return runSyncInstance(Service.use((svc) => svc.get(sessionID))) } - export function list() { - return state() + export function list(): Record { + return runSyncInstance(Service.use((svc) => svc.list())) } export function set(sessionID: SessionID, status: Info) { - Bus.publish(Event.Status, { - sessionID, - status, - }) - if (status.type === "idle") { - // deprecated - Bus.publish(Event.Idle, { - sessionID, - }) - delete state()[sessionID] - return - } - state()[sessionID] = status + runSyncInstance(Service.use((svc) => svc.set(sessionID, status))) } }