| 144 | } |
| 145 | |
| 146 | function redactForPreview(text: string): string { |
| 147 | return text |
| 148 | .replace( |
| 149 | /\b(?:api[_-]?key|access[_-]?key|secret|token|password|passwd|pwd)=([^&\s"'`]+)/gi, |
| 150 | (match) => `${match.split('=')[0]}=[REDACTED]`, |
| 151 | ) |
| 152 | .replace( |
| 153 | /\b[A-Za-z0-9_-]{24,}\.[A-Za-z0-9_-]{12,}\.[A-Za-z0-9_-]{12,}\b/g, |
| 154 | '[REDACTED_TOKEN]', |
| 155 | ) |
| 156 | .replace( |
| 157 | /\b(?:sk|pk|gho|ghp|glpat|xox[baprs])-?[A-Za-z0-9_-]{16,}\b/g, |
| 158 | '[REDACTED_TOKEN]', |
| 159 | ) |
| 160 | .replace(/\b[A-Fa-f0-9]{32,}\b/g, '[REDACTED_HEX]') |
| 161 | .replace(/\b[A-Za-z0-9+/]{32,}={0,2}\b/g, (match) => |
| 162 | /[A-Za-z]/.test(match) && /\d/.test(match) ? '[REDACTED_SECRET]' : match, |
| 163 | ) |
| 164 | } |
| 165 | |
| 166 | function getMessagePreview(message: ChatMessage | undefined): string { |
| 167 | if (!message) return '(none)' |