mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 11:55:05 +03:00
address review comments
This commit is contained in:
1 parent
50e8798c45
commit
befcc63493
4 files changed
+37
-32
No files matched your search
@@ -92,8 +92,6 @@ const supportRequest: SubmittedSupportRequest = {
|
||||
frontConversationId: 'front-conversation-1',
|
||||
}
|
||||
|
||||
// A minimal but contract-accurate ProjectDetailResponse, so a mock drifting
|
||||
// from the OpenAPI shape (missing fields, stale enum values) fails to compile.
|
||||
const readyProjectDetail: ProjectDetailResponse = {
|
||||
id: 1,
|
||||
ref: 'project-1',
|
||||
|
||||
@@ -13,12 +13,25 @@ import { databasePoliciesKeys } from '@/data/database-policies/keys'
|
||||
import { databaseTriggerKeys } from '@/data/database-triggers/keys'
|
||||
import { databaseKeys } from '@/data/database/keys'
|
||||
import { enumeratedTypesKeys } from '@/data/enumerated-types/keys'
|
||||
import { handleError } from '@/data/fetchers'
|
||||
import { handleError, isValidConnString } from '@/data/fetchers'
|
||||
import type { ProjectDetail } from '@/data/projects/project-detail-query'
|
||||
import { tableKeys } from '@/data/tables/keys'
|
||||
import { tryParseJson } from '@/lib/helpers'
|
||||
import type { SqlSnippet } from '@/state/ai-assistant-state'
|
||||
import { ResponseError } from '@/types'
|
||||
|
||||
// [Monica] Whether a project has finished provisioning and has a usable connection string
|
||||
export function isProjectReadyForAssistant(
|
||||
projectDetail: Pick<ProjectDetail, 'status' | 'connectionString'> | undefined
|
||||
): boolean {
|
||||
return (
|
||||
!!projectDetail &&
|
||||
projectDetail.status !== 'COMING_UP' &&
|
||||
projectDetail.status !== 'UNKNOWN' &&
|
||||
isValidConnString(projectDetail.connectionString)
|
||||
)
|
||||
}
|
||||
|
||||
export type MutationCategory = 'functions' | 'rls-policies'
|
||||
|
||||
// [Joshen] This is just very basic identification, but possible can extend perhaps
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ASSISTANT_ERRORS } from './AiAssistant.constants'
|
||||
import {
|
||||
containsLogsSnippets,
|
||||
hasPendingToolApproval,
|
||||
isProjectReadyForAssistant,
|
||||
onErrorChat,
|
||||
resolvePendingToolApprovalsAsDenied,
|
||||
} from './AIAssistant.utils'
|
||||
@@ -31,7 +32,6 @@ import { Message } from './Message'
|
||||
import { Markdown } from '@/components/interfaces/Markdown'
|
||||
import { useCheckOpenAIKeyQuery } from '@/data/ai/check-api-key-query'
|
||||
import { useRateMessageMutation } from '@/data/ai/rate-message-mutation'
|
||||
import { isValidConnString } from '@/data/fetchers'
|
||||
import { useProjectDetailQuery } from '@/data/projects/project-detail-query'
|
||||
import { useTablesQuery } from '@/data/tables/tables-query'
|
||||
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
|
||||
@@ -179,13 +179,7 @@ export const AssistantChat = ({
|
||||
isError: isSupportChatProjectError,
|
||||
refetch: refetchSupportChatProjectDetail,
|
||||
} = useProjectDetailQuery({ ref: supportMetadata?.projectRef }, { enabled: isOrgViewSupportChat })
|
||||
// Mirrors the readiness check in SupportAssistantSuccessCardContent — a project still
|
||||
// coming up, or with a connection string that isn't valid yet, isn't ready to send to.
|
||||
const isSupportChatProjectReady =
|
||||
!!supportChatProjectDetail &&
|
||||
supportChatProjectDetail.status !== 'COMING_UP' &&
|
||||
supportChatProjectDetail.status !== 'UNKNOWN' &&
|
||||
isValidConnString(supportChatProjectDetail.connectionString)
|
||||
const isSupportChatProjectReady = isProjectReadyForAssistant(supportChatProjectDetail)
|
||||
const isResolvingSupportChatConnectionString = isOrgViewSupportChat && !isSupportChatProjectReady
|
||||
|
||||
// Update context in state. On org-level pages there's no project in the URL, so
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import type { UIMessage as MessageType } from '@ai-sdk/react'
|
||||
import { ArrowUpRight } from 'lucide-react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useEffectEvent,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useSyncExternalStore,
|
||||
} from 'react'
|
||||
import type { JSX, MouseEvent } from 'react'
|
||||
import type { StreamdownProps } from 'streamdown'
|
||||
import {
|
||||
@@ -16,11 +24,11 @@ import {
|
||||
Skeleton,
|
||||
} from 'ui'
|
||||
|
||||
import { isProjectReadyForAssistant } from './AIAssistant.utils'
|
||||
import { buildSupportAssistantPrompt } from '@/components/interfaces/Support/SupportAssistant.utils'
|
||||
import type { SubmittedSupportRequest } from '@/components/interfaces/Support/SupportForm.state'
|
||||
import { NO_PROJECT_MARKER } from '@/components/interfaces/Support/SupportForm.utils'
|
||||
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
|
||||
import { isValidConnString } from '@/data/fetchers'
|
||||
import { useProjectDetailQuery } from '@/data/projects/project-detail-query'
|
||||
import { useTrack } from '@/lib/telemetry/track'
|
||||
import {
|
||||
@@ -72,21 +80,10 @@ export function SupportAssistantSuccessCardContent({
|
||||
refetch: refetchProjectDetail,
|
||||
} = useProjectDetailQuery({ ref: request.projectRef }, { enabled: hasAssistantContext })
|
||||
|
||||
// Mirrors the readiness check useProjectDetailQuery itself polls on: a project
|
||||
// still coming up, or one without a usable connection string yet, isn't ready
|
||||
// to receive requests, even though the query already returned some data.
|
||||
const isProjectReady =
|
||||
!!projectDetail &&
|
||||
projectDetail.status !== 'COMING_UP' &&
|
||||
projectDetail.status !== 'UNKNOWN' &&
|
||||
isValidConnString(projectDetail.connectionString)
|
||||
const isProjectReady = isProjectReadyForAssistant(projectDetail)
|
||||
const connectionString = projectDetail?.connectionString ?? undefined
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasAssistantContext) return
|
||||
if (!isProjectReady) return
|
||||
if (createdChatIdRef.current) return
|
||||
|
||||
const createSupportChat = useEffectEvent(() => {
|
||||
aiAssistantState.setContext({
|
||||
projectRef: request.projectRef,
|
||||
orgSlug: request.organizationSlug,
|
||||
@@ -100,9 +97,15 @@ export function SupportAssistantSuccessCardContent({
|
||||
|
||||
createdChatIdRef.current = newChatId
|
||||
setChatId(newChatId)
|
||||
// aiAssistantState is a stable context value (same identity across renders)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [aiAssistant, assistantPrompt, connectionString, hasAssistantContext, isProjectReady, request])
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasAssistantContext) return
|
||||
if (!isProjectReady) return
|
||||
if (createdChatIdRef.current) return
|
||||
|
||||
createSupportChat()
|
||||
}, [hasAssistantContext, isProjectReady])
|
||||
|
||||
const handleOpenAssistant = () => {
|
||||
track(
|
||||
@@ -153,9 +156,6 @@ export function SupportAssistantSuccessCardContent({
|
||||
|
||||
if (!hasAssistantContext) return null
|
||||
|
||||
// Before the chat exists (still loading, or failed) there's nothing for the card to
|
||||
// open — disable its click/keyboard handlers so only "Try again" (while erroring) is
|
||||
// interactive, and clicking mid-load can't open the sidebar with no chat prepared.
|
||||
const isInteractive = !!chat
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user