From 6dd71aaa38ec0eb1f04add42c782fb1155df625b Mon Sep 17 00:00:00 2001 From: Abdullah1738 Date: Wed, 7 Oct 2026 12:43:26 +0400 Subject: [PATCH] perf(server): OpenCode 2 stops writing unchanged session status updates --- .../Adapters/OpenCode2AdapterV2.test.ts | 64 +++++++++++++++++++ .../src/server/v2/adapter.ts | 3 + 2 files changed, 67 insertions(+) diff --git a/apps/server/src/orchestration-v2/Adapters/OpenCode2AdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/OpenCode2AdapterV2.test.ts index 548ff5cb6643..25b8d1cfb740 100644 --- a/apps/server/src/orchestration-v2/Adapters/OpenCode2AdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/OpenCode2AdapterV2.test.ts @@ -3922,6 +3922,70 @@ it.layer(McpProviderSessions.layer)("OpenCode2 adapter", (it) => { }).pipe(Effect.scoped, Effect.provide(IdAllocator.layer)), ); + it.effect("reports the shared session's status only when it changes", () => + Effect.gen(function* () { + const OTHER = "ses_f148ca2deffeOtherSession000"; + const promptInto = ( + session: string, + recorded: string, + ): ReadonlyArray => [ + out("session.prompt", { sessionID: session, id: recorded, text: "" }), + replyData("session.prompt", { + id: recorded, + sessionID: session, + time: { created: 1790656601410 }, + type: "user", + payload: { text: "hi" }, + delivery: "steer", + }), + ]; + const { runtime, thread } = yield* resumed([ + out("session.get", { sessionID: OTHER }), + replyData("session.get", sessionInfo({ id: OTHER })), + out("permission.list", { sessionID: OTHER }), + replyData("permission.list", []), + out("session.form.list", { sessionID: OTHER }), + replyData("session.form.list", []), + ...promptInto(SESSION, "msg_recorded_turn_a"), + out("session.instructions.entry.put", { sessionID: OTHER, key: "t3-code", value: "" }), + reply("session.instructions.entry.put", null), + ...promptInto(OTHER, "msg_recorded_turn_b"), + event("session.execution.succeeded", { sessionID: SESSION }), + event("session.execution.succeeded", { sessionID: OTHER }), + ]); + const other = { + ...thread, + id: ProviderThreadId.make("provider-thread:opencode2-adapter:other"), + nativeThreadRef: { + driver: OPENCODE_PROVIDER, + nativeId: OTHER, + strength: "strong" as const, + }, + }; + yield* runtime.resumeThread({ + providerThread: other, + threadId, + modelSelection: bigPickle, + runtimePolicy: policy(), + }); + let ended = 0; + const collected = yield* runtime.events.pipe( + Stream.takeUntil((event) => event.type === "turn.terminal" && ++ended === 2), + Stream.runCollect, + Effect.forkScoped, + ); + yield* runtime.startTurn(turnInput(thread)); + yield* runtime.startTurn(turnInput(other)); + // The second turn starts and the first ends while the session stays running. + assert.deepEqual( + [...(yield* Fiber.join(collected))].flatMap((event) => + event.type === "provider_session.updated" ? [event.providerSession.status] : [], + ), + ["running", "ready"], + ); + }).pipe(Effect.scoped), + ); + it.effect.each([ ["refuses a rollback while a timed-out Stop's run is still going", true], ["rolls back once a timed-out Stop's run has left the server", false], diff --git a/packages/provider-opencode/src/server/v2/adapter.ts b/packages/provider-opencode/src/server/v2/adapter.ts index 785bf1a06e70..78afb18bd7f4 100644 --- a/packages/provider-opencode/src/server/v2/adapter.ts +++ b/packages/provider-opencode/src/server/v2/adapter.ts @@ -1050,6 +1050,9 @@ export const make = Effect.fn("OpenCode2Adapter.make")(function* (instanceId: Pr lastError: string | null, ) => Effect.gen(function* () { + // The session is shared by every thread on this instance and is persisted + // once per attached thread, so a repeat of the same state is not worth a write. + if (session.status === status && session.lastError === lastError) return; session = { ...session, status, lastError, updatedAt: yield* DateTime.now }; yield* emit({ type: "provider_session.updated", driver, providerSession: session }); });