import * as dntShim from "../../../../../../_dnt.shims.js";
import type { FsFileWrapper, Path } from "../../../path/0.3.2/mod.js";
import { type ConsoleSize, type RenderInterval, type StaticTextContainer, type TextItem } from "../../../console-static-text/0.3.4/mod.js";
import { Buffer } from "../../../../@std/io/0.225.3/buffer.js";
import type { CommandBuilder, KillSignal } from "./command.js";
import type { ByteRingBuffer } from "./byteRingBuffer.js";
import { LineRingBuffer } from "./lineRingBuffer.js";
import type { Closer, Reader, ReaderSync, Writer, WriterSync } from "../../../../@std/io/0.225.3/types.js";
import type { CommandPipeWriter } from "./commandHandler.js";
export type { Closer, Reader, ReaderSync, Writer, WriterSync };
/**
 * Owns the static text scope and the list of active tail segments. A single
 * shared instance handles all `InheritTailWriter`s in the process so parallel
 * commands interleave into the same pinned region. Tests can construct
 * their own with a stand-in `StaticTextContainer` to assert on the emitted
 * ANSI bytes; pass `interval: null` to skip the periodic refresh and drive
 * `container.refresh()` manually.
 */
export declare class TailRenderer implements Disposable {
    #private;
    readonly container: StaticTextContainer;
    constructor(options?: {
        container?: StaticTextContainer;
        interval?: RenderInterval | null;
    });
    [Symbol.dispose](): void;
    /** @internal */
    register(seg: InheritTailState): void;
    /** @internal */
    unregister(seg: InheritTailState): void;
    /** @internal */
    logAbove(items: TextItem[]): void;
}
export type PipeReader = Reader | ReaderSync;
export type PipeWriter = Writer | WriterSync;
/** An awaitable that resolves to an object exposing a `readable` stream —
 * e.g. a `RequestBuilder` that resolves to a response with `.readable`. */
export interface AwaitableReadable {
    /** Resolves to an object that exposes a `ReadableStream<Uint8Array>` via
     * its `readable` property. */
    then<TResult1 = {
        readable: dntShim.ReadableStream<Uint8Array>;
    }, TResult2 = never>(onfulfilled?: ((value: {
        readable: dntShim.ReadableStream<Uint8Array>;
    }) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}
/** Behaviour to use for stdin.
 * @value "inherit" - Sends the stdin of the process to the shell (default).
 * @value "null" - Does not pipe or redirect the pipe.
 */
export type ShellPipeReaderKind = "inherit" | "null" | Reader | dntShim.ReadableStream<Uint8Array> | Uint8Array | CommandBuilder | FsFileWrapper | Path | AwaitableReadable;
/**
 * The behaviour to use for a shell pipe.
 * @value "inherit" - Sends the output directly to the current process' corresponding pipe (default).
 * @value "null" - Does not pipe or redirect the pipe.
 * @value "piped" - Captures the pipe without outputting.
 * @value "inheritPiped" - Captures the pipe with outputting.
 */
export type ShellPipeWriterKind = "inherit" | "null" | "piped" | "inheritPiped" | WriterSync | dntShim.WritableStream<Uint8Array> | FsFileWrapper | Path;
export declare class NullPipeReader implements Reader {
    read(_p: Uint8Array): Promise<number | null>;
}
export declare class NullPipeWriter implements WriterSync {
    writeSync(p: Uint8Array): number;
}
export declare class ShellPipeWriter {
    #private;
    constructor(kind: ShellPipeWriterKind, inner: PipeWriter);
    get kind(): ShellPipeWriterKind;
    get inner(): PipeWriter;
    write(p: Uint8Array): number | Promise<number>;
    writeAll(data: Uint8Array): void | Promise<void>;
    writeText(text: string): void | Promise<void>;
    writeLine(text: string): void | Promise<void>;
}
export declare class CapturingBufferWriter implements Writer {
    #private;
    constructor(innerWriter: Writer, buffer: Buffer);
    getBuffer(): Buffer;
    write(p: Uint8Array): Promise<number>;
}
export declare class CapturingBufferWriterSync implements WriterSync {
    #private;
    constructor(innerWriter: WriterSync, buffer: Buffer);
    getBuffer(): Buffer;
    writeSync(p: Uint8Array): number;
}
/** Async tap that mirrors writes into a {@link ByteRingBuffer} for use as
 * "errorTail" — the ring keeps the trailing N bytes of whatever the
 * command sent through this stream, so they can be surfaced in the thrown
 * `Error` even when the underlying sink (a piped command, a `WritableStream`,
 * a file on disk) doesn't expose what was written. Pairs with
 * {@link ErrorTailCaptureWriterSync}. */
export declare class ErrorTailCaptureWriter implements Writer {
    #private;
    readonly ring: ByteRingBuffer;
    constructor(innerWriter: Writer, ring: ByteRingBuffer);
    write(p: Uint8Array): Promise<number>;
}
/** Sync variant of {@link ErrorTailCaptureWriter}. */
export declare class ErrorTailCaptureWriterSync implements WriterSync {
    #private;
    readonly ring: ByteRingBuffer;
    constructor(innerWriter: WriterSync, ring: ByteRingBuffer);
    writeSync(p: Uint8Array): number;
}
export declare class InheritStaticTextBypassWriter implements WriterSync {
    #private;
    constructor(innerWriter: WriterSync);
    writeSync(p: Uint8Array): number;
    flush(): void;
}
/**
 * Default number of lines to show in `.tailDisplay()` mode. Docker Compose
 * shows a comparable-sized window; small enough not to dominate the terminal,
 * large enough to convey progress.
 */
export declare const DEFAULT_INHERIT_TAIL_LINES = 5;
/**
 * Default number of lines to retain for error-time flushback. On error the
 * live tail (5 lines) rarely shows what actually broke, so we keep a larger
 * buffer and promote it to scrollback when the command fails.
 */
export declare const DEFAULT_INHERIT_TAIL_ERROR_LINES = 80;
/** Context passed to a `TailMaxLines` callback at draw time. */
export interface TailMaxLinesContext {
    /** Current terminal size, or `undefined` if the host isn't a TTY. */
    size: ConsoleSize | undefined;
}
/** Total number of rows the tail occupies — header included — so two
 * commands tailing at `"50%"` each compose into a full screen instead of
 * spilling. When a header is shown the visible output count is `maxLines - 1`,
 * clamped to at least 1 row of output (so a headered tail is always at
 * least 2 rows total). Accepts:
 * - A literal `number`, taken as-is.
 * - A string like `"50%"`, resolved against the terminal's row count at draw
 *   time so the tail re-fits if the user resizes mid-run.
 * - A function called per draw — for cases neither form covers, e.g.
 *   `(ctx) => Math.min(10, (ctx.size?.rows ?? 24) - 5)` to leave headroom. */
export type TailMaxLines = number | `${number}%` | ((ctx: TailMaxLinesContext) => number);
/** Context passed to a `TailHeader` callback at draw time. */
export interface TailHeaderContext {
    /** The raw command text being run. */
    command: string;
    /** Current terminal size, or `undefined` if the host isn't a TTY. */
    size: ConsoleSize | undefined;
}
/** Header rendered above the live tail.
 * - `undefined` (default): `Running <command>` while running, `Ran <command>` in scrollback (when `printCommand()` is set).
 * - `false`: no header.
 * - `string`: rendered verbatim — you supply any styling.
 * - function: called per draw with `{ command, size }`; the result is rendered verbatim.
 *
 * Regardless of this setting, the error path still emits `> <command>` to
 * scrollback so failed commands stay unambiguous in logs. */
export type TailHeader = string | false | ((ctx: TailHeaderContext) => string);
/**
 * Construction-time options for `InheritTailWriter`. The user-facing
 * `.tailDisplay()` API maps onto this plus a few post-construction setters
 * for header/promote behavior.
 */
export interface InheritTailWriterOptions {
    /** Number of visible tail lines. See {@link TailMaxLines}.
     * @default 5
     */
    maxLines?: TailMaxLines;
    /** Treat the inner writer as TTY-attached. Defaults to `process.stderr.isTTY`.
     * When false, writes pass through to the inner writer untouched (no pinned
     * region) — used when the host process isn't a terminal. */
    isTty?: boolean;
    /** Renderer hosting the pinned scrolling region. Defaults to the global
     * one tied to `staticText` + `renderInterval`. Tests pass a custom
     * renderer to capture the emitted ANSI bytes in isolation. */
    renderer?: TailRenderer;
    /** Header text or per-draw callback (already pre-bound — accepts only
     * `{ size }`). Set in the constructor so the segment is fully labeled
     * before it gets registered with the renderer; otherwise the live area
     * could paint a header-less segment for one tick. */
    header?: string | ((ctx: {
        size: ConsoleSize | undefined;
    }) => string);
    /** When true, render `header` as-is (no `Running` / `Ran` framing). */
    headerVerbatim?: boolean;
    /** Always-shown command label on the error scrollback path, even when
     * `header` is hidden or customized. */
    errorHeader?: string;
    /** When true, promote the header to scrollback as `Ran <cmd>` (or the
     * verbatim header) on success — typically wired to `.printCommand()`. */
    promoteHeaderOnSuccess?: boolean;
}
/**
 * Default size of the per-stream error-context ring buffer. 8 KiB is enough
 * to capture the last few screens worth of output — large enough to convey
 * what went wrong without ballooning memory for long-running commands.
 */
export declare const DEFAULT_ERROR_TAIL_BYTES: number;
/**
 * Configuration for `.errorTail()`. When enabled, dax silently retains
 * the trailing N bytes of stdout and/or stderr and appends them to the
 * thrown `Error.message` if the command exits with a non-zero code.
 * Targets streams the user can't see — piped to another command,
 * redirected to a file, sent to a `WritableStream`, or discarded with
 * `"null"`. Streams routed to the terminal (`"inherit"` /
 * `"inheritPiped"`) are skipped since the bytes already reached the
 * user's scrollback.
 */
export interface ErrorTailOptions {
    /** Per-stream cap on retained bytes. Once exceeded, the oldest bytes
     * are dropped first.
     * @default 8192 (8 KiB) */
    maxBytes?: number;
    /** Capture the trailing bytes of stdout.
     * @default true */
    stdout?: boolean;
    /** Capture the trailing bytes of stderr.
     * @default true */
    stderr?: boolean;
    /** Capture stdout and stderr into a single interleaved buffer instead
     * of separate per-stream buffers. When true, the error message shows
     * output in the order it was written rather than grouped by stream.
     * @default false */
    combined?: boolean;
}
/**
 * Configuration for `.tailDisplay()`. Pass `true` to enable with defaults,
 * or an options object to customize.
 */
export interface TailDisplayOptions {
    /** Number of visible tail lines. See {@link TailMaxLines}.
     * @default 5
     */
    maxLines?: TailMaxLines;
    /** Header rendered above the live tail. See {@link TailHeader}. */
    header?: TailHeader;
}
/** Internal: a maxLines value normalized into a uniform per-draw callback,
 * so the renderer doesn't dispatch on type each tick. */
type ResolvedMaxLinesFn = (ctx: TailMaxLinesContext) => number;
/** Internal: a header value normalized into a uniform per-draw callback.
 * The user-facing `(ctx: TailHeaderContext) => string` is pre-bound with
 * the command text by command.ts before reaching state, so the renderer
 * (which only knows about `size`) can call it uniformly. */
type ResolvedHeaderFn = (ctx: {
    size: ConsoleSize | undefined;
}) => string;
declare class InheritTailState {
    #private;
    readonly resolveMaxLines: ResolvedMaxLinesFn;
    readonly lines: LineRingBuffer;
    readonly enabled: boolean;
    /** Per-draw callback that produces the header text. `undefined` means
     * "no header" (live tail renders no label). Percentages, raw strings and
     * user callbacks are all normalized into this single shape upstream. */
    headerFn: ResolvedHeaderFn | undefined;
    /** When true, the header is rendered verbatim instead of being framed
     * with the built-in `Running <text>` / `Ran <text>` styling. Set when
     * the user supplies a custom header string or function. */
    headerVerbatim: boolean;
    /** Always-present fallback shown on the error path, even if the live
     * header is hidden or customized — so error scrollback is unambiguous
     * about which command failed. */
    errorHeader: string | undefined;
    promoteHeaderOnSuccess: boolean;
    readonly renderer: TailRenderer;
    constructor(renderer: TailRenderer, maxLines: TailMaxLines, isTty: boolean, maxErrorLines?: number);
    get omittedLineCount(): number;
    /** Visible output rows after subtracting the header (if any) from the
     * total `maxLines` budget. Floors to 1 so a headered segment always shows
     * at least one line. */
    visibleLineCount(ctx: TailMaxLinesContext): number;
    addRef(): void;
    setHeader(header: string | ResolvedHeaderFn | undefined, options?: {
        verbatim?: boolean;
    }): void;
    appendLines(newLines: string[]): void;
    release(errored: boolean, trailing: string[]): void;
}
/**
 * Docker-style partial scrolling writer.
 *
 * Instead of streaming command output straight to the terminal, this buffers
 * output line-by-line and shows only the most recent `maxLines` lines inside
 * a static text scope pinned to the bottom of the terminal. When the command
 * finishes successfully, the scope is cleared (the header is promoted to
 * scrollback); on error the retained tail is flushed above so the user can
 * see what happened.
 *
 * Falls back to writing directly to `innerWriter` when the host process is
 * not attached to a TTY, since there's nowhere to anchor a scrolling region.
 *
 * Pass an existing writer as the second argument to share its scrolling
 * region — used internally when both stdout and stderr are tailed, so the
 * two streams interleave into one scroll area with a single header.
 */
export declare class InheritTailWriter implements WriterSync, Disposable {
    #private;
    constructor(innerWriter: WriterSync, options?: InheritTailWriterOptions);
    constructor(innerWriter: WriterSync, sibling: InheritTailWriter);
    /** Snapshot of the live tail (last visible-window retained lines, oldest
     * first). The visible-window size is `maxLines - 1` when a header is shown
     * (recomputed from the current console size for percentage / callback
     * `maxLines`). */
    get tailLines(): readonly string[];
    /** Number of completed lines that were dropped from the retained ring
     * buffer because its capacity is bounded. Rendered as
     * `...N lines omitted...` above the retained tail when the command fails. */
    get omittedLineCount(): number;
    /**
     * Sets a label rendered above the tail lines that identifies what this
     * scrolling region is showing. Accepts a literal string (collapsed to
     * a single line) or a per-draw callback that receives the current
     * `{ size }`. `undefined` removes the header. Long text is truncated to
     * the terminal width.
     *
     * When `options.verbatim` is true, the text is rendered as-is (no
     * built-in `Running` / `Ran` framing). Used by `.tailDisplay({ header })`
     * so the caller has full control over styling.
     */
    setHeader(header: string | ((ctx: {
        size: ConsoleSize | undefined;
    }) => string) | undefined, options?: {
        verbatim?: boolean;
    }): void;
    /**
     * Sets the command label preserved on the error scrollback path even
     * when the live header is hidden or customized — so `> <command>` is
     * always shown when a tailed command fails, regardless of `.tailDisplay`
     * header config.
     */
    setErrorHeader(text: string | undefined): void;
    /**
     * Controls whether the `Ran <command>` header is promoted to scrollback
     * on successful finalize. Defaults to `false` — on success the live tail
     * clears silently unless the caller opts in (command.ts enables it when
     * `.printCommand()` was set, so the command stays visible in scrollback).
     * The error-path header (`> <command>` + retained tail) is always emitted
     * regardless of this flag since it's diagnostic.
     */
    setPromoteHeaderOnSuccess(value: boolean): void;
    writeSync(p: Uint8Array): number;
    /**
     * Clears the scrolling region. Called on successful command completion.
     *
     * If a header was set it's promoted to scrollback via `logAbove` before
     * the scope is disposed, so "which commands ran" remains visible after
     * the transient tail clears. When multiple writers share a scope the
     * scope is only disposed once all of them have finalized.
     *
     * Any partial pending line is still passed to `release` so that — if a
     * sibling writer subsequently errors — the success side's last partial
     * line is preserved in the error scrollback. The success path itself
     * never renders trailing lines, so there's no visual cost when no
     * sibling errors.
     */
    finalize(): void;
    [Symbol.dispose](): void;
    /**
     * Promotes the header + retained tail above the static region before
     * clearing it. Called when the command errored so the user has visible
     * context. When multiple writers share a scope, any writer finalizing
     * for error causes the shared region to use the error path once all
     * writers have finalized.
     */
    finalizeForError(): void;
}
/**
 * Header rendered above the live tail while the command is in flight:
 * `Running <command>` in bold cyan.
 */
export declare function formatTailHeader(text: string, size: ConsoleSize | undefined): string;
/**
 * Past-tense header promoted to scrollback when a tailed command completes
 * successfully: `Ran <command>` in bold green.
 */
export declare function formatRanHeader(text: string, size: ConsoleSize | undefined): string;
export interface PipedBufferListener extends WriterSync, Closer {
    setError(err: Error): void;
}
export declare class PipedBuffer implements WriterSync {
    #private;
    constructor();
    getBuffer(): Buffer | undefined;
    setError(err: Error): void;
    close(): void;
    writeSync(p: Uint8Array): number;
    setListener(listener: PipedBufferListener): void;
}
export declare class PipeSequencePipe implements Reader, WriterSync {
    #private;
    close(): void;
    writeSync(p: Uint8Array): number;
    read(p: Uint8Array): Promise<number | null>;
}
export declare function pipeReaderToWritable(reader: Reader, writable: dntShim.WritableStream<Uint8Array>, signal: AbortSignal): Promise<void>;
export declare function pipeReadableToWriterSync(readable: dntShim.ReadableStream<Uint8Array>, writer: ShellPipeWriter | CommandPipeWriter, signal: AbortSignal | KillSignal): Promise<void>;
//# sourceMappingURL=pipes.d.ts.map