@sema-agent/core
Version:
Stateless, task-oriented AI agent core
69 lines (68 loc) • 2.49 kB
JavaScript
export const MAX_LANDING_ADMISSION_ROUNDS = 4;
export class LandingsNeedAdmission extends Error {
landings;
constructor(landings) {
super("memory landings need admission");
this.landings = landings;
}
}
const landingKey = (l) => `${l.scope}\u0000${l.slug}`;
export function requireLandingsAdmitted(admitted, landings) {
const pending = landings.filter((l) => !admitted.has(landingKey(l)));
if (pending.length > 0)
throw new LandingsNeedAdmission(pending);
}
export function cutPerLanding(ops, evidence, shares, finalAccount) {
const cuts = [];
let open;
let opsAt = 0;
let evidenceAt = 0;
for (const s of shares) {
if (s.opsEnd > opsAt || s.evidenceEnd > evidenceAt) {
if (open === undefined)
cuts.push((open = { ops: [], evidence: [], account: finalAccount }));
open.ops.push(...ops.slice(opsAt, s.opsEnd));
open.evidence.push(...evidence.slice(evidenceAt, s.evidenceEnd));
opsAt = s.opsEnd;
evidenceAt = s.evidenceEnd;
}
if (s.landed !== undefined && open !== undefined) {
open.account = s.landed;
open = undefined;
}
}
const last = cuts[cuts.length - 1];
if (last !== undefined)
last.account = finalAccount;
return cuts;
}
export async function applyEachAlone(backend, patches, before) {
const report = { applied: [], conflicts: [] };
for (const p of patches) {
before();
const r = await backend.applyPatches([p]);
report.applied.push(...r.applied);
report.conflicts.push(...r.conflicts);
}
return report;
}
export async function admittingLandings(admit, run) {
if (admit === undefined)
return run(undefined);
const admitted = new Set();
for (let round = 0;; round++) {
try {
return await run(admitted);
}
catch (err) {
if (!(err instanceof LandingsNeedAdmission))
throw err;
if (round >= MAX_LANDING_ADMISSION_ROUNDS) {
throw Object.assign(new Error(`memory landings kept moving: ${err.landings.length} spelling(s) were still unadmitted after ${MAX_LANDING_ADMISSION_ROUNDS} rounds, nothing was written`), { code: "memory.landing_unstable" });
}
await admit(err.landings);
for (const l of err.landings)
admitted.add(landingKey(l));
}
}
}