| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { mkdir, stat } from "node:fs/promises"; |
| import { dirname } from "node:path"; |
|
|
| import { AgentFS } from "agentfs-sdk"; |
| import type { FileSystem } from "agentfs-sdk"; |
|
|
| import { hostRegistry } from "../agentfs-sandbox/host.js"; |
| import { AgentFsDebugError, mapAgentFsOpenError } from "./errors.js"; |
| import { resolveSessionDbPath } from "./paths.js"; |
|
|
| export type OpenAgent = Awaited<ReturnType<typeof AgentFS.open>>; |
|
|
| async function closeQuietly(agent: OpenAgent): Promise<void> { |
| try { |
| await agent.close(); |
| } catch { |
| |
| } |
| } |
|
|
| |
| export async function assertDbExists( |
| dbPath: string, |
| notFound: { code: string; message: string }, |
| ): Promise<void> { |
| try { |
| await stat(dbPath); |
| } catch (err) { |
| const code = (err as NodeJS.ErrnoException).code; |
| if (code === "ENOENT") { |
| throw new AgentFsDebugError(404, notFound.code, notFound.message); |
| } |
| throw err; |
| } |
| } |
|
|
| |
| export async function assertSessionDbExists(sessionId: string): Promise<string> { |
| const sessionDb = resolveSessionDbPath(sessionId); |
| await assertDbExists(sessionDb, { |
| code: "session_not_found", |
| message: `session 不存在: ${sessionId}`, |
| }); |
| return sessionDb; |
| } |
|
|
| |
| |
| |
| |
| |
| export async function withAgentFsAtPath<T>( |
| dbPath: string, |
| fn: (agent: OpenAgent) => Promise<T>, |
| opts?: { |
| mustExist?: boolean; |
| label?: string; |
| notFound?: { code: string; message: string }; |
| }, |
| ): Promise<T> { |
| const mustExist = opts?.mustExist ?? true; |
| const label = opts?.label ?? dbPath; |
|
|
| if (mustExist) { |
| await assertDbExists( |
| dbPath, |
| opts?.notFound ?? { |
| code: "session_not_found", |
| message: `库不存在: ${label}`, |
| }, |
| ); |
| } else { |
| await mkdir(dirname(dbPath), { recursive: true }); |
| } |
|
|
| let agent: OpenAgent; |
| try { |
| agent = await AgentFS.open({ path: dbPath }); |
| } catch (err) { |
| throw mapAgentFsOpenError(err, label); |
| } |
|
|
| try { |
| return await fn(agent); |
| } finally { |
| await closeQuietly(agent); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function withSessionFileSystem<T>( |
| sessionId: string, |
| fn: (fs: FileSystem) => Promise<T>, |
| ): Promise<T> { |
| const dbPath = await assertSessionDbExists(sessionId); |
|
|
| return hostRegistry.withSharedAccess(dbPath, async () => { |
| const live = hostRegistry.getByDbPath(dbPath); |
| if (live) { |
| return fn(live.agentFs.fs); |
| } |
| return withAgentFsAtPath( |
| dbPath, |
| (agent) => fn(agent.fs), |
| { |
| mustExist: true, |
| label: sessionId, |
| notFound: { |
| code: "session_not_found", |
| message: `session 不存在: ${sessionId}`, |
| }, |
| }, |
| ); |
| }); |
| } |
|
|
| |
| |
| |
| |
| export async function withAgentFs<T>( |
| sessionId: string, |
| fn: (agent: OpenAgent) => Promise<T>, |
| ): Promise<T> { |
| const dbPath = resolveSessionDbPath(sessionId); |
| return withAgentFsAtPath(dbPath, fn, { |
| mustExist: true, |
| label: sessionId, |
| notFound: { |
| code: "session_not_found", |
| message: `session 不存在: ${sessionId}`, |
| }, |
| }); |
| } |
|
|