Skip to content

Commit

Permalink
Add Directory Mention provider for Cody (#5210)
Browse files Browse the repository at this point in the history
Closes:
https://linear.app/sourcegraph/issue/SRCH-892/support-mentioning-dirs-and-better-monorepo-support-overall

This PR adds @directories and @Remote Directories mention providers for
Cody.

Merge it only after this commit is merged & deployed on
sourcegraph.sourcegraph.com:
sourcegraph/sourcegraph@0684b55

It requires a new `filesPattern` filter on `getCodyContext` API.
Therefore the providers are limited to SG version 5.7.0 and the insider
builds.

## Test plan

Demo:
https://www.loom.com/share/e55afcb2a5064a708a08f7851a618b2e?sid=8d68a39c-521a-4b47-9e5d-fb769f3975f4

## Changelog

- Add @-mention directories & remote directories provider for enterprise
Cody users.
  • Loading branch information
thenamankumar authored Aug 20, 2024
1 parent db9f50b commit 8245034
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 62 deletions.
30 changes: 21 additions & 9 deletions lib/prompt-editor/src/mentions/mentionMenu/MentionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type MentionMenuData,
type MentionQuery,
NO_SYMBOL_MATCHES_HELP_LABEL,
REMOTE_DIRECTORY_PROVIDER_URI,
REMOTE_FILE_PROVIDER_URI,
SYMBOL_CONTEXT_MENTION_PROVIDER,
parseMentionQuery,
Expand Down Expand Up @@ -137,21 +138,32 @@ export const MentionMenu: FunctionComponent<
// return files instead of repos if the repo name is in the query.
if (item.provider === 'openctx' && 'providerUri' in item) {
if (
item.providerUri === REMOTE_FILE_PROVIDER_URI &&
item.mention?.data?.repoName &&
!item.mention?.data?.filePath
(item.providerUri === REMOTE_FILE_PROVIDER_URI &&
item.mention?.data?.repoName &&
!item.mention?.data?.filePath) ||
(item.providerUri === REMOTE_DIRECTORY_PROVIDER_URI &&
item.mention?.data?.repoID &&
!item.mention?.data?.directoryPath)
) {
// Do not set the selected item as mention if it is repo item from the remote file search provider.
// Rather keep the provider in place and update the query with repo name so that the provider can
// start showing the files instead.

updateMentionMenuParams({
parentItem: {
id: REMOTE_FILE_PROVIDER_URI,
title: 'Remote Files',
queryLabel: 'Enter file path to search',
emptyLabel: `No matching files found in ${item?.mention?.data.repoName} repository`,
},
parentItem:
item.providerUri === REMOTE_DIRECTORY_PROVIDER_URI
? {
id: REMOTE_DIRECTORY_PROVIDER_URI,
title: 'Remote Directories',
queryLabel: 'Enter directory path to search',
emptyLabel: `No matching directories found in ${item?.mention?.data.repoName} repository`,
}
: {
id: REMOTE_FILE_PROVIDER_URI,
title: 'Remote Files',
queryLabel: 'Enter file path to search',
emptyLabel: `No matching files found in ${item?.mention?.data.repoName} repository`,
},
})

setEditorQuery(currentText => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
CURRENT_REPOSITORY_DIRECTORY_PROVIDER_URI,
type ContextItem,
type ContextMentionProviderMetadata,
FILE_CONTEXT_MENTION_PROVIDER,
IGNORED_FILE_WARNING_LABEL,
LARGE_FILE_WARNING_LABEL,
type MentionQuery,
REMOTE_DIRECTORY_PROVIDER_URI,
REMOTE_FILE_PROVIDER_URI,
REMOTE_REPOSITORY_PROVIDER_URI,
SYMBOL_CONTEXT_MENTION_PROVIDER,
Expand Down Expand Up @@ -142,5 +144,7 @@ export const iconForProvider: Record<
'internal-linear-issues': LinearLogo, // Can't import LinearIssuesProvider due to transitive dep on vscode.
[REMOTE_REPOSITORY_PROVIDER_URI]: FolderGitIcon,
[REMOTE_FILE_PROVIDER_URI]: FolderGitIcon,
[REMOTE_DIRECTORY_PROVIDER_URI]: FolderGitIcon,
[CURRENT_REPOSITORY_DIRECTORY_PROVIDER_URI]: FolderGitIcon,
[WEB_PROVIDER_URI]: LinkIcon,
}
10 changes: 8 additions & 2 deletions lib/prompt-editor/src/mentions/mentionMenu/useMentionMenuData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import type {
MentionQuery,
} from '@sourcegraph/cody-shared'
import {
CURRENT_REPOSITORY_DIRECTORY_PROVIDER_URI,
ContextItemSource,
REMOTE_DIRECTORY_PROVIDER_URI,
REMOTE_FILE_PROVIDER_URI,
REMOTE_REPOSITORY_PROVIDER_URI,
memoizeLastValue,
Expand Down Expand Up @@ -33,8 +35,12 @@ export function useMentionMenuParams(): {

const isRemoteLikeProviderActive =
mentionSettings.resolutionMode === 'remote' ||
params.parentItem?.id === REMOTE_FILE_PROVIDER_URI ||
params.parentItem?.id === REMOTE_REPOSITORY_PROVIDER_URI
[
REMOTE_FILE_PROVIDER_URI,
REMOTE_DIRECTORY_PROVIDER_URI,
REMOTE_REPOSITORY_PROVIDER_URI,
CURRENT_REPOSITORY_DIRECTORY_PROVIDER_URI,
].includes(params.parentItem?.id || '')

// Increase debounce time in case of remote context item resolution (Cody Web case) or
// in case of remote-like providers such as remote repositories or remote files
Expand Down
2 changes: 2 additions & 0 deletions lib/shared/src/context/openctx/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ export function setOpenCtx({ controller, disposable }: OpenCtx): void {

export const REMOTE_REPOSITORY_PROVIDER_URI = 'internal-remote-repository-search'
export const REMOTE_FILE_PROVIDER_URI = 'internal-remote-file-search'
export const REMOTE_DIRECTORY_PROVIDER_URI = 'internal-remote-directory-search'
export const CURRENT_REPOSITORY_DIRECTORY_PROVIDER_URI = 'internal-current-repository-directory-search'
export const WEB_PROVIDER_URI = 'internal-web-provider'
export const GIT_OPENCTX_PROVIDER_URI = 'internal-git-openctx-provider'
2 changes: 2 additions & 0 deletions lib/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ export {
openCtx,
REMOTE_REPOSITORY_PROVIDER_URI,
REMOTE_FILE_PROVIDER_URI,
REMOTE_DIRECTORY_PROVIDER_URI,
CURRENT_REPOSITORY_DIRECTORY_PROVIDER_URI,
WEB_PROVIDER_URI,
GIT_OPENCTX_PROVIDER_URI,
} from './context/openctx/api'
Expand Down
43 changes: 38 additions & 5 deletions lib/shared/src/sourcegraph-api/graphql/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
GET_FEATURE_FLAGS_QUERY,
GET_REMOTE_FILE_QUERY,
GET_URL_CONTENT_QUERY,
LEGACY_CONTEXT_SEARCH_QUERY,
LOG_EVENT_MUTATION,
LOG_EVENT_MUTATION_DEPRECATED,
PACKAGE_LIST_QUERY,
Expand Down Expand Up @@ -285,6 +286,7 @@ interface FileMatchSearchResponse {
results: {
__typename: string
repository: {
id: string
name: string
}
file: {
Expand Down Expand Up @@ -980,18 +982,49 @@ export class SourcegraphGraphQLAPIClient {
return extractDataOrError(response, data => data)
}

public async contextSearch(
repoIDs: string[],
query: string,
/**
* Checks if the current site version is valid based on the given criteria.
*
* @param options - The options for version validation.
* @param options.minimumVersion - The minimum version required.
* @param options.insider - Whether to consider insider builds as valid. Defaults to true.
* @returns A promise that resolves to a boolean indicating if the version is valid.
*/
public async isValidSiteVersion({
minimumVersion,
insider = true,
}: { minimumVersion: string; insider?: boolean }): Promise<boolean> {
const version = await this.getSiteVersion()
if (isError(version)) {
return false
}

const isInsiderBuild = version.length > 12 || version.includes('dev')

return (insider && isInsiderBuild) || semver.gte(version, minimumVersion)
}

public async contextSearch({
repoIDs,
query,
signal,
filePatterns,
}: {
repoIDs: string[]
query: string
signal?: AbortSignal
): Promise<ContextSearchResult[] | null | Error> {
filePatterns?: string[]
}): Promise<ContextSearchResult[] | null | Error> {
const isValidVersion = await this.isValidSiteVersion({ minimumVersion: '5.7.0' })

return this.fetchSourcegraphAPI<APIResponse<ContextSearchResponse>>(
CONTEXT_SEARCH_QUERY,
isValidVersion ? CONTEXT_SEARCH_QUERY : LEGACY_CONTEXT_SEARCH_QUERY,
{
repos: repoIDs,
query,
codeResultsCount: 15,
textResultsCount: 5,
...(isValidVersion ? { filePatterns } : {}),
},
signal
).then(response =>
Expand Down
25 changes: 24 additions & 1 deletion lib/shared/src/sourcegraph-api/graphql/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ query FileMatchSearchQuery($query: String!) {
__typename
... on FileMatch {
repository {
id
name
}
file {
Expand Down Expand Up @@ -224,7 +225,7 @@ query RankContext($interactionId: String!, $query: String!, $contextItems: [Inpu
}
}`

export const CONTEXT_SEARCH_QUERY = `
export const LEGACY_CONTEXT_SEARCH_QUERY = `
query GetCodyContext($repos: [ID!]!, $query: String!, $codeResultsCount: Int!, $textResultsCount: Int!) {
getCodyContext(repos: $repos, query: $query, codeResultsCount: $codeResultsCount, textResultsCount: $textResultsCount) {
...on FileChunkContext {
Expand All @@ -246,6 +247,28 @@ query GetCodyContext($repos: [ID!]!, $query: String!, $codeResultsCount: Int!, $
}
}`

export const CONTEXT_SEARCH_QUERY = `
query GetCodyContext($repos: [ID!]!, $query: String!, $codeResultsCount: Int!, $textResultsCount: Int!, $filePatterns: [String!]!) {
getCodyContext(repos: $repos, query: $query, codeResultsCount: $codeResultsCount, textResultsCount: $textResultsCount, filePatterns: $filePatterns) {
...on FileChunkContext {
blob {
path
repository {
id
name
}
commit {
oid
}
url
}
startLine
endLine
chunkContent
}
}
}`

export const CONTEXT_FILTERS_QUERY = `
query ContextFilters {
site {
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vscode/src/chat/chat-view/ContextRetriever.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ export class ContextRetriever implements vscode.Disposable {
return []
}

const remoteResultPromise = graphqlClient.contextSearch(repoIDs, query, signal)
const remoteResultPromise = graphqlClient.contextSearch({ repoIDs, query, signal })

const remoteResult = await remoteResultPromise
if (isError(remoteResult)) {
Expand Down
Loading

0 comments on commit 8245034

Please sign in to comment.