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,
+ });
+}