2026-05-15 00:50:23 +00:00
|
|
|
import { Location } from "@opencode-ai/core/location"
|
2026-06-28 15:30:38 +00:00
|
|
|
import { LocationServiceMap } from "@opencode-ai/core/location-services"
|
2026-05-30 04:06:08 +00:00
|
|
|
import { AbsolutePath } from "@opencode-ai/core/schema"
|
2026-07-27 00:08:55 +00:00
|
|
|
import { Workspace } from "@opencode-ai/core/workspace"
|
2026-06-25 02:15:31 +00:00
|
|
|
import { Effect, Layer } from "effect"
|
2026-05-14 00:58:24 +00:00
|
|
|
import { HttpServerRequest } from "effect/unstable/http"
|
2026-06-25 02:15:31 +00:00
|
|
|
import { HttpApiMiddleware } from "effect/unstable/httpapi"
|
2026-05-14 00:58:24 +00:00
|
|
|
|
2026-06-28 15:30:38 +00:00
|
|
|
export type LocationServices = Layer.Success<ReturnType<(typeof LocationServiceMap.Service)["get"]>>
|
2026-05-14 00:58:24 +00:00
|
|
|
|
2026-06-25 02:15:31 +00:00
|
|
|
export class LocationMiddleware extends HttpApiMiddleware.Service<LocationMiddleware, { provides: LocationServices }>()(
|
|
|
|
|
"@opencode/HttpApiLocation",
|
|
|
|
|
) {}
|
2026-05-14 00:58:24 +00:00
|
|
|
|
2026-06-04 06:57:43 +00:00
|
|
|
export function response<A, E, R>(data: Effect.Effect<A, E, R>) {
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-03 08:55:15 +00:00
|
|
|
export function requestRef(request: HttpServerRequest.HttpServerRequest): Location.Ref {
|
2026-05-14 00:58:24 +00:00
|
|
|
const query = new URL(request.url, "http://localhost").searchParams
|
2026-06-04 03:02:17 +00:00
|
|
|
const workspaceID = query.get("location[workspace]") || request.headers["x-opencode-workspace"]
|
2026-06-12 18:45:16 +00:00
|
|
|
const directory =
|
|
|
|
|
query.get("location[directory]") ||
|
|
|
|
|
(request.headers["x-opencode-directory"] ? decode(request.headers["x-opencode-directory"]) : process.cwd())
|
2026-06-10 04:08:26 +00:00
|
|
|
return Location.Ref.make({
|
2026-06-12 18:45:16 +00:00
|
|
|
directory: AbsolutePath.make(directory),
|
2026-07-27 00:08:55 +00:00
|
|
|
workspaceID: workspaceID ? Workspace.ID.make(workspaceID) : undefined,
|
2026-06-10 04:08:26 +00:00
|
|
|
})
|
2026-05-14 00:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
2026-06-12 18:45:16 +00:00
|
|
|
function decode(input: string) {
|
|
|
|
|
try {
|
|
|
|
|
return decodeURIComponent(input)
|
|
|
|
|
} catch {
|
|
|
|
|
return input
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-14 00:58:24 +00:00
|
|
|
export const layer = Layer.effect(
|
2026-06-07 03:27:28 +00:00
|
|
|
LocationMiddleware,
|
2026-05-14 00:58:24 +00:00
|
|
|
Effect.gen(function* () {
|
2026-06-28 15:30:38 +00:00
|
|
|
const locations = yield* LocationServiceMap.Service
|
2026-06-07 03:27:28 +00:00
|
|
|
return LocationMiddleware.of((effect) =>
|
2026-05-14 00:58:24 +00:00
|
|
|
Effect.gen(function* () {
|
|
|
|
|
const request = yield* HttpServerRequest.HttpServerRequest
|
2026-07-03 08:55:15 +00:00
|
|
|
return yield* effect.pipe(Effect.provide(locations.get(requestRef(request))))
|
2026-05-14 00:58:24 +00:00
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
}),
|
2026-06-02 01:32:50 +00:00
|
|
|
)
|