fix(web): select the correct Company Brain workspace (#1372)

## What changed

- Make `/brain` reuse the active Company Brain, switch to a single existing Company Brain, show a picker for multiple choices, or create one only when none exists.
- Wait for active-organization restoration before making that decision.
- Make Company Brain onboarding match organizations by the confirmed company domain and never offer unrelated-domain workspaces.
- Create a new Company Brain when no matching workspace exists and show an actionable workspace-limit toast when creation is blocked.
- Improve the organization picker, loading, and error states.

## Why

The previous flows could use or mutate the currently active normal organization, start research against stale Company Brain metadata, or offer unrelated Company Brain workspaces after a quota failure.

## Impact

Normal organizations are no longer silently converted. Research is scoped to the Company Brain for the confirmed domain, and users receive a clear recovery path when they reach their workspace limit.

This keeps the existing `{ domain }` research API contract; no organization-reconfiguration API is required.

## Validation

- Biome checks passed for all five changed web files
- Targeted web TypeScript diagnostics reported no errors for the changed files
- React Doctor against `origin/main`: no issues found
- `git diff --check`

No test files were added.
This commit is contained in:
MaheshtheDev 2026-07-28 06:14:22 +00:00
parent ac880a4dc6
commit db7f5c3f64
5 changed files with 493 additions and 60 deletions

View file

@ -2,13 +2,19 @@
import { useCallback, useEffect, useRef, useState } from "react"
import { useRouter } from "next/navigation"
import { Loader2 } from "lucide-react"
import { LogoFull } from "@ui/assets/Logo"
import { Button } from "@ui/components/button"
import { AlertTriangle, ChevronRight, Loader2, RotateCw } from "lucide-react"
import { authClient } from "@lib/auth"
import { useAuth } from "@lib/auth-context"
import { SHARED_TEAM_BRAIN_TAG } from "@lib/constants"
import { cn } from "@lib/utils"
import { analytics } from "@/lib/analytics"
import { dmSansClassName } from "@/lib/fonts"
import {
type BrainEntryOrganization,
resolveCompanyBrainEntry,
} from "@/lib/company-brain-entry"
import { dmSans125ClassName, dmSansClassName } from "@/lib/fonts"
import {
detectModeFromEmail,
generateOrgSlug,
@ -21,22 +27,39 @@ import {
const BACKEND =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const modalCardStyle = {
boxShadow:
"0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset",
}
const inputBevelStyle = {
boxShadow:
"0px 1px 2px 0px rgba(0,43,87,0.1), inset 0px 0px 0px 1px rgba(43,49,67,0.08), inset 0px 1px 1px 0px rgba(0,0,0,0.08), inset 0px 2px 4px 0px rgba(0,0,0,0.02)",
}
// No forms: sign up → org auto-created → Slack install.
// After OAuth, mono attaches api_scale (14d trial) + company_brain (200 credits).
export default function BrainEntryPage() {
const router = useRouter()
const { user, org, organizations, setActiveOrg, refetchOrganizations } =
useAuth()
const {
user,
org,
organizations,
isRestoring,
setActiveOrg,
refetchOrganizations,
} = useAuth()
const { email = null } = user ?? {}
const [error, setError] = useState<string | null>(null)
const [choices, setChoices] = useState<BrainEntryOrganization[] | null>(null)
const [attempt, setAttempt] = useState(0)
const startedRef = useRef(false)
const run = useCallback(async () => {
if (organizations && organizations.length > 0) {
const active =
org ?? organizations.find((o) => o.slug) ?? organizations[0]
if (!org && active?.slug) await setActiveOrg(active.slug)
const continueWithOrganization = useCallback(
async (organization: BrainEntryOrganization) => {
if (org?.id !== organization.id) {
await setActiveOrg(organization.slug)
}
const status = await fetch(`${BACKEND}/brain/slack/status`, {
credentials: "include",
headers: { "X-App-Source": "nova" },
@ -48,9 +71,11 @@ export default function BrainEntryPage() {
return
}
window.location.href = `${BACKEND}/brain/slack/oauth/install`
return
}
},
[org?.id, router, setActiveOrg],
)
const createCompanyBrain = useCallback(async () => {
// Personal email → shell org; the Slack workspace resolves identity later.
const domain =
detectModeFromEmail(email) === "team"
@ -85,53 +110,206 @@ export default function BrainEntryPage() {
has_domain: Boolean(domain),
})
window.location.href = `${BACKEND}/brain/slack/oauth/install`
}, [email, org, organizations, setActiveOrg, refetchOrganizations, router])
}, [email, refetchOrganizations, setActiveOrg])
const run = useCallback(async () => {
const organizationsWithActiveMetadata = (organizations ?? []).map(
(organization) =>
organization.id === org?.id
? { ...organization, metadata: org.metadata }
: organization,
)
const decision = resolveCompanyBrainEntry(
org?.id,
organizationsWithActiveMetadata,
)
if (decision.action === "use" || decision.action === "switch") {
await continueWithOrganization(decision.organization)
return
}
if (decision.action === "choose") {
setChoices(decision.organizations)
return
}
await createCompanyBrain()
}, [continueWithOrganization, createCompanyBrain, org, organizations])
const handleChoice = useCallback(
(organization: BrainEntryOrganization) => {
setChoices(null)
setError(null)
continueWithOrganization(organization).catch((e) => {
startedRef.current = false
console.error("Company Brain organization selection failed:", e)
setError(e instanceof Error ? e.message : "Something went wrong.")
})
},
[continueWithOrganization],
)
// Sole caller of run(): the guard is only released on failure, so a dep change
// mid-flight can't kick off a second org creation.
// biome-ignore lint/correctness/useExhaustiveDependencies: attempt retriggers the retry
useEffect(() => {
if (!user || organizations === null || startedRef.current) return
if (!user || organizations === null || isRestoring || startedRef.current)
return
startedRef.current = true
run().catch((e) => {
startedRef.current = false
console.error("Brain entry failed:", e)
setError(e instanceof Error ? e.message : "Something went wrong.")
})
}, [user, organizations, run, attempt])
}, [user, organizations, isRestoring, run, attempt])
return (
<div
className={cn(
"flex min-h-dvh flex-col items-center justify-center gap-4 bg-[#05080D] px-6 text-center",
dmSansClassName(),
)}
>
{error ? (
<>
<p className="text-[15px] font-medium text-[#FAFAFA]">
<EntryShell>
{choices ? (
<section
className="w-full max-w-md rounded-[22px] bg-[#1B1F24] p-6 text-left md:p-8"
style={modalCardStyle}
>
<p
className={cn(
"text-[20px] font-semibold text-[#fafafa]",
dmSans125ClassName(),
)}
>
Choose your Company Brain
</p>
<p className="mt-1.5 text-[14px] font-medium leading-[1.5] text-[#737373]">
You're a member of more than one workspace. Pick the one to open.
</p>
<div className="mt-6 flex flex-col gap-2">
{choices.map((organization) => (
<button
key={organization.id}
type="button"
onClick={() => handleChoice(organization)}
style={inputBevelStyle}
className="group flex w-full items-center gap-3 rounded-[14px] border border-[rgba(82,89,102,0.2)] bg-[#14161A] px-3 py-3 text-left transition-colors hover:bg-[#1E2228] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4BA0FA]/60"
>
<span className="flex size-9 shrink-0 items-center justify-center rounded-full border border-[rgba(115,115,115,0.15)] bg-[#0D121A] text-[13px] font-semibold uppercase text-[#A1A1AA]">
{(organization.name.trim()[0] ?? "?").toUpperCase()}
</span>
<span className="min-w-0 flex-1">
<span className="block truncate text-[14px] font-medium text-[#fafafa]">
{organization.name}
</span>
{generateOrgSlug(organization.name) !== organization.slug && (
<span className="mt-0.5 block truncate text-[12px] font-medium text-[#525D6E]">
{organization.slug}
</span>
)}
</span>
<ChevronRight className="size-4 shrink-0 text-[#525D6E] transition-[color,transform] group-hover:translate-x-0.5 group-hover:text-[#A1A1AA]" />
</button>
))}
</div>
{email && (
<p className="mt-5 border-t border-white/[0.06] pt-4 text-[12px] font-medium text-[#525D6E]">
Signed in as {email}
</p>
)}
</section>
) : error ? (
<section
className="w-full max-w-md rounded-[22px] bg-[#1B1F24] p-8 text-center"
style={modalCardStyle}
>
<div
className="mx-auto flex size-12 items-center justify-center rounded-[14px] border border-[rgba(82,89,102,0.2)] bg-[#14161A]"
style={inputBevelStyle}
>
<AlertTriangle className="size-5 text-[#E5A94B]" />
</div>
<p
className={cn(
"mt-5 text-[20px] font-semibold text-[#fafafa]",
dmSans125ClassName(),
)}
>
Couldn't set up your Company Brain
</p>
<p className="max-w-sm text-[13px] text-[#8A94A6]">{error}</p>
<button
type="button"
<p className="mt-2 text-[14px] font-medium leading-[1.5] text-[#737373]">
{error}
</p>
<Button
variant="insideOut"
onClick={() => {
setError(null)
setAttempt((a) => a + 1)
}}
className="rounded-full bg-white px-5 py-2 text-[13px] font-semibold text-[#1D1C1D] hover:bg-white/95"
className="mt-6 rounded-full px-5 py-[10px] text-[13px] font-medium text-[#fafafa]"
>
<RotateCw className="size-3.5" />
Try again
</button>
</>
</Button>
</section>
) : (
<>
<Loader2 className="size-6 animate-spin text-[#4BA0FA]" />
<p className="text-[14px] font-medium text-[#8A94A6]">
Setting up your Company Brain
<div className="flex flex-col items-center text-center">
<div className="relative flex size-14 items-center justify-center">
<span className="absolute inset-0 animate-ping rounded-[18px] bg-[#4BA0FA]/10" />
<span
className="absolute inset-0 rounded-[18px] border border-[rgba(82,89,102,0.2)] bg-[#14161A]"
style={inputBevelStyle}
/>
<Loader2 className="relative size-5 animate-spin text-[#4BA0FA]" />
</div>
<p
className={cn(
"mt-6 text-[20px] font-semibold text-[#fafafa]",
dmSans125ClassName(),
)}
>
Setting up your Company Brain
</p>
</>
<p className="mt-2 max-w-sm text-[14px] font-medium leading-[1.5] text-[#737373]">
Preparing your workspace, then we'll connect it to Slack.
</p>
</div>
)}
</EntryShell>
)
}
function EntryShell({ children }: { children: React.ReactNode }) {
return (
<div
className={cn(
"relative min-h-dvh overflow-hidden bg-[#05080D] text-[#fafafa]",
dmSansClassName(),
)}
>
<div
aria-hidden
className="pointer-events-none absolute inset-0 select-none"
style={{
background:
"radial-gradient(ellipse 80% 60% at 50% 40%, rgba(75,160,250,0.08) 0%, rgba(34,97,202,0.04) 35%, transparent 70%)",
}}
/>
<div
aria-hidden
className="pointer-events-none absolute inset-0 select-none"
style={{
backgroundImage:
"radial-gradient(circle at center, rgba(105,167,240,0.22) 1px, transparent 1px)",
backgroundSize: "28px 28px",
maskImage:
"radial-gradient(ellipse at center, black 0%, black 40%, transparent 90%)",
WebkitMaskImage:
"radial-gradient(ellipse at center, black 0%, black 40%, transparent 90%)",
}}
/>
<header className="pointer-events-none absolute inset-x-0 top-0 z-20 px-4 py-4 md:px-10">
<LogoFull className="h-5 text-[#fafafa] md:h-6" />
</header>
<main className="relative z-10 flex min-h-dvh flex-col items-center justify-center px-4 py-20 md:px-10">
{children}
</main>
</div>
)
}

View file

@ -8,6 +8,7 @@ import { useAuth } from "@lib/auth-context"
import { authClient } from "@lib/auth"
import { SHARED_TEAM_BRAIN_TAG } from "@lib/constants"
import { analytics } from "@/lib/analytics"
import { resolveCompanyBrainEntry } from "@/lib/company-brain-entry"
import { BrainShell } from "@/components/onboarding-brain/shell"
import {
StepAbout,
@ -55,6 +56,20 @@ const getErrorMessage = (error: unknown, fallback: string) => {
return fallback
}
const getWorkspaceCreationErrorCopy = (message: string) => {
const limit = message.match(/maximum number of workspaces \((\d+)\)/i)?.[1]
if (limit) {
return {
title: "Workspace limit reached",
description: `You can own up to ${limit} workspaces. Delete one in Settings or contact support@supermemory.com for a higher limit.`,
}
}
return {
title: "Couldn't create workspace",
description: message,
}
}
export default function BrainOnboardingPage() {
const router = useRouter()
const params = useSearchParams()
@ -245,8 +260,16 @@ export default function BrainOnboardingPage() {
const creatingOrgRef = useRef(false)
const ensureOrg = useCallback(
async (domainOverride?: string): Promise<boolean> => {
if (!forceCreate && organizations && organizations.length > 0)
async (
domainOverride?: string,
createEvenIfExisting = false,
): Promise<boolean> => {
if (
!createEvenIfExisting &&
!forceCreate &&
organizations &&
organizations.length > 0
)
return false
const name = (
domainOverride
@ -328,8 +351,14 @@ export default function BrainOnboardingPage() {
analytics.onboardingWorkspaceCreateFailed({
error: message,
})
toast.error("Organization was not created", {
description: "Please try again from Settings.",
const errorCopy = getWorkspaceCreationErrorCopy(message)
toast.error(errorCopy.title, {
description: errorCopy.description,
duration: 8000,
action: {
label: "Open Settings",
onClick: () => router.push("/settings"),
},
})
if (forceCreate && (organizations?.length ?? 0) > 0) {
router.replace("/")
@ -342,7 +371,10 @@ export default function BrainOnboardingPage() {
const isCompanyBrain = mode === "team"
const handleBrainConfirm = useCallback(
async (confirmedDomain: string): Promise<CompanyBrainConfirmResult> => {
async (
confirmedDomain: string,
organizationId?: string,
): Promise<CompanyBrainConfirmResult> => {
if (creatingOrgRef.current) return { ok: false }
creatingOrgRef.current = true
setCreatingOrg(true)
@ -353,7 +385,42 @@ export default function BrainOnboardingPage() {
workspaceDomain: confirmedDomain,
workspaceName: workspaceName || a.workspaceName,
}))
const orgCreated = await ensureOrg(confirmedDomain)
let orgCreated = false
if (forceCreate) {
orgCreated = await ensureOrg(confirmedDomain, true)
} else if (organizationId) {
const selected = organizations?.find(
(organization) => organization.id === organizationId,
)
if (!selected) return { ok: false }
if (selected.id !== org?.id) await setActiveOrg(selected.slug)
} else {
const organizationsWithActiveMetadata = (organizations ?? []).map(
(organization) =>
organization.id === org?.id
? { ...organization, metadata: org.metadata }
: organization,
)
const decision = resolveCompanyBrainEntry(
org?.id,
organizationsWithActiveMetadata,
confirmedDomain,
)
if (decision.action === "choose") {
return {
ok: false,
choices: decision.organizations.map((organization) => ({
id: organization.id,
name: organization.name,
})),
}
}
if (decision.action === "switch") {
await setActiveOrg(decision.organization.slug)
} else if (decision.action === "create") {
orgCreated = await ensureOrg(confirmedDomain, true)
}
}
// Re-entering onboarding on an existing org ("Try onboarding") must
// kick research from the client. New orgs rely on the signup hook after
// provisioning — a duplicate /start races and can strand the DO task.
@ -393,8 +460,14 @@ export default function BrainOnboardingPage() {
const message = getErrorMessage(e, "Organization was not created.")
console.error("Failed to create organization:", e)
analytics.onboardingWorkspaceCreateFailed({ error: message })
toast.error("Organization was not created", {
description: "Please try again.",
const errorCopy = getWorkspaceCreationErrorCopy(message)
toast.error(errorCopy.title, {
description: errorCopy.description,
duration: 8000,
action: {
label: "Open Settings",
onClick: () => router.push("/settings"),
},
})
return { ok: false }
} finally {
@ -402,7 +475,15 @@ export default function BrainOnboardingPage() {
setCreatingOrg(false)
}
},
[ensureOrg, queryClient],
[
ensureOrg,
forceCreate,
org,
organizations,
queryClient,
setActiveOrg,
router,
],
)
const [sendingInvites, setSendingInvites] = useState(false)

View file

@ -4,7 +4,14 @@ import { LogoFull } from "@ui/assets/Logo"
import { Button } from "@ui/components/button"
import { Input } from "@ui/components/input"
import { cn } from "@lib/utils"
import { ArrowRight, Check, Globe, Loader2 } from "lucide-react"
import {
ArrowRight,
Building2,
Check,
ChevronRight,
Globe,
Loader2,
} from "lucide-react"
import { useQueryClient } from "@tanstack/react-query"
import { AnimatePresence, motion } from "motion/react"
import { type ReactNode, useEffect, useRef, useState } from "react"
@ -25,6 +32,7 @@ import {
import { ResearchActionRail } from "./research-action-rail"
import {
type CompanyBrainConfirmResult,
type CompanyBrainOrganizationChoice,
workspaceNameFromDomain,
} from "./types"
@ -33,7 +41,10 @@ interface CompanyBrainOnboardingProps {
avatarUrl: string | null
domain: string
submitting: boolean
onConfirm: (domain: string) => Promise<CompanyBrainConfirmResult>
onConfirm: (
domain: string,
organizationId?: string,
) => Promise<CompanyBrainConfirmResult>
onDone: () => void
onUsePersonal: () => void
}
@ -72,6 +83,9 @@ export function CompanyBrainOnboarding({
}: CompanyBrainOnboardingProps) {
const [phase, setPhase] = useState<Phase>("confirm")
const [domain, setDomain] = useState(initialDomain)
const [organizationChoices, setOrganizationChoices] = useState<
CompanyBrainOrganizationChoice[] | null
>(null)
const [serverSchedulesResearch, setServerSchedulesResearch] = useState(false)
const firstName = name.trim().split(/\s+/)[0] ?? ""
const clean = normalizeDomain(domain)
@ -84,10 +98,14 @@ export function CompanyBrainOnboarding({
)
const [retryUi, setRetryUi] = useState<null | "retrying" | "exhausted">(null)
const handleConfirm = async () => {
const handleConfirm = async (organizationId?: string) => {
if (!clean || submitting) return
const result = await onConfirm(clean)
if (!result.ok) return
const result = await onConfirm(clean, organizationId)
if (!result.ok) {
if (result.choices?.length) setOrganizationChoices(result.choices)
return
}
setOrganizationChoices(null)
setServerSchedulesResearch(result.serverSchedulesResearch)
setPhase("research")
}
@ -211,15 +229,24 @@ export function CompanyBrainOnboarding({
exit={{ opacity: 0 }}
transition={{ duration: 0.15 }}
>
<ConfirmBody
firstName={firstName}
name={name}
avatarUrl={avatarUrl}
domain={domain}
onDomainChange={setDomain}
onConfirm={handleConfirm}
submitting={submitting}
/>
{organizationChoices ? (
<OrganizationChoiceBody
organizations={organizationChoices}
submitting={submitting}
onSelect={(organizationId) => handleConfirm(organizationId)}
onBack={() => setOrganizationChoices(null)}
/>
) : (
<ConfirmBody
firstName={firstName}
name={name}
avatarUrl={avatarUrl}
domain={domain}
onDomainChange={setDomain}
onConfirm={() => handleConfirm()}
submitting={submitting}
/>
)}
</motion.div>
) : (
<motion.div
@ -240,7 +267,7 @@ export function CompanyBrainOnboarding({
</AnimatePresence>
</motion.div>
{phase === "confirm" && (
{phase === "confirm" && !organizationChoices && (
<div className="w-full max-w-xl mx-auto mt-5 flex items-center justify-between gap-4 px-1">
<button
type="button"
@ -252,7 +279,7 @@ export function CompanyBrainOnboarding({
</button>
<Button
variant="insideOut"
onClick={handleConfirm}
onClick={() => handleConfirm()}
disabled={!clean || submitting}
className="rounded-full px-5 py-[10px] text-[13px] font-medium text-[#fafafa]"
>
@ -300,6 +327,67 @@ export function CompanyBrainOnboarding({
)
}
function OrganizationChoiceBody({
organizations,
submitting,
onSelect,
onBack,
}: {
organizations: CompanyBrainOrganizationChoice[]
submitting: boolean
onSelect: (organizationId: string) => void
onBack: () => void
}) {
return (
<>
<div className="flex items-start gap-4">
<div className="flex size-12 shrink-0 items-center justify-center rounded-full border border-[rgba(82,89,102,0.2)] bg-[#14161A] text-[#4BA0FA]">
<Building2 className="size-5" />
</div>
<div>
<p className="text-[20px] font-semibold leading-tight text-[#FAFAFA]">
Choose your Company Brain
</p>
<p className="mt-1 text-[14px] font-medium leading-[1.4] text-[#737373]">
You already belong to more than one Company Brain workspace.
</p>
</div>
</div>
<div className="mt-6 flex flex-col gap-2">
{organizations.map((organization) => (
<button
key={organization.id}
type="button"
disabled={submitting}
onClick={() => onSelect(organization.id)}
className="flex w-full items-center gap-3 rounded-xl border border-white/[0.08] bg-white/[0.04] px-3 py-3 text-left transition-colors hover:bg-white/[0.08] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4BA0FA] disabled:opacity-50"
>
<span className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-[#4BA0FA]/10 text-[#4BA0FA]">
<Building2 className="size-4" />
</span>
<span className="min-w-0 flex-1 truncate text-[14px] font-medium text-[#FAFAFA]">
{organization.name}
</span>
{submitting ? (
<Loader2 className="size-4 shrink-0 animate-spin text-[#8A94A6]" />
) : (
<ChevronRight className="size-4 shrink-0 text-[#8A94A6]" />
)}
</button>
))}
</div>
<button
type="button"
disabled={submitting}
onClick={onBack}
className="mt-4 text-[13px] font-medium text-[#737373] transition-colors hover:text-[#FAFAFA] disabled:opacity-50"
>
Use a different domain
</button>
</>
)
}
function ConfirmBody({
firstName,
name,

View file

@ -1,6 +1,11 @@
export type CompanyBrainOrganizationChoice = {
id: string
name: string
}
export type CompanyBrainConfirmResult =
| { ok: true; serverSchedulesResearch: boolean }
| { ok: false }
| { ok: false; choices?: CompanyBrainOrganizationChoice[] }
export type BrainMode = "personal" | "team"

View file

@ -0,0 +1,81 @@
import {
getBrainMode,
getBrainWorkspaceDomain,
getCompanyBrainOverride,
hasCompanyBrain,
} from "./billing-utils"
export type BrainEntryOrganization = {
id: string
name: string
slug: string
metadata?: Record<string, unknown> | string | null
}
export type CompanyBrainEntryDecision =
| { action: "use"; organization: BrainEntryOrganization }
| { action: "switch"; organization: BrainEntryOrganization }
| { action: "choose"; organizations: BrainEntryOrganization[] }
| { action: "create" }
export function isCompanyBrainOrganization(
organization: BrainEntryOrganization,
): boolean {
const override = getCompanyBrainOverride(organization.metadata)
if (override !== undefined) return override
return (
hasCompanyBrain(organization.metadata) ||
getBrainMode(organization.metadata) === "team"
)
}
export function getCompanyBrainOrganizations(
organizations: BrainEntryOrganization[],
): BrainEntryOrganization[] {
return organizations.filter(isCompanyBrainOrganization)
}
function normalizeDomain(domain: string): string {
return domain
.trim()
.toLowerCase()
.replace(/^https?:\/\//, "")
.replace(/^www\./, "")
.replace(/\/.*$/, "")
}
export function resolveCompanyBrainEntry(
activeOrganizationId: string | null | undefined,
organizations: BrainEntryOrganization[],
requestedDomain?: string,
): CompanyBrainEntryDecision {
const normalizedRequestedDomain = requestedDomain
? normalizeDomain(requestedDomain)
: null
const companyBrains = getCompanyBrainOrganizations(organizations).filter(
(organization) => {
if (!normalizedRequestedDomain) return true
const organizationDomain = getBrainWorkspaceDomain(organization.metadata)
return (
organizationDomain !== null &&
normalizeDomain(organizationDomain) === normalizedRequestedDomain
)
},
)
const active = organizations.find(
(organization) => organization.id === activeOrganizationId,
)
if (
active &&
companyBrains.some((organization) => organization.id === active.id)
) {
return { action: "use", organization: active }
}
if (companyBrains.length === 1 && companyBrains[0]) {
return { action: "switch", organization: companyBrains[0] }
}
if (companyBrains.length > 1) {
return { action: "choose", organizations: companyBrains }
}
return { action: "create" }
}