From cd004cf0b28aa49344da2d5947a78703d30bcaf1 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:18:13 -0400 Subject: [PATCH 01/10] refactor(session): eliminate Effect.promise roundtrips for sync MessageV2.stream (#21973) --- packages/opencode/src/session/index.ts | 19 ++++++++++++++++++- packages/opencode/src/session/prompt.ts | 25 +++++++++---------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index d28a1988d7..55532a7946 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -29,7 +29,7 @@ import type { Provider } from "@/provider/provider" import { Permission } from "@/permission" import { Global } from "@/global" import type { LanguageModelV2Usage } from "@ai-sdk/provider" -import { Effect, Layer, Context } from "effect" +import { Effect, Layer, Option, Context } from "effect" import { makeRuntime } from "@/effect/run-service" export namespace Session { @@ -352,6 +352,11 @@ export namespace Session { field: string delta: string }) => Effect.Effect + /** Finds the first message matching the predicate, searching newest-first. */ + readonly findMessage: ( + sessionID: SessionID, + predicate: (msg: MessageV2.WithParts) => boolean, + ) => Effect.Effect> } export class Service extends Context.Service()("@opencode/Session") {} @@ -636,6 +641,17 @@ export namespace Session { yield* bus.publish(MessageV2.Event.PartDelta, input) }) + /** Finds the first message matching the predicate, searching newest-first. */ + const findMessage = Effect.fn("Session.findMessage")(function* ( + sessionID: SessionID, + predicate: (msg: MessageV2.WithParts) => boolean, + ) { + for (const item of MessageV2.stream(sessionID)) { + if (predicate(item)) return Option.some(item) + } + return Option.none() + }) + return Service.of({ create, fork, @@ -657,6 +673,7 @@ export namespace Session { updatePart, getPart, updatePartDelta, + findMessage, }) }), ) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index de26e03286..2b092fc8fe 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -902,12 +902,8 @@ NOTE: At any point in time through this workflow you should feel free to ask the }) const lastModel = Effect.fnUntraced(function* (sessionID: SessionID) { - const model = yield* Effect.promise(async () => { - for await (const item of MessageV2.stream(sessionID)) { - if (item.info.role === "user" && item.info.model) return item.info.model - } - }) - if (model) return model + const match = yield* sessions.findMessage(sessionID, (m) => m.info.role === "user" && !!m.info.model) + if (Option.isSome(match) && match.value.info.role === "user") return match.value.info.model return yield* provider.defaultModel() }) @@ -1290,16 +1286,13 @@ NOTE: At any point in time through this workflow you should feel free to ask the }, ) - const lastAssistant = (sessionID: SessionID) => - Effect.promise(async () => { - let latest: MessageV2.WithParts | undefined - for await (const item of MessageV2.stream(sessionID)) { - latest ??= item - if (item.info.role !== "user") return item - } - if (latest) return latest - throw new Error("Impossible") - }) + const lastAssistant = Effect.fnUntraced(function* (sessionID: SessionID) { + const match = yield* sessions.findMessage(sessionID, (m) => m.info.role !== "user") + if (Option.isSome(match)) return match.value + const msgs = yield* sessions.messages({ sessionID, limit: 1 }) + if (msgs.length > 0) return msgs[0] + throw new Error("Impossible") + }) const runLoop: (sessionID: SessionID) => Effect.Effect = Effect.fn("SessionPrompt.run")( function* (sessionID: SessionID) { From 4341ab838e3494b5d640780b1c59d6305aa59e95 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:18:30 -0400 Subject: [PATCH 02/10] refactor(tool): use Session.Service directly in TaskTool (#21975) --- packages/opencode/src/tool/task.ts | 68 +++++++++++++++--------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index d0eaaf6f2a..4e176391c3 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -36,6 +36,7 @@ export const TaskTool = Tool.define( Effect.gen(function* () { const agent = yield* Agent.Service const config = yield* Config.Service + const sessions = yield* Session.Service const run = Effect.fn("TaskTool.execute")(function* (params: z.infer, ctx: Tool.Context) { const cfg = yield* config.get() @@ -62,44 +63,41 @@ export const TaskTool = Tool.define( const taskID = params.task_id const session = taskID - ? yield* Effect.promise(() => { - const id = SessionID.make(taskID) - return Session.get(id).catch(() => undefined) - }) + ? yield* sessions.get(SessionID.make(taskID)).pipe( + Effect.catchCause(() => Effect.succeed(undefined)), + ) : undefined const nextSession = session ?? - (yield* Effect.promise(() => - Session.create({ - parentID: ctx.sessionID, - title: params.description + ` (@${next.name} subagent)`, - permission: [ - ...(canTodo - ? [] - : [ - { - permission: "todowrite" as const, - pattern: "*" as const, - action: "deny" as const, - }, - ]), - ...(canTask - ? [] - : [ - { - permission: id, - pattern: "*" as const, - action: "deny" as const, - }, - ]), - ...(cfg.experimental?.primary_tools?.map((item) => ({ - pattern: "*", - action: "allow" as const, - permission: item, - })) ?? []), - ], - }), - )) + (yield* sessions.create({ + parentID: ctx.sessionID, + title: params.description + ` (@${next.name} subagent)`, + permission: [ + ...(canTodo + ? [] + : [ + { + permission: "todowrite" as const, + pattern: "*" as const, + action: "deny" as const, + }, + ]), + ...(canTask + ? [] + : [ + { + permission: id, + pattern: "*" as const, + action: "deny" as const, + }, + ]), + ...(cfg.experimental?.primary_tools?.map((item) => ({ + pattern: "*", + action: "allow" as const, + permission: item, + })) ?? []), + ], + })) const msg = yield* Effect.sync(() => MessageV2.get({ sessionID: ctx.sessionID, messageID: ctx.messageID })) if (msg.info.role !== "assistant") return yield* Effect.fail(new Error("Not an assistant message")) From f38f415bf0af3fb8baf211b83996d3a58a1fd010 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:18:54 -0400 Subject: [PATCH 03/10] refactor: collapse Format facade (#21980) --- packages/opencode/src/format/index.ts | 15 --------------- packages/opencode/src/project/bootstrap.ts | 2 +- packages/opencode/src/server/instance.ts | 3 ++- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts index 36844d3510..1aeb2e51a4 100644 --- a/packages/opencode/src/format/index.ts +++ b/packages/opencode/src/format/index.ts @@ -2,7 +2,6 @@ import { Effect, Layer, Context } from "effect" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner" import { InstanceState } from "@/effect/instance-state" -import { makeRuntime } from "@/effect/run-service" import path from "path" import { mergeDeep } from "remeda" import z from "zod" @@ -193,18 +192,4 @@ export namespace Format { Layer.provide(Config.defaultLayer), Layer.provide(CrossSpawnSpawner.defaultLayer), ) - - const { runPromise } = makeRuntime(Service, defaultLayer) - - export async function init() { - return runPromise((s) => s.init()) - } - - export async function status() { - return runPromise((s) => s.status()) - } - - export async function file(filepath: string) { - return runPromise((s) => s.file(filepath)) - } } diff --git a/packages/opencode/src/project/bootstrap.ts b/packages/opencode/src/project/bootstrap.ts index 9ddcca5569..1340a692ff 100644 --- a/packages/opencode/src/project/bootstrap.ts +++ b/packages/opencode/src/project/bootstrap.ts @@ -17,7 +17,7 @@ export async function InstanceBootstrap() { Log.Default.info("bootstrapping", { directory: Instance.directory }) await Plugin.init() void AppRuntime.runPromise(ShareNext.Service.use((svc) => svc.init())) - Format.init() + void AppRuntime.runPromise(Format.Service.use((svc) => svc.init())) await LSP.init() File.init() FileWatcher.init() diff --git a/packages/opencode/src/server/instance.ts b/packages/opencode/src/server/instance.ts index 4bd7802e2a..015d67bfc1 100644 --- a/packages/opencode/src/server/instance.ts +++ b/packages/opencode/src/server/instance.ts @@ -30,6 +30,7 @@ import { ProviderRoutes } from "./routes/provider" import { EventRoutes } from "./routes/event" import { errorHandler } from "./middleware" import { getMimeType } from "hono/utils/mime" +import { AppRuntime } from "@/effect/app-runtime" const log = Log.create({ service: "server" }) @@ -277,7 +278,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket, app: Hono = new Hono() }, }), async (c) => { - return c.json(await Format.status()) + return c.json(await AppRuntime.runPromise(Format.Service.use((svc) => svc.status()))) }, ) .all("/*", async (c) => { From 2868000c2030a2b6474947778265c6b008f2c536 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Sat, 11 Apr 2026 03:19:50 +0000 Subject: [PATCH 04/10] chore: generate --- packages/opencode/src/tool/task.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 4e176391c3..ce99ab2992 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -63,9 +63,7 @@ export const TaskTool = Tool.define( const taskID = params.task_id const session = taskID - ? yield* sessions.get(SessionID.make(taskID)).pipe( - Effect.catchCause(() => Effect.succeed(undefined)), - ) + ? yield* sessions.get(SessionID.make(taskID)).pipe(Effect.catchCause(() => Effect.succeed(undefined))) : undefined const nextSession = session ?? From 87e23abb10625bae4194406545e41beebb1b5a06 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:25:43 -0400 Subject: [PATCH 05/10] refactor: remove ProviderAuth facade (#21983) --- packages/opencode/src/provider/auth.ts | 19 ------------ .../opencode/src/server/routes/provider.ts | 31 ++++++++++++------- .../test/plugin/auth-override.test.ts | 9 ++++-- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/packages/opencode/src/provider/auth.ts b/packages/opencode/src/provider/auth.ts index 3823baf135..e410b86365 100644 --- a/packages/opencode/src/provider/auth.ts +++ b/packages/opencode/src/provider/auth.ts @@ -2,7 +2,6 @@ import type { AuthOAuthResult, Hooks } from "@opencode-ai/plugin" import { NamedError } from "@opencode-ai/util/error" import { Auth } from "@/auth" import { InstanceState } from "@/effect/instance-state" -import { makeRuntime } from "@/effect/run-service" import { Plugin } from "../plugin" import { ProviderID } from "./schema" import { Array as Arr, Effect, Layer, Record, Result, Context } from "effect" @@ -232,22 +231,4 @@ export namespace ProviderAuth { export const defaultLayer = Layer.suspend(() => layer.pipe(Layer.provide(Auth.defaultLayer), Layer.provide(Plugin.defaultLayer)), ) - - const { runPromise } = makeRuntime(Service, defaultLayer) - - export async function methods() { - return runPromise((svc) => svc.methods()) - } - - export async function authorize(input: { - providerID: ProviderID - method: number - inputs?: Record - }): Promise { - return runPromise((svc) => svc.authorize(input)) - } - - export async function callback(input: { providerID: ProviderID; method: number; code?: string }) { - return runPromise((svc) => svc.callback(input)) - } } diff --git a/packages/opencode/src/server/routes/provider.ts b/packages/opencode/src/server/routes/provider.ts index 59a4a686b2..efd126ea0f 100644 --- a/packages/opencode/src/server/routes/provider.ts +++ b/packages/opencode/src/server/routes/provider.ts @@ -6,6 +6,7 @@ import { Provider } from "../../provider/provider" import { ModelsDev } from "../../provider/models" import { ProviderAuth } from "../../provider/auth" import { ProviderID } from "../../provider/schema" +import { AppRuntime } from "../../effect/app-runtime" import { mapValues } from "remeda" import { errors } from "../error" import { lazy } from "../../util/lazy" @@ -81,7 +82,7 @@ export const ProviderRoutes = lazy(() => }, }), async (c) => { - return c.json(await ProviderAuth.methods()) + return c.json(await AppRuntime.runPromise(ProviderAuth.Service.use((svc) => svc.methods()))) }, ) .post( @@ -118,11 +119,15 @@ export const ProviderRoutes = lazy(() => async (c) => { const providerID = c.req.valid("param").providerID const { method, inputs } = c.req.valid("json") - const result = await ProviderAuth.authorize({ - providerID, - method, - inputs, - }) + const result = await AppRuntime.runPromise( + ProviderAuth.Service.use((svc) => + svc.authorize({ + providerID, + method, + inputs, + }), + ), + ) return c.json(result) }, ) @@ -160,11 +165,15 @@ export const ProviderRoutes = lazy(() => async (c) => { const providerID = c.req.valid("param").providerID const { method, code } = c.req.valid("json") - await ProviderAuth.callback({ - providerID, - method, - code, - }) + await AppRuntime.runPromise( + ProviderAuth.Service.use((svc) => + svc.callback({ + providerID, + method, + code, + }), + ), + ) return c.json(true) }, ), diff --git a/packages/opencode/test/plugin/auth-override.test.ts b/packages/opencode/test/plugin/auth-override.test.ts index 6b77083828..36a02058ea 100644 --- a/packages/opencode/test/plugin/auth-override.test.ts +++ b/packages/opencode/test/plugin/auth-override.test.ts @@ -1,6 +1,7 @@ import { describe, expect, test } from "bun:test" import path from "path" import fs from "fs/promises" +import { Effect } from "effect" import { tmpdir } from "../fixture/fixture" import { Instance } from "../../src/project/instance" import { ProviderAuth } from "../../src/provider/auth" @@ -39,14 +40,18 @@ describe("plugin.auth-override", () => { const methods = await Instance.provide({ directory: tmp.path, fn: async () => { - return ProviderAuth.methods() + return Effect.runPromise( + ProviderAuth.Service.use((svc) => svc.methods()).pipe(Effect.provide(ProviderAuth.defaultLayer)), + ) }, }) const plainMethods = await Instance.provide({ directory: plain.path, fn: async () => { - return ProviderAuth.methods() + return Effect.runPromise( + ProviderAuth.Service.use((svc) => svc.methods()).pipe(Effect.provide(ProviderAuth.defaultLayer)), + ) }, }) From 03ce2e5288c8d2ef58e1197f6200b6be8f2797d7 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:26:16 -0400 Subject: [PATCH 06/10] refactor(installation): drop facade runtime wrappers (#21984) --- packages/opencode/src/cli/cmd/uninstall.ts | 3 +- packages/opencode/src/cli/cmd/upgrade.ts | 11 ++-- packages/opencode/src/cli/upgrade.ts | 7 +-- packages/opencode/src/installation/index.ts | 15 ------ packages/opencode/src/server/routes/global.ts | 54 ++++++++++++------- 5 files changed, 50 insertions(+), 40 deletions(-) diff --git a/packages/opencode/src/cli/cmd/uninstall.ts b/packages/opencode/src/cli/cmd/uninstall.ts index de41f32a0d..31830f0859 100644 --- a/packages/opencode/src/cli/cmd/uninstall.ts +++ b/packages/opencode/src/cli/cmd/uninstall.ts @@ -1,6 +1,7 @@ import type { Argv } from "yargs" import { UI } from "../ui" import * as prompts from "@clack/prompts" +import { AppRuntime } from "@/effect/app-runtime" import { Installation } from "../../installation" import { Global } from "../../global" import fs from "fs/promises" @@ -57,7 +58,7 @@ export const UninstallCommand = { UI.empty() prompts.intro("Uninstall OpenCode") - const method = await Installation.method() + const method = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method())) prompts.log.info(`Installation method: ${method}`) const targets = await collectRemovalTargets(args, method) diff --git a/packages/opencode/src/cli/cmd/upgrade.ts b/packages/opencode/src/cli/cmd/upgrade.ts index 0182056633..3ffa0f228c 100644 --- a/packages/opencode/src/cli/cmd/upgrade.ts +++ b/packages/opencode/src/cli/cmd/upgrade.ts @@ -1,6 +1,7 @@ import type { Argv } from "yargs" import { UI } from "../ui" import * as prompts from "@clack/prompts" +import { AppRuntime } from "@/effect/app-runtime" import { Installation } from "../../installation" export const UpgradeCommand = { @@ -24,7 +25,7 @@ export const UpgradeCommand = { UI.println(UI.logo(" ")) UI.empty() prompts.intro("Upgrade") - const detectedMethod = await Installation.method() + const detectedMethod = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method())) const method = (args.method as Installation.Method) ?? detectedMethod if (method === "unknown") { prompts.log.error(`opencode is installed to ${process.execPath} and may be managed by a package manager`) @@ -42,7 +43,9 @@ export const UpgradeCommand = { } } prompts.log.info("Using method: " + method) - const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest() + const target = args.target + ? args.target.replace(/^v/, "") + : await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest())) if (Installation.VERSION === target) { prompts.log.warn(`opencode upgrade skipped: ${target} is already installed`) @@ -53,7 +56,9 @@ export const UpgradeCommand = { prompts.log.info(`From ${Installation.VERSION} → ${target}`) const spinner = prompts.spinner() spinner.start("Upgrading...") - const err = await Installation.upgrade(method, target).catch((err) => err) + const err = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.upgrade(method, target))).catch( + (err) => err, + ) if (err) { spinner.stop("Upgrade failed", 1) if (err instanceof Installation.UpgradeFailedError) { diff --git a/packages/opencode/src/cli/upgrade.ts b/packages/opencode/src/cli/upgrade.ts index 7b7199d4ea..e902dcb921 100644 --- a/packages/opencode/src/cli/upgrade.ts +++ b/packages/opencode/src/cli/upgrade.ts @@ -1,12 +1,13 @@ import { Bus } from "@/bus" import { Config } from "@/config/config" +import { AppRuntime } from "@/effect/app-runtime" import { Flag } from "@/flag/flag" import { Installation } from "@/installation" export async function upgrade() { const config = await Config.getGlobal() - const method = await Installation.method() - const latest = await Installation.latest(method).catch(() => {}) + const method = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method())) + const latest = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest(method))).catch(() => {}) if (!latest) return if (Flag.OPENCODE_ALWAYS_NOTIFY_UPDATE) { @@ -25,7 +26,7 @@ export async function upgrade() { } if (method === "unknown") return - await Installation.upgrade(method, latest) + await AppRuntime.runPromise(Installation.Service.use((svc) => svc.upgrade(method, latest))) .then(() => Bus.publish(Installation.Event.Updated, { version: latest })) .catch(() => {}) } diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index 06b673217f..29f9bf1be2 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -1,7 +1,6 @@ import { Effect, Layer, Schema, Context, Stream } from "effect" import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http" import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner" -import { makeRuntime } from "@/effect/run-service" import { withTransientReadRetry } from "@/util/effect-http-client" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import path from "path" @@ -338,18 +337,4 @@ export namespace Installation { Layer.provide(FetchHttpClient.layer), Layer.provide(CrossSpawnSpawner.defaultLayer), ) - - const { runPromise } = makeRuntime(Service, defaultLayer) - - export async function method(): Promise { - return runPromise((svc) => svc.method()) - } - - export async function latest(installMethod?: Method): Promise { - return runPromise((svc) => svc.latest(installMethod)) - } - - export async function upgrade(m: Method, target: string): Promise { - return runPromise((svc) => svc.upgrade(m, target)) - } } diff --git a/packages/opencode/src/server/routes/global.ts b/packages/opencode/src/server/routes/global.ts index ec7afcf23d..6b0a9a164b 100644 --- a/packages/opencode/src/server/routes/global.ts +++ b/packages/opencode/src/server/routes/global.ts @@ -1,10 +1,12 @@ import { Hono, type Context } from "hono" import { describeRoute, resolver, validator } from "hono-openapi" import { streamSSE } from "hono/streaming" +import { Effect } from "effect" import z from "zod" import { BusEvent } from "@/bus/bus-event" import { SyncEvent } from "@/sync" import { GlobalBus } from "@/bus/global" +import { AppRuntime } from "@/effect/app-runtime" import { AsyncQueue } from "@/util/queue" import { Instance } from "../../project/instance" import { Installation } from "@/installation" @@ -290,25 +292,41 @@ export const GlobalRoutes = lazy(() => }), ), async (c) => { - const method = await Installation.method() - if (method === "unknown") { - return c.json({ success: false, error: "Unknown installation method" }, 400) + const result = await AppRuntime.runPromise( + Installation.Service.use((svc) => + Effect.gen(function* () { + const method = yield* svc.method() + if (method === "unknown") { + return { success: false as const, status: 400 as const, error: "Unknown installation method" } + } + + const target = c.req.valid("json").target || (yield* svc.latest(method)) + const result = yield* Effect.catch( + svc.upgrade(method, target).pipe(Effect.as({ success: true as const, version: target })), + (err) => + Effect.succeed({ + success: false as const, + status: 500 as const, + error: err instanceof Error ? err.message : String(err), + }), + ) + if (!result.success) return result + return { ...result, status: 200 as const } + }), + ), + ) + if (!result.success) { + return c.json({ success: false, error: result.error }, result.status) } - const target = c.req.valid("json").target || (await Installation.latest(method)) - const result = await Installation.upgrade(method, target) - .then(() => ({ success: true as const, version: target })) - .catch((e) => ({ success: false as const, error: e instanceof Error ? e.message : String(e) })) - if (result.success) { - GlobalBus.emit("event", { - directory: "global", - payload: { - type: Installation.Event.Updated.type, - properties: { version: target }, - }, - }) - return c.json(result) - } - return c.json(result, 500) + const target = result.version + GlobalBus.emit("event", { + directory: "global", + payload: { + type: Installation.Event.Updated.type, + properties: { version: target }, + }, + }) + return c.json({ success: true, version: target }) }, ), ) From ba3600a5156c382c3fde73ec029b26f318b7391d Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:27:30 -0400 Subject: [PATCH 07/10] refactor(session): remove dead updatePartDelta facade (#21985) --- packages/opencode/src/session/index.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 55532a7946..2375d8333d 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -851,14 +851,4 @@ export namespace Session { return runPromise((svc) => svc.updatePart(part)) } - export const updatePartDelta = fn( - z.object({ - sessionID: SessionID.zod, - messageID: MessageID.zod, - partID: PartID.zod, - field: z.string(), - delta: z.string(), - }), - (input) => runPromise((svc) => svc.updatePartDelta(input)), - ) } From 3b523b32f5c88141ba50a76e4e6ccab22cee8e5c Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Sat, 11 Apr 2026 03:28:30 +0000 Subject: [PATCH 08/10] chore: generate --- packages/opencode/src/session/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 2375d8333d..d7bf99637a 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -850,5 +850,4 @@ export namespace Session { MessageV2.Part.parse(part) return runPromise((svc) => svc.updatePart(part)) } - } From 9ca06e033605d3670f1e61b5f31ff0a975f569dc Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 23:35:50 -0400 Subject: [PATCH 09/10] docs(effect): mark SessionTodo migrated (#21987) --- packages/opencode/specs/effect-migration.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opencode/specs/effect-migration.md b/packages/opencode/specs/effect-migration.md index 8ada3f7389..b0ce4a3ee1 100644 --- a/packages/opencode/specs/effect-migration.md +++ b/packages/opencode/specs/effect-migration.md @@ -223,7 +223,7 @@ Fully migrated (single namespace, InstanceState where needed, flattened facade): Still open: -- [ ] `SessionTodo` — `session/todo.ts` +- [x] `SessionTodo` — `session/todo.ts` - [ ] `SyncEvent` — `sync/index.ts` - [ ] `Workspace` — `control-plane/workspace.ts` @@ -338,4 +338,5 @@ For each service, the migration is roughly: - `SessionStatus` — migrated 2026-04-11. Replaced the last route and retry-policy callers with `AppRuntime.runPromise(SessionStatus.Service.use(...))` and removed the `makeRuntime(...)` facade. - `ShareNext` — migrated 2026-04-11. Swapped remaining async callers to `AppRuntime.runPromise(ShareNext.Service.use(...))`, removed the `makeRuntime(...)` facade, and kept instance bootstrap on the shared app runtime. +- `SessionTodo` — migrated 2026-04-10. Already matched the target service shape in `session/todo.ts`: single namespace, traced Effect methods, and no `makeRuntime(...)` facade remained; checklist updated to reflect the completed migration. - `Storage` — migrated 2026-04-10. One production caller (`Session.diff`) and all storage.test.ts tests converted to effectful style. Facades and `makeRuntime` removed. From c92c462148a48a9e9496735f7754a69e4a695b31 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Sat, 11 Apr 2026 03:39:49 +0000 Subject: [PATCH 10/10] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index d827b203d2..13809499e9 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-285KZ7rZLRoc6XqCZRHc25NE+mmpGh/BVeMpv8aPQtQ=", - "aarch64-linux": "sha256-qIwmY4TP4CI7R7G6A5OMYRrorVNXjkg25tTtVpIHm2o=", - "aarch64-darwin": "sha256-RwvnZQhdYZ0u7h7evyfxuPLHHX9eO/jXTAxIFc8B+IE=", - "x86_64-darwin": "sha256-vVj40al+TEeMpbe5XG2GmJEpN+eQAvtr9W0T98l5PBE=" + "x86_64-linux": "sha256-LkmY8hoc1OkJWnTxberdbo2wKlMTmq1NlyOndHSoR1Y=", + "aarch64-linux": "sha256-TOojgsW0rpYiSuDCV/ZmAuewmkYitB6GBmxus3pXpNo=", + "aarch64-darwin": "sha256-Vf+XYCm3YQQ5HBUK7UDXvEKEDeFUMwlGXQsmzrK+a1E=", + "x86_64-darwin": "sha256-68OlpJhmf5tpapxYGhcYjhx9716X+BFoIHTGosA3Yg4=" } }