import type { InboxTierDTO, IsoTime, NodeIdDTO } from './common.js'; /** One runtime card supplied by a caller: the runtime renders and escapes it * exactly once, so a caller cannot emit a malformed card or smuggle markup * into one. `kind` must be namespaced (contain `:`) — bare kinds are * crouter's own closed vocabulary. */ export interface RuntimeCardRequest { kind: string; facts?: Record; /** Data, not markup. */ body?: string; } /** `POST /v1/nodes/{id}/messages` body. */ export interface SendMessageRequest { body: string; tier?: InboxTierDTO; /** Sender node id for feed attribution (the CLI resolves `CRTR_NODE_ID`; * the daemon has no ambient caller identity). Absent → an external/human * caller (`from: null`). */ from?: NodeIdDTO | null; /** Revive with no inbox entry (`--fresh` → `reviveNode({ resume: false })`). */ fresh?: boolean; /** Before delivery, make the target resident and clear its finalization latch * when present (`--reopen`). Accepted for both durable and interactive * delivery; `--fresh` retains its separate finalized-only gate. */ reopen?: boolean; /** Hidden ambient context upserted onto the target's sidecar as a * `situational` card, never visible chat (`--situational-context`). * Immediate only; valid alone (no body). Prose only — its body is NOT * escaped; a caller with untrusted text uses `situational_card`. */ situational_context?: string; /** A runtime card that REPLACES the target's situational sidecar, delivered * ahead of the body in the same turn and re-stated by the session-start * bearings after a context refresh. Mutually exclusive with * `situational_context`; valid alone (no body) on the durable path. */ situational_card?: RuntimeCardRequest; /** One-shot runtime cards for this turn only — never persisted. Delivered in * array order, after `situational_card` and ahead of the body. */ context_cards?: RuntimeCardRequest[]; /** Raw JSON-schema string installing a one-off output schema before delivery * (`--output-schema`); the target answers with `crtr push result`. Immediate only. */ output_schema?: string; /** `'interactive'`: deliver via the target's LIVE broker engine (prompt/steer * on its one serialized frame loop — the same ordering a tmux viewer gets) * instead of the durable inbox; a dormant or mid-revive target falls back to * the durable inbox + revive (watcher delivers post-boot). Plain immediate * body only — rejected with fresh/situational_context/output_schema or tier * 'deferred'. Runtime cards and reopen ARE accepted: a * card-bearing send is an ordinary human send that happens to carry context, * and the live deliver frame places the cards ahead of the body in one turn. * Absent → durable inbox (unchanged). */ delivery?: 'interactive'; } /** Result of an immediate message send. */ export interface MessageResultDTO { node_id: NodeIdDTO; /** Whether an inbox entry was appended now. */ delivered: boolean; /** Whether this request synchronously launched the target. Ordinary durable * delivery to an active or idle dormant target always reports false: the * lifecycle reconciler launches it from the durable inbox entry later. */ revived: boolean; /** Present only when this request attempted a synchronous wake and no broker * slot was free. The target's row is frozen and the daemon relaunches it * when one frees; the entry was durably appended either way. */ not_revived_reason?: 'capacity_frozen'; /** Present only when the entry was appended ABOVE the requested tier: a * terminal target never takes the later cycle `normal`/`deferred` wait for, * so its mail is raised to the steering tier. */ delivered_tier?: InboxTierDTO; delivered_at?: IsoTime; /** Which channel a `delivery:'interactive'` send actually used: `'engine'` * (live broker frame loop, no inbox entry) or `'inbox'` (durable fallback). * Absent for non-interactive sends. */ delivered_via?: 'engine' | 'inbox'; } /** `POST /v1/nodes/{id}/interrupt` result — the human Esc, first-class. Cancels * pending undelivered human-send inbox entries FIRST, then aborts a live * in-flight turn; a dormant target is NEVER revived. */ export interface InterruptResultDTO { node_id: NodeIdDTO; /** Primary outcome: `aborted_turn` wins over `canceled_pending` over `idle` * (abort + cancel can co-occur; the flags below carry the full picture). */ outcome: 'aborted_turn' | 'canceled_pending' | 'idle'; /** True when a live in-flight turn (or `!` bash run) was actually aborted. */ aborted_turn: boolean; /** How many pending undelivered human-send inbox entries were canceled. */ canceled_pending: number; }