@sema-agent/core
Version:
Stateless, task-oriented AI agent core
66 lines (65 loc) • 2.93 kB
JavaScript
import { homeViewsOf } from "./read-deny-home.js";
export function movedReads(previous, again) {
const before = targetsByCandidate(previous);
const after = targetsByCandidate(again);
const changed = [];
for (const key of new Set([...before.keys(), ...after.keys()])) {
const b = before.get(key);
const a = after.get(key);
if (b !== undefined && a !== undefined && sameTargets(b.targets, a.targets))
continue;
changed.push(...(b?.reads ?? []), ...(a?.reads ?? []));
}
return changed.filter((r) => r.target !== undefined);
}
function targetsByCandidate(e) {
const out = new Map();
const walk = (p, at) => {
p.plan.segments.forEach((segment, si) => {
for (const r of p.reads.get(segment) ?? []) {
const c = r.candidate;
const key = [at, si, c.denyOnly === true ? "floor" : "read", c.provenance, c.spelled, String(c.expands), c.raw].join("\0");
const landing = out.get(key) ?? { targets: new Set(), reads: [] };
out.set(key, landing);
landing.reads.push(r);
if ((r.established === "canonical" || r.established === "expansion") && r.target !== undefined)
landing.targets.add(r.target);
}
segment.nested.forEach((n, ni) => {
const nested = p.nested.get(n);
if (nested !== undefined)
walk(nested, `${at}/${si}.${ni}`);
});
});
};
walk(e, "");
return out;
}
function sameTargets(a, b) {
return a.size === b.size && [...a].every((t) => b.has(t));
}
export async function withHomeViews(door, placed, established, signal) {
const views = homeViewsOf(door.fs, placed, signal);
const unread = [];
const place = async (p) => {
const reads = new Map();
for (const [segment, rs] of p.reads) {
const out = [];
for (const r of rs) {
const landed = r.target !== undefined && (r.established === "canonical" || r.established === "expansion");
const home = landed ? await views.of(r.target, r.node === "file" ? { leaf: "file" } : undefined) : {};
if (home.unread !== undefined && !unread.includes(home.unread))
unread.push(home.unread);
out.push(home.view === undefined || r.spellings.includes(home.view) ? r : { ...r, spellings: [...r.spellings, home.view] });
}
reads.set(segment, out);
}
const nested = new Map();
for (const [n, np] of p.nested)
nested.set(n, await place(np));
return { ...p, reads, nested };
};
const withViews = await place(established);
door.adopt(unread.map((p) => ({ op: "fileIdentity", detail: `"${p}" cannot be identified against the home directories` })));
return withViews;
}