omniroute 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/.next/BUILD_ID +1 -1
- package/app/.next/build-manifest.json +2 -2
- package/app/.next/prerender-manifest.json +3 -3
- package/app/.next/server/app/(dashboard)/dashboard/a2a/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/agents/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/api-manager/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/audit-log/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/auto-combo/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/costs/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/health/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/limits/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/logs/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/mcp/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/media/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/onboarding/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/playground/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/search-tools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/settings/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/400/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/401/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/403/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/408/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/429/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/500/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/502/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/503/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error.html +2 -2
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/docs/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/forbidden/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/forgot-password/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/maintenance/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/privacy/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/status/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/terms/page_client-reference-manifest.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__051203a6._.js +2 -2
- package/app/.next/server/chunks/[root-of-the-server]__0891af92._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__1f2b0d89._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__61d78f9d._.js +2 -2
- package/app/.next/server/chunks/[root-of-the-server]__6e52619e._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__afddb4ce._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__e27a89bd._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__fd2fbc93._.js +1 -1
- package/app/.next/server/chunks/_05c48915._.js +1 -1
- package/app/.next/server/chunks/_06515a8a._.js +1 -1
- package/app/.next/server/chunks/_2115d8de._.js +1 -1
- package/app/.next/server/chunks/_3ac953eb._.js +1 -1
- package/app/.next/server/chunks/_4b8fd853._.js +1 -1
- package/app/.next/server/chunks/_68683848._.js +1 -1
- package/app/.next/server/chunks/_6f1b3c3f._.js +1 -1
- package/app/.next/server/chunks/_ee9b677b._.js +1 -1
- package/app/.next/server/chunks/_efd5ede2._.js +2 -2
- package/app/.next/server/chunks/_ffda39da._.js +1 -1
- package/app/.next/server/chunks/open-sse_translator_index_ts_f5fd0821._.js +1 -1
- package/app/.next/server/chunks/src_6320c728._.js +1 -1
- package/app/.next/server/chunks/ssr/[root-of-the-server]__9ef96d20._.js +1 -1
- package/app/.next/server/chunks/ssr/[root-of-the-server]__a6942102._.js +1 -1
- package/app/.next/server/chunks/ssr/_f3674909._.js +1 -1
- package/app/.next/server/chunks/ssr/src_a82a42f9._.js +1 -1
- package/app/.next/server/chunks/ssr/src_app_(dashboard)_dashboard_936a9ee0._.js +1 -1
- package/app/.next/server/chunks/ssr/src_app_(dashboard)_dashboard_settings_9e20fb8d._.js +1 -1
- package/app/.next/server/pages/500.html +2 -2
- package/app/.next/server/server-reference-manifest.js +1 -1
- package/app/.next/server/server-reference-manifest.json +1 -1
- package/app/.next/static/chunks/26aeb12cf79339b1.js +1 -0
- package/app/.next/static/chunks/{80658e0c2b2c7004.js → 633a312ddcf9fa11.js} +1 -1
- package/app/.next/static/chunks/7df0b3c357097db5.js +1 -0
- package/app/.next/static/chunks/a051245b46459ad2.css +1 -0
- package/app/.next/static/chunks/d188e358e1ec0a7d.js +1 -0
- package/app/.next/static/chunks/{4e3fe685e3218d24.js → fa9e2a946d2cdbc7.js} +1 -1
- package/app/CHANGELOG.md +122 -68
- package/app/docs/i18n/ru/README.md +3 -3
- package/app/docs/openapi.yaml +1 -1
- package/app/open-sse/handlers/chatCore.ts +9 -2
- package/app/open-sse/handlers/responseTranslator.ts +13 -3
- package/app/open-sse/services/usage.ts +22 -9
- package/app/open-sse/translator/request/openai-to-claude.ts +10 -2
- package/app/package-lock.json +2 -2
- package/app/package.json +1 -1
- package/app/src/app/(dashboard)/dashboard/providers/[id]/page.tsx +198 -63
- package/app/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx +123 -19
- package/app/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx +22 -24
- package/app/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx +5 -0
- package/app/src/lib/providers/validation.ts +21 -0
- package/app/src/shared/components/ProxyConfigModal.tsx +42 -13
- package/package.json +1 -1
- package/app/.next/static/chunks/594bdf69c19b5310.js +0 -1
- package/app/.next/static/chunks/643428fcd3f9bb51.js +0 -1
- package/app/.next/static/chunks/8efe14530c87d9f6.css +0 -1
- package/app/.next/static/chunks/d0cff7a6c3a66c7d.js +0 -1
- /package/app/.next/static/{cQZnxkFFvb8O7T4x7OSsG → bF7pUIj1e9VsHgSW5x9WX}/_buildManifest.js +0 -0
- /package/app/.next/static/{cQZnxkFFvb8O7T4x7OSsG → bF7pUIj1e9VsHgSW5x9WX}/_clientMiddlewareManifest.json +0 -0
- /package/app/.next/static/{cQZnxkFFvb8O7T4x7OSsG → bF7pUIj1e9VsHgSW5x9WX}/_ssgManifest.js +0 -0
|
@@ -412,24 +412,25 @@ export default function ProviderLimits() {
|
|
|
412
412
|
|
|
413
413
|
<div className="flex items-center gap-2">
|
|
414
414
|
{/* Group by toggle */}
|
|
415
|
-
<div className="flex rounded-lg border border-
|
|
415
|
+
<div className="flex rounded-lg border border-border overflow-hidden">
|
|
416
416
|
<button
|
|
417
417
|
onClick={() => handleSetGroupBy("none")}
|
|
418
418
|
className="px-2.5 py-1.5 text-[12px] font-medium cursor-pointer border-none"
|
|
419
419
|
style={{
|
|
420
|
-
background: groupBy === "none" ? "
|
|
421
|
-
color: groupBy === "none" ? "var(--text-main)" : "var(--text-muted)",
|
|
420
|
+
background: groupBy === "none" ? "var(--color-bg-subtle)" : "transparent",
|
|
421
|
+
color: groupBy === "none" ? "var(--color-text-main)" : "var(--color-text-muted)",
|
|
422
422
|
}}
|
|
423
423
|
>
|
|
424
424
|
{t("viewFlat")}
|
|
425
425
|
</button>
|
|
426
426
|
<button
|
|
427
427
|
onClick={() => handleSetGroupBy("environment")}
|
|
428
|
-
className="px-2.5 py-1.5 text-[12px] font-medium cursor-pointer border-none
|
|
428
|
+
className="px-2.5 py-1.5 text-[12px] font-medium cursor-pointer border-none"
|
|
429
429
|
style={{
|
|
430
|
-
background: groupBy === "environment" ? "
|
|
431
|
-
color:
|
|
432
|
-
|
|
430
|
+
background: groupBy === "environment" ? "var(--color-bg-subtle)" : "transparent",
|
|
431
|
+
color:
|
|
432
|
+
groupBy === "environment" ? "var(--color-text-main)" : "var(--color-text-muted)",
|
|
433
|
+
borderLeft: "1px solid var(--color-border)",
|
|
433
434
|
}}
|
|
434
435
|
>
|
|
435
436
|
{t("viewByEnvironment")}
|
|
@@ -442,7 +443,7 @@ export default function ProviderLimits() {
|
|
|
442
443
|
setAutoRefresh(next);
|
|
443
444
|
localStorage.setItem(LS_AUTO_REFRESH, String(next));
|
|
444
445
|
}}
|
|
445
|
-
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-
|
|
446
|
+
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-border bg-transparent cursor-pointer text-text-main text-[13px]"
|
|
446
447
|
>
|
|
447
448
|
<span
|
|
448
449
|
className="material-symbols-outlined text-[18px]"
|
|
@@ -459,7 +460,7 @@ export default function ProviderLimits() {
|
|
|
459
460
|
<button
|
|
460
461
|
onClick={refreshAll}
|
|
461
462
|
disabled={refreshingAll}
|
|
462
|
-
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg bg-
|
|
463
|
+
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg bg-bg-subtle border border-border text-text-main text-[13px] disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
|
|
463
464
|
>
|
|
464
465
|
<span
|
|
465
466
|
className={`material-symbols-outlined text-[16px] ${refreshingAll ? "animate-spin" : ""}`}
|
|
@@ -483,10 +484,10 @@ export default function ProviderLimits() {
|
|
|
483
484
|
className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold cursor-pointer"
|
|
484
485
|
style={{
|
|
485
486
|
border: active
|
|
486
|
-
? "1px solid var(--primary, #E54D5E)"
|
|
487
|
-
: "1px solid
|
|
488
|
-
background: active ? "rgba(
|
|
489
|
-
color: active ? "var(--primary, #E54D5E)" : "var(--text-muted)",
|
|
487
|
+
? "1px solid var(--color-primary, #E54D5E)"
|
|
488
|
+
: "1px solid var(--color-border)",
|
|
489
|
+
background: active ? "rgba(229,77,94,0.1)" : "transparent",
|
|
490
|
+
color: active ? "var(--color-primary, #E54D5E)" : "var(--color-text-muted)",
|
|
490
491
|
}}
|
|
491
492
|
>
|
|
492
493
|
<span>{t(tier.labelKey)}</span>
|
|
@@ -497,10 +498,10 @@ export default function ProviderLimits() {
|
|
|
497
498
|
</div>
|
|
498
499
|
|
|
499
500
|
{/* Account rows */}
|
|
500
|
-
<div className="rounded-xl border border-
|
|
501
|
+
<div className="rounded-xl border border-border overflow-hidden bg-bg-subtle">
|
|
501
502
|
{/* Table header */}
|
|
502
503
|
<div
|
|
503
|
-
className="items-center px-4 py-2.5 border-b border-
|
|
504
|
+
className="items-center px-4 py-2.5 border-b border-border text-[11px] font-semibold uppercase tracking-wider text-text-muted"
|
|
504
505
|
style={{ display: "grid", gridTemplateColumns: "280px 1fr 100px 48px" }}
|
|
505
506
|
>
|
|
506
507
|
<div>{t("account")}</div>
|
|
@@ -523,11 +524,11 @@ export default function ProviderLimits() {
|
|
|
523
524
|
return (
|
|
524
525
|
<div
|
|
525
526
|
key={conn.id}
|
|
526
|
-
className="items-center px-4 py-3.5 transition-[background] duration-150 hover:bg-white/[0.02]"
|
|
527
|
+
className="items-center px-4 py-3.5 transition-[background] duration-150 hover:bg-black/[0.03] dark:hover:bg-white/[0.02]"
|
|
527
528
|
style={{
|
|
528
529
|
display: "grid",
|
|
529
530
|
gridTemplateColumns: "280px 1fr 100px 48px",
|
|
530
|
-
borderBottom: !isLast ? "1px solid
|
|
531
|
+
borderBottom: !isLast ? "1px solid var(--color-border)" : "none",
|
|
531
532
|
}}
|
|
532
533
|
>
|
|
533
534
|
{/* Account Info */}
|
|
@@ -614,7 +615,7 @@ export default function ProviderLimits() {
|
|
|
614
615
|
) : null}
|
|
615
616
|
|
|
616
617
|
{/* Progress bar */}
|
|
617
|
-
<div className="flex-1 h-1.5 rounded-sm bg-white/[0.06] min-w-[60px] overflow-hidden">
|
|
618
|
+
<div className="flex-1 h-1.5 rounded-sm bg-black/[0.06] dark:bg-white/[0.06] min-w-[60px] overflow-hidden">
|
|
618
619
|
<div
|
|
619
620
|
className="h-full rounded-sm transition-[width] duration-300 ease-out"
|
|
620
621
|
style={{
|
|
@@ -672,13 +673,10 @@ export default function ProviderLimits() {
|
|
|
672
673
|
if (groupedConnections) {
|
|
673
674
|
const entries = [...groupedConnections.entries()];
|
|
674
675
|
return entries.map(([groupName, conns]) => (
|
|
675
|
-
<div
|
|
676
|
-
key={groupName}
|
|
677
|
-
className="border border-white/[0.08] rounded-lg overflow-hidden mb-2"
|
|
678
|
-
>
|
|
676
|
+
<div key={groupName} className="border border-border rounded-lg overflow-hidden mb-2">
|
|
679
677
|
<button
|
|
680
678
|
onClick={() => toggleGroup(groupName)}
|
|
681
|
-
className="w-full flex items-center gap-2 px-4 py-2.5 bg-
|
|
679
|
+
className="w-full flex items-center gap-2 px-4 py-2.5 bg-bg-subtle hover:bg-black/[0.04] dark:hover:bg-white/[0.05] transition-colors text-left border-none cursor-pointer"
|
|
682
680
|
>
|
|
683
681
|
<span className="material-symbols-outlined text-[16px] text-text-muted">
|
|
684
682
|
{expandedGroups.has(groupName) ? "expand_less" : "expand_more"}
|
|
@@ -689,7 +687,7 @@ export default function ProviderLimits() {
|
|
|
689
687
|
<span className="text-[12px] font-semibold text-text-main uppercase tracking-wider flex-1">
|
|
690
688
|
{groupName}
|
|
691
689
|
</span>
|
|
692
|
-
<span className="text-[11px] text-text-muted bg-white/[0.06] px-2 py-0.5 rounded-full">
|
|
690
|
+
<span className="text-[11px] text-text-muted bg-black/[0.04] dark:bg-white/[0.06] px-2 py-0.5 rounded-full">
|
|
693
691
|
{conns.length}
|
|
694
692
|
</span>
|
|
695
693
|
</button>
|
|
@@ -222,6 +222,11 @@ export function normalizePlanTier(plan) {
|
|
|
222
222
|
|
|
223
223
|
const upper = raw.toUpperCase();
|
|
224
224
|
|
|
225
|
+
// Provider names that are not real plan tiers — treat as unknown
|
|
226
|
+
if (upper === "CLAUDE CODE" || upper === "KIMI CODING" || upper === "KIRO") {
|
|
227
|
+
return { key: "unknown", label: raw, variant: "default", rank: 0, raw };
|
|
228
|
+
}
|
|
229
|
+
|
|
225
230
|
if (upper.includes("PRO+") || upper.includes("PRO PLUS") || upper.includes("PROPLUS")) {
|
|
226
231
|
return { key: "plus", label: "Pro+", variant: "secondary", rank: 4, raw };
|
|
227
232
|
}
|
|
@@ -652,6 +652,27 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi
|
|
|
652
652
|
elevenlabs: validateElevenLabsProvider,
|
|
653
653
|
inworld: validateInworldProvider,
|
|
654
654
|
"bailian-coding-plan": validateBailianCodingPlanProvider,
|
|
655
|
+
// LongCat AI — does not expose /v1/models; validate via chat completions directly (#592)
|
|
656
|
+
longcat: async ({ apiKey }: any) => {
|
|
657
|
+
try {
|
|
658
|
+
const res = await fetch("https://longcat.chat/api/v1/chat/completions", {
|
|
659
|
+
method: "POST",
|
|
660
|
+
headers: buildBearerHeaders(apiKey),
|
|
661
|
+
body: JSON.stringify({
|
|
662
|
+
model: "longcat",
|
|
663
|
+
messages: [{ role: "user", content: "test" }],
|
|
664
|
+
max_tokens: 1,
|
|
665
|
+
}),
|
|
666
|
+
});
|
|
667
|
+
if (res.status === 401 || res.status === 403) {
|
|
668
|
+
return { valid: false, error: "Invalid API key" };
|
|
669
|
+
}
|
|
670
|
+
// Any non-auth response (200, 400, 422) means auth passed
|
|
671
|
+
return { valid: true, error: null };
|
|
672
|
+
} catch (error: any) {
|
|
673
|
+
return { valid: false, error: error.message || "Connection failed" };
|
|
674
|
+
}
|
|
675
|
+
},
|
|
655
676
|
// Search providers — use factored validator
|
|
656
677
|
...Object.fromEntries(
|
|
657
678
|
Object.entries(SEARCH_VALIDATOR_CONFIGS).map(([id, configFn]) => [
|
|
@@ -245,6 +245,7 @@ export default function ProxyConfigModal({
|
|
|
245
245
|
setSelectedProxyId("");
|
|
246
246
|
}
|
|
247
247
|
onSaved?.();
|
|
248
|
+
onClose();
|
|
248
249
|
} catch (error) {
|
|
249
250
|
console.error("Error saving proxy:", error);
|
|
250
251
|
setFormError(error.message || "Failed to save proxy configuration");
|
|
@@ -281,6 +282,7 @@ export default function ProxyConfigModal({
|
|
|
281
282
|
setSelectedProxyId("");
|
|
282
283
|
setTestResult(null);
|
|
283
284
|
onSaved?.();
|
|
285
|
+
onClose();
|
|
284
286
|
} catch (error) {
|
|
285
287
|
console.error("Error clearing proxy:", error);
|
|
286
288
|
setFormError(error.message || "Failed to clear proxy configuration");
|
|
@@ -290,22 +292,49 @@ export default function ProxyConfigModal({
|
|
|
290
292
|
};
|
|
291
293
|
|
|
292
294
|
const handleTest = async () => {
|
|
293
|
-
if (mode === "saved") {
|
|
294
|
-
setFormError("Use custom mode to run manual connection test.");
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
if (!host.trim()) return;
|
|
298
295
|
setFormError(null);
|
|
299
296
|
setTesting(true);
|
|
300
297
|
setTestResult(null);
|
|
301
298
|
try {
|
|
302
|
-
|
|
303
|
-
type:
|
|
304
|
-
host:
|
|
305
|
-
port:
|
|
306
|
-
username
|
|
307
|
-
password
|
|
308
|
-
};
|
|
299
|
+
let proxy: {
|
|
300
|
+
type: string;
|
|
301
|
+
host: string;
|
|
302
|
+
port: string;
|
|
303
|
+
username?: string;
|
|
304
|
+
password?: string;
|
|
305
|
+
} | null = null;
|
|
306
|
+
|
|
307
|
+
if (mode === "saved") {
|
|
308
|
+
if (!selectedProxyId) {
|
|
309
|
+
setFormError("Select a saved proxy first.");
|
|
310
|
+
setTesting(false);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const found = (savedProxies as any[]).find((p: any) => p.id === selectedProxyId);
|
|
314
|
+
if (!found) {
|
|
315
|
+
setFormError("Selected proxy not found.");
|
|
316
|
+
setTesting(false);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
proxy = {
|
|
320
|
+
type: found.type || "http",
|
|
321
|
+
host: found.host || "",
|
|
322
|
+
port: String(found.port || 8080),
|
|
323
|
+
};
|
|
324
|
+
} else {
|
|
325
|
+
if (!host.trim()) {
|
|
326
|
+
setTesting(false);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
proxy = {
|
|
330
|
+
type: proxyType,
|
|
331
|
+
host: host.trim(),
|
|
332
|
+
port: port.trim() || getDefaultPort(proxyType),
|
|
333
|
+
username: username.trim(),
|
|
334
|
+
password: password.trim(),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
309
338
|
const res = await fetch("/api/settings/proxy/test", {
|
|
310
339
|
method: "POST",
|
|
311
340
|
headers: { "Content-Type": "application/json" },
|
|
@@ -550,7 +579,7 @@ export default function ProxyConfigModal({
|
|
|
550
579
|
icon="speed"
|
|
551
580
|
onClick={handleTest}
|
|
552
581
|
loading={testing}
|
|
553
|
-
disabled={mode
|
|
582
|
+
disabled={mode === "saved" ? !selectedProxyId : !host.trim()}
|
|
554
583
|
>
|
|
555
584
|
Test Connection
|
|
556
585
|
</Button>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omniroute",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,710864,e=>{"use strict";var t=e.i(843476),r=e.i(271645),a=e.i(174080),s=e.i(627949),l=e.i(745009),i=e.i(618566),o=e.i(522016),n=e.i(657688),d=e.i(948148);e.i(565650);var c=e.i(11477),p=e.i(474078),u=e.i(628029),m=e.i(339971),x=e.i(87855),h=e.i(454149),f=e.i(116016),f=f,g=e.i(567955),g=g,v=e.i(419947),v=v,b=e.i(148943),y=e.i(961430),j=e.i(105370),N=e.i(623249);e.i(313705);var C=e.i(25230),w=e.i(556938);let k=["openai","openai-responses","claude"];function S(e){let t=new Map;for(let r of e)r.id&&t.set(r.id,r);return t}function T(e,t,r){return e?.compatByProtocol?.[r]??t?.compatByProtocol?.[r]}function P(e,t,r,a){let s=r.get(e),l=a.get(e),i=T(s,l,t);return i&&Object.prototype.hasOwnProperty.call(i,"normalizeToolCallId")?!!i.normalizeToolCallId:!!s?.normalizeToolCallId||!!l?.normalizeToolCallId}function R(e,t,r,a){let s=r.get(e),l=a.get(e),i=T(s,l,t);return i&&Object.prototype.hasOwnProperty.call(i,"preserveOpenAIDeveloperRole")?!!i.preserveOpenAIDeveloperRole:s&&Object.prototype.hasOwnProperty.call(s,"preserveOpenAIDeveloperRole")?!!s.preserveOpenAIDeveloperRole:!(l&&Object.prototype.hasOwnProperty.call(l,"preserveOpenAIDeveloperRole"))||!!l.preserveOpenAIDeveloperRole}async function I(e){try{let t=await e.json(),r=t?.error;if(Array.isArray(r?.details)&&r.details.length>0)return r.details.map(e=>{let t="string"==typeof e.field&&e.field?e.field:"?",r="string"==typeof e.message?e.message:"";return r?`${t}: ${r}`:t}).join("; ");if("string"==typeof r?.message&&r.message.trim())return r.message.trim()}catch{}return e.statusText?.trim()||`HTTP ${e.status}`}function M(e,t,r,a){let s=r.get(e),l=a.get(e),i={};s?.upstreamHeaders&&"object"==typeof s.upstreamHeaders?Object.assign(i,s.upstreamHeaders):l?.upstreamHeaders&&"object"==typeof l.upstreamHeaders&&Object.assign(i,l.upstreamHeaders);let o=T(s,l,t);return o?.upstreamHeaders&&"object"==typeof o.upstreamHeaders&&Object.assign(i,o.upstreamHeaders),i}function A(e){let t=e&&"object"==typeof e&&!Array.isArray(e)?e:{};return{use5h:"boolean"!=typeof t.use5h||t.use5h,useWeekly:"boolean"!=typeof t.useWeekly||t.useWeekly}}function O({t:e,effectiveModelNormalize:s,effectiveModelPreserveDeveloper:l,getUpstreamHeadersRecord:i,onCompatPatch:o,showDeveloperToggle:n=!0,disabled:d}){let[c,p]=(0,r.useState)(!1),[u,x]=(0,r.useState)(k[0]),[h,f]=(0,r.useState)([]),[g,v]=(0,r.useState)(null),[y,j]=(0,r.useState)(null),N=(0,r.useRef)(null),C=(0,r.useRef)(null),[w,S]=(0,r.useState)(null),T=(0,r.useRef)(0),P=(0,r.useRef)([]);P.current=h;let R=()=>(T.current+=1,`uh-${T.current}`),I=s(u),M=l(u),A=n&&"claude"!==u,O=(0,r.useCallback)(e=>{let t,r,a=function(e){let t={};for(let r of e){let e=r.name.trim();e&&(t[e]=r.value)}return t}(e),s=i(u);t=Object.keys(a).sort(),r=Object.keys(s).sort(),t.length===r.length&&t.every((e,t)=>e===r[t]&&a[e]===s[e])||o(u,{upstreamHeaders:a})},[i,o,u]),E=(0,r.useCallback)(()=>{queueMicrotask(()=>O(P.current))},[O]);(0,r.useEffect)(()=>{if(c)return()=>{O(P.current)}},[c,O]),(0,r.useEffect)(()=>{var e;let t;c&&f((e=i(u),0===(t=Object.entries(e).filter(([e])=>e.trim())).length?[{id:R(),name:"",value:""}]:t.map(([e,t])=>({id:R(),name:e,value:t}))))},[c,u]),(0,r.useEffect)(()=>{v(null),j(null)},[c,u]);let D=h.filter(e=>e.name.trim()).length<16,U=(e,t)=>{f(r=>r.map(r=>r.id===e?{...r,...t}:r))};(0,r.useEffect)(()=>{if(!c)return;let e=e=>{let t=e.target,r=N.current?.contains(t),a=C.current?.contains(t);r||a||p(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[c]);let L=(0,r.useCallback)(()=>{if(!c||!N.current)return;let e=N.current.getBoundingClientRect(),t=Math.min(window.innerWidth-20,384),r=e.right-t;r=Math.max(10,Math.min(r,window.innerWidth-t-10)),S({top:e.bottom+8,left:r,width:t})},[c]);return(0,r.useLayoutEffect)(()=>c?(L(),window.addEventListener("resize",L),window.addEventListener("scroll",L,!0),()=>{window.removeEventListener("resize",L),window.removeEventListener("scroll",L,!0)}):void S(null),[c,L]),(0,t.jsxs)("div",{className:"relative inline-flex",ref:N,children:[(0,t.jsxs)("button",{type:"button",onClick:()=>p(e=>!e),disabled:d,className:"inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-lg border border-border bg-background text-text-muted hover:bg-muted hover:text-text-main disabled:opacity-50 transition-colors",title:e("compatAdjustmentsTitle"),children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-base leading-none",children:"tune"}),e("compatButtonLabel")]}),c&&"u">typeof document&&w&&(0,a.createPortal)((0,t.jsxs)("div",{ref:C,className:"flex max-h-[min(82vh,42rem)] flex-col overflow-hidden rounded-xl border-2 border-zinc-200 bg-white shadow-2xl dark:border-zinc-600 dark:bg-zinc-950",style:{position:"fixed",top:w.top,left:w.left,width:w.width,zIndex:10040},children:[(0,t.jsxs)("div",{className:"shrink-0 border-b-2 border-zinc-200 bg-zinc-100 px-3 py-2.5 dark:border-zinc-600 dark:bg-zinc-900",children:[(0,t.jsx)("p",{className:"text-xs font-semibold text-text-main",children:e("compatAdjustmentsTitle")}),(0,t.jsx)("p",{className:"text-[11px] text-text-muted mt-1 leading-relaxed",children:e("compatProtocolHint")})]}),(0,t.jsxs)("div",{className:"min-h-0 flex-1 overflow-x-hidden overflow-y-auto bg-white p-3 [scrollbar-gutter:stable] [scrollbar-width:thin] dark:bg-zinc-950",children:[(0,t.jsx)("label",{className:"block text-[11px] font-medium text-text-muted mb-1.5",children:e("compatProtocolLabel")}),(0,t.jsx)("select",{value:u,onChange:e=>x(e.target.value),disabled:d,className:"mb-4 w-full rounded-lg border border-zinc-200 bg-white px-2.5 py-2 text-xs text-text-main focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-zinc-600 dark:bg-zinc-900",children:k.map(r=>(0,t.jsx)("option",{value:r,children:e("openai"===r?"compatProtocolOpenAI":"openai-responses"===r?"compatProtocolOpenAIResponses":"claude"===r?"compatProtocolClaude":"compatProtocolOpenAI")},r))}),(0,t.jsxs)("div",{className:"flex flex-col gap-3.5",children:[(0,t.jsx)(b.Toggle,{size:"sm",label:e("compatToolIdShort"),title:e("normalizeToolCallIdLabel"),checked:I,onChange:e=>o(u,{normalizeToolCallId:e}),disabled:d}),A&&(0,t.jsx)(b.Toggle,{size:"sm",label:e("compatDoNotPreserveDeveloper"),title:e("preserveDeveloperRoleLabel"),checked:!1===M,onChange:e=>o(u,{preserveOpenAIDeveloperRole:!e}),disabled:d})]}),(0,t.jsxs)("div",{className:"mt-4 rounded-lg border-2 border-zinc-200 bg-zinc-100 p-3 dark:border-zinc-600 dark:bg-zinc-900",children:[(0,t.jsx)("label",{className:"block text-[11px] font-semibold text-text-main mb-1",children:e("compatUpstreamHeadersLabel")}),(0,t.jsx)("p",{className:"text-[11px] text-text-muted mb-3 leading-relaxed",children:e("compatUpstreamHeadersHint")}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] gap-1.5 items-end text-[10px] font-medium uppercase tracking-wide text-text-muted px-0.5",children:[(0,t.jsx)("span",{children:e("compatUpstreamHeaderName")}),(0,t.jsx)("span",{className:"col-span-1",children:e("compatUpstreamHeaderValue")}),(0,t.jsx)("span",{className:"w-8 shrink-0","aria-hidden":!0})]}),h.map(r=>(0,t.jsxs)("div",{className:"grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] gap-1.5 items-center",children:[(0,t.jsx)(m.Input,{value:r.name,onChange:e=>U(r.id,{name:e.target.value}),onBlur:E,disabled:d,placeholder:"Authentication",className:"gap-0 min-w-0",inputClassName:"h-9 bg-white py-1.5 px-2 text-xs font-mono dark:bg-zinc-900",autoComplete:"off"}),(0,t.jsx)("div",{className:"min-w-0",onMouseEnter:()=>v(r.id),onMouseLeave:()=>v(e=>e===r.id?null:e),children:(0,t.jsx)(m.Input,{type:g===r.id||y===r.id?"text":"password",value:r.value,onChange:e=>U(r.id,{value:e.target.value}),onFocus:()=>j(r.id),onBlur:()=>{j(e=>e===r.id?null:e),E()},disabled:d,placeholder:"•••",className:"gap-0 min-w-0",inputClassName:"h-9 bg-white py-1.5 px-2 text-xs dark:bg-zinc-900",autoComplete:"off",spellCheck:!1})}),(0,t.jsx)("button",{type:"button",disabled:d||h.length<=1,onClick:()=>{var e;return e=r.id,void f(t=>{let r=t.filter(t=>t.id!==e),a=0===r.length?[{id:R(),name:"",value:""}]:r;return queueMicrotask(()=>O(a)),a})},title:e("compatUpstreamRemoveRow"),className:"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border/80 text-text-muted hover:bg-red-500/10 hover:text-red-600 dark:hover:text-red-400 disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-text-muted transition-colors",children:(0,t.jsx)("span",{className:"material-symbols-outlined text-lg leading-none",children:"close"})})]},r.id))]}),(0,t.jsxs)("button",{type:"button",disabled:d||!D,onClick:()=>{D&&f(e=>[...e,{id:R(),name:"",value:""}])},className:"mt-3 flex w-full items-center justify-center gap-1.5 rounded-lg border border-dashed border-border py-2 text-xs font-medium text-primary hover:bg-primary/5 disabled:opacity-40 disabled:hover:bg-transparent transition-colors",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-base leading-none",children:"add"}),e("compatUpstreamAddRow")]})]})]})]}),document.body)]})}function E(){let e=(0,i.useParams)(),a=(0,i.useRouter)(),l=e.id,[u,m]=(0,r.useState)([]),[b,y]=(0,r.useState)(!0),[T,O]=(0,r.useState)(null),[E,L]=(0,r.useState)(!1),[B,z]=(0,r.useState)(!1),[K,W]=(0,r.useState)(!1),[V,G]=(0,r.useState)(!1),[Y,Q]=(0,r.useState)(null),[X,Z]=(0,r.useState)(null),[ee,et]=(0,r.useState)(!1),[er,ea]=(0,r.useState)(null),[es,el]=(0,r.useState)({}),[ei,eo]=(0,r.useState)(!1),{copied:en,copy:ed}=(0,w.useCopyToClipboard)(),ec=(0,d.useTranslations)("providers"),ep=(0,s.useNotificationStore)(),eu=(0,r.useRef)(!1),em=(0,r.useRef)(!1),[ex,eh]=(0,r.useState)(null),[ef,eg]=(0,r.useState)(null),[ev,eb]=(0,r.useState)(!1),[ey,ej]=(0,r.useState)(!1),[eN,eC]=(0,r.useState)({current:0,total:0,phase:"idle",status:"",logs:[],error:"",importedCount:0}),[ew,ek]=(0,r.useState)({customModels:[],modelCompatOverrides:[]}),[eS,eT]=(0,r.useState)(null),eP=T?{id:T.id,name:T.name||("anthropic-compatible"===T.type?ec("anthropicCompatibleName"):ec("openaiCompatibleName")),color:"anthropic-compatible"===T.type?"#D97757":"#10A37F",textIcon:"anthropic-compatible"===T.type?"AC":"OC",apiType:T.apiType,baseUrl:T.baseUrl,type:T.type}:N.FREE_PROVIDERS[l]||N.OAUTH_PROVIDERS[l]||N.APIKEY_PROVIDERS[l],eR=!!N.FREE_PROVIDERS[l]||!!N.OAUTH_PROVIDERS[l],eI=(0,C.getModelsByProviderId)(l),eM=(0,N.getProviderAlias)(l),eA=(0,N.isOpenAICompatibleProvider)(l),eO=(0,N.isAnthropicCompatibleProvider)(l),eE=eA||eO,eD=l.endsWith("-search"),eU=eE?l:eM,eL=eE?T?.prefix||l:eM,e_=(0,r.useCallback)(async()=>{try{let e=await fetch("/api/models/alias"),t=await e.json();e.ok&&el(t.aliases||{})}catch(e){console.log("Error fetching aliases:",e)}},[]),e$=(0,r.useCallback)(async()=>{if(!eD)try{let e=await fetch(`/api/provider-models?provider=${encodeURIComponent(l)}`,{cache:"no-store"});if(!e.ok)return;let t=await e.json();ek({customModels:t.models||[],modelCompatOverrides:t.modelCompatOverrides||[]})}catch(e){console.error("fetchProviderModelMeta",e)}},[l,eD]),eB=(0,r.useCallback)(async()=>{try{let[e,t]=await Promise.all([fetch("/api/providers",{cache:"no-store"}),fetch("/api/provider-nodes",{cache:"no-store"})]),r=await e.json(),a=await t.json();if(e.ok){let e=(r.connections||[]).filter(e=>e.provider===l);m(e)}if(t.ok){let e=(a.nodes||[]).find(e=>e.id===l)||null;if(!e&&eE)for(let t=0;t<3;t+=1){await new Promise(e=>setTimeout(e,150));let t=await fetch("/api/provider-nodes",{cache:"no-store"});if(t.ok&&(e=((await t.json()).nodes||[]).find(e=>e.id===l)||null))break}O(e)}}catch(e){console.log("Error fetching connections:",e)}finally{y(!1)}},[l,eE]),ez=async e=>{try{let t=await fetch(`/api/provider-nodes/${l}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),r=await t.json();t.ok&&(O(r.node),await eB(),G(!1))}catch(e){console.log("Error updating provider node:",e)}};(0,r.useEffect)(()=>{eB(),e_(),fetch("/api/settings/proxy").then(e=>e.ok?e.json():null).then(e=>eg(e)).catch(()=>{})},[eB,e_]),(0,r.useEffect)(()=>{b||eD||e$()},[b,eD,e$]),(0,r.useEffect)(()=>{b||0!==u.length||!eP||eE||eu.current||em.current||(eu.current=!0,eR?L(!0):z(!0))},[b]);let eq=async(e,t,r=eM)=>{let a=`${r}/${e}`;try{let e=await fetch("/api/models/alias",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:a,alias:t})});if(e.ok)await e_();else{let t=await e.json();alert(t.error||ec("failedSetAlias"))}}catch(e){console.log("Error setting alias:",e)}},eF=async e=>{try{(await fetch(`/api/models/alias?alias=${encodeURIComponent(e)}`,{method:"DELETE"})).ok&&await e_()}catch(e){console.log("Error deleting alias:",e)}},eK=async e=>{if(confirm(ec("deleteConnectionConfirm")))try{(await fetch(`/api/providers/${e}`,{method:"DELETE"})).ok&&m(u.filter(t=>t.id!==e))}catch(e){console.log("Error deleting connection:",e)}},eH=(0,r.useCallback)(()=>{eB(),L(!1)},[eB]),eJ=async e=>{try{let t=await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:l,...e})});if(t.ok)return await eB(),z(!1),null;let r=await t.json().catch(()=>({}));return r.error?.message||r.error||ec("failedSaveConnection")}catch(e){return console.log("Error saving connection:",e),ec("failedSaveConnectionRetry")}},eW=async e=>{try{let t=await fetch(`/api/providers/${Y.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(t.ok)return await eB(),W(!1),null;let r=await t.json().catch(()=>({}));return r.error?.message||r.error||ec("failedSaveConnection")}catch(e){return console.log("Error updating connection:",e),ec("failedSaveConnectionRetry")}},eV=async(e,t)=>{try{(await fetch(`/api/providers/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:t})})).ok&&m(r=>r.map(r=>r.id===e?{...r,isActive:t}:r))}catch(e){console.log("Error updating connection status:",e)}},eG=async(e,t)=>{try{(await fetch("/api/rate-limits",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({connectionId:e,enabled:t})})).ok&&m(r=>r.map(r=>r.id===e?{...r,rateLimitProtection:t}:r))}catch(e){console.error("Error toggling rate limit:",e)}},eY=async(e,t,r)=>{try{let a=u.find(t=>t.id===e);if(!a)return;let s=a.providerSpecificData&&"object"==typeof a.providerSpecificData?a.providerSpecificData:{},l=s.codexLimitPolicy&&"object"==typeof s.codexLimitPolicy?s.codexLimitPolicy:{},i={...A(l),[t]:r},o=await fetch(`/api/providers/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerSpecificData:{...s,codexLimitPolicy:i}})});if(!o.ok){let e=await o.json().catch(()=>({}));ep.error(e.error||"Failed to update Codex limit policy");return}m(t=>t.map(t=>t.id===e?{...t,providerSpecificData:{...t.providerSpecificData||{},codexLimitPolicy:i}}:t)),ep.success("Codex limit policy updated")}catch(e){console.error("Error toggling Codex quota policy:",e),ep.error("Failed to update Codex limit policy")}},eQ=async e=>{if(e&&!X){Z(e);try{let t=await fetch(`/api/providers/${e}/test`,{method:"POST"});if(!t.ok){let e=await t.json().catch(()=>({}));alert(e.error||ec("failedRetestConnection"));return}await eB()}catch(e){console.error("Error retesting connection:",e)}finally{Z(null)}}},eX=async()=>{if(ee||0===u.length)return;et(!0),ea(null);let e=new AbortController,t=setTimeout(()=>e.abort(),12e4);try{let t,r=await fetch("/api/providers/test-batch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({mode:"provider",providerId:l}),signal:e.signal});try{t=await r.json()}catch{t={error:ec("providerTestFailed"),results:[],summary:null}}if(ea({...t,error:t.error?"object"==typeof t.error?t.error.message||t.error.error||JSON.stringify(t.error):String(t.error):null}),t?.summary){let{passed:e,failed:r,total:a}=t.summary;0===r?ep.success(ec("allTestsPassed",{total:a})):ep.warning(ec("testSummary",{passed:e,failed:r,total:a}))}await eB()}catch(t){let e=t?.name==="AbortError"?ec("providerTestTimeout"):ec("providerTestFailed");ea({error:e,results:[],summary:null}),ep.error(e)}finally{clearTimeout(t),et(!1)}},[eZ,e0]=(0,r.useState)(null),e1=async e=>{if(!eZ){e0(e);try{let t=await fetch(`/api/providers/${e}/refresh`,{method:"POST"}),r=await t.json().catch(()=>({}));t.ok&&r.success?(ep.success(ec("tokenRefreshed")),await eB()):ep.error(r.error||ec("tokenRefreshFailed"))}catch(e){console.error("Error refreshing token:",e),ep.error(ec("tokenRefreshFailed"))}finally{e0(null)}}},e5=async(e,t)=>{if(e&&t)try{let r=t.priority,a=e.priority;r===a&&(r=u.indexOf(e)>u.indexOf(t)?t.priority-.5:t.priority+.5),await Promise.all([fetch(`/api/providers/${e.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({priority:r})}),fetch(`/api/providers/${t.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({priority:a})})]),await eB()}catch(e){console.log("Error swapping priority:",e)}},e2=async()=>{if(ev)return;let e=u.find(e=>!1!==e.isActive);if(e){eb(!0),ej(!0),eC({current:0,total:0,phase:"fetching",status:ec("fetchingModels"),logs:[],error:"",importedCount:0});try{let t=await fetch(`/api/providers/${e.id}/models`),r=await t.json();if(!t.ok)return void eC(e=>({...e,phase:"error",status:ec("failedFetchModels"),error:r.error||ec("failedImportModels")}));let a=r.models||[];if(0===a.length)return void eC(e=>({...e,phase:"done",status:ec("noModelsFound"),logs:[ec("noModelsReturnedFromEndpoint")]}));eC(e=>({...e,phase:"importing",total:a.length,status:ec("importingModelsProgress",{current:0,total:a.length}),logs:[ec("foundModelsStartingImport",{count:a.length})]}));let s=0;for(let e=0;e<a.length;e++){let t=a[e],r=t.id||t.name||t.model;if(!r)continue;let i=r.split("/"),o=i[i.length-1];eC(t=>({...t,current:e+1,status:ec("importingModelsProgress",{current:e+1,total:a.length}),logs:[...t.logs,ec("importingModelById",{modelId:r})]})),await fetch("/api/provider-models",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:l,modelId:r,modelName:t.name||r,source:"imported"})}),es[o]||await eq(r,o,eU),s+=1}await e_(),eC(e=>({...e,phase:"done",current:a.length,status:s>0?ec("importSuccessCount",{count:s}):ec("noNewModelsAddedExisting"),logs:[...e.logs,s>0?ec("importDoneCount",{count:s}):ec("noNewModelsAdded")],importedCount:s})),s>0&&setTimeout(()=>{window.location.reload()},2e3)}catch(e){console.log("Error importing models:",e),eC(t=>({...t,phase:"error",status:ec("importFailed"),error:e instanceof Error?e.message:ec("unexpectedErrorOccurred")}))}finally{eb(!1)}}},e3=async(e,t)=>{ej(!0),eC({current:0,total:0,phase:"fetching",status:ec("fetchingModels"),logs:[],error:"",importedCount:0});try{let r=(await e()).models||[];if(0===r.length)return void eC(e=>({...e,phase:"done",status:ec("noModelsFound"),logs:[ec("noModelsReturnedFromEndpoint")]}));eC(e=>({...e,phase:"importing",total:r.length,status:ec("importingModelsProgress",{current:0,total:r.length}),logs:[ec("foundModelsStartingImport",{count:r.length})]}));let a=0;for(let e=0;e<r.length;e++){let s=r[e],l=s.id||s.name||s.model;l&&(eC(t=>({...t,current:e+1,status:ec("importingModelsProgress",{current:e+1,total:r.length}),logs:[...t.logs,ec("importingModelById",{modelId:l})]})),await t(s)&&(a+=1))}eC(e=>({...e,phase:"done",current:r.length,status:a>0?ec("importSuccessCount",{count:a}):ec("noNewModelsAdded"),logs:[...e.logs,a>0?ec("importDoneCount",{count:a}):ec("noNewModelsAdded")],importedCount:a})),a>0&&setTimeout(()=>{window.location.reload()},2e3)}catch(e){console.log("Error importing models:",e),eC(t=>({...t,phase:"error",status:ec("importFailed"),error:e instanceof Error?e.message:ec("unexpectedErrorOccurred")}))}},e4=u.some(e=>!1!==e.isActive),e6=(0,r.useMemo)(()=>S(ew.customModels),[ew.customModels]),e8=(0,r.useMemo)(()=>S(ew.modelCompatOverrides),[ew.modelCompatOverrides]),e9=(e,t=k[0])=>P(e,t,e6,e8),e7=(e,t=k[0])=>R(e,t,e6,e8),te=(0,r.useCallback)((e,t)=>M(e,t,e6,e8),[e6,e8]),tt=async(e,t)=>{eT(e);try{let r,a=e6.get(e),s=t.compatByProtocol&&void 0===t.normalizeToolCallId&&void 0===t.preserveOpenAIDeveloperRole&&!("upstreamHeaders"in t);a?s?r={provider:l,modelId:e,compatByProtocol:t.compatByProtocol}:(r={provider:l,modelId:e,modelName:a.name||e,source:a.source||"manual",apiFormat:a.apiFormat||"chat-completions",supportedEndpoints:Array.isArray(a.supportedEndpoints)&&a.supportedEndpoints.length?a.supportedEndpoints:["chat"],normalizeToolCallId:void 0!==t.normalizeToolCallId?t.normalizeToolCallId:!!a.normalizeToolCallId,preserveOpenAIDeveloperRole:void 0!==t.preserveOpenAIDeveloperRole?t.preserveOpenAIDeveloperRole:!Object.prototype.hasOwnProperty.call(a,"preserveOpenAIDeveloperRole")||!!a.preserveOpenAIDeveloperRole},t.compatByProtocol&&(r.compatByProtocol=t.compatByProtocol)):r={provider:l,modelId:e,...t};let i=await fetch("/api/provider-models",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!i.ok){let e=await I(i);ep.error(e?`${ec("failedSaveCustomModel")} — ${e}`:ec("failedSaveCustomModel"));return}}catch{ep.error(ec("failedSaveCustomModel"));return}finally{eT(null)}try{await e$()}catch{}};return b?(0,t.jsxs)("div",{className:"flex flex-col gap-8",children:[(0,t.jsx)(h.CardSkeleton,{}),(0,t.jsx)(h.CardSkeleton,{})]}):eP?(0,t.jsxs)("div",{className:"flex flex-col gap-8",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)(o.default,{href:"/dashboard/providers",className:"inline-flex items-center gap-1 text-sm text-text-muted hover:text-primary transition-colors mb-4",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-lg",children:"arrow_back"}),ec("backToProviders")]}),(0,t.jsxs)("div",{className:"flex items-center gap-4",children:[(0,t.jsx)("div",{className:"rounded-lg flex items-center justify-center",style:{backgroundColor:`${eP.color}15`},children:ei?(0,t.jsx)("span",{className:"text-sm font-bold",style:{color:eP.color},children:eP.textIcon||eP.id.slice(0,2).toUpperCase()}):(0,t.jsx)(n.default,{src:eA&&eP.apiType?"responses"===eP.apiType?"/providers/oai-r.png":"/providers/oai-cc.png":eO?"/providers/anthropic-m.png":`/providers/${eP.id}.png`,alt:eP.name,width:48,height:48,className:"object-contain rounded-lg max-w-[48px] max-h-[48px]",sizes:"48px",onError:()=>eo(!0)})}),(0,t.jsxs)("div",{children:[eP.website?(0,t.jsxs)("a",{href:eP.website,target:"_blank",rel:"noopener noreferrer",className:"text-3xl font-semibold tracking-tight hover:underline inline-flex items-center gap-2",style:{color:eP.color},children:[eP.name,(0,t.jsx)("span",{className:"material-symbols-outlined text-lg opacity-60",children:"open_in_new"})]}):(0,t.jsx)("h1",{className:"text-3xl font-semibold tracking-tight",children:eP.name}),(0,t.jsx)("p",{className:"text-text-muted",children:ec("connectionCountLabel",{count:u.length})})]})]})]}),eE&&T&&(0,t.jsxs)(c.Card,{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h2",{className:"text-lg font-semibold",children:eO?ec("anthropicCompatibleDetails"):ec("openaiCompatibleDetails")}),(0,t.jsxs)("p",{className:"text-sm text-text-muted",children:[eO?ec("messagesApi"):"responses"===T.apiType?ec("responsesApi"):ec("chatCompletions")," ","· ",(T.baseUrl||"").replace(/\/$/,""),"/",eO?ec("messagesPath"):"responses"===T.apiType?ec("responsesPath"):ec("chatCompletionsPath")]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(p.Button,{size:"sm",icon:"add",onClick:()=>z(!0),disabled:u.length>0,children:ec("add")}),(0,t.jsx)(p.Button,{size:"sm",variant:"secondary",icon:"edit",onClick:()=>G(!0),children:ec("edit")}),(0,t.jsx)(p.Button,{size:"sm",variant:"secondary",icon:"delete",onClick:async()=>{if(confirm(ec("deleteCompatibleNodeConfirm",{type:eO?ec("anthropic"):ec("openai")})))try{(await fetch(`/api/provider-nodes/${l}`,{method:"DELETE"})).ok&&a.push("/dashboard/providers")}catch(e){console.log("Error deleting provider node:",e)}},children:ec("delete")})]})]}),u.length>0&&(0,t.jsx)("p",{className:"text-sm text-text-muted",children:ec("singleConnectionPerCompatible")})]}),(0,t.jsxs)(c.Card,{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)("h2",{className:"text-lg font-semibold",children:ec("connections")}),(0,t.jsxs)("button",{onClick:()=>eh({level:"provider",id:l,label:eP?.name||l}),className:`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium transition-all ${ef?.providers?.[l]?"bg-amber-500/15 text-amber-500 hover:bg-amber-500/25":"bg-black/[0.03] dark:bg-white/[0.03] text-text-muted/50 hover:text-text-muted hover:bg-black/[0.06] dark:hover:bg-white/[0.06]"}`,title:ef?.providers?.[l]?ec("providerProxyTitleConfigured",{host:ef.providers[l].host||ec("configured")}):ec("providerProxyConfigureHint"),children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"vpn_lock"}),ef?.providers?.[l]&&ef.providers[l].host||ec("providerProxy")]})]}),u.length>1&&(0,t.jsxs)("button",{onClick:eX,disabled:ee||!!X,className:`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium border transition-colors ${ee?"bg-primary/20 border-primary/40 text-primary animate-pulse":"bg-bg-subtle border-border text-text-muted hover:text-text-primary hover:border-primary/40"}`,title:ec("testAll"),"aria-label":ec("testAll"),children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:ee?"sync":"play_arrow"}),ee?ec("testing"):ec("testAll")]}),eE?0===u.length&&(0,t.jsx)(p.Button,{size:"sm",icon:"add",onClick:()=>z(!0),children:ec("add")}):(0,t.jsx)(p.Button,{size:"sm",icon:"add",onClick:()=>eR?L(!0):z(!0),children:ec("add")})]}),0===u.length?(0,t.jsxs)("div",{className:"text-center py-12",children:[(0,t.jsx)("div",{className:"inline-flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary mb-4",children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[32px]",children:eR?"lock":"key"})}),(0,t.jsx)("p",{className:"text-text-main font-medium mb-1",children:ec("noConnectionsYet")}),(0,t.jsx)("p",{className:"text-sm text-text-muted mb-4",children:ec("addFirstConnectionHint")}),!eE&&(0,t.jsx)(p.Button,{icon:"add",onClick:()=>eR?L(!0):z(!0),children:ec("addConnection")})]}):(0,t.jsx)("div",{className:"flex flex-col divide-y divide-black/[0.03] dark:divide-white/[0.03]",children:u.sort((e,t)=>(e.priority||0)-(t.priority||0)).map((e,r)=>(0,t.jsx)(q,{connection:e,isOAuth:eR,isFirst:0===r,isLast:r===u.length-1,onMoveUp:()=>e5(e,u[r-1]),onMoveDown:()=>e5(e,u[r+1]),onToggleActive:t=>eV(e.id,t),onToggleRateLimit:t=>eG(e.id,t),isCodex:"codex"===l,onToggleCodex5h:t=>eY(e.id,"use5h",t),onToggleCodexWeekly:t=>eY(e.id,"useWeekly",t),onRetest:()=>eQ(e.id),isRetesting:X===e.id,onEdit:()=>{Q(e),W(!0)},onDelete:()=>eK(e.id),onReauth:eR?()=>L(!0):void 0,onRefreshToken:eR?()=>e1(e.id):void 0,isRefreshing:eZ===e.id,onProxy:()=>eh({level:"key",id:e.id,label:e.name||e.email||e.id}),hasProxy:!!(ef?.keys?.[e.id]||ef?.providers?.[l]||ef?.global),proxySource:ef?.keys?.[e.id]?"key":ef?.providers?.[l]?"provider":ef?.global?"global":null,proxyHost:(ef?.keys?.[e.id]||ef?.providers?.[l]||ef?.global)?.host||null},e.id))})]}),!eD&&(0,t.jsxs)(c.Card,{children:[(0,t.jsx)("h2",{className:"text-lg font-semibold mb-4",children:ec("availableModels")}),(()=>{if(eE)return(0,t.jsx)($,{providerStorageAlias:eU,providerDisplayAlias:eL,modelAliases:es,copied:en,onCopy:ed,onSetAlias:eq,onDeleteAlias:eF,connections:u,isAnthropic:eO,onImportWithProgress:e3,t:ec,effectiveModelNormalize:e9,effectiveModelPreserveDeveloper:e7,getUpstreamHeadersRecord:te,saveModelCompatFlags:tt,compatSavingModelId:eS,onModelsChanged:e$});if(eP.passthroughModels)return(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 mb-4",children:[(0,t.jsx)(p.Button,{size:"sm",variant:"secondary",icon:"download",onClick:e2,disabled:!e4||ev,children:ev?ec("importingModels"):ec("importFromModels")}),!e4&&(0,t.jsx)("span",{className:"text-xs text-text-muted",children:ec("addConnectionToImport")})]}),(0,t.jsx)(U,{providerAlias:eM,modelAliases:es,copied:en,onCopy:ed,onSetAlias:eq,onDeleteAlias:eF,t:ec,effectiveModelNormalize:e9,effectiveModelPreserveDeveloper:e7,getUpstreamHeadersRecord:te,saveModelCompatFlags:tt,compatSavingModelId:eS})]});let e=(0,t.jsxs)("div",{className:"flex items-center gap-2 mb-4",children:[(0,t.jsx)(p.Button,{size:"sm",variant:"secondary",icon:"download",onClick:e2,disabled:!e4||ev,children:ev?ec("importingModels"):ec("importFromModels")}),!e4&&(0,t.jsx)("span",{className:"text-xs text-text-muted",children:ec("addConnectionToImport")})]});return 0===eI.length?(0,t.jsxs)("div",{children:[e,(0,t.jsx)("p",{className:"text-sm text-text-muted",children:ec("noModelsConfigured")})]}):(0,t.jsxs)("div",{children:[e,(0,t.jsx)("div",{className:"flex flex-wrap gap-3",children:eI.map(e=>(0,t.jsx)(D,{model:e,fullModel:`${eL}/${e.id}`,copied:en,onCopy:ed,t:ec,showDeveloperToggle:!0,effectiveModelNormalize:e9,effectiveModelPreserveDeveloper:e7,getUpstreamHeadersRecord:t=>te(e.id,t),saveModelCompatFlags:tt,compatDisabled:eS===e.id},e.id))})]})})(),!eE&&(0,t.jsx)(_,{providerId:l,providerAlias:eL,copied:en,onCopy:ed,onModelsChanged:e$})]}),eD&&(0,t.jsxs)(c.Card,{children:[(0,t.jsx)("h2",{className:"text-lg font-semibold mb-4",children:ec("searchProvider")||"Search Provider"}),(0,t.jsx)("p",{className:"text-sm text-text-muted",children:ec("searchProviderDesc")||"This provider is used for web search via POST /v1/search. No model configuration needed — search providers are ready to use once an API key is connected."}),"perplexity-search"===l&&(0,t.jsxs)("div",{className:"mt-3 flex items-center gap-2 px-3 py-2 rounded-lg bg-blue-500/10 border border-blue-500/20",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-sm text-blue-400",children:"link"}),(0,t.jsxs)("p",{className:"text-xs text-blue-300",children:["Uses the same API key as ",(0,t.jsx)("strong",{children:"Perplexity"})," (chat provider). If you already have Perplexity configured, no additional setup is needed."]})]})]}),"kiro"===l?(0,t.jsx)(g.default,{isOpen:E,providerInfo:eP,onSuccess:eH,onClose:()=>{em.current=!0,L(!1)}}):"cursor"===l?(0,t.jsx)(v.default,{isOpen:E,onSuccess:eH,onClose:()=>{em.current=!0,L(!1)}}):(0,t.jsx)(f.default,{isOpen:E,provider:l,providerInfo:eP,onSuccess:eH,onClose:()=>{em.current=!0,L(!1)}}),(0,t.jsx)(F,{isOpen:B,provider:l,providerName:eP.name,isCompatible:eE,isAnthropic:eO,onSave:eJ,onClose:()=>z(!1)}),(0,t.jsx)(H,{isOpen:K,connection:Y,onSave:eW,onClose:()=>W(!1)}),eE&&(0,t.jsx)(J,{isOpen:V,node:T,onSave:ez,onClose:()=>G(!1),isAnthropic:eO}),er&&(0,t.jsxs)("div",{className:"fixed inset-0 z-50 flex items-start justify-center pt-[10vh]",onClick:()=>ea(null),children:[(0,t.jsx)("div",{className:"absolute inset-0 bg-black/60 backdrop-blur-sm"}),(0,t.jsxs)("div",{className:"relative bg-bg-primary border border-border rounded-xl w-full max-w-[600px] max-h-[80vh] overflow-y-auto shadow-2xl",onClick:e=>e.stopPropagation(),children:[(0,t.jsxs)("div",{className:"sticky top-0 z-10 flex items-center justify-between px-5 py-3 border-b border-border bg-bg-primary/95 backdrop-blur-sm rounded-t-xl",children:[(0,t.jsx)("h3",{className:"font-semibold",children:ec("testResults")}),(0,t.jsx)("button",{onClick:()=>ea(null),className:"p-1 rounded-lg hover:bg-bg-subtle text-text-muted hover:text-text-primary transition-colors","aria-label":"Close",children:(0,t.jsx)("span",{className:"material-symbols-outlined text-lg",children:"close"})})]}),(0,t.jsx)("div",{className:"p-5",children:er.error&&(!er.results||0===er.results.length)?(0,t.jsxs)("div",{className:"text-center py-6",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-red-500 text-[32px] mb-2 block",children:"error"}),(0,t.jsx)("p",{className:"text-sm text-red-400",children:String(er.error)})]}):(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[er.summary&&(0,t.jsxs)("div",{className:"flex items-center gap-3 text-xs mb-1",children:[(0,t.jsx)("span",{className:"text-text-muted",children:eP?.name||l}),(0,t.jsx)("span",{className:"px-2 py-0.5 rounded bg-emerald-500/15 text-emerald-400 font-medium",children:ec("passedCount",{count:er.summary.passed})}),er.summary.failed>0&&(0,t.jsx)("span",{className:"px-2 py-0.5 rounded bg-red-500/15 text-red-400 font-medium",children:ec("failedCount",{count:er.summary.failed})}),(0,t.jsx)("span",{className:"text-text-muted ml-auto",children:ec("testedCount",{count:er.summary.total})})]}),(er.results||[]).map((e,r)=>(0,t.jsxs)("div",{className:"flex items-center gap-2 text-xs px-3 py-2 rounded-lg bg-black/[0.03] dark:bg-white/[0.03]",children:[(0,t.jsx)("span",{className:`material-symbols-outlined text-[16px] ${e.valid?"text-emerald-500":"text-red-500"}`,children:e.valid?"check_circle":"error"}),(0,t.jsx)("div",{className:"flex-1 min-w-0",children:(0,t.jsx)("span",{className:"font-medium",children:e.connectionName})}),void 0!==e.latencyMs&&(0,t.jsx)("span",{className:"text-text-muted font-mono tabular-nums",children:ec("millisecondsAbbr",{value:e.latencyMs})}),(0,t.jsx)("span",{className:`text-[10px] uppercase font-bold px-1.5 py-0.5 rounded ${e.valid?"bg-emerald-500/15 text-emerald-400":"bg-red-500/15 text-red-400"}`,children:e.valid?ec("okShort"):e.diagnosis?.type||ec("errorShort")})]},e.connectionId||r)),(!er.results||0===er.results.length)&&(0,t.jsx)("div",{className:"text-center py-4 text-text-muted text-sm",children:ec("noActiveConnectionsInGroup")})]})})]})]}),ex&&(0,t.jsx)(j.ProxyConfigModal,{isOpen:!!ex,onClose:()=>eh(null),level:ex.level,levelId:ex.id,levelLabel:ex.label}),(0,t.jsx)(x.Modal,{isOpen:ey,onClose:()=>{("done"===eN.phase||"error"===eN.phase)&&ej(!1)},title:ec("importingModelsTitle"),size:"md",closeOnOverlay:!1,showCloseButton:"done"===eN.phase||"error"===eN.phase,children:(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:["fetching"===eN.phase&&(0,t.jsx)("span",{className:"material-symbols-outlined text-primary animate-spin",children:"progress_activity"}),"importing"===eN.phase&&(0,t.jsx)("span",{className:"material-symbols-outlined text-primary animate-spin",children:"progress_activity"}),"done"===eN.phase&&(0,t.jsx)("span",{className:"material-symbols-outlined text-green-500",children:"check_circle"}),"error"===eN.phase&&(0,t.jsx)("span",{className:"material-symbols-outlined text-red-500",children:"error"}),(0,t.jsx)("span",{className:"text-sm font-medium text-text-main",children:eN.status})]}),("importing"===eN.phase||"done"===eN.phase)&&eN.total>0&&(0,t.jsxs)("div",{className:"w-full",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-1",children:[(0,t.jsxs)("span",{className:"text-xs text-text-muted",children:[eN.current," / ",eN.total]}),(0,t.jsxs)("span",{className:"text-xs text-text-muted",children:[Math.round(eN.current/eN.total*100),"%"]})]}),(0,t.jsx)("div",{className:"w-full h-2.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden",children:(0,t.jsx)("div",{className:"h-full rounded-full transition-all duration-300 ease-out",style:{width:`${eN.current/eN.total*100}%`,background:"done"===eN.phase?"linear-gradient(90deg, #22c55e, #16a34a)":"linear-gradient(90deg, var(--color-primary), var(--color-primary-hover, var(--color-primary)))"}})})]}),"fetching"===eN.phase&&(0,t.jsx)("div",{className:"w-full h-2.5 bg-black/10 dark:bg-white/10 rounded-full overflow-hidden",children:(0,t.jsx)("div",{className:"h-full rounded-full animate-pulse",style:{width:"60%",background:"linear-gradient(90deg, var(--color-primary), var(--color-primary-hover, var(--color-primary)))"}})}),"error"===eN.phase&&eN.error&&(0,t.jsx)("div",{className:"p-3 rounded-lg bg-red-500/10 border border-red-500/20",children:(0,t.jsx)("p",{className:"text-sm text-red-400",children:eN.error})}),eN.logs.length>0&&(0,t.jsx)("div",{className:"max-h-48 overflow-y-auto rounded-lg bg-black/5 dark:bg-white/5 p-3 border border-black/5 dark:border-white/5",children:(0,t.jsx)("div",{className:"flex flex-col gap-1",children:eN.logs.map((e,r)=>(0,t.jsx)("p",{className:`text-xs font-mono ${e.startsWith("✓")?"text-green-500 font-semibold":"text-text-muted"}`,children:e},r))})}),"done"===eN.phase&&eN.importedCount>0&&(0,t.jsx)("p",{className:"text-xs text-text-muted text-center animate-pulse",children:ec("pageAutoRefresh")})]})})]}):(0,t.jsxs)("div",{className:"text-center py-20",children:[(0,t.jsx)("p",{className:"text-text-muted",children:ec("providerNotFound")}),(0,t.jsx)(o.default,{href:"/dashboard/providers",className:"text-primary mt-4 inline-block",children:ec("backToProviders")})]})}function D({model:e,fullModel:r,copied:a,onCopy:s,t:l,showDeveloperToggle:i=!0,effectiveModelNormalize:o,effectiveModelPreserveDeveloper:n,getUpstreamHeadersRecord:d,saveModelCompatFlags:c,compatDisabled:p}){return(0,t.jsxs)("div",{className:"flex min-w-[220px] max-w-md items-center gap-2 rounded-lg border border-border px-3 py-2 hover:bg-sidebar/50",children:[(0,t.jsxs)("div",{className:"flex min-w-0 flex-1 flex-wrap items-center gap-2",children:[(0,t.jsx)("span",{className:"material-symbols-outlined shrink-0 text-base text-text-muted",children:"smart_toy"}),(0,t.jsx)("code",{className:"rounded bg-sidebar px-1.5 py-0.5 font-mono text-xs text-text-muted",children:r}),(0,t.jsx)("button",{onClick:()=>s(r,`model-${e.id}`),className:"rounded p-0.5 text-text-muted hover:bg-sidebar hover:text-primary",title:l("copyModel"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:a===`model-${e.id}`?"check":"content_copy"})})]}),(0,t.jsx)("div",{className:"shrink-0",children:(0,t.jsx)(O,{t:l,effectiveModelNormalize:t=>o(e.id,t),effectiveModelPreserveDeveloper:t=>n(e.id,t),getUpstreamHeadersRecord:d,onCompatPatch:(t,r)=>c(e.id,{compatByProtocol:{[t]:r}}),showDeveloperToggle:i,disabled:p})})]})}function U({providerAlias:e,modelAliases:a,copied:s,onCopy:l,onSetAlias:i,onDeleteAlias:o,t:n,effectiveModelNormalize:d,effectiveModelPreserveDeveloper:c,getUpstreamHeadersRecord:u,saveModelCompatFlags:m,compatSavingModelId:x}){let[h,f]=(0,r.useState)(""),[g,v]=(0,r.useState)(!1),b=Object.entries(a).filter(([,t])=>t.startsWith(`${e}/`)).map(([t,r])=>({modelId:r.replace(`${e}/`,""),fullModel:r,alias:t})),y=async()=>{let e;if(!h.trim()||g)return;let t=h.trim(),r=(e=t.split("/"))[e.length-1];if(a[r])return void alert(n("aliasExistsAlert",{alias:r}));v(!0);try{await i(t,r),f("")}catch(e){console.log("Error adding model:",e)}finally{v(!1)}};return(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsx)("p",{className:"text-sm text-text-muted",children:n("openRouterAnyModelHint")}),(0,t.jsxs)("div",{className:"flex items-end gap-2",children:[(0,t.jsxs)("div",{className:"flex-1",children:[(0,t.jsx)("label",{htmlFor:"new-model-input",className:"text-xs text-text-muted mb-1 block",children:n("modelIdFromOpenRouter")}),(0,t.jsx)("input",{id:"new-model-input",type:"text",value:h,onChange:e=>f(e.target.value),onKeyDown:e=>"Enter"===e.key&&y(),placeholder:n("openRouterModelPlaceholder"),className:"w-full px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"})]}),(0,t.jsx)(p.Button,{size:"sm",icon:"add",onClick:y,disabled:!h.trim()||g,children:g?n("adding"):n("add")})]}),b.length>0&&(0,t.jsx)("div",{className:"flex flex-col gap-3",children:b.map(({modelId:e,fullModel:r,alias:a})=>(0,t.jsx)(L,{modelId:e,fullModel:r,copied:s,onCopy:l,onDeleteAlias:()=>o(a),t:n,showDeveloperToggle:!0,effectiveModelNormalize:d,effectiveModelPreserveDeveloper:c,getUpstreamHeadersRecord:t=>u(e,t),saveModelCompatFlags:m,compatDisabled:x===e},r))})]})}function L({modelId:e,fullModel:r,copied:a,onCopy:s,onDeleteAlias:l,t:i,showDeveloperToggle:o=!0,effectiveModelNormalize:n,effectiveModelPreserveDeveloper:d,getUpstreamHeadersRecord:c,saveModelCompatFlags:p,compatDisabled:u}){return(0,t.jsxs)("div",{className:"flex gap-0 rounded-lg border border-border p-3 hover:bg-sidebar/50",children:[(0,t.jsxs)("div",{className:"flex min-w-0 flex-1 items-start gap-3",children:[(0,t.jsx)("span",{className:"material-symbols-outlined shrink-0 text-base text-text-muted",children:"smart_toy"}),(0,t.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,t.jsx)("p",{className:"truncate text-sm font-medium",children:e}),(0,t.jsxs)("div",{className:"mt-1 flex flex-wrap items-center gap-1",children:[(0,t.jsx)("code",{className:"rounded bg-sidebar px-1.5 py-0.5 font-mono text-xs text-text-muted",children:r}),(0,t.jsx)("button",{onClick:()=>s(r,`model-${e}`),className:"rounded p-0.5 text-text-muted hover:bg-sidebar hover:text-primary",title:i("copyModel"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:a===`model-${e}`?"check":"content_copy"})})]})]})]}),(0,t.jsxs)("div",{className:"flex shrink-0 items-center gap-1 self-start",children:[(0,t.jsx)(O,{t:i,effectiveModelNormalize:t=>n(e,t),effectiveModelPreserveDeveloper:t=>d(e,t),getUpstreamHeadersRecord:c,onCompatPatch:(t,r)=>p(e,{compatByProtocol:{[t]:r}}),showDeveloperToggle:o,disabled:u}),(0,t.jsx)("button",{onClick:l,className:"rounded p-1 text-red-500 hover:bg-red-50",title:i("removeModel"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:"delete"})})]})]})}function _({providerId:e,providerAlias:a,copied:l,onCopy:i,onModelsChanged:o}){let n=(0,d.useTranslations)("providers"),c=(0,s.useNotificationStore)(),[u,m]=(0,r.useState)([]),[x,h]=(0,r.useState)([]),[f,g]=(0,r.useState)(""),[v,b]=(0,r.useState)(""),[y,j]=(0,r.useState)("chat-completions"),[N,C]=(0,r.useState)(["chat"]),[w,A]=(0,r.useState)(!1),[E,D]=(0,r.useState)(!0),[U,L]=(0,r.useState)(null),[_,$]=(0,r.useState)("chat-completions"),[B,z]=(0,r.useState)(["chat"]),[q,F]=(0,r.useState)(null),K=(0,r.useMemo)(()=>S(u),[u]),H=(0,r.useMemo)(()=>S(x),[x]),J=(0,r.useCallback)(async()=>{try{let t=await fetch(`/api/provider-models?provider=${encodeURIComponent(e)}`);if(t.ok){let e=await t.json();m(e.models||[]),h(e.modelCompatOverrides||[])}}catch(e){console.error("Failed to fetch custom models:",e)}finally{D(!1)}},[e]);(0,r.useEffect)(()=>{J()},[J]);let W=async()=>{if(f.trim()&&!w){A(!0);try{(await fetch("/api/provider-models",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e,modelId:f.trim(),modelName:v.trim()||void 0,apiFormat:y,supportedEndpoints:N})})).ok&&(g(""),b(""),j("chat-completions"),C(["chat"]),await J(),o?.())}catch(e){console.error("Failed to add custom model:",e)}finally{A(!1)}}},V=async t=>{try{await fetch(`/api/provider-models?provider=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}`,{method:"DELETE"}),await J(),o?.()}catch(e){console.error("Failed to remove custom model:",e)}},G=()=>{L(null),$("chat-completions"),z(["chat"]),F(null)},Y=async(t,r)=>{F(t);try{let a=await fetch("/api/provider-models",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e,modelId:t,...r})});if(!a.ok){let e=await I(a);c.error(e?`${n("failedSaveCustomModel")} — ${e}`:n("failedSaveCustomModel"));return}}catch{c.error(n("failedSaveCustomModel"));return}finally{F(null)}try{await J(),o?.()}catch{}},Q=async t=>{if(U&&U===t){if(!B.length)return void c.error("Select at least one supported endpoint");F(t);try{let r=u.find(e=>e.id===t),a=await fetch("/api/provider-models",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e,modelId:t,modelName:r?.name||t,source:r?.source||"manual",apiFormat:_,supportedEndpoints:B})});if(!a.ok){let e=await I(a);throw Error(e||"Failed to save model endpoint settings")}await J(),o?.(),c.success("Saved model endpoint settings"),G()}catch(e){console.error("Failed to save custom model:",e),c.error(e instanceof Error&&e.message?e.message:"Failed to save model endpoint settings")}finally{F(null)}}};return(0,t.jsxs)("div",{className:"mt-6 pt-6 border-t border-border",children:[(0,t.jsxs)("h3",{className:"text-sm font-semibold mb-3 flex items-center gap-2",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-base text-primary",children:"tune"}),n("customModels")]}),(0,t.jsx)("p",{className:"text-xs text-text-muted mb-3",children:n("customModelsHint")}),(0,t.jsxs)("div",{className:"flex flex-col gap-3 mb-3",children:[(0,t.jsxs)("div",{className:"flex items-end gap-2",children:[(0,t.jsxs)("div",{className:"flex-1",children:[(0,t.jsx)("label",{htmlFor:"custom-model-id",className:"text-xs text-text-muted mb-1 block",children:n("modelId")}),(0,t.jsx)("input",{id:"custom-model-id",type:"text",value:f,onChange:e=>g(e.target.value),onKeyDown:e=>"Enter"===e.key&&W(),placeholder:n("customModelPlaceholder"),className:"w-full px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"})]}),(0,t.jsxs)("div",{className:"w-40",children:[(0,t.jsx)("label",{htmlFor:"custom-model-name",className:"text-xs text-text-muted mb-1 block",children:n("displayName")}),(0,t.jsx)("input",{id:"custom-model-name",type:"text",value:v,onChange:e=>b(e.target.value),onKeyDown:e=>"Enter"===e.key&&W(),placeholder:n("optional"),className:"w-full px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"})]}),(0,t.jsx)(p.Button,{size:"sm",icon:"add",onClick:W,disabled:!f.trim()||w,children:w?n("adding"):n("add")})]}),(0,t.jsxs)("div",{className:"flex items-end gap-4 flex-wrap",children:[(0,t.jsxs)("div",{className:"w-48",children:[(0,t.jsx)("label",{htmlFor:"custom-api-format",className:"text-xs text-text-muted mb-1 block",children:"API Format"}),(0,t.jsxs)("select",{id:"custom-api-format",value:y,onChange:e=>j(e.target.value),className:"w-full px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary",children:[(0,t.jsx)("option",{value:"chat-completions",children:"Chat Completions"}),(0,t.jsx)("option",{value:"responses",children:"Responses API"})]})]}),(0,t.jsxs)("div",{className:"flex-1",children:[(0,t.jsx)("span",{className:"text-xs text-text-muted mb-1 block",children:"Supported Endpoints"}),(0,t.jsx)("div",{className:"flex items-center gap-3",children:["chat","embeddings","images","audio"].map(e=>(0,t.jsxs)("label",{className:"flex items-center gap-1.5 text-xs text-text-main cursor-pointer",children:[(0,t.jsx)("input",{type:"checkbox",checked:N.includes(e),onChange:t=>{t.target.checked?C(t=>[...t,e]):C(t=>t.filter(t=>t!==e))},className:"rounded border-border"}),"chat"===e?"💬 Chat":"embeddings"===e?"📐 Embeddings":"images"===e?"🖼️ Images":"🔊 Audio"]},e))})]})]})]}),E?(0,t.jsx)("p",{className:"text-xs text-text-muted",children:n("loading")}):u.length>0?(0,t.jsx)("div",{className:"flex flex-col gap-2",children:u.map(e=>{let r=`${a}/${e.id}`,s=`custom-${e.id}`;return(0,t.jsxs)("div",{className:"flex items-center gap-3 rounded-lg border border-border p-3 hover:bg-sidebar/50",children:[U!==e.id&&(0,t.jsx)("span",{className:"material-symbols-outlined text-base text-primary shrink-0",children:"tune"}),(0,t.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,t.jsx)("p",{className:"text-sm font-medium truncate",children:e.name||e.id}),(0,t.jsxs)("div",{className:"flex items-center gap-1 mt-1 flex-wrap",children:[(0,t.jsx)("code",{className:"text-xs text-text-muted font-mono bg-sidebar px-1.5 py-0.5 rounded",children:r}),(0,t.jsx)("button",{onClick:()=>i(r,s),className:"p-0.5 hover:bg-sidebar rounded text-text-muted hover:text-primary",title:n("copyModel"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:l===s?"check":"content_copy"})}),"responses"===e.apiFormat&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-blue-500/15 text-blue-400 font-medium",children:"Responses"}),e.supportedEndpoints?.includes("embeddings")&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-purple-500/15 text-purple-400 font-medium",children:"📐 Embed"}),e.supportedEndpoints?.includes("images")&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-amber-500/15 text-amber-400 font-medium",children:"🖼️ Images"}),e.supportedEndpoints?.includes("audio")&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-green-500/15 text-green-400 font-medium",children:"🔊 Audio"}),function(e,t,r){let a=t.get(e),s=r.get(e);if(a?.normalizeToolCallId||s?.normalizeToolCallId)return!0;for(let e of k){let t=T(a,s,e);if(t?.normalizeToolCallId)return!0}return!1}(e.id,K,H)&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-slate-500/15 text-slate-400 font-medium",title:n("normalizeToolCallIdLabel"),children:"ID×9"}),function(e,t,r){let a=t.get(e),s=r.get(e);if(a&&Object.prototype.hasOwnProperty.call(a,"preserveOpenAIDeveloperRole")&&!1===a.preserveOpenAIDeveloperRole||s&&Object.prototype.hasOwnProperty.call(s,"preserveOpenAIDeveloperRole")&&!1===s.preserveOpenAIDeveloperRole)return!0;for(let e of k){let t=T(a,s,e);if(t&&Object.prototype.hasOwnProperty.call(t,"preserveOpenAIDeveloperRole")&&!1===t.preserveOpenAIDeveloperRole)return!0}return!1}(e.id,K,H)&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-cyan-500/15 text-cyan-400 font-medium",title:n("compatDoNotPreserveDeveloper"),children:n("compatBadgeNoPreserve")}),function(e,t,r){let a=t.get(e),s=r.get(e),l=e=>e&&"object"==typeof e&&!Array.isArray(e)&&Object.keys(e).length>0;if(l(a?.upstreamHeaders)||l(s?.upstreamHeaders))return!0;for(let e of k){let t=T(a,s,e);if(l(t?.upstreamHeaders))return!0}return!1}(e.id,K,H)&&(0,t.jsx)("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full bg-violet-500/15 text-violet-400 font-medium",title:n("compatUpstreamHeadersLabel"),children:n("compatBadgeUpstreamHeaders")})]}),U===e.id&&(0,t.jsx)("div",{className:"mt-3 min-w-0 max-w-full rounded-lg border border-border bg-muted p-3 dark:bg-zinc-900",children:(0,t.jsxs)("div",{className:"flex min-w-0 flex-wrap items-end gap-x-3 gap-y-2",children:[(0,t.jsxs)("div",{className:"w-[11rem] shrink-0 min-w-0",children:[(0,t.jsx)("label",{className:"text-xs text-text-muted mb-1 block",children:"API Format"}),(0,t.jsxs)("select",{value:_,onChange:e=>$(e.target.value),className:"w-full px-2.5 py-2 text-xs border border-border rounded-lg bg-background text-text-main focus:outline-none focus:border-primary",children:[(0,t.jsx)("option",{value:"chat-completions",children:"Chat Completions"}),(0,t.jsx)("option",{value:"responses",children:"Responses API"})]})]}),(0,t.jsxs)("div",{className:"flex min-w-0 flex-1 flex-wrap items-center gap-x-3 gap-y-1 overflow-x-auto overflow-y-visible [scrollbar-width:thin]",children:[(0,t.jsx)("span",{className:"text-xs text-text-muted shrink-0",children:"Supported Endpoints"}),(0,t.jsx)("div",{className:"flex flex-wrap items-center gap-x-2 sm:gap-x-3 gap-y-1 min-w-0",children:["chat","embeddings","images","audio"].map(e=>(0,t.jsxs)("label",{className:"flex items-center gap-1.5 text-xs text-text-main cursor-pointer whitespace-nowrap",children:[(0,t.jsx)("input",{type:"checkbox",checked:B.includes(e),onChange:t=>{t.target.checked?z(t=>t.includes(e)?t:[...t,e]):z(t=>t.filter(t=>t!==e))},className:"rounded border-border"}),"chat"===e?"💬 Chat":"embeddings"===e?"📐 Embeddings":"images"===e?"🖼️ Images":"🔊 Audio"]},e))})]}),(0,t.jsxs)("div",{className:"flex shrink-0 flex-wrap items-center gap-2 pb-0.5",children:[(0,t.jsx)(p.Button,{size:"sm",onClick:()=>Q(e.id),disabled:q===e.id,children:q===e.id?n("saving"):n("save")}),(0,t.jsx)(p.Button,{size:"sm",variant:"ghost",onClick:G,children:n("cancel")})]})]})})]}),(0,t.jsxs)("div",{className:"flex shrink-0 items-center gap-1",children:[(0,t.jsx)("button",{onClick:()=>{L(e.id),$(e.apiFormat||"chat-completions"),z(Array.isArray(e.supportedEndpoints)&&e.supportedEndpoints.length?e.supportedEndpoints:["chat"])},className:"rounded p-1 text-text-muted hover:bg-sidebar hover:text-primary",title:n("edit"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:"edit"})}),(0,t.jsx)(O,{t:n,effectiveModelNormalize:t=>P(e.id,t,K,H),effectiveModelPreserveDeveloper:t=>R(e.id,t,K,H),getUpstreamHeadersRecord:t=>M(e.id,t,K,H),onCompatPatch:(t,r)=>Y(e.id,{compatByProtocol:{[t]:r}}),showDeveloperToggle:!0,disabled:q===e.id}),(0,t.jsx)("button",{onClick:()=>V(e.id),className:"rounded p-1 text-red-500 hover:bg-red-50",title:n("removeCustomModel"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:"delete"})})]})]},e.id)})}):(0,t.jsx)("p",{className:"text-xs text-text-muted",children:n("noCustomModels")})]})}function $({providerStorageAlias:e,providerDisplayAlias:a,modelAliases:l,copied:i,onCopy:o,onSetAlias:n,onDeleteAlias:d,connections:c,isAnthropic:u,onImportWithProgress:m,t:x,effectiveModelNormalize:h,effectiveModelPreserveDeveloper:f,getUpstreamHeadersRecord:g,saveModelCompatFlags:v,compatSavingModelId:b,onModelsChanged:y}){let[j,N]=(0,r.useState)(""),[C,w]=(0,r.useState)(!1),[k,S]=(0,r.useState)(!1),T=(0,s.useNotificationStore)(),P=Object.entries(l).filter(([,t])=>t.startsWith(`${e}/`)).map(([t,r])=>({modelId:r.replace(`${e}/`,""),fullModel:r,alias:t})),R=e=>{let t,r=(t=e.split("/"))[t.length-1];if(!l[r])return r;let s=`${a}-${r}`;return l[s]?null:s},I=async()=>{if(!j.trim()||C)return;let t=j.trim(),r=R(t);if(!r)return void T.error(x("allSuggestedAliasesExist"));w(!0);try{let a=await fetch("/api/provider-models",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e,modelId:t,modelName:t,source:"manual"})});if(!a.ok){let e={};try{e=await a.json()}catch(e){console.error("Failed to parse error response from custom model API:",e)}throw Error(e.error?.message||x("failedSaveCustomModel"))}await n(t,r,e),N(""),T.success(x("modelAddedSuccess",{modelId:t})),y?.()}catch(e){console.error("Error adding model:",e),T.error(e instanceof Error?e.message:x("failedAddModelTryAgain"))}finally{w(!1)}},M=async()=>{if(k)return;let t=c.find(e=>!1!==e.isActive);if(t){S(!0);try{await m(async()=>{let e=await fetch(`/api/providers/${t.id}/models`),r=await e.json();if(!e.ok)throw Error(r.error||x("failedImportModels"));return r},async t=>{let r=t.id||t.name||t.model;if(!r)return!1;let a=R(r);return!!a&&((await fetch("/api/provider-models",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e,modelId:r,modelName:t.name||r,source:"imported"})})).ok?(await n(r,a,e),!0):(T.error(x("failedSaveImportedModel")),!1))})}catch(e){console.error("Error importing models:",e),T.error(x("failedImportModelsTryAgain"))}finally{S(!1)}}},A=c.some(e=>!1!==e.isActive),O=async(t,r)=>{try{if(!(await fetch(`/api/provider-models?provider=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}`,{method:"DELETE"})).ok)throw Error(x("failedRemoveModelFromDatabase"));await d(r),T.success(x("modelRemovedSuccess")),y?.()}catch(e){console.error("Error deleting model:",e),T.error(e instanceof Error?e.message:x("failedDeleteModelTryAgain"))}};return(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsx)("p",{className:"text-sm text-text-muted",children:x("compatibleModelsDescription",{type:u?x("anthropic"):x("openai")})}),(0,t.jsxs)("div",{className:"flex items-end gap-2 flex-wrap",children:[(0,t.jsxs)("div",{className:"flex-1 min-w-[240px]",children:[(0,t.jsx)("label",{htmlFor:"new-compatible-model-input",className:"text-xs text-text-muted mb-1 block",children:x("modelId")}),(0,t.jsx)("input",{id:"new-compatible-model-input",type:"text",value:j,onChange:e=>N(e.target.value),onKeyDown:e=>"Enter"===e.key&&I(),placeholder:u?x("anthropicCompatibleModelPlaceholder"):x("openaiCompatibleModelPlaceholder"),className:"w-full px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"})]}),(0,t.jsx)(p.Button,{size:"sm",icon:"add",onClick:I,disabled:!j.trim()||C,children:C?x("adding"):x("add")}),(0,t.jsx)(p.Button,{size:"sm",variant:"secondary",icon:"download",onClick:M,disabled:!A||k,children:k?x("importingModels"):x("importFromModels")})]}),!A&&(0,t.jsx)("p",{className:"text-xs text-text-muted",children:x("addConnectionToImport")}),P.length>0&&(0,t.jsx)("div",{className:"flex flex-col gap-3",children:P.map(({modelId:e,fullModel:r,alias:s})=>(0,t.jsx)(L,{modelId:e,fullModel:`${a}/${e}`,copied:i,onCopy:o,onDeleteAlias:()=>O(e,s),t:x,showDeveloperToggle:!u,effectiveModelNormalize:h,effectiveModelPreserveDeveloper:f,getUpstreamHeadersRecord:t=>g(e,t),saveModelCompatFlags:v,compatDisabled:b===e},r))})]})}function B({until:e}){let[a,s]=(0,r.useState)("");return((0,r.useEffect)(()=>{let t=()=>{let t=new Date(e).getTime()-Date.now();if(t<=0)return void s("");let r=Math.floor(t/1e3);if(r<60)s(`${r}s`);else if(r<3600)s(`${Math.floor(r/60)}m ${r%60}s`);else{let e=Math.floor(r/3600),t=Math.floor(r%3600/60);s(`${e}h ${t}m`)}};t();let r=setInterval(t,1e3);return()=>clearInterval(r)},[e]),a)?(0,t.jsxs)("span",{className:"text-xs text-orange-500 font-mono",children:["⏱ ",a]}):null}D.propTypes={model:l.default.shape({id:l.default.string.isRequired}).isRequired,fullModel:l.default.string.isRequired,copied:l.default.string,onCopy:l.default.func.isRequired,t:l.default.func,showDeveloperToggle:l.default.bool,effectiveModelNormalize:l.default.func.isRequired,effectiveModelPreserveDeveloper:l.default.func.isRequired,getUpstreamHeadersRecord:l.default.func.isRequired,saveModelCompatFlags:l.default.func.isRequired,compatDisabled:l.default.bool},U.propTypes={providerAlias:l.default.string.isRequired,modelAliases:l.default.object.isRequired,copied:l.default.string,onCopy:l.default.func.isRequired,onSetAlias:l.default.func.isRequired,onDeleteAlias:l.default.func.isRequired,t:l.default.func.isRequired,effectiveModelNormalize:l.default.func.isRequired,effectiveModelPreserveDeveloper:l.default.func.isRequired,getUpstreamHeadersRecord:l.default.func.isRequired,saveModelCompatFlags:l.default.func.isRequired,compatSavingModelId:l.default.string},L.propTypes={modelId:l.default.string.isRequired,fullModel:l.default.string.isRequired,copied:l.default.string,onCopy:l.default.func.isRequired,onDeleteAlias:l.default.func.isRequired,t:l.default.func,showDeveloperToggle:l.default.bool,effectiveModelNormalize:l.default.func.isRequired,effectiveModelPreserveDeveloper:l.default.func.isRequired,getUpstreamHeadersRecord:l.default.func.isRequired,saveModelCompatFlags:l.default.func.isRequired,compatDisabled:l.default.bool},_.propTypes={providerId:l.default.string.isRequired,providerAlias:l.default.string.isRequired,copied:l.default.string,onCopy:l.default.func.isRequired,onModelsChanged:l.default.func},$.propTypes={providerStorageAlias:l.default.string.isRequired,providerDisplayAlias:l.default.string.isRequired,modelAliases:l.default.object.isRequired,copied:l.default.string,onCopy:l.default.func.isRequired,onSetAlias:l.default.func.isRequired,onDeleteAlias:l.default.func.isRequired,connections:l.default.arrayOf(l.default.shape({id:l.default.string,isActive:l.default.bool})).isRequired,isAnthropic:l.default.bool,onImportWithProgress:l.default.func.isRequired,t:l.default.func.isRequired,effectiveModelNormalize:l.default.func.isRequired,effectiveModelPreserveDeveloper:l.default.func.isRequired,getUpstreamHeadersRecord:l.default.func.isRequired,saveModelCompatFlags:l.default.func.isRequired,compatSavingModelId:l.default.string,onModelsChanged:l.default.func},B.propTypes={until:l.default.string.isRequired};let z={runtime_error:{labelKey:"errorTypeRuntime",variant:"warning"},upstream_auth_error:{labelKey:"errorTypeUpstreamAuth",variant:"error"},account_deactivated:{labelKey:"Account Deactivated",variant:"error"},auth_missing:{labelKey:"errorTypeMissingCredential",variant:"warning"},token_refresh_failed:{labelKey:"errorTypeRefreshFailed",variant:"warning"},token_expired:{labelKey:"errorTypeTokenExpired",variant:"warning"},upstream_rate_limited:{labelKey:"errorTypeRateLimited",variant:"warning"},upstream_unavailable:{labelKey:"errorTypeUpstreamUnavailable",variant:"error"},network_error:{labelKey:"errorTypeNetworkError",variant:"warning"},unsupported:{labelKey:"errorTypeTestUnsupported",variant:"default"},upstream_error:{labelKey:"errorTypeUpstreamError",variant:"error"},banned:{labelKey:"403 Banned",variant:"error"},credits_exhausted:{labelKey:"No Credits",variant:"warning"}};function q({connection:e,isOAuth:a,isCodex:s,isFirst:l,isLast:i,onMoveUp:o,onMoveDown:n,onToggleActive:c,onToggleRateLimit:m,onToggleCodex5h:x,onToggleCodexWeekly:h,onRetest:f,isRetesting:g,onEdit:v,onDelete:y,onReauth:j,onProxy:N,hasProxy:C,proxySource:w,proxyHost:k,onRefreshToken:S,isRefreshing:T}){let P,R=(0,d.useTranslations)("providers"),I=a?e.name||e.email||e.displayName||R("oauthAccount"):e.name,[M,O]=(0,r.useState)(!1),[E,D]=(0,r.useState)(()=>a&&e.expiresAt?Math.floor((new Date(e.expiresAt).getTime()-Date.now())/6e4):null);(0,r.useEffect)(()=>{if(!a||!e.expiresAt)return;let t=setInterval(()=>{D(Math.floor((new Date(e.expiresAt).getTime()-Date.now())/6e4))},3e4);return()=>clearInterval(t)},[a,e.expiresAt]),(0,r.useEffect)(()=>{let t=()=>{O(e.rateLimitedUntil&&new Date(e.rateLimitedUntil).getTime()>Date.now())};t();let r=e.rateLimitedUntil?setInterval(t,1e3):null;return()=>{r&&clearInterval(r)}},[e.rateLimitedUntil]);let U="unavailable"!==e.testStatus||M?e.testStatus:"active",L=function(e,t,r,a){if(!1===e.isActive)return{statusVariant:"default",statusLabel:a("statusDisabled"),errorType:null,errorBadge:null,errorTextClass:"text-text-muted"};if("active"===t||"success"===t)return{statusVariant:"success",statusLabel:a("statusConnected"),errorType:null,errorBadge:null,errorTextClass:"text-text-muted"};let s=function(e,t){if(t)return"upstream_rate_limited";if("banned"===e.testStatus)return"banned";if("credits_exhausted"===e.testStatus)return"credits_exhausted";if(e.lastErrorType)return e.lastErrorType;let r=Number(e.errorCode);if(401===r||403===r)return"upstream_auth_error";if(429===r)return"upstream_rate_limited";if(r>=500)return"upstream_unavailable";let a=(e.lastError||"").toLowerCase();return a?a.includes("runtime")||a.includes("not runnable")||a.includes("not installed")||a.includes("healthcheck")?"runtime_error":a.includes("refresh failed")?"token_refresh_failed":a.includes("token expired")||a.includes("expired")?"token_expired":a.includes("invalid api key")||a.includes("token invalid")||a.includes("revoked")||a.includes("access denied")||a.includes("unauthorized")?"upstream_auth_error":a.includes("rate limit")||a.includes("quota")||a.includes("too many requests")||a.includes("429")?"upstream_rate_limited":a.includes("fetch failed")||a.includes("network")||a.includes("timeout")||a.includes("econn")||a.includes("enotfound")?"network_error":a.includes("not supported")?"unsupported":"upstream_error":null}(e,r),l=s&&z[s]||null;return"runtime_error"===s?{statusVariant:"warning",statusLabel:a("statusRuntimeIssue"),errorType:s,errorBadge:l,errorTextClass:"text-yellow-600 dark:text-yellow-400"}:"account_deactivated"===s?{statusVariant:"error",statusLabel:a("statusDeactivated","Deactivated"),errorType:s,errorBadge:l,errorTextClass:"text-red-600 font-bold"}:"upstream_auth_error"===s||"auth_missing"===s||"token_refresh_failed"===s||"token_expired"===s?{statusVariant:"error",statusLabel:a("statusAuthFailed"),errorType:s,errorBadge:l,errorTextClass:"text-red-500"}:"upstream_rate_limited"===s?{statusVariant:"warning",statusLabel:a("statusRateLimited"),errorType:s,errorBadge:l,errorTextClass:"text-yellow-600 dark:text-yellow-400"}:"network_error"===s?{statusVariant:"warning",statusLabel:a("statusNetworkIssue"),errorType:s,errorBadge:l,errorTextClass:"text-yellow-600 dark:text-yellow-400"}:"unsupported"===s?{statusVariant:"default",statusLabel:a("statusTestUnsupported"),errorType:s,errorBadge:l,errorTextClass:"text-text-muted"}:"banned"===s?{statusVariant:"error",statusLabel:a("statusBanned","Banned (403)"),errorType:s,errorBadge:l,errorTextClass:"text-red-600 font-bold"}:"credits_exhausted"===s?{statusVariant:"warning",statusLabel:a("statusCreditsExhausted","Out of Credits"),errorType:s,errorBadge:l,errorTextClass:"text-amber-500"}:{statusVariant:"error",statusLabel:({unavailable:a("statusUnavailable"),failed:a("statusFailed"),error:a("statusError")})[t]||t||a("statusError"),errorType:s,errorBadge:l,errorTextClass:"text-red-500"}}(e,U,M,R),_=!!e.rateLimitProtection,$=A(e.providerSpecificData&&"object"==typeof e.providerSpecificData&&e.providerSpecificData.codexLimitPolicy&&"object"==typeof e.providerSpecificData.codexLimitPolicy?e.providerSpecificData.codexLimitPolicy:{}),q=$.use5h,F=$.useWeekly;return(0,t.jsxs)("div",{className:`group flex items-center justify-between p-3 rounded-lg hover:bg-black/[0.02] dark:hover:bg-white/[0.02] transition-colors ${!1===e.isActive?"opacity-60":""}`,children:[(0,t.jsxs)("div",{className:"flex items-center gap-3 flex-1 min-w-0",children:[(0,t.jsxs)("div",{className:"flex flex-col",children:[(0,t.jsx)("button",{onClick:o,disabled:l,className:`p-0.5 rounded ${l?"text-text-muted/30 cursor-not-allowed":"hover:bg-sidebar text-text-muted hover:text-primary"}`,children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:"keyboard_arrow_up"})}),(0,t.jsx)("button",{onClick:n,disabled:i,className:`p-0.5 rounded ${i?"text-text-muted/30 cursor-not-allowed":"hover:bg-sidebar text-text-muted hover:text-primary"}`,children:(0,t.jsx)("span",{className:"material-symbols-outlined text-sm",children:"keyboard_arrow_down"})})]}),(0,t.jsx)("span",{className:"material-symbols-outlined text-base text-text-muted",children:a?"lock":"key"}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsx)("p",{className:"text-sm font-medium truncate",children:I}),(0,t.jsxs)("div",{className:"flex items-center gap-2 mt-1 flex-wrap",children:[(0,t.jsx)(u.Badge,{variant:L.statusVariant,size:"sm",dot:!0,children:L.statusLabel}),null!==E&&(E<0?(0,t.jsxs)("span",{className:"inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-xs font-medium bg-red-500/15 text-red-500",title:`Token expired: ${e.expiresAt}`,children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[11px]",children:"error"}),"expired"]}):E<30?(0,t.jsxs)("span",{className:"inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-xs font-medium bg-amber-500/15 text-amber-500",title:`Token expires in ${E}m`,children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[11px]",children:"warning"}),`~${E}m`]}):null),M&&!1!==e.isActive&&(0,t.jsx)(B,{until:e.rateLimitedUntil}),L.errorBadge&&!1!==e.isActive&&(0,t.jsx)(u.Badge,{variant:L.errorBadge.variant,size:"sm",children:R(L.errorBadge.labelKey)}),e.lastError&&!1!==e.isActive&&(0,t.jsx)("span",{className:`text-xs truncate max-w-[300px] ${L.errorTextClass}`,title:e.lastError,children:e.lastError}),(0,t.jsxs)("span",{className:"text-xs text-text-muted",children:["#",e.priority]}),e.globalPriority&&(0,t.jsx)("span",{className:"text-xs text-text-muted",children:R("autoPriority",{priority:e.globalPriority})}),(0,t.jsx)("span",{className:"text-text-muted/30 select-none",children:"|"}),(0,t.jsxs)("button",{onClick:()=>m(!_),className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-medium transition-all cursor-pointer ${_?"bg-emerald-500/15 text-emerald-500 hover:bg-emerald-500/25":"bg-black/[0.03] dark:bg-white/[0.03] text-text-muted/50 hover:text-text-muted hover:bg-black/[0.06] dark:hover:bg-white/[0.06]"}`,title:R(_?"disableRateLimitProtection":"enableRateLimitProtection"),children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"shield"}),R(_?"rateLimitProtected":"rateLimitUnprotected")]}),s&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"text-text-muted/30 select-none",children:"|"}),(0,t.jsxs)("button",{onClick:()=>x?.(!q),className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-medium transition-all cursor-pointer ${q?"bg-blue-500/15 text-blue-500 hover:bg-blue-500/25":"bg-black/[0.03] dark:bg-white/[0.03] text-text-muted/50 hover:text-text-muted hover:bg-black/[0.06] dark:hover:bg-white/[0.06]"}`,title:"Toggle Codex 5h limit policy",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"timer"}),"5h ",q?"ON":"OFF"]}),(0,t.jsxs)("button",{onClick:()=>h?.(!F),className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-medium transition-all cursor-pointer ${F?"bg-violet-500/15 text-violet-500 hover:bg-violet-500/25":"bg-black/[0.03] dark:bg-white/[0.03] text-text-muted/50 hover:text-text-muted hover:bg-black/[0.06] dark:hover:bg-white/[0.06]"}`,title:"Toggle Codex weekly limit policy",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"date_range"}),"Weekly ",F?"ON":"OFF"]})]}),C&&(P=R("global"===w?"proxySourceGlobal":"provider"===w?"proxySourceProvider":"proxySourceKey"),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"text-text-muted/30 select-none",children:"|"}),(0,t.jsxs)("span",{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-xs font-medium ${"global"===w?"bg-emerald-500/15 text-emerald-500":"provider"===w?"bg-amber-500/15 text-amber-500":"bg-blue-500/15 text-blue-500"}`,title:R("proxyConfiguredBySource",{source:P,host:k||R("configured")}),children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"vpn_lock"}),k||R("proxy")]})]}))]})]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(p.Button,{size:"sm",variant:"ghost",icon:"refresh",loading:g,disabled:!1===e.isActive,onClick:f,className:"!h-7 !px-2 text-xs",title:R("retestAuthentication"),children:R("retest")}),S&&(0,t.jsx)(p.Button,{size:"sm",variant:"ghost",icon:"token",loading:T,disabled:!1===e.isActive||T,onClick:S,className:"!h-7 !px-2 text-xs text-amber-500 hover:text-amber-400",title:"Refresh OAuth token manually",children:"Token"}),(0,t.jsx)(b.Toggle,{size:"sm",checked:e.isActive??!0,onChange:c,title:R(e.isActive??!0?"disableConnection":"enableConnection")}),(0,t.jsxs)("div",{className:"flex gap-1 ml-1 transition-opacity",children:[j&&(0,t.jsx)("button",{onClick:j,className:"p-2 hover:bg-amber-500/10 rounded text-amber-600 hover:text-amber-500",title:R("reauthenticateConnection"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"passkey"})}),(0,t.jsx)("button",{onClick:v,className:"p-2 hover:bg-black/5 dark:hover:bg-white/5 rounded text-text-muted hover:text-primary",title:R("edit"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"edit"})}),(0,t.jsx)("button",{onClick:N,className:"p-2 hover:bg-black/5 dark:hover:bg-white/5 rounded text-text-muted hover:text-primary",title:R("proxyConfig"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"vpn_lock"})}),(0,t.jsx)("button",{onClick:y,className:"p-2 hover:bg-red-500/10 rounded text-red-500",title:R("delete"),children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"delete"})})]})]})]})}function F({isOpen:e,provider:a,providerName:s,isCompatible:l,isAnthropic:i,onSave:o,onClose:n}){let c=(0,d.useTranslations)("providers"),h="bailian-coding-plan"===a,f="https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1",g="vertex"===a,v="us-central1",[b,y]=(0,r.useState)({name:"",apiKey:"",priority:1,baseUrl:h?f:"",region:g?v:"",validationModelId:""}),[j,N]=(0,r.useState)(!1),[C,w]=(0,r.useState)(null),[k,S]=(0,r.useState)(!1),[T,P]=(0,r.useState)(null),R=async()=>{N(!0),P(null);try{let e=await fetch("/api/providers/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:a,apiKey:b.apiKey,validationModelId:b.validationModelId||void 0})}),t=await e.json();w(t.valid?"success":"failed")}catch{w("failed")}finally{N(!1)}},I=async()=>{if(a&&b.apiKey){S(!0),P(null);try{let e=null;if(h){let t=K(b.baseUrl,f);if(t.error)return void P(t.error);e=t.value}let t=!1;try{N(!0),w(null);let e=await fetch("/api/providers/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:a,apiKey:b.apiKey,validationModelId:b.validationModelId||void 0})});t=!!(await e.json()).valid,w(t?"success":"failed")}catch{w("failed")}finally{N(!1)}if(!t)return void P(c("apiKeyValidationFailed"));let r={name:b.name,apiKey:b.apiKey,priority:b.priority,testStatus:"active",providerSpecificData:void 0};h?r.providerSpecificData={baseUrl:e}:g&&(r.providerSpecificData={region:b.region});let s=await o(r);s&&P("string"==typeof s?s:c("failedSaveConnection"))}finally{S(!1)}}};return a?(0,t.jsx)(x.Modal,{isOpen:e,title:c("addProviderApiKeyTitle",{provider:s||a}),onClose:n,children:(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsx)(m.Input,{label:c("nameLabel"),value:b.name,onChange:e=>y({...b,name:e.target.value}),placeholder:c("productionKey")}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(m.Input,{label:c("apiKeyLabel"),type:"password",value:b.apiKey,onChange:e=>y({...b,apiKey:e.target.value}),className:"flex-1",placeholder:g?"Cole o Service Account JSON aqui":void 0}),(0,t.jsx)("div",{className:"pt-6",children:(0,t.jsx)(p.Button,{onClick:R,disabled:!b.apiKey||j||k,variant:"secondary",children:j?c("checking"):c("check")})})]}),C&&(0,t.jsx)(u.Badge,{variant:"success"===C?"success":"error",children:"success"===C?c("valid"):c("invalid")}),T&&(0,t.jsx)("div",{className:"text-sm text-red-500 bg-red-500/10 border border-red-500/20 rounded-lg px-3 py-2",children:T}),l&&(0,t.jsx)("p",{className:"text-xs text-text-muted",children:i?c("validationChecksAnthropicCompatible",{provider:s||c("anthropicCompatibleName")}):c("validationChecksOpenAiCompatible",{provider:s||c("openaiCompatibleName")})}),(0,t.jsx)(m.Input,{label:"Model ID (opcional)",placeholder:"ex: grok-3 ou meta-llama/Llama-3.1-8B-Instruct",value:b.validationModelId,onChange:e=>y({...b,validationModelId:e.target.value}),hint:"Usado como fallback se a listagem de models não estiver disponível"}),(0,t.jsx)(m.Input,{label:c("priorityLabel"),type:"number",value:b.priority,onChange:e=>y({...b,priority:Number.parseInt(e.target.value)||1})}),h&&(0,t.jsx)(m.Input,{label:"Base URL",value:b.baseUrl,onChange:e=>y({...b,baseUrl:e.target.value}),placeholder:f,hint:"Optional: Custom base URL for bailian-coding-plan provider"}),g&&(0,t.jsx)(m.Input,{label:"Região (Region)",value:b.region,onChange:e=>y({...b,region:e.target.value}),placeholder:v,hint:"ex: us-central1 ou europe-west4. Partner models usam a região global automaticamente."}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(p.Button,{onClick:I,fullWidth:!0,disabled:!b.name||!b.apiKey||k,children:k?c("saving"):c("save")}),(0,t.jsx)(p.Button,{onClick:n,variant:"ghost",fullWidth:!0,children:c("cancel")})]})]})}):null}function K(e,t){let r=("string"==typeof e?e.trim():"")||t;try{let e=new URL(r);if("http:"!==e.protocol&&"https:"!==e.protocol)return{value:null,error:"Base URL must use http or https"};return{value:r,error:null}}catch{return{value:null,error:"Base URL must be a valid URL"}}}function H({isOpen:e,connection:a,onSave:s,onClose:l}){let i=(0,d.useTranslations)("providers"),[o,n]=(0,r.useState)({name:"",priority:1,apiKey:"",healthCheckInterval:60,baseUrl:"",region:"",validationModelId:""}),[c,h]=(0,r.useState)(!1),[f,g]=(0,r.useState)(null),[v,b]=(0,r.useState)(!1),[y,j]=(0,r.useState)(null),[C,w]=(0,r.useState)(!1),[k,S]=(0,r.useState)(null),[T,P]=(0,r.useState)([]),[R,I]=(0,r.useState)(""),M=a?.provider==="bailian-coding-plan",A="https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1",O=a?.provider==="vertex",E="us-central1";(0,r.useEffect)(()=>{if(a){let e=a.providerSpecificData?.baseUrl,t=a.providerSpecificData?.region;n({name:a.name||"",priority:a.priority||1,apiKey:"",healthCheckInterval:a.healthCheckInterval??60,baseUrl:("string"==typeof e?e:"")||(M?A:""),region:("string"==typeof t?t:"")||(O?E:""),validationModelId:a.providerSpecificData?.validationModelId||""});let r=a.providerSpecificData?.extraApiKeys;P(Array.isArray(r)?r:[]),I(""),g(null),j(null),S(null)}},[a,M]);let D=async()=>{if(a?.provider){h(!0),g(null);try{let e=await fetch(`/api/providers/${a.id}/test`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({validationModelId:o.validationModelId||void 0})}),t=await e.json();g({valid:!!t.valid,diagnosis:t.diagnosis||null,message:t.error||null})}catch{g({valid:!1,diagnosis:{type:"network_error"},message:i("failedTestConnection")})}finally{h(!1)}}},U=async()=>{if(a?.provider&&o.apiKey){b(!0),j(null);try{let e=await fetch("/api/providers/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:a.provider,apiKey:o.apiKey,validationModelId:o.validationModelId||void 0})}),t=await e.json();j(t.valid?"success":"failed")}catch{j("failed")}finally{b(!1)}}},L=async()=>{w(!0),S(null);try{let e={name:o.name,priority:o.priority,healthCheckInterval:o.healthCheckInterval},t=null;if(M){let e=K(o.baseUrl,A);if(e.error)return void S(e.error);t=e.value}if(!_&&o.apiKey){e.apiKey=o.apiKey;let t="success"===y;if(!t)try{b(!0),j(null);let e=await fetch("/api/providers/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:a.provider,apiKey:o.apiKey,validationModelId:o.validationModelId||void 0})});t=!!(await e.json()).valid,j(t?"success":"failed")}catch{j("failed")}finally{b(!1)}t&&(e.testStatus="active",e.lastError=null,e.lastErrorAt=null,e.lastErrorType=null,e.lastErrorSource=null,e.errorCode=null,e.rateLimitedUntil=null)}!_&&(e.providerSpecificData={...a.providerSpecificData||{},extraApiKeys:T.filter(e=>e.trim().length>0)},o.validationModelId&&(e.providerSpecificData.validationModelId=o.validationModelId),M?e.providerSpecificData.baseUrl=t:O&&(e.providerSpecificData.region=o.region));let r=await s(e);r&&S("string"==typeof r?r:i("failedSaveConnection"))}finally{w(!1)}};if(!a)return null;let _="oauth"===a.authType,$=(0,N.isOpenAICompatibleProvider)(a.provider)||(0,N.isAnthropicCompatibleProvider)(a.provider),B=!f?.valid&&f?.diagnosis?.type&&z[f.diagnosis.type]||null;return(0,t.jsx)(x.Modal,{isOpen:e,title:i("editConnection"),onClose:l,children:(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsx)(m.Input,{label:i("nameLabel"),value:o.name,onChange:e=>n({...o,name:e.target.value}),placeholder:_?i("accountName"):i("productionKey")}),_&&a.email&&(0,t.jsxs)("div",{className:"bg-sidebar/50 p-3 rounded-lg",children:[(0,t.jsx)("p",{className:"text-sm text-text-muted mb-1",children:i("email")}),(0,t.jsx)("p",{className:"font-medium",children:a.email})]}),_&&(0,t.jsx)(m.Input,{label:i("healthCheckMinutes"),type:"number",value:o.healthCheckInterval,onChange:e=>n({...o,healthCheckInterval:Math.max(0,Number.parseInt(e.target.value)||0)}),hint:i("healthCheckHint")}),(0,t.jsx)(m.Input,{label:i("priorityLabel"),type:"number",value:o.priority,onChange:e=>n({...o,priority:Number.parseInt(e.target.value)||1})}),!_&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(m.Input,{label:i("apiKeyLabel"),type:"password",value:o.apiKey,onChange:e=>n({...o,apiKey:e.target.value}),placeholder:O?"Cole o Service Account JSON aqui":i("enterNewApiKey"),hint:i("leaveBlankKeepCurrentApiKey"),className:"flex-1"}),(0,t.jsx)("div",{className:"pt-6",children:(0,t.jsx)(p.Button,{onClick:U,disabled:!o.apiKey||v||C,variant:"secondary",children:v?i("checking"):i("check")})})]}),y&&(0,t.jsx)(u.Badge,{variant:"success"===y?"success":"error",children:"success"===y?i("valid"):i("invalid")}),k&&(0,t.jsx)("div",{className:"text-sm text-red-500 bg-red-500/10 border border-red-500/20 rounded-lg px-3 py-2",children:k}),(0,t.jsx)(m.Input,{label:"Model ID (opcional)",placeholder:"ex: grok-3 ou meta-llama/Llama-3.1-8B-Instruct",value:o.validationModelId,onChange:e=>n({...o,validationModelId:e.target.value}),hint:"Usado como fallback se a listagem de models não estiver disponível"})]}),M&&(0,t.jsx)(m.Input,{label:"Base URL",value:o.baseUrl,onChange:e=>n({...o,baseUrl:e.target.value}),placeholder:A,hint:"Custom base URL for bailian-coding-plan provider"}),O&&(0,t.jsx)(m.Input,{label:"Região (Region)",value:o.region,onChange:e=>n({...o,region:e.target.value}),placeholder:E,hint:"ex: us-central1 ou europe-west4. Partner models usam a região global automaticamente."}),!_&&(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsxs)("label",{className:"text-sm font-medium text-text-main",children:["Extra API Keys",(0,t.jsx)("span",{className:"ml-2 text-[11px] font-normal text-text-muted",children:"(round-robin rotation — optional)"})]}),T.length>0&&(0,t.jsx)("div",{className:"flex flex-col gap-1.5",children:T.map((e,r)=>(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:"flex-1 font-mono text-xs bg-sidebar/50 px-3 py-2 rounded border border-border text-text-muted truncate",children:`Key #${r+2}: ${e.slice(0,6)}...${e.slice(-4)}`}),(0,t.jsx)("button",{onClick:()=>P(T.filter((e,t)=>t!==r)),className:"p-1.5 rounded hover:bg-red-500/10 text-red-400 hover:text-red-500",title:"Remove this key",children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"close"})})]},r))}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)("input",{type:"password",value:R,onChange:e=>I(e.target.value),placeholder:"Add another API key...",className:"flex-1 text-sm bg-sidebar/50 border border-border rounded px-3 py-2 text-text-main placeholder:text-text-muted focus:ring-1 focus:ring-primary outline-none",onKeyDown:e=>{"Enter"===e.key&&R.trim()&&(P([...T,R.trim()]),I(""))}}),(0,t.jsx)("button",{onClick:()=>{R.trim()&&(P([...T,R.trim()]),I(""))},disabled:!R.trim(),className:"px-3 py-2 rounded bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-40 text-sm font-medium",children:"Add"})]}),T.length>0&&(0,t.jsxs)("p",{className:"text-[11px] text-text-muted",children:[T.length+1," keys total — rotating round-robin on each request."]})]}),!$&&(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)(p.Button,{onClick:D,variant:"secondary",disabled:c,children:c?i("testing"):i("testConnection")}),f&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(u.Badge,{variant:f.valid?"success":"error",children:f.valid?i("valid"):i("failed")}),B&&(0,t.jsx)(u.Badge,{variant:B.variant,children:i(B.labelKey)})]})]}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(p.Button,{onClick:L,fullWidth:!0,disabled:C,children:C?i("saving"):i("save")}),(0,t.jsx)(p.Button,{onClick:l,variant:"ghost",fullWidth:!0,children:i("cancel")})]})]})})}function J({isOpen:e,node:a,onSave:s,onClose:l,isAnthropic:i}){let o=(0,d.useTranslations)("providers"),[n,c]=(0,r.useState)({name:"",prefix:"",apiType:"chat",baseUrl:"https://api.openai.com/v1",chatPath:"",modelsPath:""}),[h,f]=(0,r.useState)(!1),[g,v]=(0,r.useState)(""),[b,j]=(0,r.useState)(!1),[N,C]=(0,r.useState)(null),[w,k]=(0,r.useState)(!1);(0,r.useEffect)(()=>{a&&(c({name:a.name||"",prefix:a.prefix||"",apiType:a.apiType||"chat",baseUrl:a.baseUrl||(i?"https://api.anthropic.com/v1":"https://api.openai.com/v1"),chatPath:a.chatPath||"",modelsPath:a.modelsPath||""}),k(!!(a.chatPath||a.modelsPath)))},[a,i]);let S=[{value:"chat",label:o("chatCompletions")},{value:"responses",label:o("responsesApi")}],T=async()=>{if(n.name.trim()&&n.prefix.trim()&&n.baseUrl.trim()){f(!0);try{let e={name:n.name,prefix:n.prefix,baseUrl:n.baseUrl,chatPath:n.chatPath||"",modelsPath:n.modelsPath||""};i||(e.apiType=n.apiType),await s(e)}finally{f(!1)}}},P=async()=>{j(!0);try{let e=await fetch("/api/provider-nodes/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({baseUrl:n.baseUrl,apiKey:g,type:i?"anthropic-compatible":"openai-compatible",modelsPath:n.modelsPath||""})}),t=await e.json();C(t.valid?"success":"failed")}catch{C("failed")}finally{j(!1)}};return a?(0,t.jsx)(x.Modal,{isOpen:e,title:o("editCompatibleTitle",{type:o(i?"anthropic":"openai")}),onClose:l,children:(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsx)(m.Input,{label:o("nameLabel"),value:n.name,onChange:e=>c({...n,name:e.target.value}),placeholder:o("compatibleProdPlaceholder",{type:o(i?"anthropic":"openai")}),hint:o("nameHint")}),(0,t.jsx)(m.Input,{label:o("prefixLabel"),value:n.prefix,onChange:e=>c({...n,prefix:e.target.value}),placeholder:o(i?"anthropicPrefixPlaceholder":"openaiPrefixPlaceholder"),hint:o("prefixHint")}),!i&&(0,t.jsx)(y.Select,{label:o("apiTypeLabel"),options:S,value:n.apiType,onChange:e=>c({...n,apiType:e.target.value})}),(0,t.jsx)(m.Input,{label:o("baseUrlLabel"),value:n.baseUrl,onChange:e=>c({...n,baseUrl:e.target.value}),placeholder:o(i?"anthropicBaseUrlPlaceholder":"openaiBaseUrlPlaceholder"),hint:o("compatibleBaseUrlHint",{type:o(i?"anthropic":"openai")})}),(0,t.jsxs)("button",{type:"button",className:"text-sm text-text-muted hover:text-text-primary flex items-center gap-1",onClick:()=>k(!w),"aria-expanded":w,"aria-controls":"advanced-settings",children:[(0,t.jsx)("span",{className:`transition-transform ${w?"rotate-90":""}`,"aria-hidden":"true",children:"▶"}),o("advancedSettings")]}),w&&(0,t.jsxs)("div",{id:"advanced-settings",className:"flex flex-col gap-3 pl-2 border-l-2 border-border",children:[(0,t.jsx)(m.Input,{label:o("chatPathLabel"),value:n.chatPath,onChange:e=>c({...n,chatPath:e.target.value}),placeholder:i?"/messages":o("chatPathPlaceholder"),hint:o("chatPathHint")}),(0,t.jsx)(m.Input,{label:o("modelsPathLabel"),value:n.modelsPath,onChange:e=>c({...n,modelsPath:e.target.value}),placeholder:o("modelsPathPlaceholder"),hint:o("modelsPathHint")})]}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(m.Input,{label:o("apiKeyForCheck"),type:"password",value:g,onChange:e=>v(e.target.value),className:"flex-1"}),(0,t.jsx)("div",{className:"pt-6",children:(0,t.jsx)(p.Button,{onClick:P,disabled:!g||b||!n.baseUrl.trim(),variant:"secondary",children:o(b?"checking":"check")})})]}),N&&(0,t.jsx)(u.Badge,{variant:"success"===N?"success":"error",children:o("success"===N?"valid":"invalid")}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(p.Button,{onClick:T,fullWidth:!0,disabled:!n.name.trim()||!n.prefix.trim()||!n.baseUrl.trim()||h,children:o(h?"saving":"save")}),(0,t.jsx)(p.Button,{onClick:l,variant:"ghost",fullWidth:!0,children:o("cancel")})]})]})}):null}q.propTypes={connection:l.default.shape({id:l.default.string,name:l.default.string,email:l.default.string,displayName:l.default.string,rateLimitedUntil:l.default.string,rateLimitProtection:l.default.bool,testStatus:l.default.string,isActive:l.default.bool,priority:l.default.number,lastError:l.default.string,lastErrorType:l.default.string,lastErrorSource:l.default.string,errorCode:l.default.oneOfType([l.default.string,l.default.number]),globalPriority:l.default.number,providerSpecificData:l.default.object}).isRequired,isOAuth:l.default.bool.isRequired,isCodex:l.default.bool,isFirst:l.default.bool.isRequired,isLast:l.default.bool.isRequired,onMoveUp:l.default.func.isRequired,onMoveDown:l.default.func.isRequired,onToggleActive:l.default.func.isRequired,onToggleRateLimit:l.default.func.isRequired,onToggleCodex5h:l.default.func,onToggleCodexWeekly:l.default.func,onRetest:l.default.func.isRequired,isRetesting:l.default.bool,onEdit:l.default.func.isRequired,onDelete:l.default.func.isRequired,onReauth:l.default.func},F.propTypes={isOpen:l.default.bool.isRequired,provider:l.default.string,providerName:l.default.string,isCompatible:l.default.bool,isAnthropic:l.default.bool,onSave:l.default.func.isRequired,onClose:l.default.func.isRequired},H.propTypes={isOpen:l.default.bool.isRequired,connection:l.default.shape({id:l.default.string,name:l.default.string,email:l.default.string,priority:l.default.number,authType:l.default.string,provider:l.default.string}),onSave:l.default.func.isRequired,onClose:l.default.func.isRequired},J.propTypes={isOpen:l.default.bool.isRequired,node:l.default.shape({id:l.default.string,name:l.default.string,prefix:l.default.string,apiType:l.default.string,baseUrl:l.default.string,chatPath:l.default.string,modelsPath:l.default.string}),onSave:l.default.func.isRequired,onClose:l.default.func.isRequired,isAnthropic:l.default.bool},e.s(["default",()=>E],710864)}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,565650,e=>{"use strict";e.i(342923),e.i(80173),e.i(907714),e.i(393718),e.i(703166),e.i(454149),e.i(822124),e.i(969353),e.i(635055),e.i(897844),e.i(450222),e.i(647829),e.i(6998),e.i(982131),e.i(116016),e.i(279743),e.i(193464),e.i(548036),e.i(566770),e.i(953789),e.i(8839),e.i(227404),e.i(621745),e.i(567955),e.i(17517),e.i(419947),e.i(323060),e.i(642440),e.i(629342),e.i(816062),e.i(690777),e.i(563201),e.i(115243),e.i(165149),e.i(359505),e.s([],565650)},11477,e=>{"use strict";var t=e.i(393718);e.s(["Card",()=>t.default])},659497,e=>{"use strict";var t=e.i(843476),s=e.i(271645);e.i(565650);var a=e.i(454149),r=e.i(948148),n=e.i(657688),l=e.i(25230),i=e.i(243009);function o(e,t={},s={}){let a=Number(t?.used||0),r=Number(t?.total||0),n=t?.resetAt||null,l=function(e){if(!e)return!1;let t="number"==typeof e?e:"string"==typeof e?Date.parse(e):NaN;return!!Number.isFinite(t)&&Date.now()>=t}(n),c=l?0:a,d=Number.isFinite(r)?r:0,u=(0,i.safePercentage)(t?.remainingPercentage),x=l&&d>0?100:void 0!==u?u:void 0;return{name:e,used:Number.isFinite(c)?c:0,total:d,resetAt:n,staleAfterReset:l,...void 0!==x?{remainingPercentage:x}:{},...s}}function c(e){let t="string"==typeof e?e.trim():"";if(!t)return{key:"unknown",label:"Unknown",variant:"default",rank:0,raw:null};let s=t.toUpperCase();return s.includes("PRO+")||s.includes("PRO PLUS")||s.includes("PROPLUS")?{key:"plus",label:"Pro+",variant:"secondary",rank:4,raw:t}:s.includes("ENTERPRISE")||s.includes("CORP")||s.includes("ORG")?{key:"enterprise",label:"Enterprise",variant:"info",rank:7,raw:t}:s.includes("TEAM")||s.includes("CHATGPTTEAM")?{key:"team",label:"Team",variant:"info",rank:6,raw:t}:s.includes("BUSINESS")||s.includes("STANDARD")||s.includes("BIZ")?{key:"business",label:"Business",variant:"warning",rank:5,raw:t}:s.includes("STUDENT")?{key:"pro",label:"Student",variant:"primary",rank:3,raw:t}:s.includes("ULTRA")?{key:"ultra",label:"Ultra",variant:"success",rank:4,raw:t}:s.includes("PRO")||s.includes("PREMIUM")?{key:"pro",label:"Pro",variant:"primary",rank:3,raw:t}:s.includes("PLUS")||s.includes("PAID")?{key:"plus",label:"Plus",variant:"secondary",rank:2,raw:t}:s.includes("FREE")||s.includes("BASIC")||s.includes("TRIAL")||s.includes("LEGACY")?{key:"free",label:"Free",variant:"default",rank:1,raw:t}:{key:"unknown",label:t.toLowerCase().split(/[\s_-]+/).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")||"Unknown",variant:"default",rank:0,raw:t}}var d=e.i(393718),u=e.i(969353),x=e.i(623249);let m="omniroute:limits:groupBy",p="omniroute:limits:autoRefresh",h="omniroute:limits:expandedGroups",f={antigravity:{label:"Antigravity",color:"#F59E0B"},github:{label:"GitHub Copilot",color:"#333"},kiro:{label:"Kiro AI",color:"#FF6B35"},codex:{label:"OpenAI Codex",color:"#10A37F"},claude:{label:"Claude Code",color:"#D97757"},glm:{label:"GLM (Z.AI)",color:"#4A90D9"},"kimi-coding":{label:"Kimi Coding",color:"#1E3A8A"}},b=[{key:"all",labelKey:"tierAll"},{key:"enterprise",labelKey:"tierEnterprise"},{key:"team",labelKey:"tierTeam"},{key:"business",labelKey:"tierBusiness"},{key:"ultra",labelKey:"tierUltra"},{key:"pro",labelKey:"tierPro"},{key:"plus",labelKey:"tierPlus"},{key:"free",labelKey:"tierFree"},{key:"unknown",labelKey:"tierUnknown"}];function g(){let e,i=(0,r.useTranslations)("usage"),[g,y]=(0,s.useState)([]),[v,j]=(0,s.useState)({}),[N,k]=(0,s.useState)({}),[w,S]=(0,s.useState)({}),[E,C]=(0,s.useState)(()=>"true"===localStorage.getItem(p)),[I,P]=(0,s.useState)(null),[T,A]=(0,s.useState)(!1),[R,M]=(0,s.useState)(120),[O,q]=(0,s.useState)(!0),[D,U]=(0,s.useState)("all"),[F,K]=(0,s.useState)(()=>{let e=localStorage.getItem(m);return"environment"===e||"none"===e?e:"none"}),[L,_]=(0,s.useState)(()=>{try{let e=localStorage.getItem(h);return e?new Set(JSON.parse(e)):new Set}catch{return new Set}}),B=(0,s.useRef)(null),$=(0,s.useRef)(null),G=(0,s.useRef)({}),H=(0,s.useRef)({}),Q=(0,s.useCallback)(async()=>{try{let e=await fetch("/api/providers/client");if(!e.ok)throw Error("Failed");let t=(await e.json()).connections||[];return y(t),t}catch{return y([]),[]}},[]),z=(0,s.useCallback)(async(e,t,s={})=>{let a=s?.force===!0,r=Date.now(),n=G.current[e]||0;if(a||!(r-n<3e4)){G.current[e]=r,k(t=>({...t,[e]:!0})),S(t=>({...t,[e]:null}));try{let s=await fetch(`/api/usage/${e}`);if(!s.ok){let t=(await s.json().catch(()=>({}))).error||s.statusText;if(404===s.status)return;if(401===s.status)return void j(s=>({...s,[e]:{quotas:[],message:t}}));throw Error(`HTTP ${s.status}: ${t}`)}let a=await s.json(),r=function(e,t){if(!t||"object"!=typeof t)return[];let s=[];try{switch(e.toLowerCase()){case"github":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{(!t?.unlimited||t?.total&&!(t.total<=0))&&s.push(o(e,t))});break;case"antigravity":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{s.push(o(t.displayName||e,t,{modelKey:e}))});break;case"codex":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{s.push(o(e,t))});break;case"kiro":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{s.push(o(e,t))});break;case"claude":t.message?s.push({name:"error",used:0,total:0,resetAt:null,message:t.message}):t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{s.push(o(e,t))});break;default:t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{s.push(o(e,t))})}}catch(t){return console.error(`Error parsing quota data for ${e}:`,t),[]}let a=(0,l.getModelsByProviderId)(e);if(a.length>0){let e=new Map(a.map((e,t)=>[e.id,t]));s.sort((t,s)=>{let a=t.modelKey||t.name,r=s.modelKey||s.name;return(e.get(a)??999)-(e.get(r)??999)})}return s}(t,a);if(r.some(e=>e?.staleAfterReset===!0)){let s=H.current[e]||0;Date.now()-s>=3e4&&(H.current[e]=Date.now(),setTimeout(()=>{z(e,t,{force:!0}).catch(()=>{})},5e3))}j(t=>({...t,[e]:{quotas:r,plan:a.plan||null,message:a.message||null,raw:a}}))}catch(t){S(s=>({...s,[e]:t.message||"Failed to fetch quota"}))}finally{k(t=>({...t,[e]:!1}))}}},[]),J=(0,s.useCallback)(async(e,t)=>{await z(e,t),P(new Date)},[z]),V=(0,s.useCallback)(async()=>{if(!T){A(!0),M(120);try{let e=(await Q()).filter(e=>x.USAGE_SUPPORTED_PROVIDERS.includes(e.provider)&&("oauth"===e.authType||"apikey"===e.authType));await Promise.all(e.map(e=>z(e.id,e.provider))),P(new Date)}catch(e){console.error("Error refreshing all:",e)}finally{A(!1)}}},[T,Q,z]);(0,s.useEffect)(()=>{(async()=>{q(!0),await V(),q(!1)})()},[]),(0,s.useEffect)(()=>{if(!E){B.current&&clearInterval(B.current),$.current&&clearInterval($.current);return}return B.current=setInterval(V,12e4),$.current=setInterval(()=>{M(e=>e<=1?120:e-1)},1e3),()=>{B.current&&clearInterval(B.current),$.current&&clearInterval($.current)}},[E,V]),(0,s.useEffect)(()=>{let e=()=>{document.hidden?(B.current&&clearInterval(B.current),$.current&&clearInterval($.current)):E&&(B.current=setInterval(V,12e4),$.current=setInterval(()=>{M(e=>e<=1?120:e-1)},1e3))};return document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[E,V]);let W=(0,s.useMemo)(()=>g.filter(e=>x.USAGE_SUPPORTED_PROVIDERS.includes(e.provider)&&("oauth"===e.authType||"apikey"===e.authType)),[g]),Z=(0,s.useMemo)(()=>{let e={antigravity:1,github:2,codex:3,claude:4,kiro:5,glm:6,"kimi-coding":7};return[...W].sort((t,s)=>(e[t.provider]||9)-(e[s.provider]||9))},[W]),Y=(0,s.useMemo)(()=>{let e={};for(let t of Z)e[t.id]=c(v[t.id]?.plan);return e},[Z,v]),X=(0,s.useMemo)(()=>{let e={all:Z.length,enterprise:0,team:0,business:0,ultra:0,pro:0,free:0,unknown:0};for(let t of Z){let s=Y[t.id]?.key||"unknown";e[s]=(e[s]||0)+1}return e},[Z,Y]),ee=(0,s.useMemo)(()=>"all"===D?Z:Z.filter(e=>(Y[e.id]?.key||"unknown")===D),[Z,Y,D]),et=(0,s.useMemo)(()=>{if("environment"!==F)return null;let e=new Map;for(let t of ee){let s=t.group||i("ungrouped");e.has(s)||e.set(s,[]),e.get(s).push(t)}return e},[F,ee,i]),es=e=>{K(e),localStorage.setItem(m,e)};return((0,s.useEffect)(()=>{null===localStorage.getItem(m)&&g.some(e=>e.group)&&K("environment")},[g]),(0,s.useEffect)(()=>{if("environment"===F&&et&&0===L.size){let e=new Set([...et.keys()]);_(e),localStorage.setItem(h,JSON.stringify([...e]))}},[F,et]),O)?(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsx)(a.CardSkeleton,{}),(0,t.jsx)(a.CardSkeleton,{})]}):0===Z.length?(0,t.jsx)(d.default,{padding:"lg",children:(0,t.jsxs)("div",{className:"text-center py-12",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[64px] opacity-15",children:"cloud_off"}),(0,t.jsx)("h3",{className:"mt-4 text-lg font-semibold text-text-main",children:i("noProviders")}),(0,t.jsx)("p",{className:"mt-2 text-sm text-text-muted max-w-[400px] mx-auto",children:i("connectProvidersForQuota")})]})}):(0,t.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)("h2",{className:"text-lg font-semibold text-text-main m-0",children:i("providerLimits")}),(0,t.jsxs)("span",{className:"text-[13px] text-text-muted",children:[i("accountsCount",{count:ee.length}),ee.length!==Z.length&&` ${i("filteredFromCount",{count:Z.length})}`]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsxs)("div",{className:"flex rounded-lg border border-white/[0.08] overflow-hidden",children:[(0,t.jsx)("button",{onClick:()=>es("none"),className:"px-2.5 py-1.5 text-[12px] font-medium cursor-pointer border-none",style:{background:"none"===F?"rgba(255,255,255,0.1)":"transparent",color:"none"===F?"var(--text-main)":"var(--text-muted)"},children:i("viewFlat")}),(0,t.jsx)("button",{onClick:()=>es("environment"),className:"px-2.5 py-1.5 text-[12px] font-medium cursor-pointer border-none border-l border-white/[0.08]",style:{background:"environment"===F?"rgba(255,255,255,0.1)":"transparent",color:"environment"===F?"var(--text-main)":"var(--text-muted)",borderLeft:"1px solid rgba(255,255,255,0.08)"},children:i("viewByEnvironment")})]}),(0,t.jsxs)("button",{onClick:()=>{let e=!E;C(e),localStorage.setItem(p,String(e))},className:"flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-white/[0.08] bg-transparent cursor-pointer text-text-main text-[13px]",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[18px]",style:{color:E?"#22c55e":"var(--text-muted)"},children:E?"toggle_on":"toggle_off"}),i("autoRefresh"),E&&(0,t.jsxs)("span",{className:"text-xs text-text-muted",children:["(",R,"s)"]})]}),(0,t.jsxs)("button",{onClick:V,disabled:T,className:"flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg bg-white/[0.06] border border-white/10 text-text-main text-[13px] disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer",children:[(0,t.jsx)("span",{className:`material-symbols-outlined text-[16px] ${T?"animate-spin":""}`,children:"refresh"}),i("refreshAll")]})]})]}),(0,t.jsx)("div",{className:"flex items-center gap-2 flex-wrap",children:b.map(e=>{if("all"!==e.key&&!X[e.key])return null;let s=D===e.key;return(0,t.jsxs)("button",{onClick:()=>U(e.key),className:"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold cursor-pointer",style:{border:s?"1px solid var(--primary, #E54D5E)":"1px solid rgba(255,255,255,0.12)",background:s?"rgba(249,120,21,0.14)":"transparent",color:s?"var(--primary, #E54D5E)":"var(--text-muted)"},children:[(0,t.jsx)("span",{children:i(e.labelKey)}),(0,t.jsx)("span",{className:"opacity-85",children:X[e.key]||0})]},e.key)})}),(0,t.jsxs)("div",{className:"rounded-xl border border-white/[0.06] overflow-hidden bg-black/15",children:[(0,t.jsxs)("div",{className:"items-center px-4 py-2.5 border-b border-white/[0.06] text-[11px] font-semibold uppercase tracking-wider text-text-muted",style:{display:"grid",gridTemplateColumns:"280px 1fr 100px 48px"},children:[(0,t.jsx)("div",{children:i("account")}),(0,t.jsx)("div",{children:i("modelQuotas")}),(0,t.jsx)("div",{className:"text-center",children:i("lastUsed")}),(0,t.jsx)("div",{className:"text-center",children:i("actions")})]}),(e=(e,s)=>{let a=v[e.id],r=N[e.id],l=w[e.id],o=f[e.provider]||{label:e.provider,color:"#666"},d=Y[e.id]||c(null);return(0,t.jsxs)("div",{className:"items-center px-4 py-3.5 transition-[background] duration-150 hover:bg-white/[0.02]",style:{display:"grid",gridTemplateColumns:"280px 1fr 100px 48px",borderBottom:s?"none":"1px solid rgba(255,255,255,0.04)"},children:[(0,t.jsxs)("div",{className:"flex items-center gap-2.5 min-w-0",children:[(0,t.jsx)("div",{className:"w-8 h-8 rounded-lg flex items-center justify-center overflow-hidden shrink-0",children:(0,t.jsx)(n.default,{src:`/providers/${e.provider}.png`,alt:e.provider,width:32,height:32,className:"object-contain",sizes:"32px"})}),(0,t.jsxs)("div",{className:"min-w-0",children:[(0,t.jsx)("div",{className:"text-[13px] font-semibold text-text-main truncate",children:e.name||o.label}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 mt-0.5",children:[(0,t.jsx)("span",{title:a?.plan?i("rawPlanWithValue",{plan:a.plan}):i("noPlanFromProvider"),children:(0,t.jsx)(u.default,{variant:d.variant,size:"sm",dot:!0,children:d.label})}),(0,t.jsx)("span",{className:"text-[11px] text-text-muted",children:o.label})]})]})]}),(0,t.jsx)("div",{className:"flex flex-wrap gap-x-3 gap-y-1.5 pr-3",children:r?(0,t.jsxs)("div",{className:"flex items-center gap-1.5 text-text-muted text-xs",children:[(0,t.jsx)("span",{className:"material-symbols-outlined animate-spin text-[14px]",children:"progress_activity"}),i("loadingQuotas")]}):l?(0,t.jsxs)("div",{className:"flex items-center gap-1.5 text-xs text-red-500",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"error"}),(0,t.jsx)("span",{className:"overflow-hidden text-ellipsis whitespace-nowrap max-w-[300px]",children:l})]}):a?.message&&(!a.quotas||0===a.quotas.length)?(0,t.jsx)("div",{className:"text-xs text-text-muted italic",children:a.message}):a?.quotas?.length>0?a.quotas.map((e,s)=>{var a,r,n;let l=void 0!==e.remainingPercentage?Math.round(e.remainingPercentage):(a=e.used,(r=e.total)&&0!==r?!a||a<0?100:a>=r?0:Math.round((r-a)/r*100):0),i=l>70?{bar:"#22c55e",text:"#22c55e",bg:"rgba(34,197,94,0.12)"}:l>=30?{bar:"#eab308",text:"#eab308",bg:"rgba(234,179,8,0.12)"}:{bar:"#ef4444",text:"#ef4444",bg:"rgba(239,68,68,0.12)"},o=function(e){if(!e)return null;try{let t=new Date(e)-new Date;if(t<=0)return null;let s=Math.floor(t/36e5),a=Math.floor(t%36e5/6e4);if(s>=24){let e=Math.floor(s/24);return`${e}d ${s%24}h`}return`${s}h ${a}m`}catch{return null}}(e.resetAt),c={"gemini-3-pro-high":"G3 Pro","gemini-3-pro-low":"G3 Pro Low","gemini-3-flash":"G3 Flash","gemini-2.5-flash":"G2.5 Flash","claude-opus-4-6-thinking":"Opus 4.6 Tk","claude-opus-4-5-thinking":"Opus 4.5 Tk","claude-opus-4-5":"Opus 4.5","claude-sonnet-4-5-thinking":"Sonnet 4.5 Tk","claude-sonnet-4-5":"Sonnet 4.5",chat:"Chat",completions:"Completions",premium_interactions:"Premium",session:"Session",weekly:"Weekly",agentic_request:"Agentic",agentic_request_freetrial:"Agentic (Trial)"}[n=e.name]||n,d=!0===e.staleAfterReset;return(0,t.jsxs)("div",{className:"flex items-center gap-1.5 min-w-[200px] shrink-0",children:[(0,t.jsx)("span",{className:"text-[11px] font-semibold py-0.5 px-2 rounded whitespace-nowrap min-w-[60px] text-center",style:{background:i.bg,color:i.text},children:c}),d?(0,t.jsx)("span",{className:"text-[10px] text-text-muted whitespace-nowrap",children:"⟳ Refreshing..."}):o?(0,t.jsxs)("span",{className:"text-[10px] text-text-muted whitespace-nowrap",children:["⏱ ",o]}):null,(0,t.jsx)("div",{className:"flex-1 h-1.5 rounded-sm bg-white/[0.06] min-w-[60px] overflow-hidden",children:(0,t.jsx)("div",{className:"h-full rounded-sm transition-[width] duration-300 ease-out",style:{width:`${Math.min(l,100)}%`,background:i.bar}})}),(0,t.jsxs)("span",{className:"text-[11px] font-semibold min-w-[32px] text-right",style:{color:i.text},children:[l,"%"]})]},s)}):(0,t.jsx)("div",{className:"text-xs text-text-muted italic",children:i("noQuotaData")})}),(0,t.jsx)("div",{className:"text-center text-[11px] text-text-muted",children:I?(0,t.jsx)("span",{children:I.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}):"-"}),(0,t.jsx)("div",{className:"flex justify-center gap-0.5",children:(0,t.jsx)("button",{onClick:()=>J(e.id,e.provider),disabled:r,title:i("refreshQuota"),className:"p-1 rounded-md border-none bg-transparent cursor-pointer disabled:cursor-not-allowed disabled:opacity-30 opacity-60 hover:opacity-100 flex items-center justify-center transition-opacity duration-150",children:(0,t.jsx)("span",{className:`material-symbols-outlined text-[16px] text-text-muted ${r?"animate-spin":""}`,children:"refresh"})})})]},e.id)},et?[...et.entries()].map(([s,a])=>(0,t.jsxs)("div",{className:"border border-white/[0.08] rounded-lg overflow-hidden mb-2",children:[(0,t.jsxs)("button",{onClick:()=>{_(e=>{let t=new Set(e);return t.has(s)?t.delete(s):t.add(s),localStorage.setItem(h,JSON.stringify([...t])),t})},className:"w-full flex items-center gap-2 px-4 py-2.5 bg-white/[0.03] hover:bg-white/[0.05] transition-colors text-left border-none cursor-pointer",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[16px] text-text-muted",children:L.has(s)?"expand_less":"expand_more"}),(0,t.jsx)("span",{className:"material-symbols-outlined text-[16px] text-text-muted",children:"folder"}),(0,t.jsx)("span",{className:"text-[12px] font-semibold text-text-main uppercase tracking-wider flex-1",children:s}),(0,t.jsx)("span",{className:"text-[11px] text-text-muted bg-white/[0.06] px-2 py-0.5 rounded-full",children:a.length})]}),L.has(s)&&(0,t.jsx)("div",{children:a.map((t,s)=>e(t,s===a.length-1))})]},s)):ee.map((t,s)=>e(t,s===ee.length-1))),0===ee.length&&(0,t.jsxs)("div",{className:"py-6 px-4 text-center text-text-muted text-[13px]",children:[i("noAccountsForTierFilter")," ",(0,t.jsx)("strong",{children:i(b.find(e=>e.key===D)?.labelKey||"tierUnknown")}),"."]})]})]})}var y=e.i(11477);function v(){let e=(0,r.useTranslations)("usage"),a=(0,r.useTranslations)("common"),[n,l]=(0,s.useState)({lockouts:[],cacheStats:null}),[i,o]=(0,s.useState)(!0),c=(0,s.useCallback)(async()=>{try{let e=await fetch("/api/rate-limits");e.ok&&l(await e.json())}catch{}finally{o(!1)}},[]);return(0,s.useEffect)(()=>{c();let e=setInterval(c,1e4);return()=>clearInterval(e)},[c]),(0,t.jsx)("div",{className:"flex flex-col gap-4",children:(0,t.jsxs)(y.Card,{children:[(0,t.jsxs)("div",{className:"flex items-center gap-3 mb-4",children:[(0,t.jsx)("div",{className:"p-2 rounded-lg bg-orange-500/10 text-orange-500",children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[20px]","aria-hidden":"true",children:"lock_clock"})}),(0,t.jsxs)("div",{className:"flex-1",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold",children:e("modelLockouts")}),(0,t.jsx)("p",{className:"text-sm text-text-muted",children:e("lockoutsAutoRefreshHint")})]}),n.lockouts.length>0&&(0,t.jsx)("span",{className:"px-2.5 py-1 rounded-full text-xs font-semibold bg-orange-500/10 text-orange-400 border border-orange-500/20",children:e("lockedCount",{count:n.lockouts.length})})]}),0===n.lockouts.length?(0,t.jsxs)("div",{className:"text-center py-6 text-text-muted",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[32px] mb-2 block opacity-40","aria-hidden":"true",children:"lock_open"}),(0,t.jsx)("p",{className:"text-sm",children:e("noLockouts")})]}):(0,t.jsx)("div",{className:"flex flex-col gap-2",children:n.lockouts.map((s,r)=>{var n;return(0,t.jsxs)("div",{className:"flex items-center justify-between px-3 py-2.5 rounded-lg bg-orange-500/5 border border-orange-500/15",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[16px] text-orange-400","aria-hidden":"true",children:"lock"}),(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-sm font-medium",children:s.model}),(0,t.jsxs)("p",{className:"text-xs text-text-muted",children:[e("account"),":"," ",(0,t.jsx)("span",{className:"font-mono",children:s.accountId?.slice(0,12)||a("none")}),s.reason&&(0,t.jsxs)(t.Fragment,{children:[e("reasonSeparator"),s.reason]})]})]})]}),(0,t.jsx)("span",{className:"text-xs font-mono tabular-nums text-orange-400",children:e("timeLeft",{time:(n=s.remainingMs)<1e3?e("durationMillisecondsShort",{value:n}):n<6e4?e("durationSecondsShort",{value:Math.ceil(n/1e3)}):e("durationMinutesShort",{value:Math.ceil(n/6e4)})})})]},r)})})]})})}function j(){let e=(0,r.useTranslations)("usage"),[a,n]=(0,s.useState)({count:0,sessions:[]}),[l,i]=(0,s.useState)(!0),o=(0,s.useCallback)(async()=>{try{let e=await fetch("/api/sessions");e.ok&&n(await e.json())}catch{}finally{i(!1)}},[]);return(0,s.useEffect)(()=>{o();let e=setInterval(o,5e3);return()=>clearInterval(e)},[o]),(0,t.jsxs)(y.Card,{children:[(0,t.jsxs)("div",{className:"flex items-center gap-3 mb-5",children:[(0,t.jsx)("div",{className:"p-2 rounded-lg bg-cyan-500/10 text-cyan-500",children:(0,t.jsx)("span",{className:"material-symbols-outlined text-[20px]","aria-hidden":"true",children:"fingerprint"})}),(0,t.jsxs)("div",{className:"flex-1",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold",children:e("activeSessions")}),(0,t.jsx)("p",{className:"text-sm text-text-muted",children:e("sessionsTrackedHint")})]}),(0,t.jsx)("div",{className:"flex items-center gap-2",children:(0,t.jsxs)("span",{className:"flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-cyan-500/10 border border-cyan-500/20",children:[(0,t.jsx)("span",{className:"w-2 h-2 rounded-full bg-cyan-500 animate-pulse"}),(0,t.jsx)("span",{className:"text-sm font-semibold tabular-nums text-cyan-400",children:a.count})]})})]}),0===a.sessions.length?(0,t.jsxs)("div",{className:"text-center py-8 text-text-muted",children:[(0,t.jsx)("span",{className:"material-symbols-outlined text-[40px] mb-2 block opacity-40","aria-hidden":"true",children:"fingerprint"}),(0,t.jsx)("p",{className:"text-sm",children:e("noSessions")}),(0,t.jsx)("p",{className:"text-xs mt-1",children:e("sessionsHint")})]}):(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)("table",{className:"w-full text-sm",children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{className:"border-b border-border/30",children:[(0,t.jsx)("th",{className:"text-left py-2 px-3 text-xs font-semibold text-text-muted uppercase tracking-wider",children:e("session")}),(0,t.jsx)("th",{className:"text-left py-2 px-3 text-xs font-semibold text-text-muted uppercase tracking-wider",children:e("age")}),(0,t.jsx)("th",{className:"text-right py-2 px-3 text-xs font-semibold text-text-muted uppercase tracking-wider",children:e("requests")}),(0,t.jsx)("th",{className:"text-left py-2 px-3 text-xs font-semibold text-text-muted uppercase tracking-wider",children:e("connection")})]})}),(0,t.jsx)("tbody",{children:a.sessions.map(s=>{var a;return(0,t.jsxs)("tr",{className:"border-b border-border/10 hover:bg-surface/20 transition-colors",children:[(0,t.jsx)("td",{className:"py-2.5 px-3",children:(0,t.jsxs)("span",{className:"font-mono text-xs px-2 py-1 rounded bg-surface/40 text-text-muted",children:[s.sessionId.slice(0,12),"…"]})}),(0,t.jsx)("td",{className:"py-2.5 px-3 text-text-muted tabular-nums",children:(a=s.ageMs)<6e4?e("durationSecondsShort",{value:Math.floor(a/1e3)}):a<36e5?e("durationMinutesShort",{value:Math.floor(a/6e4)}):e("durationHoursShort",{value:Math.floor(a/36e5)})}),(0,t.jsx)("td",{className:"py-2.5 px-3 text-right",children:(0,t.jsx)("span",{className:"font-semibold tabular-nums",children:s.requestCount})}),(0,t.jsx)("td",{className:"py-2.5 px-3",children:s.connectionId?(0,t.jsx)("span",{className:"text-xs font-mono text-cyan-400",children:s.connectionId.slice(0,10)}):(0,t.jsx)("span",{className:"text-text-muted/40",children:e("notAvailableSymbol")})})]},s.sessionId)})})]})})]})}function N(){return(0,t.jsxs)("div",{className:"flex flex-col gap-6",children:[(0,t.jsx)(s.Suspense,{fallback:(0,t.jsx)(a.CardSkeleton,{}),children:(0,t.jsx)(g,{})}),(0,t.jsx)(j,{}),(0,t.jsx)(v,{})]})}e.s(["default",()=>N],659497)}]);
|