1const ACP_STDERR_TAIL_MAX_CHARS = 4_096;
2
3const PAIRING_URL_PATTERN = /https?:\/\/[^\s]*\/pair#[^\s]*/gi;
4const SIGN_IN_URL_PATTERN = /https?:\/\/accounts\.google\.com[^\s]*/gi;
5const BEARER_TOKEN_PATTERN = /\bBearer\s+[A-Za-z0-9._\-+=/]+/gi;
6const BASIC_AUTH_PATTERN = /\bAuthorization:\s*Basic\s+\S+/gi;
7const API_KEY_HEADER_PATTERN = /\bx-api-key:\s*\S+/gi;
8const SECRET_TOKEN_PATTERN =
9 /\b(?:sk-[A-Za-z0-9][A-Za-z0-9_-]{7,}|ghp_[A-Za-z0-9]+|xox[a-zA-Z]-[A-Za-z0-9-]+)\b/g;
10
11export function appendAcpStderrTail(current: string, chunk: string): string {
12 const next = `${current}${chunk}`;
13 return next.length <= ACP_STDERR_TAIL_MAX_CHARS ? next : next.slice(-ACP_STDERR_TAIL_MAX_CHARS);
14}
15
16export function sanitizeAcpStderrExcerpt(
17 text: string,
18 homeDirectory: string,
19 environment: NodeJS.ProcessEnv = process.env,
20): string {
21 let result = text.replaceAll("\0", "");
22 const homes = [environment.HOME, environment.USERPROFILE, homeDirectory].filter(
23 (value): value is string => typeof value === "string" && value.length > 1,
24 );
25 for (const home of new Set(homes)) {
26 result = result.split(home).join("~");
27 }
28 result = result
29 .replace(PAIRING_URL_PATTERN, "[pairing-url]")
30 .replace(SIGN_IN_URL_PATTERN, "[sign-in-url]")
31 .replace(BEARER_TOKEN_PATTERN, "Bearer [redacted]")
32 .replace(BASIC_AUTH_PATTERN, "Authorization: Basic [redacted]")
33 .replace(API_KEY_HEADER_PATTERN, "x-api-key: [redacted]")
34 .replace(SECRET_TOKEN_PATTERN, "[redacted]");
35 return result.trim();
36}