@sema-agent/core
Version:
Stateless, task-oriented AI agent core
189 lines (188 loc) • 7.67 kB
JavaScript
export const RECEIPT_FAULTS = Object.freeze(["proxy", "accessor", "hidden", "getter-threw", "prototype-moved", "not-data", "cycle", "too-deep", "uncopyable"]);
export function isPlainRecord(v) {
if (typeof v !== "object" || v === null || Array.isArray(v))
return false;
const proto = Object.getPrototypeOf(v);
return proto === Object.prototype || proto === null;
}
function isOrdinaryArray(v) {
return Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype;
}
export function receive(value, mode, held) {
const seen = new Map();
const path = [];
const open = new Set();
const heights = new Map();
const faults = [];
const refusedAt = new Map();
const stack = [];
const refusals = new Set();
const refuse = (kind) => {
const fault = Object.freeze({ kind, path: Object.freeze([...path]) });
refusals.add(fault);
throw fault;
};
const faultOf = (err) => typeof err === "object" && err !== null && refusals.has(err) ? err : Object.freeze({ kind: "uncopyable", path: Object.freeze([...path]) });
const other = (v, kind) => (mode.others === "as-is" ? v : refuse(kind));
const refuseContainer = (v, kind) => {
if (mode.contain === true) {
refusedAt.set(v, kind);
open.delete(v);
}
return refuse(kind);
};
const memberOf = (v, d) => {
if (Object.hasOwn(d, "value")) {
if (mode.accessors === "refuse" && d.enumerable !== true)
refuse("hidden");
return d.value;
}
if (mode.accessors === "refuse")
refuse("accessor");
const get = Object.hasOwn(d, "get") ? d.get : undefined;
try {
return get === undefined ? undefined : Reflect.apply(get, v, []);
}
catch {
return refuse("getter-threw");
}
};
const measured = mode.past === "refuse" || mode.others !== "as-is";
const heightOf = (v) => heights.get(v) ?? (open.has(v) || (held?.has(v) === true && mode.isProxy?.(v) !== true && (isOrdinaryArray(v) || isPlainRecord(v))) ? 1 : 0);
const pastDepth = (v, level) => measured && level + heightOf(v) > mode.depth;
const meet = (v, level) => {
if (v === null || v === undefined || typeof v === "string" || typeof v === "number" || typeof v === "boolean")
return v;
if (typeof v !== "object")
return other(v, "not-data");
if (held?.has(v) === true)
return pastDepth(v, level) ? refuse("too-deep") : v;
if (seen.has(v)) {
if (refusedAt.has(v))
return refuse(refusedAt.get(v));
if (open.has(v) && mode.others !== "as-is")
return refuse("cycle");
return pastDepth(v, level) ? refuse("too-deep") : seen.get(v);
}
if (level >= mode.depth && mode.past === "refuse") {
if (mode.isProxy?.(v) === true)
return refuse("proxy");
if (isOrdinaryArray(v) || isPlainRecord(v))
return refuse("too-deep");
}
if (level >= mode.depth)
return other(v, "too-deep");
if (mode.isProxy?.(v) === true)
return refuse("proxy");
const list = isOrdinaryArray(v) || (mode.others === "copy" && Array.isArray(v));
if (!list && !isPlainRecord(v) && mode.others !== "copy")
return other(v, "not-data");
const proto = Object.getPrototypeOf(v);
const captured = Object.getOwnPropertyDescriptors(v);
const out = list ? [] : {};
seen.set(v, out);
open.add(v);
if (mode.accessors === "refuse" && Object.getOwnPropertySymbols(captured).length > 0)
refuseContainer(v, "hidden");
stack.push({ v, out, list, proto, captured, keys: Object.getOwnPropertyNames(captured), level, next: 0, height: 1, key: "", member: undefined });
return out;
};
const land = (f, key, copy, member) => {
if (measured && typeof member === "object" && member !== null)
f.height = Math.max(f.height, heightOf(member) + 1);
Object.defineProperty(f.out, key, { value: copy, enumerable: true, writable: true, configurable: true });
path.length = f.level;
};
const finish = (f) => {
heights.set(f.v, f.height);
if (mode.accessors === "call-once" && mode.others !== "copy" && Object.getPrototypeOf(f.v) !== f.proto)
refuseContainer(f.v, "prototype-moved");
if (Array.isArray(f.out)) {
const length = f.captured["length"]?.value;
if (typeof length === "number")
f.out.length = length;
}
if (mode.freeze === true)
Object.freeze(f.out);
open.delete(f.v);
return f.out;
};
const received = (copy) => (mode.contain === true ? { ok: true, value: copy, faults: Object.freeze(faults) } : { ok: true, value: copy });
try {
const copy = meet(value, 0);
if (stack.length === 0)
return received(copy);
}
catch (err) {
return { ok: false, fault: faultOf(err) };
}
for (;;) {
const f = stack[stack.length - 1];
if (f.next < f.keys.length) {
const key = f.keys[f.next++];
if (f.list && key === "length")
continue;
path.push(key);
try {
const member = memberOf(f.v, f.captured[key]);
const frames = stack.length;
const copy = meet(member, f.level + 1);
if (stack.length > frames) {
f.key = key;
f.member = member;
}
else
land(f, key, copy, member);
}
catch (err) {
if (mode.contain !== true)
return { ok: false, fault: faultOf(err) };
faults.push(faultOf(err));
path.length = f.level;
}
continue;
}
let copy;
try {
copy = finish(f);
}
catch (err) {
stack.pop();
const holder = stack[stack.length - 1];
if (mode.contain !== true || holder === undefined)
return { ok: false, fault: faultOf(err) };
faults.push(faultOf(err));
path.length = holder.level;
continue;
}
stack.pop();
const holder = stack[stack.length - 1];
if (holder === undefined)
return received(copy);
land(holder, holder.key, copy, holder.member);
}
}
export const MODS_PAYLOAD_MODE = Object.freeze({ accessors: "refuse", depth: Infinity, others: "as-is", freeze: true });
export function describeFault(fault) {
const at = fault.path.length > 0 ? ` at ${fault.path.join(".")}` : "";
switch (fault.kind) {
case "proxy":
return `a Proxy${at}`;
case "accessor":
return `an accessor${at} (a getter is never run)`;
case "hidden":
return `a member that is not an enumerable data property${at}`;
case "getter-threw":
return `a getter that threw${at}`;
case "prototype-moved":
return `a prototype that moved while it was read${at}`;
case "not-data":
return `a value that is not data${at}`;
case "cycle":
return `a cycle${at}`;
case "too-deep":
return `a value nested too deep${at}`;
case "uncopyable":
return `a value that could not be copied whole${at}`;
}
}