Cody Web: Fix no embeddings use case (#51082)

Reported here:
https://github.com/sourcegraph/sourcegraph/pull/51072#issuecomment-1521295540

Right now, Cody web simply crashes when encountering a repo that has no
embeddings. This is because it falls back to the keyword based
implementation which throws on the web (we won't have it there for a
while, because the vs code extension uses a native library to implement
that).

Since Cody is now useful even for unindexed repos (because we add the
currently viewed file into the context automatically), I think making it
gracefully handle this situation is better than disabling Cody for these
views.

## Test plan

<img width="593" alt="Screenshot 2023-04-25 at 12 15 13"
src="https://user-images.githubusercontent.com/458591/234247521-281859da-4c34-4c2c-b451-f355d0e7e2f7.png">


<!-- All pull requests REQUIRE a test plan:
https://docs.sourcegraph.com/dev/background-information/testing_principles
-->
This commit is contained in:
Philipp Spiess 2023-04-25 15:36:34 +02:00 committed by GitHub
parent 97055b017e
commit fed54b854e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 15 additions and 13 deletions

View File

@ -4,7 +4,6 @@ import { Editor } from '../editor'
import { PrefilledOptions, withPreselectedOptions } from '../editor/withPreselectedOptions'
import { SourcegraphEmbeddingsSearchClient } from '../embeddings/client'
import { SourcegraphIntentDetectorClient } from '../intent-detector/client'
import { KeywordContextFetcher } from '../keyword-context'
import { SourcegraphBrowserCompletionsClient } from '../sourcegraph-api/completions/browserClient'
import { SourcegraphGraphQLAPIClient } from '../sourcegraph-api/graphql/client'
import { isError } from '../utils'
@ -63,7 +62,7 @@ export async function createClient({
const embeddingsSearch = repoId ? new SourcegraphEmbeddingsSearchClient(graphqlClient, repoId) : null
const codebaseContext = new CodebaseContext(config, embeddingsSearch, noopKeywordFetcher)
const codebaseContext = new CodebaseContext(config, embeddingsSearch, null)
const intentDetector = new SourcegraphIntentDetectorClient(graphqlClient)
@ -142,10 +141,3 @@ export async function createClient({
},
}
}
const noopKeywordFetcher: KeywordContextFetcher = {
// eslint-disable-next-line @typescript-eslint/require-await
async getContext() {
throw new Error('noopKeywordFetcher: not implemented')
},
}

View File

@ -5,4 +5,5 @@ export interface ChatContextStatus {
connection?: boolean
codebase?: string
filePath?: string
supportsKeyword?: boolean
}

View File

@ -17,7 +17,7 @@ export class CodebaseContext {
constructor(
private config: Pick<Configuration, 'useContext'>,
private embeddings: EmbeddingsSearch | null,
private keywords: KeywordContextFetcher
private keywords: KeywordContextFetcher | null
) {}
public onConfigurationChange(newConfig: typeof this.config): void {
@ -81,6 +81,10 @@ export class CodebaseContext {
}
private async getKeywordContextMessages(query: string, options: ContextSearchOptions): Promise<ContextMessage[]> {
if (!this.keywords) {
return []
}
const results = await this.keywords.getContext(query, options.numCodeResults + options.numTextResults)
return results.flatMap(({ content, fileName }) => {
const messageText = populateCodeContextTemplate(content, fileName)

View File

@ -37,9 +37,12 @@ export const ChatInputContext: React.FunctionComponent<{
return (
<div className={classNames(styles.container, className)}>
<h3 className={styles.badge}>
{contextStatus.mode && contextStatus.connection ? 'Embeddings' : 'Keyword'}
</h3>
{contextStatus.mode && contextStatus.connection ? (
<h3 className={styles.badge}>Embeddings</h3>
) : contextStatus.supportsKeyword ? (
<h3 className={styles.badge}>Keyword</h3>
) : null}
{items.length > 0 && (
<ul className={styles.items}>
{items.map(({ icon, text, tooltip }, index) => (

View File

@ -326,6 +326,7 @@ export class ChatViewProvider implements vscode.WebviewViewProvider, vscode.Disp
connection: this.codebaseContext.checkEmbeddingsConnection(),
codebase: this.config.codebase,
filePath: editorContext ? vscode.workspace.asRelativePath(editorContext.filePath) : undefined,
supportsKeyword: true,
},
})
}

View File

@ -187,6 +187,7 @@ export const useChatStoreState = create<CodyChatStore>((set, get): CodyChatStore
return {
codebase: config?.codebase,
filePath: editor?.getActiveTextEditorSelectionOrEntireFile()?.fileName,
supportsKeyword: false,
mode: config?.useContext,
connection: true,
}