Files
Codeman/src/utils/single-line.ts
T
3b747774f1 fix(single-line): join lines by split and trim instead of a backtracking regex
/\s*[\r\n]+\s*/g backtracks over every start position of a long
whitespace run, so 50,000 spaces took over a second. Split on line breaks,
trim each line, drop blank ones and join with a space: linear, and a
leading or trailing blank line no longer leaves a space behind. A prompt
without a line break is still returned unchanged. session-auto-ops now
imports toSingleLine from the utils barrel like respawn-controller.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:03:53 +02:00

30 lines
1.2 KiB
TypeScript

/**
* @fileoverview Collapse a prompt onto the one line an unattended sender writes.
*
* @module utils/single-line
*/
/**
* A prompt as one line: each line is trimmed, blank lines are dropped, and the rest
* are joined with a single space; a prompt without a line break is returned as is.
*
* For the senders that run unattended through `writeViaMux` (respawn's update and
* kickstart steps, auto-compact). The mux pastes a multi-line prompt as one block,
* and the check that re-presses a stranded Enter cannot reliably recognise a
* multi-line paste in the composer, so nobody would notice a prompt left unsubmitted.
* Cron rejects multi-line prompts for the same reason; these senders join them
* instead, so a saved multi-line setting is still sent rather than refused.
*
* Split and trim, which is linear, rather than one regex replace that folds the
* whitespace around each break: that regex backtracks quadratically over a long
* whitespace run (50,000 spaces took over a second).
*/
export function toSingleLine(prompt: string): string {
if (!/[\r\n]/.test(prompt)) return prompt;
return prompt
.split(/[\r\n]+/)
.map((line) => line.trim())
.filter(Boolean)
.join(' ');
}