diff --git a/src/app/(dashboard)/page.tsx b/src/app/(dashboard)/page.tsx
index 8d486c9..33d4513 100644
--- a/src/app/(dashboard)/page.tsx
+++ b/src/app/(dashboard)/page.tsx
@@ -1,10 +1,10 @@
export const dynamic = "force-dynamic";
-
import { WeatherWidget } from "@/components/widgets/WeatherWidget";
import { CalendarWidget } from "@/components/widgets/CalendarWidget";
import { DashboardHeader } from "@/components/widgets/DashboardHeader";
import { SavingsWidget } from "@/components/widgets/SavingsWidget";
import { GitActivityWidget } from "@/components/widgets/GitActivityWidget";
+import { ClaudeUsageWidget } from "@/components/widgets/ClaudeUsageWidget";
export default function DashboardPage() {
return (
@@ -18,6 +18,7 @@ export default function DashboardPage() {
+
diff --git a/src/app/api/claude-sub/route.ts b/src/app/api/claude-sub/route.ts
index 0c3a82a..ffa3c7a 100644
--- a/src/app/api/claude-sub/route.ts
+++ b/src/app/api/claude-sub/route.ts
@@ -1,61 +1,34 @@
export const dynamic = "force-dynamic";
import { NextResponse } from "next/server";
-// Bridge HTTP API (cosmo-studio bridge в той же сети coolify)
-const BRIDGE_URL = "http://172.18.0.5:3402/api/usage";
+const PROXY_URL = "http://192.168.31.103:3301/claude-oauth-usage";
export async function GET() {
try {
- const res = await fetch(BRIDGE_URL, {
- signal: AbortSignal.timeout(5000),
+ const res = await fetch(PROXY_URL, {
+ signal: AbortSignal.timeout(8000),
cache: "no-store",
});
-
- if (!res.ok) throw new Error(`Bridge HTTP ${res.status}`);
+ if (!res.ok) throw new Error(`Proxy HTTP ${res.status}`);
const data = await res.json();
- const usage = data.usage;
- if (!usage) {
- return NextResponse.json({ ok: false, error: "No usage data yet" });
- }
-
- // Найти данные Anthropic
- const anthropicProvider = usage.planLimits?.providers?.find(
- (p: any) => p.provider === "anthropic"
- );
- const windows = anthropicProvider?.windows || [];
- const window5h = windows.find((w: any) => w.label?.includes("5") || w.label === "5h");
- const windowWeek = windows.find((w: any) => w.label?.toLowerCase().includes("week"));
- const windowSonnet = windows.find((w: any) => w.label?.toLowerCase().includes("sonnet"));
-
- // Стоимость сегодня
- const todayEntry = usage.cost?.daily?.find((d: any) => {
- const today = new Date().toISOString().split("T")[0];
- return d.date === today;
- });
+ const toWindow = (obj: any) => obj ? {
+ label: obj.label || "",
+ usedPercent: obj.utilization ?? 0,
+ resetAt: obj.resets_at ? new Date(obj.resets_at).getTime() : undefined,
+ } : null;
return NextResponse.json({
ok: true,
anthropic: {
- window5h: window5h || null,
- windowWeek: windowWeek || null,
- windowSonnet: windowSonnet || null,
- error: anthropicProvider?.error || null,
- plan: anthropicProvider?.plan || null,
+ window5h: toWindow(data.five_hour),
+ windowWeek: toWindow(data.seven_day),
+ windowSonnet: toWindow(data.seven_day_sonnet),
+ error: null,
},
- cost: {
- today: todayEntry?.totalCost || 0,
- todayTokens: todayEntry?.totalTokens || 0,
- total: usage.cost?.totals?.totalCost || 0,
- },
- updatedAt: usage.updatedAt,
- });
- } catch (e) {
- return NextResponse.json({
- ok: false,
- error: String(e),
- anthropic: null,
cost: null,
});
+ } catch (e) {
+ return NextResponse.json({ ok: false, error: String(e), anthropic: null, cost: null });
}
}