diff --git a/packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts b/packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts index 65c90b9529..3d88db60db 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts @@ -62,7 +62,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session", return Instance.restore(instance, () => Array.from( Session.list({ - directory: ctx.query.directory, + directory: ctx.query.scope === "project" ? undefined : ctx.query.directory, scope: ctx.query.scope, path: ctx.query.path, roots: ctx.query.roots, diff --git a/packages/opencode/test/server/httpapi-session.test.ts b/packages/opencode/test/server/httpapi-session.test.ts index 8e1987cedf..f561a13061 100644 --- a/packages/opencode/test/server/httpapi-session.test.ts +++ b/packages/opencode/test/server/httpapi-session.test.ts @@ -1,4 +1,6 @@ import { afterEach, describe, expect } from "bun:test" +import { mkdir } from "node:fs/promises" +import path from "node:path" import { Effect } from "effect" import { Flag } from "@opencode-ai/core/flag/flag" import { PermissionID } from "../../src/permission/schema" @@ -9,7 +11,10 @@ import { SessionPaths } from "../../src/server/routes/instance/httpapi/groups/se import { Session } from "@/session/session" import { MessageID, PartID, type SessionID } from "../../src/session/schema" import { MessageV2 } from "../../src/session/message-v2" +import { Database } from "@/storage/db" +import { SessionTable } from "@/session/session.sql" import * as Log from "@opencode-ai/core/util/log" +import { eq } from "drizzle-orm" import { resetDatabase } from "../fixture/db" import { tmpdir } from "../fixture/fixture" import { it } from "../lib/effect" @@ -249,6 +254,41 @@ describe("session HttpApi", () => { ), ) + it.live( + "matches legacy project-scoped path and directory precedence", + withTmp({ git: true, config: { formatter: false, lsp: false } }, (tmp) => + Effect.gen(function* () { + const currentDir = path.join(tmp.path, "packages", "opencode", "src") + yield* Effect.promise(() => mkdir(currentDir, { recursive: true })) + + const pathSession = yield* createSession(currentDir) + const pathlessSession = yield* createSession(currentDir) + yield* Effect.sync(() => + Database.use((db) => + db.update(SessionTable).set({ path: null }).where(eq(SessionTable.id, pathlessSession.id)).run(), + ), + ) + + const query = new URLSearchParams({ + scope: "project", + path: "packages/opencode/src", + directory: currentDir, + }) + const headers = { "x-opencode-directory": tmp.path } + const legacy = (yield* json( + yield* requestWithBackend(false, `${SessionPaths.list}?${query}`, { headers }), + )).map((item) => item.id) + const effect = (yield* json( + yield* requestWithBackend(true, `${SessionPaths.list}?${query}`, { headers }), + )).map((item) => item.id) + + expect(legacy).toContain(pathSession.id) + expect(legacy).not.toContain(pathlessSession.id) + expect(effect).toEqual(legacy) + }), + ), + ) + it.live( "serves message mutation routes through Hono bridge", withTmp({ git: true, config: { formatter: false, lsp: false } }, (tmp) =>