- Introduced Cloudflare AI as a new provider with specific configurations in providerModels.js and providers.js. - Updated DefaultExecutor to handle account ID resolution for Cloudflare AI connections. - Enhanced AddApiKeyModal and EditConnectionModal to include account ID input for Cloudflare AI. - Implemented validation for Cloudflare AI API key connections in testUtils.js and route.js. - Updated UI components to reflect changes in provider management and connection handling.
86 lines
3.2 KiB
JavaScript
86 lines
3.2 KiB
JavaScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import PropTypes from "prop-types";
|
|
import Card from "./Card";
|
|
import Select from "./Select";
|
|
import Badge from "./Badge";
|
|
|
|
const NONE_PROXY_POOL_VALUE = "__none__";
|
|
|
|
export default function NoAuthProxyCard({ providerId }) {
|
|
const [proxyPools, setProxyPools] = useState([]);
|
|
const [proxyPoolId, setProxyPoolId] = useState(NONE_PROXY_POOL_VALUE);
|
|
const [saving, setSaving] = useState(false);
|
|
const [savedFlash, setSavedFlash] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
Promise.all([
|
|
fetch("/api/proxy-pools?isActive=true", { cache: "no-store" }).then((r) => r.ok ? r.json() : { proxyPools: [] }),
|
|
fetch("/api/settings", { cache: "no-store" }).then((r) => r.ok ? r.json() : {}),
|
|
]).then(([poolData, settingsData]) => {
|
|
if (cancelled) return;
|
|
setProxyPools(poolData.proxyPools || []);
|
|
const override = (settingsData.providerStrategies || {})[providerId] || {};
|
|
setProxyPoolId(override.proxyPoolId || NONE_PROXY_POOL_VALUE);
|
|
}).catch(() => {});
|
|
return () => { cancelled = true; };
|
|
}, [providerId]);
|
|
|
|
const handleChange = async (newValue) => {
|
|
setProxyPoolId(newValue);
|
|
setSaving(true);
|
|
try {
|
|
const res = await fetch("/api/settings", { cache: "no-store" });
|
|
const data = res.ok ? await res.json() : {};
|
|
const current = data.providerStrategies || {};
|
|
const override = { ...(current[providerId] || {}) };
|
|
if (newValue === NONE_PROXY_POOL_VALUE) delete override.proxyPoolId;
|
|
else override.proxyPoolId = newValue;
|
|
const updated = { ...current };
|
|
if (Object.keys(override).length === 0) delete updated[providerId];
|
|
else updated[providerId] = override;
|
|
await fetch("/api/settings", {
|
|
method: "PATCH",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ providerStrategies: updated }),
|
|
});
|
|
setSavedFlash(true);
|
|
setTimeout(() => setSavedFlash(false), 1500);
|
|
} catch (e) {
|
|
console.log("Save proxyPoolId error:", e);
|
|
} finally {
|
|
setSaving(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Card>
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="inline-flex items-center justify-center w-10 h-10 rounded-full bg-green-500/10 text-green-500">
|
|
<span className="material-symbols-outlined text-[20px]">lock_open</span>
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-medium">No authentication required</p>
|
|
<p className="text-xs text-text-muted">This provider is ready to use. Optionally route requests through a proxy pool to bypass IP-based limits.</p>
|
|
</div>
|
|
{savedFlash && <Badge variant="success" size="sm">Saved</Badge>}
|
|
</div>
|
|
<Select
|
|
label="Proxy Pool"
|
|
value={proxyPoolId}
|
|
onChange={(e) => handleChange(e.target.value)}
|
|
disabled={saving}
|
|
options={[
|
|
{ value: NONE_PROXY_POOL_VALUE, label: "None (direct)" },
|
|
...proxyPools.map((pool) => ({ value: pool.id, label: pool.name })),
|
|
]}
|
|
/>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
NoAuthProxyCard.propTypes = {
|
|
providerId: PropTypes.string.isRequired,
|
|
};
|