mirror of
https://github.com/coaidev/coai.git
synced 2025-05-22 14:30:14 +09:00
chore: update model market
This commit is contained in:
parent
c7db899797
commit
2d41885cd6
@ -15,6 +15,7 @@ export type PopupDialogProps = {
|
|||||||
title: string;
|
title: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
placeholder?: string;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
onValueChange?: (value: string) => string;
|
onValueChange?: (value: string) => string;
|
||||||
onSubmit?: (value: string) => Promise<boolean>;
|
onSubmit?: (value: string) => Promise<boolean>;
|
||||||
@ -44,6 +45,7 @@ function PopupDialog({
|
|||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
name,
|
name,
|
||||||
|
placeholder,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
onValueChange,
|
onValueChange,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
@ -71,6 +73,7 @@ function PopupDialog({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
value={value}
|
value={value}
|
||||||
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
@ -35,7 +35,7 @@ function AppProvider() {
|
|||||||
if (!obj) return;
|
if (!obj) return;
|
||||||
|
|
||||||
item.free = obj.type === nonBilling;
|
item.free = obj.type === nonBilling;
|
||||||
item.auth = item.free && !obj.anonymous;
|
item.auth = !item.free || !obj.anonymous;
|
||||||
});
|
});
|
||||||
|
|
||||||
resetJsArray(supportModels, loadPreferenceModels(market));
|
resetJsArray(supportModels, loadPreferenceModels(market));
|
||||||
|
@ -422,6 +422,7 @@
|
|||||||
"update": "更新",
|
"update": "更新",
|
||||||
"migrate": "提交",
|
"migrate": "提交",
|
||||||
"sync": "同步上游",
|
"sync": "同步上游",
|
||||||
|
"sync-site": "上游地址",
|
||||||
"sync-tip": "同步上游模型市场",
|
"sync-tip": "同步上游模型市场",
|
||||||
"sync-placeholder": "请输入上游 Chat Nio 的 API 地址,如:https://api.chatnio.net",
|
"sync-placeholder": "请输入上游 Chat Nio 的 API 地址,如:https://api.chatnio.net",
|
||||||
"sync-items": "共发现 {{length}} 个模型,已有模型 {{exist}} 个(不会覆盖),新增模型 {{new}} 个,本站点渠道已支持模型 {{support}} 个",
|
"sync-items": "共发现 {{length}} 个模型,已有模型 {{exist}} 个(不会覆盖),新增模型 {{new}} 个,本站点渠道已支持模型 {{support}} 个",
|
||||||
|
@ -488,7 +488,8 @@
|
|||||||
"sync-placeholder": "Please enter the API address of the upstream Chat Nio, for example: https://api.chatnio.net",
|
"sync-placeholder": "Please enter the API address of the upstream Chat Nio, for example: https://api.chatnio.net",
|
||||||
"sync-items": "A total of {{length}} models have been found, {{exist}} models have been found (will not be overwritten), {{new}} models have been added, {{support}} models have been supported in this site channel",
|
"sync-items": "A total of {{length}} models have been found, {{exist}} models have been found (will not be overwritten), {{new}} models have been added, {{support}} models have been supported in this site channel",
|
||||||
"sync-all": "Sync all ({{length}})",
|
"sync-all": "Sync all ({{length}})",
|
||||||
"sync-self": "Sync supported models ({{length}})"
|
"sync-self": "Sync supported models ({{length}})",
|
||||||
|
"sync-site": "Upstream address"
|
||||||
},
|
},
|
||||||
"model-chart-tip": "Token usage",
|
"model-chart-tip": "Token usage",
|
||||||
"subscription": "Subscription Management",
|
"subscription": "Subscription Management",
|
||||||
|
@ -488,7 +488,8 @@
|
|||||||
"sync-placeholder": "アップストリームのChat NioのAPIアドレスを入力してください。例: https://api.chatnio.net",
|
"sync-placeholder": "アップストリームのChat NioのAPIアドレスを入力してください。例: https://api.chatnio.net",
|
||||||
"sync-items": "合計{{length}}個のモデルが見つかりました。{{exist}}個のモデルが見つかりました(上書きされません)。{{new}}個のモデルが追加されました。{{support}}個のモデルがこのサイトチャンネルでサポートされています",
|
"sync-items": "合計{{length}}個のモデルが見つかりました。{{exist}}個のモデルが見つかりました(上書きされません)。{{new}}個のモデルが追加されました。{{support}}個のモデルがこのサイトチャンネルでサポートされています",
|
||||||
"sync-all": "すべて同期({{length}})",
|
"sync-all": "すべて同期({{length}})",
|
||||||
"sync-self": "サポートされているモデルを同期({{ length }})"
|
"sync-self": "サポートされているモデルを同期({{ length }})",
|
||||||
|
"sync-site": "アップストリームアドレス"
|
||||||
},
|
},
|
||||||
"model-chart-tip": "トークンの使用状況",
|
"model-chart-tip": "トークンの使用状況",
|
||||||
"subscription": "サブスクリプション管理",
|
"subscription": "サブスクリプション管理",
|
||||||
|
@ -488,7 +488,8 @@
|
|||||||
"sync-placeholder": "Введите API-адрес вышестоящего Chat Nio, например: https://api.chatnio.net",
|
"sync-placeholder": "Введите API-адрес вышестоящего Chat Nio, например: https://api.chatnio.net",
|
||||||
"sync-items": "Всего было найдено {{length}} моделей, {{exist}} моделей было найдено (не будет перезаписано), {{new}} моделей было добавлено, {{support}} моделей было поддержано в этом канале сайта",
|
"sync-items": "Всего было найдено {{length}} моделей, {{exist}} моделей было найдено (не будет перезаписано), {{new}} моделей было добавлено, {{support}} моделей было поддержано в этом канале сайта",
|
||||||
"sync-all": "Синхронизировать все ({{length}})",
|
"sync-all": "Синхронизировать все ({{length}})",
|
||||||
"sync-self": "Синхронизация поддерживаемых моделей ({{length}})"
|
"sync-self": "Синхронизация поддерживаемых моделей ({{length}})",
|
||||||
|
"sync-site": "Адрес выше по потоку"
|
||||||
},
|
},
|
||||||
"model-chart-tip": "Использование токенов",
|
"model-chart-tip": "Использование токенов",
|
||||||
"subscription": "Управление подписками",
|
"subscription": "Управление подписками",
|
||||||
|
@ -8,9 +8,15 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Dispatch, useMemo, useReducer, useState } from "react";
|
import { Dispatch, useMemo, useReducer, useState } from "react";
|
||||||
import { Model as RawModel } from "@/api/types.ts";
|
import { Model as RawModel } from "@/api/types.ts";
|
||||||
import { supportModels } from "@/conf";
|
import { supportModels } from "@/conf";
|
||||||
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
|
||||||
import { Input } from "@/components/ui/input.tsx";
|
import { Input } from "@/components/ui/input.tsx";
|
||||||
import { GripVertical, HelpCircle, Loader2, Plus, Trash2 } from "lucide-react";
|
import {
|
||||||
|
ChevronDown,
|
||||||
|
ChevronUp,
|
||||||
|
HelpCircle,
|
||||||
|
Loader2,
|
||||||
|
Plus,
|
||||||
|
Trash2,
|
||||||
|
} from "lucide-react";
|
||||||
import { generateRandomChar, isUrl } from "@/utils/base.ts";
|
import { generateRandomChar, isUrl } from "@/utils/base.ts";
|
||||||
import Require from "@/components/Require.tsx";
|
import Require from "@/components/Require.tsx";
|
||||||
import { Textarea } from "@/components/ui/textarea.tsx";
|
import { Textarea } from "@/components/ui/textarea.tsx";
|
||||||
@ -26,6 +32,7 @@ import { Combobox } from "@/components/ui/combo-box.tsx";
|
|||||||
import { channelModels } from "@/admin/channel.ts";
|
import { channelModels } from "@/admin/channel.ts";
|
||||||
import { cn } from "@/components/ui/lib/utils.ts";
|
import { cn } from "@/components/ui/lib/utils.ts";
|
||||||
import { marketEvent } from "@/events/market.ts";
|
import { marketEvent } from "@/events/market.ts";
|
||||||
|
import PopupDialog from "@/components/PopupDialog.tsx";
|
||||||
|
|
||||||
type Model = RawModel & {
|
type Model = RawModel & {
|
||||||
seed?: string;
|
seed?: string;
|
||||||
@ -169,6 +176,18 @@ function reducer(state: MarketForm, action: any): MarketForm {
|
|||||||
const [removed] = state.splice(from, 1);
|
const [removed] = state.splice(from, 1);
|
||||||
state.splice(to, 0, removed);
|
state.splice(to, 0, removed);
|
||||||
return [...state];
|
return [...state];
|
||||||
|
case "upward":
|
||||||
|
if (action.payload.idx === 0) return state;
|
||||||
|
const upward = state[action.payload.idx];
|
||||||
|
state[action.payload.idx] = state[action.payload.idx - 1];
|
||||||
|
state[action.payload.idx - 1] = upward;
|
||||||
|
return [...state];
|
||||||
|
case "downward":
|
||||||
|
if (action.payload.idx === state.length - 1) return state;
|
||||||
|
const downward = state[action.payload.idx];
|
||||||
|
state[action.payload.idx] = state[action.payload.idx + 1];
|
||||||
|
state[action.payload.idx + 1] = downward;
|
||||||
|
return [...state];
|
||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
@ -339,8 +358,19 @@ function Market() {
|
|||||||
}, [form, index]);
|
}, [form, index]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [popupOpen, setPopupOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`market`}>
|
<div className={`market`}>
|
||||||
|
<PopupDialog
|
||||||
|
title={t("admin.market.sync")}
|
||||||
|
name={t("admin.market.sync-site")}
|
||||||
|
placeholder={t("admin.market.sync-placeholder")}
|
||||||
|
open={popupOpen}
|
||||||
|
setOpen={setPopupOpen}
|
||||||
|
defaultValue={"https://api.chatnio.net"}
|
||||||
|
/>
|
||||||
|
|
||||||
<Card className={`admin-card market-card`}>
|
<Card className={`admin-card market-card`}>
|
||||||
<CardHeader className={`flex flex-row items-center select-none`}>
|
<CardHeader className={`flex flex-row items-center select-none`}>
|
||||||
<CardTitle>
|
<CardTitle>
|
||||||
@ -348,56 +378,18 @@ function Market() {
|
|||||||
{loading && <Loader2 className={`h-4 w-4 ml-2 animate-spin`} />}
|
{loading && <Loader2 className={`h-4 w-4 ml-2 animate-spin`} />}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Button
|
<Button
|
||||||
loading={true}
|
|
||||||
className={`ml-auto mt-0 whitespace-nowrap`}
|
className={`ml-auto mt-0 whitespace-nowrap`}
|
||||||
size={`sm`}
|
size={`sm`}
|
||||||
style={{ marginTop: 0 }}
|
style={{ marginTop: 0 }}
|
||||||
onClick={update}
|
onClick={() => setPopupOpen(true)}
|
||||||
>
|
>
|
||||||
{t("admin.market.migrate")}
|
{t("admin.market.sync")}
|
||||||
</Button>
|
</Button>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<DragDropContext
|
<div className={`market-list`}>
|
||||||
onDragEnd={(result) => {
|
|
||||||
const { destination, source } = result;
|
|
||||||
if (
|
|
||||||
!destination ||
|
|
||||||
destination.index === source.index ||
|
|
||||||
destination.index === -1
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const from = source.index;
|
|
||||||
const to = destination.index;
|
|
||||||
|
|
||||||
dispatch({ type: "replace", payload: { from, to } });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Droppable droppableId={`admin-market`}>
|
|
||||||
{(provided) => (
|
|
||||||
<div
|
|
||||||
className={`market-list`}
|
|
||||||
{...provided.droppableProps}
|
|
||||||
ref={provided.innerRef}
|
|
||||||
>
|
|
||||||
{form.map((model, index) => (
|
{form.map((model, index) => (
|
||||||
<Draggable
|
<div className={cn("market-item", !checked(index) && "error")}>
|
||||||
draggableId={`admin-model-${model.seed}`}
|
|
||||||
index={index}
|
|
||||||
key={model.seed}
|
|
||||||
>
|
|
||||||
{(provided) => (
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"market-item",
|
|
||||||
!checked(index) && "error",
|
|
||||||
)}
|
|
||||||
ref={provided.innerRef}
|
|
||||||
{...provided.draggableProps}
|
|
||||||
{...provided.dragHandleProps}
|
|
||||||
>
|
|
||||||
<GripVertical className={`drop-icon h-4 w-4 mr-2`} />
|
|
||||||
<div className={`model-wrapper`}>
|
<div className={`model-wrapper`}>
|
||||||
<div className={`market-row`}>
|
<div className={`market-row`}>
|
||||||
<span>
|
<span>
|
||||||
@ -406,9 +398,7 @@ function Market() {
|
|||||||
</span>
|
</span>
|
||||||
<Input
|
<Input
|
||||||
value={model.name}
|
value={model.name}
|
||||||
placeholder={t(
|
placeholder={t("admin.market.model-name-placeholder")}
|
||||||
"admin.market.model-name-placeholder",
|
|
||||||
)}
|
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "update-name",
|
type: "update-name",
|
||||||
@ -435,9 +425,7 @@ function Market() {
|
|||||||
}}
|
}}
|
||||||
className={`model-combobox`}
|
className={`model-combobox`}
|
||||||
list={channelModels}
|
list={channelModels}
|
||||||
placeholder={t(
|
placeholder={t("admin.market.model-id-placeholder")}
|
||||||
"admin.market.model-id-placeholder",
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={`market-row`}>
|
<div className={`market-row`}>
|
||||||
@ -461,9 +449,7 @@ function Market() {
|
|||||||
<div className={`market-row`}>
|
<div className={`market-row`}>
|
||||||
<span>
|
<span>
|
||||||
{t("admin.market.model-context")}
|
{t("admin.market.model-context")}
|
||||||
<Tips
|
<Tips content={t("admin.market.model-context-tip")} />
|
||||||
content={t("admin.market.model-context-tip")}
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
<Switch
|
<Switch
|
||||||
className={`ml-auto`}
|
className={`ml-auto`}
|
||||||
@ -482,11 +468,7 @@ function Market() {
|
|||||||
<div className={`market-row`}>
|
<div className={`market-row`}>
|
||||||
<span>
|
<span>
|
||||||
{t("admin.market.model-is-default")}
|
{t("admin.market.model-is-default")}
|
||||||
<Tips
|
<Tips content={t("admin.market.model-is-default-tip")} />
|
||||||
content={t(
|
|
||||||
"admin.market.model-is-default-tip",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
<Switch
|
<Switch
|
||||||
className={`ml-auto`}
|
className={`ml-auto`}
|
||||||
@ -521,7 +503,32 @@ function Market() {
|
|||||||
<div className={`market-row`}>
|
<div className={`market-row`}>
|
||||||
<div className={`grow`} />
|
<div className={`grow`} />
|
||||||
<Button
|
<Button
|
||||||
|
size={`icon`}
|
||||||
variant={`outline`}
|
variant={`outline`}
|
||||||
|
onClick={() =>
|
||||||
|
dispatch({
|
||||||
|
type: "upward",
|
||||||
|
payload: { idx: index },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={index === 0}
|
||||||
|
>
|
||||||
|
<ChevronUp className={`h-4 w-4`} />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size={`icon`}
|
||||||
|
variant={`outline`}
|
||||||
|
onClick={() =>
|
||||||
|
dispatch({
|
||||||
|
type: "downward",
|
||||||
|
payload: { idx: index },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={index === form.length - 1}
|
||||||
|
>
|
||||||
|
<ChevronDown className={`h-4 w-4`} />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
size={`icon`}
|
size={`icon`}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -532,25 +539,11 @@ function Market() {
|
|||||||
>
|
>
|
||||||
<Trash2 className={`h-4 w-4`} />
|
<Trash2 className={`h-4 w-4`} />
|
||||||
</Button>
|
</Button>
|
||||||
{index === form.length - 1 && (
|
|
||||||
<Button
|
|
||||||
size={`icon`}
|
|
||||||
onClick={() => dispatch({ type: "new" })}
|
|
||||||
>
|
|
||||||
<Plus className={`h-4 w-4`} />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</Draggable>
|
|
||||||
))}
|
))}
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</Droppable>
|
|
||||||
</DragDropContext>
|
|
||||||
<div className={`market-footer flex flex-row items-center mt-4`}>
|
<div className={`market-footer flex flex-row items-center mt-4`}>
|
||||||
<div className={`grow`} />
|
<div className={`grow`} />
|
||||||
<Button
|
<Button
|
||||||
|
Loading…
Reference in New Issue
Block a user