UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

92 lines (91 loc) • 2.41 kB
import { thrownText } from "./thrown-value.js"; function containedError(thrown) { try { if (thrown instanceof Error && typeof thrown.message === "string") return thrown; return new Error(String(thrown)); } catch { return new Error(`a thrown value of type ${typeof thrown} that cannot be inspected or converted to text`); } } export function safeErrorMessage(error) { try { const m = error?.message; if (typeof m === "string") return m; return thrownText(error); } catch { return "a failure whose message could not be read"; } } export function createSafeNotifier(opts) { const onError = opts?.onError; let sites; let total = 0; const record = (site, thrown) => { const error = containedError(thrown); total += 1; if (sites === undefined) sites = new Map(); const state = sites.get(site); if (state !== undefined) { state.count += 1; state.last = error; return; } sites.set(site, { count: 1, last: error }); if (onError === undefined) return; try { onError({ site, error, failures: 1 }); } catch { } }; return { notify(run, site) { try { run(); return true; } catch (e) { record(site, e); return false; } }, async notifyAsync(run, site) { try { await run(); return true; } catch (e) { record(site, e); return false; } }, get failures() { return total; }, failuresAt(site) { return sites?.get(site)?.count ?? 0; }, lastErrorAt(site) { return sites?.get(site)?.last; }, failedSites() { return sites === undefined ? [] : [...sites.keys()]; }, }; } export function observeThenableRejection(r, notifier, site) { if (typeof r?.then === "function") { r.then(undefined, (err) => { const error = containedError(err); notifier.notify(() => { throw error; }, site); }); } }