Skip to content

feat(printer, config): Add bounded-latency typewriter controller#646

Merged
JeanMertz merged 3 commits into
mainfrom
prr213
May 16, 2026
Merged

feat(printer, config): Add bounded-latency typewriter controller#646
JeanMertz merged 3 commits into
mainfrom
prr213

Conversation

@JeanMertz
Copy link
Copy Markdown
Collaborator

Introduce a max_latency setting to TypewriterConfig and a matching controller in Printer that automatically reduces the per-character typewriter delay when the queue of pending characters grows large enough to risk falling behind the source by more than the configured budget.

With a fast provider such as Cerebras, the static text_delay / code_delay can cause the typewriter to trail the source by many seconds. Setting style.typewriter.max_latency to, e.g., 200ms keeps the printed output within that window: the effective delay shrinks to min(cap, max_latency / pending_chars) as the queue grows, and expands back toward the cap as it drains — subject to the drain-mode floor described below.

When the provider stops emitting (Event::Finished), the coordinator calls signal_typewriter_drain(), which snapshots the pending- character count. The controller then uses max(snapshot, pending) as the divisor, so the per-character delay never creeps back up as the tail of the queue empties. Any subsequent typewriter enqueue clears the snapshot and returns the controller to live mode.

Setting max_latency = 0 (the default) disables the controller entirely, preserving the existing static-delay behavior.

JeanMertz added 3 commits May 16, 2026 09:25
Introduce a `max_latency` setting to `TypewriterConfig` and a matching
controller in `Printer` that automatically reduces the per-character
typewriter delay when the queue of pending characters grows large enough
to risk falling behind the source by more than the configured budget.

With a fast provider such as Cerebras, the static `text_delay` /
`code_delay` can cause the typewriter to trail the source by many
seconds. Setting `style.typewriter.max_latency` to, e.g., `200ms` keeps
the printed output within that window: the effective delay shrinks to
`min(cap, max_latency / pending_chars)` as the queue grows, and expands
back toward the cap as it drains — subject to the drain-mode floor
described below.

When the provider stops emitting (`Event::Finished`), the coordinator
calls `signal_typewriter_drain()`, which snapshots the pending-
character count. The controller then uses `max(snapshot, pending)` as
the divisor, so the per-character delay never creeps back up as the tail
of the queue empties. Any subsequent typewriter enqueue clears the
snapshot and returns the controller to live mode.

Setting `max_latency = 0` (the default) disables the controller
entirely, preserving the existing static-delay behavior.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
@JeanMertz JeanMertz merged commit 7af9517 into main May 16, 2026
19 of 25 checks passed
@JeanMertz JeanMertz deleted the prr213 branch May 16, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant