fix(opencode): preserve v1 database compatibility (#42444)
This commit is contained in:
@@ -12,7 +12,6 @@ import { SessionMessage } from "./message"
|
||||
import { SessionMessageUpdater } from "./message-updater"
|
||||
import { SessionInput } from "./input"
|
||||
import { WorkspaceV2 } from "../workspace"
|
||||
import { SessionContextEpoch } from "./context-epoch"
|
||||
import { MessageTable, PartTable, SessionInputTable, SessionMessageTable, SessionTable } from "./sql"
|
||||
import type { DeepMutable } from "../schema"
|
||||
|
||||
@@ -253,7 +252,6 @@ const layer = Layer.effectDiscard(
|
||||
.where(eq(SessionTable.id, event.data.sessionID))
|
||||
.run()
|
||||
.pipe(Effect.orDie)
|
||||
yield* SessionContextEpoch.reset(db, event.data.sessionID)
|
||||
}),
|
||||
)
|
||||
yield* events.project(SessionV1.Event.Deleted, (event) =>
|
||||
@@ -449,7 +447,6 @@ const layer = Layer.effectDiscard(
|
||||
.where(eq(SessionTable.id, event.data.sessionID))
|
||||
.run()
|
||||
.pipe(Effect.orDie)
|
||||
yield* SessionContextEpoch.reset(db, event.data.sessionID)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { DateTime, Effect, Schema } from "effect"
|
||||
import { asc, eq } from "drizzle-orm"
|
||||
import { asc, eq, sql } from "drizzle-orm"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
@@ -22,6 +22,7 @@ import { SessionInput } from "@opencode-ai/core/session/input"
|
||||
import { SessionInputTable, SessionMessageTable, SessionTable } from "@opencode-ai/core/session/sql"
|
||||
import { testEffect } from "./lib/effect"
|
||||
import { Snapshot } from "@opencode-ai/core/snapshot"
|
||||
import { Location } from "@opencode-ai/core/location"
|
||||
|
||||
const it = testEffect(AppNodeBuilder.build(LayerNode.group([Database.node, EventV2.node, SessionProjector.node])))
|
||||
const sessionsLayer = AppNodeBuilder.build(SessionV2.node, [[SessionExecution.node, SessionExecution.noopLayer]])
|
||||
@@ -44,6 +45,39 @@ const assistantRow = (
|
||||
}
|
||||
|
||||
describe("SessionProjector", () => {
|
||||
it.effect("projects moved sessions without the transitional context epoch table", () =>
|
||||
Effect.gen(function* () {
|
||||
const { db } = yield* Database.Service
|
||||
const events = yield* EventV2.Service
|
||||
yield* db
|
||||
.insert(ProjectTable)
|
||||
.values({ id: Project.ID.global, worktree: AbsolutePath.make("/project"), sandboxes: [] })
|
||||
.run()
|
||||
yield* db
|
||||
.insert(SessionTable)
|
||||
.values({
|
||||
id: sessionID,
|
||||
project_id: Project.ID.global,
|
||||
slug: "test",
|
||||
directory: "/project",
|
||||
title: "test",
|
||||
version: "test",
|
||||
})
|
||||
.run()
|
||||
yield* db.run(sql`DROP TABLE session_context_epoch`)
|
||||
|
||||
yield* events.publish(SessionEvent.Moved, {
|
||||
sessionID,
|
||||
timestamp: DateTime.makeUnsafe(1),
|
||||
location: Location.Ref.make({ directory: AbsolutePath.make("/project/subdir") }),
|
||||
})
|
||||
|
||||
expect(yield* db.select({ directory: SessionTable.directory }).from(SessionTable).get()).toEqual({
|
||||
directory: "/project/subdir",
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("projects staged, cleared, and committed reverts", () =>
|
||||
Effect.gen(function* () {
|
||||
const db = (yield* Database.Service).db
|
||||
|
||||
@@ -703,13 +703,6 @@ describe("SessionRunnerLLM", () => {
|
||||
timestamp: DateTime.makeUnsafe(1),
|
||||
location: Location.Ref.make({ directory: AbsolutePath.make("/moved") }),
|
||||
})
|
||||
expect(
|
||||
yield* db
|
||||
.select()
|
||||
.from(SessionContextEpochTable)
|
||||
.where(eq(SessionContextEpochTable.session_id, sessionID))
|
||||
.get(),
|
||||
).toBeUndefined()
|
||||
|
||||
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
||||
|
||||
@@ -714,6 +714,7 @@ const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const list = Effect.fn("Workspace.list")(function* (project: Project.Info) {
|
||||
if (!flags.experimentalWorkspaces) return []
|
||||
return (yield* db
|
||||
.select()
|
||||
.from(WorkspaceTable)
|
||||
@@ -851,6 +852,7 @@ const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const startWorkspaceSyncing = Effect.fn("Workspace.startWorkspaceSyncing")(function* (projectID: ProjectV2.ID) {
|
||||
if (!flags.experimentalWorkspaces) return
|
||||
const rows = yield* db
|
||||
.selectDistinct({ workspace: WorkspaceTable })
|
||||
.from(WorkspaceTable)
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Effect, Exit, Fiber, Layer, Schema } from "effect"
|
||||
import { HttpServer, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
|
||||
import { eq } from "drizzle-orm"
|
||||
import { GlobalBus, type GlobalEvent } from "@/bus/global"
|
||||
import { Project } from "@/project/project"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { ProjectV2 } from "@opencode-ai/core/project"
|
||||
import { ProjectTable } from "@opencode-ai/core/project/sql"
|
||||
@@ -133,6 +134,9 @@ const startWorkspaceSyncingWithFlag = (projectID: ProjectV2.ID, experimentalWork
|
||||
Workspace.use.startWorkspaceSyncing(projectID).pipe(Effect.provide(workspaceLayer(experimentalWorkspaces))),
|
||||
)
|
||||
|
||||
const listWithFlag = (project: Project.Info, experimentalWorkspaces: boolean) =>
|
||||
Effect.runPromise(Workspace.use.list(project).pipe(Effect.provide(workspaceLayer(experimentalWorkspaces))))
|
||||
|
||||
function captureGlobalEvents() {
|
||||
const events: GlobalEvent[] = []
|
||||
const handler = (event: GlobalEvent) => events.push(event)
|
||||
@@ -417,6 +421,18 @@ describe("workspace CRUD", () => {
|
||||
{ git: true },
|
||||
)
|
||||
|
||||
it.instance(
|
||||
"list is disabled by the experimental workspace flag",
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const instance = yield* requireInstance
|
||||
yield* insertWorkspace(workspaceInfo(instance.project.id, "manual"))
|
||||
|
||||
expect(yield* Effect.promise(() => listWithFlag(instance.project, false))).toEqual([])
|
||||
}),
|
||||
{ git: true },
|
||||
)
|
||||
|
||||
it.instance(
|
||||
"create configures, persists, creates, starts local sync, and passes environment",
|
||||
() =>
|
||||
|
||||
Reference in New Issue
Block a user