/** * The animation's frame rate, measured from the machine rather than assumed. * * The interval was a constant 80ms, which is what a fast machine can paint and what a slower one * cannot. Reported precisely that way: "koneck cli is performing well in terms of speed, the * problem is this machine the raspberry pi, it is slow here and on windows computer it is Ok". * A Pi 5 driving a terminal over SSH pays several times a laptop's cost for the same repaint, and * asking it for a frame every 80ms does not produce a faster animation — it produces a saturated * event loop, where the frame the agent's own work is waiting behind arrives late too. The whole * interface lags, which is the lag that was reported. * * A fixed number cannot be right for both machines, and picking one by guessing a machine's speed * would be inventing a limit. So the rate is derived from evidence the loop already has: a frame is * asked for in `n` milliseconds, and the tick records how long it actually took to arrive. A timer * that comes back on time means the machine is keeping up and the rate stands. A timer that comes * back late means the event loop was busy for longer than the frame it was given, and the honest * response is to ask for less — not to keep queueing work that cannot be done. * * So a laptop settles at the target rate and stays there, a Pi settles at whatever it can actually * sustain, and neither has a number written for it in advance. Recovery is deliberately slower than * backoff: a machine that has just proved it cannot keep up should not be asked to prove it twice a * second, and a single quick frame is not evidence that a slow machine has become a fast one. */ /** The target: fast enough that a spinner turns smoothly. Nothing is ever asked for faster. */ export declare const MIN_FRAME_MS = 80; /** * The slowest the animation may become before it stops being one. * * Past about a third of a second a spinner reads as stepping rather than turning. A machine that * cannot sustain even this is better served by a visibly slow animation than by a saturated loop, * so this is a floor on responsiveness, not a promise about smoothness. */ export declare const MAX_FRAME_MS = 320; /** * The interval to ask for next, given the one just used and how long it really took to arrive. * * Pure, so the pacing can be asserted rather than eyeballed: the same pair of numbers always gives * the same answer, and the curve can be checked at both ends without a terminal. */ export declare function pacedInterval(current: number, deliveredMs: number, floor?: number): number; /** * The rate to start from, given whether the terminal composites a redraw. * * In alt-screen mode a frame rewrites the whole screen. A terminal that implements synchronized * output presents that as one picture, so it can be done often and looks smooth. A terminal that * does not shows the erase, so every frame is a visible blink of the entire interface — and the * honest response is to do it far less often, not to keep blinking twelve times a second because * the animation would be prettier if the terminal were better. * * Four frames a second still reads as a spinner turning. It is a compromise, and it is the right * way round: a slightly steppy spinner is a cosmetic loss, a blinking screen is why somebody stops * using the tool. */ export declare const UNSYNCED_FRAME_MS = 250; export declare function startingInterval(synchronized: boolean): number; /** * The floor for this terminal: the pacer must never speed back up past what it can show cleanly. * * Without this the recovery path would walk a blinking terminal back to 80ms the moment a few * frames arrived on time — the machine was keeping up, which was never the problem. */ export declare function floorFor(synchronized: boolean): number; /** * How long after a keystroke the animation stays out of the way. * * Long enough to cover ordinary typing — a fast typist leaves under 200ms between keys, and a * thinking pause mid-sentence should not bring the spinner back for one frame and then lose it * again. Short enough that it returns almost at once when the hands stop. */ export declare const TYPING_QUIET_MS = 900; /** * Whether this frame should be drawn at all, given when a key was last pressed. * * Pure, so the rule can be asserted rather than inferred from a running terminal. A frame erases * the live region and writes it again — activity lines, composer and status bar together — so on a * terminal that does not composite that, every frame is a flash, and while somebody types it lands * on top of the repaint their keystroke already caused. */ export declare function shouldDrawFrame(now: number, lastKeyAt: number): boolean; //# sourceMappingURL=frame-pace.d.ts.map