Skip to content

Commit 63164fe

Browse files
authored
Revert "Revert "Feature/assistant mcp"" (supabase#36687)
* Revert "Revert "Feature/assistant mcp" (supabase#36684)" This reverts commit 2bff117. * Attempt
1 parent 94036ce commit 63164fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3788
-2000
lines changed

apps/studio/components/interfaces/App/CommandMenu/CommandMenu.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
useQueryTableCommands,
55
useSnippetCommands,
66
} from 'components/layouts/SQLEditorLayout/SqlEditor.Commands'
7-
import { useGenerateSqlCommand } from 'components/interfaces/SqlGenerator/SqlGenerator.Commands'
87
import { useProjectLevelTableEditorCommands } from 'components/layouts/TableEditorLayout/TableEditor.Commands'
98
import { useLayoutNavCommands } from 'components/layouts/useLayoutNavCommands'
109
import { CommandHeader, CommandInput, CommandList, CommandMenu } from 'ui-patterns/CommandMenu'
@@ -19,7 +18,6 @@ import { useSupportCommands } from './Support'
1918
import { orderCommandSectionsByPriority } from './ordering'
2019

2120
export default function StudioCommandMenu() {
22-
useGenerateSqlCommand()
2321
useApiKeysCommands()
2422
useApiUrlCommand()
2523
useProjectLevelTableEditorCommands()

apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
77
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
88
import { IS_PLATFORM } from 'lib/constants'
99
import { useAppStateSnapshot } from 'state/app-state'
10-
import { removeTabsByEditor } from 'state/tabs'
1110
import { Badge, Button, Modal, ScrollArea, cn } from 'ui'
1211
import { APISidePanelPreview } from './APISidePanelPreview'
1312
import { CLSPreview } from './CLSPreview'
@@ -58,13 +57,6 @@ const FeaturePreviewModal = () => {
5857
properties: { feature: selectedFeatureKey },
5958
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
6059
})
61-
62-
if (ref && selectedFeatureKey === LOCAL_STORAGE_KEYS.UI_TABLE_EDITOR_TABS) {
63-
removeTabsByEditor(ref, 'table')
64-
}
65-
if (ref && selectedFeatureKey === LOCAL_STORAGE_KEYS.UI_SQL_EDITOR_TABS) {
66-
removeTabsByEditor(ref, 'sql')
67-
}
6860
}
6961

7062
function handleCloseFeaturePreviewModal() {

apps/studio/components/interfaces/Integrations/CronJobs/CronJobScheduleSection.tsx

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import { useEffect, useState } from 'react'
33
import { UseFormReturn } from 'react-hook-form'
44
import { useDebounce } from 'use-debounce'
55

6-
import { useCompletion } from 'ai/react'
76
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
7+
import { useSqlCronGenerateMutation } from 'data/ai/sql-cron-mutation'
88
import { useCronTimezoneQuery } from 'data/database-cron-jobs/database-cron-timezone-query'
9-
import { constructHeaders } from 'data/fetchers'
10-
import { BASE_PATH } from 'lib/constants'
119
import {
1210
Accordion_Shadcn_,
1311
AccordionContent_Shadcn_,
@@ -50,25 +48,13 @@ export const CronJobScheduleSection = ({ form, supportsSeconds }: CronJobSchedul
5048
{ name: 'Every Monday at 2 AM', expression: '0 2 * * 1' },
5149
] as const
5250

53-
const {
54-
complete: generateCronSyntax,
55-
isLoading: isGeneratingCron,
56-
stop,
57-
} = useCompletion({
58-
api: `${BASE_PATH}/api/ai/sql/cron`,
59-
onResponse: async (response) => {
60-
if (response.ok) {
61-
// remove quotes from the cron expression
62-
const expression = (await response.text()).trim().replace(/^"|"$/g, '')
63-
form.setValue('schedule', expression, {
64-
shouldValidate: true,
65-
shouldDirty: true,
66-
shouldTouch: true,
67-
})
68-
}
69-
},
70-
onError: (error) => {
71-
console.error('Error generating cron:', error)
51+
const { mutate: generateCronSyntax, isLoading: isGeneratingCron } = useSqlCronGenerateMutation({
52+
onSuccess: (expression) => {
53+
form.setValue('schedule', expression, {
54+
shouldValidate: true,
55+
shouldDirty: true,
56+
shouldTouch: true,
57+
})
7258
},
7359
})
7460

@@ -79,12 +65,7 @@ export const CronJobScheduleSection = ({ form, supportsSeconds }: CronJobSchedul
7965

8066
useEffect(() => {
8167
if (useNaturalLanguage && debouncedValue) {
82-
constructHeaders().then((headers) =>
83-
generateCronSyntax(debouncedValue, {
84-
headers: { Authorization: headers.get('Authorization') ?? '' },
85-
})
86-
)
87-
return () => stop()
68+
generateCronSyntax({ prompt: debouncedValue })
8869
}
8970
// eslint-disable-next-line react-hooks/exhaustive-deps
9071
}, [debouncedValue, useNaturalLanguage])
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { ReactNode } from 'react'
2+
import { Control } from 'react-hook-form'
3+
4+
import { AIOptInFormValues } from 'hooks/forms/useAIOptInForm'
5+
import { useFlag } from 'hooks/ui/useFlag'
6+
import { FormField_Shadcn_, RadioGroup_Shadcn_, RadioGroupItem_Shadcn_ } from 'ui'
7+
import { Admonition } from 'ui-patterns'
8+
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
9+
import { OptInToOpenAIToggle } from './OptInToOpenAIToggle'
10+
11+
interface AIOptInLevelSelectorProps {
12+
control: Control<AIOptInFormValues>
13+
disabled?: boolean
14+
label?: ReactNode
15+
layout?: 'horizontal' | 'vertical' | 'flex-row-reverse'
16+
}
17+
18+
const AI_OPT_IN_LEVELS = [
19+
{
20+
value: 'disabled',
21+
title: 'Disabled',
22+
description:
23+
'You do not consent to sharing any database information with Amazon Bedrock and understand that responses will be generic and not tailored to your database',
24+
},
25+
{
26+
value: 'schema',
27+
title: 'Schema Only',
28+
description:
29+
'You consent to sharing your database’s schema metadata (such as table and column names, data types, and relationships—but not actual database data) with Amazon Bedrock',
30+
},
31+
{
32+
value: 'schema_and_log',
33+
title: 'Schema & Logs',
34+
description:
35+
'You consent to sharing your schema and logs (which may contain PII/database data) with Amazon Bedrock for better results',
36+
},
37+
{
38+
value: 'schema_and_log_and_data',
39+
title: 'Schema, Logs & Database Data',
40+
description:
41+
'You consent to give Amazon Bedrock full access to run database read only queries and analyze results for optimal results',
42+
},
43+
]
44+
45+
export const AIOptInLevelSelector = ({
46+
control,
47+
disabled,
48+
label,
49+
layout = 'vertical',
50+
}: AIOptInLevelSelectorProps) => {
51+
const newOrgAiOptIn = useFlag('newOrgAiOptIn')
52+
53+
return (
54+
<FormItemLayout
55+
label={label}
56+
description={
57+
<div className="flex flex-col gap-y-4 my-4 max-w-xl">
58+
{!newOrgAiOptIn && (
59+
<Admonition
60+
type="note"
61+
title="Assistant Opt-in is temporarily disabled"
62+
description="We will re-enable opting in to the assistant shortly!"
63+
/>
64+
)}
65+
<p>
66+
Supabase AI can provide more relevant answers if you choose to share different levels of
67+
data. This feature is powered by Amazon Bedrock which does not store or log your prompts
68+
and completions, nor does it use them to train AWS models or distribute them to third
69+
parties. This is an organization-wide setting, so please select the level of data you
70+
are comfortable sharing.
71+
</p>
72+
<OptInToOpenAIToggle />
73+
</div>
74+
}
75+
layout={layout}
76+
>
77+
<div className="max-w-xl">
78+
<FormField_Shadcn_
79+
control={control}
80+
name="aiOptInLevel"
81+
render={({ field }) => (
82+
<RadioGroup_Shadcn_
83+
value={field.value}
84+
onValueChange={field.onChange}
85+
disabled={disabled}
86+
className="space-y-2 mb-6"
87+
>
88+
{AI_OPT_IN_LEVELS.map((item) => (
89+
<div key={item.value} className="flex items-start space-x-3">
90+
<RadioGroupItem_Shadcn_
91+
value={item.value}
92+
id={`ai-opt-in-${item.value}`}
93+
className="mt-0.5"
94+
/>
95+
<label
96+
htmlFor={`ai-opt-in-${item.value}`}
97+
className="cursor-pointer flex flex-col"
98+
>
99+
<span className="text-sm font-medium text-foreground">{item.title}</span>
100+
<span className="text-sm text-foreground-light">{item.description}</span>
101+
</label>
102+
</div>
103+
))}
104+
</RadioGroup_Shadcn_>
105+
)}
106+
/>
107+
</div>
108+
</FormItemLayout>
109+
)
110+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { PermissionAction } from '@supabase/shared-types/out/constants'
2+
import { useEffect } from 'react'
3+
4+
import { FormActions } from 'components/ui/Forms/FormActions'
5+
import { useAIOptInForm } from 'hooks/forms/useAIOptInForm'
6+
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
7+
import { useFlag } from 'hooks/ui/useFlag'
8+
import { Card, CardContent, CardFooter, Form_Shadcn_ } from 'ui'
9+
import { AIOptInLevelSelector } from './AIOptInLevelSelector'
10+
11+
export const DataPrivacyForm = () => {
12+
const newOrgAiOptIn = useFlag('newOrgAiOptIn')
13+
const { form, onSubmit, isUpdating, currentOptInLevel } = useAIOptInForm()
14+
const canUpdateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations')
15+
16+
const permissionsHelperText = !canUpdateOrganization
17+
? "You need additional permissions to manage this organization's settings"
18+
: undefined
19+
20+
useEffect(() => {
21+
form.reset({ aiOptInLevel: currentOptInLevel })
22+
}, [currentOptInLevel, form])
23+
24+
return (
25+
<Form_Shadcn_ {...form}>
26+
<form id="org-privacy-form" onSubmit={form.handleSubmit(onSubmit)}>
27+
<Card>
28+
<CardContent className="pt-6">
29+
<AIOptInLevelSelector
30+
control={form.control}
31+
disabled={!canUpdateOrganization || !newOrgAiOptIn || isUpdating}
32+
layout="flex-row-reverse"
33+
label="Supabase Assistant Opt-in Level"
34+
/>
35+
</CardContent>
36+
<CardFooter className="flex justify-end p-4 md:px-8">
37+
<FormActions
38+
form="org-privacy-form"
39+
isSubmitting={isUpdating}
40+
hasChanges={form.formState.isDirty}
41+
handleReset={() => form.reset()}
42+
helper={permissionsHelperText}
43+
disabled={!canUpdateOrganization}
44+
/>
45+
</CardFooter>
46+
</Card>
47+
</form>
48+
</Form_Shadcn_>
49+
)
50+
}

0 commit comments

Comments
 (0)