Add duplicate functionality for assistants and credentials

Implement server-side duplication for both assistants and credentials, allowing users to create copies with unique IDs and modified names. Update the respective API routes and frontend components to handle duplication requests, ensuring sensitive information is securely managed. Enhance the AssistantPage and ComponentsModelsPage to support this new feature, including loading and error handling for the duplication process.
This commit is contained in:
Xin Wang
2026-06-09 09:48:43 +08:00
parent b444ea777c
commit 30b96bb3be
5 changed files with 642 additions and 163 deletions

View File

@@ -5,6 +5,7 @@ import {
CheckCircle2,
ChevronLeft,
ChevronRight,
Copy,
Eye,
EyeOff,
HelpCircle,
@@ -109,6 +110,7 @@ export function ComponentsModelsPage() {
const [saving, setSaving] = useState(false);
const [saveError, setSaveError] = useState<string | null>(null);
const [deletingId, setDeletingId] = useState<string | null>(null);
const [duplicatingId, setDuplicatingId] = useState<string | null>(null);
const [testing, setTesting] = useState(false);
const [testResult, setTestResult] = useState<"idle" | "ok" | "fail">("idle");
@@ -233,6 +235,19 @@ export function ComponentsModelsPage() {
}
}
// 服务端整行复制(含真 key,密钥不经浏览器)
async function handleDuplicate(id: string) {
setDuplicatingId(id);
try {
await credentialsApi.duplicate(id);
await loadModels();
} catch (error) {
setLoadError(error instanceof Error ? error.message : "复制失败");
} finally {
setDuplicatingId(null);
}
}
const filteredModels = models.filter((model) => {
if (typeFilter !== "全部" && model.type !== typeFilter) {
return false;
@@ -404,6 +419,21 @@ export function ComponentsModelsPage() {
align="end"
className="w-32 min-w-32 rounded-xl border border-hairline bg-popover p-1"
>
<DropdownMenuItem
className="rounded-lg"
disabled={duplicatingId === model.id}
onSelect={(event) => {
event.preventDefault();
void handleDuplicate(model.id);
}}
>
{duplicatingId === model.id ? (
<Loader2 size={14} className="animate-spin" />
) : (
<Copy size={14} />
)}
</DropdownMenuItem>
<DropdownMenuItem
variant="destructive"
className="rounded-lg"