UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

192 lines (191 loc) • 7.25 kB
import { w as root } from "../../fs-safe-BBzelG8F.mjs"; import { d as buildMultimodalChunkForIndexing, l as readMemoryFile, p as listMemoryFiles, u as buildFileEntry } from "../../engine-storage-DwRRcchW.mjs"; import "../../memory-core-host-engine-storage-D6wIwcVO.mjs"; import "../../file-access-runtime-BSYnDRNI.mjs"; import { t as createFileWatchNotifier } from "../../file-watch-notifier-DodcPHwr.mjs"; import path from "node:path"; import { AsyncLocalStorage } from "node:async_hooks"; import fs from "node:fs/promises"; import { createInterface } from "node:readline"; //#region extensions/memory-core/src/remote/memory-files-worker.ts /** Same-version file IPC; the provisioned adapter owns admission and configured roots. */ async function serveMemoryFiles(options) { if (options.watch) { const runInBackgroundContext = AsyncLocalStorage.snapshot(); const { MemoryFileWatcher } = await import("../../file-watcher-CIbiYSjU.mjs"); const lines = createInterface({ input: options.input, crlfDelay: Infinity }); let watcher; let closing; let outputClosing; let notifier; let stopped = false; const close = () => { stopped = true; closing ??= watcher?.close(); outputClosing ??= notifier?.close(); outputClosing?.catch(() => void 0); closing?.catch(() => void 0); }; notifier = createFileWatchNotifier(options.output, () => { close(); lines.close(); }); options.input.on("end", close).on("close", close); const errors = []; try { for await (const line of lines) { if (stopped) break; if (watcher) throw new Error("Unexpected message on the Memory watch subscription"); const request = JSON.parse(line); const notify = (event) => notifier?.send(event); watcher = new MemoryFileWatcher({ runInBackgroundContext, workspaceDir: path.resolve(options.workspace), agentId: request.agentId, settings: request.settings, onChange: () => notify("change"), onUnavailable: () => notify("unavailable") }); if (options.input.readableEnded || options.input.destroyed) { close(); break; } await watcher.start(); } } catch (error) { errors.push(error); } finally { options.input.off("end", close).off("close", close); lines.close(); close(); const results = await Promise.allSettled([closing, outputClosing]); errors.push(...results.flatMap((result) => result.status === "rejected" ? [result.reason] : [])); notifier = void 0; } if (errors.length) throw new AggregateError(errors, "Memory watch retirement failed"); return; } const chunks = []; const inputChunks = options.input; for await (const chunk of inputChunks) { if (typeof chunk !== "string" && !(chunk instanceof Uint8Array)) throw new Error("Memory file request must be bytes"); chunks.push(Buffer.from(chunk)); } const decoded = JSON.parse(Buffer.concat(chunks).toString("utf8")); if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) throw new Error("Memory file request must be an object"); const request = decoded; const workspace = path.resolve(options.workspace); let result; let failure; try { switch (request.operation) { case "maintenance": result = await runMaintenance(request, workspace); break; case "list": { const skipped = []; result = { files: await listMemoryFiles(workspace, request.extraPaths, request.multimodal, (p) => skipped.push(p)), skipped }; break; } case "inspect": result = await buildFileEntry(request.filePath, workspace, request.multimodal); break; case "read": result = await readMemoryFile({ ...request.params, workspaceDir: workspace }); break; case "readForIndexing": { const read = await (await root(path.dirname(request.filePath), { hardlinks: "allow", symlinks: "reject", maxBytes: Number.MAX_SAFE_INTEGER })).read(path.basename(request.filePath)); result = { content: read.buffer.toString("utf8"), canonicalRelativePath: path.relative(await fs.realpath(workspace), read.realPath).replaceAll(path.sep, "/") }; break; } case "multimodal": result = await buildMultimodalChunkForIndexing(request.entry); break; default: throw new Error("Unknown Memory file operation"); } } catch (error) { failure = { message: error instanceof Error ? error.message : String(error), ...error instanceof Error ? { name: error.name } : {}, ...error && typeof error === "object" && "publication" in error && (error.publication === "uncertain" || error.publication === "committed") ? { publication: error.publication } : {}, ...error && typeof error === "object" && "code" in error && typeof error.code === "string" ? { code: error.code } : {} }; } await new Promise((resolve, reject) => { options.output.write(JSON.stringify(failure ? { error: failure } : { result }), (error) => error ? reject(error) : resolve()); }); } async function runMaintenance(request, workspace) { switch (request.method) { case "readFile": return (await fs.readFile(...request.args)).toString("base64"); case "stat": { const [filePath, followSymlinks] = request.args; const info = followSymlinks ? await fs.stat(filePath) : await fs.lstat(filePath); return { isFile: info.isFile(), isDirectory: info.isDirectory(), isSymbolicLink: info.isSymbolicLink(), size: info.size, mtimeMs: info.mtimeMs, mode: info.mode }; } case "listDirectory": return (await fs.readdir(request.args[0], { withFileTypes: true })).map((entry) => ({ name: entry.name, isFile: entry.isFile(), isDirectory: entry.isDirectory(), isSymbolicLink: entry.isSymbolicLink() })); case "mkdir": await fs.mkdir(request.args[0], { recursive: true }); return null; case "rename": return await fs.rename(...request.args); case "resolveWritePath": { const { resolveMemoryWritePath } = await import("../../short-term-promotion-memory-write-lV2sFCqH.mjs"); return await resolveMemoryWritePath(...request.args); } case "commitContent": { const { commitMemoryContent } = await import("../../short-term-promotion-memory-write-lV2sFCqH.mjs"); return await commitMemoryContent(...request.args); } case "resolveDreamsPath": { const { resolveDreamsPath } = await import("../../dreaming-dreams-file-P_bqPfIl.mjs"); return await resolveDreamsPath(workspace); } case "readDreams": { const { readDreamsFile } = await import("../../dreaming-dreams-file-P_bqPfIl.mjs"); return await readDreamsFile(...request.args); } case "writeDreams": { const { writeDreamsFileAtomic } = await import("../../dreaming-dreams-file-P_bqPfIl.mjs"); return await writeDreamsFileAtomic(...request.args); } case "replaceReport": { const { replaceDreamingMarkdownFile } = await import("../../dreaming-markdown-DpRMM0jp.mjs"); return await replaceDreamingMarkdownFile(...request.args); } case "appendCorpus": { const { appendSessionCorpusText } = await import("../../session-ingestion-CnCCGx5y.mjs"); return await appendSessionCorpusText(...request.args); } default: throw new Error("Unknown Memory maintenance operation"); } } //#endregion export { serveMemoryFiles };