mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
feat(ui): i18n for AI hub public forms and useful links
This commit is contained in:
parent
71624ed3b7
commit
77f006ff8e
6 changed files with 310 additions and 110 deletions
|
|
@ -5,6 +5,7 @@ import { ChevronDownIcon, ChevronRightIcon, ExternalLinkIcon, PlusCircleIcon } f
|
|||
import { Card, Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow, Text, Title } from "@tremor/react";
|
||||
import Link from "next/link";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getProxyBaseUrl, getPublicModelHubInfo, updateUsefulLinksCall } from "../networking";
|
||||
|
||||
interface UsefulLinksManagementProps {
|
||||
|
|
@ -20,6 +21,7 @@ interface Link {
|
|||
}
|
||||
|
||||
const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessToken, userRole }) => {
|
||||
const { t } = useTranslation();
|
||||
const [links, setLinks] = useState<Link[]>([]);
|
||||
const [newLink, setNewLink] = useState({ url: "", displayName: "" });
|
||||
const [editingLink, setEditingLink] = useState<Link | null>(null);
|
||||
|
|
@ -106,7 +108,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error saving links:", error);
|
||||
NotificationsManager.fromBackend(`Failed to save links - ${error}`);
|
||||
NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.saveLinksFailed", { error }));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
@ -118,13 +120,13 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
try {
|
||||
new URL(newLink.url);
|
||||
} catch {
|
||||
NotificationsManager.fromBackend("Please enter a valid URL");
|
||||
NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.invalidUrl"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicate display names
|
||||
if (links.some((link) => link.displayName === newLink.displayName)) {
|
||||
NotificationsManager.fromBackend("A link with this display name already exists");
|
||||
NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.duplicateDisplayName"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +141,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
if (await saveLinksToBackend(updatedLinks)) {
|
||||
setLinks(updatedLinks);
|
||||
setNewLink({ url: "", displayName: "" });
|
||||
NotificationsManager.success("Link added successfully");
|
||||
NotificationsManager.success(t("aiHub.usefulLinksManagement.addSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -154,13 +156,13 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
try {
|
||||
new URL(editingLink.url);
|
||||
} catch {
|
||||
NotificationsManager.fromBackend("Please enter a valid URL");
|
||||
NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.invalidUrl"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicate display names (excluding current link)
|
||||
if (links.some((link) => link.id !== editingLink.id && link.displayName === editingLink.displayName)) {
|
||||
NotificationsManager.fromBackend("A link with this display name already exists");
|
||||
NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.duplicateDisplayName"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +171,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
if (await saveLinksToBackend(updatedLinks)) {
|
||||
setLinks(updatedLinks);
|
||||
setEditingLink(null);
|
||||
NotificationsManager.success("Link updated successfully");
|
||||
NotificationsManager.success(t("aiHub.usefulLinksManagement.updateSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -182,7 +184,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
|
||||
if (await saveLinksToBackend(updatedLinks)) {
|
||||
setLinks(updatedLinks);
|
||||
NotificationsManager.success("Link deleted successfully");
|
||||
NotificationsManager.success(t("aiHub.usefulLinksManagement.deleteSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -208,7 +210,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
if (await saveLinksToBackend(links)) {
|
||||
setIsRearranging(false);
|
||||
setOriginalLinksOrder([]);
|
||||
NotificationsManager.success("Link order saved successfully");
|
||||
NotificationsManager.success(t("aiHub.usefulLinksManagement.reorderSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -230,10 +232,8 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
<Card className="mb-6">
|
||||
<div className="flex items-center justify-between cursor-pointer" onClick={() => setIsExpanded(!isExpanded)}>
|
||||
<div className="flex flex-col">
|
||||
<Title className="mb-0">Link Management</Title>
|
||||
<p className="text-sm text-gray-500">
|
||||
Manage the links that are displayed under 'Useful Links' on the public model hub.
|
||||
</p>
|
||||
<Title className="mb-0">{t("aiHub.usefulLinksManagement.title")}</Title>
|
||||
<p className="text-sm text-gray-500">{t("aiHub.usefulLinksManagement.description")}</p>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
{isExpanded ? (
|
||||
|
|
@ -247,10 +247,14 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
{isExpanded && (
|
||||
<div className="mt-4">
|
||||
<div className="mb-6">
|
||||
<Text className="text-sm font-medium text-gray-700 mb-2">Add New Link</Text>
|
||||
<Text className="text-sm font-medium text-gray-700 mb-2">
|
||||
{t("aiHub.usefulLinksManagement.addNewLink")}
|
||||
</Text>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs text-gray-500 mb-1">Display Name</label>
|
||||
<label className="block text-xs text-gray-500 mb-1">
|
||||
{t("aiHub.usefulLinksManagement.labelDisplayName")}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newLink.displayName}
|
||||
|
|
@ -260,7 +264,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
displayName: e.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="Friendly name"
|
||||
placeholder={t("aiHub.usefulLinksManagement.placeholderDisplayName")}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -286,22 +290,24 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
className={`flex items-center px-4 py-2 rounded-md text-sm ${!newLink.url || !newLink.displayName ? "bg-gray-300 text-gray-500 cursor-not-allowed" : "bg-green-600 text-white hover:bg-green-700"}`}
|
||||
>
|
||||
<PlusCircleIcon className="w-4 h-4 mr-1" />
|
||||
Add Link
|
||||
{t("aiHub.usefulLinksManagement.addLink")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<Text className="text-sm font-medium text-gray-700">Manage Existing Links</Text>
|
||||
<Text className="text-sm font-medium text-gray-700">
|
||||
{t("aiHub.usefulLinksManagement.manageExistingLinks")}
|
||||
</Text>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Link
|
||||
href={`${getProxyBaseUrl()}/ui/model_hub_table`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs bg-blue-50 text-blue-600 px-3 py-1.5 rounded hover:bg-blue-100 flex items-center"
|
||||
title="Open Public Model Hub"
|
||||
title={t("aiHub.usefulLinksManagement.openPublicModelHub")}
|
||||
>
|
||||
Public Model Hub
|
||||
{t("aiHub.usefulLinksManagement.publicModelHub")}
|
||||
<ExternalLinkIcon className="w-4 h-4 ml-1" />
|
||||
</Link>
|
||||
{!isRearranging ? (
|
||||
|
|
@ -309,7 +315,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
onClick={handleStartRearranging}
|
||||
className="text-xs bg-purple-50 text-purple-600 px-3 py-1.5 rounded hover:bg-purple-100 flex items-center"
|
||||
>
|
||||
Rearrange Order
|
||||
{t("aiHub.usefulLinksManagement.rearrangeOrder")}
|
||||
</button>
|
||||
) : (
|
||||
<div className="flex space-x-2">
|
||||
|
|
@ -317,13 +323,13 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
onClick={handleSaveRearranging}
|
||||
className="text-xs bg-green-600 text-white px-3 py-1.5 rounded hover:bg-green-700"
|
||||
>
|
||||
Save Order
|
||||
{t("aiHub.usefulLinksManagement.saveOrder")}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCancelRearranging}
|
||||
className="text-xs bg-gray-50 text-gray-600 px-3 py-1.5 rounded hover:bg-gray-100"
|
||||
>
|
||||
Cancel
|
||||
{t("common.cancel")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -334,9 +340,11 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
<Table className="[&_td]:py-0.5 [&_th]:py-1">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeaderCell className="py-1 h-8">Display Name</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">
|
||||
{t("aiHub.usefulLinksManagement.colDisplayName")}
|
||||
</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">URL</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">Actions</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">{t("common.actions")}</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
|
|
@ -376,13 +384,13 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
onClick={handleUpdateLink}
|
||||
className="text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100"
|
||||
>
|
||||
Save
|
||||
{t("common.save")}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCancelEdit}
|
||||
className="text-xs bg-gray-50 text-gray-600 px-2 py-1 rounded hover:bg-gray-100"
|
||||
>
|
||||
Cancel
|
||||
{t("common.cancel")}
|
||||
</button>
|
||||
</div>
|
||||
</TableCell>
|
||||
|
|
@ -397,17 +405,17 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
<TableIconActionButton
|
||||
variant="Up"
|
||||
onClick={() => handleMoveUp(index)}
|
||||
tooltipText="Move up"
|
||||
tooltipText={t("aiHub.usefulLinksManagement.tooltipMoveUp")}
|
||||
disabled={index === 0}
|
||||
disabledTooltipText="Already at the top"
|
||||
disabledTooltipText={t("aiHub.usefulLinksManagement.tooltipAlreadyAtTop")}
|
||||
dataTestId={`move-up-${link.id}`}
|
||||
/>
|
||||
<TableIconActionButton
|
||||
variant="Down"
|
||||
onClick={() => handleMoveDown(index)}
|
||||
tooltipText="Move down"
|
||||
tooltipText={t("aiHub.usefulLinksManagement.tooltipMoveDown")}
|
||||
disabled={index === links.length - 1}
|
||||
disabledTooltipText="Already at the bottom"
|
||||
disabledTooltipText={t("aiHub.usefulLinksManagement.tooltipAlreadyAtBottom")}
|
||||
dataTestId={`move-down-${link.id}`}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -416,19 +424,19 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
<TableIconActionButton
|
||||
variant="Open"
|
||||
onClick={() => setCurrentLink(link.url)}
|
||||
tooltipText="Open link"
|
||||
tooltipText={t("aiHub.usefulLinksManagement.tooltipOpenLink")}
|
||||
dataTestId={`open-link-${link.id}`}
|
||||
/>
|
||||
<TableIconActionButton
|
||||
variant="Edit"
|
||||
onClick={() => handleEditLink(link)}
|
||||
tooltipText="Edit link"
|
||||
tooltipText={t("aiHub.usefulLinksManagement.tooltipEditLink")}
|
||||
dataTestId={`edit-link-${link.id}`}
|
||||
/>
|
||||
<TableIconActionButton
|
||||
variant="Delete"
|
||||
onClick={() => deleteLink(link.id)}
|
||||
tooltipText="Delete link"
|
||||
tooltipText={t("aiHub.usefulLinksManagement.tooltipDeleteLink")}
|
||||
dataTestId={`delete-link-${link.id}`}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -441,7 +449,7 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
|
|||
{links.length === 0 && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={3} className="py-0.5 text-sm text-gray-500 text-center">
|
||||
No links added yet. Add a new link above.
|
||||
{t("aiHub.usefulLinksManagement.noLinks")}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Text, Title, Badge } from "@tremor/react";
|
|||
import { makeAgentsPublicCall } from "../../networking";
|
||||
import NotificationsManager from "../../molecules/notifications_manager";
|
||||
import { AgentHubData } from "@/components/AIHub/AgentHubTableColumns";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
|
||||
const { Step } = Steps;
|
||||
|
||||
|
|
@ -22,6 +23,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
agentHubData,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [selectedAgents, setSelectedAgents] = useState<Set<string>>(new Set());
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
@ -37,7 +39,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
const handleNext = () => {
|
||||
if (currentStep === 0) {
|
||||
if (selectedAgents.size === 0) {
|
||||
NotificationsManager.fromBackend("Please select at least one agent to make public");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeAgentPublicForm.selectAtLeastOne"));
|
||||
return;
|
||||
}
|
||||
setCurrentStep(1);
|
||||
|
|
@ -83,7 +85,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
|
||||
const handleSubmit = async () => {
|
||||
if (selectedAgents.size === 0) {
|
||||
NotificationsManager.fromBackend("Please select at least one agent to make public");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeAgentPublicForm.selectAtLeastOne"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -94,12 +96,12 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
// Make batch API call for all agents
|
||||
await makeAgentsPublicCall(accessToken, agentIdsToMakePublic);
|
||||
|
||||
NotificationsManager.success(`Successfully made ${agentIdsToMakePublic.length} agent(s) public!`);
|
||||
NotificationsManager.success(t("aiHub.makeAgentPublicForm.successCount", { count: agentIdsToMakePublic.length }));
|
||||
handleClose();
|
||||
onSuccess();
|
||||
} catch (error) {
|
||||
console.error("Error making agents public:", error);
|
||||
NotificationsManager.fromBackend("Failed to make agents public. Please try again.");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeAgentPublicForm.failedToMakePublic"));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
|
@ -113,7 +115,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Title>Select Agents to Make Public</Title>
|
||||
<Title>{t("aiHub.makeAgentPublicForm.selectTitle")}</Title>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
checked={allAgentsSelected}
|
||||
|
|
@ -121,21 +123,18 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
onChange={(e) => handleSelectAll(e.target.checked)}
|
||||
disabled={agentHubData.length === 0}
|
||||
>
|
||||
Select All {agentHubData.length > 0 && `(${agentHubData.length})`}
|
||||
{t("aiHub.makeAgentPublicForm.selectAll")} {agentHubData.length > 0 && `(${agentHubData.length})`}
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Select the agents you want to be visible on the public model hub. Users will still require a valid Virtual Key
|
||||
to use these agents.
|
||||
</Text>
|
||||
<Text className="text-sm text-gray-600">{t("aiHub.makeAgentPublicForm.selectDescription")}</Text>
|
||||
|
||||
<div className="max-h-96 overflow-y-auto border rounded-lg p-4">
|
||||
<div className="space-y-3">
|
||||
{agentHubData.length === 0 ? (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<Text>No agents available.</Text>
|
||||
<Text>{t("aiHub.makeAgentPublicForm.noAgents")}</Text>
|
||||
</div>
|
||||
) : (
|
||||
agentHubData.map((agent) => {
|
||||
|
|
@ -162,7 +161,9 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
</Badge>
|
||||
))}
|
||||
{agent.skills.length > 3 && (
|
||||
<Text className="text-xs text-gray-500">+{agent.skills.length - 3} more</Text>
|
||||
<Text className="text-xs text-gray-500">
|
||||
{t("aiHub.makeAgentPublicForm.moreSkills", { count: agent.skills.length - 3 })}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -177,7 +178,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
{selectedAgents.size > 0 && (
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
<strong>{selectedAgents.size}</strong> agent{selectedAgents.size !== 1 ? "s" : ""} selected
|
||||
{t("aiHub.makeAgentPublicForm.selectedCount", { count: selectedAgents.size })}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -188,17 +189,17 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
const renderStep2Content = () => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Title>Confirm Making Agents Public</Title>
|
||||
<Title>{t("aiHub.makeAgentPublicForm.confirmTitle")}</Title>
|
||||
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<Text className="text-sm text-yellow-800">
|
||||
<strong>Warning:</strong> Once you make these agents public, anyone who can go to the{" "}
|
||||
<code>/ui/model_hub_table</code> will be able to know they exist on the proxy.
|
||||
<strong>Warning:</strong>{" "}
|
||||
<Trans i18nKey="aiHub.makeAgentPublicForm.warningText" components={{ code: <code key="code" /> }} />
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<Text className="font-medium">Agents to be made public:</Text>
|
||||
<Text className="font-medium">{t("aiHub.makeAgentPublicForm.agentsToBeMadePublic")}</Text>
|
||||
<div className="max-h-48 overflow-y-auto border rounded-lg p-3">
|
||||
<div className="space-y-2">
|
||||
{Array.from(selectedAgents).map((agentId) => {
|
||||
|
|
@ -225,8 +226,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
Total: <strong>{selectedAgents.size}</strong> agent{selectedAgents.size !== 1 ? "s" : ""} will be made
|
||||
public
|
||||
{t("aiHub.makeAgentPublicForm.totalCount", { count: selectedAgents.size })}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -248,19 +248,19 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
return (
|
||||
<div className="flex justify-between mt-6">
|
||||
<Button onClick={currentStep === 0 ? handleClose : handlePrevious}>
|
||||
{currentStep === 0 ? "Cancel" : "Previous"}
|
||||
{currentStep === 0 ? t("common.cancel") : t("common.previous")}
|
||||
</Button>
|
||||
|
||||
<div className="flex space-x-2">
|
||||
{currentStep === 0 && (
|
||||
<Button onClick={handleNext} disabled={selectedAgents.size === 0}>
|
||||
Next
|
||||
{t("common.next")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{currentStep === 1 && (
|
||||
<Button onClick={handleSubmit} loading={loading}>
|
||||
Make Public
|
||||
{t("aiHub.makeAgentPublicForm.makePublic")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -270,7 +270,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
|
||||
return (
|
||||
<Modal
|
||||
title="Make Agents Public"
|
||||
title={t("aiHub.makeAgentPublicForm.modalTitle")}
|
||||
open={visible}
|
||||
onCancel={handleClose}
|
||||
footer={null}
|
||||
|
|
@ -279,8 +279,8 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
|
|||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Steps current={currentStep} className="mb-6">
|
||||
<Step title="Select Agents" />
|
||||
<Step title="Confirm" />
|
||||
<Step title={t("aiHub.makeAgentPublicForm.stepSelectAgents")} />
|
||||
<Step title={t("aiHub.makeAgentPublicForm.stepConfirm")} />
|
||||
</Steps>
|
||||
|
||||
{renderStepContent()}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Text, Title, Badge } from "@tremor/react";
|
|||
import { makeMCPPublicCall } from "../../networking";
|
||||
import NotificationsManager from "../../molecules/notifications_manager";
|
||||
import { MCPServerData } from "@/components/mcp_hub_table_columns";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
|
||||
const { Step } = Steps;
|
||||
|
||||
|
|
@ -22,6 +23,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
mcpHubData,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [selectedServers, setSelectedServers] = useState<Set<string>>(new Set());
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
@ -37,7 +39,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
const handleNext = () => {
|
||||
if (currentStep === 0) {
|
||||
if (selectedServers.size === 0) {
|
||||
NotificationsManager.fromBackend("Please select at least one MCP server to make public");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeMCPPublicForm.selectAtLeastOne"));
|
||||
return;
|
||||
}
|
||||
setCurrentStep(1);
|
||||
|
|
@ -84,7 +86,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
|
||||
const handleSubmit = async () => {
|
||||
if (selectedServers.size === 0) {
|
||||
NotificationsManager.fromBackend("Please select at least one MCP server to make public");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeMCPPublicForm.selectAtLeastOne"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -95,12 +97,12 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
// Make batch API call for all servers
|
||||
await makeMCPPublicCall(accessToken, serverIdsToMakePublic);
|
||||
|
||||
NotificationsManager.success(`Successfully made ${serverIdsToMakePublic.length} MCP server(s) public!`);
|
||||
NotificationsManager.success(t("aiHub.makeMCPPublicForm.successCount", { count: serverIdsToMakePublic.length }));
|
||||
handleClose();
|
||||
onSuccess();
|
||||
} catch (error) {
|
||||
console.error("Error making MCP servers public:", error);
|
||||
NotificationsManager.fromBackend("Failed to make MCP servers public. Please try again.");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeMCPPublicForm.failedToMakePublic"));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
|
@ -114,7 +116,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Title>Select MCP Servers to Make Public</Title>
|
||||
<Title>{t("aiHub.makeMCPPublicForm.selectTitle")}</Title>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
checked={allServersSelected}
|
||||
|
|
@ -122,21 +124,18 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
onChange={(e) => handleSelectAll(e.target.checked)}
|
||||
disabled={mcpHubData.length === 0}
|
||||
>
|
||||
Select All {mcpHubData.length > 0 && `(${mcpHubData.length})`}
|
||||
{t("aiHub.makeMCPPublicForm.selectAll")} {mcpHubData.length > 0 && `(${mcpHubData.length})`}
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Select the MCP servers you want to be visible on the public model hub. Users will still require a valid
|
||||
Virtual Key to use these servers.
|
||||
</Text>
|
||||
<Text className="text-sm text-gray-600">{t("aiHub.makeMCPPublicForm.selectDescription")}</Text>
|
||||
|
||||
<div className="max-h-96 overflow-y-auto border rounded-lg p-4">
|
||||
<div className="space-y-3">
|
||||
{mcpHubData.length === 0 ? (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<Text>No MCP servers available.</Text>
|
||||
<Text>{t("aiHub.makeMCPPublicForm.noServers")}</Text>
|
||||
</div>
|
||||
) : (
|
||||
mcpHubData.map((server) => {
|
||||
|
|
@ -155,7 +154,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
<Text className="font-medium">{server.server_name}</Text>
|
||||
{isPublic && (
|
||||
<Badge color="emerald" size="sm">
|
||||
Public
|
||||
{t("aiHub.makeMCPPublicForm.badgePublic")}
|
||||
</Badge>
|
||||
)}
|
||||
<Badge color="blue" size="sm">
|
||||
|
|
@ -183,7 +182,9 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
</Badge>
|
||||
))}
|
||||
{server.allowed_tools.length > 3 && (
|
||||
<Text className="text-xs text-gray-500">+{server.allowed_tools.length - 3} more</Text>
|
||||
<Text className="text-xs text-gray-500">
|
||||
{t("aiHub.makeMCPPublicForm.moreTools", { count: server.allowed_tools.length - 3 })}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -198,7 +199,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
{selectedServers.size > 0 && (
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
<strong>{selectedServers.size}</strong> MCP server{selectedServers.size !== 1 ? "s" : ""} selected
|
||||
{t("aiHub.makeMCPPublicForm.selectedCount", { count: selectedServers.size })}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -209,17 +210,17 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
const renderStep2Content = () => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Title>Confirm Making MCP Servers Public</Title>
|
||||
<Title>{t("aiHub.makeMCPPublicForm.confirmTitle")}</Title>
|
||||
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<Text className="text-sm text-yellow-800">
|
||||
<strong>Warning:</strong> Once you make these MCP servers public, anyone who can go to the{" "}
|
||||
<code>/ui/model_hub_table</code> will be able to know they exist on the proxy.
|
||||
<strong>Warning:</strong>{" "}
|
||||
<Trans i18nKey="aiHub.makeMCPPublicForm.warningText" components={{ code: <code key="code" /> }} />
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<Text className="font-medium">MCP Servers to be made public:</Text>
|
||||
<Text className="font-medium">{t("aiHub.makeMCPPublicForm.serversToBeMadePublic")}</Text>
|
||||
<div className="max-h-48 overflow-y-auto border rounded-lg p-3">
|
||||
<div className="space-y-2">
|
||||
{Array.from(selectedServers).map((serverId) => {
|
||||
|
|
@ -261,8 +262,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
Total: <strong>{selectedServers.size}</strong> MCP server{selectedServers.size !== 1 ? "s" : ""} will be
|
||||
made public
|
||||
{t("aiHub.makeMCPPublicForm.totalCount", { count: selectedServers.size })}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -284,19 +284,19 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
return (
|
||||
<div className="flex justify-between mt-6">
|
||||
<Button onClick={currentStep === 0 ? handleClose : handlePrevious}>
|
||||
{currentStep === 0 ? "Cancel" : "Previous"}
|
||||
{currentStep === 0 ? t("common.cancel") : t("common.previous")}
|
||||
</Button>
|
||||
|
||||
<div className="flex space-x-2">
|
||||
{currentStep === 0 && (
|
||||
<Button onClick={handleNext} disabled={selectedServers.size === 0}>
|
||||
Next
|
||||
{t("common.next")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{currentStep === 1 && (
|
||||
<Button onClick={handleSubmit} loading={loading}>
|
||||
Make Public
|
||||
{t("aiHub.makeMCPPublicForm.makePublic")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -306,7 +306,7 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
|
||||
return (
|
||||
<Modal
|
||||
title="Make MCP Servers Public"
|
||||
title={t("aiHub.makeMCPPublicForm.modalTitle")}
|
||||
open={visible}
|
||||
onCancel={handleClose}
|
||||
footer={null}
|
||||
|
|
@ -315,8 +315,8 @@ const MakeMCPPublicForm: React.FC<MakeMCPPublicFormProps> = ({
|
|||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Steps current={currentStep} className="mb-6">
|
||||
<Step title="Select Servers" />
|
||||
<Step title="Confirm" />
|
||||
<Step title={t("aiHub.makeMCPPublicForm.stepSelectServers")} />
|
||||
<Step title={t("aiHub.makeMCPPublicForm.stepConfirm")} />
|
||||
</Steps>
|
||||
|
||||
{renderStepContent()}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Text, Title, Badge } from "@tremor/react";
|
|||
import { makeModelGroupPublic } from "../../networking";
|
||||
import ModelFilters from "../../model_filters";
|
||||
import NotificationsManager from "../../molecules/notifications_manager";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
|
||||
const { Step } = Steps;
|
||||
|
||||
|
|
@ -40,6 +41,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
modelHubData,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [selectedModels, setSelectedModels] = useState<Set<string>>(new Set());
|
||||
const [filteredData, setFilteredData] = useState<ModelGroupInfo[]>([]);
|
||||
|
|
@ -57,7 +59,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
const handleNext = () => {
|
||||
if (currentStep === 0) {
|
||||
if (selectedModels.size === 0) {
|
||||
NotificationsManager.fromBackend("Please select at least one model to make public");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeModelPublicForm.selectAtLeastOne"));
|
||||
return;
|
||||
}
|
||||
setCurrentStep(1);
|
||||
|
|
@ -110,7 +112,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
|
||||
const handleSubmit = async () => {
|
||||
if (selectedModels.size === 0) {
|
||||
NotificationsManager.fromBackend("Please select at least one model to make public");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeModelPublicForm.selectAtLeastOne"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -119,12 +121,14 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
const modelGroupsToMakePublic = Array.from(selectedModels);
|
||||
await makeModelGroupPublic(accessToken, modelGroupsToMakePublic);
|
||||
|
||||
NotificationsManager.success(`Successfully made ${modelGroupsToMakePublic.length} model group(s) public!`);
|
||||
NotificationsManager.success(
|
||||
t("aiHub.makeModelPublicForm.successCount", { count: modelGroupsToMakePublic.length }),
|
||||
);
|
||||
handleClose();
|
||||
onSuccess();
|
||||
} catch (error) {
|
||||
console.error("Error making model groups public:", error);
|
||||
NotificationsManager.fromBackend("Failed to make model groups public. Please try again.");
|
||||
NotificationsManager.fromBackend(t("aiHub.makeModelPublicForm.failedToMakePublic"));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
|
@ -138,7 +142,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Title>Select Models to Make Public</Title>
|
||||
<Title>{t("aiHub.makeModelPublicForm.selectTitle")}</Title>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
checked={allModelsSelected}
|
||||
|
|
@ -146,15 +150,12 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
onChange={(e) => handleSelectAll(e.target.checked)}
|
||||
disabled={filteredData.length === 0}
|
||||
>
|
||||
Select All {filteredData.length > 0 && `(${filteredData.length})`}
|
||||
{t("aiHub.makeModelPublicForm.selectAll")} {filteredData.length > 0 && `(${filteredData.length})`}
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Text className="text-sm text-gray-600">
|
||||
Select the models you want to be visible on the public model hub. Users will still require a valid Virtual Key
|
||||
to use these models.
|
||||
</Text>
|
||||
<Text className="text-sm text-gray-600">{t("aiHub.makeModelPublicForm.selectDescription")}</Text>
|
||||
|
||||
{/* Filters */}
|
||||
<ModelFilters
|
||||
|
|
@ -168,7 +169,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
<div className="space-y-3">
|
||||
{filteredData.length === 0 ? (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<Text>No models match the current filters.</Text>
|
||||
<Text>{t("aiHub.makeModelPublicForm.noModels")}</Text>
|
||||
</div>
|
||||
) : (
|
||||
filteredData.map((model) => (
|
||||
|
|
@ -206,7 +207,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
{selectedModels.size > 0 && (
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
<strong>{selectedModels.size}</strong> model{selectedModels.size !== 1 ? "s" : ""} selected
|
||||
{t("aiHub.makeModelPublicForm.selectedCount", { count: selectedModels.size })}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -217,17 +218,17 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
const renderStep2Content = () => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Title>Confirm Making Models Public</Title>
|
||||
<Title>{t("aiHub.makeModelPublicForm.confirmTitle")}</Title>
|
||||
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<Text className="text-sm text-yellow-800">
|
||||
<strong>Warning:</strong> Once you make these models public, anyone who can go to the{" "}
|
||||
<code>/ui/model_hub_table</code> will be able to know they exist on the proxy.
|
||||
<strong>Warning:</strong>{" "}
|
||||
<Trans i18nKey="aiHub.makeModelPublicForm.warningText" components={{ code: <code key="code" /> }} />
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<Text className="font-medium">Models to be made public:</Text>
|
||||
<Text className="font-medium">{t("aiHub.makeModelPublicForm.modelsToBeMadePublic")}</Text>
|
||||
<div className="max-h-48 overflow-y-auto border rounded-lg p-3">
|
||||
<div className="space-y-2">
|
||||
{Array.from(selectedModels).map((modelGroup) => {
|
||||
|
|
@ -255,8 +256,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<Text className="text-sm text-blue-800">
|
||||
Total: <strong>{selectedModels.size}</strong> model{selectedModels.size !== 1 ? "s" : ""} will be made
|
||||
public
|
||||
{t("aiHub.makeModelPublicForm.totalCount", { count: selectedModels.size })}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -278,19 +278,19 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
return (
|
||||
<div className="flex justify-between mt-6">
|
||||
<Button onClick={currentStep === 0 ? handleClose : handlePrevious}>
|
||||
{currentStep === 0 ? "Cancel" : "Previous"}
|
||||
{currentStep === 0 ? t("common.cancel") : t("common.previous")}
|
||||
</Button>
|
||||
|
||||
<div className="flex space-x-2">
|
||||
{currentStep === 0 && (
|
||||
<Button onClick={handleNext} disabled={selectedModels.size === 0}>
|
||||
Next
|
||||
{t("common.next")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{currentStep === 1 && (
|
||||
<Button onClick={handleSubmit} loading={loading}>
|
||||
Make Public
|
||||
{t("aiHub.makeModelPublicForm.makePublic")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -300,7 +300,7 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
|
||||
return (
|
||||
<Modal
|
||||
title="Make Models Public"
|
||||
title={t("aiHub.makeModelPublicForm.modalTitle")}
|
||||
open={visible}
|
||||
onCancel={handleClose}
|
||||
footer={null}
|
||||
|
|
@ -309,8 +309,8 @@ const MakeModelPublicForm: React.FC<MakeModelPublicFormProps> = ({
|
|||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Steps current={currentStep} className="mb-6">
|
||||
<Step title="Select Models" />
|
||||
<Step title="Confirm" />
|
||||
<Step title={t("aiHub.makeModelPublicForm.stepSelectModels")} />
|
||||
<Step title={t("aiHub.makeModelPublicForm.stepConfirm")} />
|
||||
</Steps>
|
||||
|
||||
{renderStepContent()}
|
||||
|
|
|
|||
|
|
@ -6593,6 +6593,102 @@
|
|||
"searchPlaceholder": "Search by name, namespace, or tag…",
|
||||
"showing_one": "Showing {{filtered}} of {{count}} skill",
|
||||
"showing_other": "Showing {{filtered}} of {{count}} skills"
|
||||
},
|
||||
"usefulLinksManagement": {
|
||||
"title": "Link Management",
|
||||
"description": "Manage the links that are displayed under 'Useful Links' on the public model hub.",
|
||||
"addNewLink": "Add New Link",
|
||||
"labelDisplayName": "Display Name",
|
||||
"placeholderDisplayName": "Friendly name",
|
||||
"addLink": "Add Link",
|
||||
"manageExistingLinks": "Manage Existing Links",
|
||||
"publicModelHub": "Public Model Hub",
|
||||
"openPublicModelHub": "Open Public Model Hub",
|
||||
"rearrangeOrder": "Rearrange Order",
|
||||
"saveOrder": "Save Order",
|
||||
"colDisplayName": "Display Name",
|
||||
"colActions": "Actions",
|
||||
"tooltipMoveUp": "Move up",
|
||||
"tooltipAlreadyAtTop": "Already at the top",
|
||||
"tooltipMoveDown": "Move down",
|
||||
"tooltipAlreadyAtBottom": "Already at the bottom",
|
||||
"tooltipOpenLink": "Open link",
|
||||
"tooltipEditLink": "Edit link",
|
||||
"tooltipDeleteLink": "Delete link",
|
||||
"noLinks": "No links added yet. Add a new link above.",
|
||||
"saveLinksFailed": "Failed to save links - {{error}}",
|
||||
"invalidUrl": "Please enter a valid URL",
|
||||
"duplicateDisplayName": "A link with this display name already exists",
|
||||
"addSuccess": "Link added successfully",
|
||||
"updateSuccess": "Link updated successfully",
|
||||
"deleteSuccess": "Link deleted successfully",
|
||||
"reorderSuccess": "Link order saved successfully"
|
||||
},
|
||||
"makeAgentPublicForm": {
|
||||
"modalTitle": "Make Agents Public",
|
||||
"stepSelectAgents": "Select Agents",
|
||||
"stepConfirm": "Confirm",
|
||||
"selectTitle": "Select Agents to Make Public",
|
||||
"selectAll": "Select All",
|
||||
"selectDescription": "Select the agents you want to be visible on the public model hub. Users will still require a valid Virtual Key to use these agents.",
|
||||
"noAgents": "No agents available.",
|
||||
"moreSkills": "+{{count}} more",
|
||||
"selectedCount_one": "{{count}} agent selected",
|
||||
"selectedCount_other": "{{count}} agents selected",
|
||||
"confirmTitle": "Confirm Making Agents Public",
|
||||
"warningText": "Once you make these agents public, anyone who can go to the <code>/ui/model_hub_table</code> will be able to know they exist on the proxy.",
|
||||
"agentsToBeMadePublic": "Agents to be made public:",
|
||||
"totalCount_one": "Total: {{count}} agent will be made public",
|
||||
"totalCount_other": "Total: {{count}} agents will be made public",
|
||||
"makePublic": "Make Public",
|
||||
"selectAtLeastOne": "Please select at least one agent to make public",
|
||||
"successCount_one": "Successfully made {{count}} agent public!",
|
||||
"successCount_other": "Successfully made {{count}} agents public!",
|
||||
"failedToMakePublic": "Failed to make agents public. Please try again."
|
||||
},
|
||||
"makeMCPPublicForm": {
|
||||
"modalTitle": "Make MCP Servers Public",
|
||||
"stepSelectServers": "Select Servers",
|
||||
"stepConfirm": "Confirm",
|
||||
"selectTitle": "Select MCP Servers to Make Public",
|
||||
"selectAll": "Select All",
|
||||
"selectDescription": "Select the MCP servers you want to be visible on the public model hub. Users will still require a valid Virtual Key to use these servers.",
|
||||
"noServers": "No MCP servers available.",
|
||||
"moreTools": "+{{count}} more",
|
||||
"selectedCount_one": "{{count}} MCP server selected",
|
||||
"selectedCount_other": "{{count}} MCP servers selected",
|
||||
"confirmTitle": "Confirm Making MCP Servers Public",
|
||||
"warningText": "Once you make these MCP servers public, anyone who can go to the <code>/ui/model_hub_table</code> will be able to know they exist on the proxy.",
|
||||
"serversToBeMadePublic": "MCP Servers to be made public:",
|
||||
"totalCount_one": "Total: {{count}} MCP server will be made public",
|
||||
"totalCount_other": "Total: {{count}} MCP servers will be made public",
|
||||
"makePublic": "Make Public",
|
||||
"badgePublic": "Public",
|
||||
"selectAtLeastOne": "Please select at least one MCP server to make public",
|
||||
"successCount_one": "Successfully made {{count}} MCP server public!",
|
||||
"successCount_other": "Successfully made {{count}} MCP servers public!",
|
||||
"failedToMakePublic": "Failed to make MCP servers public. Please try again."
|
||||
},
|
||||
"makeModelPublicForm": {
|
||||
"modalTitle": "Make Models Public",
|
||||
"stepSelectModels": "Select Models",
|
||||
"stepConfirm": "Confirm",
|
||||
"selectTitle": "Select Models to Make Public",
|
||||
"selectAll": "Select All",
|
||||
"selectDescription": "Select the models you want to be visible on the public model hub. Users will still require a valid Virtual Key to use these models.",
|
||||
"noModels": "No models match the current filters.",
|
||||
"selectedCount_one": "{{count}} model selected",
|
||||
"selectedCount_other": "{{count}} models selected",
|
||||
"confirmTitle": "Confirm Making Models Public",
|
||||
"warningText": "Once you make these models public, anyone who can go to the <code>/ui/model_hub_table</code> will be able to know they exist on the proxy.",
|
||||
"modelsToBeMadePublic": "Models to be made public:",
|
||||
"totalCount_one": "Total: {{count}} model will be made public",
|
||||
"totalCount_other": "Total: {{count}} models will be made public",
|
||||
"makePublic": "Make Public",
|
||||
"selectAtLeastOne": "Please select at least one model to make public",
|
||||
"successCount_one": "Successfully made {{count}} model group public!",
|
||||
"successCount_other": "Successfully made {{count}} model groups public!",
|
||||
"failedToMakePublic": "Failed to make model groups public. Please try again."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6593,6 +6593,102 @@
|
|||
"searchPlaceholder": "按名称、命名空间或标签搜索…",
|
||||
"showing_one": "显示 {{filtered}} / {{count}} 个技能",
|
||||
"showing_other": "显示 {{filtered}} / {{count}} 个技能"
|
||||
},
|
||||
"usefulLinksManagement": {
|
||||
"title": "链接管理",
|
||||
"description": "管理公开模型 Hub 上「实用链接」栏目中显示的链接。",
|
||||
"addNewLink": "添加新链接",
|
||||
"labelDisplayName": "显示名称",
|
||||
"placeholderDisplayName": "友好名称",
|
||||
"addLink": "添加链接",
|
||||
"manageExistingLinks": "管理现有链接",
|
||||
"publicModelHub": "公开模型 Hub",
|
||||
"openPublicModelHub": "打开公开模型 Hub",
|
||||
"rearrangeOrder": "重新排序",
|
||||
"saveOrder": "保存顺序",
|
||||
"colDisplayName": "显示名称",
|
||||
"colActions": "操作",
|
||||
"tooltipMoveUp": "上移",
|
||||
"tooltipAlreadyAtTop": "已在顶部",
|
||||
"tooltipMoveDown": "下移",
|
||||
"tooltipAlreadyAtBottom": "已在底部",
|
||||
"tooltipOpenLink": "打开链接",
|
||||
"tooltipEditLink": "编辑链接",
|
||||
"tooltipDeleteLink": "删除链接",
|
||||
"noLinks": "暂无链接,请在上方添加新链接。",
|
||||
"saveLinksFailed": "保存链接失败 - {{error}}",
|
||||
"invalidUrl": "请输入有效的 URL",
|
||||
"duplicateDisplayName": "已存在同名显示名称的链接",
|
||||
"addSuccess": "链接添加成功",
|
||||
"updateSuccess": "链接更新成功",
|
||||
"deleteSuccess": "链接删除成功",
|
||||
"reorderSuccess": "链接顺序保存成功"
|
||||
},
|
||||
"makeAgentPublicForm": {
|
||||
"modalTitle": "将 Agent 设为公开",
|
||||
"stepSelectAgents": "选择 Agent",
|
||||
"stepConfirm": "确认",
|
||||
"selectTitle": "选择要公开的 Agent",
|
||||
"selectAll": "全选",
|
||||
"selectDescription": "选择要在公开模型 Hub 上展示的 Agent。用户仍需有效的虚拟密钥才能使用这些 Agent。",
|
||||
"noAgents": "暂无可用 Agent。",
|
||||
"moreSkills": "+{{count}} 个",
|
||||
"selectedCount_one": "已选择 {{count}} 个 Agent",
|
||||
"selectedCount_other": "已选择 {{count}} 个 Agent",
|
||||
"confirmTitle": "确认将 Agent 设为公开",
|
||||
"warningText": "将这些 Agent 设为公开后,任何能访问 <code>/ui/model_hub_table</code> 的用户都能知道它们存在于代理中。",
|
||||
"agentsToBeMadePublic": "即将设为公开的 Agent:",
|
||||
"totalCount_one": "共 {{count}} 个 Agent 将被设为公开",
|
||||
"totalCount_other": "共 {{count}} 个 Agent 将被设为公开",
|
||||
"makePublic": "设为公开",
|
||||
"selectAtLeastOne": "请至少选择一个 Agent 以设为公开",
|
||||
"successCount_one": "成功将 {{count}} 个 Agent 设为公开!",
|
||||
"successCount_other": "成功将 {{count}} 个 Agent 设为公开!",
|
||||
"failedToMakePublic": "将 Agent 设为公开失败,请重试。"
|
||||
},
|
||||
"makeMCPPublicForm": {
|
||||
"modalTitle": "将 MCP 服务器设为公开",
|
||||
"stepSelectServers": "选择服务器",
|
||||
"stepConfirm": "确认",
|
||||
"selectTitle": "选择要公开的 MCP 服务器",
|
||||
"selectAll": "全选",
|
||||
"selectDescription": "选择要在公开模型 Hub 上展示的 MCP 服务器。用户仍需有效的虚拟密钥才能使用这些服务器。",
|
||||
"noServers": "暂无可用 MCP 服务器。",
|
||||
"moreTools": "+{{count}} 个",
|
||||
"selectedCount_one": "已选择 {{count}} 个 MCP 服务器",
|
||||
"selectedCount_other": "已选择 {{count}} 个 MCP 服务器",
|
||||
"confirmTitle": "确认将 MCP 服务器设为公开",
|
||||
"warningText": "将这些 MCP 服务器设为公开后,任何能访问 <code>/ui/model_hub_table</code> 的用户都能知道它们存在于代理中。",
|
||||
"serversToBeMadePublic": "即将设为公开的 MCP 服务器:",
|
||||
"totalCount_one": "共 {{count}} 个 MCP 服务器将被设为公开",
|
||||
"totalCount_other": "共 {{count}} 个 MCP 服务器将被设为公开",
|
||||
"makePublic": "设为公开",
|
||||
"badgePublic": "公开",
|
||||
"selectAtLeastOne": "请至少选择一个 MCP 服务器以设为公开",
|
||||
"successCount_one": "成功将 {{count}} 个 MCP 服务器设为公开!",
|
||||
"successCount_other": "成功将 {{count}} 个 MCP 服务器设为公开!",
|
||||
"failedToMakePublic": "将 MCP 服务器设为公开失败,请重试。"
|
||||
},
|
||||
"makeModelPublicForm": {
|
||||
"modalTitle": "将模型设为公开",
|
||||
"stepSelectModels": "选择模型",
|
||||
"stepConfirm": "确认",
|
||||
"selectTitle": "选择要公开的模型",
|
||||
"selectAll": "全选",
|
||||
"selectDescription": "选择要在公开模型 Hub 上展示的模型。用户仍需有效的虚拟密钥才能使用这些模型。",
|
||||
"noModels": "没有与当前筛选条件匹配的模型。",
|
||||
"selectedCount_one": "已选择 {{count}} 个模型",
|
||||
"selectedCount_other": "已选择 {{count}} 个模型",
|
||||
"confirmTitle": "确认将模型设为公开",
|
||||
"warningText": "将这些模型设为公开后,任何能访问 <code>/ui/model_hub_table</code> 的用户都能知道它们存在于代理中。",
|
||||
"modelsToBeMadePublic": "即将设为公开的模型:",
|
||||
"totalCount_one": "共 {{count}} 个模型将被设为公开",
|
||||
"totalCount_other": "共 {{count}} 个模型将被设为公开",
|
||||
"makePublic": "设为公开",
|
||||
"selectAtLeastOne": "请至少选择一个模型以设为公开",
|
||||
"successCount_one": "成功将 {{count}} 个模型组设为公开!",
|
||||
"successCount_other": "成功将 {{count}} 个模型组设为公开!",
|
||||
"failedToMakePublic": "将模型组设为公开失败,请重试。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue