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)