Skip to content

Commit

Permalink
Merge pull request #34 from BBai-Tips/staging
Browse files Browse the repository at this point in the history
Added option for regex patterns to search and replace tool
  • Loading branch information
cngarrison authored Sep 30, 2024
2 parents e0985d4 + e6e4d10 commit a6b5d96
Show file tree
Hide file tree
Showing 10 changed files with 419 additions and 17 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0



## [0.0.19-beta] - 2024-09-30

### Changed

- Added option for regex patterns to search and replace tool.


## [0.0.18-beta] - 2024-09-29

### Changed
Expand Down
2 changes: 1 addition & 1 deletion api/deno.jsonc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bbai-api",
"version": "0.0.18-beta",
"version": "0.0.19-beta",
"exports": "./src/main.ts",
"tasks": {
"start": "deno run --allow-read --allow-write --allow-run --allow-net --allow-env src/main.ts",
Expand Down
43 changes: 33 additions & 10 deletions api/src/llms/tools/searchAndReplaceTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ export default class LLMToolSearchAndReplace extends LLMTool {
search: {
type: 'string',
description:
'The exact literal text to search for, with all leading and trailing whitespace from the original file; prepare the search text with JSON encoding, such as escaping backslash characters',
'The exact literal text to search for with all leading and trailing whitespace from the original file; OR a JavaScript Regex search pattern. The `regexPattern` option must be set to `true` for patterns that are a Regex.',
},
replace: {
type: 'string',
description:
'The text to replace with, matching the same indent level as the original file',
},
regexPattern: {
type: 'boolean',
description:
'Whether the search pattern is a regex (true) or a literal pattern (false). This affects the usage of special characters. If regexPattern is false (default) then special characters will be a literal match',
default: false,
},
replaceAll: {
type: 'boolean',
description: 'Whether to replace all occurrences or just the first one',
Expand Down Expand Up @@ -97,7 +103,15 @@ export default class LLMToolSearchAndReplace extends LLMTool {
const { toolUseId: _toolUseId, toolInput } = toolUse;
const { filePath, operations, createIfMissing = true } = toolInput as {
filePath: string;
operations: Array<{ search: string; replace: string; replaceAll?: boolean; caseSensitive?: boolean }>;
operations: Array<
{
search: string;
replace: string;
regexPattern?: boolean;
replaceAll?: boolean;
caseSensitive?: boolean;
}
>;
createIfMissing?: boolean;
};

Expand Down Expand Up @@ -133,7 +147,7 @@ export default class LLMToolSearchAndReplace extends LLMTool {
const operationResults = [];
const successfulOperations = [];
for (const [index, operation] of operations.entries()) {
const { search, replace, replaceAll = false, caseSensitive = true } = operation;
const { search, replace, regexPattern = false, replaceAll = false, caseSensitive = true } = operation;
const operationWarnings = [];
let operationSuccess = false;

Expand All @@ -152,15 +166,24 @@ export default class LLMToolSearchAndReplace extends LLMTool {
}

const originalContent = content;
if (replaceAll) {
content = caseSensitive
? content.replaceAll(search, replace)
: content.replaceAll(new RegExp(search, 'gi'), replace);

let searchPattern: string | RegExp;

const escapeRegExp = (str: string) => str.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
const flags = `${replaceAll ? 'g' : ''}${caseSensitive ? '' : 'i'}`;

if (regexPattern) {
searchPattern = new RegExp(search, flags);
} else if (!caseSensitive) {
searchPattern = new RegExp(escapeRegExp(search), flags);
} else {
content = caseSensitive
? content.replace(search, replace)
: content.replace(new RegExp(search, 'i'), replace);
searchPattern = search;
}
//logger.info(`Searching for pattern: `, searchPattern);

content = replaceAll && searchPattern instanceof RegExp
? content.replaceAll(searchPattern, replace)
: content.replace(searchPattern, replace);

// Check if the content actually changed
if (content !== originalContent) {
Expand Down
4 changes: 3 additions & 1 deletion api/src/utils/fileHandling.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export async function generateFileListing(projectRoot: string): Promise<string |
}
}

logger.error(`FileHandlingUtil: Failed to generate file listing within token limit (${tokenLimit}) after all tiers`);
logger.error(
`FileHandlingUtil: Failed to generate file listing within token limit (${tokenLimit}) after all tiers`,
);
return null;
}

Expand Down
Loading

0 comments on commit a6b5d96

Please sign in to comment.