import { Effect, Data } from "effect"; import { createAgentMessage, type VolumeCommand, type VolumeCommandPayload } from "@zerobyte/contracts/agent-protocol"; import type { BackendConfig, Volume as AgentVolume } from "@zerobyte/contracts/volumes"; import { toMessage } from "@zerobyte/core/utils"; import { createVolumeBackend, getStatFs, getVolumePath } from "../volume-host"; import { browseFilesystem, listVolumeFiles, testVolumeConnection } from "../volume-host/operations"; import type { ControllerCommandContext } from "../context"; type VolumeBackedCommand = Extract; class VolumeCommandError extends Data.TaggedError("StopAgentManagerServerError")<{ cause: unknown; }> {} const asVolume = (volume: VolumeBackedCommand["volume"]): AgentVolume => ({ ...volume, config: volume.config as BackendConfig, provisioningId: volume.provisioningId ?? null, }); const runBackendOperation = ( command: Extract, operation: "mount" | "unmount" | "checkHealth", ) => Effect.tryPromise({ try: () => { const backend = createVolumeBackend(asVolume(command.volume)); return backend[operation](); }, catch: (error) => new VolumeCommandError({ cause: error }), }); const executeVolumeCommand = (command: VolumeCommand) => Effect.gen(function* () { switch (command.name) { case "volume.mount": return { name: command.name, result: yield* runBackendOperation(command, "mount") }; case "volume.unmount": return { name: command.name, result: yield* runBackendOperation(command, "unmount") }; case "volume.checkHealth": return { name: command.name, result: yield* runBackendOperation(command, "checkHealth") }; case "volume.statfs": { const result = yield* Effect.tryPromise({ try: () => getStatFs(getVolumePath(asVolume(command.volume))), catch: (error) => new VolumeCommandError({ cause: error }), }); return { name: command.name, result }; } case "volume.listFiles": { const result = yield* Effect.tryPromise({ try: () => listVolumeFiles(asVolume(command.volume), command.subPath, command.offset, command.limit), catch: (error) => new VolumeCommandError({ cause: error }), }); return { name: command.name, result }; } case "volume.testConnection": { const result = yield* testVolumeConnection(command.backendConfig as BackendConfig); return { name: command.name, result }; } case "filesystem.browse": const result = yield* Effect.tryPromise({ try: () => browseFilesystem(command.path), catch: (error) => new VolumeCommandError({ cause: error }), }); return { name: command.name, result }; } }); export const handleVolumeCommand = (context: ControllerCommandContext, payload: VolumeCommandPayload) => { return Effect.gen(function* () { const command = yield* executeVolumeCommand(payload.command); yield* context.offerOutbound( createAgentMessage("volume.commandResult", { commandId: payload.commandId, status: "success", command, }), ); return command; }).pipe( Effect.catchAll((error) => context.offerOutbound( createAgentMessage("volume.commandResult", { commandId: payload.commandId, status: "error", error: toMessage(error?.cause), }), ), ), ); };