UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

80 lines (79 loc) • 2.36 kB
class Seat { sessionId; leg; holders = new Set(); constructor(sessionId) { this.sessionId = sessionId; } get current() { return this.leg?.current ?? "default"; } get observed() { return this.leg?.observed ?? "default"; } addHolder(holder, via, signal) { if (signal.aborted) return; const entry = { holder, via }; this.holders.add(entry); signal.addEventListener("abort", () => this.holders.delete(entry), { once: true }); } moveCeiling(affected, move) { const before = [...this.holders].filter((e) => affected(e.via)).map((e) => [e.holder, e.holder.receipt()]); move(); for (const [holder, receipt] of before) holder.ceilingRebound(receipt); } } class LegCeiling { leg; seat; live = true; constructor(leg, seat) { this.leg = leg; this.seat = seat; } get sessionId() { return this.seat.sessionId; } get current() { return this.live ? this.leg.current : this.seat.current; } get observed() { return this.live ? this.leg.observed : (this.seat.observed ?? this.seat.current); } hold(holder, signal) { this.seat.addHolder(holder, this, signal); } commit() { if (this.seat.leg === this.leg) return; this.seat.moveCeiling((via) => !via.live, () => (this.seat.leg = this.leg)); } end() { if (!this.live) return; this.seat.moveCeiling((via) => via === this, () => (this.live = false)); } } export class SessionModeSeats { seats = new Map(); reaper = new FinalizationRegistry(({ sessionId, ref }) => { if (this.seats.get(sessionId) === ref) this.seats.delete(sessionId); }); seatOf(sessionId) { const live = this.seats.get(sessionId)?.deref(); if (live !== undefined) return live; const seat = new Seat(sessionId); const ref = new WeakRef(seat); this.seats.set(sessionId, ref); this.reaper.register(seat, { sessionId, ref }); return seat; } legCeiling(sessionId, leg) { const ceiling = new LegCeiling(leg, this.seatOf(sessionId)); return { ceiling, commit: () => ceiling.commit(), end: () => ceiling.end() }; } }