diff --git a/packages/opencode/src/v2/session/storage-memory.ts b/packages/opencode/src/v2/session/storage-memory.ts index 0ca2bd1c26..d47d0678b1 100644 --- a/packages/opencode/src/v2/session/storage-memory.ts +++ b/packages/opencode/src/v2/session/storage-memory.ts @@ -1,4 +1,4 @@ -import { DateTime, Effect, Layer } from "effect" +import { Context, DateTime, Effect, Layer } from "effect" import { SessionMessage } from "@opencode-ai/core/session-message" import { SessionStorage } from "./storage" @@ -7,15 +7,18 @@ export interface State { readonly messages: Map } -export const makeState = (): State => ({ +export class StateService extends Context.Service()("@opencode/v2/session/StorageMemoryState") {} + +const stateLayer = Layer.sync(StateService, () => ({ sessions: new Map(), messages: new Map(), -}) +})) -export const layer = (state: State = makeState()) => - Layer.succeed( - SessionStorage.Service, - SessionStorage.Service.of({ +const storageLayer = Layer.effect( + SessionStorage.Service, + Effect.gen(function* () { + const state = yield* StateService + return SessionStorage.Service.of({ get: (sessionID) => Effect.sync(() => state.sessions.get(sessionID)), list: (input) => Effect.sync(() => { @@ -79,10 +82,13 @@ export const layer = (state: State = makeState()) => const index = messages.findLastIndex((message) => message.type === "compaction") return index === -1 ? messages : messages.slice(index) }), - }), - ) + }) + }), +) -export const defaultLayer = layer() +export const layer = storageLayer.pipe(Layer.provideMerge(stateLayer)) + +export const defaultLayer = layer function compareCursor( id: string, diff --git a/packages/opencode/test/v2/session-storage.test.ts b/packages/opencode/test/v2/session-storage.test.ts index 165097fdec..262f613d6a 100644 --- a/packages/opencode/test/v2/session-storage.test.ts +++ b/packages/opencode/test/v2/session-storage.test.ts @@ -19,7 +19,6 @@ const sessionB = SessionID.make("ses_storage_b") const sessionC = SessionID.make("ses_storage_c") const sessionD = SessionID.make("ses_storage_d") const encodeMessage = Schema.encodeSync(SessionMessage.Message) -const memoryState = SessionStorageMemory.makeState() interface Seeds { readonly reset: Effect.Effect @@ -163,27 +162,29 @@ const sqlSeeds: Seeds = { sessionStorageContract("SessionStorageSql", SessionStorageSql.defaultLayer, sqlSeeds) -const memorySeeds: Seeds = { - reset: Effect.sync(() => { +const memorySeeds: Seeds = { + reset: Effect.gen(function* () { + const memoryState = yield* SessionStorageMemory.StateService memoryState.sessions.clear() memoryState.messages.clear() }), project: Effect.void, session: (input) => - Effect.sync(() => { + Effect.gen(function* () { + const memoryState = yield* SessionStorageMemory.StateService memoryState.sessions.set(input.id, makeSessionRow(input)) }), userMessage: (input) => - Effect.sync(() => { - appendMemoryMessage(makeUserMessage(input)) + Effect.gen(function* () { + yield* appendMemoryMessage(makeUserMessage(input)) }), compaction: (input) => - Effect.sync(() => { - appendMemoryMessage(makeCompaction(input)) + Effect.gen(function* () { + yield* appendMemoryMessage(makeCompaction(input)) }), } -sessionStorageContract("SessionStorageMemory", SessionStorageMemory.layer(memoryState), memorySeeds) +sessionStorageContract("SessionStorageMemory", SessionStorageMemory.layer, memorySeeds) function seedProject() { Database.use((db) => @@ -323,7 +324,10 @@ function seedMessage( } function appendMemoryMessage(message: SessionMessage.Message) { - const current = memoryState.messages.get(sessionA) ?? [] - current.push(message) - memoryState.messages.set(sessionA, current) + return Effect.gen(function* () { + const memoryState = yield* SessionStorageMemory.StateService + const current = memoryState.messages.get(sessionA) ?? [] + current.push(message) + memoryState.messages.set(sessionA, current) + }) }