Help us shape the future of Go! Take the 2026 Go Developer Survey

safetext

package
v0.15.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package safetext converts raw process output bytes into model-safe text (spec "docs/specs/long-running-command-supervision.md", "Output capture and storage": "Model-visible text passes through safe-text normalization: invalid UTF-8 is replaced deterministically; disallowed terminal control sequences are escaped or removed; binary detection is reported; normalization is reported").

This package is pure text processing: it has no knowledge of processes, owners, handles, cursors, or storage, and it must stay that way -- the process package (process/render.go) is the only place that wires this package's output to a process's identity and cursor-addressed reads. safetext is stdlib-only.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LooksBinary

func LooksBinary(data []byte) bool

LooksBinary reports whether data looks like binary data rather than text, so a caller (process/render.go) can route it through base64 instead of inline safe text. This is a heuristic, not a proof: it combines a NUL-byte density check with a Shannon-entropy check over the byte-value distribution (task text: "NUL-byte density and/or Shannon-entropy-style byte-distribution check").

func Truncate

func Truncate(data []byte, limit int) []byte

Truncate trims data to at most limit bytes without splitting a multi-byte UTF-8 sequence in half. data is assumed to already be valid UTF-8 (as Normalize's own output always is), so any RuneError observed while backing off from the cut point can only mean the cut fell inside a multi-byte sequence, never a genuinely invalid byte -- backing off by at most utf8.UTFMax-1 bytes always reaches a valid boundary. A non-positive limit returns data unchanged (no cap requested); limit == 0 returns an empty slice.

Types

type Normalizer

type Normalizer struct {
	// contains filtered or unexported fields
}

Normalizer incrementally converts a raw byte stream, arriving in arbitrary chunks, into model-safe text. It:

  • replaces invalid UTF-8 byte sequences deterministically with the standard U+FFFD replacement character;
  • strips C0 control bytes (0x00-0x1F) and C1 control codepoints (U+0080-U+009F, however encoded) except approved whitespace (space, tab, newline, and carriage return -- see the isApprovedWhitespace doc comment for why \r is included);
  • recognizes and removes ANSI/terminal CSI (`ESC [ ... final-byte`), OSC (`ESC ] ... BEL` or `ESC ] ... ESC \`), and DCS (`ESC P ... ESC \`) sequences as complete units, even when a sequence is split across two separate Normalize calls.

The zero Normalizer is ready to use. A Normalizer carries state between calls (in-progress escape sequence, a truncated trailing UTF-8 byte sequence) and assumes its Normalize calls are fed strictly in stream order with no gaps or rewinds; it is NOT safe for concurrent use, and re-feeding an overlapping or out-of-order chunk produces undefined (though never unsafe -- no raw control byte can leak) results. Each distinct byte stream (e.g. one process's combined output) needs its own Normalizer.

func (*Normalizer) Normalize

func (n *Normalizer) Normalize(chunk []byte) []byte

Normalize consumes chunk -- the next slice of a byte stream, in stream order -- and returns the model-safe text produced from it. Bytes that belong to an in-progress escape sequence or a truncated UTF-8 rune carried over from a previous call (or held back for a future one) are never included in the returned slice's bytes as raw/partial data; they are either completed and dropped (escape sequences are removed entirely) or reconstructed and decoded (a completed multi-byte rune) on a later call.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL