diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index 103684f54776..469a719551c4 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -541,7 +541,7 @@ impl Query { } async fn repository_list(ctx: &Context) -> Result> { - let user = check_user(ctx).await?; + let user = check_user_allow_auth_token(ctx).await?; ctx.locator .repository() @@ -574,7 +574,7 @@ impl Query { } async fn context_info(ctx: &Context) -> Result { - let user = check_user_allow_auth_token(ctx).await?; + let user = check_user(ctx).await?; ctx.locator.context().read(Some(&user.policy)).await } diff --git a/ee/tabby-ui/components/chat/chat.tsx b/ee/tabby-ui/components/chat/chat.tsx index e0939fdfcf42..1d55a45c64ad 100644 --- a/ee/tabby-ui/components/chat/chat.tsx +++ b/ee/tabby-ui/components/chat/chat.tsx @@ -12,13 +12,13 @@ import type { import { useQuery } from 'urql' import { ERROR_CODE_NOT_FOUND } from '@/lib/constants' +import { graphql } from '@/lib/gql/generates' import { CodeQueryInput, - ContextInfo, - ContextSourceKind, CreateMessageInput, InputMaybe, MessageAttachmentCodeInput, + RepositorySourceListQuery, ThreadRunOptionsInput } from '@/lib/gql/generates/graphql' import { useDebounceCallback } from '@/lib/hooks/use-debounce' @@ -26,8 +26,6 @@ import { useLatest } from '@/lib/hooks/use-latest' import { useThreadRun } from '@/lib/hooks/use-thread-run' import { filename2prism } from '@/lib/language-utils' import { useChatStore } from '@/lib/stores/chat-store' -import { client } from '@/lib/tabby/gql' -import { contextInfoQuery, resolveGitUrlQuery } from '@/lib/tabby/query' import { ExtendedCombinedError } from '@/lib/types' import { AssistantMessage, @@ -36,13 +34,27 @@ import { UserMessage, UserMessageWithOptionalId } from '@/lib/types/chat' -import { cn, nanoid } from '@/lib/utils' +import { cn, findClosestRepositoryMatch, nanoid } from '@/lib/utils' import { ChatPanel, ChatPanelRef } from './chat-panel' import { ChatScrollAnchor } from './chat-scroll-anchor' import { EmptyScreen } from './empty-screen' import { QuestionAnswerList } from './question-answer' +const repositoryListQuery = graphql(/* GraphQL */ ` + query RepositorySourceList { + repositoryList { + id + name + kind + gitUrl + sourceId + sourceName + sourceKind + } + } +`) + type ChatContextValue = { initialized: boolean threadId: string | undefined @@ -71,8 +83,8 @@ type ChatContextValue = { supportsOnApplyInEditorV2: boolean selectedRepoId: string | undefined setSelectedRepoId: React.Dispatch> - repos: ContextInfo['sources'] - fetchingSources: boolean + repos: RepositorySourceListQuery['repositoryList'] | undefined + fetchingRepos: boolean } export const ChatContext = React.createContext( @@ -160,20 +172,11 @@ function ChatRenderer( ) const chatPanelRef = React.useRef(null) - const [{ data: contextInfoData, fetching: fetchingSources }] = useQuery({ - query: contextInfoQuery + + const [{ data: repositoryListData, fetching: fetchingRepos }] = useQuery({ + query: repositoryListQuery }) - const repos = React.useMemo(() => { - return ( - contextInfoData?.contextInfo?.sources.filter(source => { - return [ - ContextSourceKind.Git, - ContextSourceKind.Github, - ContextSourceKind.Gitlab - ].includes(source.sourceKind) - }) ?? [] - ) - }, [contextInfoData]) + const repos = repositoryListData?.repositoryList const { sendUserMessage, @@ -530,30 +533,31 @@ function ChatRenderer( } } - const resolveGitUrl = async (gitUrl: string | undefined) => { - if (!gitUrl) return undefined - return client.query(resolveGitUrlQuery, { gitUrl }).toPromise() - } - React.useEffect(() => { const init = async () => { const gitRepoInfo = await fetchWorkspaceGitRepo() // get default repo - if (gitRepoInfo?.length) { + if (gitRepoInfo?.length && repos?.length) { const defaultGitUrl = gitRepoInfo[0].gitUrl - const repo = await resolveGitUrl(defaultGitUrl) - if (repo?.data?.resolveGitUrl) { - setSelectedRepoId(repo.data.resolveGitUrl.sourceId) + const targetGirUrl = findClosestRepositoryMatch( + defaultGitUrl, + repos.map(x => x.gitUrl) + ) + if (targetGirUrl) { + const repo = repos.find(x => x.gitUrl === targetGirUrl) + if (repo) { + setSelectedRepoId(repo.sourceId) + } } } setInitialized(true) } - if (!fetchingSources && !initialized) { + if (!fetchingRepos && !initialized) { init() } - }, [fetchingSources]) + }, [fetchingRepos]) React.useEffect(() => { if (initialized) { @@ -600,7 +604,7 @@ function ChatRenderer( selectedRepoId, setSelectedRepoId, repos, - fetchingSources, + fetchingRepos, initialized }} > @@ -669,13 +673,3 @@ function formatThreadRunErrorMessage(error: ExtendedCombinedError | undefined) { return error.message || 'Failed to fetch' } - -function isValidContextForCodeQuery(context: FileContext | undefined) { - if (!context) return false - - const isUntitledFile = - context.filepath.startsWith('untitled:') && - !filename2prism(context.filepath)[0] - - return !isUntitledFile -} diff --git a/ee/tabby-ui/components/chat/repo-select.tsx b/ee/tabby-ui/components/chat/repo-select.tsx index d2ee9229c8d2..36d841aa24a0 100644 --- a/ee/tabby-ui/components/chat/repo-select.tsx +++ b/ee/tabby-ui/components/chat/repo-select.tsx @@ -1,6 +1,6 @@ import { useRef, useState } from 'react' -import { ContextInfo } from '@/lib/gql/generates/graphql' +import { RepositorySourceListQuery } from '@/lib/gql/generates/graphql' import { cn } from '@/lib/utils' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' @@ -29,7 +29,7 @@ import LoadingWrapper from '@/components/loading-wrapper' import { SourceIcon } from '../source-icon' interface RepoSelectProps { - repos: ContextInfo['sources'] | undefined + repos: RepositorySourceListQuery['repositoryList'] | undefined value: string | undefined onChange: (v: string | undefined) => void isInitializing?: boolean diff --git a/ee/tabby-ui/lib/tabby/query.ts b/ee/tabby-ui/lib/tabby/query.ts index 0bf616e8cdd9..0e3bfa34e57e 100644 --- a/ee/tabby-ui/lib/tabby/query.ts +++ b/ee/tabby-ui/lib/tabby/query.ts @@ -280,20 +280,6 @@ export const repositoryListQuery = graphql(/* GraphQL */ ` } `) -export const resolveGitUrlQuery = graphql(/* GraphQL */ ` - query ResolveGitUrl($gitUrl: String!) { - resolveGitUrl(gitUrl: $gitUrl) { - id - sourceId - sourceKind - sourceName - name - kind - gitUrl - } - } -`) - export const repositorySearch = graphql(/* GraphQL */ ` query RepositorySearch( $kind: RepositoryKind! diff --git a/ee/tabby-ui/lib/utils/index.ts b/ee/tabby-ui/lib/utils/index.ts index b68738695766..218487694347 100644 --- a/ee/tabby-ui/lib/utils/index.ts +++ b/ee/tabby-ui/lib/utils/index.ts @@ -8,6 +8,7 @@ import { AttachmentCodeItem, AttachmentDocItem } from '@/lib/types' import { Maybe } from '../gql/generates/graphql' export * from './chat' +export * from './repository' export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs))