@nextclaw/ui 0.9.7 → 0.9.9
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/CHANGELOG.md +14 -0
- package/dist/assets/{ChannelsList-BEbqjBdM.js → ChannelsList-a063_8pv.js} +1 -1
- package/dist/assets/{ChatPage-BaUQCtqU.js → ChatPage-CMthudUt.js} +1 -1
- package/dist/assets/{DocBrowser-CtDiU1-0.js → DocBrowser-BOvBC_5q.js} +1 -1
- package/dist/assets/{LogoBadge-Cy-EHxZ6.js → LogoBadge-BUvLZbji.js} +1 -1
- package/dist/assets/{MarketplacePage-D_r1Xy_C.js → MarketplacePage-CcbfvtGX.js} +1 -1
- package/dist/assets/{McpMarketplacePage-Bftp9zkB.js → McpMarketplacePage-D56yvyWI.js} +1 -1
- package/dist/assets/{ModelConfig-CdFIVFue.js → ModelConfig-D5AuTffd.js} +1 -1
- package/dist/assets/ProvidersList-Bd4n7muZ.js +1 -0
- package/dist/assets/{RemoteAccessPage-3JbDaO3y.js → RemoteAccessPage-Be8jduPM.js} +1 -1
- package/dist/assets/{RuntimeConfig-V2C7bIJt.js → RuntimeConfig-D8DYogZ1.js} +1 -1
- package/dist/assets/{SearchConfig-Wq9VNK2x.js → SearchConfig-BtiGCmXR.js} +1 -1
- package/dist/assets/{SecretsConfig-DuYOs4z3.js → SecretsConfig-fwAjbwlq.js} +1 -1
- package/dist/assets/{SessionsConfig-fuPlbwC7.js → SessionsConfig-Y7_TDSk2.js} +1 -1
- package/dist/assets/{chat-message-D729qtQ5.js → chat-message-Cwq8nW0e.js} +1 -1
- package/dist/assets/index-C6dwNe7e.js +8 -0
- package/dist/assets/{label-DCtPX8p3.js → label-C0dJBNgU.js} +1 -1
- package/dist/assets/{page-layout-Dr5ymRVA.js → page-layout-4_789zOC.js} +1 -1
- package/dist/assets/{popover-YWmgsAlv.js → popover-CWmq2f6H.js} +1 -1
- package/dist/assets/provider-models-BOeNnjk9.js +1 -0
- package/dist/assets/{security-config-bwP5X0a-.js → security-config-CZeVwEwq.js} +1 -1
- package/dist/assets/{skeleton-C4iXwmBW.js → skeleton-kjkadEki.js} +1 -1
- package/dist/assets/{status-dot-SDG0WNvL.js → status-dot-C7cVa53V.js} +1 -1
- package/dist/assets/{switch-lC_seKUL.js → switch-C6zdGbY0.js} +1 -1
- package/dist/assets/{tabs-custom-LAWD0u69.js → tabs-custom-BQj0Z-ZC.js} +1 -1
- package/dist/assets/{useConfirmDialog-D0akncY4.js → useConfirmDialog-yX-ZMNf9.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +4 -4
- package/src/api/client.ts +1 -1
- package/src/api/remote.types.ts +0 -1
- package/src/api/types.ts +2 -0
- package/src/components/config/ProviderForm.tsx +91 -641
- package/src/components/config/ProvidersList.tsx +10 -5
- package/src/components/config/provider-advanced-settings-section.tsx +92 -0
- package/src/components/config/provider-auth-section.tsx +113 -0
- package/src/components/config/provider-enabled-field.tsx +20 -0
- package/src/components/config/provider-form-support.ts +345 -0
- package/src/components/config/provider-models-section.tsx +198 -0
- package/src/components/config/provider-pill-selector.tsx +39 -0
- package/src/components/config/provider-status-badge.tsx +21 -0
- package/src/hooks/useWebSocket.ts +1 -1
- package/src/lib/i18n.remote.ts +3 -3
- package/src/lib/provider-models.ts +2 -2
- package/dist/assets/ProvidersList-Bx3w67f2.js +0 -1
- package/dist/assets/index-D3eWL7gT.js +0 -8
- package/dist/assets/provider-models-D3B_xWXx.js +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { Button } from '@/components/ui/button';
|
|
2
|
+
import { Input } from '@/components/ui/input';
|
|
3
|
+
import { Label } from '@/components/ui/label';
|
|
4
|
+
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
|
5
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
6
|
+
import { t } from '@/lib/i18n';
|
|
7
|
+
import type { ThinkingLevel } from '@/api/types';
|
|
8
|
+
import { Plus, Settings2, X } from 'lucide-react';
|
|
9
|
+
|
|
10
|
+
type ModelThinkingConfig = Record<string, { supported: ThinkingLevel[]; default?: ThinkingLevel | null }>;
|
|
11
|
+
|
|
12
|
+
type ProviderModelsSectionProps = {
|
|
13
|
+
models: string[];
|
|
14
|
+
modelThinking: ModelThinkingConfig;
|
|
15
|
+
modelDraft: string;
|
|
16
|
+
showModelInput: boolean;
|
|
17
|
+
onModelDraftChange: (value: string) => void;
|
|
18
|
+
onShowModelInputChange: (value: boolean) => void;
|
|
19
|
+
onAddModel: () => void;
|
|
20
|
+
onRemoveModel: (modelName: string) => void;
|
|
21
|
+
onToggleModelThinkingLevel: (modelName: string, level: ThinkingLevel) => void;
|
|
22
|
+
onSetModelThinkingDefault: (modelName: string, level: ThinkingLevel | null) => void;
|
|
23
|
+
thinkingLevels: ThinkingLevel[];
|
|
24
|
+
formatThinkingLevelLabel: (level: ThinkingLevel) => string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function ProviderModelsSection(props: ProviderModelsSectionProps) {
|
|
28
|
+
const {
|
|
29
|
+
models,
|
|
30
|
+
modelThinking,
|
|
31
|
+
modelDraft,
|
|
32
|
+
showModelInput,
|
|
33
|
+
onModelDraftChange,
|
|
34
|
+
onShowModelInputChange,
|
|
35
|
+
onAddModel,
|
|
36
|
+
onRemoveModel,
|
|
37
|
+
onToggleModelThinkingLevel,
|
|
38
|
+
onSetModelThinkingDefault,
|
|
39
|
+
thinkingLevels,
|
|
40
|
+
formatThinkingLevelLabel
|
|
41
|
+
} = props;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className="space-y-2">
|
|
45
|
+
<div className="flex items-center justify-between">
|
|
46
|
+
<Label className="text-sm font-medium text-gray-900">{t('providerModelsTitle')}</Label>
|
|
47
|
+
{!showModelInput ? (
|
|
48
|
+
<button
|
|
49
|
+
type="button"
|
|
50
|
+
onClick={() => onShowModelInputChange(true)}
|
|
51
|
+
className="flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80"
|
|
52
|
+
>
|
|
53
|
+
<Plus className="h-3 w-3" />
|
|
54
|
+
{t('providerAddModel')}
|
|
55
|
+
</button>
|
|
56
|
+
) : null}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
{showModelInput ? (
|
|
60
|
+
<div className="flex items-center gap-2">
|
|
61
|
+
<Input
|
|
62
|
+
value={modelDraft}
|
|
63
|
+
onChange={(event) => onModelDraftChange(event.target.value)}
|
|
64
|
+
onKeyDown={(event) => {
|
|
65
|
+
if (event.key === 'Enter') {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
onAddModel();
|
|
68
|
+
}
|
|
69
|
+
if (event.key === 'Escape') {
|
|
70
|
+
onShowModelInputChange(false);
|
|
71
|
+
onModelDraftChange('');
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
placeholder={t('providerModelInputPlaceholder')}
|
|
75
|
+
className="flex-1 rounded-xl"
|
|
76
|
+
autoFocus
|
|
77
|
+
/>
|
|
78
|
+
<Button type="button" size="sm" onClick={onAddModel} disabled={modelDraft.trim().length === 0}>
|
|
79
|
+
{t('add')}
|
|
80
|
+
</Button>
|
|
81
|
+
<Button
|
|
82
|
+
type="button"
|
|
83
|
+
size="sm"
|
|
84
|
+
variant="ghost"
|
|
85
|
+
onClick={() => {
|
|
86
|
+
onShowModelInputChange(false);
|
|
87
|
+
onModelDraftChange('');
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
<X className="h-4 w-4" />
|
|
91
|
+
</Button>
|
|
92
|
+
</div>
|
|
93
|
+
) : null}
|
|
94
|
+
|
|
95
|
+
{models.length === 0 ? (
|
|
96
|
+
<div className="rounded-xl border border-dashed border-gray-200 bg-gray-50 px-4 py-6 text-center">
|
|
97
|
+
<p className="text-sm text-gray-500">{t('providerModelsEmptyShort')}</p>
|
|
98
|
+
{!showModelInput ? (
|
|
99
|
+
<button
|
|
100
|
+
type="button"
|
|
101
|
+
onClick={() => onShowModelInputChange(true)}
|
|
102
|
+
className="mt-2 text-sm font-medium text-primary hover:text-primary/80"
|
|
103
|
+
>
|
|
104
|
+
{t('providerAddFirstModel')}
|
|
105
|
+
</button>
|
|
106
|
+
) : null}
|
|
107
|
+
</div>
|
|
108
|
+
) : (
|
|
109
|
+
<div className="flex flex-wrap gap-2">
|
|
110
|
+
{models.map((modelName) => {
|
|
111
|
+
const thinkingEntry = modelThinking[modelName];
|
|
112
|
+
const supportedLevels = thinkingEntry?.supported ?? [];
|
|
113
|
+
const defaultThinkingLevel = thinkingEntry?.default ?? null;
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<div
|
|
117
|
+
key={modelName}
|
|
118
|
+
className="group inline-flex max-w-full items-center gap-1 rounded-full border border-gray-200 bg-white px-3 py-1.5"
|
|
119
|
+
>
|
|
120
|
+
<span className="max-w-[140px] truncate text-sm text-gray-800 sm:max-w-[220px]">{modelName}</span>
|
|
121
|
+
<Popover>
|
|
122
|
+
<PopoverTrigger asChild>
|
|
123
|
+
<button
|
|
124
|
+
type="button"
|
|
125
|
+
className="inline-flex h-5 w-5 items-center justify-center rounded-full text-gray-400 opacity-100 transition-opacity hover:bg-gray-100 hover:text-gray-600 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100"
|
|
126
|
+
aria-label={t('providerModelThinkingTitle')}
|
|
127
|
+
title={t('providerModelThinkingTitle')}
|
|
128
|
+
>
|
|
129
|
+
<Settings2 className="h-3 w-3" />
|
|
130
|
+
</button>
|
|
131
|
+
</PopoverTrigger>
|
|
132
|
+
<PopoverContent className="w-80 space-y-3">
|
|
133
|
+
<div className="space-y-1">
|
|
134
|
+
<p className="text-xs font-semibold text-gray-800">{t('providerModelThinkingTitle')}</p>
|
|
135
|
+
<p className="text-xs text-gray-500">{t('providerModelThinkingHint')}</p>
|
|
136
|
+
</div>
|
|
137
|
+
<div className="flex flex-wrap gap-1.5">
|
|
138
|
+
{thinkingLevels.map((level) => {
|
|
139
|
+
const selected = supportedLevels.includes(level);
|
|
140
|
+
return (
|
|
141
|
+
<button
|
|
142
|
+
key={level}
|
|
143
|
+
type="button"
|
|
144
|
+
onClick={() => onToggleModelThinkingLevel(modelName, level)}
|
|
145
|
+
className={`rounded-full border px-2.5 py-1 text-xs font-medium transition-colors ${
|
|
146
|
+
selected
|
|
147
|
+
? 'border-primary bg-primary text-white'
|
|
148
|
+
: 'border-gray-200 bg-white text-gray-600 hover:border-primary/40 hover:text-primary'
|
|
149
|
+
}`}
|
|
150
|
+
>
|
|
151
|
+
{formatThinkingLevelLabel(level)}
|
|
152
|
+
</button>
|
|
153
|
+
);
|
|
154
|
+
})}
|
|
155
|
+
</div>
|
|
156
|
+
<div className="space-y-1.5">
|
|
157
|
+
<Label className="text-xs font-medium text-gray-700">{t('providerModelThinkingDefault')}</Label>
|
|
158
|
+
<Select
|
|
159
|
+
value={defaultThinkingLevel ?? '__none__'}
|
|
160
|
+
onValueChange={(value) =>
|
|
161
|
+
onSetModelThinkingDefault(modelName, value === '__none__' ? null : (value as ThinkingLevel))
|
|
162
|
+
}
|
|
163
|
+
disabled={supportedLevels.length === 0}
|
|
164
|
+
>
|
|
165
|
+
<SelectTrigger className="h-8 rounded-lg bg-white text-xs">
|
|
166
|
+
<SelectValue />
|
|
167
|
+
</SelectTrigger>
|
|
168
|
+
<SelectContent>
|
|
169
|
+
<SelectItem value="__none__">{t('providerModelThinkingDefaultNone')}</SelectItem>
|
|
170
|
+
{supportedLevels.map((level) => (
|
|
171
|
+
<SelectItem key={level} value={level}>
|
|
172
|
+
{formatThinkingLevelLabel(level)}
|
|
173
|
+
</SelectItem>
|
|
174
|
+
))}
|
|
175
|
+
</SelectContent>
|
|
176
|
+
</Select>
|
|
177
|
+
{supportedLevels.length === 0 ? (
|
|
178
|
+
<p className="text-xs text-gray-500">{t('providerModelThinkingNoSupported')}</p>
|
|
179
|
+
) : null}
|
|
180
|
+
</div>
|
|
181
|
+
</PopoverContent>
|
|
182
|
+
</Popover>
|
|
183
|
+
<button
|
|
184
|
+
type="button"
|
|
185
|
+
onClick={() => onRemoveModel(modelName)}
|
|
186
|
+
className="inline-flex h-5 w-5 items-center justify-center rounded-full text-gray-400 opacity-100 transition-opacity hover:bg-gray-100 hover:text-gray-600 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100"
|
|
187
|
+
aria-label={t('remove')}
|
|
188
|
+
>
|
|
189
|
+
<X className="h-3 w-3" />
|
|
190
|
+
</button>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
})}
|
|
194
|
+
</div>
|
|
195
|
+
)}
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type PillSelectOption = {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type ProviderPillSelectorProps = {
|
|
7
|
+
value: string;
|
|
8
|
+
onChange: (value: string) => void;
|
|
9
|
+
options: PillSelectOption[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type { PillSelectOption };
|
|
13
|
+
|
|
14
|
+
export function ProviderPillSelector(props: ProviderPillSelectorProps) {
|
|
15
|
+
const { value, onChange, options } = props;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div className="flex flex-wrap gap-2">
|
|
19
|
+
{options.map((option) => {
|
|
20
|
+
const selected = option.value === value;
|
|
21
|
+
return (
|
|
22
|
+
<button
|
|
23
|
+
key={option.value}
|
|
24
|
+
type="button"
|
|
25
|
+
onClick={() => onChange(option.value)}
|
|
26
|
+
aria-pressed={selected}
|
|
27
|
+
className={`rounded-full border px-3 py-1.5 text-xs font-medium transition-colors ${
|
|
28
|
+
selected
|
|
29
|
+
? 'border-primary bg-primary text-white shadow-sm'
|
|
30
|
+
: 'border-gray-200 bg-white text-gray-700 hover:border-primary/40 hover:text-primary'
|
|
31
|
+
}`}
|
|
32
|
+
>
|
|
33
|
+
{option.label}
|
|
34
|
+
</button>
|
|
35
|
+
);
|
|
36
|
+
})}
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { StatusDot } from '@/components/ui/status-dot';
|
|
2
|
+
import { t } from '@/lib/i18n';
|
|
3
|
+
|
|
4
|
+
type ProviderStatusBadgeProps = {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
apiKeySet: boolean;
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function ProviderStatusBadge(props: ProviderStatusBadgeProps) {
|
|
11
|
+
if (!props.enabled) {
|
|
12
|
+
return <StatusDot status="inactive" label={t('disabled')} className={props.className} />;
|
|
13
|
+
}
|
|
14
|
+
return (
|
|
15
|
+
<StatusDot
|
|
16
|
+
status={props.apiKeySet ? 'ready' : 'setup'}
|
|
17
|
+
label={props.apiKeySet ? t('statusReady') : t('statusSetup')}
|
|
18
|
+
className={props.className}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -36,7 +36,7 @@ export function useWebSocket(queryClient?: QueryClient) {
|
|
|
36
36
|
const wsUrl = (() => {
|
|
37
37
|
const base = API_BASE?.replace(/\/$/, '');
|
|
38
38
|
if (!base) {
|
|
39
|
-
return 'ws://127.0.0.1:
|
|
39
|
+
return 'ws://127.0.0.1:55667/ws';
|
|
40
40
|
}
|
|
41
41
|
try {
|
|
42
42
|
const resolved = new URL(base, window.location.origin);
|
package/src/lib/i18n.remote.ts
CHANGED
|
@@ -189,10 +189,10 @@ export const REMOTE_LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
189
189
|
remoteEmail: { zh: '邮箱', en: 'Email' },
|
|
190
190
|
remotePassword: { zh: '密码', en: 'Password' },
|
|
191
191
|
remotePasswordPlaceholder: { zh: '请输入你的平台密码', en: 'Enter your platform password' },
|
|
192
|
-
remoteRegisterIfNeeded: { zh: '
|
|
192
|
+
remoteRegisterIfNeeded: { zh: '首次验证自动创建账号', en: 'Auto-create on First Verification' },
|
|
193
193
|
remoteRegisterIfNeededHelp: {
|
|
194
|
-
zh: '
|
|
195
|
-
en: 'When enabled, the UI will
|
|
194
|
+
zh: '如果邮箱还没有对应账号,平台会在验证码验证成功后自动创建账号并保存登录态。',
|
|
195
|
+
en: 'When enabled, the UI will sign in on the platform and then save the resulting login token.'
|
|
196
196
|
},
|
|
197
197
|
remoteLogin: { zh: '登录平台', en: 'Login to Platform' },
|
|
198
198
|
remoteCreateAccount: { zh: '注册并登录', en: 'Create Account & Login' },
|
|
@@ -174,8 +174,8 @@ function isProviderConfigured(provider: ProviderConfigView | undefined): boolean
|
|
|
174
174
|
if (!provider) {
|
|
175
175
|
return false;
|
|
176
176
|
}
|
|
177
|
-
// Keep in sync with ProvidersList "已配置" tab: only
|
|
178
|
-
return provider.apiKeySet === true;
|
|
177
|
+
// Keep in sync with ProvidersList "已配置" tab: only enabled providers with apiKey count as configured.
|
|
178
|
+
return provider.enabled !== false && provider.apiKeySet === true;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
export function buildProviderModelCatalog(params: {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as x,j as e,aF as Mt,aG as Tt,az as ot,at as _e,f as kt,e as F,X as tt,aH as st,i as St,aI as Lt,G as It,K as Dt}from"./vendor-CmQZsDAE.js";import{c as de,I as X,B as z,t as n,u as ct,a as dt,b as ut,U as Et,V as _t,W as $t,X as Bt,Y as zt,Z as Kt,_ as Ft,S as Te,e as ke,f as Se,g as Le,h as ye,$ as Ot}from"./index-D3eWL7gT.js";import{L as O}from"./label-DCtPX8p3.js";import{a as Ht,b as Rt,c as Wt}from"./popover-YWmgsAlv.js";import{S as mt}from"./status-dot-SDG0WNvL.js";import{h as le}from"./config-hints-CApS3K_7.js";import{c as qt,b as Gt,C as Ut,a as Vt}from"./config-layout-BHnOoweL.js";import{T as Qt}from"./tabs-custom-LAWD0u69.js";import{L as Xt}from"./LogoBadge-Cy-EHxZ6.js";import{P as Yt,a as Zt}from"./page-layout-Dr5ymRVA.js";function Jt({isSet:t,className:r,value:a,onChange:l,placeholder:c,...g}){const[d,u]=x.useState(!1),[j,b]=x.useState(!1),w=typeof a=="string"&&a.length>0,I=t&&!w&&!j;return e.jsxs("div",{className:"relative",children:[I?e.jsx("div",{onClick:()=>b(!0),className:de("flex h-9 w-full rounded-xl border border-gray-200/80 bg-white px-3.5 py-2 text-sm text-gray-500 cursor-text items-center pr-12",r),children:"••••••••••••"}):e.jsx(X,{type:d?"text":"password",className:de("pr-12",r),value:a,onChange:l,onBlur:()=>{w||b(!1)},placeholder:c,autoFocus:j,...g}),e.jsx("div",{className:"absolute right-2 top-1/2 -translate-y-1/2 flex gap-1",children:(t||w)&&e.jsx(z,{type:"button",variant:"ghost",size:"icon",className:"h-7 w-7",onClick:()=>u(!d),children:d?e.jsx(Mt,{className:"h-4 w-4"}):e.jsx(Tt,{className:"h-4 w-4"})})})]})}function es({value:t,onChange:r,className:a}){const l=t?Object.entries(t):[],c=(u,j,b)=>{const w=[...l];w[u]=[j,b],r(Object.fromEntries(w))},g=()=>{r({...t,"":""})},d=u=>{const j=l.filter((b,w)=>w!==u);r(Object.fromEntries(j))};return e.jsxs("div",{className:de("space-y-2",a),children:[l.map(([u,j],b)=>e.jsxs("div",{className:"flex gap-2",children:[e.jsx(X,{type:"text",value:u,onChange:w=>c(b,w.target.value,j),placeholder:n("headerName"),className:"flex-1"}),e.jsx(X,{type:"text",value:j,onChange:w=>c(b,u,w.target.value),placeholder:n("headerValue"),className:"flex-1"}),e.jsx(z,{type:"button",variant:"ghost",size:"icon",onClick:()=>d(b),children:e.jsx(ot,{className:"h-4 w-4 text-red-500"})})]},b)),e.jsxs(z,{type:"button",variant:"outline",size:"sm",onClick:g,children:[e.jsx(_e,{className:"h-4 w-4 mr-2"}),n("add")]})]})}const ts={displayName:"",apiKeySet:!1,apiBase:null,extraHeaders:null,wireApi:null,models:[],modelThinking:{}},Ee=["off","minimal","low","medium","high","adaptive","xhigh"],ss=new Set(Ee);function ce(t){if(!t)return null;const r=Object.entries(t).map(([a,l])=>[a.trim(),l]).filter(([a])=>a.length>0);return r.length===0?null:Object.fromEntries(r)}function nt(t,r){const a=ce(t),l=ce(r);if(a===null&&l===null)return!0;if(!a||!l)return!1;const c=Object.entries(a).sort(([d],[u])=>d.localeCompare(u)),g=Object.entries(l).sort(([d],[u])=>d.localeCompare(u));return c.length!==g.length?!1:c.every(([d,u],j)=>d===g[j][0]&&u===g[j][1])}function Ie(t){if(!t||t.length===0)return[];const r=new Set;for(const a of t){const l=a.trim();l&&r.add(l)}return[...r]}function ns(t,r){const a=t.trim();if(!a||!r.trim())return a;const l=`${r.trim()}/`;return a.startsWith(l)?a.slice(l.length):a}function oe(t,r){let a=t.trim();if(!a)return"";for(const l of r){const c=l.trim();c&&(a=ns(a,c))}return a.trim()}function je(t,r){return t.length!==r.length?!1:t.every((a,l)=>a===r[l])}function rs(t,r){const a=[...t];for(const l of r)a.includes(l)||a.push(l);return a}function as(t,r){return r.length===0?t:r.every(l=>!t.includes(l))?rs(t,r):r}function is(t,r){return je(t,r)?[]:t}function $e(t){if(typeof t!="string")return null;const r=t.trim().toLowerCase();return r&&ss.has(r)?r:null}function ht(t){if(!Array.isArray(t))return[];const r=[];for(const a of t){const l=$e(a);!l||r.includes(l)||r.push(l)}return r}function ls(t,r){if(!t)return{};const a={};for(const[l,c]of Object.entries(t)){const g=oe(l,r);if(!g)continue;const d=ht(c==null?void 0:c.supported);if(d.length===0)continue;const u=$e(c==null?void 0:c.default);a[g]=u&&d.includes(u)?{supported:d,default:u}:{supported:d}}return a}function De(t,r){const a=new Set(r.map(c=>c.trim()).filter(Boolean)),l={};for(const[c,g]of Object.entries(t)){if(!a.has(c))continue;const d=ht(g.supported);if(d.length===0)continue;const u=$e(g.default);l[c]=u&&d.includes(u)?{supported:d,default:u}:{supported:d}}return l}function rt(t,r){const a=Object.keys(t).sort(),l=Object.keys(r).sort();if(a.length!==l.length)return!1;for(let c=0;c<a.length;c+=1){const g=a[c];if(g!==l[c])return!1;const d=t[g],u=r[g];if(!d||!u)return!1;const j=[...d.supported].sort(),b=[...u.supported].sort();if(!je(j,b)||(d.default??null)!==(u.default??null))return!1}return!0}function at(t){return t==="off"?n("chatThinkingLevelOff"):t==="minimal"?n("chatThinkingLevelMinimal"):t==="low"?n("chatThinkingLevelLow"):t==="medium"?n("chatThinkingLevelMedium"):t==="high"?n("chatThinkingLevelHigh"):t==="adaptive"?n("chatThinkingLevelAdaptive"):n("chatThinkingLevelXhigh")}function os(t){var j,b,w,I,D;const{providerName:r,methods:a,defaultMethodId:l,language:c}=t;if(a.length===0)return"";const g=new Map;for(const k of a){const A=k.id.trim();A&&g.set(A.toLowerCase(),A)}const d=(...k)=>{for(const A of k){const P=g.get(A.toLowerCase());if(P)return P}},u=l==null?void 0:l.trim();if(r==="minimax-portal"){if(c==="zh")return d("cn","china-mainland")??d(u??"")??((j=a[0])==null?void 0:j.id)??"";if(c==="en")return d("global","intl","international")??d(u??"")??((b=a[0])==null?void 0:b.id)??""}if(u){const k=d(u);if(k)return k}return c==="zh"?d("cn")??((w=a[0])==null?void 0:w.id)??"":c==="en"?d("global")??((I=a[0])==null?void 0:I.id)??"":((D=a[0])==null?void 0:D.id)??""}function it(t){return t.required&&t.hasDefault&&t.optionCount>1&&t.optionCount<=3}function lt(t){const{value:r,onChange:a,options:l}=t;return e.jsx("div",{className:"flex flex-wrap gap-2",children:l.map(c=>{const g=c.value===r;return e.jsx("button",{type:"button",onClick:()=>a(c.value),"aria-pressed":g,className:`rounded-full border px-3 py-1.5 text-xs font-medium transition-colors ${g?"border-primary bg-primary text-white shadow-sm":"border-gray-200 bg-white text-gray-700 hover:border-primary/40 hover:text-primary"}`,children:c.label},c.value)})})}function cs({providerName:t,onProviderDeleted:r}){var Ve,Qe,Xe,Ye,Ze,Je,et;const a=kt(),{data:l}=ct(),{data:c}=dt(),{data:g}=ut(),d=Et(),u=_t(),j=$t(),b=Bt(),w=zt(),I=Kt(),[D,k]=x.useState(""),[A,P]=x.useState(""),[H,ne]=x.useState(null),[f,v]=x.useState("auto"),[N,M]=x.useState([]),[E,_]=x.useState({}),[R,$]=x.useState(""),[G,Y]=x.useState(""),[be,pt]=x.useState(!1),[ve,ue]=x.useState(!1),[me,W]=x.useState(null),[Be,B]=x.useState(""),[ze,he]=x.useState(""),pe=x.useRef(null),i=c==null?void 0:c.providers.find(s=>s.name===t),T=(t?l==null?void 0:l.providers[t]:null)??ts,xe=g==null?void 0:g.uiHints,Z=!!(i!=null&&i.isCustom),J=t?le(`providers.${t}.apiKey`,xe):void 0,K=t?le(`providers.${t}.apiBase`,xe):void 0,we=t?le(`providers.${t}.extraHeaders`,xe):void 0,Ne=t?le(`providers.${t}.wireApi`,xe):void 0,Ke=(i==null?void 0:i.displayName)||t||"",ee=(T.displayName||"").trim()||Ke,xt=G.trim()||ee||t||n("providersSelectPlaceholder"),Fe=(i==null?void 0:i.modelPrefix)||t||"",q=x.useMemo(()=>Ie([Fe,t||""]),[Fe,t]),Ce=(i==null?void 0:i.defaultApiBase)||"",re=T.apiBase||Ce,Ae=ce(T.extraHeaders||null),ae=T.wireApi||(i==null?void 0:i.defaultWireApi)||"auto",Pe=x.useMemo(()=>Ie(((i==null?void 0:i.defaultModels)??[]).map(s=>oe(s,q))),[i==null?void 0:i.defaultModels,q]),Oe=x.useMemo(()=>Ie((T.models??[]).map(s=>oe(s,q))),[T.models,q]),U=x.useMemo(()=>as(Pe,Oe),[Pe,Oe]),ie=x.useMemo(()=>De(ls(T.modelThinking,q),U),[U,q,T.modelThinking]),V=Ft(),ft=((Ve=i==null?void 0:i.apiBaseHelp)==null?void 0:Ve[V])||((Qe=i==null?void 0:i.apiBaseHelp)==null?void 0:Qe.en)||(K==null?void 0:K.help)||n("providerApiBaseHelp"),p=i==null?void 0:i.auth,S=x.useMemo(()=>(p==null?void 0:p.methods)??[],[p==null?void 0:p.methods]),He=x.useMemo(()=>S.map(s=>{var o,h;return{value:s.id,label:((o=s.label)==null?void 0:o[V])||((h=s.label)==null?void 0:h.en)||s.id}}),[S,V]),fe=x.useMemo(()=>os({providerName:t,methods:S,defaultMethodId:p==null?void 0:p.defaultMethodId,language:V}),[t,p==null?void 0:p.defaultMethodId,S,V]),te=x.useMemo(()=>{var o;if(!S.length)return"";const s=ze.trim();return s&&S.some(h=>h.id===s)?s:fe||((o=S[0])==null?void 0:o.id)||""},[ze,fe,S]),se=x.useMemo(()=>S.find(s=>s.id===te),[S,te]),Re=((Xe=se==null?void 0:se.hint)==null?void 0:Xe[V])||((Ye=se==null?void 0:se.hint)==null?void 0:Ye.en)||"",gt=it({required:(p==null?void 0:p.kind)==="device_code",hasDefault:!!((Ze=p==null?void 0:p.defaultMethodId)!=null&&Ze.trim()),optionCount:S.length}),We=((Je=p==null?void 0:p.note)==null?void 0:Je[V])||((et=p==null?void 0:p.note)==null?void 0:et.en)||(p==null?void 0:p.displayName)||"",Me=((i==null?void 0:i.wireApiOptions)||["auto","chat","responses"]).map(s=>({value:s,label:s==="chat"?n("wireApiChat"):s==="responses"?n("wireApiResponses"):n("wireApiAuto")})),yt=it({required:!!(i!=null&&i.supportsWireApi),hasDefault:typeof(i==null?void 0:i.defaultWireApi)=="string"&&i.defaultWireApi.length>0,optionCount:Me.length}),L=x.useCallback(()=>{pe.current!==null&&(window.clearTimeout(pe.current),pe.current=null)},[]),qe=x.useCallback((s,o)=>{L(),pe.current=window.setTimeout(()=>{(async()=>{if(t)try{const h=await w.mutateAsync({provider:t,data:{sessionId:s}});if(h.status==="pending"){B(n("providerAuthWaitingBrowser")),qe(s,h.nextPollMs??o);return}if(h.status==="authorized"){W(null),L(),B(n("providerAuthCompleted")),F.success(n("providerAuthCompleted")),a.invalidateQueries({queryKey:["config"]}),a.invalidateQueries({queryKey:["config-meta"]});return}W(null),L(),B(h.message||`Authorization ${h.status}.`),F.error(h.message||`Authorization ${h.status}.`)}catch(h){W(null),L();const m=h instanceof Error?h.message:String(h);B(m),F.error(`Authorization failed: ${m}`)}})()},Math.max(1e3,o))},[L,w,t,a]);x.useEffect(()=>{if(!t){k(""),P(""),ne(null),v("auto"),M([]),_({}),$(""),Y(""),W(null),B(""),he(""),L();return}k(""),P(re),ne(T.extraHeaders||null),v(ae),M(U),_(ie),$(""),Y(ee),W(null),B(""),he(fe),L()},[t,re,T.extraHeaders,ae,U,ie,ee,fe,L]),x.useEffect(()=>()=>L(),[L]),x.useEffect(()=>{_(s=>De(s,N))},[N]);const Ge=x.useMemo(()=>{if(!t)return!1;const s=D.trim().length>0,o=A.trim()!==re.trim(),h=!nt(H,Ae),m=i!=null&&i.supportsWireApi?f!==ae:!1,y=!je(N,U),C=!rt(E,ie),ge=Z?G.trim()!==ee:!1;return s||o||h||m||y||C||ge},[t,Z,G,ee,D,A,re,H,Ae,i==null?void 0:i.supportsWireApi,f,ae,N,U,E,ie]),Ue=()=>{const s=oe(R,q);if(s){if(N.includes(s)){$("");return}M(o=>[...o,s]),$("")}},jt=(s,o)=>{_(h=>{const m=h[s],y=(m==null?void 0:m.supported)??[],C=y.includes(o)?y.filter(Q=>Q!==o):Ee.filter(Q=>Q===o||y.includes(Q));if(C.length===0){const Q={...h};return delete Q[s],Q}const ge=m!=null&&m.default&&C.includes(m.default)?m.default:void 0;return{...h,[s]:ge?{supported:C,default:ge}:{supported:C}}})},bt=(s,o)=>{_(h=>{const m=h[s];return!m||m.supported.length===0||o&&!m.supported.includes(o)?h:{...h,[s]:o?{supported:m.supported,default:o}:{supported:m.supported}}})},vt=s=>{if(s.preventDefault(),!t)return;const o={},h=D.trim(),m=A.trim(),y=ce(H),C=G.trim();Z&&C!==ee&&(o.displayName=C.length>0?C:null),h.length>0&&(o.apiKey=h),m!==re.trim()&&(o.apiBase=m.length>0&&m!==Ce?m:null),nt(y,Ae)||(o.extraHeaders=y),i!=null&&i.supportsWireApi&&f!==ae&&(o.wireApi=f),je(N,U)||(o.models=is(N,Pe)),rt(E,ie)||(o.modelThinking=De(E,N)),d.mutate({provider:t,data:o})},wt=async()=>{if(!t)return;const s=N.find(m=>m.trim().length>0)??"",o=oe(s,q),h={apiBase:A.trim(),extraHeaders:ce(H),model:o||null};D.trim().length>0&&(h.apiKey=D.trim()),i!=null&&i.supportsWireApi&&(h.wireApi=f);try{const m=await j.mutateAsync({provider:t,data:h});if(m.success){F.success(`${n("providerTestConnectionSuccess")} (${m.latencyMs}ms)`);return}const y=[`provider=${m.provider}`,`latency=${m.latencyMs}ms`];m.model&&y.push(`model=${m.model}`),F.error(`${n("providerTestConnectionFailed")}: ${m.message} | ${y.join(" | ")}`)}catch(m){const y=m instanceof Error?m.message:String(m);F.error(`${n("providerTestConnectionFailed")}: ${y}`)}},Nt=async()=>{if(!(!t||!Z||!window.confirm(n("providerDeleteConfirm"))))try{await u.mutateAsync({provider:t}),r==null||r(t)}catch{}},Ct=async()=>{if(!(!t||(p==null?void 0:p.kind)!=="device_code"))try{B("");const s=await b.mutateAsync({provider:t,data:te?{methodId:te}:{}});if(!s.sessionId||!s.verificationUri)throw new Error(n("providerAuthStartFailed"));W(s.sessionId),B(`${n("providerAuthOpenPrompt")}${s.userCode}${n("providerAuthOpenPromptSuffix")}`),window.open(s.verificationUri,"_blank","noopener,noreferrer"),qe(s.sessionId,s.intervalMs)}catch(s){const o=s instanceof Error?s.message:String(s);W(null),L(),B(o),F.error(`${n("providerAuthStartFailed")}: ${o}`)}},At=async()=>{if(!(!t||(p==null?void 0:p.kind)!=="device_code"))try{L(),W(null);const s=await I.mutateAsync({provider:t}),o=s.expiresAt?` (expires: ${s.expiresAt})`:"";B(`${n("providerAuthImportStatusPrefix")}${o}`),F.success(n("providerAuthImportSuccess")),a.invalidateQueries({queryKey:["config"]}),a.invalidateQueries({queryKey:["config-meta"]})}catch(s){const o=s instanceof Error?s.message:String(s);B(o),F.error(`${n("providerAuthImportFailed")}: ${o}`)}};if(!t||!i)return e.jsx("div",{className:qt,children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-base font-semibold text-gray-900",children:n("providersSelectTitle")}),e.jsx("p",{className:"mt-2 text-sm text-gray-500",children:n("providersSelectDescription")})]})});const Pt=T.apiKeySet?n("statusReady"):n("statusSetup");return e.jsxs("div",{className:Gt,children:[e.jsx("div",{className:"border-b border-gray-100 px-6 py-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"truncate text-lg font-semibold text-gray-900",children:xt}),e.jsxs("div",{className:"flex items-center gap-3",children:[Z&&e.jsx("button",{type:"button",onClick:Nt,disabled:u.isPending,className:"text-gray-400 hover:text-red-500 transition-colors",title:n("providerDelete"),children:e.jsx(ot,{className:"h-4 w-4"})}),e.jsx(mt,{status:T.apiKeySet?"ready":"setup",label:Pt})]})]})}),e.jsxs("form",{onSubmit:vt,className:"flex min-h-0 flex-1 flex-col",children:[e.jsxs("div",{className:"min-h-0 flex-1 space-y-5 overflow-y-auto px-6 py-5",children:[Z&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"providerDisplayName",className:"text-sm font-medium text-gray-900",children:n("providerDisplayName")}),e.jsx(X,{id:"providerDisplayName",type:"text",value:G,onChange:s=>Y(s.target.value),placeholder:Ke||n("providerDisplayNamePlaceholder"),className:"rounded-xl"}),e.jsx("p",{className:"text-xs text-gray-500",children:n("providerDisplayNameHelpShort")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"apiKey",className:"text-sm font-medium text-gray-900",children:(J==null?void 0:J.label)??n("apiKey")}),e.jsx(Jt,{id:"apiKey",value:D,isSet:T.apiKeySet,onChange:s=>k(s.target.value),placeholder:(J==null?void 0:J.placeholder)??n("enterApiKey"),className:"rounded-xl"}),e.jsx("p",{className:"text-xs text-gray-500",children:n("leaveBlankToKeepUnchanged")})]}),(p==null?void 0:p.kind)==="device_code"&&e.jsxs("div",{className:"space-y-2 rounded-xl border border-primary/20 bg-primary-50/50 p-3",children:[e.jsx(O,{className:"text-sm font-medium text-gray-900",children:p.displayName||n("providerAuthSectionTitle")}),We?e.jsx("p",{className:"text-xs text-gray-600",children:We}):null,S.length>1?e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{className:"text-xs font-medium text-gray-700",children:n("providerAuthMethodLabel")}),gt?e.jsx(lt,{value:te,onChange:he,options:He}):e.jsxs(Te,{value:te,onValueChange:he,children:[e.jsx(ke,{className:"h-8 rounded-lg bg-white",children:e.jsx(Se,{placeholder:n("providerAuthMethodPlaceholder")})}),e.jsx(Le,{children:He.map(s=>e.jsx(ye,{value:s.value,children:s.label},s.value))})]}),Re?e.jsx("p",{className:"text-xs text-gray-500",children:Re}):null]}):null,e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(z,{type:"button",variant:"outline",size:"sm",onClick:Ct,disabled:b.isPending||!!me,children:b.isPending?n("providerAuthStarting"):me?n("providerAuthAuthorizing"):n("providerAuthAuthorizeInBrowser")}),p.supportsCliImport?e.jsx(z,{type:"button",variant:"outline",size:"sm",onClick:At,disabled:I.isPending,children:I.isPending?n("providerAuthImporting"):n("providerAuthImportFromCli")}):null,me?e.jsxs("span",{className:"text-xs text-gray-500",children:[n("providerAuthSessionLabel"),": ",me.slice(0,8),"…"]}):null]}),Be?e.jsx("p",{className:"text-xs text-gray-600",children:Be}):null]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"apiBase",className:"text-sm font-medium text-gray-900",children:(K==null?void 0:K.label)??n("apiBase")}),e.jsx(X,{id:"apiBase",type:"text",value:A,onChange:s=>P(s.target.value),placeholder:Ce||(K==null?void 0:K.placeholder)||"https://api.example.com",className:"rounded-xl"}),e.jsx("p",{className:"text-xs text-gray-500",children:ft})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(O,{className:"text-sm font-medium text-gray-900",children:n("providerModelsTitle")}),!ve&&e.jsxs("button",{type:"button",onClick:()=>ue(!0),className:"text-xs text-primary hover:text-primary/80 font-medium flex items-center gap-1",children:[e.jsx(_e,{className:"h-3 w-3"}),n("providerAddModel")]})]}),ve&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(X,{value:R,onChange:s=>$(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),Ue()),s.key==="Escape"&&(ue(!1),$(""))},placeholder:n("providerModelInputPlaceholder"),className:"flex-1 rounded-xl",autoFocus:!0}),e.jsx(z,{type:"button",size:"sm",onClick:Ue,disabled:R.trim().length===0,children:n("add")}),e.jsx(z,{type:"button",size:"sm",variant:"ghost",onClick:()=>{ue(!1),$("")},children:e.jsx(tt,{className:"h-4 w-4"})})]}),N.length===0?e.jsxs("div",{className:"rounded-xl border border-dashed border-gray-200 bg-gray-50 px-4 py-6 text-center",children:[e.jsx("p",{className:"text-sm text-gray-500",children:n("providerModelsEmptyShort")}),!ve&&e.jsx("button",{type:"button",onClick:()=>ue(!0),className:"mt-2 text-sm text-primary hover:text-primary/80 font-medium",children:n("providerAddFirstModel")})]}):e.jsx("div",{className:"flex flex-wrap gap-2",children:N.map(s=>{const o=E[s],h=(o==null?void 0:o.supported)??[],m=(o==null?void 0:o.default)??null;return e.jsxs("div",{className:"group inline-flex max-w-full items-center gap-1 rounded-full border border-gray-200 bg-white px-3 py-1.5",children:[e.jsx("span",{className:"max-w-[140px] truncate text-sm text-gray-800 sm:max-w-[220px]",children:s}),e.jsxs(Ht,{children:[e.jsx(Rt,{asChild:!0,children:e.jsx("button",{type:"button",className:"inline-flex h-5 w-5 items-center justify-center rounded-full text-gray-400 transition-opacity hover:bg-gray-100 hover:text-gray-600 opacity-100 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100","aria-label":n("providerModelThinkingTitle"),title:n("providerModelThinkingTitle"),children:e.jsx(st,{className:"h-3 w-3"})})}),e.jsxs(Wt,{className:"w-80 space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-xs font-semibold text-gray-800",children:n("providerModelThinkingTitle")}),e.jsx("p",{className:"text-xs text-gray-500",children:n("providerModelThinkingHint")})]}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:Ee.map(y=>{const C=h.includes(y);return e.jsx("button",{type:"button",onClick:()=>jt(s,y),className:`rounded-full border px-2.5 py-1 text-xs font-medium transition-colors ${C?"border-primary bg-primary text-white":"border-gray-200 bg-white text-gray-600 hover:border-primary/40 hover:text-primary"}`,children:at(y)},y)})}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{className:"text-xs font-medium text-gray-700",children:n("providerModelThinkingDefault")}),e.jsxs(Te,{value:m??"__none__",onValueChange:y=>bt(s,y==="__none__"?null:y),disabled:h.length===0,children:[e.jsx(ke,{className:"h-8 rounded-lg bg-white text-xs",children:e.jsx(Se,{})}),e.jsxs(Le,{children:[e.jsx(ye,{value:"__none__",children:n("providerModelThinkingDefaultNone")}),h.map(y=>e.jsx(ye,{value:y,children:at(y)},y))]})]}),h.length===0?e.jsx("p",{className:"text-xs text-gray-500",children:n("providerModelThinkingNoSupported")}):null]})]})]}),e.jsx("button",{type:"button",onClick:()=>{M(y=>y.filter(C=>C!==s)),_(y=>{const C={...y};return delete C[s],C})},className:"inline-flex h-5 w-5 items-center justify-center rounded-full text-gray-400 transition-opacity hover:bg-gray-100 hover:text-gray-600 opacity-100 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100","aria-label":n("remove"),children:e.jsx(tt,{className:"h-3 w-3"})})]},s)})})]}),e.jsxs("div",{className:"border-t border-gray-100 pt-4",children:[e.jsxs("button",{type:"button",onClick:()=>pt(!be),className:"flex w-full items-center justify-between text-sm text-gray-600 hover:text-gray-900 transition-colors",children:[e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(st,{className:"h-3.5 w-3.5"}),n("providerAdvancedSettings")]}),e.jsx(St,{className:`h-4 w-4 transition-transform ${be?"rotate-180":""}`})]}),be&&e.jsxs("div",{className:"mt-4 space-y-5",children:[i.supportsWireApi&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"wireApi",className:"text-sm font-medium text-gray-900",children:(Ne==null?void 0:Ne.label)??n("wireApi")}),yt?e.jsx(lt,{value:f,onChange:s=>v(s),options:Me}):e.jsxs(Te,{value:f,onValueChange:s=>v(s),children:[e.jsx(ke,{className:"rounded-xl",children:e.jsx(Se,{})}),e.jsx(Le,{children:Me.map(s=>e.jsx(ye,{value:s.value,children:s.label},s.value))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{className:"text-sm font-medium text-gray-900",children:(we==null?void 0:we.label)??n("extraHeaders")}),e.jsx(es,{value:H,onChange:ne}),e.jsx("p",{className:"text-xs text-gray-500",children:n("providerExtraHeadersHelpShort")})]})]})]})]}),e.jsxs("div",{className:"flex items-center justify-between border-t border-gray-100 px-6 py-4",children:[e.jsxs(z,{type:"button",variant:"outline",size:"sm",onClick:wt,disabled:j.isPending,children:[e.jsx(Lt,{className:"mr-1.5 h-4 w-4"}),j.isPending?n("providerTestingConnection"):n("providerTestConnection")]}),e.jsx(z,{type:"submit",disabled:d.isPending||!Ge,children:d.isPending?n("saving"):Ge?n("save"):n("unchanged")})]})]})]})}function ds(t){if(!t)return null;try{const r=new URL(t),a=r.pathname&&r.pathname!=="/"?r.pathname:"";return`${r.host}${a}`}catch{return t.replace(/^https?:\/\//,"")}}function Cs(){const{data:t}=ct(),{data:r}=dt(),{data:a}=ut(),l=Ot(),[c,g]=x.useState("installed"),[d,u]=x.useState(),[j,b]=x.useState(""),w=a==null?void 0:a.uiHints,I=(r==null?void 0:r.providers)??[],D=(t==null?void 0:t.providers)??{},k=I.filter(f=>{var v;return(v=D[f.name])==null?void 0:v.apiKeySet}).length,A=[{id:"installed",label:n("providersTabConfigured"),count:k},{id:"all",label:n("providersTabAll"),count:I.length}],P=x.useMemo(()=>{const f=(r==null?void 0:r.providers)??[],v=(t==null?void 0:t.providers)??{},N=j.trim().toLowerCase();return f.filter(M=>{var E;return c==="installed"?!!((E=v[M.name])!=null&&E.apiKeySet):!0}).filter(M=>{var R,$;return N?((($=(R=v[M.name])==null?void 0:R.displayName)==null?void 0:$.trim())||M.displayName||M.name).toLowerCase().includes(N)||M.name.toLowerCase().includes(N):!0})},[r,t,c,j]);x.useEffect(()=>{if(P.length===0){u(void 0);return}P.some(v=>v.name===d)||u(P[0].name)},[P,d]);const H=d,ne=async()=>{try{const f=await l.mutateAsync({data:{}});g("all"),b(""),u(f.name)}catch{}};return!t||!r?e.jsx("div",{className:"p-8",children:n("providersLoading")}):e.jsxs(Yt,{children:[e.jsx(Zt,{title:n("providersPageTitle"),description:n("providersPageDescription")}),e.jsxs("div",{className:Ut,children:[e.jsxs("section",{className:Vt,children:[e.jsxs("div",{className:"border-b border-gray-100 px-4 pt-4 pb-3 space-y-3",children:[e.jsx(Qt,{tabs:A,activeTab:c,onChange:g,className:"mb-0"}),e.jsxs(z,{type:"button",variant:"outline",className:"w-full justify-center",onClick:ne,disabled:l.isPending,children:[e.jsx(_e,{className:"mr-2 h-4 w-4"}),l.isPending?n("saving"):n("providerAddCustom")]})]}),e.jsx("div",{className:"border-b border-gray-100 px-4 py-3",children:e.jsxs("div",{className:"relative",children:[e.jsx(It,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),e.jsx(X,{value:j,onChange:f=>b(f.target.value),placeholder:n("providersFilterPlaceholder"),className:"h-10 rounded-xl pl-9"})]})}),e.jsxs("div",{className:"min-h-0 flex-1 space-y-2 overflow-y-auto p-3",children:[P.map(f=>{var Y;const v=t.providers[f.name],N=!!(v!=null&&v.apiKeySet),M=H===f.name,E=((Y=v==null?void 0:v.displayName)==null?void 0:Y.trim())||f.displayName||f.name,_=le(`providers.${f.name}`,w),R=(v==null?void 0:v.apiBase)||f.defaultApiBase||"",G=ds(R)||(_==null?void 0:_.help)||n("providersDefaultDescription");return e.jsx("button",{type:"button",onClick:()=>u(f.name),className:de("w-full rounded-xl border p-2.5 text-left transition-all",M?"border-primary/30 bg-primary-50/40 shadow-sm":"border-gray-200/70 bg-white hover:border-gray-300 hover:bg-gray-50/70"),children:e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[e.jsx(Xt,{name:f.name,src:f.logo?`/logos/${f.logo}`:null,className:de("h-10 w-10 rounded-lg border",N?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:e.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:f.name[0]})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"truncate text-sm font-semibold text-gray-900",children:E}),e.jsx("p",{className:"line-clamp-1 text-[11px] text-gray-500",children:G})]})]}),e.jsx(mt,{status:N?"ready":"setup",label:N?n("statusReady"):n("statusSetup"),className:"min-w-[56px] justify-center"})]})},f.name)}),P.length===0&&e.jsxs("div",{className:"flex h-full min-h-[220px] flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 bg-gray-50/70 py-10 text-center",children:[e.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-white",children:e.jsx(Dt,{className:"h-5 w-5 text-gray-300"})}),e.jsx("p",{className:"text-sm font-medium text-gray-700",children:n("providersNoMatch")})]})]})]}),e.jsx(cs,{providerName:H,onProviderDeleted:f=>{f===d&&u(void 0)}})]})]})}export{Cs as ProvidersList};
|