From a8c4f5c0ad9c53fd2582a19241eac85f4e37fdf2 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Tue, 16 Dec 2025 15:50:33 -0800 Subject: [PATCH 1/7] Add limit v1 --- .../copilot-message/components/index.ts | 1 + .../components/usage-limit-actions.tsx | 146 ++++++++++++++++++ .../copilot-message/copilot-message.tsx | 4 + apps/sim/stores/panel/copilot/store.ts | 21 ++- apps/sim/stores/panel/copilot/types.ts | 1 + 5 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/index.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/index.ts index cca1f618e8..75eb971876 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/index.ts @@ -2,3 +2,4 @@ export * from './file-display' export { default as CopilotMarkdownRenderer } from './markdown-renderer' export * from './smooth-streaming' export * from './thinking-block' +export * from './usage-limit-actions' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx new file mode 100644 index 0000000000..e4a0e58d65 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx @@ -0,0 +1,146 @@ +'use client' + +import { useState } from 'react' +import { useParams, useRouter } from 'next/navigation' +import { ArrowRight, Check, CreditCard, Loader2 } from 'lucide-react' +import { Button } from '@/components/emcn' +import { useSubscriptionData, useUpdateUsageLimit } from '@/hooks/queries/subscription' +import { canEditUsageLimit } from '@/lib/billing/subscriptions/utils' + +/** + * Component that displays actionable UI when a user hits their usage limit + * Shows inline input to increase limit or button to upgrade plan + */ +export function UsageLimitActions() { + const router = useRouter() + const params = useParams() + const workspaceId = params?.workspaceId as string + const { data: subscriptionData } = useSubscriptionData() + const updateUsageLimitMutation = useUpdateUsageLimit() + + const subscription = subscriptionData?.subscription + const canEdit = subscription ? canEditUsageLimit(subscription) : false + const currentLimit = subscriptionData?.data?.usage?.limit || 10 + const currentUsage = subscriptionData?.data?.usage?.current || 0 + + // Suggest an increase of at least $10 or enough to cover current usage + $5 + const suggestedIncrease = Math.max(10, Math.ceil(currentUsage - currentLimit + 5)) + const suggestedLimit = currentLimit + suggestedIncrease + + const [newLimit, setNewLimit] = useState(suggestedLimit.toString()) + const [showSuccess, setShowSuccess] = useState(false) + + const handleUpdateLimit = async () => { + const limitValue = Number.parseFloat(newLimit) + if (Number.isNaN(limitValue) || limitValue <= currentLimit) { + return + } + + try { + await updateUsageLimitMutation.mutateAsync({ limit: limitValue }) + setShowSuccess(true) + setTimeout(() => setShowSuccess(false), 3000) + } catch (error) { + // Error is handled by the mutation + } + } + + const handleNavigateToUpgrade = () => { + router.push(`/workspace/${workspaceId}/settings?tab=subscription`) + } + + if (!canEdit) { + // Show upgrade button for users who can't edit (free/enterprise) + return ( +
+
+ +
+

+ Usage Limit Reached +

+

+ Upgrade your plan to get higher limits and continue using the copilot. +

+
+
+ +
+ ) + } + + // Show inline edit for users who can edit their limit + return ( +
+
+ +
+

+ Usage Limit Reached +

+

+ Current limit: ${currentLimit}. Increase your limit to continue. +

+
+
+ + {showSuccess ? ( +
+ + + Limit updated successfully! + +
+ ) : ( +
+
+ + $ + + setNewLimit(e.target.value)} + min={currentLimit} + step='1' + className='h-9 w-full rounded-md border border-orange-300 bg-white pl-6 pr-3 text-sm text-gray-900 focus:border-orange-500 focus:outline-none focus:ring-1 focus:ring-orange-500 dark:border-orange-700 dark:bg-gray-800 dark:text-gray-100' + placeholder={suggestedLimit.toString()} + /> +
+ +
+ )} + + {updateUsageLimitMutation.isError && ( +

+ {updateUsageLimitMutation.error?.message || 'Failed to update limit'} +

+ )} +
+ ) +} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx index b1d8a1a12a..ab5ba28d2f 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx @@ -9,6 +9,7 @@ import { SmoothStreamingText, StreamingIndicator, ThinkingBlock, + UsageLimitActions, } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components' import CopilotMarkdownRenderer from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/markdown-renderer' import { @@ -458,6 +459,9 @@ const CopilotMessage: FC = memo( )} + {/* Usage limit actions for 402 errors */} + {message.errorType === 'usage_limit' && } + {/* Action buttons for completed messages */} {!isStreaming && cleanTextContent && (
diff --git a/apps/sim/stores/panel/copilot/store.ts b/apps/sim/stores/panel/copilot/store.ts index a350fb2d88..cb645adcb1 100644 --- a/apps/sim/stores/panel/copilot/store.ts +++ b/apps/sim/stores/panel/copilot/store.ts @@ -533,7 +533,11 @@ function createStreamingMessage(): CopilotMessage { } } -function createErrorMessage(messageId: string, content: string): CopilotMessage { +function createErrorMessage( + messageId: string, + content: string, + errorType?: 'usage_limit' | 'unauthorized' | 'forbidden' | 'rate_limit' | 'upgrade_required' +): CopilotMessage { return { id: messageId, role: 'assistant', @@ -546,6 +550,7 @@ function createErrorMessage(messageId: string, content: string): CopilotMessage timestamp: Date.now(), }, ], + errorType, } } @@ -2066,23 +2071,35 @@ export const useCopilotStore = create()( // Check for specific status codes and provide custom messages let errorContent = result.error || 'Failed to send message' + let errorType: + | 'usage_limit' + | 'unauthorized' + | 'forbidden' + | 'rate_limit' + | 'upgrade_required' + | undefined = undefined if (result.status === 401) { errorContent = '_Unauthorized request. You need a valid API key to use the copilot. You can get one by going to [sim.ai](https://sim.ai) settings and generating one there._' + errorType = 'unauthorized' } else if (result.status === 402) { errorContent = '_Usage limit exceeded. To continue using this service, upgrade your plan or top up on credits._' + errorType = 'usage_limit' } else if (result.status === 403) { errorContent = '_Provider config not allowed for non-enterprise users. Please remove the provider config and try again_' + errorType = 'forbidden' } else if (result.status === 426) { errorContent = '_Please upgrade to the latest version of the Sim platform to continue using the copilot._' + errorType = 'upgrade_required' } else if (result.status === 429) { errorContent = '_Provider rate limit exceeded. Please try again later._' + errorType = 'rate_limit' } - const errorMessage = createErrorMessage(streamingMessage.id, errorContent) + const errorMessage = createErrorMessage(streamingMessage.id, errorContent, errorType) set((state) => ({ messages: state.messages.map((m) => (m.id === streamingMessage.id ? errorMessage : m)), error: errorContent, diff --git a/apps/sim/stores/panel/copilot/types.ts b/apps/sim/stores/panel/copilot/types.ts index 2380aca2b1..201508935d 100644 --- a/apps/sim/stores/panel/copilot/types.ts +++ b/apps/sim/stores/panel/copilot/types.ts @@ -39,6 +39,7 @@ export interface CopilotMessage { > fileAttachments?: MessageFileAttachment[] contexts?: ChatContext[] + errorType?: 'usage_limit' | 'unauthorized' | 'forbidden' | 'rate_limit' | 'upgrade_required' } // Contexts attached to a user message From 79aa83fe5cb4c91566e1cb58adef1bbcb135a264 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Thu, 18 Dec 2025 17:37:32 -0800 Subject: [PATCH 2/7] fix ui for copilot upgrade limit inline --- .../components/usage-limit-actions.tsx | 173 +++++++----------- apps/sim/stores/panel/copilot/store.ts | 4 +- 2 files changed, 72 insertions(+), 105 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx index e4a0e58d65..c3da9eabd9 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx @@ -1,15 +1,17 @@ 'use client' import { useState } from 'react' +import { ArrowRight, Loader2 } from 'lucide-react' import { useParams, useRouter } from 'next/navigation' -import { ArrowRight, Check, CreditCard, Loader2 } from 'lucide-react' import { Button } from '@/components/emcn' -import { useSubscriptionData, useUpdateUsageLimit } from '@/hooks/queries/subscription' import { canEditUsageLimit } from '@/lib/billing/subscriptions/utils' +import { useSubscriptionData, useUpdateUsageLimit } from '@/hooks/queries/subscription' +import { useCopilotStore } from '@/stores/panel/copilot/store' /** * Component that displays actionable UI when a user hits their usage limit - * Shows inline input to increase limit or button to upgrade plan + * Shows button options to increase limit or button to upgrade plan + * After updating limit, retries the original user query */ export function UsageLimitActions() { const router = useRouter() @@ -17,31 +19,53 @@ export function UsageLimitActions() { const workspaceId = params?.workspaceId as string const { data: subscriptionData } = useSubscriptionData() const updateUsageLimitMutation = useUpdateUsageLimit() - - const subscription = subscriptionData?.subscription + + // The billing API returns { success, context, data }, where data contains plan/status + const subscription = subscriptionData?.data const canEdit = subscription ? canEditUsageLimit(subscription) : false - const currentLimit = subscriptionData?.data?.usage?.limit || 10 - const currentUsage = subscriptionData?.data?.usage?.current || 0 - - // Suggest an increase of at least $10 or enough to cover current usage + $5 - const suggestedIncrease = Math.max(10, Math.ceil(currentUsage - currentLimit + 5)) - const suggestedLimit = currentLimit + suggestedIncrease - - const [newLimit, setNewLimit] = useState(suggestedLimit.toString()) - const [showSuccess, setShowSuccess] = useState(false) - - const handleUpdateLimit = async () => { - const limitValue = Number.parseFloat(newLimit) - if (Number.isNaN(limitValue) || limitValue <= currentLimit) { - return - } + const [selectedAmount, setSelectedAmount] = useState(null) + const [isHidden, setIsHidden] = useState(false) + + // Fixed limit options + const limitOptions = [50, 100, 150] + + const handleUpdateLimit = async (newLimit: number) => { + setSelectedAmount(newLimit) try { - await updateUsageLimitMutation.mutateAsync({ limit: limitValue }) - setShowSuccess(true) - setTimeout(() => setShowSuccess(false), 3000) + await updateUsageLimitMutation.mutateAsync({ limit: newLimit }) + + // Hide the buttons immediately + setIsHidden(true) + + // Get the store state and retry the last user message + const { messages, sendMessage } = useCopilotStore.getState() + + // Find the last user message (before the error) + const lastUserMessage = [...messages].reverse().find((m) => m.role === 'user') + + if (lastUserMessage) { + // Remove the error message (assistant message with usage_limit error) + const filteredMessages = messages.filter( + (m) => !(m.role === 'assistant' && m.errorType === 'usage_limit') + ) + + // Update messages to remove the error message + useCopilotStore.setState({ messages: filteredMessages }) + + // Retry the original query by passing the same messageId + // This replaces from that point instead of duplicating + await sendMessage(lastUserMessage.content, { + fileAttachments: lastUserMessage.fileAttachments, + contexts: lastUserMessage.contexts, + messageId: lastUserMessage.id, + }) + } } catch (error) { // Error is handled by the mutation + setIsHidden(false) + } finally { + setSelectedAmount(null) } } @@ -49,98 +73,41 @@ export function UsageLimitActions() { router.push(`/workspace/${workspaceId}/settings?tab=subscription`) } + // Hide if already processed + if (isHidden) { + return null + } + if (!canEdit) { // Show upgrade button for users who can't edit (free/enterprise) return ( -
-
- -
-

- Usage Limit Reached -

-

- Upgrade your plan to get higher limits and continue using the copilot. -

-
-
-
) } - // Show inline edit for users who can edit their limit + // Show button options for users who can edit their limit return ( -
-
- -
-

- Usage Limit Reached -

-

- Current limit: ${currentLimit}. Increase your limit to continue. -

-
-
- - {showSuccess ? ( -
- - - Limit updated successfully! - -
- ) : ( -
-
- - $ - - setNewLimit(e.target.value)} - min={currentLimit} - step='1' - className='h-9 w-full rounded-md border border-orange-300 bg-white pl-6 pr-3 text-sm text-gray-900 focus:border-orange-500 focus:outline-none focus:ring-1 focus:ring-orange-500 dark:border-orange-700 dark:bg-gray-800 dark:text-gray-100' - placeholder={suggestedLimit.toString()} - /> -
+
+ {limitOptions.map((limit) => { + const isLoading = updateUsageLimitMutation.isPending && selectedAmount === limit + const isDisabled = updateUsageLimitMutation.isPending + + return ( -
- )} - - {updateUsageLimitMutation.isError && ( -

- {updateUsageLimitMutation.error?.message || 'Failed to update limit'} -

- )} + ) + })}
) } diff --git a/apps/sim/stores/panel/copilot/store.ts b/apps/sim/stores/panel/copilot/store.ts index cb645adcb1..7235074f28 100644 --- a/apps/sim/stores/panel/copilot/store.ts +++ b/apps/sim/stores/panel/copilot/store.ts @@ -2077,14 +2077,14 @@ export const useCopilotStore = create()( | 'forbidden' | 'rate_limit' | 'upgrade_required' - | undefined = undefined + | undefined if (result.status === 401) { errorContent = '_Unauthorized request. You need a valid API key to use the copilot. You can get one by going to [sim.ai](https://sim.ai) settings and generating one there._' errorType = 'unauthorized' } else if (result.status === 402) { errorContent = - '_Usage limit exceeded. To continue using this service, upgrade your plan or top up on credits._' + '_Usage limit exceeded. To continue using this service, upgrade your plan or increase your usage limit to:_' errorType = 'usage_limit' } else if (result.status === 403) { errorContent = From 6a9eeb5f0c579f9bb8e6327b84b268b406ba964b Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Thu, 18 Dec 2025 18:06:59 -0800 Subject: [PATCH 3/7] open settings modal --- .../copilot-message/components/usage-limit-actions.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx index c3da9eabd9..34afe08f14 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx @@ -2,7 +2,6 @@ import { useState } from 'react' import { ArrowRight, Loader2 } from 'lucide-react' -import { useParams, useRouter } from 'next/navigation' import { Button } from '@/components/emcn' import { canEditUsageLimit } from '@/lib/billing/subscriptions/utils' import { useSubscriptionData, useUpdateUsageLimit } from '@/hooks/queries/subscription' @@ -14,9 +13,6 @@ import { useCopilotStore } from '@/stores/panel/copilot/store' * After updating limit, retries the original user query */ export function UsageLimitActions() { - const router = useRouter() - const params = useParams() - const workspaceId = params?.workspaceId as string const { data: subscriptionData } = useSubscriptionData() const updateUsageLimitMutation = useUpdateUsageLimit() @@ -70,7 +66,7 @@ export function UsageLimitActions() { } const handleNavigateToUpgrade = () => { - router.push(`/workspace/${workspaceId}/settings?tab=subscription`) + window.dispatchEvent(new CustomEvent('open-settings', { detail: { tab: 'subscription' } })) } // Hide if already processed From 8f43e3d183683c453246cfbe7f9fe78b5a4e34a8 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Thu, 18 Dec 2025 18:16:34 -0800 Subject: [PATCH 4/7] Upgrade plan button --- .../copilot-message/components/usage-limit-actions.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx index 34afe08f14..56a2c9afb7 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx @@ -1,7 +1,7 @@ 'use client' import { useState } from 'react' -import { ArrowRight, Loader2 } from 'lucide-react' +import { Loader2 } from 'lucide-react' import { Button } from '@/components/emcn' import { canEditUsageLimit } from '@/lib/billing/subscriptions/utils' import { useSubscriptionData, useUpdateUsageLimit } from '@/hooks/queries/subscription' @@ -80,7 +80,6 @@ export function UsageLimitActions() {
) From e1675d6a51405b7c514dd7f871d536bff4b1950f Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Thu, 18 Dec 2025 18:20:04 -0800 Subject: [PATCH 5/7] Remove comments --- .../components/usage-limit-actions.tsx | 17 +---------------- .../copilot-message/copilot-message.tsx | 1 - 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx index 56a2c9afb7..0280e597ad 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx @@ -16,14 +16,12 @@ export function UsageLimitActions() { const { data: subscriptionData } = useSubscriptionData() const updateUsageLimitMutation = useUpdateUsageLimit() - // The billing API returns { success, context, data }, where data contains plan/status const subscription = subscriptionData?.data const canEdit = subscription ? canEditUsageLimit(subscription) : false const [selectedAmount, setSelectedAmount] = useState(null) const [isHidden, setIsHidden] = useState(false) - // Fixed limit options const limitOptions = [50, 100, 150] const handleUpdateLimit = async (newLimit: number) => { @@ -31,34 +29,24 @@ export function UsageLimitActions() { try { await updateUsageLimitMutation.mutateAsync({ limit: newLimit }) - // Hide the buttons immediately setIsHidden(true) - // Get the store state and retry the last user message const { messages, sendMessage } = useCopilotStore.getState() - - // Find the last user message (before the error) const lastUserMessage = [...messages].reverse().find((m) => m.role === 'user') if (lastUserMessage) { - // Remove the error message (assistant message with usage_limit error) const filteredMessages = messages.filter( (m) => !(m.role === 'assistant' && m.errorType === 'usage_limit') ) - - // Update messages to remove the error message useCopilotStore.setState({ messages: filteredMessages }) - // Retry the original query by passing the same messageId - // This replaces from that point instead of duplicating await sendMessage(lastUserMessage.content, { fileAttachments: lastUserMessage.fileAttachments, contexts: lastUserMessage.contexts, messageId: lastUserMessage.id, }) } - } catch (error) { - // Error is handled by the mutation + } catch { setIsHidden(false) } finally { setSelectedAmount(null) @@ -69,13 +57,11 @@ export function UsageLimitActions() { window.dispatchEvent(new CustomEvent('open-settings', { detail: { tab: 'subscription' } })) } - // Hide if already processed if (isHidden) { return null } if (!canEdit) { - // Show upgrade button for users who can't edit (free/enterprise) return (
-
+ ) } return ( -
+ <> {limitOptions.map((limit) => { const isLoading = updateUsageLimitMutation.isPending && selectedAmount === limit const isDisabled = updateUsageLimitMutation.isPending @@ -88,6 +91,6 @@ export function UsageLimitActions() { ) })} -
+ ) } diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx index 08dcb54cfe..8a865cfbf0 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx @@ -459,7 +459,11 @@ const CopilotMessage: FC = memo( )} - {message.errorType === 'usage_limit' && } + {message.errorType === 'usage_limit' && ( +
+ +
+ )} {/* Action buttons for completed messages */} {!isStreaming && cleanTextContent && ( From fd40e25aba3a768705a4dd3f4eac6b3c2865a14d Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Fri, 19 Dec 2025 10:13:32 -0800 Subject: [PATCH 7/7] Fix hardcoded bumps --- .../components/usage-limit-actions.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx index f9184ce035..0683694588 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/usage-limit-actions.tsx @@ -8,11 +8,12 @@ import { isHosted } from '@/lib/core/config/feature-flags' import { useSubscriptionData, useUpdateUsageLimit } from '@/hooks/queries/subscription' import { useCopilotStore } from '@/stores/panel/copilot/store' -/** - * Component that displays actionable UI when a user hits their usage limit - * Shows button options to increase limit or button to upgrade plan - * After updating limit, retries the original user query - */ +const LIMIT_INCREMENTS = [0, 50, 100] as const + +function roundUpToNearest50(value: number): number { + return Math.ceil(value / 50) * 50 +} + export function UsageLimitActions() { const { data: subscriptionData } = useSubscriptionData() const updateUsageLimitMutation = useUpdateUsageLimit() @@ -23,7 +24,9 @@ export function UsageLimitActions() { const [selectedAmount, setSelectedAmount] = useState(null) const [isHidden, setIsHidden] = useState(false) - const limitOptions = [50, 100, 150] + const currentLimit = subscription?.usage_limit ?? 0 + const baseLimit = roundUpToNearest50(currentLimit) || 50 + const limitOptions = LIMIT_INCREMENTS.map((increment) => baseLimit + increment) const handleUpdateLimit = async (newLimit: number) => { setSelectedAmount(newLimit)