@sema-agent/core
Version:
Stateless, task-oriented AI agent core
105 lines (104 loc) • 8.23 kB
TypeScript
import type { CrossSessionHoldCause } from "./cross-session-judge.js";
/** The in-process held buffer's capacity: a hold past this evicts the OLDEST entry as `expired` with a
* receipt to its sender (CC `Q=100`). Per recipient session. */
export declare const PEER_HELD_QUEUE_CAP = 100;
/** An idle subscription's time to live, on BOTH halves (CC `NRt`, 12 h): the target sweeps a
* subscriber older than this silently; the requester's own timer answers `expired` at the same age. */
export declare const PEER_IDLE_SUBSCRIPTION_TTL_MS = 43200000;
/** The target-side subscriber table's cap (CC `t0e`); a subscription past it answers `unavailable`. */
export declare const PEER_IDLE_SUBSCRIBER_TABLE_CAP = 32;
/** The requester-side outstanding table's cap (CC `t0e`, the `cap` send verdict). */
export declare const PEER_IDLE_OUTSTANDING_CAP = 32;
/** How many earlier outstanding subscriptions to the SAME target a requester keeps (CC `eor`). */
export declare const PEER_IDLE_PRIORS_KEPT = 3;
/** The idle-fire settle window: the target waits this long after going idle before it fires, so a
* turn that immediately continues does not announce a false idle (CC `gDn`). */
export declare const PEER_IDLE_FIRE_DEBOUNCE_MS = 750;
/** While the target holds peer messages for review it is NOT idle to a subscriber ("nothing queued"
* includes the held buffer): the fire is re-checked at this cadence (CC `yDn`). */
export declare const PEER_IDLE_HELD_BACKOFF_MS = 30000;
/** The idle notice's detail line cap (CC `R=100`). */
export declare const PEER_IDLE_LABEL_MAX = 100;
/** The `dialogExpiry` vocabulary (CC settings schema: `["60s","5m","10m","never"]`, default `"5m"`).
* How long a HELD cross-session message awaits approval before it resolves to its safe no-action
* default (expired, dropped WITH a receipt to the sender); `"never"` disables the deadline. */
export declare const CROSS_SESSION_DIALOG_EXPIRY_VALUES: readonly ["60s", "5m", "10m", "never"];
export type CrossSessionDialogExpiry = (typeof CROSS_SESSION_DIALOG_EXPIRY_VALUES)[number];
export declare const CROSS_SESSION_DIALOG_EXPIRY_DEFAULT: CrossSessionDialogExpiry;
export interface ResolvedCrossSessionDialogExpiry {
/** Milliseconds before a held message expires; `null` = `"never"` (no deadline). */
ms: number | null;
value: CrossSessionDialogExpiry;
/** `true` when the raw value was outside the vocabulary and the DEFAULT was applied — the caller
* MUST announce it (bad-value loudness: a garbage setting never silently reads as a policy). */
invalid: boolean;
}
/** Resolve a `dialogExpiry` value. `undefined`/`null`/`"default"` ⇒ the default (not invalid); a member
* ⇒ itself; anything else ⇒ the default WITH `invalid: true` so the caller can announce it. */
export declare function resolveCrossSessionDialogExpiry(raw: unknown): ResolvedCrossSessionDialogExpiry;
/** The hold causes a human REVIEW can resolve, and therefore the ones the `dialogExpiry` deadline is
* armed for (CC arms its dialog + deadline for exactly `mode-mismatch` / `no-mode-asserted`; the sema
* attestation-garbage arm is a review cause by its own sentence and joins them). Every other cause
* waits for a setting or mode change (CC form: "set it to accept", "once the session finishes
* starting up") and is re-judged at each drain round, never expired by clock. */
export declare const PEER_HELD_REVIEW_CAUSES: readonly CrossSessionHoldCause[];
/** The six terminal states a sender can be told about one of its messages (CC receipt states). */
export declare const PEER_DELIVERY_RECEIPT_STATES: readonly ["held", "denied", "expired", "delivered", "refused", "dropped"];
export type PeerDeliveryReceiptState = (typeof PEER_DELIVERY_RECEIPT_STATES)[number];
export declare function isPeerDeliveryReceiptState(v: unknown): v is PeerDeliveryReceiptState;
/**
* The drop reasons a `dropped` receipt may carry (CC vocabulary, kept verbatim — the recipient's ingress guard).
*
* `queue-full` is a member of the set but is NOT minted by this engine today: CC judges "recipient's queue
* is at its limit" on the recipient's ingress and reports it back as a dropped receipt, whereas here the
* SendMessage tool reads the recipient box's observable count at the send station and refuses synchronously
* (tool error code `queue_full`, nothing queued). The word stays so that renderers and ledgers keyed on this
* set remain aligned with CC and an ingress-side mint (two senders racing past the count) would need no
* vocabulary change. The approval-hold buffer overflowing is a different arm: the oldest held message is
* evicted with an `expired` receipt (see peer-held-queue).
*/
export declare const PEER_DROP_REASONS: readonly ["rate-limited", "duplicate", "hop-loop", "hop-runaway", "queue-full"];
export type PeerDropReason = (typeof PEER_DROP_REASONS)[number];
/** CC `ule` — the recipient suffix: unique non-empty labels, at most three named. */
export declare function peerRecipientSuffix(recipients: readonly string[]): string;
/**
* CC `y$e` — the model-face delivery receipt for the five non-drop states. `count` folds several
* receipts of one state into one line (the requester's drain may fold; a single record renders as 1).
*/
export declare function renderCrossSessionDeliveryNotice(state: Exclude<PeerDeliveryReceiptState, "dropped">, count: number, recipients?: readonly string[]): string;
/** CC `S$e` — the drop reasons, rendered. */
export declare function describePeerDropReasons(reasons: readonly (PeerDropReason | undefined)[]): string;
/** CC `b$e` — the model-face receipt for messages DROPPED at the recipient's ingress guard. */
export declare function renderCrossSessionDroppedNotice(count: number, recipients?: readonly string[], reasons?: readonly (PeerDropReason | undefined)[]): string;
/** The four idle-notice kinds (CC `ror` arms). `expired` is minted by the REQUESTER's own timer; the
* other three by the target's harness. */
export declare const PEER_IDLE_NOTICE_KINDS: readonly ["idle", "exited", "unavailable", "expired"];
export type PeerIdleNoticeKind = (typeof PEER_IDLE_NOTICE_KINDS)[number];
export declare function isPeerIdleNoticeKind(v: unknown): v is PeerIdleNoticeKind;
/** CC `M` — why a target is "not holding" a subscription (one sentence, four causes). */
export declare const PEER_IDLE_UNAVAILABLE_CAUSES = "it is shutting down, its subscription table is full, a newer subscription displaced this one, or it answered in a form this version does not recognize";
/**
* CC `nYt` — a label or detail line made safe for the notice text: format/control characters and the
* envelope-ish punctuation (`<>«»"[]`) become spaces, whitespace collapses, the notice's own prefix
* phrase cannot be smuggled in, and the result is capped at {@link PEER_IDLE_LABEL_MAX}. `undefined`
* when nothing printable is left.
*/
export declare function peerIdleNoticeLabel(raw: string): string | undefined;
export interface PeerIdleNoticeFields {
kind: PeerIdleNoticeKind;
/** The target's label as the requester knows it (already through {@link peerIdleNoticeLabel}). */
label: string;
/** `idle`/`exited`: when the target finished its turn (epoch ms). */
finishedAt?: number;
/** `idle` only: the target's one-line detail (already through {@link peerIdleNoticeLabel}). */
detail?: string;
}
/** CC `k` — a wall-clock time, HH:MM, 24-hour, in the reader's locale. */
export declare function formatPeerNoticeClock(epochMs: number | undefined): string;
/** CC `ror` — the model-face idle notice (the requester's model reads this as a user-frame line). */
export declare function renderCrossSessionIdleNotice(n: PeerIdleNoticeFields): string;
/** CC `iYt` (sema form) — the host-facing announcement that a peer subscribed to this session's idle.
* CC sends the one-line detail only to a pid-VERIFIED peer whose class passes parity; sema verifies no
* peer identity (§7), so by default NO detail is sent — a host that wires the `lastTurnText` seat
* opts its deployment in (the parity gate still applies), and the sentence says so. */
export declare function describePeerIdleSubscription(address: string): string;