/**
 * outbox — the one owner of buffered, timed, serialized delivery for the
 * batching sinks in this folder: `file`, `cloudwatch` (and `agentcore`, which
 * is built on it) and `xray`.
 *
 * A sink accepts items on its hot path (sync, no I/O) and hands them here. The
 * outbox decides WHEN a batch leaves and makes sure only one leaves at a time:
 *
 *   - **One queue, every trigger.** The size trigger, the timer and `drain()`
 *     (the sink's `flush()`, and so every shutdown) all queue a delivery on
 *     the same promise chain. Nothing calls `deliver` any other way.
 *   - **One delivery in flight.** A delivery starts only after the previous
 *     one settled. A large `fs.promises.appendFile` is several `write()`s; two
 *     of them interleaved tear NDJSON lines (reported in #223, where the timer
 *     bypassed the chain). Whatever a sink does around its write — the file
 *     sink's rotation — runs inside its delivery, so it can never be skipped
 *     or reordered either. This keeps ONE sink's deliveries from interleaving;
 *     it does not make a delivery atomic (a disk that fails partway through an
 *     append can still leave part of it behind).
 *   - **Oldest first, within the receiver's limits.** A delivery takes the
 *     oldest waiting items, so items leave in the order they were accepted.
 *     When a receiving service limits one request (`maxItemsPerDelivery`,
 *     `maxBytesPerDelivery` — CloudWatch's PutLogEvents), a delivery takes
 *     only the oldest items that fit, and the rest go in the next delivery,
 *     right after. That matters BECAUSE of the queue: a slow delivery lets a
 *     backlog build behind it, which one request may not be allowed to carry.
 *     Each part settles on its own — shipped, or dropped and reported.
 *   - **`drain()` is bounded.** It resolves once every item accepted BEFORE
 *     the call has settled (delivered, or dropped and reported), one the timer
 *     already had in flight included — then makes one sweep of what arrived
 *     while it waited. It never chases a producer that keeps emitting: under
 *     steady traffic it ends after about two deliveries.
 *   - **A failed batch is dropped and reported once**, then the next batch
 *     goes. It is never requeued, so a full disk or an outage cannot grow the
 *     outbox. The queue never rejects: a failure report that itself throws is
 *     said on the console instead of becoming an unhandled rejection.
 *
 * What it does NOT do: bound a delivery that never settles. A hung disk holds
 * the queue, and `drain()` with it; nothing can cancel an in-flight write.
 *
 * Role: leaf helper for `adapters/observability/*`. Composed as a field,
 * never inherited.
 */
/** What a sink tells its outbox. */
export interface OutboxOptions<T> {
    /** The sink's name: it prefixes a refused option and the console line when
     *  a failure report throws. */
    readonly name: string;
    /** Size trigger: deliver once `waiting >= maxItems`. Compared as given —
     *  the meaning each sink's option had before the outbox, so no value that
     *  worked is refused: `0` or a negative number triggers on every item,
     *  `2.5` on the third, `NaN` or `Infinity` never (then only the byte
     *  trigger, the timer and `drain()` deliver). It never limits what a
     *  delivery takes. */
    readonly maxItems: number;
    /** Size trigger: deliver once `waitingBytes >= maxBytes`, compared as
     *  given. Omitted → no byte trigger. */
    readonly maxBytes?: number;
    /** Most items one delivery takes: a positive whole number — a sink maps its
     *  own option to one first, and refuses by its own name what cannot map.
     *  Omitted → everything waiting. */
    readonly maxItemsPerDelivery?: number;
    /** Most bytes one delivery may carry, as the receiving service counts them:
     *  for each item, the `bytes` it was added with plus `overheadBytesPerItem`.
     *  A delivery always takes at least one item, so an item too large for any
     *  delivery still goes — alone — and the service's answer decides it.
     *  Omitted → no byte limit. */
    readonly maxBytesPerDelivery?: number;
    /** Bytes the receiving service adds to each item it counts (CloudWatch
     *  Logs: 26 per event). Default 0. */
    readonly overheadBytesPerItem?: number;
    /** Timer trigger for sparse traffic, in ms. `0` disables it: only the size
     *  trigger and `drain()` deliver. */
    readonly flushIntervalMs: number;
    /** Does an armed timer keep the process alive? Each sink decides: the file
     *  sink says no (a local write is never worth holding a process open for),
     *  the network sinks say yes (an un-stopped one lingers up to
     *  `flushIntervalMs` so its timer can still ship the tail). */
    readonly timerHoldsProcess: boolean;
    /** Ship one batch. Never called while another call is still in flight. */
    readonly deliver: (batch: readonly T[]) => Promise<void>;
    /** Describe a batch `deliver` failed to ship — the report it is dropped
     *  with. */
    readonly dropped: (batch: readonly T[], cause: unknown) => Error;
    /** Where that report goes. Read at call time by the sink, so a consumer
     *  who assigns `_onError` after construction still receives it. */
    readonly report: (error: Error) => void;
}
/** The three things a sink does with its outbox. */
export interface Outbox<T> {
    /** Accept one item. Sync, never throws, never does I/O. `bytes` counts
     *  toward the byte trigger. Accepting is the SINK's decision — the outbox
     *  takes what it is given, including after `stop()`. */
    add(item: T, bytes?: number): void;
    /** Settle everything accepted before this call — behind whatever is in
     *  flight — then sweep once what arrived meanwhile. Never rejects. */
    drain(): Promise<void>;
    /** Cancel the timer and arm no new one. Discards nothing: `drain()`
     *  afterwards still delivers what was accepted. */
    stop(): void;
}
/** Build the outbox one sink owns. A per-delivery cap that could take
 *  nothing is refused: such a delivery could never finish a drain. */
export declare function createOutbox<T>(opts: OutboxOptions<T>): Outbox<T>;
//# sourceMappingURL=outbox.d.ts.map