diff --git a/agent/src/cli/command-bench/strategy-chat-nls.ts b/agent/src/cli/command-bench/strategy-chat-nls.ts index b9c367d262d1..666d2141bc67 100644 --- a/agent/src/cli/command-bench/strategy-chat-nls.ts +++ b/agent/src/cli/command-bench/strategy-chat-nls.ts @@ -1,5 +1,6 @@ import path from 'node:path' import { graphqlClient, isError } from '@sourcegraph/cody-shared' +import { escapeNLSQuery } from '../../../../vscode/src/chat/chat-view/handlers/SearchHandler' import { version } from '../../../package.json' import type { CodyBenchOptions } from './command-bench' import { @@ -75,7 +76,7 @@ async function runNLSSearch(examples: Example[]): Promise { const repoNames = targetRepoRevs.map(repoRev => repoRev.repoName) const repoFilter = 'repo:' + repoNames.join('|') - const fullQuery = `${repoFilter} content:"${query.replaceAll('"', '\\"')}"` + const fullQuery = `${repoFilter} content:"${escapeNLSQuery(query)}"` const resultsResp = await graphqlClient.nlsSearchQuery({ query: fullQuery, }) diff --git a/vscode/src/chat/chat-view/handlers/SearchHandler.ts b/vscode/src/chat/chat-view/handlers/SearchHandler.ts index 372755e5ea39..4d491daa4d7a 100644 --- a/vscode/src/chat/chat-view/handlers/SearchHandler.ts +++ b/vscode/src/chat/chat-view/handlers/SearchHandler.ts @@ -45,9 +45,8 @@ export class SearchHandler implements AgentHandler { ? 'boost:relevant.repos()' : '' - const query = `content:"${inputTextWithoutContextChips.replaceAll( - '"', - '\\"' + const query = `content:"${escapeNLSQuery( + inputTextWithoutContextChips )}" ${currentRepoBoost} ${myProjectsBoost} ${scopes.length ? `(${scopes.join(' OR ')})` : ''}` try { @@ -75,6 +74,16 @@ export class SearchHandler implements AgentHandler { } } +export function escapeNLSQuery(query: string): string { + return ( + query + // first escape backslashes + .replaceAll('\\', '\\\\') + // then escape quotes + .replaceAll('"', '\\"') + ) +} + async function getSearchScopesFromMentions(mentions: ContextItem[]): Promise { const validMentions = mentions.reduce( (groups, mention) => { diff --git a/vscode/src/chat/chat-view/handlers/__tests__/SearchHandler.test.ts b/vscode/src/chat/chat-view/handlers/__tests__/SearchHandler.test.ts new file mode 100644 index 000000000000..4774b5810ea5 --- /dev/null +++ b/vscode/src/chat/chat-view/handlers/__tests__/SearchHandler.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from 'vitest' +import { escapeNLSQuery } from '../SearchHandler' + +describe('escapeNLSQuery', () => { + it('escapes backslashes', () => { + expect(escapeNLSQuery('path\\to\\file')).toBe('path\\\\to\\\\file') + }) + + it('escapes double quotes', () => { + expect(escapeNLSQuery(`say "hello"`)).toBe(`say \\"hello\\"`) + }) + + it('escapes escaped quotes', () => { + expect(escapeNLSQuery(`c:\\path\\"file"`)).toBe(`c:\\\\path\\\\\\"file\\"`) + }) +})