@sema-agent/core
Version:
Stateless, task-oriented AI agent core
60 lines (59 loc) • 2.89 kB
JavaScript
import { canonicalPathIsAuthoritative } from "../../core/remote-env.js";
const OBSERVED = Symbol("observedFilesystem");
const CONCLUSIVE = new Set(["not_found", "not_directory", "not_supported"]);
export function canonicalRootsOnce(env, readRoots, known) {
let once = known ? Promise.resolve({ roots: readRoots, incomplete: [] }) : undefined;
return (signal) => (once ??= (async () => {
const seen = observeEnvironment(env);
const roots = [];
for (const r of readRoots) {
const c = await seen.fs.canonicalPath(r, signal);
roots.push(c.ok ? c.value : r);
}
const result = { roots, incomplete: seen.incomplete() };
if (result.incomplete.length > 0)
once = undefined;
return result;
})());
}
export function observeEnvironment(env) {
const authoritative = canonicalPathIsAuthoritative(env);
const records = [];
const note = (op, path, what, code) => void records.push({ op, detail: `"${path}" ${what} (${code})` });
const watch = (op, path, what, ask) => new Promise((resolve) => resolve(ask())).then((r) => {
if (!r.ok && !CONCLUSIVE.has(r.error.code))
note(op, path, what, r.error.code);
return r;
}, (e) => {
note(op, path, what, e instanceof Error ? e.name : "threw");
throw e;
});
const look = (op, what, member) => member === undefined ? {} : { [op]: (path, signal) => watch(op, path, what, () => member.call(env, path, signal)) };
const overlay = {
...look("canonicalPath", "cannot be resolved", env.canonicalPath),
...look("listDir", "cannot be enumerated", env.listDir),
...look("fileInfo", "cannot be inspected", env.fileInfo),
...look("readLink", "cannot be read as a link", env.readLink),
...look("exists", "cannot be checked", env.exists),
...look("absolutePath", "cannot be made absolute", env.absolutePath),
...look("canonicalChain", "its link chain cannot be read", env.canonicalChain),
...look("fileIdentity", "cannot be identified", env.fileIdentity),
[OBSERVED]: true,
};
const fs = new Proxy(env, {
get: (target, prop) => {
if (Object.prototype.hasOwnProperty.call(overlay, prop))
return overlay[prop];
const value = Reflect.get(target, prop, target);
return typeof value === "function" ? value.bind(target) : value;
},
has: (target, prop) => Object.prototype.hasOwnProperty.call(overlay, prop) || Reflect.has(target, prop),
});
return {
fs,
authoritative,
incomplete: () => records.map(({ op, detail }) => ({ op, detail })),
bound: (detail) => void records.push({ op: "bound", detail }),
adopt: (adopted) => void records.push(...adopted.map(({ op, detail }) => ({ op, detail }))),
};
}