import { Location } from "@opencode-ai/core/location" import { LocationServiceMap } from "@opencode-ai/core/location-services" import { AbsolutePath } from "@opencode-ai/core/schema" import { WorkspaceV2 } from "@opencode-ai/core/workspace" import { Effect, Layer } from "effect" import { HttpServerRequest } from "effect/unstable/http" import { HttpApiMiddleware } from "effect/unstable/httpapi" export type LocationServices = Layer.Success> export class LocationMiddleware extends HttpApiMiddleware.Service()( "@opencode/HttpApiLocation", ) {} export function response(data: Effect.Effect) { return Effect.gen(function* () { const location = yield* Location.Service return { location: new Location.Info({ directory: location.directory, workspaceID: location.workspaceID, project: location.project, }), data: yield* data, } }) } function ref(request: HttpServerRequest.HttpServerRequest): Location.Ref { const query = new URL(request.url, "http://localhost").searchParams const workspaceID = query.get("location[workspace]") || request.headers["x-opencode-workspace"] const directory = query.get("location[directory]") || (request.headers["x-opencode-directory"] ? decode(request.headers["x-opencode-directory"]) : process.cwd()) return Location.Ref.make({ directory: AbsolutePath.make(directory), workspaceID: workspaceID ? WorkspaceV2.ID.make(workspaceID) : undefined, }) } function decode(input: string) { try { return decodeURIComponent(input) } catch { return input } } export const layer = Layer.effect( LocationMiddleware, Effect.gen(function* () { const locations = yield* LocationServiceMap.Service return LocationMiddleware.of((effect) => Effect.gen(function* () { const request = yield* HttpServerRequest.HttpServerRequest return yield* effect.pipe(Effect.provide(locations.get(ref(request)))) }), ) }), )