Просмотр исходного кода

fix(workspace): claim detached sessions to source project (#26413)

Kit Langton 4 месяцев назад
Родитель
Сommit
21d055be19

+ 1 - 2
packages/opencode/src/control-plane/workspace.ts

@@ -5,7 +5,6 @@ import { asc } from "drizzle-orm"
 import { eq } from "drizzle-orm"
 import { inArray } from "drizzle-orm"
 import { Project } from "@/project/project"
-import { Instance } from "@/project/instance"
 import { BusEvent } from "@/bus/bus-event"
 import { GlobalBus } from "@/bus/global"
 import { Auth } from "@/auth"
@@ -646,7 +645,7 @@ export const layer = Layer.effect(
 
             // "claim" this session so any future events coming from
             // the old workspace are ignored
-            SyncEvent.claim(input.sessionID, input.workspaceID ?? Instance.project.id)
+            SyncEvent.claim(input.sessionID, input.workspaceID ?? previous.projectID)
           }
         }
 

+ 35 - 0
packages/opencode/test/control-plane/workspace.test.ts

@@ -848,6 +848,41 @@ describe("workspace CRUD", () => {
     })
   })
 
+  test("sessionWarp detaches to the source project when invoked from a workspace instance", async () => {
+    await withInstance(async () => {
+      const projectID = Instance.project.id
+      await using workspaceTmp = await tmpdir({ git: true })
+      const previousType = unique("warp-detach-workspace-instance")
+      const previous = workspaceInfo(projectID, previousType)
+      insertWorkspace(previous)
+      registerAdapter(projectID, previousType, localAdapter(workspaceTmp.path, { createDir: false }).adapter)
+      const session = await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({})))
+      attachSessionToWorkspace(session.id, previous.id)
+
+      const workspaceProjectID = await WithInstance.provide({
+        directory: workspaceTmp.path,
+        fn: async () => {
+          const id = Instance.project.id
+          expect(id).not.toBe(projectID)
+          await warpWorkspaceSession({ workspaceID: null, sessionID: session.id })
+          return id
+        },
+      })
+
+      expect(
+        Database.use((db) =>
+          db
+            .select({ workspaceID: SessionTable.workspace_id })
+            .from(SessionTable)
+            .where(eq(SessionTable.id, session.id))
+            .get(),
+        )?.workspaceID,
+      ).toBeNull()
+      expect(sessionSequenceOwner(session.id)).toBe(projectID)
+      expect(sessionSequenceOwner(session.id)).not.toBe(workspaceProjectID)
+    })
+  })
+
   it.live("sessionWarp syncs previous remote history, replays it, steals, and claims the sequence", () => {
     const calls: FetchCall[] = []
     let historySessionID: SessionID | undefined