diff --git a/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/UsagePanelContent.tsx b/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/UsagePanelContent.tsx index fe420d145d..a24a281ba4 100644 --- a/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/UsagePanelContent.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/UsagePanelContent.tsx @@ -3,6 +3,7 @@ import { Button } from "@/components/atoms/Button/Button"; import Link from "next/link"; import { formatCents } from "../RateLimitResetDialog/RateLimitResetDialog"; import { useResetRateLimit } from "../../hooks/useResetRateLimit"; +import { useWorkspaceStorage } from "./useWorkspaceStorage"; export function formatResetTime( resetsAt: Date | string, @@ -73,6 +74,57 @@ function UsageBar({ ); } +export function formatBytes(bytes: number): string { + if (bytes < 1024) return `${bytes} B`; + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`; + if (bytes < 1024 * 1024 * 1024) + return `${(bytes / (1024 * 1024)).toFixed(0)} MB`; + return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`; +} + +function StorageBar({ + usedBytes, + limitBytes, + fileCount, +}: { + usedBytes: number; + limitBytes: number; + fileCount: number; +}) { + if (limitBytes <= 0) return null; + + const rawPercent = (usedBytes / limitBytes) * 100; + const percent = Math.min(100, Math.round(rawPercent)); + const isHigh = percent >= 80; + const percentLabel = + usedBytes > 0 && percent === 0 ? "<1% used" : `${percent}% used`; + + return ( +
+
+ + File storage + + + {percentLabel} + +
+
+ {formatBytes(usedBytes)} of {formatBytes(limitBytes)} ·{" "} + {fileCount} {fileCount === 1 ? "file" : "files"} +
+
+
0 ? 1 : 0, percent)}%` }} + /> +
+
+ ); +} + function ResetButton({ cost, onCreditChange, @@ -97,6 +149,19 @@ function ResetButton({ ); } +function WorkspaceStorageSection() { + const { data: storage } = useWorkspaceStorage(); + if (!storage || storage.limit_bytes <= 0) return null; + + return ( + + ); +} + export function UsagePanelContent({ usage, showBillingLink = true, @@ -154,6 +219,7 @@ export function UsagePanelContent({ resetsAt={usage.weekly.resets_at} /> )} + {isDailyExhausted && !isWeeklyExhausted && resetCost > 0 && diff --git a/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/useWorkspaceStorage.ts b/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/useWorkspaceStorage.ts new file mode 100644 index 0000000000..a0b064cfbb --- /dev/null +++ b/autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/useWorkspaceStorage.ts @@ -0,0 +1,25 @@ +import { useQuery } from "@tanstack/react-query"; +import { customMutator } from "@/app/api/mutators/custom-mutator"; + +type StorageUsage = { + used_bytes: number; + limit_bytes: number; + used_percent: number; + file_count: number; +}; + +export function useWorkspaceStorage() { + return useQuery({ + queryKey: ["workspace", "storage", "usage"], + queryFn: async () => { + const res = await customMutator<{ + data: StorageUsage; + status: number; + headers: Headers; + }>("/api/workspace/storage/usage", { method: "GET" }); + return res.data; + }, + staleTime: 30000, + refetchInterval: 60000, + }); +}