Documentation
¶
Overview ¶
Package util provides generic, reusable string and formatting helpers. This file contains pure string-truncation utilities only; session-ID formatting lives in session.go, and secret/security truncation lives in the sanitize package.
Index ¶
- Variables
- func AtomicWriteFile(filePath string, data []byte, perm os.FileMode) (err error)
- func ClientAddr(addr string) string
- func ClientHost(host string) string
- func CopyTrimmedStringIntMap(input map[string]int) map[string]int
- func DecodeStrictJSON(r io.Reader, value any) error
- func DeduplicateStrings(input []string, sorted bool) []string
- func DeepCloneJSON(v any) any
- func FindDuplicate[T comparable](items []T) (T, bool)
- func FormatDuration(d time.Duration) string
- func FormatFutureTime(t time.Time) string
- func FormatSessionIDForLog(sessionID string) string
- func GetStringFromMap(m map[string]any, keys ...string) string
- func HashForLog(value string, hexLen int, prefix string) string
- func HashForLogIf(sensitive bool, value string, hexLen int, prefix string) string
- func HashIdentifierForLog(id string) string
- func InterfaceToIntString(v any) (string, bool)
- func NormalizeStringCI(value string) string
- func ParseServerIDFromToolName(toolName string) string
- func RandomBigInt(bits uint) (*big.Int, error)
- func RandomBytes(n int) ([]byte, error)
- func RandomHex(n int) (string, error)
- func RandomHexWithFallback(n int) string
- func ShallowCloneMap[K comparable, V any](m map[K]V) map[K]V
- func SortedSetKeys(set map[string]struct{}) []string
- func StringsToAny(input []string) []any
- func Truncate(s string, maxLen int) string
- func TruncateRunes(s string, maxRunes int) string
- func TruncateRunesWithSuffix(s string, maxRunes int, suffix string) string
- func TruncateWithSuffix(s string, maxLen int, suffix string) string
- func ValidateUnique[T any, K comparable](items []T, validate func(T) error, key func(T) K, duplicateError func(T) error) error
Constants ¶
This section is empty.
Variables ¶
var ( // ErrTrailingJSON is returned by DecodeStrictJSON when non-whitespace data // follows the first JSON value. ErrTrailingJSON = errors.New("input must contain exactly one JSON value") // ErrMalformedTrailingJSON is returned when malformed data follows the first // JSON value. It wraps ErrTrailingJSON so errors.Is matches both sentinels. ErrMalformedTrailingJSON = fmt.Errorf("%w: malformed trailing data", ErrTrailingJSON) )
Functions ¶
func AtomicWriteFile ¶ added in v0.4.18
AtomicWriteFile writes data to filePath by syncing a uniquely named temporary file in the destination directory, renaming it into place, and syncing the destination directory.
func ClientAddr ¶ added in v0.4.6
ClientAddr returns a client-friendly address from a listener address. When the host is a wildcard (empty, 0.0.0.0, ::, or [::]), it substitutes "localhost" so the printed address is usable from a client. Use this when a resolvable hostname is required (e.g. for GH_HOST with the gh CLI). For gateway output URLs where a numeric loopback address is preferred, use ClientHost.
func ClientHost ¶ added in v0.4.7
ClientHost returns a client-friendly hostname from a listener host string. When the host is a wildcard (empty, 0.0.0.0, ::, or [::]), it returns "127.0.0.1" so the address is usable in client-facing URLs. Use ClientAddr when you need to operate on a full host:port string.
func CopyTrimmedStringIntMap ¶
CopyTrimmedStringIntMap returns a defensive copy of a string→int map with whitespace trimmed from all keys.
func DecodeStrictJSON ¶ added in v0.4.21
DecodeStrictJSON decodes exactly one JSON value from r into value. Unknown fields are rejected, and any data following the first JSON value (other than whitespace) is rejected as well. First-value decode failures are returned unwrapped so callers can add their own context; trailing data is reported as ErrTrailingJSON. Malformed trailing data matches both ErrTrailingJSON and ErrMalformedTrailingJSON and retains its decode error.
func DeduplicateStrings ¶
DeduplicateStrings returns a new slice with whitespace-trimmed, empty, and duplicate entries removed from input. When sorted is true the result is sorted in ascending order. The relative order of first-seen entries is preserved when sorted is false.
func DeepCloneJSON ¶
DeepCloneJSON creates a deep copy of a JSON-compatible value. It handles the three container types used by encoding/json: map[string]any (JSON objects), []any (JSON arrays), and any other type (JSON scalars: string, float64, bool, nil), which is returned as-is since scalar values are not reference types and need no cloning.
func FindDuplicate ¶ added in v0.4.15
func FindDuplicate[T comparable](items []T) (T, bool)
FindDuplicate returns the first item that occurs more than once, if any.
func FormatDuration ¶
FormatDuration formats a duration for display like the debug npm package. It provides granular formatting from nanoseconds to hours.
func FormatFutureTime ¶
FormatFutureTime returns a human-readable representation of a future time, combining an RFC3339 timestamp with a relative countdown (e.g. "2026-05-03T12:00:00Z (in 5.0m)"). Returns "unknown" when t is the zero value.
func FormatSessionIDForLog ¶ added in v0.4.0
FormatSessionIDForLog returns a stable, non-reversible log-safe session ID representation. A session ID may be the authenticated agent ID and must not disclose any recoverable prefix in logs, diagnostics, or traces.
func GetStringFromMap ¶
GetStringFromMap returns the first non-empty string value found for any of the given keys in m. For each key, the value must be present, typed as string, and non-empty to be returned. Returns an empty string when no matching non-empty string value is found, when the map is nil, or when no keys are provided.
With a single key the behaviour is equivalent to `v, _ := m[key].(string)`:
GetStringFromMap(m, "owner")
With multiple keys the function returns the first non-empty match, which is useful for maps that may use either snake_case or camelCase field names:
GetStringFromMap(m, "html_url", "htmlUrl")
func HashForLog ¶ added in v0.4.17
HashForLog returns a stable, non-reversible attribution token for a sensitive value that is safe to write to logs, traces, audit records, or error messages. Empty values render as "(none)". Non-empty values are rendered as prefix followed by the first hexLen hex characters of their SHA-256 digest. The mapping is deterministic, so the same value is attributable across log lines without exposing the raw value or any recoverable prefix of it. This is the single source of truth for the "non-reversible attribution token" pattern used across packages (e.g. internal/util for agent/session IDs, internal/delegation for audit records); callers should use this helper instead of hand-rolling their own truncated SHA-256 hash.
func HashForLogIf ¶ added in v0.4.21
HashForLogIf returns HashForLog(value, hexLen, prefix) when sensitive is true, and the raw value unchanged otherwise. It exists so that callers which only redact a field in sensitive modes (enclave or delegation) can express that choice inline instead of repeating a conditional block per field.
func HashIdentifierForLog ¶ added in v0.4.15
HashIdentifierForLog returns a stable, non-reversible attribution token for a sensitive identifier (such as an authenticated agent ID or session token) that is safe to write to logs, traces, and error messages. Empty identifiers render as "(none)". Non-empty identifiers are rendered as "agent:" followed by the first 12 hex characters of their SHA-256 digest. The mapping is deterministic, so the same identity is attributable across log lines without exposing the raw value or any recoverable prefix of it.
func InterfaceToIntString ¶
InterfaceToIntString attempts to convert a JSON-decoded numeric value (float64 or json.Number) to its decimal integer string representation. Returns ("", false) if the value is not a numeric type or is non-integer.
func NormalizeStringCI ¶ added in v0.4.6
NormalizeStringCI trims surrounding whitespace and lowercases a string for case-insensitive comparisons.
func ParseServerIDFromToolName ¶ added in v0.4.3
ParseServerIDFromToolName extracts the server ID prefix from a prefixed tool name of the form "<serverID>___<toolName>". If the tool name contains no separator, or the server ID portion is empty, the full toolName is returned.
This is the canonical parser for the prefixed tool-name format defined in the server package. Both middleware and other consumers should use this function instead of duplicating the string-splitting logic.
func RandomBigInt ¶ added in v0.4.6
RandomBigInt returns a cryptographically random non-negative integer with the given bit width. The result is guaranteed to be strictly positive (≥ 1). This centralises crypto/rand.Int usage for callers that need a *big.Int (e.g. X.509 certificate serial numbers).
func RandomBytes ¶
RandomBytes returns n cryptographically random bytes.
func RandomHex ¶
RandomHex returns a hex-encoded string of n cryptographically random bytes. The returned string has length 2*n.
func RandomHexWithFallback ¶
RandomHexWithFallback returns a hex-encoded string of n random bytes. On the normal path it returns the same output as RandomHex(n) — a string of length 2*n containing cryptographically random hex characters. If crypto/rand is unavailable, it falls back to a hex-encoded pid+nanosecond value that is unique within a single process run. The fallback is non-cryptographic and should only arise in unusual runtime environments; it always produces a 32-character hex string (16 bytes), regardless of n. For the typical call site (n == 16) the fallback output length matches the normal output length.
func ShallowCloneMap ¶ added in v0.4.16
func ShallowCloneMap[K comparable, V any](m map[K]V) map[K]V
ShallowCloneMap returns a shallow copy of m so callers can safely overwrite specific keys without mutating the original map.
func SortedSetKeys ¶
SortedSetKeys returns the keys of a string set (map[string]struct{}) as a sorted slice. Returns an empty (non-nil) slice when the set is empty.
func StringsToAny ¶
StringsToAny converts a []string to []any.
func Truncate ¶
Truncate truncates a string to the specified maximum length. If the string is longer than maxLen, it's truncated and "..." is appended. If maxLen is 0, returns "..." for non-empty strings, empty string for empty strings. If maxLen is negative, the original string is returned.
func TruncateRunes ¶
TruncateRunes truncates s to at most maxRunes Unicode code points (runes). Unlike Truncate, which counts bytes, TruncateRunes is safe for non-ASCII content (e.g. emoji, CJK characters). If maxRunes is 0 or negative, returns an empty string.
Performance: avoids allocating a []rune slice in the common "no truncation needed" case by using a three-stage check:
- If len(s) <= maxRunes (bytes), there are definitely <= maxRunes runes (each rune is at least 1 byte), so return s immediately with zero allocation.
- Otherwise count runes via utf8.RuneCountInString; if the count fits, return s.
- Only when truncation is required, walk the string byte-by-byte to find the cut point, avoiding the O(n) []rune allocation entirely.
func TruncateRunesWithSuffix ¶ added in v0.4.19
TruncateRunesWithSuffix truncates s to maxRunes Unicode code points and appends suffix when truncation occurs. If maxRunes is zero or negative, or no truncation is needed, it returns s unchanged.
func TruncateWithSuffix ¶
TruncateWithSuffix truncates a string to the specified maximum length with a custom suffix. If the string is longer than maxLen, it's truncated and suffix is appended. If maxLen is 0 or negative, the original string is returned.
func ValidateUnique ¶ added in v0.4.21
func ValidateUnique[T any, K comparable](items []T, validate func(T) error, key func(T) K, duplicateError func(T) error) error
ValidateUnique validates each item before checking its key and reports the first duplicate key.
Types ¶
This section is empty.