diff --git a/apps/web/components/settings/company-brain-connections.tsx b/apps/web/components/settings/company-brain-connections.tsx
index b9045e8b..7720969e 100644
--- a/apps/web/components/settings/company-brain-connections.tsx
+++ b/apps/web/components/settings/company-brain-connections.tsx
@@ -3,7 +3,7 @@
import { authClient } from "@lib/auth"
import { cn } from "@lib/utils"
import { useQuery } from "@tanstack/react-query"
-import { Check, Loader2, Lock } from "lucide-react"
+import { Loader2, Lock } from "lucide-react"
import { useCallback, useEffect, useState } from "react"
import { toast } from "sonner"
import { dmSans125ClassName } from "@/lib/fonts"
@@ -14,6 +14,67 @@ const BACKEND =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
type ConnRow = { toolkit: string; org: boolean; user: boolean }
+type SlackStatus = { connected: boolean; teamName: string | null }
+
+function SecondaryButton({
+ children,
+ href,
+}: {
+ children: React.ReactNode
+ href: string
+}) {
+ return (
+
+ {children}
+
+ )
+}
+
+function SlackMark({ className }: { className?: string }) {
+ return (
+
+ )
+}
function GithubMark({ className }: { className?: string }) {
return (
@@ -73,16 +134,20 @@ function AppCard({
toolkit,
connected,
canConnect,
+ canDisconnect,
lockedHint,
busy,
onConnect,
+ onDisconnect,
}: {
toolkit: string
connected: boolean
canConnect: boolean
+ canDisconnect: boolean
lockedHint?: string
busy: boolean
onConnect: () => void
+ onDisconnect: () => void
}) {
const meta = TOOLKITS[toolkit] ?? {
label: toolkit,
@@ -116,7 +181,13 @@ function AppCard({
- {!connected &&
+ {connected && canDisconnect ? (
+
+ {busy && }
+ Disconnect
+
+ ) : (
+ !connected &&
(canConnect ? (
{busy && }
@@ -127,7 +198,8 @@ function AppCard({
{lockedHint}
- ) : null)}
+ ) : null)
+ )}
)
@@ -182,6 +254,7 @@ function CardSkeleton() {
export default function CompanyBrainConnections() {
const isCompanyBrain = useHasCompanyBrain()
const [rows, setRows] = useState(null)
+ const [slackStatus, setSlackStatus] = useState(null)
const [busy, setBusy] = useState(null)
const roleQuery = useQuery({
@@ -195,11 +268,21 @@ export default function CompanyBrainConnections() {
const isAdmin = role === "owner" || role === "admin"
const load = useCallback(async () => {
- const res = await fetch(`${BACKEND}/brain/connections`, {
- credentials: "include",
- })
- if (res.ok)
- setRows(((await res.json()) as { toolkits: ConnRow[] }).toolkits)
+ const [connRes, slackRes] = await Promise.all([
+ fetch(`${BACKEND}/brain/connections`, { credentials: "include" }),
+ fetch(`${BACKEND}/brain/slack/status`, { credentials: "include" }),
+ ])
+ if (connRes.ok) {
+ setRows(((await connRes.json()) as { toolkits: ConnRow[] }).toolkits)
+ } else {
+ setRows([])
+ toast.error("Couldn't load connections.")
+ }
+ if (slackRes.ok) {
+ setSlackStatus((await slackRes.json()) as SlackStatus)
+ } else {
+ setSlackStatus({ connected: false, teamName: null })
+ }
}, [])
useEffect(() => {
@@ -235,6 +318,37 @@ export default function CompanyBrainConnections() {
}
}
+ const disconnect = async (toolkit: string, scope: "user" | "org") => {
+ const label = TOOLKITS[toolkit]?.label ?? toolkit
+ if (
+ !window.confirm(
+ `Disconnect ${label} from ${scope === "org" ? "the shared org account" : "your personal account"}?`,
+ )
+ )
+ return
+ setBusy(`${toolkit}:${scope}`)
+ try {
+ const res = await fetch(
+ `${BACKEND}/brain/connections/${toolkit}?scope=${scope}`,
+ { method: "DELETE", credentials: "include" },
+ )
+ if (res.status === 403) {
+ toast.error("Only admins can disconnect the shared org account.")
+ return
+ }
+ if (!res.ok) {
+ toast.error("Couldn't disconnect.")
+ return
+ }
+ toast.success(`${label} disconnected.`)
+ await load()
+ } catch {
+ toast.error("Couldn't disconnect.")
+ } finally {
+ setBusy(null)
+ }
+ }
+
if (!isCompanyBrain) {
return (
+
+ {slackStatus?.connected && slackStatus.teamName ? (
+
+ Slack ยท {slackStatus.teamName}
+
+ ) : null}
+ {isAdmin ? (
+
+
+ Reconnect Slack
+
+ ) : null}
+
connect(row.toolkit, "org")}
+ onDisconnect={() => disconnect(row.toolkit, "org")}
/>
))
)}
@@ -286,8 +420,10 @@ export default function CompanyBrainConnections() {
toolkit={row.toolkit}
connected={row.user}
canConnect
+ canDisconnect
busy={busy === `${row.toolkit}:user`}
onConnect={() => connect(row.toolkit, "user")}
+ onDisconnect={() => disconnect(row.toolkit, "user")}
/>
))
)}