@sema-agent/core
Version:
Stateless, task-oriented AI agent core
100 lines (99 loc) • 4.53 kB
JavaScript
const NO_NAMES = new Set();
export function heldAt(table, bound = NO_NAMES) {
return { start: (key) => table.stateOf(key), bound };
}
const ROOT_HOMES = ["/root", "/var/root"];
export function startedAt(later, at) {
if (at === undefined)
return later;
const fed = at.stdin !== undefined && at.stdin.length > 0 ? { ...later, stdin: at.stdin } : later;
const withFloors = at.floors === undefined || at.floors.size === 0 ? fed : { ...fed, inherited: { ...fed.inherited, floors: joinedFloors(fed.inherited.floors, at.floors) } };
const as = at.as;
if (as === undefined || as.home === "caller")
return withFloors;
const homes = as.name === "root" ? ROOT_HOMES : undefined;
const target = homes === undefined ? "unknown" : homes.map((spelled) => ({ spelled }));
const caller = later.initial("HOME");
const home = as.home === "target" ? target : caller === "unknown" || target === "unknown" ? "unknown" : [...caller, ...target];
return {
...withFloors,
initial: (name) => (name === "HOME" ? home : withFloors.initial(name)),
homeTouched: true,
...(as.login ? { bases: homes ?? "unmodelled" } : {}),
};
}
export function plannedOnce(plan) {
const planned = new Map();
return (text, kind, at) => {
const key = JSON.stringify([kind, text, [...(at?.floors ?? [])], at?.as, at?.stdin]);
if (!planned.has(key))
planned.set(key, plan(text, kind, at));
return planned.get(key);
};
}
function joinedFloors(a, b) {
const out = new Map(a);
for (const [name, floors] of b)
out.set(name, [...(out.get(name) ?? []), ...floors]);
return out;
}
export function stdinFeeds(segments, start, piped) {
const opener = [];
const enclosing = [];
const open = [];
segments.forEach((segment, si) => {
enclosing[si] = open.at(-1);
let opens = false;
for (const t of segment.tokens) {
if ((t.kind === "group" && t.op === "(") || (t.kind === "word" && t.raw === "{")) {
open.push(si);
opens = true;
}
else if ((t.kind === "group" && t.op === ")") || (t.kind === "word" && t.raw === "}"))
open.pop();
}
opener[si] = opens ? si : enclosing[si];
});
const fedAt = (si) => {
if (si > 0 && segments[si].connector === "|")
return [...new Map(piped(si).map((s) => [JSON.stringify(s), s])).values()];
const group = opener[si] !== si ? opener[si] : enclosing[si];
return group !== undefined ? fedAt(group) : start;
};
return fedAt;
}
export function rebasePlan(plan, from, to, floor) {
if (to !== "unmodelled" && to.length === 1 && to[0] === from)
return plan;
const fromSep = from.endsWith("/") || from.endsWith("\\") ? from : `${from}/`;
const moveInto = (into, b) => {
if (b === from)
return [...into];
if (b.startsWith(fromSep))
return into.map((t) => `${t.endsWith("/") || t.endsWith("\\") ? t : `${t}/`}${b.slice(fromSep.length)}`);
return [b];
};
const moveBase = (b) => (to === "unmodelled" ? [] : moveInto(to, b));
const floorAt = to === "unmodelled" ? floor : to;
const moveFloor = (bases, into) => [...new Set(bases.flatMap((b) => moveInto(into, b)))];
const moveCandidate = (c) => {
if (c.bases === "unmodelled")
return c.floorBases === undefined || floorAt === undefined ? c : { ...c, floorBases: moveFloor(c.floorBases, floorAt) };
if (c.bases.length === 0)
return c;
if (to === "unmodelled")
return floor === undefined ? { ...c, bases: "unmodelled" } : { ...c, bases: "unmodelled", floorBases: moveFloor(c.bases, floor) };
return { ...c, bases: [...new Set(c.bases.flatMap(moveBase))] };
};
return {
...plan,
segments: plan.segments.map((s) => ({
...s,
reads: s.reads.map(moveCandidate),
redirects: s.redirects.map((r) => (r.target === undefined ? r : { ...r, target: moveCandidate(r.target) })),
...(s.baseMove !== undefined ? { baseMove: { target: typeof s.baseMove.target === "string" ? s.baseMove.target : moveCandidate(s.baseMove.target) } } : {}),
bases: s.bases === "unmodelled" || to === "unmodelled" ? "unmodelled" : [...new Set(s.bases.flatMap(moveBase))],
nested: s.nested.map((n) => rebasePlan(n, from, to, floor)),
})),
};
}