rector(core,tui): handle workspace state in project context, add workspace status, improve ui (#21896)

This commit is contained in:
James Long
2026-04-10 13:03:20 -04:00
committed by GitHub
parent bf601628db
commit 180ded6a27
22 changed files with 628 additions and 609 deletions

View File

@@ -29,13 +29,20 @@ function local(method: string, path: string) {
return false
}
async function getSessionWorkspace(url: URL) {
function getSessionID(url: URL) {
if (url.pathname === "/session/status") return null
const id = url.pathname.match(/^\/session\/([^/]+)(?:\/|$)/)?.[1]
if (!id) return null
const session = await Session.get(SessionID.make(id)).catch(() => undefined)
return SessionID.make(id)
}
async function getSessionWorkspace(url: URL) {
const id = getSessionID(url)
if (!id) return null
const session = await Session.get(id).catch(() => undefined)
return session?.workspaceID
}
@@ -71,7 +78,18 @@ export function WorkspaceRouterMiddleware(upgrade: UpgradeWebSocket): Middleware
}
const workspace = await Workspace.get(WorkspaceID.make(workspaceID))
if (!workspace) {
// Special-case deleting a session in case user's data in a
// weird state. Allow them to forcefully delete a synced session
// even if the remote workspace is not in their data.
//
// The lets the `DELETE /session/:id` endpoint through and we've
// made sure that it will run without an instance
if (url.pathname.match(/\/session\/[^/]+$/) && c.req.method === "DELETE") {
return routes().fetch(c.req.raw, c.env)
}
return new Response(`Workspace not found: ${workspaceID}`, {
status: 500,
headers: {

View File

@@ -62,6 +62,28 @@ export const WorkspaceRoutes = lazy(() =>
return c.json(Workspace.list(Instance.project))
},
)
.get(
"/status",
describeRoute({
summary: "Workspace status",
description: "Get connection status for workspaces in the current project.",
operationId: "experimental.workspace.status",
responses: {
200: {
description: "Workspace status",
content: {
"application/json": {
schema: resolver(z.array(Workspace.ConnectionStatus)),
},
},
},
},
}),
async (c) => {
const ids = new Set(Workspace.list(Instance.project).map((item) => item.id))
return c.json(Workspace.status().filter((item) => ids.has(item.workspaceID)))
},
)
.delete(
"/:id",
describeRoute({