codeSearch function in Codebuff codebase.
In this article, we review codeSearch function in Codebuff codebase. We will look at:
-
codeSearch invoked in handleToolCall.
-
codeSearch function definition
I study patterns used in an open source project found on Github Trending. For this week, I reviewed Codebuff codebase and wrote this article.
codeSearch invoked in handleToolCall.
At L346 in codebuff/sdk/src/client.ts, you will find the following block:
else if (toolName === 'code_search') {
result = await codeSearch({
projectPath: this.cwd,
...input,
} as Parameters<typeof codeSearch>[0])
}
This block is defined in handleToolCall function.
codeSearch function definition
You will find the following code in codebuff/sdk/src/tools/code-search.ts.
import { spawn } from 'child_process'
import * as path from 'path'
import { rgPath } from '@vscode/ripgrep'
import type { CodebuffToolOutput } from '../../../common/src/tools/list'
export function codeSearch({
projectPath,
pattern,
flags,
cwd,
maxResults = 30,
}: {
projectPath: string
pattern: string
flags?: string
cwd?: string
maxResults?: number
}): Promise<CodebuffToolOutput<'code_search'>> {
return new Promise((resolve) => {
let stdout = ''
let stderr = ''
const flagsArray = (flags || '').split(' ').filter(Boolean)
let searchCwd = projectPath
if (cwd) {
const requestedPath = path.resolve(projectPath, cwd)
// Ensure the search path is within the project directory
if (!requestedPath.startsWith(projectPath)) {
resolve([
{
type: 'json',
value: {
errorMessage: `Invalid cwd: Path '${cwd}' is outside the project directory.`,
},
},
])
return
}
searchCwd = requestedPath
}
const args = [...flagsArray, pattern, '.']
const childProcess = spawn(rgPath, args, {
cwd: searchCwd,
stdio: ['ignore', 'pipe', 'pipe'],
})
childProcess.stdout.on('data', (data) => {
stdout += data.toString()
})
childProcess.stderr.on('data', (data) => {
stderr += data.toString()
})
childProcess.on('close', (code) => {
// Limit results to maxResults
const lines = stdout.split('\n')
const limitedLines = lines.slice(0, maxResults)
const limitedStdout = limitedLines.join('\n')
// Add truncation message if results were limited
const finalStdout =
lines.length > maxResults
? limitedStdout +
`\n\n[Results limited to ${maxResults} of ${lines.length} total matches]`
: limitedStdout
// Truncate output to prevent memory issues
const maxLength = 10000
const truncatedStdout =
finalStdout.length > maxLength
? finalStdout.substring(0, maxLength) + '\n\n[Output truncated]'
: finalStdout
const maxErrorLength = 1000
const truncatedStderr =
stderr.length > maxErrorLength
? stderr.substring(0, maxErrorLength) + '\n\n[Error output truncated]'
: stderr
const result = {
stdout: truncatedStdout,
...(truncatedStderr && { stderr: truncatedStderr }),
...(code !== null && { exitCode: code }),
message: 'Code search completed',
}
resolve([
{
type: 'json',
value: result,
},
])
})
childProcess.on('error', (error) => {
resolve([
{
type: 'json',
value: {
errorMessage: `Failed to execute ripgrep: ${error.message}. Make sure ripgrep is installed and available in PATH.`,
},
},
])
})
})
}
I believe the search is happening in the below block of code:
const childProcess = spawn(rgPath, args, {
cwd: searchCwd,
stdio: ['ignore', 'pipe', 'pipe'],
})
Here rgPath is imported as shown below:
import { rgPath } from '@vscode/ripgrep'
Learn more about vscode-ripgrep.
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Want to learn from open-source? Solve challenges inspired by open-source projects.
References:
-
https://github.com/CodebuffAI/codebuff/blob/main/sdk/src/client.ts#L350
-
https://github.com/CodebuffAI/codebuff/blob/main/sdk/src/tools/code-search.ts#L8
-
https://github.com/CodebuffAI/codebuff/blob/main/sdk/src/client.ts#L346