feat(core): session warping (#25768)

This commit is contained in:
James Long
2026-05-04 21:28:38 -04:00
committed by GitHub
parent 84afd2bef8
commit 22a4a9df8b
25 changed files with 4032 additions and 1095 deletions

View File

@@ -1,4 +1,5 @@
import { NonNegativeInt } from "@/util/schema"
import { SessionID } from "@/session/schema"
import { Schema } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { Authorization } from "../middleware/authorization"
@@ -21,6 +22,9 @@ export const ReplayPayload = Schema.Struct({
export const ReplayResponse = Schema.Struct({
sessionID: Schema.String,
})
export const SessionPayload = Schema.Struct({
sessionID: SessionID,
})
export const HistoryPayload = Schema.Record(Schema.String, NonNegativeInt)
export const HistoryEvent = Schema.Struct({
id: Schema.String,
@@ -33,6 +37,7 @@ export const HistoryEvent = Schema.Struct({
export const SyncPaths = {
start: `${root}/start`,
replay: `${root}/replay`,
steal: `${root}/steal`,
history: `${root}/history`,
} as const
@@ -60,6 +65,17 @@ export const SyncApi = HttpApi.make("sync")
description: "Validate and replay a complete sync event history.",
}),
),
HttpApiEndpoint.post("steal", SyncPaths.steal, {
payload: SessionPayload,
success: described(SessionPayload, "Session stolen into workspace"),
error: HttpApiError.BadRequest,
}).annotateMerge(
OpenApi.annotations({
identifier: "sync.steal",
summary: "Steal session into workspace",
description: "Update a session to belong to the current workspace through the sync event system.",
}),
),
HttpApiEndpoint.post("history", SyncPaths.history, {
payload: HistoryPayload,
success: described(Schema.Array(HistoryEvent), "Sync events"),

View File

@@ -1,21 +1,17 @@
import { Workspace } from "@/control-plane/workspace"
import { WorkspaceAdapterEntry } from "@/control-plane/types"
import { NonNegativeInt } from "@/util/schema"
import { Schema, Struct } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
import { Authorization } from "../middleware/authorization"
import { InstanceContextMiddleware } from "../middleware/instance-context"
import { WorkspaceRoutingMiddleware } from "../middleware/workspace-routing"
import { described } from "./metadata"
const root = "/experimental/workspace"
export const CreatePayload = Schema.Struct({
...Struct.omit(Workspace.CreateInput.fields, ["projectID", "extra"]),
extra: Schema.optional(Workspace.CreateInput.fields.extra),
})
export const SessionRestorePayload = Schema.Struct(Struct.omit(Workspace.SessionRestoreInput.fields, ["workspaceID"]))
export const SessionRestoreResponse = Schema.Struct({
total: NonNegativeInt,
export const CreatePayload = Schema.Struct(Struct.omit(Workspace.CreateInput.fields, ["projectID"]))
export const WarpPayload = Schema.Struct({
id: Schema.NullOr(Workspace.Info.fields.id),
sessionID: Workspace.SessionWarpInput.fields.sessionID,
})
export const WorkspacePaths = {
@@ -23,7 +19,7 @@ export const WorkspacePaths = {
list: root,
status: `${root}/status`,
remove: `${root}/:id`,
sessionRestore: `${root}/:id/session-restore`,
warp: `${root}/warp`,
} as const
export const WorkspaceApi = HttpApi.make("workspace")
@@ -79,16 +75,15 @@ export const WorkspaceApi = HttpApi.make("workspace")
description: "Remove an existing workspace.",
}),
),
HttpApiEndpoint.post("sessionRestore", WorkspacePaths.sessionRestore, {
params: { id: Workspace.Info.fields.id },
payload: SessionRestorePayload,
success: described(SessionRestoreResponse, "Session replay started"),
HttpApiEndpoint.post("warp", WorkspacePaths.warp, {
payload: WarpPayload,
success: described(HttpApiSchema.NoContent, "Session warped"),
error: HttpApiError.BadRequest,
}).annotateMerge(
OpenApi.annotations({
identifier: "experimental.workspace.sessionRestore",
summary: "Restore session into workspace",
description: "Replay a session's sync events into the target workspace in batches.",
identifier: "experimental.workspace.warp",
summary: "Warp session into workspace",
description: "Move a session's sync history into the target workspace, or detach it to the local project.",
}),
),
)