// localterm's state directory and the two policy files the scrub reads. These // hold names + env vars only — NEVER secret values (values live in the macOS // Keychain) — so reading them never touches a key. Mirrors the same constants // in localterm-server so the paths stay in lockstep. export const LOCALTERM_STATE_DIRNAME = ".localterm"; export const SECRETS_FILENAME = "secrets.json"; export const PROCESSES_FILENAME = "processes.json"; // The process name localterm wraps with a PATH shim. The scrub strips exactly // the secrets this process is wired to, mirroring what the shim injected. export const PI_PROCESS_NAME = "pi"; // pi's settings file name (global ~/.pi/agent/settings.json + project // /.pi/settings.json). The bash override reads these to preserve a // user's configured shell + command prefix. export const PI_SETTINGS_FILENAME = "settings.json"; // Canonical validation patterns — mirror localterm-server's zod schemas so a // malformed or hostile policy file can never trick the scrub into deleting an // unrelated env var. An env var in particular must match the strict uppercase // identifier shape a real secret envVar always has. export const SECRET_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/; export const PROCESS_NAME_PATTERN = /^[A-Za-z0-9_.+-]+$/; export const ENV_VAR_PATTERN = /^[A-Z_][A-Z0-9_]*$/; // Minimum byte length a secret value must reach before it is redacted from the // agent's bash-tool output. Below this, exact-value substring replacement would // clobber ordinary command output (a 2-3 char value matches everywhere). // Mirrors localterm-server's REDACTION_MIN_VALUE_LENGTH so the two packages // (deliberately decoupled — the extension runs inside pi, not the daemon) stay // in lockstep. export const REDACTION_MIN_VALUE_LENGTH = 4; // The token substituted for each redacted secret occurrence. A single fixed // character avoids leaking the value's length. Mirrors localterm-server's // REDACTION_MASK. export const REDACTION_MASK = "*"; // Mirror localterm-server's MAX_NOTIFICATION_LENGTH: the daemon slices any // OSC 9 body past this many UTF-16 code units, which can split a surrogate // pair. We cap the body ourselves before framing so the emitted sequence is // always within the daemon's limit and never split. Used by the OSC 9 // notification builder. export const NOTIFICATION_MAX_LENGTH = 1024; // Only push a desktop notification when the agent turn ran at least this long, // so quick back-and-forth turns don't spam a user actively watching the pi // tab. Tunable: lower to notify sooner, raise to stay quieter while focused. export const AGENT_NOTIFY_MIN_ELAPSED_MS = 30_000; export const PI_RETRY_STARTED_EVENT = "pi-retry:started"; export const PI_RETRY_COMPLETED_EVENT = "pi-retry:completed"; export const PI_RETRY_CANCELLED_EVENT = "pi-retry:cancelled"; // Cap on the assistant-response excerpt carried by the "pi finished" // notification body, counted in UTF-16 code units after whitespace is // collapsed. Long enough to surface a sentence or two of the agent's final // answer so a user who stepped away can tell what concluded; short enough to // stay readable in an OS banner (which truncates visually well before the // daemon's 1024-unit OSC cap that NOTIFICATION_MAX_LENGTH mirrors). export const AGENT_NOTIFY_EXCERPT_MAX_CHARS = 160;