Merge branch 'master' into feat/compute-and-disk

This commit is contained in:
Jonathan Summers-Muir committed 2024-11-01 00:54:56 +08:00
commit 2570147a79
9 files changed
+127 -8

No files matched your search

+1
View File
@@ -58,6 +58,7 @@ const nextConfig = {
experimental: {
outputFileTracingIncludes: {
'/api/crawlers': ['./features/docs/generated/**/*', './docs/ref/**/*'],
'/reference/**/*': ['./features/docs/generated/**/*', './docs/ref/**/*'],
},
},
webpack: (config, options) => {
@@ -68,6 +68,8 @@ const formUnion = z.discriminatedUnion('type', [
type: z.literal('loki'),
url: z.string().min(1, { message: 'Loki URL is required' }),
headers: z.record(z.string(), z.string()),
username: z.string().optional(),
password: z.string().optional(),
}),
])
@@ -162,6 +164,8 @@ export function LogDrainDestinationSheetForm({
url: defaultValues?.config?.url || '',
api_key: defaultValues?.config?.api_key || '',
region: defaultValues?.config?.region || '',
username: defaultValues?.config?.username || '',
password: defaultValues?.config?.password || '',
},
})
@@ -422,10 +426,24 @@ export function LogDrainDestinationSheetForm({
<LogDrainFormItem
type="url"
value="url"
placeholder="https://my-logs-endpoint.grafana.net/loki/api/v1/push"
label="Loki URL"
formControl={form.control}
description="The Loki HTTP(S) endpoint to send events."
/>
<LogDrainFormItem
value="username"
label="Username"
placeholder="123456789"
formControl={form.control}
/>
<LogDrainFormItem
type="password"
value="password"
label="Password"
placeholder="glc_ABCD1234567890"
formControl={form.control}
/>
</div>
)}
<FormMessage_Shadcn_ />
@@ -131,8 +131,15 @@ export function LogDrains({
<TableBody>
{logDrains?.map((drain) => (
<TableRow key={drain.id}>
<TableCell className="font-medium">{drain.name}</TableCell>
<TableCell>{drain.description}</TableCell>
<TableCell className="font-medium truncate max-w-72" title={drain.name}>
{drain.name}
</TableCell>
<TableCell
className="text-foreground-light truncate max-w-72"
title={drain.description}
>
{drain.description}
</TableCell>
<TableCell className="text-right font-mono">{drain.type}</TableCell>
<TableCell className="text-right">
<DropdownMenu>
@@ -180,7 +187,7 @@ export function LogDrains({
}}
onCancel={() => setIsDeleteModalOpen(false)}
>
<div className="text-foreground-light">
<div className="text-foreground-light text-sm">
<p>
Are you sure you want to delete{' '}
<span className="text-foreground">{selectedLogDrain?.name}</span>?
@@ -4,10 +4,14 @@ import { Info } from 'lucide-react'
import { useEffect, useMemo, useRef, useState } from 'react'
import { toast } from 'sonner'
import { Alert, AlertDescription, AlertTitle } from '@ui/components/shadcn/ui/alert'
import { Message as MessageType } from 'ai'
import { useChat } from 'ai/react'
import { useParams } from 'common'
import { IS_PLATFORM } from 'common/constants/environment'
import { Markdown } from 'components/interfaces/Markdown'
import { SchemaComboBox } from 'components/ui/SchemaComboBox'
import { useCheckOpenAIKeyQuery } from 'data/ai/check-api-key-query'
import { useEntityDefinitionsQuery } from 'data/database/entity-definitions-query'
import { useOrganizationUpdateMutation } from 'data/organizations/organization-update-mutation'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
@@ -73,6 +77,9 @@ export const AiAssistantPanel = ({
const shouldShowNotOptimizedAlert =
selectedOrganization && !includeSchemaMetadata && showAiNotOptimizedWarningSetting
const { data: check } = useCheckOpenAIKeyQuery()
const isApiKeySet = IS_PLATFORM || !!check?.hasKey
const { data } = useEntityDefinitionsQuery(
{
schemas: selectedSchemas,
@@ -289,11 +296,21 @@ export const AiAssistantPanel = ({
<div ref={bottomRef} className="h-1" />
</div>
<div className="sticky p-5 flex-0 border-t">
<div className="sticky p-5 flex-0 border-t grid gap-4">
{!isApiKeySet && (
<Alert>
<AlertTitle>OpenAI API key not set</AlertTitle>
<AlertDescription>
<Markdown
content={'Add your `OPENAI_API_KEY` to `./docker/.env` to use the AI Assistant.'}
/>
</AlertDescription>
</Alert>
)}
<AssistantChatForm
textAreaRef={inputRef}
loading={isLoading}
disabled={isLoading}
disabled={isLoading || !isApiKeySet}
icon={
<AiIconAnimation
allowHoverEffect
@@ -243,7 +243,7 @@ const DeployNewReplicaPanel = ({
</div>
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
) : isAWSProvider ? (
) : !isAWSProvider ? (
<Alert_Shadcn_>
<WarningIcon />
<AlertTitle_Shadcn_>
@@ -9,9 +9,11 @@ import { toast } from 'sonner'
import type { Message as MessageType } from 'ai/react'
import { useChat } from 'ai/react'
import { useParams } from 'common'
import { Markdown } from 'components/interfaces/Markdown'
import OptInToOpenAIToggle from 'components/interfaces/Organization/GeneralSettings/OptInToOpenAIToggle'
import { MessageWithDebug } from 'components/interfaces/SQLEditor/AiAssistantPanel'
import { DiffType } from 'components/interfaces/SQLEditor/SQLEditor.types'
import { useCheckOpenAIKeyQuery } from 'data/ai/check-api-key-query'
import { useSqlDebugMutation } from 'data/ai/sql-debug-mutation'
import { useEntityDefinitionQuery } from 'data/database/entity-definition-query'
import { useEntityDefinitionsQuery } from 'data/database/entity-definitions-query'
@@ -116,6 +118,9 @@ export const AIAssistant = ({
selectedSchemas.length === 0 &&
selectedTables.length === 0
const { data: check } = useCheckOpenAIKeyQuery()
const isApiKeySet = IS_PLATFORM || !!check?.hasKey
const { data: existingDefinition } = useEntityDefinitionQuery({
id: entity?.id,
type: editor,
@@ -457,6 +462,19 @@ export const AIAssistant = ({
description="Give us a moment while we work on bringing the Assistant back online"
/>
)}
{!isApiKeySet && (
<Admonition
type="warning"
title="OpenAI API key not set"
description={
<Markdown
content={
'Add your `OPENAI_API_KEY` to `./docker/.env` to use the AI Assistant.'
}
/>
}
/>
)}
<div className="w-full border rounded">
<div className="py-2 px-3 border-b flex gap-2 flex-wrap">
<DropdownMenu>
@@ -619,7 +637,7 @@ export const AIAssistant = ({
'[&>textarea]:rounded-none [&>textarea]:border-0 [&>textarea]:!outline-none [&>textarea]:!ring-offset-0 [&>textarea]:!ring-0'
)}
loading={isLoading}
disabled={disablePrompts || isLoading}
disabled={!isApiKeySet || disablePrompts || isLoading}
placeholder={
hasMessages ? 'Reply to the assistant...' : 'How can we help you today?'
}
@@ -630,7 +648,7 @@ export const AIAssistant = ({
sendMessageToAssistant(value)
}}
/>
{!hasMessages && (
{!hasMessages && IS_PLATFORM && (
<div className="text-xs text-foreground-lighter text-opacity-60 bg-control px-3 pb-2">
The Assistant is in Alpha and your prompts might be rate limited
</div>
@@ -0,0 +1,31 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
import { get, isResponseOk } from 'lib/common/fetch'
import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
import { resourceKeys } from './keys'
// check to see if the OPENAI_API_KEY env var is set in self-hosted
// so we can disable the chat editor and add a warning about manually adding the key
export async function checkOpenAIKey(signal?: AbortSignal) {
const response = await get(`${BASE_PATH}/api/ai/sql/check-api-key`, { signal })
if (!isResponseOk(response)) {
throw (response as any).error
}
return response as { hasKey: boolean }
}
export type ResourceData = Awaited<ReturnType<typeof checkOpenAIKey>>
export type ResourceError = { errorEventId: string; message: string }
export const useCheckOpenAIKeyQuery = <TData = ResourceData>({
enabled = true,
...options
}: UseQueryOptions<ResourceData, ResourceError, TData> = {}) =>
useQuery<ResourceData, ResourceError, TData>(
resourceKeys.apiKey(),
({ signal }) => checkOpenAIKey(signal),
{ enabled: !IS_PLATFORM && enabled, ...options }
)
+3
View File
@@ -0,0 +1,3 @@
export const resourceKeys = {
apiKey: () => ['api-key'] as const,
}
@@ -0,0 +1,24 @@
import apiWrapper from 'lib/api/apiWrapper'
import { NextApiRequest, NextApiResponse } from 'next'
export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
async function handler(req: NextApiRequest, res: NextApiResponse) {
const { method } = req
switch (method) {
case 'GET':
return handleGet(req, res)
default:
res.setHeader('Allow', ['POST'])
res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
}
}
const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
if (process.env.OPENAI_API_KEY) {
return res.status(200).json({ hasKey: true })
} else {
return res.status(404).json({ hasKey: false })
}
}