Files
digital-home-dashboard/src/app/api/claude-sub/route.ts
Cosmo 1d4a00a80d
All checks were successful
Build & Deploy Dashboard / deploy (push) Successful in 1m2s
fix: claude-sub uses bridge HTTP instead of direct WS
2026-04-16 09:45:29 +00:00

62 lines
1.9 KiB
TypeScript

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";
export async function GET() {
try {
const res = await fetch(BRIDGE_URL, {
signal: AbortSignal.timeout(5000),
cache: "no-store",
});
if (!res.ok) throw new Error(`Bridge 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;
});
return NextResponse.json({
ok: true,
anthropic: {
window5h: window5h || null,
windowWeek: windowWeek || null,
windowSonnet: windowSonnet || null,
error: anthropicProvider?.error || null,
plan: anthropicProvider?.plan || 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,
});
}
}