import type { JobWidgetView } from "@oh-my-pi/pi-tui/tools/job-widget"; import { type JobWidgetAgg, type JobWidgetSampleLines, type JobWidgetSpec } from "./spec.js"; import { type JobTextSource } from "./types.js"; /** Longest line kept; longer lines are cut. */ export declare const MAX_LINE_CHARS = 4096; /** Points a spark draws after downsampling. */ export declare const SPARK_POINTS = 48; /** Window of `rate` and lines/s. */ export declare const RATE_WINDOW_MS = 60000; /** Complete lines a {@link SourceLineReader} read, and whether the source may grow. */ export interface SourceLines { lines: string[]; open: boolean; /** Offset just past the read text (the source's size so far). */ end: number; } /** * Reads one source between refreshes: keeps a cursor, carries the trailing * partial line to the next read, turns CR/CRLF into line breaks, strips ANSI * and control characters, and cuts lines at {@link MAX_LINE_CHARS}. When the * source dropped text the reader never saw, the torn line at the gap is * skipped so no rule reads half a line. */ export declare class SourceLineReader { #private; readonly source: JobTextSource; constructor(source: JobTextSource); /** New complete lines; `flush` also ends the line in progress (the source closed or the job settled). */ read(flush: boolean): SourceLines; } /** One key's (or all keys') accumulated matches. */ export interface WidgetSeries { /** Matches, including those that carried no number. */ count: number; /** Numbers folded in. */ values: number; first: number; last: number; min: number; max: number; sum: number; /** Matches per refresh time within the last {@link RATE_WINDOW_MS}, oldest first. */ recent: { t: number; n: number; }[]; /** Newest values with their times, oldest first; between {@link RING_POINTS} and twice that once full. */ ring: { t: number; v: number; }[]; /** Latest captured text (untrimmed length; cut when drawn). */ text?: string; /** Latest matching line (cut when drawn). */ line?: string; updatedAt: number; } /** * Reduce a series. `count` and `rate` are defined on an empty series (0); * value aggregations are `undefined` until a number arrived, and `change` is * `undefined` when it would divide a move by a zero start. */ export declare function aggregateSeries(series: WidgetSeries, agg: JobWidgetAgg, now: number, startTime: number): number | undefined; /** Equal-count bucket means, at most `points` of them, each with its last point's time. */ export declare function downsample(ring: readonly { t: number; v: number; }[], points: number): { t: number; v: number; }[]; /** What the author reads about one source. */ export interface JobWidgetSourceSample { id: string; label: string; /** Text read so far, in the source's own unit (bytes for a pipe). */ size: number; /** Non-empty lines read so far. */ lines: number; /** First and last non-empty lines (no overlap), oldest first. */ head: string[]; tail: string[]; } /** Job facts a view needs besides the derived state. */ export interface JobWidgetViewContext { /** The fallback view's title: what the job is for, else its label. */ label: string; /** A task's stage in its own words, from its progress; the stage line whenever present. */ stage?: string; /** * Whether output lines may stand for the stage when the context names * none (a spec's stage rule, else the newest line): true for a command's * output, not for a subagent's tool results (file contents, search hits). */ lineStage?: boolean; /** A spec request is in flight. */ authoring: boolean; } /** * One job's derivation state under one spec (or none: the fallback view). * Installing a new spec starts a fresh runtime that rereads every source * from its oldest retained text. */ export declare class JobWidgetRuntime { #private; readonly spec: JobWidgetSpec | undefined; readonly startTime: number; readonly now: () => number; constructor(spec: JobWidgetSpec | undefined, startTime: number, now?: () => number); /** Lines seen since the last match on a source some rule reads. */ get unmatchedLines(): number; /** Time of the newest match; `undefined` before the first. */ get lastMatchAt(): number | undefined; /** Non-empty lines read across every source. */ get totalLines(): number; /** * Why the spec draws something other than the job's progress, judged on * every line read so far; empty while it fits. A rule loose enough to match * unrelated text shows it on lines the author's samples left out, so the * registry checks a spec here before installing it and while it runs: * - a rule on `tools` matching the results of several tools reads file * contents and search hits, not one command's progress lines; * - a keyed field with more keys than its blocks draw keys words of * arbitrary lines (a cell per line of prose); * - a grid whose cells mostly carry no status its tones name colours words. */ problems(): string[]; /** Read every source's new text; `flush` ends lines in progress. Returns whether anything new arrived. */ ingest(sources: readonly JobTextSource[], flush: boolean): boolean; /** First and last lines per source, most active first, for the author and the dry run. */ samples(): JobWidgetSourceSample[]; /** The view now: the spec's blocks when a spec drives it, else the fallback. */ view(context: JobWidgetViewContext): JobWidgetView; } /** * A spark's value domain: the data's range (values and marks) padded by 10% * on both sides, so a series moving within 160–186 does not draw as a flat * bar; a flat series pads by max(1, 5% of its value). The bottom stays at or * above 0 when every bound is non-negative. A spec's `min`/`max` win. */ export declare function sparkDomain(bounds: readonly number[], specMin?: number, specMax?: number): { min: number; max: number; }; /** * Bar and cell labels for keys: the last `/` segment when every key has one * and those segments stay unique (`openai-codex/gpt-6-luna` → `gpt-6-luna`), * else the keys as they are. */ export declare function keyLabels(keys: readonly string[]): string[]; /** Samples as plain line lists for {@link validateJobWidgetSpec}'s dry run. */ export declare function sampleLines(samples: readonly JobWidgetSourceSample[]): JobWidgetSampleLines[];