feat(core): allow external workspace creation (#26212)

This commit is contained in:
James Long
2026-05-08 11:09:12 -04:00
committed by GitHub
parent c36ab3f935
commit c818c9dcb6
21 changed files with 2039 additions and 145 deletions

View File

@@ -93,6 +93,23 @@ export const WorkspaceRoutes = lazy(() =>
return c.json(await AppRuntime.runPromise(Workspace.Service.use((svc) => svc.list(Instance.project))))
},
)
.post(
"/sync-list",
describeRoute({
summary: "Sync workspace list",
description: "Register missing workspaces returned by workspace adapters.",
operationId: "experimental.workspace.syncList",
responses: {
204: {
description: "Workspace list synced",
},
},
}),
async (c) => {
await AppRuntime.runPromise(Workspace.Service.use((svc) => svc.syncList(Instance.project)))
return c.body(null, 204)
},
)
.get(
"/status",
describeRoute({

View File

@@ -29,6 +29,7 @@ export class ApiWorkspaceWarpError extends Schema.ErrorClass<ApiWorkspaceWarpErr
export const WorkspacePaths = {
adapters: `${root}/adapter`,
list: root,
syncList: `${root}/sync-list`,
status: `${root}/status`,
remove: `${root}/:id`,
warp: `${root}/warp`,
@@ -67,6 +68,15 @@ export const WorkspaceApi = HttpApi.make("workspace")
description: "Create a workspace for the current project.",
}),
),
HttpApiEndpoint.post("syncList", WorkspacePaths.syncList, {
success: described(HttpApiSchema.NoContent, "Workspace list synced"),
}).annotateMerge(
OpenApi.annotations({
identifier: "experimental.workspace.syncList",
summary: "Sync workspace list",
description: "Register missing workspaces returned by workspace adapters.",
}),
),
HttpApiEndpoint.get("status", WorkspacePaths.status, {
success: described(Schema.Array(Workspace.ConnectionStatus), "Workspace status"),
}).annotateMerge(

View File

@@ -14,7 +14,7 @@ export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspac
const adapters = Effect.fn("WorkspaceHttpApi.adapters")(function* () {
const instance = yield* InstanceState.context
return yield* Effect.promise(() => listAdapters(instance.project.id))
return yield* Effect.sync(() => listAdapters(instance.project.id))
})
const list = Effect.fn("WorkspaceHttpApi.list")(function* () {
@@ -32,6 +32,10 @@ export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspac
.pipe(Effect.mapError(() => new HttpApiError.BadRequest({})))
})
const syncList = Effect.fn("WorkspaceHttpApi.syncList")(function* () {
yield* workspace.syncList((yield* InstanceState.context).project)
})
const status = Effect.fn("WorkspaceHttpApi.status")(function* () {
const ids = new Set((yield* workspace.list((yield* InstanceState.context).project)).map((item) => item.id))
return (yield* workspace.status()).filter((item) => ids.has(item.workspaceID))
@@ -73,6 +77,7 @@ export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspac
.handle("adapters", adapters)
.handle("list", list)
.handle("create", create)
.handle("syncList", syncList)
.handle("status", status)
.handle("remove", remove)
.handle("warp", warp)