Files
oh-my-pi/packages/coding-agent/src/tools/bash-interceptor.ts
T
can1357 779ca4872b style(deps): migrated from Prettier to Biome and updated formatting rules
- 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.
2026-01-24 04:20:19 +01:00

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 };
}