Download src/gateway/terminal/buffer-text.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 1.88 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/gateway/terminal/buffer-text.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/gateway/terminal/buffer-text.ts
-
curl -L -o buffer-text.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/gateway/terminal/buffer-text.ts
1.88 kB
| // Renders a session's raw output ring as plain text for the agent terminal tool, | |
| // which needs readable output rather than escape sequences. | |
| import { stripAnsiSequences } from "../../../packages/terminal-core/src/ansi.js"; | |
| // Built at runtime so the source stays free of literal control characters and | |
| // the no-control-regex lint rule cannot statically detect them (same approach | |
| // as terminal-core's sanitizeForLog). Tab survives; \r/\n are handled above. | |
| const C0_EXCEPT_TAB_CR_LF = `${String.fromCharCode(0x00)}-${String.fromCharCode(0x08)}${String.fromCharCode(0x0b)}${String.fromCharCode(0x0c)}${String.fromCharCode(0x0e)}-${String.fromCharCode(0x1f)}${String.fromCharCode(0x7f)}`; | |
| // C1 control characters (0x80-0x9f) include the CSI introducer (0x9b), | |
| // which is an alternative ANSI escape prefix equivalent to ESC [. | |
| const C1 = `${String.fromCharCode(0x80)}-${String.fromCharCode(0x9f)}`; | |
| const CONTROL_BYTES_REGEX = new RegExp(`[${C0_EXCEPT_TAB_CR_LF}${C1}]`, "g"); | |
| /** | |
| * Approximates what a terminal would show without running a VT emulator: | |
| * strips ANSI sequences, collapses carriage-return overwrites (progress bars | |
| * emit "10%\r20%\r30%" — keep the last write per line), and drops remaining | |
| * C0/C1 control bytes. Cursor-movement layouts (vim, htop) will not reconstruct | |
| * faithfully; a true screen snapshot is a tracked follow-up. | |
| */ | |
| export function renderTerminalBufferText(raw: string): string { | |
| const stripped = stripAnsiSequences(raw); | |
| return stripped | |
| .split("\n") | |
| .map((line) => { | |
| // A final CR has not overwritten anything yet. Exclude only that CR; | |
| // an earlier CR still starts the last write, even when it is empty. | |
| const end = line.endsWith("\r") ? line.length - 1 : line.length; | |
| return line.slice(line.lastIndexOf("\r", end - 1) + 1, end).replace(CONTROL_BYTES_REGEX, ""); | |
| }) | |
| .join("\n"); | |
| } | |