/** * Pure protocol constants, frame parsing, and byte-safe line framing for local diffusion backends. * * @remarks * The line framer is **byte-oriented**: it retains raw bytes (never a decoded string), enforces the * `maxLineBytes` cap while consuming input (so an unbounded no-newline write cannot balloon memory), * discards the remainder of an over-sized physical line up to its next newline before resuming, and * decodes each bounded, complete line with a fatal UTF-8 decoder (invalid encoding → a `malformed` * frame, never a silent mis-parse). {@link parseFrame} is total — it classifies every line as a typed * frame and never throws. * * @module @nhtio/adk/batteries/generation/local_diffusion/protocol */ /** The configurable wire tags used by a local diffusion backend. */ export type ProtocolConfig = { /** Leading tag on every host→backend command line (DiffusionBee: `b2py`). */ commandPrefix: string; /** Leading tag on every backend→host event line (DiffusionBee: `sdbk`). */ eventPrefix: string; /** Operation sub-tags for the two request commands. */ ops: { /** text→image generate op sub-tag (DiffusionBee: `t2im`). */ generate: string; /** image+text→image edit op sub-tag (DiffusionBee: `im2im`). */ edit: string; }; /** Control-command sub-tags (no request payload). */ control: { /** Advisory cancel of the current request (DiffusionBee: `__stop__`). */ stop: string; /** Graceful backend shutdown request (DiffusionBee: `__shutdown__`). */ shutdown: string; }; /** Backend→host event sub-tags. */ events: { /** Startup model-load progress event (DiffusionBee: `mdld`). */ modelLoad: string; /** Backend-ready event that resolves preload (DiffusionBee: `rdy`). */ ready: string; /** Per-step generation progress event (DiffusionBee: `dnpr`). */ progress: string; /** One finished image result event (DiffusionBee: `nwim`). */ image: string; /** Request-complete terminal event (DiffusionBee: `done`). */ done: string; /** Request-error terminal event (DiffusionBee: `err`). */ error: string; }; }; /** The DiffusionBee-compatible default local diffusion protocol configuration. */ export declare const DEFAULT_PROTOCOL: ProtocolConfig; /** A parsed startup model-loading progress frame. */ export type ModelLoadFrame = { /** Discriminant. */ kind: 'modelLoad'; /** Normalized model-load progress in `0..1`. */ progress: number; }; /** A parsed backend-ready frame. */ export type ReadyFrame = { /** Discriminant. */ kind: 'ready'; }; /** A parsed request progress frame. */ export type ProgressFrame = { /** Discriminant. */ kind: 'progress'; /** The request id this progress belongs to. */ rid: number; /** Normalized per-step generation progress in `0..1`. */ progress: number; }; /** A parsed image result frame. */ export type ImageFrame = { /** Discriminant. */ kind: 'image'; /** The request id this image belongs to. */ rid: number; /** The image payload: either an inline base64 blob or a backend-written file path, plus its MIME. */ payload: { /** Backend-written output file path (mutually exclusive with `b64`). */ path?: string; /** Inline base64-encoded image bytes (mutually exclusive with `path`). */ b64?: string; /** Concrete image MIME type, e.g. `image/png`. */ mimeType: string; }; }; /** A parsed request completion frame. */ export type DoneFrame = { /** Discriminant. */ kind: 'done'; /** The request id that completed. */ rid: number; }; /** A parsed request error frame. */ export type ErrorFrame = { /** Discriminant. */ kind: 'error'; /** The request id that errored. */ rid: number; /** The backend-reported error message. */ message: string; }; /** A frame with a tag this protocol version does not understand. */ export type UnknownFrame = { /** Discriminant. */ kind: 'unknown'; /** The original, unrecognized line. */ raw: string; }; /** A prefix-matched frame whose fields or JSON do not satisfy the protocol. */ export type MalformedFrame = { /** Discriminant. */ kind: 'malformed'; /** The original line that failed validation (best-effort, lossy decode for invalid UTF-8). */ raw: string; /** Why the line was rejected. */ detail: string; }; /** A stream-level protocol problem, such as an over-sized line. */ export type ProtocolErrorFrame = { /** Discriminant. */ kind: 'protocolError'; /** Why the stream framing failed. */ detail: string; }; /** The total, discriminated result of parsing one backend stdout line. */ export type ParsedFrame = ModelLoadFrame | ReadyFrame | ProgressFrame | ImageFrame | DoneFrame | ErrorFrame | UnknownFrame | MalformedFrame | ProtocolErrorFrame; /** * Parse one already-split backend stdout line into a typed {@link ParsedFrame}. Total by contract — * it never throws: malformed input yields a `malformed`/`unknown` frame, and a runtime-invalid or * hostile `config` (null, partial, or a throwing accessor) is caught and reported as `malformed`. * * @param line - One already-newline-split backend stdout line. * @param config - Protocol tag configuration; defaults to {@link DEFAULT_PROTOCOL}. * @returns The discriminated parse result. */ export declare const parseFrame: (line: string, config?: ProtocolConfig) => ParsedFrame; /** Build a generate command frame, including its terminating newline. */ export declare const buildGenerateCommand: (rid: number, args: Record, config?: ProtocolConfig) => string; /** Build an edit command frame, including its terminating newline. */ export declare const buildEditCommand: (rid: number, args: Record, config?: ProtocolConfig) => string; /** Build a best-effort stop command frame, including its terminating newline. */ export declare const buildStopCommand: (rid: number, config?: ProtocolConfig) => string; /** Build a backend shutdown command frame, including its terminating newline. */ export declare const buildShutdownCommand: (config?: ProtocolConfig) => string; /** * Create an incremental, **byte-oriented** line reader. Raw bytes are retained (never a decoded * string), the `maxLineBytes` cap is enforced while consuming so an unbounded no-newline write cannot * balloon memory, an over-sized physical line reports exactly one `protocolError` and is then discarded * through its next newline (its continuation is NOT re-parsed as a fresh frame), and each bounded, * complete line is decoded with a fatal UTF-8 decoder — invalid encoding yields a `malformed` frame. * Malformed protocol lines are reported as `malformed` rather than thrown. * * Pending bytes of an in-progress line are held as a queue of chunk SEGMENTS with a running byte * count, and concatenated exactly once when the line's terminator arrives — so many small fragments of * one line cost O(line length) total, not O(line length²) (terra v2 #4). * * @throws RangeError if `maxLineBytes` is provided but is not a positive, finite, safe integer — an * unvalidated `Infinity`/`NaN`/negative would silently defeat the bounded-memory guarantee (terra v2 #3). */ export declare const createFrameReader: (opts: { onFrame(frame: ParsedFrame): void; config?: ProtocolConfig; maxLineBytes?: number; }) => { push(chunk: Uint8Array): void; end(): void; };