| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- import { Effect, Layer, Schema } from "effect"
- import { HttpApiBuilder } from "effect/unstable/httpapi"
- import { HttpRouter, HttpServer, HttpServerRequest } from "effect/unstable/http"
- import { AppRuntime } from "@/effect/app-runtime"
- import { InstanceRef, WorkspaceRef } from "@/effect/instance-ref"
- import { Observability } from "@/effect"
- import { InstanceBootstrap } from "@/project/bootstrap"
- import { Instance } from "@/project/instance"
- import { lazy } from "@/util/lazy"
- import { Filesystem } from "@/util"
- import { authorizationLayer } from "./auth"
- import { ConfigApi, configHandlers } from "./config"
- import { FileApi, fileHandlers } from "./file"
- import { ExperimentalApi, experimentalHandlers } from "./experimental"
- import { InstanceApi, instanceHandlers } from "./instance"
- import { McpApi, mcpHandlers } from "./mcp"
- import { PermissionApi, permissionHandlers } from "./permission"
- import { ProjectApi, projectHandlers } from "./project"
- import { ProviderApi, providerHandlers } from "./provider"
- import { QuestionApi, questionHandlers } from "./question"
- import { WorkspaceApi, workspaceHandlers } from "./workspace"
- import { memoMap } from "@opencode-ai/core/effect/memo-map"
- const Query = Schema.Struct({
- directory: Schema.optional(Schema.String),
- workspace: Schema.optional(Schema.String),
- auth_token: Schema.optional(Schema.String),
- })
- const Headers = Schema.Struct({
- authorization: Schema.optional(Schema.String),
- "x-opencode-directory": Schema.optional(Schema.String),
- })
- function decode(input: string) {
- try {
- return decodeURIComponent(input)
- } catch {
- return input
- }
- }
- const instance = HttpRouter.middleware()(
- Effect.gen(function* () {
- return (effect) =>
- Effect.gen(function* () {
- const query = yield* HttpServerRequest.schemaSearchParams(Query)
- const headers = yield* HttpServerRequest.schemaHeaders(Headers)
- const raw = query.directory || headers["x-opencode-directory"] || process.cwd()
- const workspace = query.workspace || undefined
- const ctx = yield* Effect.promise(() =>
- Instance.provide({
- directory: Filesystem.resolve(decode(raw)),
- init: () => AppRuntime.runPromise(InstanceBootstrap),
- fn: () => Instance.current,
- }),
- )
- const next = workspace ? effect.pipe(Effect.provideService(WorkspaceRef, workspace)) : effect
- return yield* next.pipe(Effect.provideService(InstanceRef, ctx))
- })
- }),
- ).layer
- export const routes = Layer.mergeAll(
- HttpApiBuilder.layer(ConfigApi).pipe(Layer.provide(configHandlers)),
- HttpApiBuilder.layer(ExperimentalApi).pipe(Layer.provide(experimentalHandlers)),
- HttpApiBuilder.layer(FileApi).pipe(Layer.provide(fileHandlers)),
- HttpApiBuilder.layer(InstanceApi).pipe(Layer.provide(instanceHandlers)),
- HttpApiBuilder.layer(McpApi).pipe(Layer.provide(mcpHandlers)),
- HttpApiBuilder.layer(ProjectApi).pipe(Layer.provide(projectHandlers)),
- HttpApiBuilder.layer(QuestionApi).pipe(Layer.provide(questionHandlers)),
- HttpApiBuilder.layer(PermissionApi).pipe(Layer.provide(permissionHandlers)),
- HttpApiBuilder.layer(ProviderApi).pipe(Layer.provide(providerHandlers)),
- HttpApiBuilder.layer(WorkspaceApi).pipe(Layer.provide(workspaceHandlers)),
- ).pipe(
- Layer.provide(authorizationLayer),
- Layer.provide(instance),
- Layer.provide(HttpServer.layerServices),
- Layer.provideMerge(Observability.layer),
- )
- export const webHandler = lazy(() =>
- HttpRouter.toWebHandler(routes, {
- memoMap,
- }),
- )
- export * as ExperimentalHttpApiServer from "./server"
|