Serve instance events through HttpApiBuilder (#25182)
This commit is contained in:
@@ -2,8 +2,8 @@ import { Bus } from "@/bus"
|
|||||||
import * as Log from "@opencode-ai/core/util/log"
|
import * as Log from "@opencode-ai/core/util/log"
|
||||||
import { Effect, Schema } from "effect"
|
import { Effect, Schema } from "effect"
|
||||||
import * as Stream from "effect/Stream"
|
import * as Stream from "effect/Stream"
|
||||||
import { HttpRouter, HttpServerResponse } from "effect/unstable/http"
|
import { HttpServerResponse } from "effect/unstable/http"
|
||||||
import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
|
import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
|
||||||
import * as Sse from "effect/unstable/encoding/Sse"
|
import * as Sse from "effect/unstable/encoding/Sse"
|
||||||
|
|
||||||
const log = Log.create({ service: "server" })
|
const log = Log.create({ service: "server" })
|
||||||
@@ -16,7 +16,7 @@ export const EventApi = HttpApi.make("event").add(
|
|||||||
HttpApiGroup.make("event")
|
HttpApiGroup.make("event")
|
||||||
.add(
|
.add(
|
||||||
HttpApiEndpoint.get("subscribe", EventPaths.event, {
|
HttpApiEndpoint.get("subscribe", EventPaths.event, {
|
||||||
success: Schema.Unknown,
|
success: Schema.String.pipe(HttpApiSchema.asText({ contentType: "text/event-stream" })),
|
||||||
}).annotateMerge(
|
}).annotateMerge(
|
||||||
OpenApi.annotations({
|
OpenApi.annotations({
|
||||||
identifier: "event.subscribe",
|
identifier: "event.subscribe",
|
||||||
@@ -37,13 +37,7 @@ function eventData(data: unknown): Sse.Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventRoute = HttpRouter.use((router) =>
|
function eventResponse(bus: Bus.Interface) {
|
||||||
Effect.gen(function* () {
|
|
||||||
const bus = yield* Bus.Service
|
|
||||||
yield* router.add(
|
|
||||||
"GET",
|
|
||||||
EventPaths.event,
|
|
||||||
Effect.gen(function* () {
|
|
||||||
const events = bus.subscribeAll().pipe(Stream.takeUntil((event) => event.type === Bus.InstanceDisposed.type))
|
const events = bus.subscribeAll().pipe(Stream.takeUntil((event) => event.type === Bus.InstanceDisposed.type))
|
||||||
const heartbeat = Stream.tick("10 seconds").pipe(
|
const heartbeat = Stream.tick("10 seconds").pipe(
|
||||||
Stream.drop(1),
|
Stream.drop(1),
|
||||||
@@ -68,7 +62,13 @@ export const eventRoute = HttpRouter.use((router) =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}),
|
}
|
||||||
)
|
|
||||||
|
export const eventHandlers = HttpApiBuilder.group(EventApi, "event", (handlers) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const bus = yield* Bus.Service
|
||||||
|
return handlers.handleRaw("subscribe", Effect.fn("EventHttpApi.subscribe")(function* () {
|
||||||
|
return eventResponse(bus)
|
||||||
|
}))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import { isAllowedCorsOrigin } from "@/server/cors"
|
|||||||
import { serveUIEffect } from "@/server/routes/ui"
|
import { serveUIEffect } from "@/server/routes/ui"
|
||||||
import { InstanceHttpApi, RootHttpApi } from "./api"
|
import { InstanceHttpApi, RootHttpApi } from "./api"
|
||||||
import { ServerAuthConfig, authorizationLayer, authorizationRouterMiddleware } from "./middleware/authorization"
|
import { ServerAuthConfig, authorizationLayer, authorizationRouterMiddleware } from "./middleware/authorization"
|
||||||
import { eventRoute } from "./event"
|
import { EventApi, eventHandlers } from "./event"
|
||||||
import { configHandlers } from "./handlers/config"
|
import { configHandlers } from "./handlers/config"
|
||||||
import { controlHandlers } from "./handlers/control"
|
import { controlHandlers } from "./handlers/control"
|
||||||
import { experimentalHandlers } from "./handlers/experimental"
|
import { experimentalHandlers } from "./handlers/experimental"
|
||||||
@@ -86,6 +86,14 @@ const cors = HttpRouter.middleware(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const rootApiRoutes = HttpApiBuilder.layer(RootHttpApi).pipe(Layer.provide([controlHandlers, globalHandlers]))
|
const rootApiRoutes = HttpApiBuilder.layer(RootHttpApi).pipe(Layer.provide([controlHandlers, globalHandlers]))
|
||||||
|
const instanceRouterLayer = authorizationRouterMiddleware
|
||||||
|
.combine(instanceRouterMiddleware)
|
||||||
|
.combine(workspaceRouterMiddleware)
|
||||||
|
.layer.pipe(Layer.provide(Socket.layerWebSocketConstructorGlobal), Layer.provide(ServerAuthConfig.defaultLayer))
|
||||||
|
const eventApiRoutes = HttpApiBuilder.layer(EventApi).pipe(
|
||||||
|
Layer.provide(eventHandlers),
|
||||||
|
Layer.provide(instanceRouterLayer),
|
||||||
|
)
|
||||||
const instanceApiRoutes = HttpApiBuilder.layer(InstanceHttpApi).pipe(
|
const instanceApiRoutes = HttpApiBuilder.layer(InstanceHttpApi).pipe(
|
||||||
Layer.provide([
|
Layer.provide([
|
||||||
configHandlers,
|
configHandlers,
|
||||||
@@ -105,13 +113,8 @@ const instanceApiRoutes = HttpApiBuilder.layer(InstanceHttpApi).pipe(
|
|||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
|
|
||||||
const rawInstanceRoutes = Layer.mergeAll(eventRoute, ptyConnectRoute).pipe(
|
const rawInstanceRoutes = Layer.mergeAll(ptyConnectRoute).pipe(
|
||||||
Layer.provide(
|
Layer.provide(instanceRouterLayer),
|
||||||
authorizationRouterMiddleware
|
|
||||||
.combine(instanceRouterMiddleware)
|
|
||||||
.combine(workspaceRouterMiddleware)
|
|
||||||
.layer.pipe(Layer.provide(Socket.layerWebSocketConstructorGlobal), Layer.provide(ServerAuthConfig.defaultLayer)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
const instanceRoutes = Layer.mergeAll(rawInstanceRoutes, instanceApiRoutes).pipe(
|
const instanceRoutes = Layer.mergeAll(rawInstanceRoutes, instanceApiRoutes).pipe(
|
||||||
Layer.provide([
|
Layer.provide([
|
||||||
@@ -129,7 +132,7 @@ const uiRoute = HttpRouter.use((router) =>
|
|||||||
}),
|
}),
|
||||||
).pipe(Layer.provide(authorizationRouterMiddleware.layer.pipe(Layer.provide(ServerAuthConfig.defaultLayer))))
|
).pipe(Layer.provide(authorizationRouterMiddleware.layer.pipe(Layer.provide(ServerAuthConfig.defaultLayer))))
|
||||||
|
|
||||||
export const routes = Layer.mergeAll(rootApiRoutes, instanceRoutes, uiRoute).pipe(
|
export const routes = Layer.mergeAll(rootApiRoutes, eventApiRoutes, instanceRoutes, uiRoute).pipe(
|
||||||
Layer.provide([
|
Layer.provide([
|
||||||
cors,
|
cors,
|
||||||
runtime,
|
runtime,
|
||||||
|
|||||||
Reference in New Issue
Block a user