feat(opencode): add filesystem read and list routes

This commit is contained in:
Dax Raad
2026-06-02 01:54:10 -04:00
parent 0136f03fa9
commit 5937e606df
10 changed files with 414 additions and 15 deletions

View File

@@ -4,6 +4,7 @@ import { ModelGroup } from "./v2/model"
import { ProviderGroup } from "./v2/provider"
import { SessionGroup } from "./v2/session"
import { PermissionGroup, PermissionSavedGroup, SessionPermissionGroup } from "./v2/permission"
import { FileSystemGroup } from "./v2/fs"
export const V2Api = HttpApi.make("v2")
.add(SessionGroup)
@@ -13,6 +14,7 @@ export const V2Api = HttpApi.make("v2")
.add(PermissionGroup)
.add(SessionPermissionGroup)
.add(PermissionSavedGroup)
.add(FileSystemGroup)
.annotateMerge(
OpenApi.annotations({
title: "opencode experimental HttpApi",

View File

@@ -0,0 +1,54 @@
import { LocationFileSystem } from "@opencode-ai/core/location-filesystem"
import { RelativePath } from "@opencode-ai/core/schema"
import { Schema } from "effect"
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { V2Authorization } from "../../middleware/authorization"
import { LocationQuery, locationQueryOpenApi, V2LocationMiddleware } from "./location"
const ReadQuery = Schema.Struct({
...LocationQuery.fields,
path: RelativePath,
})
const ListQuery = Schema.Struct({
...LocationQuery.fields,
path: RelativePath.pipe(Schema.optional),
})
export const FileSystemGroup = HttpApiGroup.make("v2.fs")
.add(
HttpApiEndpoint.get("read", "/api/fs/read", {
query: ReadQuery,
success: LocationFileSystem.Content,
})
.annotateMerge(locationQueryOpenApi)
.annotateMerge(
OpenApi.annotations({
identifier: "v2.fs.read",
summary: "Read file",
description: "Read one file relative to the requested location.",
}),
),
)
.add(
HttpApiEndpoint.get("list", "/api/fs/list", {
query: ListQuery,
success: Schema.Array(LocationFileSystem.Entry),
})
.annotateMerge(locationQueryOpenApi)
.annotateMerge(
OpenApi.annotations({
identifier: "v2.fs.list",
summary: "List directory",
description: "List direct children of one directory relative to the requested location.",
}),
),
)
.annotateMerge(
OpenApi.annotations({
title: "v2 filesystem",
description: "Experimental v2 location-scoped filesystem routes.",
}),
)
.middleware(V2LocationMiddleware)
.middleware(V2Authorization)

View File

@@ -1,6 +1,7 @@
import { Catalog } from "@opencode-ai/core/catalog"
import { Location } from "@opencode-ai/core/location"
import { LocationServiceMap } from "@opencode-ai/core/location-layer"
import { LocationFileSystem } from "@opencode-ai/core/location-filesystem"
import { PermissionV2 } from "@opencode-ai/core/permission"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { PluginBoot } from "@opencode-ai/core/plugin/boot"
@@ -35,7 +36,7 @@ export const locationQueryOpenApi = OpenApi.annotations({
export class V2LocationMiddleware extends HttpApiMiddleware.Service<
V2LocationMiddleware,
{
provides: Catalog.Service | PluginBoot.Service | PermissionV2.Service
provides: Catalog.Service | PluginBoot.Service | PermissionV2.Service | LocationFileSystem.Service
}
>()("@opencode/ExperimentalHttpApiV2Location") {}

View File

@@ -8,6 +8,7 @@ import { modelHandlers } from "./v2/model"
import { providerHandlers } from "./v2/provider"
import { sessionHandlers } from "./v2/session"
import { permissionHandlers, savedPermissionHandlers, sessionPermissionHandlers } from "./v2/permission"
import { fileSystemHandlers } from "./v2/fs"
export const v2Handlers = Layer.mergeAll(
sessionHandlers,
@@ -17,6 +18,7 @@ export const v2Handlers = Layer.mergeAll(
permissionHandlers,
sessionPermissionHandlers,
savedPermissionHandlers,
fileSystemHandlers,
).pipe(
Layer.provide(v2LocationLayer),
Layer.provide(LocationServiceMap.layer),

View File

@@ -0,0 +1,12 @@
import { LocationFileSystem } from "@opencode-ai/core/location-filesystem"
import { Effect } from "effect"
import { HttpApiBuilder } from "effect/unstable/httpapi"
import { InstanceHttpApi } from "../../api"
export const fileSystemHandlers = HttpApiBuilder.group(InstanceHttpApi, "v2.fs", (handlers) =>
Effect.gen(function* () {
return handlers
.handle("read", (ctx) => LocationFileSystem.Service.use((fs) => fs.read(ctx.query)))
.handle("list", (ctx) => LocationFileSystem.Service.use((fs) => fs.list(ctx.query)))
}),
)