diff --git a/packages/opencode/src/cli/cmd/debug/file.ts b/packages/opencode/src/cli/cmd/debug/file.ts
index 0e6ef98c24..750d25942b 100644
--- a/packages/opencode/src/cli/cmd/debug/file.ts
+++ b/packages/opencode/src/cli/cmd/debug/file.ts
@@ -1,10 +1,11 @@
import { EOL } from "os"
import { Effect } from "effect"
import { FileSystem } from "@opencode-ai/core/filesystem"
+import { FSUtil } from "@opencode-ai/core/fs-util"
import { LocationServiceMap } from "@opencode-ai/core/location-layer"
import { Location } from "@opencode-ai/core/location"
import { AbsolutePath, RelativePath } from "@opencode-ai/core/schema"
-import { effectCmd } from "../../effect-cmd"
+import { CliError, effectCmd } from "../../effect-cmd"
import { cmd } from "../cmd"
const filesystem = (effect: Effect.Effect) =>
@@ -13,6 +14,8 @@ const filesystem = (effect: Effect.Effect) =>
Effect.provide(LocationServiceMap.layer),
)
+const fileError = (error: FileSystem.PathError | FSUtil.Error) => new CliError({ message: error.message })
+
const FileSearchCommand = effectCmd({
command: "search ",
describe: "search files by query",
@@ -38,7 +41,9 @@ const FileReadCommand = effectCmd({
description: "File path to read",
}),
handler: Effect.fn("Cli.debug.file.read")(function* (args) {
- const file = yield* filesystem(FileSystem.Service.use((svc) => svc.read({ path: RelativePath.make(args.path) })))
+ const file = yield* filesystem(
+ FileSystem.Service.use((svc) => svc.read({ path: RelativePath.make(args.path) })),
+ ).pipe(Effect.mapError(fileError))
process.stdout.write(
JSON.stringify(
{ content: Buffer.from(file.content).toString("base64"), encoding: "base64", mime: file.mime },
@@ -59,7 +64,9 @@ const FileListCommand = effectCmd({
description: "File path to list",
}),
handler: Effect.fn("Cli.debug.file.list")(function* (args) {
- const files = yield* filesystem(FileSystem.Service.use((svc) => svc.list({ path: RelativePath.make(args.path) })))
+ const files = yield* filesystem(
+ FileSystem.Service.use((svc) => svc.list({ path: RelativePath.make(args.path) })),
+ ).pipe(Effect.mapError(fileError))
process.stdout.write(JSON.stringify(files, null, 2) + EOL)
}),
})
diff --git a/packages/opencode/src/server/routes/instance/httpapi/handlers/file.ts b/packages/opencode/src/server/routes/instance/httpapi/handlers/file.ts
index bacc4b0457..cfc804d0f6 100644
--- a/packages/opencode/src/server/routes/instance/httpapi/handlers/file.ts
+++ b/packages/opencode/src/server/routes/instance/httpapi/handlers/file.ts
@@ -10,6 +10,10 @@ import ignore from "ignore"
import path from "path"
import { HttpApiBuilder } from "effect/unstable/httpapi"
import { InstanceHttpApi } from "../api"
+import { InvalidRequestError } from "../errors"
+
+const invalidRequest = (error: FileSystem.PathError | FSUtil.Error) =>
+ new InvalidRequestError({ message: error.message, kind: error._tag })
export const fileHandlers = HttpApiBuilder.group(InstanceHttpApi, "file", (handlers) =>
Effect.gen(function* () {
@@ -79,7 +83,9 @@ export const fileHandlers = HttpApiBuilder.group(InstanceHttpApi, "file", (handl
.readFileString(path.join(location.project.directory, ".ignore"))
.pipe(Effect.catch(() => Effect.succeed("")))
if (ignorefile) ignored.add(ignorefile)
- return (yield* fs.list({ path: RelativePath.make(ctx.query.path) })).map((item) => ({
+ return (yield* fs
+ .list({ path: RelativePath.make(ctx.query.path) })
+ .pipe(Effect.mapError(invalidRequest))).map((item) => ({
name: path.basename(item.path),
path: item.path,
absolute: path.resolve(location.directory, item.path),
@@ -101,6 +107,7 @@ export const fileHandlers = HttpApiBuilder.group(InstanceHttpApi, "file", (handl
return yield* filesystem(
FileSystem.Service.use((fs) => fs.read({ path: RelativePath.make(ctx.query.path) })),
).pipe(
+ Effect.mapError(invalidRequest),
Effect.flatMap((item) =>
Effect.gen(function* () {
const text = item.content.includes(0)