From bf70c1bb00983472799f294a03c67dfb833d13d1 Mon Sep 17 00:00:00 2001 From: Will Chen Date: Tue, 22 Apr 2025 17:12:51 -0700 Subject: [PATCH] Supabase integration experiment setting (off by default) --- src/components/SupabaseIntegrationSwitch.tsx | 64 ++++++++++++++++++++ src/ipc/handlers/chat_stream_handlers.ts | 22 ++++--- src/lib/schemas.ts | 7 +++ src/main/settings.ts | 3 + src/pages/app-details.tsx | 7 ++- src/pages/settings.tsx | 17 ++++++ 6 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 src/components/SupabaseIntegrationSwitch.tsx diff --git a/src/components/SupabaseIntegrationSwitch.tsx b/src/components/SupabaseIntegrationSwitch.tsx new file mode 100644 index 0000000..26bb726 --- /dev/null +++ b/src/components/SupabaseIntegrationSwitch.tsx @@ -0,0 +1,64 @@ +import { useState, useEffect } from "react"; +import { Switch } from "@/components/ui/switch"; +import { useSettings } from "@/hooks/useSettings"; +import { showSuccess, showError } from "@/lib/toast"; + +interface SupabaseIntegrationSwitchProps { + showToast?: boolean; +} + +export function SupabaseIntegrationSwitch({ + showToast = true, +}: SupabaseIntegrationSwitchProps) { + const { settings, updateSettings, refreshSettings } = useSettings(); + const [isEnabled, setIsEnabled] = useState(false); + const [isUpdating, setIsUpdating] = useState(false); + + useEffect(() => { + if (settings) { + setIsEnabled(settings.experiments?.enableSupabaseIntegration || false); + } + }, [settings]); + + const handleToggle = async () => { + try { + setIsUpdating(true); + const newValue = !isEnabled; + + await updateSettings({ + experiments: { + enableSupabaseIntegration: newValue, + }, + }); + + setIsEnabled(newValue); + if (showToast) { + showSuccess( + `Supabase integration ${newValue ? "enabled" : "disabled"}` + ); + } + refreshSettings(); + } catch (error) { + console.error("Error toggling Supabase integration:", error); + if (showToast) { + showError("Failed to update Supabase integration setting"); + } + } finally { + setIsUpdating(false); + } + }; + + return ( +
+ + +
+ ); +} diff --git a/src/ipc/handlers/chat_stream_handlers.ts b/src/ipc/handlers/chat_stream_handlers.ts index 4ec5df8..04458ee 100644 --- a/src/ipc/handlers/chat_stream_handlers.ts +++ b/src/ipc/handlers/chat_stream_handlers.ts @@ -167,16 +167,18 @@ export function registerChatStreamHandlers() { messageHistory.pop(); } let systemPrompt = SYSTEM_PROMPT; - if (updatedChat.app?.supabaseProjectId) { - systemPrompt += - "\n\n" + - SUPABASE_AVAILABLE_SYSTEM_PROMPT + - "\n\n" + - (await getSupabaseContext({ - supabaseProjectId: updatedChat.app.supabaseProjectId, - })); - } else { - systemPrompt += "\n\n" + SUPABASE_NOT_AVAILABLE_SYSTEM_PROMPT; + if (readSettings().experiments?.enableSupabaseIntegration) { + if (updatedChat.app?.supabaseProjectId) { + systemPrompt += + "\n\n" + + SUPABASE_AVAILABLE_SYSTEM_PROMPT + + "\n\n" + + (await getSupabaseContext({ + supabaseProjectId: updatedChat.app.supabaseProjectId, + })); + } else { + systemPrompt += "\n\n" + SUPABASE_NOT_AVAILABLE_SYSTEM_PROMPT; + } } const { textStream } = streamText({ maxTokens: 8_000, diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts index 5989a77..3164c5e 100644 --- a/src/lib/schemas.ts +++ b/src/lib/schemas.ts @@ -87,6 +87,11 @@ export const SupabaseSchema = z.object({ }); export type Supabase = z.infer; +export const ExperimentsSchema = z.object({ + enableSupabaseIntegration: z.boolean().optional(), +}); +export type Experiments = z.infer; + /** * Zod schema for user settings */ @@ -100,6 +105,8 @@ export const UserSettingsSchema = z.object({ telemetryConsent: z.enum(["opted_in", "opted_out", "unset"]).optional(), telemetryUserId: z.string().optional(), hasRunBefore: z.boolean().optional(), + + experiments: ExperimentsSchema.optional(), // DEPRECATED. runtimeMode: RuntimeModeSchema.optional(), }); diff --git a/src/main/settings.ts b/src/main/settings.ts index c0bb4fc..397ecc1 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -16,6 +16,9 @@ const DEFAULT_SETTINGS: UserSettings = { telemetryConsent: "unset", telemetryUserId: uuidv4(), hasRunBefore: false, + experiments: { + enableSupabaseIntegration: false, + }, }; const SETTINGS_FILE = "user-settings.json"; diff --git a/src/pages/app-details.tsx b/src/pages/app-details.tsx index 8f6c388..9f47e70 100644 --- a/src/pages/app-details.tsx +++ b/src/pages/app-details.tsx @@ -29,6 +29,7 @@ import { } from "@/components/ui/dialog"; import { GitHubConnector } from "@/components/GitHubConnector"; import { SupabaseConnector } from "@/components/SupabaseConnector"; +import { useSettings } from "@/hooks/useSettings"; export default function AppDetailsPage() { const navigate = useNavigate(); @@ -48,7 +49,7 @@ export default function AppDetailsPage() { const [newFolderName, setNewFolderName] = useState(""); const [isRenamingFolder, setIsRenamingFolder] = useState(false); const appBasePath = useAtomValue(appBasePathAtom); - + const { settings } = useSettings(); // Get the appId from search params and find the corresponding app const appId = search.appId ? Number(search.appId) : null; const selectedApp = appId ? appsList.find((app) => app.id === appId) : null; @@ -241,7 +242,9 @@ export default function AppDetailsPage() { - {appId && } + {appId && settings?.experiments?.enableSupabaseIntegration && ( + + )} {/* Rename Dialog */} diff --git a/src/pages/settings.tsx b/src/pages/settings.tsx index 116b4ea..d24512e 100644 --- a/src/pages/settings.tsx +++ b/src/pages/settings.tsx @@ -6,6 +6,7 @@ import { IpcClient } from "@/ipc/ipc_client"; import { showSuccess, showError } from "@/lib/toast"; import { AutoApproveSwitch } from "@/components/AutoApproveSwitch"; import { TelemetrySwitch } from "@/components/TelemetrySwitch"; +import { SupabaseIntegrationSwitch } from "@/components/SupabaseIntegrationSwitch"; import { useSettings } from "@/hooks/useSettings"; import { Button } from "@/components/ui/button"; import { ArrowLeft } from "lucide-react"; @@ -145,6 +146,22 @@ export default function SettingsPage() { + {/* Experiments Section */} +
+

+ Experiments +

+
+
+ +
+ Enable integration with Supabase for auth, database and server + function support. +
+
+
+
+ {/* Danger Zone */}