import { Database } from "@opencode-ai/core/database/database" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { httpClient } from "@opencode-ai/core/effect/app-node-platform" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { EventV2 } from "@opencode-ai/core/event" import { EventLogger } from "@opencode-ai/core/event-logger" import { Observability } from "@opencode-ai/core/observability" import { Credential } from "@opencode-ai/core/credential" import { PermissionSaved } from "@opencode-ai/core/permission/saved" import { PtyTicket } from "@opencode-ai/core/pty/ticket" import { Project } from "@opencode-ai/core/project" import { SessionV2 } from "@opencode-ai/core/session" import { Job } from "@opencode-ai/core/job" import { LocationServiceMap } from "@opencode-ai/core/location-service-map" import { SessionRestart } from "@opencode-ai/core/session/execution/restart" import { PluginRuntime } from "@opencode-ai/core/plugin/runtime" import { SdkPlugins } from "@opencode-ai/core/plugin/sdk" import { ToolOutputStore } from "@opencode-ai/core/tool-output-store" import { WellKnown } from "@opencode-ai/core/wellknown" import { HttpRouter, HttpServer } from "effect/unstable/http" import { HttpApiBuilder } from "effect/unstable/httpapi" import { Context, Effect, Layer, Option } from "effect" import { Api } from "./api" import { ServerAuth } from "./auth" import { handlers } from "./handlers" import { authorizationLayer } from "./middleware/authorization" import { schemaErrorLayer } from "./middleware/schema-error" import { PtyEnvironment } from "./pty-environment" import { layer } from "./location" import { formLocationLayer } from "./middleware/form-location" import { sessionLocationLayer } from "./middleware/session-location" import { ServerInfo } from "./server-info" const applicationServices = LayerNode.group([ Database.node, EventV2.node, EventLogger.node, httpClient, ToolOutputStore.cleanupNode, Job.node, Project.node, SessionV2.node, PluginRuntime.providerNode, SdkPlugins.node, PermissionSaved.node, PtyTicket.node, Credential.node, WellKnown.node, PtyEnvironment.node, LocationServiceMap.node, SessionRestart.node, ]) export function createRoutes(password?: string, serviceURLs: () => ReadonlyArray = () => []) { return makeRoutes( password ? ServerAuth.Config.configLayer({ username: "opencode", password: Option.some(password) }) : ServerAuth.Config.layer, serviceURLs, ) } export function createEmbeddedRoutes() { return makeRoutes(ServerAuth.Config.configLayer({ username: "opencode", password: Option.none() })) } function makeRoutes( auth: Layer.Layer, serviceURLs: () => ReadonlyArray = () => [], ) { const pluginRuntimeCell = PluginRuntime.makeCell() const replacements: LayerNode.Replacements = [ [PluginRuntime.node, PluginRuntime.layerWithCell(pluginRuntimeCell)], [PluginRuntime.providerNode, PluginRuntime.providerNodeWithCell(pluginRuntimeCell)], ] const serviceLayer = simulateEnabled() ? Layer.unwrap( Effect.gen(function* () { const { simulationReplacements } = yield* Effect.promise(() => import("@opencode-ai/simulation/backend")) const simulation = yield* simulationReplacements() return AppNodeBuilder.build(applicationServices, [...replacements, ...simulation]) }), ) : AppNodeBuilder.build(applicationServices, replacements) return serviceLayer.pipe( Layer.flatMap((context) => { const services = Layer.succeedContext(context) const requestServices = Layer.merge( Layer.succeedContext(Context.pick(PermissionSaved.Service, Project.Service, WellKnown.Service)(context)), ServerInfo.layer(serviceURLs), ) return HttpApiBuilder.layer(Api, { openapiPath: "/openapi.json" }).pipe( Layer.provide(handlers.pipe(Layer.provide(services))), Layer.provide(formLocationLayer), Layer.provide(sessionLocationLayer), Layer.provide(layer), Layer.provide(authorizationLayer), Layer.provide(schemaErrorLayer), Layer.provide(auth), Layer.provide(Observability.layer), HttpRouter.provideRequest(requestServices), Layer.provideMerge(services), Layer.provideMerge(HttpRouter.layer), ) }), ) } function simulateEnabled() { return !!process.env.OPENCODE_SIMULATE } export const webHandler = () => HttpRouter.toWebHandler(createRoutes().pipe(Layer.provide(HttpServer.layerServices)))