address review comments

This commit is contained in:
Monica Khoury committed 2026-08-22 22:23:08 +03:00
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 (