/** * Regression test for the same bug class as #26574 (sibling of #26566 and * #26553). The Desktop app calls GET /session//diff; before #26574 * the response was Schema-encoded against `Snapshot.FileDiff` with * `patch: Schema.String` (required), so any session whose stored * `summary_diffs` had a row without `patch` returned HTTP 400 and the * session never loaded. * * This test inserts a session row with a missing-patch diff entry and * asserts that GET /session//diff returns 200 with the row intact. */ import { afterEach, describe, expect } from "bun:test" import { Effect } from "effect" import { Server } from "@/server/server" import { SessionPaths } from "@/server/routes/instance/httpapi/groups/session" import { Session } from "@/session/session" import { Storage } from "@/storage/storage" import { WithInstance } from "@/project/with-instance" import { resetDatabase } from "../fixture/db" import { disposeAllInstances, tmpdir } from "../fixture/fixture" import { it } from "../lib/effect" import * as Log from "@opencode-ai/core/util/log" void Log.init({ print: false }) afterEach(async () => { await disposeAllInstances() await resetDatabase() }) function pathFor(template: string, params: Record) { return Object.entries(params).reduce((result, [key, value]) => result.replace(`:${key}`, value), template) } describe("session diff with missing patch (#26574)", () => { it.live("GET /session//diff returns 200 when summary_diffs row has no patch", () => Effect.gen(function* () { const tmp = yield* Effect.acquireRelease( Effect.promise(() => tmpdir({ git: true, config: { formatter: false, lsp: false } })), (t) => Effect.promise(() => t[Symbol.asyncDispose]()), ) yield* Effect.promise(() => WithInstance.provide({ directory: tmp.path, fn: async () => { const session = await Effect.runPromise( Effect.provide( Session.Service.use((s) => s.create({ title: "missing-patch" })), Session.defaultLayer, ), ) // Mimic legacy/imported on-disk shape: a diff entry with no // `patch` text. Pre-fix the typed response encoder rejects // this and returns 400. await Effect.runPromise( Effect.provide( Storage.Service.use((s) => s.write(["session_diff", session.id], [{ file: "legacy.txt", additions: 1, deletions: 0 }]), ), Storage.defaultLayer, ), ) const headers = { "x-opencode-directory": tmp.path } const response = await Server.Default().app.request(pathFor(SessionPaths.diff, { sessionID: session.id }), { headers, }) expect(response.status).toBe(200) const body = (await response.json()) as Array<{ file: string; patch?: string; additions: number }> expect(body).toHaveLength(1) expect(body[0]?.file).toBe("legacy.txt") expect(body[0]?.additions).toBe(1) expect(body[0]?.patch).toBeUndefined() }, }), ) }), ) })