import { modelProviderLabel } from '#src/core/modelLabel.js'; /** * TUI-C40 — the resting face, under the name the animation layer refers to it by. * * Every frame below is the same five lines and the same 16-column field, so swapping one in changes * nothing about the layout: the right column still starts at {@link RIGHT_COLUMN} and the * truncation budgets are untouched. That invariant is what makes an animation a data change rather * than a geometry change, and it is asserted per frame in the specs. */ export declare const RESTING_FACE: readonly [" ▄█▀▀▀▀▀▀▀▀█▄", "▄▀█▄█▀▀▀▀▀▀█▄█▀▄", "█ ▀█▄▀ ▀▄█▀ █", "▀▄▀▀ ██████ ▀▀▄▀", " ▀██████████▀"]; /** The animations a click can play. This list is the complete set. */ export declare const SLOTH_ANIMATIONS: readonly ['blink', 'nod', 'look-around', 'eyeroll']; export type SlothAnimation = (typeof SLOTH_ANIMATIONS)[number]; /** One frame of an animation and how long it stays on screen. */ export interface SlothAnimationStep { face: readonly string[]; holdMs: number; } /** * The four sequences, as the frames shown AFTER the resting face. * * Playback always settles back on {@link RESTING_FACE} once the last step's hold elapses, so no * sequence lists a trailing rest — but `nod` lists rest in the MIDDLE, because nodding twice means * returning to level between the two dips. None of them loops, and a click plays exactly one. */ export declare const SLOTH_ANIMATION_STEPS: Record; /** * Pick one animation at random. `random` is injectable so a test can pin the choice — the * production call passes nothing and gets `Math.random`. */ export declare function pickSlothAnimation(random?: () => number): SlothAnimation; /** * Blank columns prepended to every art row (TUI-C36). One column of left margin, so the block does * not sit flush against the edge of the terminal. */ export declare const LEFT_PAD = 1; /** * Column at which the right-hand column begins on EVERY row — the single number the whole layout * and the colour split are expressed in terms of (margin + face + gutter = 22). */ export declare const RIGHT_COLUMN: number; /** Column at which the version label begins on row 2 (right column + wordmark + gap = 44). */ export declare const VERSION_COLUMN: number; /** * Narrowest terminal that still gets the right column. The wordmark itself ends at column 40, so * anything narrower than this leaves no usable room for the fields beside it; below the threshold * the face prints alone (see the module docs on why wrapping is not an option). */ export declare const MIN_BANNER_COLUMNS: number; /** The live values the banner reports, plus the terminal geometry it has to fit inside. */ export interface LaunchBannerInput { /** Gaunt Sloth version, WITHOUT the `v` prefix (this module adds it). */ version?: string; /** `config.modelDisplayName`. */ model?: string; /** `config.modelProviderType`. */ provider?: string; /** * TUI-C74 — where the session IS: the working directory the agent's shell and file tools resolve * against (`getCurrentWorkDir()`), before the home-prefix collapse. Never the config root, which * is `projectDir` below and is an ancestor of this whenever the two differ. */ workDir?: string; /** * TUI-C74 — the directory of the DISCOVERED project config (`peekProjectDir()`), i.e. whose * guidelines, prompts and `.gsloth-settings` this session is running under. `undefined` when * discovery found no project config. Rendered on its own labelled row, and only when it differs * from `workDir` — see the module docs on why the common case stays one unlabelled row. */ projectDir?: string; /** The user's home dir; when a reported path sits under it the prefix collapses to `~`. */ homeDir?: string; /** Live `stdout.columns`; `undefined` (non-TTY / tests) falls back to `DEFAULT_COLUMNS`. */ columns?: number; /** Emit ANSI colour. Only {@link launchBannerText} reads this; Ink colours rows itself. */ colour?: boolean; /** * TUI-C40 — which face to draw. Defaults to {@link RESTING_FACE}, so every existing caller is * unaffected and a plain launch is byte-identical to before. An animation frame differs only in * these five lines: the geometry below reads the face's width from the constants, never from the * strings, so a swapped frame cannot move the right column or change a truncation budget. */ face?: readonly string[]; } /** * One rendered banner row, pre-split at {@link RIGHT_COLUMN} so each surface can colour the two * halves independently without re-deriving the geometry. */ export interface LaunchBannerRow { /** * Columns 0–21: the {@link LEFT_PAD} margin and the face, right-padded to {@link RIGHT_COLUMN} * when this row has right-hand content (and left unpadded when it does not, so no row ends in * trailing whitespace). Rendered in magenta — the margin is blank, so painting it is a no-op. * Empty on the two blank padding rows, which carry nothing at all. */ face: string; /** Columns 21+: wordmark, version, model/provider or a location. Default foreground, no colour. */ right: string; } /** * The shared `model (provider)` spelling, re-exported so this module stays the documented home of * the banner's fields. It lives in `modelLabel.ts` because the agent renders it too and must not * import this module's console/filesystem graph to do so. */ export { modelProviderLabel }; /** * Assemble the banner as {@link LaunchBannerRow}s: a blank row, the five art rows each pre-split at * {@link RIGHT_COLUMN}, and a blank row. Pure — every input arrives as an argument, so the geometry * is testable without a terminal, a config or a process. */ export declare function launchBannerRows(input: LaunchBannerInput): LaunchBannerRow[]; /** * Render the banner as one multi-line string for the plain (readline) surface. * * Colour is the 16-colour `magenta` slot from {@link ANSI_COLORS} — the SAME slot the rest of the * CLI uses — and never a 256-colour or 24-bit escape: the 16-colour slot picks up the violet from * the user's own terminal theme, so the sloth looks native in both light and dark schemes. The * right column carries no escape at all, not even dim. * * With `colour: false` the output contains ZERO escape sequences — not one dim wrapper, not one * reset — so a monochrome session (`useColour: false`) stays genuinely clean. The caller decides; * the plain surface passes `getUseColour()`, the TUI passes nothing and lets Ink's own * colour-support detection make the same call. */ export declare function launchBannerText(input: LaunchBannerInput): string; /** The process-resolved half of {@link LaunchBannerInput} — everything but the geometry. */ export type LaunchBannerFields = Pick; /** * Read the live fields off the process, so both surfaces report the same values from the same * sources instead of each picking its own. `model`/`provider` come from the caller because only it * has the resolved config (`config.modelDisplayName` / `config.modelProviderType`); the rest are * process-global. * * Fail-soft, as in `debugDump`: `getSlothVersion()` reads the installed `package.json` through the * install dir that the CLI entry point sets, and THROWS when nothing set it (an embedded caller, a * unit test). A missing version drops one label — it must never stop a session from starting. */ export declare function launchBannerFields(model?: string, provider?: string): LaunchBannerFields;