/** * SDK-internal lifecycle events surfaced on the canonical `TaskEvent` iterator * and on `client.receive()`. * * These are NOT QAR envelope kinds — the `qar.client.*` namespace makes them * unambiguously SDK-side so a stray server-side discriminant can never collide * with one. They have no `message_id`, no `session_id`, no `payload` shape. * * The current set: `qar.client.reconnecting` / `qar.client.reconnected` * / `qar.client.reconnect_failed` for transport-loss recovery, plus * `qar.client.cancel_acked` synthesized from inbound `task.canceling` * envelopes so consumers can render the "cancel acknowledged, awaiting * terminal" intermediate state without expanding the `TaskEvent` * switch. `kind` is the stable forward-compatible discriminator. */ import type { TaskId } from './ids.js'; /** A reconnect attempt is about to fire. Emitted before the backoff sleep. */ export interface ClientReconnectingEvent { readonly kind: 'qar.client.reconnecting'; /** 1-based attempt counter — `1` is the first retry after the drop. */ readonly attempt: number; /** Delay in milliseconds before this attempt fires. */ readonly delayMs: number; /** Best-effort cause describing why we're reconnecting (close code, error message). */ readonly cause?: string; /** Safe, structured trigger category for progress and telemetry consumers. */ readonly trigger?: 'close' | 'error'; /** WebSocket close code when `trigger` is `close`. */ readonly closeCode?: number; /** Safe socket or HTTP status code when `trigger` is `error`. */ readonly errorCode?: string | number; } /** A reconnect attempt succeeded. Emitted after active task replay is attempted. */ export interface ClientReconnectedEvent { readonly kind: 'qar.client.reconnected'; /** 1-based attempt counter that succeeded. */ readonly attempt: number; /** Number of `task.resubscribe` wire-send attempts made on the new transport. */ readonly resubscribeAttempts?: number; } /** Reconnect attempts exhausted. Subscriptions error out after this. */ export interface ClientReconnectFailedEvent { readonly kind: 'qar.client.reconnect_failed'; /** Total attempts made before giving up — same as `ClientReconnectOptions.maxAttempts`. */ readonly attempts: number; /** Best-effort message from the last failed attempt. */ readonly lastError?: string; } /** * Cancellation acknowledged by the SDK. * * Synthesized one-to-one from an inbound `task.canceling` envelope on the * wire — the SDK converts the envelope's payload fields into this client * event before broadcasting to subscriptions. Surfaces on the canonical * `AsyncIterable` so a consumer waiting on the iterator can * render the "cancel ack received, waiting for terminal `task.done`" * intermediate state. * * Informational only — terminal status still arrives as `task.done * { status: 'canceled' | 'failed' }`. Do not branch business logic on * the pod identifiers; they're best-effort and may change between * deployments. * * Surfaced as a synthetic client event rather than a first-class * `TaskEvent` variant — keeps the consumer `switch (event.kind)` * surface stable; consumers who don't care about cancel-ack just don't * add the case. */ export interface ClientCancelAckedEvent { readonly kind: 'qar.client.cancel_acked'; /** Task whose cancellation was acknowledged (always populated). */ readonly task_id: TaskId; /** Pod that initially received the `task.cancel`. Opaque; advisory. */ readonly receivedByPod?: string; /** Pod that owns the task right now. Opaque; advisory. */ readonly owningPod?: string; /** Echo of the original `TaskCancelPayload.reason`, if any. */ readonly cancelReason?: string; /** Best-effort SLO hint for time until terminal `task.done` arrives. Advisory. */ readonly expectedTerminalWithinS?: number; } export type ClientEvent = ClientReconnectingEvent | ClientReconnectedEvent | ClientReconnectFailedEvent | ClientCancelAckedEvent; /** Discriminator literal type covering every `ClientEvent` variant. */ export type ClientEventKind = ClientEvent['kind']; /** * Type guard: `true` for `qar.client.*` synthetic events. * * Accepts `unknown` so JS callers (or callers feeding raw deserialized JSON) * can drop arbitrary values in without crashing on `null` / `undefined` / * primitives. Only objects with a string `kind` matching one of the * synthetic kinds return `true`. */ export declare function isClientEvent(value: unknown): value is ClientEvent; //# sourceMappingURL=clientEvents.d.ts.map