docs(brain): note trial attach after Slack OAuth (#1313)

## Summary
- Documents that mono attaches Scale 14d trial + Company Brain after Slack OAuth from `/brain`.

Stacks on #1310. Billing implementation is in mono.
This commit is contained in:
MaheshtheDev 2026-07-21 21:34:25 +00:00
parent e39ba92cb4
commit 9bbe436fab
5 changed files with 453 additions and 130 deletions

View file

@ -21,7 +21,8 @@ import {
const BACKEND =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
// No forms: sign up → org auto-created → Slack install. The bot asks the rest.
// 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 } =

View file

@ -2,6 +2,8 @@
import { dmSans125ClassName } from "@/lib/fonts"
import { PLAN_DISPLAY_NAMES, useTokenUsage } from "@/hooks/use-token-usage"
import { useHasCompanyBrain } from "@/hooks/use-company-brain"
import { getBrainTrialInfo } from "@/lib/billing-utils"
import { cn } from "@lib/utils"
import { useAuth } from "@lib/auth-context"
import { getCanceledSubscription } from "@lib/queries"
@ -201,6 +203,42 @@ const ADVANCED_PLAN_CARDS: PlanCardDefinition[] = [
},
]
// Company Brain workspaces only sell Scale / Enterprise (no Free, Pro, Max).
const COMPANY_BRAIN_PLAN_CARDS: PlanCardDefinition[] = [
{
id: "scale",
name: "Scale",
price: "$399",
period: "/mo",
credits: "$600",
productId: "api_scale",
description: "Company Brain for your team, with production usage",
mostPopular: true,
features: [
"Company Brain Slack agent & shared memory",
"$600 monthly usage credits when paid",
"Auto top-up & spend caps",
"Team connectors & dedicated support",
],
},
{
id: "enterprise",
name: "Enterprise",
price: "Custom",
period: "",
credits: "Unlimited",
productId: "api_enterprise",
description: "Custom deployments with dedicated engineering",
includesFrom: "Scale",
features: [
"Custom metering & billing",
"Custom integrations & SSO",
"Forward-deployed engineer",
],
isContactSales: true,
},
]
const PLAN_RANK: Record<PlanCardDefinition["id"], number> = {
free: 0,
pro: 1,
@ -478,6 +516,11 @@ export default function Billing() {
const { user, org } = useAuth()
const autumn = useCustomer()
const posthog = usePostHog()
const isCompanyBrain = useHasCompanyBrain()
const brainTrial = useMemo(
() => getBrainTrialInfo(org?.metadata as Record<string, unknown> | string),
[org?.metadata],
)
const [isUpgrading, setIsUpgrading] = useState(false)
const [isCancelling, setIsCancelling] = useState(false)
const [isResuming, setIsResuming] = useState(false)
@ -511,20 +554,57 @@ export default function Billing() {
planUsagePct,
currentPlan,
hasPaidPlan,
isTrialing: autumnTrialing,
trialEndsAtMs: autumnTrialEndsAtMs,
isLoading: isCheckingStatus,
daysRemaining,
} = useTokenUsage(autumn)
const brainTrialStillOpen =
brainTrial.status === "active" &&
(brainTrial.endsAtMs == null || brainTrial.endsAtMs > Date.now())
const isBrainTrialEnded =
isCompanyBrain &&
(brainTrial.status === "expired" ||
brainTrial.status === "exhausted" ||
(brainTrial.status === "active" &&
brainTrial.endsAtMs != null &&
brainTrial.endsAtMs <= Date.now()))
const isOnTrial =
!isBrainTrialEnded &&
(autumnTrialing || (isCompanyBrain && brainTrialStillOpen))
const trialEndsAtMs = brainTrial.endsAtMs ?? autumnTrialEndsAtMs ?? null
const trialDaysLeft =
brainTrial.daysRemaining ??
(trialEndsAtMs != null
? Math.max(
0,
Math.ceil((trialEndsAtMs - Date.now()) / (1000 * 60 * 60 * 24)),
)
: null)
const trialEndsLabel =
trialEndsAtMs != null
? new Date(trialEndsAtMs).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
})
: null
const trialCredits = brainTrial.credits ?? (isOnTrial ? 200 : null)
const showPlanUsage = hasPaidPlan || isOnTrial || isCompanyBrain
// Open the carousel to the page holding the current plan (Max/Scale/Enterprise live on page 2).
// Company Brain orgs only list Scale + Enterprise — no carousel.
const didAutoOpenPlanPage = useRef(false)
useEffect(() => {
if (isCompanyBrain) return
if (didAutoOpenPlanPage.current || isCheckingStatus) return
didAutoOpenPlanPage.current = true
if (ADVANCED_PLAN_CARDS.some((p) => p.id === currentPlan)) {
setIsPlanCarouselActive(true)
setPlanPage(1)
}
}, [isCheckingStatus, currentPlan])
}, [isCheckingStatus, currentPlan, isCompanyBrain])
const balance = autumn.data?.balances?.[CREDIT_FEATURE_ID]
const creditRemaining =
@ -834,6 +914,25 @@ export default function Billing() {
)
}
// Trial Scale: primary CTA is activate paid Scale (not a dead "current" state).
if (plan.id === "scale" && (isOnTrial || isBrainTrialEnded)) {
return (
<button
type="button"
onClick={() => handleUpgrade("api_scale")}
disabled={disabled}
className={cn(
dmSans125ClassName(),
PLAN_CARD_ACTION_CLASS,
"bg-[#0054AD] text-[#FAFAFA] hover:bg-[#0B65C9]",
)}
>
{disabled ? <LoaderIcon className="size-4 animate-spin" /> : null}
Activate Scale
</button>
)
}
if (isCurrentPlan) {
return (
<button
@ -901,7 +1000,9 @@ export default function Billing() {
)}
>
{disabled ? <LoaderIcon className="size-4 animate-spin" /> : null}
Upgrade to {plan.name}
{isCompanyBrain && plan.id === "scale"
? "Activate Scale"
: `Upgrade to ${plan.name}`}
</button>
)
}
@ -914,31 +1015,43 @@ export default function Billing() {
<div className="flex flex-col gap-5">
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div className="min-w-0">
<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center gap-3">
<p
className={cn(
dmSans125ClassName(),
"font-semibold text-[18px] tracking-[-0.18px] text-[#FAFAFA]",
)}
>
{hasPaidPlan
? `${planDisplayNames[currentPlan]} plan`
: "Free plan"}
{isOnTrial ||
isBrainTrialEnded ||
(isCompanyBrain && currentPlan === "scale")
? "Scale plan"
: hasPaidPlan
? `${planDisplayNames[currentPlan]} plan`
: "Free plan"}
</p>
<Pill
tone={
isPlanCanceling
isPlanCanceling || isBrainTrialEnded
? "warning"
: hasPaidPlan
: isOnTrial
? "active"
: "muted"
: hasPaidPlan
? "active"
: "muted"
}
>
{isPlanCanceling
? "Cancelling"
: hasPaidPlan
? "Active"
: "Free"}
: isBrainTrialEnded
? brainTrial.status === "exhausted"
? "Credits used up"
: "Trial ended"
: isOnTrial
? "Free trial"
: hasPaidPlan
? "Active"
: "Free"}
</Pill>
</div>
<p
@ -948,11 +1061,44 @@ export default function Billing() {
)}
>
{isPlanCanceling
? `Cancels on ${cancelEndsLabel}${cancelEndsDays !== null ? ` · ${cancelEndsDays} day${cancelEndsDays !== 1 ? "s" : ""} left` : ""}. You'll move to Free after that.`
: hasPaidPlan
? "Expanded memory, connections, and usage for this workspace."
: "Upgrade when you need more workspace usage and integrations."}
? `Cancels on ${cancelEndsLabel}${cancelEndsDays !== null ? ` · ${cancelEndsDays} day${cancelEndsDays !== 1 ? "s" : ""} left` : ""}.${isCompanyBrain ? "" : " You'll move to Free after that."}`
: isOnTrial
? [
trialEndsLabel
? `Ends ${trialEndsLabel}${trialDaysLeft != null ? ` · ${trialDaysLeft} day${trialDaysLeft !== 1 ? "s" : ""} left` : ""}`
: null,
trialCredits != null
? `$${trialCredits} trial credits`
: null,
]
.filter(Boolean)
.join(" · ")
: isBrainTrialEnded
? "Trial ended. Activate Scale to restore access."
: hasPaidPlan
? "Expanded memory, connections, and usage for this workspace."
: "Upgrade when you need more workspace usage and integrations."}
</p>
{isBrainTrialEnded ? (
<div className="mt-3">
<button
type="button"
onClick={() => void handleUpgrade("api_scale")}
disabled={
isUpgrading || isCheckingStatus || autumn.isLoading
}
className={cn(
dmSans125ClassName(),
"inline-flex h-7 items-center gap-1.5 rounded-[7px] bg-[#0054AD] px-2.5 text-[12px] font-semibold text-[#FAFAFA] transition-colors hover:bg-[#0B65C9] disabled:opacity-60",
)}
>
{isUpgrading ? (
<LoaderIcon className="size-3 animate-spin" />
) : null}
Activate Scale
</button>
</div>
) : null}
</div>
<div className="flex shrink-0 items-center gap-2">
@ -1216,51 +1362,64 @@ export default function Billing() {
</div>
</div>
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between gap-3">
{showPlanUsage ? (
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between gap-3">
<p
className={cn(
dmSans125ClassName(),
"text-[13px] font-medium text-[#A3A3A3]",
)}
>
{isOnTrial ? "Trial credit usage" : "Plan usage"}
</p>
<p
className={cn(
dmSans125ClassName(),
"text-[13px] font-semibold tabular-nums text-[#FAFAFA]",
)}
>
{formatUsd(usdSpent)}
{usdIncluded > 0 ? (
<span className="font-medium text-[#737373]">
{" "}
/ {formatUsd(usdIncluded)}
</span>
) : null}
<span className="ml-2 text-[#A3A3A3]">
{planUsagePct < 1 && planUsagePct > 0
? "< 1"
: Math.round(planUsagePct)}
% used
</span>
</p>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-[#2E353D]">
<div
className="h-full rounded-full bg-[#4BA0FA] transition-all"
style={{
width: `${planUsagePct}%`,
background:
planUsagePct > 80
? "#C73B1B"
: "linear-gradient(90deg, #2368D2 0%, #4BA0FA 100%)",
}}
/>
</div>
<p
className={cn(
dmSans125ClassName(),
"text-[13px] font-medium text-[#A3A3A3]",
"text-[12px] text-[#737373]",
)}
>
Plan usage
</p>
<p
className={cn(
dmSans125ClassName(),
"text-[13px] font-semibold tabular-nums text-[#FAFAFA]",
)}
>
{planUsagePct < 1 && planUsagePct > 0
? "< 1"
: Math.round(planUsagePct)}
% used
{isOnTrial
? "Credits apply for the trial period"
: daysRemaining !== null
? `Resets in ${daysRemaining} day${daysRemaining !== 1 ? "s" : ""}`
: "Usage resets with your billing cycle"}
</p>
</div>
<div className="h-2 w-full overflow-hidden rounded-full bg-[#2E353D]">
<div
className="h-full rounded-full bg-[#4BA0FA] transition-all"
style={{
width: `${planUsagePct}%`,
background:
planUsagePct > 80
? "#C73B1B"
: "linear-gradient(90deg, #2368D2 0%, #4BA0FA 100%)",
}}
/>
</div>
<p
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#737373]",
)}
>
{daysRemaining !== null
? `Resets in ${daysRemaining} day${daysRemaining !== 1 ? "s" : ""}`
: "Usage resets with your billing cycle"}
</p>
</div>
) : null}
</div>
</SettingsCard>
</section>
@ -1268,7 +1427,7 @@ export default function Billing() {
<section id="billing-plans" className="flex flex-col gap-4">
<SectionTitle
aside={
isPlanCarouselActive ? (
!isCompanyBrain && isPlanCarouselActive ? (
<div className="flex items-center gap-1.5">
<button
type="button"
@ -1294,55 +1453,81 @@ export default function Billing() {
>
Plans
</SectionTitle>
<div className="overflow-hidden">
<div
className="flex gap-4 transition-transform duration-300 ease-out"
style={{
transform:
planPage === 1 ? "translateX(calc(-100% - 1rem))" : "none",
}}
>
<div className="grid w-full shrink-0 gap-4 md:grid-cols-2">
{PLAN_CARDS.map((plan) => (
<PlanCard
action={getPlanCardAction(plan)}
key={plan.id}
plan={plan}
/>
))}
</div>
<div className="grid w-full shrink-0 gap-4 md:grid-cols-3">
{ADVANCED_PLAN_CARDS.map((plan) => (
<PlanCard
action={getPlanCardAction(plan)}
key={plan.id}
plan={plan}
/>
))}
</div>
</div>
</div>
{isPlanCarouselActive ? null : (
<div className="flex justify-end px-2 pt-1">
<button
type="button"
onClick={() => {
setIsPlanCarouselActive(true)
setPlanPage(1)
}}
className={cn(
dmSans125ClassName(),
"inline-flex items-center justify-center gap-2 text-[13px] font-semibold text-[#A3A3A3] transition-colors hover:text-[#FAFAFA]",
)}
>
<span className="relative after:absolute after:right-0 after:-bottom-0.5 after:left-0 after:h-px after:origin-left after:scale-x-0 after:bg-current after:transition-transform after:duration-200 hover:after:scale-x-100">
Other plans
</span>
<span className="translate-x-1 text-[15px]" aria-hidden="true">
&rarr;
</span>
</button>
{isCompanyBrain ? (
<div className="grid w-full gap-4 md:grid-cols-2">
{COMPANY_BRAIN_PLAN_CARDS.map((plan) => (
<PlanCard
action={getPlanCardAction(plan)}
key={plan.id}
plan={
plan.id === "scale" && isOnTrial && trialCredits != null
? {
...plan,
credits: `$${trialCredits} trial / $600 paid`,
description:
"14-day free trial with Company Brain — activate anytime",
}
: plan
}
/>
))}
</div>
) : (
<>
<div className="overflow-hidden">
<div
className="flex gap-4 transition-transform duration-300 ease-out"
style={{
transform:
planPage === 1 ? "translateX(calc(-100% - 1rem))" : "none",
}}
>
<div className="grid w-full shrink-0 gap-4 md:grid-cols-2">
{PLAN_CARDS.map((plan) => (
<PlanCard
action={getPlanCardAction(plan)}
key={plan.id}
plan={plan}
/>
))}
</div>
<div className="grid w-full shrink-0 gap-4 md:grid-cols-3">
{ADVANCED_PLAN_CARDS.map((plan) => (
<PlanCard
action={getPlanCardAction(plan)}
key={plan.id}
plan={plan}
/>
))}
</div>
</div>
</div>
{isPlanCarouselActive ? null : (
<div className="flex justify-end px-2 pt-1">
<button
type="button"
onClick={() => {
setIsPlanCarouselActive(true)
setPlanPage(1)
}}
className={cn(
dmSans125ClassName(),
"inline-flex items-center justify-center gap-2 text-[13px] font-semibold text-[#A3A3A3] transition-colors hover:text-[#FAFAFA]",
)}
>
<span className="relative after:absolute after:right-0 after:-bottom-0.5 after:left-0 after:h-px after:origin-left after:scale-x-0 after:bg-current after:transition-transform after:duration-200 hover:after:scale-x-100">
Other plans
</span>
<span
className="translate-x-1 text-[15px]"
aria-hidden="true"
>
&rarr;
</span>
</button>
</div>
)}
</>
)}
</section>
@ -1567,16 +1752,16 @@ export default function Billing() {
</DialogContent>
</Dialog>
{hasPaidPlan ? (
{hasPaidPlan || isOnTrial ? (
<section className="flex flex-col gap-4">
<SectionTitle>Credits</SectionTitle>
<SettingsCard className="border border-dashed border-white/10 bg-[#14161A]/70">
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
{isOnTrial ? (
<SettingsCard>
<div className="flex min-w-0 items-start gap-3">
<Coins className="mt-1 size-4 shrink-0 text-[#4BA0FA]" />
<div className="min-w-0">
<p className="text-[11px] font-bold uppercase tracking-[0.5px] text-[#737373]">
Top-up credits
Trial credits
</p>
<p
className={cn(
@ -1584,32 +1769,72 @@ export default function Billing() {
"mt-2 text-[14px] font-semibold text-[#FAFAFA]",
)}
>
{creditRemaining > 0
? `${formatUsd(creditRemaining)} available`
: "No top-up credits yet"}
{formatUsd(creditRemaining)} remaining
{usdIncluded > 0 ? (
<span className="font-medium text-[#737373]">
{" "}
of {formatUsd(usdIncluded)}
</span>
) : trialCredits != null ? (
<span className="font-medium text-[#737373]">
{" "}
of {formatUsd(trialCredits)}
</span>
) : null}
</p>
<p className="mt-2 text-[12px] leading-snug text-[#737373]">
Optional add-on that{" "}
Company Brain trials include{" "}
<span className="font-semibold text-[#A3A3A3]">
rolls over
${trialCredits ?? 200}
</span>{" "}
month-to-month, separate from your monthly usage above.
in usage credits. Paid Scale includes $600/mo. Top-ups are
available after you activate.
</p>
</div>
</div>
<button
type="button"
onClick={() => setIsCreditsDialogOpen(true)}
className={cn(
dmSans125ClassName(),
"inline-flex h-9 shrink-0 items-center justify-center gap-2 rounded-[9px] border border-white/10 bg-[#0D121A] px-3 text-[13px] font-medium text-[#FAFAFA] transition-colors hover:bg-[#121A24]",
)}
>
<Plus className="size-3.5" />
{creditRemaining > 0 ? "Add more" : "Buy credits"}
</button>
</div>
</SettingsCard>
</SettingsCard>
) : (
<SettingsCard className="border border-dashed border-white/10 bg-[#14161A]/70">
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div className="flex min-w-0 items-start gap-3">
<Coins className="mt-1 size-4 shrink-0 text-[#4BA0FA]" />
<div className="min-w-0">
<p className="text-[11px] font-bold uppercase tracking-[0.5px] text-[#737373]">
Top-up credits
</p>
<p
className={cn(
dmSans125ClassName(),
"mt-2 text-[14px] font-semibold text-[#FAFAFA]",
)}
>
{creditRemaining > 0
? `${formatUsd(creditRemaining)} available`
: "No top-up credits yet"}
</p>
<p className="mt-2 text-[12px] leading-snug text-[#737373]">
Optional add-on that{" "}
<span className="font-semibold text-[#A3A3A3]">
rolls over
</span>{" "}
month-to-month, separate from your monthly usage above.
</p>
</div>
</div>
<button
type="button"
onClick={() => setIsCreditsDialogOpen(true)}
className={cn(
dmSans125ClassName(),
"inline-flex h-9 shrink-0 items-center justify-center gap-2 rounded-[9px] border border-white/10 bg-[#0D121A] px-3 text-[13px] font-medium text-[#FAFAFA] transition-colors hover:bg-[#121A24]",
)}
>
<Plus className="size-3.5" />
{creditRemaining > 0 ? "Add more" : "Buy credits"}
</button>
</div>
</SettingsCard>
)}
</section>
) : null}

View file

@ -39,7 +39,8 @@ const TOKEN_METER_IDS = [
] as const
export function useTokenUsage(autumn: ReturnType<typeof useCustomer>) {
const status = getSubscriptionStatus(autumn.data?.subscriptions)
const subscriptions = autumn.data?.subscriptions
const status = getSubscriptionStatus(subscriptions)
let currentPlan: PlanType = "free"
if (isAllowedFrom(status, "api_enterprise")) {
@ -54,6 +55,24 @@ export function useTokenUsage(autumn: ReturnType<typeof useCustomer>) {
const hasPaidPlan = currentPlan !== "free"
const planProductId =
currentPlan === "free" ? null : (`api_${currentPlan}` as const)
const currentSub = planProductId
? subscriptions?.find((s) => s.planId === planProductId)
: undefined
const isTrialing = currentSub?.status === "trialing"
const trialEndsAtMs = (() => {
if (!currentSub) return null
const sub = currentSub as {
trialEndsAt?: number | null
currentPeriodEnd?: number | null
expiresAt?: number | null
}
const raw = sub.trialEndsAt ?? sub.currentPeriodEnd ?? sub.expiresAt
if (raw == null) return null
return raw < 10_000_000_000 ? raw * 1000 : raw
})()
const balances = autumn.data?.balances ?? {}
const tokensUsed = TOKEN_METER_IDS.reduce((sum, id) => {
@ -88,6 +107,8 @@ export function useTokenUsage(autumn: ReturnType<typeof useCustomer>) {
planUsagePct,
currentPlan,
hasPaidPlan,
isTrialing,
trialEndsAtMs,
isLoading,
daysRemaining,
}

View file

@ -112,6 +112,78 @@ export function getBrainMode(
: null
}
export type BrainTrialStatus =
| "active"
| "exhausted"
| "expired"
| "converted"
| "skipped"
export type BrainTrialInfo = {
status: BrainTrialStatus | null
startedAtMs: number | null
endsAtMs: number | null
credits: number | null
daysRemaining: number | null
}
function parseOrgMetadata(
metadataRaw: Record<string, unknown> | string | null | undefined,
): Record<string, unknown> | null {
if (!metadataRaw) return null
if (typeof metadataRaw === "string") {
try {
return JSON.parse(metadataRaw) as Record<string, unknown>
} catch {
return null
}
}
return metadataRaw
}
/** Company Brain Slack trial fields written by mono after OAuth attach. */
export function getBrainTrialInfo(
metadataRaw: Record<string, unknown> | string | null | undefined,
): BrainTrialInfo {
const metadata = parseOrgMetadata(metadataRaw)
const rawStatus = metadata?.brainTrialStatus
const status =
rawStatus === "active" ||
rawStatus === "exhausted" ||
rawStatus === "expired" ||
rawStatus === "converted" ||
rawStatus === "skipped"
? rawStatus
: null
const startedAtMs =
typeof metadata?.brainTrialStartedAt === "string"
? Date.parse(metadata.brainTrialStartedAt)
: Number.NaN
const endsAtMs =
typeof metadata?.brainTrialEndsAt === "string"
? Date.parse(metadata.brainTrialEndsAt)
: Number.NaN
const credits =
typeof metadata?.brainTrialCredits === "number"
? metadata.brainTrialCredits
: null
const safeEnds = Number.isFinite(endsAtMs) ? endsAtMs : null
const daysRemaining =
safeEnds != null
? Math.max(0, Math.ceil((safeEnds - Date.now()) / (1000 * 60 * 60 * 24)))
: null
return {
status,
startedAtMs: Number.isFinite(startedAtMs) ? startedAtMs : null,
endsAtMs: safeEnds,
credits,
daysRemaining,
}
}
/**
* Format a number with K/M suffix for display
* @example formatUsageNumber(1500000) => "1.5M"

View file

@ -27,6 +27,10 @@ const DEFAULT_SUBSCRIPTION_STATUS: SubscriptionStatusMap = {
api_enterprise: { allowed: false, status: null },
}
function isLiveSubscriptionStatus(status: string | null | undefined): boolean {
return status === "active" || status === "trialing"
}
export function isAllowedFrom(
status: SubscriptionStatusMap,
minimumTier: PlanTier,
@ -34,7 +38,7 @@ export function isAllowedFrom(
const minIndex = PLAN_TIERS.indexOf(minimumTier)
return PLAN_TIERS.slice(minIndex).some((tier) => {
const s = status[tier]
return s?.status === "active"
return isLiveSubscriptionStatus(s?.status)
})
}
@ -49,7 +53,7 @@ export function getSubscriptionStatus(
for (const tier of PLAN_TIERS) {
const sub = subMap.get(tier)
statusMap[tier] = {
allowed: sub?.status === "active",
allowed: isLiveSubscriptionStatus(sub?.status),
status: sub?.status ?? null,
}
}