Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
5.1 kB · 157 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158import memoize from 'lodash-es/memoize.js'
export type DebugFilter = { include: string[] exclude: string[] isExclusive: boolean}
/** * Parse debug filter string into a filter configuration * Examples: * - "api,hooks" -> include only api and hooks categories * - "!1p,!file" -> exclude logging and file categories * - undefined/empty -> no filtering (show all) */export const parseDebugFilter = memoize( (filterString?: string): DebugFilter | null => { if (!filterString || filterString.trim() === '') { return null }
const filters = filterString .split(',') .map(f => f.trim()) .filter(Boolean)
// If no valid filters remain, return null if (filters.length === 0) { return null }
// Check for mixed inclusive/exclusive filters const hasExclusive = filters.some(f => f.startsWith('!')) const hasInclusive = filters.some(f => !f.startsWith('!'))
if (hasExclusive && hasInclusive) { // For now, we'll treat this as an error case and show all messages // Log error using logForDebugging to avoid console.error lint rule // We'll import and use it later when the circular dependency is resolved // For now, just return null silently return null }
// Clean up filters (remove ! prefix) and normalize const cleanFilters = filters.map(f => f.replace(/^!/, '').toLowerCase())
return { include: hasExclusive ? [] : cleanFilters, exclude: hasExclusive ? cleanFilters : [], isExclusive: hasExclusive, } },)
/** * Extract debug categories from a message * Supports multiple patterns: * - "category: message" -> ["category"] * - "[CATEGORY] message" -> ["category"] * - "MCP server \"name\": message" -> ["mcp", "name"] * - "[ANT-ONLY] 1P event: tengu_timer" -> ["ant-only", "1p"] * * Returns lowercase categories for case-insensitive matching */export function extractDebugCategories(message: string): string[] { const categories: string[] = []
// Pattern 3: MCP server "servername" - Check this first to avoid false positives const mcpMatch = message.match(/^MCP server ["']([^"']+)["']/) if (mcpMatch && mcpMatch[1]) { categories.push('mcp') categories.push(mcpMatch[1].toLowerCase()) } else { // Pattern 1: "category: message" (simple prefix) - only if not MCP pattern const prefixMatch = message.match(/^([^:[]+):/) if (prefixMatch && prefixMatch[1]) { categories.push(prefixMatch[1].trim().toLowerCase()) } }
// Pattern 2: [CATEGORY] at the start const bracketMatch = message.match(/^\[([^\]]+)]/) if (bracketMatch && bracketMatch[1]) { categories.push(bracketMatch[1].trim().toLowerCase()) }
// Pattern 4: Check for additional categories in the message // e.g., "[ANT-ONLY] 1P event: tengu_timer" should match both "ant-only" and "1p" if (message.toLowerCase().includes('1p event:')) { categories.push('1p') }
// Pattern 5: Look for secondary categories after the first pattern // e.g., "AutoUpdaterWrapper: Installation type: development" const secondaryMatch = message.match( /:\s*([^:]+?)(?:\s+(?:type|mode|status|event))?:/, ) if (secondaryMatch && secondaryMatch[1]) { const secondary = secondaryMatch[1].trim().toLowerCase() // Only add if it's a reasonable category name (not too long, no spaces) if (secondary.length < 30 && !secondary.includes(' ')) { categories.push(secondary) } }
// If no categories found, return empty array (uncategorized) return Array.from(new Set(categories)) // Remove duplicates}
/** * Check if debug message should be shown based on filter * @param categories - Categories extracted from the message * @param filter - Parsed filter configuration * @returns true if message should be shown */export function shouldShowDebugCategories( categories: string[], filter: DebugFilter | null,): boolean { // No filter means show everything if (!filter) { return true }
// If no categories found, handle based on filter mode if (categories.length === 0) { // In exclusive mode, uncategorized messages are excluded by default for security // In inclusive mode, uncategorized messages are excluded (must match a category) return false }
if (filter.isExclusive) { // Exclusive mode: show if none of the categories are in the exclude list return !categories.some(cat => filter.exclude.includes(cat)) } else { // Inclusive mode: show if any of the categories are in the include list return categories.some(cat => filter.include.includes(cat)) }}
/** * Main function to check if a debug message should be shown * Combines extraction and filtering */export function shouldShowDebugMessage( message: string, filter: DebugFilter | null,): boolean { // Fast path: no filter means show everything if (!filter) { return true }
// Only extract categories if we have a filter const categories = extractDebugCategories(message) return shouldShowDebugCategories(categories, filter)}