Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
3.7 kB · 140 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141/** * Command semantics configuration for interpreting exit codes in different contexts. * * Many commands use exit codes to convey information other than just success/failure. * For example, grep returns 1 when no matches are found, which is not an error condition. */
import { splitCommand_DEPRECATED } from '../../utils/bash/commands.js'
export type CommandSemantic = ( exitCode: number, stdout: string, stderr: string,) => { isError: boolean message?: string}
/** * Default semantic: treat only 0 as success, everything else as error */const DEFAULT_SEMANTIC: CommandSemantic = (exitCode, _stdout, _stderr) => ({ isError: exitCode !== 0, message: exitCode !== 0 ? `Command failed with exit code ${exitCode}` : undefined,})
/** * Command-specific semantics */const COMMAND_SEMANTICS: Map<string, CommandSemantic> = new Map([ // grep: 0=matches found, 1=no matches, 2+=error [ 'grep', (exitCode, _stdout, _stderr) => ({ isError: exitCode >= 2, message: exitCode === 1 ? 'No matches found' : undefined, }), ],
// ripgrep has same semantics as grep [ 'rg', (exitCode, _stdout, _stderr) => ({ isError: exitCode >= 2, message: exitCode === 1 ? 'No matches found' : undefined, }), ],
// find: 0=success, 1=partial success (some dirs inaccessible), 2+=error [ 'find', (exitCode, _stdout, _stderr) => ({ isError: exitCode >= 2, message: exitCode === 1 ? 'Some directories were inaccessible' : undefined, }), ],
// diff: 0=no differences, 1=differences found, 2+=error [ 'diff', (exitCode, _stdout, _stderr) => ({ isError: exitCode >= 2, message: exitCode === 1 ? 'Files differ' : undefined, }), ],
// test/[: 0=condition true, 1=condition false, 2+=error [ 'test', (exitCode, _stdout, _stderr) => ({ isError: exitCode >= 2, message: exitCode === 1 ? 'Condition is false' : undefined, }), ],
// [ is an alias for test [ '[', (exitCode, _stdout, _stderr) => ({ isError: exitCode >= 2, message: exitCode === 1 ? 'Condition is false' : undefined, }), ],
// wc, head, tail, cat, etc.: these typically only fail on real errors // so we use default semantics])
/** * Get the semantic interpretation for a command */function getCommandSemantic(command: string): CommandSemantic { // Extract the base command (first word, handling pipes) const baseCommand = heuristicallyExtractBaseCommand(command) const semantic = COMMAND_SEMANTICS.get(baseCommand) return semantic !== undefined ? semantic : DEFAULT_SEMANTIC}
/** * Extract just the command name (first word) from a single command string. */function extractBaseCommand(command: string): string { return command.trim().split(/\s+/)[0] || ''}
/** * Extract the primary command from a complex command line; * May get it super wrong - don't depend on this for security */function heuristicallyExtractBaseCommand(command: string): string { const segments = splitCommand_DEPRECATED(command)
// Take the last command as that's what determines the exit code const lastCommand = segments[segments.length - 1] || command
return extractBaseCommand(lastCommand)}
/** * Interpret command result based on semantic rules */export function interpretCommandResult( command: string, exitCode: number, stdout: string, stderr: string,): { isError: boolean message?: string} { const semantic = getCommandSemantic(command) const result = semantic(exitCode, stdout, stderr)
return { isError: result.isError, message: result.message, }}