@sema-agent/core
Version:
Stateless, task-oriented AI agent core
700 lines (699 loc) • 34.1 kB
JavaScript
import { CATCH_BUDGET_MS, createSelfBudget, POST_ABORT_GRACE_MS, RUNAWAY_AFTER_MS, unrefTimer, watchRunaway } from "./budget.js";
import { expandModPattern, isModEventName, MOD_SEATS, nextToRefusal, stationOn } from "./events.js";
import { ENGINE_ORIGIN, modsInvalid, screenModSeats, } from "./registration.js";
import { answerUpward, answerViolation, detachedCopy, engineObjectsOnce, handedOn, matcherMatches, matcherViolation, methodAnswerViolation, NEXT_IN_FLIGHT, receiveAnswer, receiveEvent, receivePayload, } from "./site-rules.js";
const TIER_RANK = { prepend: 0, user: 1, append: 2, builtin: 3, core: 4 };
const bypassed = (floors, tier) => floors.some((f) => TIER_RANK[f.from] < TIER_RANK[tier] && TIER_RANK[tier] < TIER_RANK[f.to]);
export async function admitMods(input) {
const report = safeReport(input.report);
const screened = screenModSeats(input.seats, input.side, (err) => report(err));
const mounted = [];
const records = [];
const describe = safeDescribe(input.describeThrown);
const bus = createBus(input.side, mounted, input.bottoms, report, records, describe, input.isProxy);
const admitted = Object.freeze({ admitted: true });
for (const cand of screened) {
if (input.signal?.aborted === true)
throw input.signal.reason;
const e = Object.freeze({
name: cand.name,
seat: cand.seat,
tier: cand.tier,
...(cand.provenance !== undefined ? { provenance: cand.provenance } : {}),
uses: Object.freeze({ events: cand.uses.events, calls: cand.uses.calls }),
});
const outcome = await bus.dispatch("plugin.register", e, {
bottom: () => admitted,
...(input.signal !== undefined ? { signal: input.signal } : {}),
checkAnswer: (a, judged, by) => a === admitted
? undefined
: refusalOf(a) === undefined
? "takes next(e) or { refuse: <reason> }"
: MOD_SEATS.indexOf(by.seat) > MOD_SEATS.findIndex((s) => s === judged["seat"])
? `a ${by.seat} registration may not refuse a ${String(judged["seat"])} registration`
: undefined,
});
if (outcome.kind === "aborted")
throw input.signal?.reason ?? new Error("admission aborted");
if (outcome.kind === "failed") {
records.push(Object.freeze({ name: cand.name, seat: cand.seat, tier: cand.tier, refusedBy: outcome.registration, reason: `${outcome.registration} failed: ${outcome.reason}` }));
continue;
}
const refused = refusalOf(outcome.answer);
if (refused !== undefined) {
records.push(Object.freeze({ name: cand.name, seat: cand.seat, tier: cand.tier, refusedBy: outcome.answeredBy ?? "engine", reason: refused }));
continue;
}
const own = mountOne(cand, input.side, describe);
mounted.push(...own);
const events = unique(own.map((h) => h.pattern));
const observe = unique(own.filter((h) => h.observe).map((h) => h.pattern));
records.push(Object.freeze({
name: cand.name,
seat: cand.seat,
tier: cand.tier,
events,
...(observe.length > 0 ? { observe } : {}),
...(outcome.skipped.length > 0 ? { skipped: outcome.skipped } : {}),
}));
}
return bus;
}
function refusalOf(a) {
if (typeof a !== "object" || a === null || !Object.prototype.hasOwnProperty.call(a, "refuse"))
return undefined;
const r = Reflect.get(a, "refuse");
return typeof r === "string" && r !== "" ? r : undefined;
}
function unique(xs) {
return Object.freeze([...new Set(xs)]);
}
function safeDescribe(describe) {
return (err) => {
try {
const text = describe(err);
if (typeof text === "string")
return text;
}
catch {
}
return "a value the host's renderer could not describe";
};
}
function safeReport(report) {
return (err, classification) => {
try {
report(err, classification);
}
catch {
}
};
}
function mountOne(cand, side, describe) {
const own = [];
let sealed = false;
let problem;
const fail = (why) => {
problem ??= why;
throw modsInvalid(`${cand.name}: ${why}`);
};
const on = (pattern, a, b, c) => {
if (sealed)
throw modsInvalid(`${cand.name}: on() was called after register() returned`);
const withMatcher = typeof a !== "function";
const fn = withMatcher ? b : a;
const opts = withMatcher ? c : b;
if (typeof fn !== "function")
fail(`on("${String(pattern)}") takes a handler function`);
if (withMatcher) {
const why = matcherViolation(a);
if (why !== undefined)
fail(`on("${String(pattern)}"): ${why}`);
}
const parsed = handlerOptions(opts);
if (typeof parsed === "string")
fail(`on("${String(pattern)}"): ${parsed}`);
const expanded = expandModPattern(pattern);
if ("refusal" in expanded)
return void fail(`on(): ${expanded.refusal}`);
const outside = expanded.names.filter((n) => !cand.eventsBound.has(n));
if (outside.length > 0)
fail(`on("${pattern}") selects ${outside.join(", ")}, outside its uses.events`);
const events = expanded.names.filter((n) => stationOn(n, side) !== undefined);
if (events.length === 0)
fail(`on("${pattern}"): no event it selects is raised on the ${side} bus in this version`);
if (typeof fn !== "function" || typeof parsed === "string")
return;
own.push({
reg: cand,
index: own.length,
pattern,
events: new Set(events),
...(withMatcher && isMatcher(a) ? { matcher: Object.freeze({ ...a }) } : {}),
fn: asHandler(fn),
...(parsed.onCatch !== undefined ? { onCatch: parsed.onCatch } : {}),
observe: parsed.observe,
});
};
let returned;
try {
returned = cand.registration.register(on, cand.registration.options);
}
catch (err) {
if (problem !== undefined)
throw modsInvalid(`${cand.name}: ${problem}`);
throw modsInvalid(`${cand.name}: register() threw: ${describe(err)}`);
}
finally {
sealed = true;
}
if (problem !== undefined)
throw modsInvalid(`${cand.name}: ${problem}`);
if (typeof returned === "object" && returned !== null && typeof Reflect.get(returned, "then") === "function") {
throw modsInvalid(`${cand.name}: register() returned a promise; register is synchronous (hang handlers with on() before it returns)`);
}
return own;
}
function isMatcher(v) {
return matcherViolation(v) === undefined;
}
function asHandler(fn) {
return (...args) => (typeof fn === "function" ? Reflect.apply(fn, undefined, args) : undefined);
}
function handlerOptions(opts) {
if (opts === undefined)
return { observe: false };
if (typeof opts !== "object" || opts === null)
return `options are { catch?, observe? }, not ${typeof opts}`;
for (const k of Object.keys(opts))
if (k !== "catch" && k !== "observe")
return `options are { catch?, observe? }; "${k}" is not one`;
const c = Reflect.get(opts, "catch");
const o = Reflect.get(opts, "observe");
if (c !== undefined && typeof c !== "function")
return "catch is a handler function";
if (o !== undefined && typeof o !== "boolean")
return "observe is true or false";
return { ...(c !== undefined ? { onCatch: asHandler(c) } : {}), observe: o === true };
}
const HA = "skipped; what is below it ran in its place";
const MA = "skipped; its last next() run's result stands";
function createBus(side, mounted, bottoms, report, records, describe, isProxy) {
const methods = [];
for (const name of Object.keys(bottoms)) {
if (!isModEventName(name) || bottoms[name] === undefined)
continue;
const st = stationOn(name, side);
if (st?.method === undefined)
continue;
const dot = name.indexOf(".");
methods.push({ event: name, ns: name.slice(0, dot), method: name.slice(dot + 1), pauses: st.method.pausesCallerBudget });
}
const bus = {
records,
mounted: () => Object.freeze(mounted.map((h) => Object.freeze({
plugin: h.reg.name,
seat: h.reg.seat,
pattern: h.pattern,
...(h.matcher !== undefined ? { matcher: h.matcher } : {}),
observe: h.observe,
caught: h.onCatch !== undefined,
}))),
hasHandlers: (event, participant) => mounted.some((h) => h.events.has(event) && admits(participant, h)),
dispatch: (event, e, options) => {
const st = stationOn(event, side);
const received = st === undefined ? { refusal: `${event} is not raised on the ${side} bus` } : receiveEvent(e);
if (st === undefined || "refusal" in received) {
const reason = `${event}: ${"refusal" in received ? received.refusal : "not raised"}`;
report(new Error(`engine: ${reason} — the dispatch was not run`));
return Promise.resolve(Object.freeze({ kind: "failed", registration: ENGINE_ORIGIN.plugin, cause: "violation", reason, skipped: Object.freeze([]) }));
}
return runDispatch(event, st, received.payload, options);
},
};
function participants(event, e, frames, participant) {
const inFrames = (fs, h) => fs.some((f) => f.plugin === h.reg.name && (f.kind === "dollar" || f.handler === h.index));
const caller = frames.slice(-1);
const above = frames.slice(0, -1);
const out = [];
for (const h of mounted) {
if (!h.events.has(event) || !admits(participant, h) || !matcherMatches(h.matcher, e))
continue;
if (inFrames(caller, h))
continue;
if (!inFrames(above, h))
out.push({ h, reentry: false });
else if (h.onCatch !== undefined && !h.observe)
out.push({ h, reentry: true });
}
return out;
}
async function callMethod(event, args, caller) {
const seat = bottoms[event];
if (seat === undefined)
throw new Error(`${caller.origin.plugin}: $.${event}: no implementation on the ${side} bus`);
const st = stationOn(event, side);
if (st === undefined)
throw new Error(`${caller.origin.plugin}: $.${event}: not raised on the ${side} bus`);
let e0 = args;
if (seat.enter !== undefined) {
const shaped = receivePayload(seat.enter(args), isProxy, engineObjectsOnce(args)());
if ("refusal" in shaped)
throw new TypeError(`${caller.origin.plugin}: $.${event}: ${shaped.refusal}`);
e0 = shaped.payload;
}
const outcome = await runDispatch(event, st, e0, {
bottom: async (e, ctx) => ({ value: await seat.run(e, ctx) }),
frames: caller.frames,
origin: caller.origin,
signal: caller.signal,
checkAnswer: methodAnswerViolation,
});
if (outcome.kind !== "aborted")
for (const s of outcome.skipped)
if (s.cause === "violation")
report(new Error(`${s.registration}: $.${event}: ${s.reason} — skipped`));
if (outcome.kind === "aborted")
throw new Error(`${caller.origin.plugin}: $.${event}: aborted`);
if (outcome.kind === "failed")
throw new Error(`${caller.origin.plugin}: $.${event}: ${outcome.reason}`);
const answer = outcome.answer;
const deny = typeof answer === "object" && answer !== null ? Reflect.get(answer, "deny") : undefined;
if (typeof deny === "string")
throw new Error(`${caller.origin.plugin}: $.${event}: ${deny}`);
return typeof answer === "object" && answer !== null ? Reflect.get(answer, "value") : undefined;
}
function dollarFor(reg, frames, budget, signal, engines) {
const origin = Object.freeze({ plugin: reg.name, tier: reg.tier });
const callerFrames = Object.freeze([...frames, Object.freeze({ kind: "dollar", plugin: reg.name })]);
const namespaces = new Map();
for (const m of methods) {
const ns = namespaces.get(m.ns) ?? {};
namespaces.set(m.ns, ns);
ns[m.method] = async (args) => {
if (!reg.callsBound.has(m.event))
throw new Error(`${reg.name}: $.${m.event}: not declared in uses.calls`);
const received = receivePayload(args === undefined ? {} : args, isProxy, engines());
if ("refusal" in received)
throw new TypeError(`${reg.name}: $.${m.event}: takes one object — ${received.refusal}`);
if (m.pauses)
budget.pause();
try {
return await callMethod(m.event, received.payload, { frames: callerFrames, origin, signal });
}
finally {
if (m.pauses)
budget.resume();
}
};
}
const out = {};
for (const [ns, fns] of namespaces)
out[ns] = Object.freeze(fns);
return Object.freeze({ ...out, plugin: Object.freeze({ name: reg.name }) });
}
function runDispatch(event, st, e0, options) {
const frames = options.frames ?? [];
const origin = options.origin ?? ENGINE_ORIGIN;
const all = participants(event, e0, frames, options.participant);
const observers = all.filter((p) => !p.reentry && p.h.observe).map((p) => p.h);
const chain = all.filter((p) => !p.h.observe).map((p) => p.h);
const reentered = new Set(all.filter((p) => p.reentry).map((p) => p.h));
const skipped = [];
const producers = new Map();
const live = new Set();
const dispatchAc = new AbortController();
const terminal = { kind: "terminal" };
let settled = false;
let graceTimer;
let resolveOut = () => { };
let rejectOut = () => { };
const out = new Promise((res, rej) => {
resolveOut = res;
rejectOut = rej;
});
const signal = options.signal;
const onAbort = () => {
if (settled)
return;
if (st.abort === "grace") {
graceTimer ??= setTimeout(() => finish({ kind: "aborted" }), POST_ABORT_GRACE_MS);
unrefTimer(graceTimer);
}
else
finish({ kind: "aborted" });
};
function finish(o) {
if (settled)
return;
settled = true;
signal?.removeEventListener("abort", onAbort);
if (graceTimer !== undefined)
clearTimeout(graceTimer);
const why = new Error(`the ${event} dispatch settled`);
if (!("kind" in o) || o.kind !== "answered")
dispatchAc.abort(why);
for (const ac of live)
ac.abort(why);
live.clear();
if ("reject" in o)
rejectOut(o.reject);
else
resolveOut(Object.freeze(o));
}
const pendingRuns = new Set();
const track = (run) => {
pendingRuns.add(run);
const drop = () => void pendingRuns.delete(run);
run.then(drop, drop);
};
const engines = engineObjectsOnce(e0);
const handOn = (passed) => {
if (passed === e0)
return { snap: e0 };
const handed = handedOn(st.pinned, e0, passed, engines(), isProxy);
return "violation" in handed ? handed : { snap: handed.payload };
};
const takeAnswer = (answer, s, e, h) => {
let taken = answer;
if (!s.answers.some((a) => Object.is(a, answer))) {
const received = receiveAnswer(answer, engines(), isProxy);
if ("refusal" in received)
return { violation: received.refusal };
taken = received.answer;
}
const below = s.pending > 0 ? [...s.answers, NEXT_IN_FLIGHT] : s.answers;
const why = answerViolation(taken, options.checkAnswer, e, answererOf(h), below);
return why !== undefined ? { violation: why } : { answer: taken };
};
const traceOf = (sink, index, plugin, tier, outcome, ms) => {
sink.push(Object.freeze({ index, plugin, tier, outcome, ms }));
};
function startBelow(state, selfTime, i, snap, nextFloors, myFrames) {
if (state.pending++ === 0)
selfTime.pause();
const below = [];
state.below = below;
const run = invoke(i + 1, snap, nextFloors, myFrames, below);
state.last = run;
const stopCounting = () => {
if (--state.pending === 0)
selfTime.resume();
};
run.then((v) => {
state.lastValue = { v };
state.answers.push(v);
stopCounting();
}, (err) => {
state.belowError = err;
stopCounting();
});
track(run);
return run;
}
async function invoke(i, e, floors, fr, sink) {
if (settled)
throw new Error(`the ${event} dispatch already settled`);
const h = chain[i];
if (h === undefined) {
const t0 = Date.now();
try {
const v = answerUpward(await options.bottom(e, Object.freeze({ frames: fr, signal: dispatchAc.signal, origin })));
traceOf(sink, i, "core", "core", "returned", Date.now() - t0);
return v;
}
catch (err) {
traceOf(sink, i, "core", "core", "rejected", Date.now() - t0);
throw err;
}
}
if (bypassed(floors, h.reg.tier)) {
traceOf(sink, i, h.reg.name, h.reg.tier, "bypassed", 0);
return invoke(i + 1, e, floors, fr, sink);
}
return runHandler(h, i, e, floors, fr, sink);
}
function makeNext(base, call, to, caught) {
const next = (e) => call(e);
Object.defineProperties(next, {
to: { value: to, enumerable: true },
origin: { value: origin, enumerable: true },
signal: { value: base.signal, enumerable: true },
trace: { get: base.trace, enumerable: true },
budget: { get: () => base.budget.reading(), enumerable: true },
...(caught !== undefined ? { error: { value: caught.error, enumerable: true }, called: { value: caught.called, enumerable: true } } : {}),
});
const frozen = Object.freeze(next);
if (!hasNextShape(frozen))
throw new TypeError("next is malformed");
return frozen;
}
async function runHandler(h, i, e, floors, fr, sink) {
const name = h.reg.name;
const ac = new AbortController();
live.add(ac);
const budget = createSelfBudget(h.reg.budgetMs, () => ac.abort(new Error(`${name} ran past its ${h.reg.budgetMs}ms budget`)));
const myFrames = Object.freeze([...fr, Object.freeze({ kind: "handler", plugin: name, handler: h.index })]);
const state = {
pending: 0,
called: false,
below: [],
answers: [],
done: false,
};
const descend = (passed, nextFloors) => {
if (state.done || settled)
return Promise.reject(new Error(`${name}: next() after it settled`));
if (state.called) {
state.violated ??= "next() already called (a handler calls next once; its first run's answer stands)";
return Promise.reject(new Error(`${name}: next() already called`));
}
const handed = handOn(passed);
if ("violation" in handed) {
state.violated ??= handed.violation;
return Promise.reject(new Error(`${name}: ${state.violated}`));
}
state.called = true;
return startBelow(state, budget, i, handed.snap, nextFloors, myFrames);
};
const to = (passed, tier) => {
const why = nextToRefusal(h.reg.tier, tier);
if (why !== undefined)
return Promise.reject(new Error(`${name}: ${why}`));
return descend(passed, [...floors, { from: h.reg.tier, to: tier }]);
};
let result;
let failure;
let handlerP = Promise.resolve();
if (reentered.has(h)) {
failure = { cause: "reentry", reason: "not run: the dispatch re-entered a frame it is part of" };
}
else {
const next = makeNext({ budget, signal: ac.signal, trace: () => Object.freeze([...state.below]) }, (x) => descend(x, floors), to);
const $ = dollarFor(h.reg, myFrames, budget, ac.signal, engines);
handlerP = invokeNow(() => h.fn($, e, next));
try {
const raced = await Promise.race([handlerP, budget.expired]);
if (raced === "expired" && budget.isExpired())
failure = { cause: "timeout", reason: `ran past its ${h.reg.budgetMs}ms budget` };
else {
const taken = takeAnswer(raced, state, e, h);
if ("violation" in taken)
failure = { cause: "violation", reason: state.violated ?? taken.violation };
else if (state.violated !== undefined)
failure = { cause: "violation", reason: state.violated };
else
result = taken.answer;
}
}
catch (err) {
failure = state.violated !== undefined ? { cause: "violation", reason: state.violated } : { cause: "threw", error: err, reason: `threw ${describe(err)}` };
}
}
state.done = true;
if (failure?.cause !== "timeout")
live.delete(ac);
const ms = budget.usedMs();
budget.clear();
if (failure === undefined) {
const passed = state.lastValue !== undefined && Object.is(state.lastValue.v, result);
if (!passed)
producers.set(result, name);
traceOf(sink, i, name, h.reg.tier, passed ? "passed" : "returned", ms);
sink.push(...state.below);
return result;
}
if (settled)
throw failure.error ?? new Error(`${name}: ${failure.reason}`);
if (failure.error === terminal || (failure.cause === "threw" && state.belowError !== undefined && failure.error === state.belowError && h.onCatch === undefined)) {
traceOf(sink, i, name, h.reg.tier, "rejected", ms);
throw failure.error;
}
if (failure.cause === "timeout") {
watchRunaway(handlerP, () => report(new Error(`${name}: ${event}: still running ${RUNAWAY_AFTER_MS}ms after its budget ran out; it ignores its signal`)));
}
const caught = h.onCatch !== undefined ? await runCatch(h, i, e, floors, myFrames, state, failure) : undefined;
if (caught !== undefined && "answer" in caught) {
if (failure.cause !== "violation" && failure.cause !== "reentry")
report(new Error(`${name}: ${event}: ${failure.reason}; its .catch answered`));
producers.set(caught.answer, name);
traceOf(sink, i, name, h.reg.tier, "caught", ms);
return caught.answer;
}
if (failure.cause === "threw" && state.belowError !== undefined && failure.error === state.belowError) {
traceOf(sink, i, name, h.reg.tier, "rejected", ms);
throw failure.error;
}
const reason = caught !== undefined ? `${failure.reason}; ${caught.problem}` : failure.reason;
if (st.failure === "refuse") {
if (failure.cause !== "violation")
report(new Error(`${name}: ${event}: ${reason} — failed closed: the dispatch ends here`));
traceOf(sink, i, name, h.reg.tier, "rejected", ms);
finish({ kind: "failed", registration: name, cause: failure.cause, reason, skipped: Object.freeze([...skipped]) });
throw terminal;
}
skipped.push(Object.freeze({ registration: name, cause: failure.cause, reason }));
const effect = state.last !== undefined ? MA : HA;
if (failure.cause !== "violation")
report(new Error(`${name}: ${event}: ${reason} — ${effect}`));
if (state.last !== undefined) {
traceOf(sink, i, name, h.reg.tier, failure.cause === "timeout" ? "expired" : "kept", ms);
return state.last;
}
traceOf(sink, i, name, h.reg.tier, failure.cause === "timeout" ? "expired" : "skipped", ms);
return invoke(i + 1, e, floors, fr, sink);
}
async function runCatch(h, i, e, floors, myFrames, state, failure) {
const onCatch = h.onCatch;
if (onCatch === undefined)
return { problem: "no .catch" };
const ac = new AbortController();
live.add(ac);
const budget = createSelfBudget(CATCH_BUDGET_MS, () => ac.abort(new Error(`${h.reg.name}: its .catch ran past its ${CATCH_BUDGET_MS}ms budget`)));
let done = false;
let violated;
const replay = (passed, nextFloors) => {
if (done || settled)
return Promise.reject(new Error(`${h.reg.name}: next() after its .catch settled`));
if (state.last !== undefined) {
const running = state.last;
budget.pause();
const resume = () => budget.resume();
running.then(resume, resume);
return running;
}
const handed = handOn(passed);
if ("violation" in handed) {
violated ??= handed.violation;
return Promise.reject(new Error(`${h.reg.name}: ${violated}`));
}
return startBelow(state, budget, i, handed.snap, nextFloors, myFrames);
};
const message = failure.cause === "threw" ? describe(failure.error) : failure.cause === "violation" ? failure.reason : undefined;
const error = Object.freeze({ kind: failure.cause, ...(message !== undefined ? { message } : {}), budget: CATCH_BUDGET_MS });
const next = makeNext({ budget, signal: ac.signal, trace: () => Object.freeze([...state.below]) }, (x) => replay(x, floors), (x, tier) => {
const why = nextToRefusal(h.reg.tier, tier);
return why !== undefined ? Promise.reject(new Error(`${h.reg.name}: ${why}`)) : replay(x, [...floors, { from: h.reg.tier, to: tier }]);
}, { error, called: state.called });
try {
const raced = await Promise.race([invokeNow(() => onCatch(dollarFor(h.reg, myFrames, budget, ac.signal, engines), e, next)), budget.expired]);
if (raced === "expired" && budget.isExpired())
return { problem: `its .catch ran past its ${CATCH_BUDGET_MS}ms budget` };
if (violated !== undefined)
return { problem: `its .catch ${violated}` };
const taken = takeAnswer(raced, state, e, h);
return "violation" in taken ? { problem: `its .catch ${taken.violation}` } : { answer: taken.answer };
}
catch (err) {
return { problem: violated !== undefined ? `its .catch: ${violated}` : `its .catch threw ${describe(err)}` };
}
finally {
done = true;
if (!budget.isExpired())
live.delete(ac);
budget.clear();
}
}
async function runObserver(h, fr) {
const name = h.reg.name;
const ac = new AbortController();
live.add(ac);
const budget = createSelfBudget(h.reg.budgetMs, () => ac.abort(new Error(`${name} ran past its ${h.reg.budgetMs}ms budget`)));
const myFrames = Object.freeze([...fr, Object.freeze({ kind: "handler", plugin: name, handler: h.index })]);
const refuse = () => Promise.reject(new Error(`${name}: an observe handler is not in the chain; next() is unavailable`));
const next = makeNext({ budget, signal: ac.signal, trace: () => Object.freeze([]) }, refuse, refuse);
const verdict = (r) => {
if (r === undefined)
return;
report(new Error(`${name}: ${event}: an observe handler returned a verdict — not adopted; an observe handler answers undefined`), "observational-hook-verdict-ignored");
};
try {
const raced = await Promise.race([invokeNow(() => h.fn(dollarFor(h.reg, myFrames, budget, ac.signal, engines), detachedCopy(e0), next)), budget.expired]);
if (raced === "expired" && budget.isExpired())
throw new Error(`ran past its ${h.reg.budgetMs}ms budget`);
verdict(raced);
}
catch (err) {
if (settled)
return;
report(new Error(`${name}: ${event}: an observe handler failed (${describe(err)}) — skipped`));
const onCatch = h.onCatch;
if (onCatch !== undefined) {
const cause = budget.isExpired() ? "timeout" : "threw";
budget.clear();
const cac = new AbortController();
live.add(cac);
const catchBudget = createSelfBudget(CATCH_BUDGET_MS, () => cac.abort(new Error(`${name}: its .catch ran past its ${CATCH_BUDGET_MS}ms budget`)));
const cnext = makeNext({ budget: catchBudget, signal: cac.signal, trace: () => Object.freeze([]) }, refuse, refuse, {
error: Object.freeze({ kind: cause, ...(cause === "threw" ? { message: describe(err) } : {}), budget: CATCH_BUDGET_MS }),
called: false,
});
try {
const caught = await Promise.race([invokeNow(() => onCatch(dollarFor(h.reg, myFrames, catchBudget, cac.signal, engines), detachedCopy(e0), cnext)), catchBudget.expired]);
if (!(caught === "expired" && catchBudget.isExpired()))
verdict(caught);
}
catch {
}
finally {
if (!catchBudget.isExpired())
live.delete(cac);
catchBudget.clear();
}
}
}
finally {
if (!budget.isExpired())
live.delete(ac);
budget.clear();
}
}
if (signal?.aborted === true && st.abort !== "grace") {
finish({ kind: "aborted" });
return out;
}
const root = [];
void (async () => {
for (const o of observers) {
if (settled)
return;
await runObserver(o, frames);
}
if (settled)
return;
const answer = await invoke(0, e0, [], frames, root);
while (st.failure === "refuse" && pendingRuns.size > 0 && !settled)
await Promise.allSettled([...pendingRuns]);
finish({ kind: "answered", answer, ...(producers.has(answer) ? { answeredBy: producers.get(answer) } : {}), skipped: Object.freeze([...skipped]) });
})().catch((err) => {
if (err === terminal || settled)
return;
finish({ reject: err });
});
if (signal !== undefined) {
if (signal.aborted)
queueMicrotask(onAbort);
else
signal.addEventListener("abort", onAbort, { once: true });
}
return out;
}
return bus;
}
function admits(participant, h) {
return participant === undefined || participant(Object.freeze({ plugin: h.reg.name, seat: h.reg.seat, observe: h.observe }));
}
function answererOf(h) {
return { plugin: h.reg.name, seat: h.reg.seat, tier: h.reg.tier };
}
function hasNextShape(f) {
return typeof f === "function" && "to" in f && "trace" in f && "budget" in f && "signal" in f && "origin" in f;
}
function invokeNow(f) {
try {
return Promise.resolve(f());
}
catch (err) {
return Promise.reject(err);
}
}