779ca4872b
- Removed Prettier configuration files (.prettierignore and .prettierrc) and migrated formatting to Biome. - Updated Biome configuration from version 2.3.11 to 2.3.12 and changed arrowParentheses rule from 'always' to 'asNeeded'. - Pinned @biomejs/biome dependency to exact version 2.3.12 in package.json and bun.lock. - Applied consistent arrow function formatting across 489 files by removing unnecessary parentheses around single parameters. - Removed blank lines after comment blocks and reorganized imports for consistency across the codebase.
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
/**
|
|
* Bash intent interceptor - redirects common shell patterns to proper tools.
|
|
*
|
|
* When an LLM calls bash with patterns like `grep`, `cat`, `find`, etc.,
|
|
* this interceptor provides helpful error messages directing them to use
|
|
* the specialized tools instead.
|
|
*/
|
|
import { type BashInterceptorRule, DEFAULT_BASH_INTERCEPTOR_RULES } from "../config/settings-manager";
|
|
|
|
export interface InterceptionResult {
|
|
/** If true, the bash command should be blocked */
|
|
block: boolean;
|
|
/** Error message to return instead of executing */
|
|
message?: string;
|
|
/** Suggested tool to use instead */
|
|
suggestedTool?: string;
|
|
}
|
|
|
|
/**
|
|
* Compile bash interceptor rules into regexes, skipping invalid patterns.
|
|
*/
|
|
function compileRules(rules: BashInterceptorRule[]): Array<{ rule: BashInterceptorRule; regex: RegExp }> {
|
|
const compiled: Array<{ rule: BashInterceptorRule; regex: RegExp }> = [];
|
|
for (const rule of rules) {
|
|
const flags = rule.flags ?? "";
|
|
try {
|
|
compiled.push({ rule, regex: new RegExp(rule.pattern, flags) });
|
|
} catch {
|
|
// Skip invalid regex patterns
|
|
}
|
|
}
|
|
return compiled;
|
|
}
|
|
|
|
/**
|
|
* Check if a bash command should be intercepted.
|
|
*
|
|
* @param command The bash command to check
|
|
* @param availableTools Set of tool names that are available
|
|
* @returns InterceptionResult indicating if the command should be blocked
|
|
*/
|
|
export function checkBashInterception(
|
|
command: string,
|
|
availableTools: string[],
|
|
rules: BashInterceptorRule[] = DEFAULT_BASH_INTERCEPTOR_RULES,
|
|
): InterceptionResult {
|
|
// Normalize command for pattern matching
|
|
const normalizedCommand = command.trim();
|
|
const compiled = compileRules(rules);
|
|
|
|
for (const { rule, regex } of compiled) {
|
|
// Only block if the suggested tool is actually available
|
|
if (!availableTools.includes(rule.tool)) {
|
|
continue;
|
|
}
|
|
|
|
if (regex.test(normalizedCommand)) {
|
|
return {
|
|
block: true,
|
|
message: `Blocked: ${rule.message}\n\nOriginal command: ${command}`,
|
|
suggestedTool: rule.tool,
|
|
};
|
|
}
|
|
}
|
|
|
|
return { block: false };
|
|
}
|
|
|
|
/**
|
|
* Check if a command is a simple directory listing that should use `ls` tool.
|
|
* Only applies to bare `ls` without complex flags.
|
|
*/
|
|
export function checkSimpleLsInterception(command: string, availableTools: string[]): InterceptionResult {
|
|
if (!availableTools.includes("ls")) {
|
|
return { block: false };
|
|
}
|
|
|
|
// Match simple ls commands (ls, ls -la, ls /path, etc.)
|
|
// Don't intercept complex pipes or commands
|
|
const simpleLsPattern = /^\s*ls(\s+(-[a-zA-Z]+\s*)*)?(\s+[^|;&]+)?\s*$/;
|
|
|
|
if (simpleLsPattern.test(command.trim())) {
|
|
return {
|
|
block: true,
|
|
message: `Use the \`ls\` tool instead of bash ls. It provides structured output.\n\nOriginal command: ${command}`,
|
|
suggestedTool: "ls",
|
|
};
|
|
}
|
|
|
|
return { block: false };
|
|
}
|